at v3.4 12 kB view raw
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_config - Configuration for RX/TX HSI modules 72 * @mode: Bit transmission mode (STREAM or FRAME) 73 * @channels: Number of channels to use [1..16] 74 * @speed: Max bit transmission speed (Kbit/s) 75 * @flow: RX flow type (SYNCHRONIZED or PIPELINE) 76 * @arb_mode: Arbitration mode for TX frame (Round robin, priority) 77 */ 78struct hsi_config { 79 unsigned int mode; 80 unsigned int channels; 81 unsigned int speed; 82 union { 83 unsigned int flow; /* RX only */ 84 unsigned int arb_mode; /* TX only */ 85 }; 86}; 87 88/** 89 * struct hsi_board_info - HSI client board info 90 * @name: Name for the HSI device 91 * @hsi_id: HSI controller id where the client sits 92 * @port: Port number in the controller where the client sits 93 * @tx_cfg: HSI TX configuration 94 * @rx_cfg: HSI RX configuration 95 * @platform_data: Platform related data 96 * @archdata: Architecture-dependent device data 97 */ 98struct hsi_board_info { 99 const char *name; 100 unsigned int hsi_id; 101 unsigned int port; 102 struct hsi_config tx_cfg; 103 struct hsi_config rx_cfg; 104 void *platform_data; 105 struct dev_archdata *archdata; 106}; 107 108#ifdef CONFIG_HSI_BOARDINFO 109extern int hsi_register_board_info(struct hsi_board_info const *info, 110 unsigned int len); 111#else 112static inline int hsi_register_board_info(struct hsi_board_info const *info, 113 unsigned int len) 114{ 115 return 0; 116} 117#endif /* CONFIG_HSI_BOARDINFO */ 118 119/** 120 * struct hsi_client - HSI client attached to an HSI port 121 * @device: Driver model representation of the device 122 * @tx_cfg: HSI TX configuration 123 * @rx_cfg: HSI RX configuration 124 * @e_handler: Callback for handling port events (RX Wake High/Low) 125 * @pclaimed: Keeps tracks if the clients claimed its associated HSI port 126 * @nb: Notifier block for port events 127 */ 128struct hsi_client { 129 struct device device; 130 struct hsi_config tx_cfg; 131 struct hsi_config rx_cfg; 132 /* private: */ 133 void (*ehandler)(struct hsi_client *, unsigned long); 134 unsigned int pclaimed:1; 135 struct notifier_block nb; 136}; 137 138#define to_hsi_client(dev) container_of(dev, struct hsi_client, device) 139 140static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data) 141{ 142 dev_set_drvdata(&cl->device, data); 143} 144 145static inline void *hsi_client_drvdata(struct hsi_client *cl) 146{ 147 return dev_get_drvdata(&cl->device); 148} 149 150int hsi_register_port_event(struct hsi_client *cl, 151 void (*handler)(struct hsi_client *, unsigned long)); 152int hsi_unregister_port_event(struct hsi_client *cl); 153 154/** 155 * struct hsi_client_driver - Driver associated to an HSI client 156 * @driver: Driver model representation of the driver 157 */ 158struct hsi_client_driver { 159 struct device_driver driver; 160}; 161 162#define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\ 163 driver) 164 165int hsi_register_client_driver(struct hsi_client_driver *drv); 166 167static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv) 168{ 169 driver_unregister(&drv->driver); 170} 171 172/** 173 * struct hsi_msg - HSI message descriptor 174 * @link: Free to use by the current descriptor owner 175 * @cl: HSI device client that issues the transfer 176 * @sgt: Head of the scatterlist array 177 * @context: Client context data associated to the transfer 178 * @complete: Transfer completion callback 179 * @destructor: Destructor to free resources when flushing 180 * @status: Status of the transfer when completed 181 * @actual_len: Actual length of data transfered on completion 182 * @channel: Channel were to TX/RX the message 183 * @ttype: Transfer type (TX if set, RX otherwise) 184 * @break_frame: if true HSI will send/receive a break frame. Data buffers are 185 * ignored in the request. 186 */ 187struct hsi_msg { 188 struct list_head link; 189 struct hsi_client *cl; 190 struct sg_table sgt; 191 void *context; 192 193 void (*complete)(struct hsi_msg *msg); 194 void (*destructor)(struct hsi_msg *msg); 195 196 int status; 197 unsigned int actual_len; 198 unsigned int channel; 199 unsigned int ttype:1; 200 unsigned int break_frame:1; 201}; 202 203struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags); 204void hsi_free_msg(struct hsi_msg *msg); 205 206/** 207 * struct hsi_port - HSI port device 208 * @device: Driver model representation of the device 209 * @tx_cfg: Current TX path configuration 210 * @rx_cfg: Current RX path configuration 211 * @num: Port number 212 * @shared: Set when port can be shared by different clients 213 * @claimed: Reference count of clients which claimed the port 214 * @lock: Serialize port claim 215 * @async: Asynchronous transfer callback 216 * @setup: Callback to set the HSI client configuration 217 * @flush: Callback to clean the HW state and destroy all pending transfers 218 * @start_tx: Callback to inform that a client wants to TX data 219 * @stop_tx: Callback to inform that a client no longer wishes to TX data 220 * @release: Callback to inform that a client no longer uses the port 221 * @n_head: Notifier chain for signaling port events to the clients. 222 */ 223struct hsi_port { 224 struct device device; 225 struct hsi_config tx_cfg; 226 struct hsi_config rx_cfg; 227 unsigned int num; 228 unsigned int shared:1; 229 int claimed; 230 struct mutex lock; 231 int (*async)(struct hsi_msg *msg); 232 int (*setup)(struct hsi_client *cl); 233 int (*flush)(struct hsi_client *cl); 234 int (*start_tx)(struct hsi_client *cl); 235 int (*stop_tx)(struct hsi_client *cl); 236 int (*release)(struct hsi_client *cl); 237 /* private */ 238 struct atomic_notifier_head n_head; 239}; 240 241#define to_hsi_port(dev) container_of(dev, struct hsi_port, device) 242#define hsi_get_port(cl) to_hsi_port((cl)->device.parent) 243 244int hsi_event(struct hsi_port *port, unsigned long event); 245int hsi_claim_port(struct hsi_client *cl, unsigned int share); 246void hsi_release_port(struct hsi_client *cl); 247 248static inline int hsi_port_claimed(struct hsi_client *cl) 249{ 250 return cl->pclaimed; 251} 252 253static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data) 254{ 255 dev_set_drvdata(&port->device, data); 256} 257 258static inline void *hsi_port_drvdata(struct hsi_port *port) 259{ 260 return dev_get_drvdata(&port->device); 261} 262 263/** 264 * struct hsi_controller - HSI controller device 265 * @device: Driver model representation of the device 266 * @owner: Pointer to the module owning the controller 267 * @id: HSI controller ID 268 * @num_ports: Number of ports in the HSI controller 269 * @port: Array of HSI ports 270 */ 271struct hsi_controller { 272 struct device device; 273 struct module *owner; 274 unsigned int id; 275 unsigned int num_ports; 276 struct hsi_port **port; 277}; 278 279#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device) 280 281struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags); 282void hsi_put_controller(struct hsi_controller *hsi); 283int hsi_register_controller(struct hsi_controller *hsi); 284void hsi_unregister_controller(struct hsi_controller *hsi); 285 286static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi, 287 void *data) 288{ 289 dev_set_drvdata(&hsi->device, data); 290} 291 292static inline void *hsi_controller_drvdata(struct hsi_controller *hsi) 293{ 294 return dev_get_drvdata(&hsi->device); 295} 296 297static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, 298 unsigned int num) 299{ 300 return (num < hsi->num_ports) ? hsi->port[num] : NULL; 301} 302 303/* 304 * API for HSI clients 305 */ 306int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); 307 308/** 309 * hsi_id - Get HSI controller ID associated to a client 310 * @cl: Pointer to a HSI client 311 * 312 * Return the controller id where the client is attached to 313 */ 314static inline unsigned int hsi_id(struct hsi_client *cl) 315{ 316 return to_hsi_controller(cl->device.parent->parent)->id; 317} 318 319/** 320 * hsi_port_id - Gets the port number a client is attached to 321 * @cl: Pointer to HSI client 322 * 323 * Return the port number associated to the client 324 */ 325static inline unsigned int hsi_port_id(struct hsi_client *cl) 326{ 327 return to_hsi_port(cl->device.parent)->num; 328} 329 330/** 331 * hsi_setup - Configure the client's port 332 * @cl: Pointer to the HSI client 333 * 334 * When sharing ports, clients should either relay on a single 335 * client setup or have the same setup for all of them. 336 * 337 * Return -errno on failure, 0 on success 338 */ 339static inline int hsi_setup(struct hsi_client *cl) 340{ 341 if (!hsi_port_claimed(cl)) 342 return -EACCES; 343 return hsi_get_port(cl)->setup(cl); 344} 345 346/** 347 * hsi_flush - Flush all pending transactions on the client's port 348 * @cl: Pointer to the HSI client 349 * 350 * This function will destroy all pending hsi_msg in the port and reset 351 * the HW port so it is ready to receive and transmit from a clean state. 352 * 353 * Return -errno on failure, 0 on success 354 */ 355static inline int hsi_flush(struct hsi_client *cl) 356{ 357 if (!hsi_port_claimed(cl)) 358 return -EACCES; 359 return hsi_get_port(cl)->flush(cl); 360} 361 362/** 363 * hsi_async_read - Submit a read transfer 364 * @cl: Pointer to the HSI client 365 * @msg: HSI message descriptor of the transfer 366 * 367 * Return -errno on failure, 0 on success 368 */ 369static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg) 370{ 371 msg->ttype = HSI_MSG_READ; 372 return hsi_async(cl, msg); 373} 374 375/** 376 * hsi_async_write - Submit a write transfer 377 * @cl: Pointer to the HSI client 378 * @msg: HSI message descriptor of the transfer 379 * 380 * Return -errno on failure, 0 on success 381 */ 382static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg) 383{ 384 msg->ttype = HSI_MSG_WRITE; 385 return hsi_async(cl, msg); 386} 387 388/** 389 * hsi_start_tx - Signal the port that the client wants to start a TX 390 * @cl: Pointer to the HSI client 391 * 392 * Return -errno on failure, 0 on success 393 */ 394static inline int hsi_start_tx(struct hsi_client *cl) 395{ 396 if (!hsi_port_claimed(cl)) 397 return -EACCES; 398 return hsi_get_port(cl)->start_tx(cl); 399} 400 401/** 402 * hsi_stop_tx - Signal the port that the client no longer wants to transmit 403 * @cl: Pointer to the HSI client 404 * 405 * Return -errno on failure, 0 on success 406 */ 407static inline int hsi_stop_tx(struct hsi_client *cl) 408{ 409 if (!hsi_port_claimed(cl)) 410 return -EACCES; 411 return hsi_get_port(cl)->stop_tx(cl); 412} 413#endif /* __LINUX_HSI_H__ */