1/* 2 * HSI core header file. 3 * 4 * Copyright (C) 2010 Nokia Corporation. All rights reserved. 5 * 6 * Contact: Carlos Chinea <carlos.chinea@nokia.com> 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 */ 38enum { 39 HSI_MODE_STREAM = 1, 40 HSI_MODE_FRAME, 41}; 42 43enum { 44 HSI_FLOW_SYNC, /* Synchronized flow */ 45 HSI_FLOW_PIPE, /* Pipelined flow */ 46}; 47 48enum { 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 */ 56enum { 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 */ 65enum { 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 */ 75struct 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 */ 90struct 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 */ 112struct 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 123extern int hsi_register_board_info(struct hsi_board_info const *info, 124 unsigned int len); 125#else 126static 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 */ 142struct 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 154static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data) 155{ 156 dev_set_drvdata(&cl->device, data); 157} 158 159static inline void *hsi_client_drvdata(struct hsi_client *cl) 160{ 161 return dev_get_drvdata(&cl->device); 162} 163 164int hsi_register_port_event(struct hsi_client *cl, 165 void (*handler)(struct hsi_client *, unsigned long)); 166int 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 */ 172struct 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 179int hsi_register_client_driver(struct hsi_client_driver *drv); 180 181static 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 */ 201struct 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 217struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags); 218void 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 */ 237struct 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 258int hsi_event(struct hsi_port *port, unsigned long event); 259int hsi_claim_port(struct hsi_client *cl, unsigned int share); 260void hsi_release_port(struct hsi_client *cl); 261 262static inline int hsi_port_claimed(struct hsi_client *cl) 263{ 264 return cl->pclaimed; 265} 266 267static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data) 268{ 269 dev_set_drvdata(&port->device, data); 270} 271 272static 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 */ 285struct 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 295struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags); 296void hsi_put_controller(struct hsi_controller *hsi); 297int hsi_register_controller(struct hsi_controller *hsi); 298void hsi_unregister_controller(struct hsi_controller *hsi); 299struct hsi_client *hsi_new_client(struct hsi_port *port, 300 struct hsi_board_info *info); 301int hsi_remove_client(struct device *dev, void *data); 302void hsi_port_unregister_clients(struct hsi_port *port); 303 304#ifdef CONFIG_OF 305void hsi_add_clients_from_dt(struct hsi_port *port, 306 struct device_node *clients); 307#else 308static inline void hsi_add_clients_from_dt(struct hsi_port *port, 309 struct device_node *clients) 310{ 311 return; 312} 313#endif 314 315static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi, 316 void *data) 317{ 318 dev_set_drvdata(&hsi->device, data); 319} 320 321static inline void *hsi_controller_drvdata(struct hsi_controller *hsi) 322{ 323 return dev_get_drvdata(&hsi->device); 324} 325 326static 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 */ 335int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); 336 337int 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 */ 345static 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 */ 356static 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 */ 370static 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 */ 386static 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 */ 400static 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 */ 413static 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 */ 425static 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 */ 438static 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