768 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * HSI core.4 *5 * Copyright (C) 2010 Nokia Corporation. All rights reserved.6 *7 * Contact: Carlos Chinea <carlos.chinea@nokia.com>8 */9#include <linux/hsi/hsi.h>10#include <linux/compiler.h>11#include <linux/list.h>12#include <linux/kobject.h>13#include <linux/slab.h>14#include <linux/string.h>15#include <linux/notifier.h>16#include <linux/of.h>17#include <linux/of_device.h>18#include "hsi_core.h"19 20static ssize_t modalias_show(struct device *dev,21 struct device_attribute *a __maybe_unused, char *buf)22{23 return sprintf(buf, "hsi:%s\n", dev_name(dev));24}25static DEVICE_ATTR_RO(modalias);26 27static struct attribute *hsi_bus_dev_attrs[] = {28 &dev_attr_modalias.attr,29 NULL,30};31ATTRIBUTE_GROUPS(hsi_bus_dev);32 33static int hsi_bus_uevent(const struct device *dev, struct kobj_uevent_env *env)34{35 add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));36 37 return 0;38}39 40static int hsi_bus_match(struct device *dev, const struct device_driver *driver)41{42 if (of_driver_match_device(dev, driver))43 return true;44 45 if (strcmp(dev_name(dev), driver->name) == 0)46 return true;47 48 return false;49}50 51static const struct bus_type hsi_bus_type = {52 .name = "hsi",53 .dev_groups = hsi_bus_dev_groups,54 .match = hsi_bus_match,55 .uevent = hsi_bus_uevent,56};57 58static void hsi_client_release(struct device *dev)59{60 struct hsi_client *cl = to_hsi_client(dev);61 62 kfree(cl->tx_cfg.channels);63 kfree(cl->rx_cfg.channels);64 kfree(cl);65}66 67struct hsi_client *hsi_new_client(struct hsi_port *port,68 struct hsi_board_info *info)69{70 struct hsi_client *cl;71 size_t size;72 73 cl = kzalloc(sizeof(*cl), GFP_KERNEL);74 if (!cl)75 goto err;76 77 cl->tx_cfg = info->tx_cfg;78 if (cl->tx_cfg.channels) {79 size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);80 cl->tx_cfg.channels = kmemdup(info->tx_cfg.channels, size,81 GFP_KERNEL);82 if (!cl->tx_cfg.channels)83 goto err_tx;84 }85 86 cl->rx_cfg = info->rx_cfg;87 if (cl->rx_cfg.channels) {88 size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);89 cl->rx_cfg.channels = kmemdup(info->rx_cfg.channels, size,90 GFP_KERNEL);91 if (!cl->rx_cfg.channels)92 goto err_rx;93 }94 95 cl->device.bus = &hsi_bus_type;96 cl->device.parent = &port->device;97 cl->device.release = hsi_client_release;98 dev_set_name(&cl->device, "%s", info->name);99 cl->device.platform_data = info->platform_data;100 if (info->archdata)101 cl->device.archdata = *info->archdata;102 if (device_register(&cl->device) < 0) {103 pr_err("hsi: failed to register client: %s\n", info->name);104 put_device(&cl->device);105 goto err;106 }107 108 return cl;109err_rx:110 kfree(cl->tx_cfg.channels);111err_tx:112 kfree(cl);113err:114 return NULL;115}116EXPORT_SYMBOL_GPL(hsi_new_client);117 118static void hsi_scan_board_info(struct hsi_controller *hsi)119{120 struct hsi_cl_info *cl_info;121 struct hsi_port *p;122 123 list_for_each_entry(cl_info, &hsi_board_list, list)124 if (cl_info->info.hsi_id == hsi->id) {125 p = hsi_find_port_num(hsi, cl_info->info.port);126 if (!p)127 continue;128 hsi_new_client(p, &cl_info->info);129 }130}131 132#ifdef CONFIG_OF133static struct hsi_board_info hsi_char_dev_info = {134 .name = "hsi_char",135};136 137static int hsi_of_property_parse_mode(struct device_node *client, char *name,138 unsigned int *result)139{140 const char *mode;141 int err;142 143 err = of_property_read_string(client, name, &mode);144 if (err < 0)145 return err;146 147 if (strcmp(mode, "stream") == 0)148 *result = HSI_MODE_STREAM;149 else if (strcmp(mode, "frame") == 0)150 *result = HSI_MODE_FRAME;151 else152 return -EINVAL;153 154 return 0;155}156 157static int hsi_of_property_parse_flow(struct device_node *client, char *name,158 unsigned int *result)159{160 const char *flow;161 int err;162 163 err = of_property_read_string(client, name, &flow);164 if (err < 0)165 return err;166 167 if (strcmp(flow, "synchronized") == 0)168 *result = HSI_FLOW_SYNC;169 else if (strcmp(flow, "pipeline") == 0)170 *result = HSI_FLOW_PIPE;171 else172 return -EINVAL;173 174 return 0;175}176 177static int hsi_of_property_parse_arb_mode(struct device_node *client,178 char *name, unsigned int *result)179{180 const char *arb_mode;181 int err;182 183 err = of_property_read_string(client, name, &arb_mode);184 if (err < 0)185 return err;186 187 if (strcmp(arb_mode, "round-robin") == 0)188 *result = HSI_ARB_RR;189 else if (strcmp(arb_mode, "priority") == 0)190 *result = HSI_ARB_PRIO;191 else192 return -EINVAL;193 194 return 0;195}196 197static void hsi_add_client_from_dt(struct hsi_port *port,198 struct device_node *client)199{200 struct hsi_client *cl;201 struct hsi_channel channel;202 struct property *prop;203 char name[32];204 int length, cells, err, i, max_chan, mode;205 206 cl = kzalloc(sizeof(*cl), GFP_KERNEL);207 if (!cl)208 return;209 210 err = of_alias_from_compatible(client, name, sizeof(name));211 if (err)212 goto err;213 214 err = hsi_of_property_parse_mode(client, "hsi-mode", &mode);215 if (err) {216 err = hsi_of_property_parse_mode(client, "hsi-rx-mode",217 &cl->rx_cfg.mode);218 if (err)219 goto err;220 221 err = hsi_of_property_parse_mode(client, "hsi-tx-mode",222 &cl->tx_cfg.mode);223 if (err)224 goto err;225 } else {226 cl->rx_cfg.mode = mode;227 cl->tx_cfg.mode = mode;228 }229 230 err = of_property_read_u32(client, "hsi-speed-kbps",231 &cl->tx_cfg.speed);232 if (err)233 goto err;234 cl->rx_cfg.speed = cl->tx_cfg.speed;235 236 err = hsi_of_property_parse_flow(client, "hsi-flow",237 &cl->rx_cfg.flow);238 if (err)239 goto err;240 241 err = hsi_of_property_parse_arb_mode(client, "hsi-arb-mode",242 &cl->rx_cfg.arb_mode);243 if (err)244 goto err;245 246 prop = of_find_property(client, "hsi-channel-ids", &length);247 if (!prop) {248 err = -EINVAL;249 goto err;250 }251 252 cells = length / sizeof(u32);253 254 cl->rx_cfg.num_channels = cells;255 cl->tx_cfg.num_channels = cells;256 cl->rx_cfg.channels = kcalloc(cells, sizeof(channel), GFP_KERNEL);257 if (!cl->rx_cfg.channels) {258 err = -ENOMEM;259 goto err;260 }261 262 cl->tx_cfg.channels = kcalloc(cells, sizeof(channel), GFP_KERNEL);263 if (!cl->tx_cfg.channels) {264 err = -ENOMEM;265 goto err2;266 }267 268 max_chan = 0;269 for (i = 0; i < cells; i++) {270 err = of_property_read_u32_index(client, "hsi-channel-ids", i,271 &channel.id);272 if (err)273 goto err3;274 275 err = of_property_read_string_index(client, "hsi-channel-names",276 i, &channel.name);277 if (err)278 channel.name = NULL;279 280 if (channel.id > max_chan)281 max_chan = channel.id;282 283 cl->rx_cfg.channels[i] = channel;284 cl->tx_cfg.channels[i] = channel;285 }286 287 cl->rx_cfg.num_hw_channels = max_chan + 1;288 cl->tx_cfg.num_hw_channels = max_chan + 1;289 290 cl->device.bus = &hsi_bus_type;291 cl->device.parent = &port->device;292 cl->device.release = hsi_client_release;293 cl->device.of_node = client;294 295 dev_set_name(&cl->device, "%s", name);296 if (device_register(&cl->device) < 0) {297 pr_err("hsi: failed to register client: %s\n", name);298 put_device(&cl->device);299 }300 301 return;302 303err3:304 kfree(cl->tx_cfg.channels);305err2:306 kfree(cl->rx_cfg.channels);307err:308 kfree(cl);309 pr_err("hsi client: missing or incorrect of property: err=%d\n", err);310}311 312void hsi_add_clients_from_dt(struct hsi_port *port, struct device_node *clients)313{314 struct device_node *child;315 316 /* register hsi-char device */317 hsi_new_client(port, &hsi_char_dev_info);318 319 for_each_available_child_of_node(clients, child)320 hsi_add_client_from_dt(port, child);321}322EXPORT_SYMBOL_GPL(hsi_add_clients_from_dt);323#endif324 325int hsi_remove_client(struct device *dev, void *data __maybe_unused)326{327 device_unregister(dev);328 329 return 0;330}331EXPORT_SYMBOL_GPL(hsi_remove_client);332 333static int hsi_remove_port(struct device *dev, void *data __maybe_unused)334{335 device_for_each_child(dev, NULL, hsi_remove_client);336 device_unregister(dev);337 338 return 0;339}340 341static void hsi_controller_release(struct device *dev)342{343 struct hsi_controller *hsi = to_hsi_controller(dev);344 345 kfree(hsi->port);346 kfree(hsi);347}348 349static void hsi_port_release(struct device *dev)350{351 kfree(to_hsi_port(dev));352}353 354/**355 * hsi_port_unregister_clients - Unregister an HSI port356 * @port: The HSI port to unregister357 */358void hsi_port_unregister_clients(struct hsi_port *port)359{360 device_for_each_child(&port->device, NULL, hsi_remove_client);361}362EXPORT_SYMBOL_GPL(hsi_port_unregister_clients);363 364/**365 * hsi_unregister_controller - Unregister an HSI controller366 * @hsi: The HSI controller to register367 */368void hsi_unregister_controller(struct hsi_controller *hsi)369{370 device_for_each_child(&hsi->device, NULL, hsi_remove_port);371 device_unregister(&hsi->device);372}373EXPORT_SYMBOL_GPL(hsi_unregister_controller);374 375/**376 * hsi_register_controller - Register an HSI controller and its ports377 * @hsi: The HSI controller to register378 *379 * Returns -errno on failure, 0 on success.380 */381int hsi_register_controller(struct hsi_controller *hsi)382{383 unsigned int i;384 int err;385 386 err = device_add(&hsi->device);387 if (err < 0)388 return err;389 for (i = 0; i < hsi->num_ports; i++) {390 hsi->port[i]->device.parent = &hsi->device;391 err = device_add(&hsi->port[i]->device);392 if (err < 0)393 goto out;394 }395 /* Populate HSI bus with HSI clients */396 hsi_scan_board_info(hsi);397 398 return 0;399out:400 while (i-- > 0)401 device_del(&hsi->port[i]->device);402 device_del(&hsi->device);403 404 return err;405}406EXPORT_SYMBOL_GPL(hsi_register_controller);407 408/**409 * hsi_register_client_driver - Register an HSI client to the HSI bus410 * @drv: HSI client driver to register411 *412 * Returns -errno on failure, 0 on success.413 */414int hsi_register_client_driver(struct hsi_client_driver *drv)415{416 drv->driver.bus = &hsi_bus_type;417 418 return driver_register(&drv->driver);419}420EXPORT_SYMBOL_GPL(hsi_register_client_driver);421 422static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)423{424 return 0;425}426 427static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)428{429 return 0;430}431 432/**433 * hsi_put_controller - Free an HSI controller434 *435 * @hsi: Pointer to the HSI controller to freed436 *437 * HSI controller drivers should only use this function if they need438 * to free their allocated hsi_controller structures before a successful439 * call to hsi_register_controller. Other use is not allowed.440 */441void hsi_put_controller(struct hsi_controller *hsi)442{443 unsigned int i;444 445 if (!hsi)446 return;447 448 for (i = 0; i < hsi->num_ports; i++)449 if (hsi->port && hsi->port[i])450 put_device(&hsi->port[i]->device);451 put_device(&hsi->device);452}453EXPORT_SYMBOL_GPL(hsi_put_controller);454 455/**456 * hsi_alloc_controller - Allocate an HSI controller and its ports457 * @n_ports: Number of ports on the HSI controller458 * @flags: Kernel allocation flags459 *460 * Return NULL on failure or a pointer to an hsi_controller on success.461 */462struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)463{464 struct hsi_controller *hsi;465 struct hsi_port **port;466 unsigned int i;467 468 if (!n_ports)469 return NULL;470 471 hsi = kzalloc(sizeof(*hsi), flags);472 if (!hsi)473 return NULL;474 port = kcalloc(n_ports, sizeof(*port), flags);475 if (!port) {476 kfree(hsi);477 return NULL;478 }479 hsi->num_ports = n_ports;480 hsi->port = port;481 hsi->device.release = hsi_controller_release;482 device_initialize(&hsi->device);483 484 for (i = 0; i < n_ports; i++) {485 port[i] = kzalloc(sizeof(**port), flags);486 if (port[i] == NULL)487 goto out;488 port[i]->num = i;489 port[i]->async = hsi_dummy_msg;490 port[i]->setup = hsi_dummy_cl;491 port[i]->flush = hsi_dummy_cl;492 port[i]->start_tx = hsi_dummy_cl;493 port[i]->stop_tx = hsi_dummy_cl;494 port[i]->release = hsi_dummy_cl;495 mutex_init(&port[i]->lock);496 BLOCKING_INIT_NOTIFIER_HEAD(&port[i]->n_head);497 dev_set_name(&port[i]->device, "port%d", i);498 hsi->port[i]->device.release = hsi_port_release;499 device_initialize(&hsi->port[i]->device);500 }501 502 return hsi;503out:504 hsi_put_controller(hsi);505 506 return NULL;507}508EXPORT_SYMBOL_GPL(hsi_alloc_controller);509 510/**511 * hsi_free_msg - Free an HSI message512 * @msg: Pointer to the HSI message513 *514 * Client is responsible to free the buffers pointed by the scatterlists.515 */516void hsi_free_msg(struct hsi_msg *msg)517{518 if (!msg)519 return;520 sg_free_table(&msg->sgt);521 kfree(msg);522}523EXPORT_SYMBOL_GPL(hsi_free_msg);524 525/**526 * hsi_alloc_msg - Allocate an HSI message527 * @nents: Number of memory entries528 * @flags: Kernel allocation flags529 *530 * nents can be 0. This mainly makes sense for read transfer.531 * In that case, HSI drivers will call the complete callback when532 * there is data to be read without consuming it.533 *534 * Return NULL on failure or a pointer to an hsi_msg on success.535 */536struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)537{538 struct hsi_msg *msg;539 int err;540 541 msg = kzalloc(sizeof(*msg), flags);542 if (!msg)543 return NULL;544 545 if (!nents)546 return msg;547 548 err = sg_alloc_table(&msg->sgt, nents, flags);549 if (unlikely(err)) {550 kfree(msg);551 msg = NULL;552 }553 554 return msg;555}556EXPORT_SYMBOL_GPL(hsi_alloc_msg);557 558/**559 * hsi_async - Submit an HSI transfer to the controller560 * @cl: HSI client sending the transfer561 * @msg: The HSI transfer passed to controller562 *563 * The HSI message must have the channel, ttype, complete and destructor564 * fields set beforehand. If nents > 0 then the client has to initialize565 * also the scatterlists to point to the buffers to write to or read from.566 *567 * HSI controllers relay on pre-allocated buffers from their clients and they568 * do not allocate buffers on their own.569 *570 * Once the HSI message transfer finishes, the HSI controller calls the571 * complete callback with the status and actual_len fields of the HSI message572 * updated. The complete callback can be called before returning from573 * hsi_async.574 *575 * Returns -errno on failure or 0 on success576 */577int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)578{579 struct hsi_port *port = hsi_get_port(cl);580 581 if (!hsi_port_claimed(cl))582 return -EACCES;583 584 WARN_ON_ONCE(!msg->destructor || !msg->complete);585 msg->cl = cl;586 587 return port->async(msg);588}589EXPORT_SYMBOL_GPL(hsi_async);590 591/**592 * hsi_claim_port - Claim the HSI client's port593 * @cl: HSI client that wants to claim its port594 * @share: Flag to indicate if the client wants to share the port or not.595 *596 * Returns -errno on failure, 0 on success.597 */598int hsi_claim_port(struct hsi_client *cl, unsigned int share)599{600 struct hsi_port *port = hsi_get_port(cl);601 int err = 0;602 603 mutex_lock(&port->lock);604 if ((port->claimed) && (!port->shared || !share)) {605 err = -EBUSY;606 goto out;607 }608 if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {609 err = -ENODEV;610 goto out;611 }612 port->claimed++;613 port->shared = !!share;614 cl->pclaimed = 1;615out:616 mutex_unlock(&port->lock);617 618 return err;619}620EXPORT_SYMBOL_GPL(hsi_claim_port);621 622/**623 * hsi_release_port - Release the HSI client's port624 * @cl: HSI client which previously claimed its port625 */626void hsi_release_port(struct hsi_client *cl)627{628 struct hsi_port *port = hsi_get_port(cl);629 630 mutex_lock(&port->lock);631 /* Allow HW driver to do some cleanup */632 port->release(cl);633 if (cl->pclaimed)634 port->claimed--;635 BUG_ON(port->claimed < 0);636 cl->pclaimed = 0;637 if (!port->claimed)638 port->shared = 0;639 module_put(to_hsi_controller(port->device.parent)->owner);640 mutex_unlock(&port->lock);641}642EXPORT_SYMBOL_GPL(hsi_release_port);643 644static int hsi_event_notifier_call(struct notifier_block *nb,645 unsigned long event, void *data __maybe_unused)646{647 struct hsi_client *cl = container_of(nb, struct hsi_client, nb);648 649 (*cl->ehandler)(cl, event);650 651 return 0;652}653 654/**655 * hsi_register_port_event - Register a client to receive port events656 * @cl: HSI client that wants to receive port events657 * @handler: Event handler callback658 *659 * Clients should register a callback to be able to receive660 * events from the ports. Registration should happen after661 * claiming the port.662 * The handler can be called in interrupt context.663 *664 * Returns -errno on error, or 0 on success.665 */666int hsi_register_port_event(struct hsi_client *cl,667 void (*handler)(struct hsi_client *, unsigned long))668{669 struct hsi_port *port = hsi_get_port(cl);670 671 if (!handler || cl->ehandler)672 return -EINVAL;673 if (!hsi_port_claimed(cl))674 return -EACCES;675 cl->ehandler = handler;676 cl->nb.notifier_call = hsi_event_notifier_call;677 678 return blocking_notifier_chain_register(&port->n_head, &cl->nb);679}680EXPORT_SYMBOL_GPL(hsi_register_port_event);681 682/**683 * hsi_unregister_port_event - Stop receiving port events for a client684 * @cl: HSI client that wants to stop receiving port events685 *686 * Clients should call this function before releasing their associated687 * port.688 *689 * Returns -errno on error, or 0 on success.690 */691int hsi_unregister_port_event(struct hsi_client *cl)692{693 struct hsi_port *port = hsi_get_port(cl);694 int err;695 696 WARN_ON(!hsi_port_claimed(cl));697 698 err = blocking_notifier_chain_unregister(&port->n_head, &cl->nb);699 if (!err)700 cl->ehandler = NULL;701 702 return err;703}704EXPORT_SYMBOL_GPL(hsi_unregister_port_event);705 706/**707 * hsi_event - Notifies clients about port events708 * @port: Port where the event occurred709 * @event: The event type710 *711 * Clients should not be concerned about wake line behavior. However, due712 * to a race condition in HSI HW protocol, clients need to be notified713 * about wake line changes, so they can implement a workaround for it.714 *715 * Events:716 * HSI_EVENT_START_RX - Incoming wake line high717 * HSI_EVENT_STOP_RX - Incoming wake line down718 *719 * Returns -errno on error, or 0 on success.720 */721int hsi_event(struct hsi_port *port, unsigned long event)722{723 return blocking_notifier_call_chain(&port->n_head, event, NULL);724}725EXPORT_SYMBOL_GPL(hsi_event);726 727/**728 * hsi_get_channel_id_by_name - acquire channel id by channel name729 * @cl: HSI client, which uses the channel730 * @name: name the channel is known under731 *732 * Clients can call this function to get the hsi channel ids similar to733 * requesting IRQs or GPIOs by name. This function assumes the same734 * channel configuration is used for RX and TX.735 *736 * Returns -errno on error or channel id on success.737 */738int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)739{740 int i;741 742 if (!cl->rx_cfg.channels)743 return -ENOENT;744 745 for (i = 0; i < cl->rx_cfg.num_channels; i++)746 if (!strcmp(cl->rx_cfg.channels[i].name, name))747 return cl->rx_cfg.channels[i].id;748 749 return -ENXIO;750}751EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name);752 753static int __init hsi_init(void)754{755 return bus_register(&hsi_bus_type);756}757postcore_initcall(hsi_init);758 759static void __exit hsi_exit(void)760{761 bus_unregister(&hsi_bus_type);762}763module_exit(hsi_exit);764 765MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");766MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");767MODULE_LICENSE("GPL v2");768