linux/drivers/slimbus/core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2011-2017, The Linux Foundation
   4 */
   5
   6#include <linux/kernel.h>
   7#include <linux/errno.h>
   8#include <linux/slab.h>
   9#include <linux/init.h>
  10#include <linux/idr.h>
  11#include <linux/of.h>
  12#include <linux/of_device.h>
  13#include <linux/pm_runtime.h>
  14#include <linux/slimbus.h>
  15#include "slimbus.h"
  16
  17static DEFINE_IDA(ctrl_ida);
  18
  19static const struct slim_device_id *slim_match(const struct slim_device_id *id,
  20                                               const struct slim_device *sbdev)
  21{
  22        while (id->manf_id != 0 || id->prod_code != 0) {
  23                if (id->manf_id == sbdev->e_addr.manf_id &&
  24                    id->prod_code == sbdev->e_addr.prod_code &&
  25                    id->dev_index == sbdev->e_addr.dev_index &&
  26                    id->instance == sbdev->e_addr.instance)
  27                        return id;
  28                id++;
  29        }
  30        return NULL;
  31}
  32
  33static int slim_device_match(struct device *dev, struct device_driver *drv)
  34{
  35        struct slim_device *sbdev = to_slim_device(dev);
  36        struct slim_driver *sbdrv = to_slim_driver(drv);
  37
  38        /* Attempt an OF style match first */
  39        if (of_driver_match_device(dev, drv))
  40                return 1;
  41
  42        return !!slim_match(sbdrv->id_table, sbdev);
  43}
  44
  45static void slim_device_update_status(struct slim_device *sbdev,
  46                                      enum slim_device_status status)
  47{
  48        struct slim_driver *sbdrv;
  49
  50        if (sbdev->status == status)
  51                return;
  52
  53        sbdev->status = status;
  54        if (!sbdev->dev.driver)
  55                return;
  56
  57        sbdrv = to_slim_driver(sbdev->dev.driver);
  58        if (sbdrv->device_status)
  59                sbdrv->device_status(sbdev, sbdev->status);
  60}
  61
  62static int slim_device_probe(struct device *dev)
  63{
  64        struct slim_device      *sbdev = to_slim_device(dev);
  65        struct slim_driver      *sbdrv = to_slim_driver(dev->driver);
  66        int ret;
  67
  68        ret = sbdrv->probe(sbdev);
  69        if (ret)
  70                return ret;
  71
  72        /* try getting the logical address after probe */
  73        ret = slim_get_logical_addr(sbdev);
  74        if (!ret) {
  75                slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP);
  76        } else {
  77                dev_err(&sbdev->dev, "Failed to get logical address\n");
  78                ret = -EPROBE_DEFER;
  79        }
  80
  81        return ret;
  82}
  83
  84static int slim_device_remove(struct device *dev)
  85{
  86        struct slim_device *sbdev = to_slim_device(dev);
  87        struct slim_driver *sbdrv;
  88
  89        if (dev->driver) {
  90                sbdrv = to_slim_driver(dev->driver);
  91                if (sbdrv->remove)
  92                        sbdrv->remove(sbdev);
  93        }
  94
  95        return 0;
  96}
  97
  98static int slim_device_uevent(struct device *dev, struct kobj_uevent_env *env)
  99{
 100        struct slim_device *sbdev = to_slim_device(dev);
 101
 102        return add_uevent_var(env, "MODALIAS=slim:%s", dev_name(&sbdev->dev));
 103}
 104
 105struct bus_type slimbus_bus = {
 106        .name           = "slimbus",
 107        .match          = slim_device_match,
 108        .probe          = slim_device_probe,
 109        .remove         = slim_device_remove,
 110        .uevent         = slim_device_uevent,
 111};
 112EXPORT_SYMBOL_GPL(slimbus_bus);
 113
 114/*
 115 * __slim_driver_register() - Client driver registration with SLIMbus
 116 *
 117 * @drv:Client driver to be associated with client-device.
 118 * @owner: owning module/driver
 119 *
 120 * This API will register the client driver with the SLIMbus
 121 * It is called from the driver's module-init function.
 122 */
 123int __slim_driver_register(struct slim_driver *drv, struct module *owner)
 124{
 125        /* ID table and probe are mandatory */
 126        if (!(drv->driver.of_match_table || drv->id_table) || !drv->probe)
 127                return -EINVAL;
 128
 129        drv->driver.bus = &slimbus_bus;
 130        drv->driver.owner = owner;
 131
 132        return driver_register(&drv->driver);
 133}
 134EXPORT_SYMBOL_GPL(__slim_driver_register);
 135
 136/*
 137 * slim_driver_unregister() - Undo effect of slim_driver_register
 138 *
 139 * @drv: Client driver to be unregistered
 140 */
 141void slim_driver_unregister(struct slim_driver *drv)
 142{
 143        driver_unregister(&drv->driver);
 144}
 145EXPORT_SYMBOL_GPL(slim_driver_unregister);
 146
 147static void slim_dev_release(struct device *dev)
 148{
 149        struct slim_device *sbdev = to_slim_device(dev);
 150
 151        kfree(sbdev);
 152}
 153
 154static int slim_add_device(struct slim_controller *ctrl,
 155                           struct slim_device *sbdev,
 156                           struct device_node *node)
 157{
 158        sbdev->dev.bus = &slimbus_bus;
 159        sbdev->dev.parent = ctrl->dev;
 160        sbdev->dev.release = slim_dev_release;
 161        sbdev->dev.driver = NULL;
 162        sbdev->ctrl = ctrl;
 163        INIT_LIST_HEAD(&sbdev->stream_list);
 164        spin_lock_init(&sbdev->stream_list_lock);
 165        sbdev->dev.of_node = of_node_get(node);
 166        sbdev->dev.fwnode = of_fwnode_handle(node);
 167
 168        dev_set_name(&sbdev->dev, "%x:%x:%x:%x",
 169                                  sbdev->e_addr.manf_id,
 170                                  sbdev->e_addr.prod_code,
 171                                  sbdev->e_addr.dev_index,
 172                                  sbdev->e_addr.instance);
 173
 174        return device_register(&sbdev->dev);
 175}
 176
 177static struct slim_device *slim_alloc_device(struct slim_controller *ctrl,
 178                                             struct slim_eaddr *eaddr,
 179                                             struct device_node *node)
 180{
 181        struct slim_device *sbdev;
 182        int ret;
 183
 184        sbdev = kzalloc(sizeof(*sbdev), GFP_KERNEL);
 185        if (!sbdev)
 186                return NULL;
 187
 188        sbdev->e_addr = *eaddr;
 189        ret = slim_add_device(ctrl, sbdev, node);
 190        if (ret) {
 191                put_device(&sbdev->dev);
 192                return NULL;
 193        }
 194
 195        return sbdev;
 196}
 197
 198static void of_register_slim_devices(struct slim_controller *ctrl)
 199{
 200        struct device *dev = ctrl->dev;
 201        struct device_node *node;
 202
 203        if (!ctrl->dev->of_node)
 204                return;
 205
 206        for_each_child_of_node(ctrl->dev->of_node, node) {
 207                struct slim_device *sbdev;
 208                struct slim_eaddr e_addr;
 209                const char *compat = NULL;
 210                int reg[2], ret;
 211                int manf_id, prod_code;
 212
 213                compat = of_get_property(node, "compatible", NULL);
 214                if (!compat)
 215                        continue;
 216
 217                ret = sscanf(compat, "slim%x,%x", &manf_id, &prod_code);
 218                if (ret != 2) {
 219                        dev_err(dev, "Manf ID & Product code not found %s\n",
 220                                compat);
 221                        continue;
 222                }
 223
 224                ret = of_property_read_u32_array(node, "reg", reg, 2);
 225                if (ret) {
 226                        dev_err(dev, "Device and Instance id not found:%d\n",
 227                                ret);
 228                        continue;
 229                }
 230
 231                e_addr.dev_index = reg[0];
 232                e_addr.instance = reg[1];
 233                e_addr.manf_id = manf_id;
 234                e_addr.prod_code = prod_code;
 235
 236                sbdev = slim_alloc_device(ctrl, &e_addr, node);
 237                if (!sbdev)
 238                        continue;
 239        }
 240}
 241
 242/*
 243 * slim_register_controller() - Controller bring-up and registration.
 244 *
 245 * @ctrl: Controller to be registered.
 246 *
 247 * A controller is registered with the framework using this API.
 248 * If devices on a controller were registered before controller,
 249 * this will make sure that they get probed when controller is up
 250 */
 251int slim_register_controller(struct slim_controller *ctrl)
 252{
 253        int id;
 254
 255        id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL);
 256        if (id < 0)
 257                return id;
 258
 259        ctrl->id = id;
 260
 261        if (!ctrl->min_cg)
 262                ctrl->min_cg = SLIM_MIN_CLK_GEAR;
 263        if (!ctrl->max_cg)
 264                ctrl->max_cg = SLIM_MAX_CLK_GEAR;
 265
 266        ida_init(&ctrl->laddr_ida);
 267        idr_init(&ctrl->tid_idr);
 268        mutex_init(&ctrl->lock);
 269        mutex_init(&ctrl->sched.m_reconf);
 270        init_completion(&ctrl->sched.pause_comp);
 271        spin_lock_init(&ctrl->txn_lock);
 272
 273        dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n",
 274                ctrl->name, ctrl->dev);
 275
 276        of_register_slim_devices(ctrl);
 277
 278        return 0;
 279}
 280EXPORT_SYMBOL_GPL(slim_register_controller);
 281
 282/* slim_remove_device: Remove the effect of slim_add_device() */
 283static void slim_remove_device(struct slim_device *sbdev)
 284{
 285        of_node_put(sbdev->dev.of_node);
 286        device_unregister(&sbdev->dev);
 287}
 288
 289static int slim_ctrl_remove_device(struct device *dev, void *null)
 290{
 291        slim_remove_device(to_slim_device(dev));
 292        return 0;
 293}
 294
 295/**
 296 * slim_unregister_controller() - Controller tear-down.
 297 *
 298 * @ctrl: Controller to tear-down.
 299 */
 300int slim_unregister_controller(struct slim_controller *ctrl)
 301{
 302        /* Remove all clients */
 303        device_for_each_child(ctrl->dev, NULL, slim_ctrl_remove_device);
 304        /* Enter Clock Pause */
 305        slim_ctrl_clk_pause(ctrl, false, 0);
 306        ida_simple_remove(&ctrl_ida, ctrl->id);
 307
 308        return 0;
 309}
 310EXPORT_SYMBOL_GPL(slim_unregister_controller);
 311
 312/**
 313 * slim_report_absent() - Controller calls this function when a device
 314 *      reports absent, OR when the device cannot be communicated with
 315 *
 316 * @sbdev: Device that cannot be reached, or sent report absent
 317 */
 318void slim_report_absent(struct slim_device *sbdev)
 319{
 320        struct slim_controller *ctrl = sbdev->ctrl;
 321
 322        if (!ctrl)
 323                return;
 324
 325        /* invalidate logical addresses */
 326        mutex_lock(&ctrl->lock);
 327        sbdev->is_laddr_valid = false;
 328        mutex_unlock(&ctrl->lock);
 329
 330        ida_simple_remove(&ctrl->laddr_ida, sbdev->laddr);
 331        slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_DOWN);
 332}
 333EXPORT_SYMBOL_GPL(slim_report_absent);
 334
 335static bool slim_eaddr_equal(struct slim_eaddr *a, struct slim_eaddr *b)
 336{
 337        return (a->manf_id == b->manf_id &&
 338                a->prod_code == b->prod_code &&
 339                a->dev_index == b->dev_index &&
 340                a->instance == b->instance);
 341}
 342
 343static int slim_match_dev(struct device *dev, void *data)
 344{
 345        struct slim_eaddr *e_addr = data;
 346        struct slim_device *sbdev = to_slim_device(dev);
 347
 348        return slim_eaddr_equal(&sbdev->e_addr, e_addr);
 349}
 350
 351static struct slim_device *find_slim_device(struct slim_controller *ctrl,
 352                                            struct slim_eaddr *eaddr)
 353{
 354        struct slim_device *sbdev;
 355        struct device *dev;
 356
 357        dev = device_find_child(ctrl->dev, eaddr, slim_match_dev);
 358        if (dev) {
 359                sbdev = to_slim_device(dev);
 360                return sbdev;
 361        }
 362
 363        return NULL;
 364}
 365
 366/**
 367 * slim_get_device() - get handle to a device.
 368 *
 369 * @ctrl: Controller on which this device will be added/queried
 370 * @e_addr: Enumeration address of the device to be queried
 371 *
 372 * Return: pointer to a device if it has already reported. Creates a new
 373 * device and returns pointer to it if the device has not yet enumerated.
 374 */
 375struct slim_device *slim_get_device(struct slim_controller *ctrl,
 376                                    struct slim_eaddr *e_addr)
 377{
 378        struct slim_device *sbdev;
 379
 380        sbdev = find_slim_device(ctrl, e_addr);
 381        if (!sbdev) {
 382                sbdev = slim_alloc_device(ctrl, e_addr, NULL);
 383                if (!sbdev)
 384                        return ERR_PTR(-ENOMEM);
 385        }
 386
 387        return sbdev;
 388}
 389EXPORT_SYMBOL_GPL(slim_get_device);
 390
 391static int of_slim_match_dev(struct device *dev, void *data)
 392{
 393        struct device_node *np = data;
 394        struct slim_device *sbdev = to_slim_device(dev);
 395
 396        return (sbdev->dev.of_node == np);
 397}
 398
 399static struct slim_device *of_find_slim_device(struct slim_controller *ctrl,
 400                                               struct device_node *np)
 401{
 402        struct slim_device *sbdev;
 403        struct device *dev;
 404
 405        dev = device_find_child(ctrl->dev, np, of_slim_match_dev);
 406        if (dev) {
 407                sbdev = to_slim_device(dev);
 408                return sbdev;
 409        }
 410
 411        return NULL;
 412}
 413
 414/**
 415 * of_slim_get_device() - get handle to a device using dt node.
 416 *
 417 * @ctrl: Controller on which this device will be added/queried
 418 * @np: node pointer to device
 419 *
 420 * Return: pointer to a device if it has already reported. Creates a new
 421 * device and returns pointer to it if the device has not yet enumerated.
 422 */
 423struct slim_device *of_slim_get_device(struct slim_controller *ctrl,
 424                                       struct device_node *np)
 425{
 426        return of_find_slim_device(ctrl, np);
 427}
 428EXPORT_SYMBOL_GPL(of_slim_get_device);
 429
 430static int slim_device_alloc_laddr(struct slim_device *sbdev,
 431                                   bool report_present)
 432{
 433        struct slim_controller *ctrl = sbdev->ctrl;
 434        u8 laddr;
 435        int ret;
 436
 437        mutex_lock(&ctrl->lock);
 438        if (ctrl->get_laddr) {
 439                ret = ctrl->get_laddr(ctrl, &sbdev->e_addr, &laddr);
 440                if (ret < 0)
 441                        goto err;
 442        } else if (report_present) {
 443                ret = ida_simple_get(&ctrl->laddr_ida,
 444                                     0, SLIM_LA_MANAGER - 1, GFP_KERNEL);
 445                if (ret < 0)
 446                        goto err;
 447
 448                laddr = ret;
 449        } else {
 450                ret = -EINVAL;
 451                goto err;
 452        }
 453
 454        if (ctrl->set_laddr) {
 455                ret = ctrl->set_laddr(ctrl, &sbdev->e_addr, laddr);
 456                if (ret) {
 457                        ret = -EINVAL;
 458                        goto err;
 459                }
 460        }
 461
 462        sbdev->laddr = laddr;
 463        sbdev->is_laddr_valid = true;
 464        mutex_unlock(&ctrl->lock);
 465
 466        slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP);
 467
 468        dev_dbg(ctrl->dev, "setting slimbus l-addr:%x, ea:%x,%x,%x,%x\n",
 469                laddr, sbdev->e_addr.manf_id, sbdev->e_addr.prod_code,
 470                sbdev->e_addr.dev_index, sbdev->e_addr.instance);
 471
 472        return 0;
 473
 474err:
 475        mutex_unlock(&ctrl->lock);
 476        return ret;
 477
 478}
 479
 480/**
 481 * slim_device_report_present() - Report enumerated device.
 482 *
 483 * @ctrl: Controller with which device is enumerated.
 484 * @e_addr: Enumeration address of the device.
 485 * @laddr: Return logical address (if valid flag is false)
 486 *
 487 * Called by controller in response to REPORT_PRESENT. Framework will assign
 488 * a logical address to this enumeration address.
 489 * Function returns -EXFULL to indicate that all logical addresses are already
 490 * taken.
 491 */
 492int slim_device_report_present(struct slim_controller *ctrl,
 493                               struct slim_eaddr *e_addr, u8 *laddr)
 494{
 495        struct slim_device *sbdev;
 496        int ret;
 497
 498        ret = pm_runtime_get_sync(ctrl->dev);
 499
 500        if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) {
 501                dev_err(ctrl->dev, "slim ctrl not active,state:%d, ret:%d\n",
 502                                    ctrl->sched.clk_state, ret);
 503                goto slimbus_not_active;
 504        }
 505
 506        sbdev = slim_get_device(ctrl, e_addr);
 507        if (IS_ERR(sbdev))
 508                return -ENODEV;
 509
 510        if (sbdev->is_laddr_valid) {
 511                *laddr = sbdev->laddr;
 512                return 0;
 513        }
 514
 515        ret = slim_device_alloc_laddr(sbdev, true);
 516
 517slimbus_not_active:
 518        pm_runtime_mark_last_busy(ctrl->dev);
 519        pm_runtime_put_autosuspend(ctrl->dev);
 520        return ret;
 521}
 522EXPORT_SYMBOL_GPL(slim_device_report_present);
 523
 524/**
 525 * slim_get_logical_addr() - get/allocate logical address of a SLIMbus device.
 526 *
 527 * @sbdev: client handle requesting the address.
 528 *
 529 * Return: zero if a logical address is valid or a new logical address
 530 * has been assigned. error code in case of error.
 531 */
 532int slim_get_logical_addr(struct slim_device *sbdev)
 533{
 534        if (!sbdev->is_laddr_valid)
 535                return slim_device_alloc_laddr(sbdev, false);
 536
 537        return 0;
 538}
 539EXPORT_SYMBOL_GPL(slim_get_logical_addr);
 540
 541static void __exit slimbus_exit(void)
 542{
 543        bus_unregister(&slimbus_bus);
 544}
 545module_exit(slimbus_exit);
 546
 547static int __init slimbus_init(void)
 548{
 549        return bus_register(&slimbus_bus);
 550}
 551postcore_initcall(slimbus_init);
 552
 553MODULE_LICENSE("GPL v2");
 554MODULE_DESCRIPTION("SLIMbus core");
 555