linux/drivers/firmware/arm_scmi/bus.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * System Control and Management Interface (SCMI) Message Protocol bus layer
   4 *
   5 * Copyright (C) 2018-2021 ARM Ltd.
   6 */
   7
   8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9
  10#include <linux/types.h>
  11#include <linux/module.h>
  12#include <linux/kernel.h>
  13#include <linux/slab.h>
  14#include <linux/device.h>
  15
  16#include "common.h"
  17
  18static DEFINE_IDA(scmi_bus_id);
  19static DEFINE_IDR(scmi_protocols);
  20static DEFINE_SPINLOCK(protocol_lock);
  21
  22static const struct scmi_device_id *
  23scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
  24{
  25        const struct scmi_device_id *id = scmi_drv->id_table;
  26
  27        if (!id)
  28                return NULL;
  29
  30        for (; id->protocol_id; id++)
  31                if (id->protocol_id == scmi_dev->protocol_id) {
  32                        if (!id->name)
  33                                return id;
  34                        else if (!strcmp(id->name, scmi_dev->name))
  35                                return id;
  36                }
  37
  38        return NULL;
  39}
  40
  41static int scmi_dev_match(struct device *dev, struct device_driver *drv)
  42{
  43        struct scmi_driver *scmi_drv = to_scmi_driver(drv);
  44        struct scmi_device *scmi_dev = to_scmi_dev(dev);
  45        const struct scmi_device_id *id;
  46
  47        id = scmi_dev_match_id(scmi_dev, scmi_drv);
  48        if (id)
  49                return 1;
  50
  51        return 0;
  52}
  53
  54static int scmi_match_by_id_table(struct device *dev, void *data)
  55{
  56        struct scmi_device *sdev = to_scmi_dev(dev);
  57        struct scmi_device_id *id_table = data;
  58
  59        return sdev->protocol_id == id_table->protocol_id &&
  60                !strcmp(sdev->name, id_table->name);
  61}
  62
  63struct scmi_device *scmi_child_dev_find(struct device *parent,
  64                                        int prot_id, const char *name)
  65{
  66        struct scmi_device_id id_table;
  67        struct device *dev;
  68
  69        id_table.protocol_id = prot_id;
  70        id_table.name = name;
  71
  72        dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
  73        if (!dev)
  74                return NULL;
  75
  76        return to_scmi_dev(dev);
  77}
  78
  79const struct scmi_protocol *scmi_protocol_get(int protocol_id)
  80{
  81        const struct scmi_protocol *proto;
  82
  83        proto = idr_find(&scmi_protocols, protocol_id);
  84        if (!proto || !try_module_get(proto->owner)) {
  85                pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id);
  86                return NULL;
  87        }
  88
  89        pr_debug("Found SCMI Protocol 0x%x\n", protocol_id);
  90
  91        return proto;
  92}
  93
  94void scmi_protocol_put(int protocol_id)
  95{
  96        const struct scmi_protocol *proto;
  97
  98        proto = idr_find(&scmi_protocols, protocol_id);
  99        if (proto)
 100                module_put(proto->owner);
 101}
 102
 103static int scmi_dev_probe(struct device *dev)
 104{
 105        struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 106        struct scmi_device *scmi_dev = to_scmi_dev(dev);
 107        const struct scmi_device_id *id;
 108
 109        id = scmi_dev_match_id(scmi_dev, scmi_drv);
 110        if (!id)
 111                return -ENODEV;
 112
 113        if (!scmi_dev->handle)
 114                return -EPROBE_DEFER;
 115
 116        return scmi_drv->probe(scmi_dev);
 117}
 118
 119static int scmi_dev_remove(struct device *dev)
 120{
 121        struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 122        struct scmi_device *scmi_dev = to_scmi_dev(dev);
 123
 124        if (scmi_drv->remove)
 125                scmi_drv->remove(scmi_dev);
 126
 127        return 0;
 128}
 129
 130static struct bus_type scmi_bus_type = {
 131        .name = "scmi_protocol",
 132        .match = scmi_dev_match,
 133        .probe = scmi_dev_probe,
 134        .remove = scmi_dev_remove,
 135};
 136
 137int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
 138                         const char *mod_name)
 139{
 140        int retval;
 141
 142        if (!driver->probe)
 143                return -EINVAL;
 144
 145        retval = scmi_protocol_device_request(driver->id_table);
 146        if (retval)
 147                return retval;
 148
 149        driver->driver.bus = &scmi_bus_type;
 150        driver->driver.name = driver->name;
 151        driver->driver.owner = owner;
 152        driver->driver.mod_name = mod_name;
 153
 154        retval = driver_register(&driver->driver);
 155        if (!retval)
 156                pr_debug("registered new scmi driver %s\n", driver->name);
 157
 158        return retval;
 159}
 160EXPORT_SYMBOL_GPL(scmi_driver_register);
 161
 162void scmi_driver_unregister(struct scmi_driver *driver)
 163{
 164        driver_unregister(&driver->driver);
 165        scmi_protocol_device_unrequest(driver->id_table);
 166}
 167EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 168
 169static void scmi_device_release(struct device *dev)
 170{
 171        kfree(to_scmi_dev(dev));
 172}
 173
 174struct scmi_device *
 175scmi_device_create(struct device_node *np, struct device *parent, int protocol,
 176                   const char *name)
 177{
 178        int id, retval;
 179        struct scmi_device *scmi_dev;
 180
 181        scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
 182        if (!scmi_dev)
 183                return NULL;
 184
 185        scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
 186        if (!scmi_dev->name) {
 187                kfree(scmi_dev);
 188                return NULL;
 189        }
 190
 191        id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
 192        if (id < 0) {
 193                kfree_const(scmi_dev->name);
 194                kfree(scmi_dev);
 195                return NULL;
 196        }
 197
 198        scmi_dev->id = id;
 199        scmi_dev->protocol_id = protocol;
 200        scmi_dev->dev.parent = parent;
 201        scmi_dev->dev.of_node = np;
 202        scmi_dev->dev.bus = &scmi_bus_type;
 203        scmi_dev->dev.release = scmi_device_release;
 204        dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
 205
 206        retval = device_register(&scmi_dev->dev);
 207        if (retval)
 208                goto put_dev;
 209
 210        return scmi_dev;
 211put_dev:
 212        kfree_const(scmi_dev->name);
 213        put_device(&scmi_dev->dev);
 214        ida_simple_remove(&scmi_bus_id, id);
 215        return NULL;
 216}
 217
 218void scmi_device_destroy(struct scmi_device *scmi_dev)
 219{
 220        kfree_const(scmi_dev->name);
 221        scmi_handle_put(scmi_dev->handle);
 222        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
 223        device_unregister(&scmi_dev->dev);
 224}
 225
 226void scmi_set_handle(struct scmi_device *scmi_dev)
 227{
 228        scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
 229}
 230
 231int scmi_protocol_register(const struct scmi_protocol *proto)
 232{
 233        int ret;
 234
 235        if (!proto) {
 236                pr_err("invalid protocol\n");
 237                return -EINVAL;
 238        }
 239
 240        if (!proto->instance_init) {
 241                pr_err("missing init for protocol 0x%x\n", proto->id);
 242                return -EINVAL;
 243        }
 244
 245        spin_lock(&protocol_lock);
 246        ret = idr_alloc(&scmi_protocols, (void *)proto,
 247                        proto->id, proto->id + 1, GFP_ATOMIC);
 248        spin_unlock(&protocol_lock);
 249        if (ret != proto->id) {
 250                pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n",
 251                       proto->id, ret);
 252                return ret;
 253        }
 254
 255        pr_debug("Registered SCMI Protocol 0x%x\n", proto->id);
 256
 257        return 0;
 258}
 259EXPORT_SYMBOL_GPL(scmi_protocol_register);
 260
 261void scmi_protocol_unregister(const struct scmi_protocol *proto)
 262{
 263        spin_lock(&protocol_lock);
 264        idr_remove(&scmi_protocols, proto->id);
 265        spin_unlock(&protocol_lock);
 266
 267        pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id);
 268
 269        return;
 270}
 271EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
 272
 273static int __scmi_devices_unregister(struct device *dev, void *data)
 274{
 275        struct scmi_device *scmi_dev = to_scmi_dev(dev);
 276
 277        scmi_device_destroy(scmi_dev);
 278        return 0;
 279}
 280
 281static void scmi_devices_unregister(void)
 282{
 283        bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
 284}
 285
 286int __init scmi_bus_init(void)
 287{
 288        int retval;
 289
 290        retval = bus_register(&scmi_bus_type);
 291        if (retval)
 292                pr_err("scmi protocol bus register failed (%d)\n", retval);
 293
 294        return retval;
 295}
 296
 297void __exit scmi_bus_exit(void)
 298{
 299        scmi_devices_unregister();
 300        bus_unregister(&scmi_bus_type);
 301        ida_destroy(&scmi_bus_id);
 302}
 303