Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc8 507 lines 13 kB view raw
1/* 2 * HSI core. 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#include <linux/hsi/hsi.h> 23#include <linux/compiler.h> 24#include <linux/list.h> 25#include <linux/kobject.h> 26#include <linux/slab.h> 27#include <linux/string.h> 28#include <linux/notifier.h> 29#include "hsi_core.h" 30 31static ssize_t modalias_show(struct device *dev, 32 struct device_attribute *a __maybe_unused, char *buf) 33{ 34 return sprintf(buf, "hsi:%s\n", dev_name(dev)); 35} 36 37static struct device_attribute hsi_bus_dev_attrs[] = { 38 __ATTR_RO(modalias), 39 __ATTR_NULL, 40}; 41 42static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 43{ 44 add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); 45 46 return 0; 47} 48 49static int hsi_bus_match(struct device *dev, struct device_driver *driver) 50{ 51 return strcmp(dev_name(dev), driver->name) == 0; 52} 53 54static struct bus_type hsi_bus_type = { 55 .name = "hsi", 56 .dev_attrs = hsi_bus_dev_attrs, 57 .match = hsi_bus_match, 58 .uevent = hsi_bus_uevent, 59}; 60 61static void hsi_client_release(struct device *dev) 62{ 63 kfree(to_hsi_client(dev)); 64} 65 66static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) 67{ 68 struct hsi_client *cl; 69 70 cl = kzalloc(sizeof(*cl), GFP_KERNEL); 71 if (!cl) 72 return; 73 cl->tx_cfg = info->tx_cfg; 74 cl->rx_cfg = info->rx_cfg; 75 cl->device.bus = &hsi_bus_type; 76 cl->device.parent = &port->device; 77 cl->device.release = hsi_client_release; 78 dev_set_name(&cl->device, info->name); 79 cl->device.platform_data = info->platform_data; 80 if (info->archdata) 81 cl->device.archdata = *info->archdata; 82 if (device_register(&cl->device) < 0) { 83 pr_err("hsi: failed to register client: %s\n", info->name); 84 put_device(&cl->device); 85 } 86} 87 88static void hsi_scan_board_info(struct hsi_controller *hsi) 89{ 90 struct hsi_cl_info *cl_info; 91 struct hsi_port *p; 92 93 list_for_each_entry(cl_info, &hsi_board_list, list) 94 if (cl_info->info.hsi_id == hsi->id) { 95 p = hsi_find_port_num(hsi, cl_info->info.port); 96 if (!p) 97 continue; 98 hsi_new_client(p, &cl_info->info); 99 } 100} 101 102static int hsi_remove_client(struct device *dev, void *data __maybe_unused) 103{ 104 device_unregister(dev); 105 106 return 0; 107} 108 109static int hsi_remove_port(struct device *dev, void *data __maybe_unused) 110{ 111 device_for_each_child(dev, NULL, hsi_remove_client); 112 device_unregister(dev); 113 114 return 0; 115} 116 117static void hsi_controller_release(struct device *dev) 118{ 119 struct hsi_controller *hsi = to_hsi_controller(dev); 120 121 kfree(hsi->port); 122 kfree(hsi); 123} 124 125static void hsi_port_release(struct device *dev) 126{ 127 kfree(to_hsi_port(dev)); 128} 129 130/** 131 * hsi_unregister_controller - Unregister an HSI controller 132 * @hsi: The HSI controller to register 133 */ 134void hsi_unregister_controller(struct hsi_controller *hsi) 135{ 136 device_for_each_child(&hsi->device, NULL, hsi_remove_port); 137 device_unregister(&hsi->device); 138} 139EXPORT_SYMBOL_GPL(hsi_unregister_controller); 140 141/** 142 * hsi_register_controller - Register an HSI controller and its ports 143 * @hsi: The HSI controller to register 144 * 145 * Returns -errno on failure, 0 on success. 146 */ 147int hsi_register_controller(struct hsi_controller *hsi) 148{ 149 unsigned int i; 150 int err; 151 152 err = device_add(&hsi->device); 153 if (err < 0) 154 return err; 155 for (i = 0; i < hsi->num_ports; i++) { 156 hsi->port[i]->device.parent = &hsi->device; 157 err = device_add(&hsi->port[i]->device); 158 if (err < 0) 159 goto out; 160 } 161 /* Populate HSI bus with HSI clients */ 162 hsi_scan_board_info(hsi); 163 164 return 0; 165out: 166 while (i-- > 0) 167 device_del(&hsi->port[i]->device); 168 device_del(&hsi->device); 169 170 return err; 171} 172EXPORT_SYMBOL_GPL(hsi_register_controller); 173 174/** 175 * hsi_register_client_driver - Register an HSI client to the HSI bus 176 * @drv: HSI client driver to register 177 * 178 * Returns -errno on failure, 0 on success. 179 */ 180int hsi_register_client_driver(struct hsi_client_driver *drv) 181{ 182 drv->driver.bus = &hsi_bus_type; 183 184 return driver_register(&drv->driver); 185} 186EXPORT_SYMBOL_GPL(hsi_register_client_driver); 187 188static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused) 189{ 190 return 0; 191} 192 193static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) 194{ 195 return 0; 196} 197 198/** 199 * hsi_put_controller - Free an HSI controller 200 * 201 * @hsi: Pointer to the HSI controller to freed 202 * 203 * HSI controller drivers should only use this function if they need 204 * to free their allocated hsi_controller structures before a successful 205 * call to hsi_register_controller. Other use is not allowed. 206 */ 207void hsi_put_controller(struct hsi_controller *hsi) 208{ 209 unsigned int i; 210 211 if (!hsi) 212 return; 213 214 for (i = 0; i < hsi->num_ports; i++) 215 if (hsi->port && hsi->port[i]) 216 put_device(&hsi->port[i]->device); 217 put_device(&hsi->device); 218} 219EXPORT_SYMBOL_GPL(hsi_put_controller); 220 221/** 222 * hsi_alloc_controller - Allocate an HSI controller and its ports 223 * @n_ports: Number of ports on the HSI controller 224 * @flags: Kernel allocation flags 225 * 226 * Return NULL on failure or a pointer to an hsi_controller on success. 227 */ 228struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) 229{ 230 struct hsi_controller *hsi; 231 struct hsi_port **port; 232 unsigned int i; 233 234 if (!n_ports) 235 return NULL; 236 237 hsi = kzalloc(sizeof(*hsi), flags); 238 if (!hsi) 239 return NULL; 240 port = kzalloc(sizeof(*port)*n_ports, flags); 241 if (!port) { 242 kfree(hsi); 243 return NULL; 244 } 245 hsi->num_ports = n_ports; 246 hsi->port = port; 247 hsi->device.release = hsi_controller_release; 248 device_initialize(&hsi->device); 249 250 for (i = 0; i < n_ports; i++) { 251 port[i] = kzalloc(sizeof(**port), flags); 252 if (port[i] == NULL) 253 goto out; 254 port[i]->num = i; 255 port[i]->async = hsi_dummy_msg; 256 port[i]->setup = hsi_dummy_cl; 257 port[i]->flush = hsi_dummy_cl; 258 port[i]->start_tx = hsi_dummy_cl; 259 port[i]->stop_tx = hsi_dummy_cl; 260 port[i]->release = hsi_dummy_cl; 261 mutex_init(&port[i]->lock); 262 ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head); 263 dev_set_name(&port[i]->device, "port%d", i); 264 hsi->port[i]->device.release = hsi_port_release; 265 device_initialize(&hsi->port[i]->device); 266 } 267 268 return hsi; 269out: 270 hsi_put_controller(hsi); 271 272 return NULL; 273} 274EXPORT_SYMBOL_GPL(hsi_alloc_controller); 275 276/** 277 * hsi_free_msg - Free an HSI message 278 * @msg: Pointer to the HSI message 279 * 280 * Client is responsible to free the buffers pointed by the scatterlists. 281 */ 282void hsi_free_msg(struct hsi_msg *msg) 283{ 284 if (!msg) 285 return; 286 sg_free_table(&msg->sgt); 287 kfree(msg); 288} 289EXPORT_SYMBOL_GPL(hsi_free_msg); 290 291/** 292 * hsi_alloc_msg - Allocate an HSI message 293 * @nents: Number of memory entries 294 * @flags: Kernel allocation flags 295 * 296 * nents can be 0. This mainly makes sense for read transfer. 297 * In that case, HSI drivers will call the complete callback when 298 * there is data to be read without consuming it. 299 * 300 * Return NULL on failure or a pointer to an hsi_msg on success. 301 */ 302struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags) 303{ 304 struct hsi_msg *msg; 305 int err; 306 307 msg = kzalloc(sizeof(*msg), flags); 308 if (!msg) 309 return NULL; 310 311 if (!nents) 312 return msg; 313 314 err = sg_alloc_table(&msg->sgt, nents, flags); 315 if (unlikely(err)) { 316 kfree(msg); 317 msg = NULL; 318 } 319 320 return msg; 321} 322EXPORT_SYMBOL_GPL(hsi_alloc_msg); 323 324/** 325 * hsi_async - Submit an HSI transfer to the controller 326 * @cl: HSI client sending the transfer 327 * @msg: The HSI transfer passed to controller 328 * 329 * The HSI message must have the channel, ttype, complete and destructor 330 * fields set beforehand. If nents > 0 then the client has to initialize 331 * also the scatterlists to point to the buffers to write to or read from. 332 * 333 * HSI controllers relay on pre-allocated buffers from their clients and they 334 * do not allocate buffers on their own. 335 * 336 * Once the HSI message transfer finishes, the HSI controller calls the 337 * complete callback with the status and actual_len fields of the HSI message 338 * updated. The complete callback can be called before returning from 339 * hsi_async. 340 * 341 * Returns -errno on failure or 0 on success 342 */ 343int hsi_async(struct hsi_client *cl, struct hsi_msg *msg) 344{ 345 struct hsi_port *port = hsi_get_port(cl); 346 347 if (!hsi_port_claimed(cl)) 348 return -EACCES; 349 350 WARN_ON_ONCE(!msg->destructor || !msg->complete); 351 msg->cl = cl; 352 353 return port->async(msg); 354} 355EXPORT_SYMBOL_GPL(hsi_async); 356 357/** 358 * hsi_claim_port - Claim the HSI client's port 359 * @cl: HSI client that wants to claim its port 360 * @share: Flag to indicate if the client wants to share the port or not. 361 * 362 * Returns -errno on failure, 0 on success. 363 */ 364int hsi_claim_port(struct hsi_client *cl, unsigned int share) 365{ 366 struct hsi_port *port = hsi_get_port(cl); 367 int err = 0; 368 369 mutex_lock(&port->lock); 370 if ((port->claimed) && (!port->shared || !share)) { 371 err = -EBUSY; 372 goto out; 373 } 374 if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) { 375 err = -ENODEV; 376 goto out; 377 } 378 port->claimed++; 379 port->shared = !!share; 380 cl->pclaimed = 1; 381out: 382 mutex_unlock(&port->lock); 383 384 return err; 385} 386EXPORT_SYMBOL_GPL(hsi_claim_port); 387 388/** 389 * hsi_release_port - Release the HSI client's port 390 * @cl: HSI client which previously claimed its port 391 */ 392void hsi_release_port(struct hsi_client *cl) 393{ 394 struct hsi_port *port = hsi_get_port(cl); 395 396 mutex_lock(&port->lock); 397 /* Allow HW driver to do some cleanup */ 398 port->release(cl); 399 if (cl->pclaimed) 400 port->claimed--; 401 BUG_ON(port->claimed < 0); 402 cl->pclaimed = 0; 403 if (!port->claimed) 404 port->shared = 0; 405 module_put(to_hsi_controller(port->device.parent)->owner); 406 mutex_unlock(&port->lock); 407} 408EXPORT_SYMBOL_GPL(hsi_release_port); 409 410static int hsi_event_notifier_call(struct notifier_block *nb, 411 unsigned long event, void *data __maybe_unused) 412{ 413 struct hsi_client *cl = container_of(nb, struct hsi_client, nb); 414 415 (*cl->ehandler)(cl, event); 416 417 return 0; 418} 419 420/** 421 * hsi_register_port_event - Register a client to receive port events 422 * @cl: HSI client that wants to receive port events 423 * @cb: Event handler callback 424 * 425 * Clients should register a callback to be able to receive 426 * events from the ports. Registration should happen after 427 * claiming the port. 428 * The handler can be called in interrupt context. 429 * 430 * Returns -errno on error, or 0 on success. 431 */ 432int hsi_register_port_event(struct hsi_client *cl, 433 void (*handler)(struct hsi_client *, unsigned long)) 434{ 435 struct hsi_port *port = hsi_get_port(cl); 436 437 if (!handler || cl->ehandler) 438 return -EINVAL; 439 if (!hsi_port_claimed(cl)) 440 return -EACCES; 441 cl->ehandler = handler; 442 cl->nb.notifier_call = hsi_event_notifier_call; 443 444 return atomic_notifier_chain_register(&port->n_head, &cl->nb); 445} 446EXPORT_SYMBOL_GPL(hsi_register_port_event); 447 448/** 449 * hsi_unregister_port_event - Stop receiving port events for a client 450 * @cl: HSI client that wants to stop receiving port events 451 * 452 * Clients should call this function before releasing their associated 453 * port. 454 * 455 * Returns -errno on error, or 0 on success. 456 */ 457int hsi_unregister_port_event(struct hsi_client *cl) 458{ 459 struct hsi_port *port = hsi_get_port(cl); 460 int err; 461 462 WARN_ON(!hsi_port_claimed(cl)); 463 464 err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb); 465 if (!err) 466 cl->ehandler = NULL; 467 468 return err; 469} 470EXPORT_SYMBOL_GPL(hsi_unregister_port_event); 471 472/** 473 * hsi_event -Notifies clients about port events 474 * @port: Port where the event occurred 475 * @event: The event type 476 * 477 * Clients should not be concerned about wake line behavior. However, due 478 * to a race condition in HSI HW protocol, clients need to be notified 479 * about wake line changes, so they can implement a workaround for it. 480 * 481 * Events: 482 * HSI_EVENT_START_RX - Incoming wake line high 483 * HSI_EVENT_STOP_RX - Incoming wake line down 484 * 485 * Returns -errno on error, or 0 on success. 486 */ 487int hsi_event(struct hsi_port *port, unsigned long event) 488{ 489 return atomic_notifier_call_chain(&port->n_head, event, NULL); 490} 491EXPORT_SYMBOL_GPL(hsi_event); 492 493static int __init hsi_init(void) 494{ 495 return bus_register(&hsi_bus_type); 496} 497postcore_initcall(hsi_init); 498 499static void __exit hsi_exit(void) 500{ 501 bus_unregister(&hsi_bus_type); 502} 503module_exit(hsi_exit); 504 505MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>"); 506MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework"); 507MODULE_LICENSE("GPL v2");