1 /* 2 * HSI core header file. 3 * 4 * Copyright (C) 2010 Nokia Corporation. All rights reserved. 5 * 6 * Contact: Carlos Chinea <[email protected]> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22 23 #ifndef __LINUX_HSI_H__ 24 #define __LINUX_HSI_H__ 25 26 #include <linux/device.h> 27 #include <linux/mutex.h> 28 #include <linux/scatterlist.h> 29 #include <linux/list.h> 30 #include <linux/module.h> 31 #include <linux/notifier.h> 32 33 /* HSI message ttype */ 34 #define HSI_MSG_READ 0 35 #define HSI_MSG_WRITE 1 36 37 /* HSI configuration values */ 38 enum { 39 HSI_MODE_STREAM = 1, 40 HSI_MODE_FRAME, 41 }; 42 43 enum { 44 HSI_FLOW_SYNC, /* Synchronized flow */ 45 HSI_FLOW_PIPE, /* Pipelined flow */ 46 }; 47 48 enum { 49 HSI_ARB_RR, /* Round-robin arbitration */ 50 HSI_ARB_PRIO, /* Channel priority arbitration */ 51 }; 52 53 #define HSI_MAX_CHANNELS 16 54 55 /* HSI message status codes */ 56 enum { 57 HSI_STATUS_COMPLETED, /* Message transfer is completed */ 58 HSI_STATUS_PENDING, /* Message pending to be read/write (POLL) */ 59 HSI_STATUS_PROCEEDING, /* Message transfer is ongoing */ 60 HSI_STATUS_QUEUED, /* Message waiting to be served */ 61 HSI_STATUS_ERROR, /* Error when message transfer was ongoing */ 62 }; 63 64 /* HSI port event codes */ 65 enum { 66 HSI_EVENT_START_RX, 67 HSI_EVENT_STOP_RX, 68 }; 69 70 /** 71 * struct hsi_channel - channel resource used by the hsi clients 72 * @id: Channel number 73 * @name: Channel name 74 */ 75 struct hsi_channel { 76 unsigned int id; 77 const char *name; 78 }; 79 80 /** 81 * struct hsi_config - Configuration for RX/TX HSI modules 82 * @mode: Bit transmission mode (STREAM or FRAME) 83 * @channels: Channel resources used by the client 84 * @num_channels: Number of channel resources 85 * @num_hw_channels: Number of channels the transceiver is configured for [1..16] 86 * @speed: Max bit transmission speed (Kbit/s) 87 * @flow: RX flow type (SYNCHRONIZED or PIPELINE) 88 * @arb_mode: Arbitration mode for TX frame (Round robin, priority) 89 */ 90 struct hsi_config { 91 unsigned int mode; 92 struct hsi_channel *channels; 93 unsigned int num_channels; 94 unsigned int num_hw_channels; 95 unsigned int speed; 96 union { 97 unsigned int flow; /* RX only */ 98 unsigned int arb_mode; /* TX only */ 99 }; 100 }; 101 102 /** 103 * struct hsi_board_info - HSI client board info 104 * @name: Name for the HSI device 105 * @hsi_id: HSI controller id where the client sits 106 * @port: Port number in the controller where the client sits 107 * @tx_cfg: HSI TX configuration 108 * @rx_cfg: HSI RX configuration 109 * @platform_data: Platform related data 110 * @archdata: Architecture-dependent device data 111 */ 112 struct hsi_board_info { 113 const char *name; 114 unsigned int hsi_id; 115 unsigned int port; 116 struct hsi_config tx_cfg; 117 struct hsi_config rx_cfg; 118 void *platform_data; 119 struct dev_archdata *archdata; 120 }; 121 122 #ifdef CONFIG_HSI_BOARDINFO 123 extern int hsi_register_board_info(struct hsi_board_info const *info, 124 unsigned int len); 125 #else 126 static inline int hsi_register_board_info(struct hsi_board_info const *info, 127 unsigned int len) 128 { 129 return 0; 130 } 131 #endif /* CONFIG_HSI_BOARDINFO */ 132 133 /** 134 * struct hsi_client - HSI client attached to an HSI port 135 * @device: Driver model representation of the device 136 * @tx_cfg: HSI TX configuration 137 * @rx_cfg: HSI RX configuration 138 * @e_handler: Callback for handling port events (RX Wake High/Low) 139 * @pclaimed: Keeps tracks if the clients claimed its associated HSI port 140 * @nb: Notifier block for port events 141 */ 142 struct hsi_client { 143 struct device device; 144 struct hsi_config tx_cfg; 145 struct hsi_config rx_cfg; 146 /* private: */ 147 void (*ehandler)(struct hsi_client *, unsigned long); 148 unsigned int pclaimed:1; 149 struct notifier_block nb; 150 }; 151 152 #define to_hsi_client(dev) container_of(dev, struct hsi_client, device) 153 154 static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data) 155 { 156 dev_set_drvdata(&cl->device, data); 157 } 158 159 static inline void *hsi_client_drvdata(struct hsi_client *cl) 160 { 161 return dev_get_drvdata(&cl->device); 162 } 163 164 int hsi_register_port_event(struct hsi_client *cl, 165 void (*handler)(struct hsi_client *, unsigned long)); 166 int hsi_unregister_port_event(struct hsi_client *cl); 167 168 /** 169 * struct hsi_client_driver - Driver associated to an HSI client 170 * @driver: Driver model representation of the driver 171 */ 172 struct hsi_client_driver { 173 struct device_driver driver; 174 }; 175 176 #define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\ 177 driver) 178 179 int hsi_register_client_driver(struct hsi_client_driver *drv); 180 181 static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv) 182 { 183 driver_unregister(&drv->driver); 184 } 185 186 /** 187 * struct hsi_msg - HSI message descriptor 188 * @link: Free to use by the current descriptor owner 189 * @cl: HSI device client that issues the transfer 190 * @sgt: Head of the scatterlist array 191 * @context: Client context data associated to the transfer 192 * @complete: Transfer completion callback 193 * @destructor: Destructor to free resources when flushing 194 * @status: Status of the transfer when completed 195 * @actual_len: Actual length of data transferred on completion 196 * @channel: Channel were to TX/RX the message 197 * @ttype: Transfer type (TX if set, RX otherwise) 198 * @break_frame: if true HSI will send/receive a break frame. Data buffers are 199 * ignored in the request. 200 */ 201 struct hsi_msg { 202 struct list_head link; 203 struct hsi_client *cl; 204 struct sg_table sgt; 205 void *context; 206 207 void (*complete)(struct hsi_msg *msg); 208 void (*destructor)(struct hsi_msg *msg); 209 210 int status; 211 unsigned int actual_len; 212 unsigned int channel; 213 unsigned int ttype:1; 214 unsigned int break_frame:1; 215 }; 216 217 struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags); 218 void hsi_free_msg(struct hsi_msg *msg); 219 220 /** 221 * struct hsi_port - HSI port device 222 * @device: Driver model representation of the device 223 * @tx_cfg: Current TX path configuration 224 * @rx_cfg: Current RX path configuration 225 * @num: Port number 226 * @shared: Set when port can be shared by different clients 227 * @claimed: Reference count of clients which claimed the port 228 * @lock: Serialize port claim 229 * @async: Asynchronous transfer callback 230 * @setup: Callback to set the HSI client configuration 231 * @flush: Callback to clean the HW state and destroy all pending transfers 232 * @start_tx: Callback to inform that a client wants to TX data 233 * @stop_tx: Callback to inform that a client no longer wishes to TX data 234 * @release: Callback to inform that a client no longer uses the port 235 * @n_head: Notifier chain for signaling port events to the clients. 236 */ 237 struct hsi_port { 238 struct device device; 239 struct hsi_config tx_cfg; 240 struct hsi_config rx_cfg; 241 unsigned int num; 242 unsigned int shared:1; 243 int claimed; 244 struct mutex lock; 245 int (*async)(struct hsi_msg *msg); 246 int (*setup)(struct hsi_client *cl); 247 int (*flush)(struct hsi_client *cl); 248 int (*start_tx)(struct hsi_client *cl); 249 int (*stop_tx)(struct hsi_client *cl); 250 int (*release)(struct hsi_client *cl); 251 /* private */ 252 struct atomic_notifier_head n_head; 253 }; 254 255 #define to_hsi_port(dev) container_of(dev, struct hsi_port, device) 256 #define hsi_get_port(cl) to_hsi_port((cl)->device.parent) 257 258 int hsi_event(struct hsi_port *port, unsigned long event); 259 int hsi_claim_port(struct hsi_client *cl, unsigned int share); 260 void hsi_release_port(struct hsi_client *cl); 261 262 static inline int hsi_port_claimed(struct hsi_client *cl) 263 { 264 return cl->pclaimed; 265 } 266 267 static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data) 268 { 269 dev_set_drvdata(&port->device, data); 270 } 271 272 static inline void *hsi_port_drvdata(struct hsi_port *port) 273 { 274 return dev_get_drvdata(&port->device); 275 } 276 277 /** 278 * struct hsi_controller - HSI controller device 279 * @device: Driver model representation of the device 280 * @owner: Pointer to the module owning the controller 281 * @id: HSI controller ID 282 * @num_ports: Number of ports in the HSI controller 283 * @port: Array of HSI ports 284 */ 285 struct hsi_controller { 286 struct device device; 287 struct module *owner; 288 unsigned int id; 289 unsigned int num_ports; 290 struct hsi_port **port; 291 }; 292 293 #define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device) 294 295 struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags); 296 void hsi_put_controller(struct hsi_controller *hsi); 297 int hsi_register_controller(struct hsi_controller *hsi); 298 void hsi_unregister_controller(struct hsi_controller *hsi); 299 struct hsi_client *hsi_new_client(struct hsi_port *port, 300 struct hsi_board_info *info); 301 int hsi_remove_client(struct device *dev, void *data); 302 void hsi_port_unregister_clients(struct hsi_port *port); 303 304 #ifdef CONFIG_OF 305 void hsi_add_clients_from_dt(struct hsi_port *port, 306 struct device_node *clients); 307 #else 308 static inline void hsi_add_clients_from_dt(struct hsi_port *port, 309 struct device_node *clients) 310 { 311 return; 312 } 313 #endif 314 315 static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi, 316 void *data) 317 { 318 dev_set_drvdata(&hsi->device, data); 319 } 320 321 static inline void *hsi_controller_drvdata(struct hsi_controller *hsi) 322 { 323 return dev_get_drvdata(&hsi->device); 324 } 325 326 static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, 327 unsigned int num) 328 { 329 return (num < hsi->num_ports) ? hsi->port[num] : NULL; 330 } 331 332 /* 333 * API for HSI clients 334 */ 335 int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); 336 337 int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name); 338 339 /** 340 * hsi_id - Get HSI controller ID associated to a client 341 * @cl: Pointer to a HSI client 342 * 343 * Return the controller id where the client is attached to 344 */ 345 static inline unsigned int hsi_id(struct hsi_client *cl) 346 { 347 return to_hsi_controller(cl->device.parent->parent)->id; 348 } 349 350 /** 351 * hsi_port_id - Gets the port number a client is attached to 352 * @cl: Pointer to HSI client 353 * 354 * Return the port number associated to the client 355 */ 356 static inline unsigned int hsi_port_id(struct hsi_client *cl) 357 { 358 return to_hsi_port(cl->device.parent)->num; 359 } 360 361 /** 362 * hsi_setup - Configure the client's port 363 * @cl: Pointer to the HSI client 364 * 365 * When sharing ports, clients should either relay on a single 366 * client setup or have the same setup for all of them. 367 * 368 * Return -errno on failure, 0 on success 369 */ 370 static inline int hsi_setup(struct hsi_client *cl) 371 { 372 if (!hsi_port_claimed(cl)) 373 return -EACCES; 374 return hsi_get_port(cl)->setup(cl); 375 } 376 377 /** 378 * hsi_flush - Flush all pending transactions on the client's port 379 * @cl: Pointer to the HSI client 380 * 381 * This function will destroy all pending hsi_msg in the port and reset 382 * the HW port so it is ready to receive and transmit from a clean state. 383 * 384 * Return -errno on failure, 0 on success 385 */ 386 static inline int hsi_flush(struct hsi_client *cl) 387 { 388 if (!hsi_port_claimed(cl)) 389 return -EACCES; 390 return hsi_get_port(cl)->flush(cl); 391 } 392 393 /** 394 * hsi_async_read - Submit a read transfer 395 * @cl: Pointer to the HSI client 396 * @msg: HSI message descriptor of the transfer 397 * 398 * Return -errno on failure, 0 on success 399 */ 400 static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg) 401 { 402 msg->ttype = HSI_MSG_READ; 403 return hsi_async(cl, msg); 404 } 405 406 /** 407 * hsi_async_write - Submit a write transfer 408 * @cl: Pointer to the HSI client 409 * @msg: HSI message descriptor of the transfer 410 * 411 * Return -errno on failure, 0 on success 412 */ 413 static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg) 414 { 415 msg->ttype = HSI_MSG_WRITE; 416 return hsi_async(cl, msg); 417 } 418 419 /** 420 * hsi_start_tx - Signal the port that the client wants to start a TX 421 * @cl: Pointer to the HSI client 422 * 423 * Return -errno on failure, 0 on success 424 */ 425 static inline int hsi_start_tx(struct hsi_client *cl) 426 { 427 if (!hsi_port_claimed(cl)) 428 return -EACCES; 429 return hsi_get_port(cl)->start_tx(cl); 430 } 431 432 /** 433 * hsi_stop_tx - Signal the port that the client no longer wants to transmit 434 * @cl: Pointer to the HSI client 435 * 436 * Return -errno on failure, 0 on success 437 */ 438 static inline int hsi_stop_tx(struct hsi_client *cl) 439 { 440 if (!hsi_port_claimed(cl)) 441 return -EACCES; 442 return hsi_get_port(cl)->stop_tx(cl); 443 } 444 #endif /* __LINUX_HSI_H__ */ 445