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
 108        if (!scmi_dev->handle)
 109                return -EPROBE_DEFER;
 110
 111        return scmi_drv->probe(scmi_dev);
 112}
 113
 114static int scmi_dev_remove(struct device *dev)
 115{
 116        struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 117        struct scmi_device *scmi_dev = to_scmi_dev(dev);
 118
 119        if (scmi_drv->remove)
 120                scmi_drv->remove(scmi_dev);
 121
 122        return 0;
 123}
 124
 125static struct bus_type scmi_bus_type = {
 126        .name = "scmi_protocol",
 127        .match = scmi_dev_match,
 128        .probe = scmi_dev_probe,
 129        .remove = scmi_dev_remove,
 130};
 131
 132int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
 133                         const char *mod_name)
 134{
 135        int retval;
 136
 137        if (!driver->probe)
 138                return -EINVAL;
 139
 140        retval = scmi_protocol_device_request(driver->id_table);
 141        if (retval)
 142                return retval;
 143
 144        driver->driver.bus = &scmi_bus_type;
 145        driver->driver.name = driver->name;
 146        driver->driver.owner = owner;
 147        driver->driver.mod_name = mod_name;
 148
 149        retval = driver_register(&driver->driver);
 150        if (!retval)
 151                pr_debug("registered new scmi driver %s\n", driver->name);
 152
 153        return retval;
 154}
 155EXPORT_SYMBOL_GPL(scmi_driver_register);
 156
 157void scmi_driver_unregister(struct scmi_driver *driver)
 158{
 159        driver_unregister(&driver->driver);
 160        scmi_protocol_device_unrequest(driver->id_table);
 161}
 162EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 163
 164static void scmi_device_release(struct device *dev)
 165{
 166        kfree(to_scmi_dev(dev));
 167}
 168
 169struct scmi_device *
 170scmi_device_create(struct device_node *np, struct device *parent, int protocol,
 171                   const char *name)
 172{
 173        int id, retval;
 174        struct scmi_device *scmi_dev;
 175
 176        scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
 177        if (!scmi_dev)
 178                return NULL;
 179
 180        scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
 181        if (!scmi_dev->name) {
 182                kfree(scmi_dev);
 183                return NULL;
 184        }
 185
 186        id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
 187        if (id < 0) {
 188                kfree_const(scmi_dev->name);
 189                kfree(scmi_dev);
 190                return NULL;
 191        }
 192
 193        scmi_dev->id = id;
 194        scmi_dev->protocol_id = protocol;
 195        scmi_dev->dev.parent = parent;
 196        scmi_dev->dev.of_node = np;
 197        scmi_dev->dev.bus = &scmi_bus_type;
 198        scmi_dev->dev.release = scmi_device_release;
 199        dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
 200
 201        retval = device_register(&scmi_dev->dev);
 202        if (retval)
 203                goto put_dev;
 204
 205        return scmi_dev;
 206put_dev:
 207        kfree_const(scmi_dev->name);
 208        put_device(&scmi_dev->dev);
 209        ida_simple_remove(&scmi_bus_id, id);
 210        return NULL;
 211}
 212
 213void scmi_device_destroy(struct scmi_device *scmi_dev)
 214{
 215        kfree_const(scmi_dev->name);
 216        scmi_handle_put(scmi_dev->handle);
 217        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
 218        device_unregister(&scmi_dev->dev);
 219}
 220
 221void scmi_set_handle(struct scmi_device *scmi_dev)
 222{
 223        scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
 224}
 225
 226int scmi_protocol_register(const struct scmi_protocol *proto)
 227{
 228        int ret;
 229
 230        if (!proto) {
 231                pr_err("invalid protocol\n");
 232                return -EINVAL;
 233        }
 234
 235        if (!proto->instance_init) {
 236                pr_err("missing init for protocol 0x%x\n", proto->id);
 237                return -EINVAL;
 238        }
 239
 240        spin_lock(&protocol_lock);
 241        ret = idr_alloc(&scmi_protocols, (void *)proto,
 242                        proto->id, proto->id + 1, GFP_ATOMIC);
 243        spin_unlock(&protocol_lock);
 244        if (ret != proto->id) {
 245                pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n",
 246                       proto->id, ret);
 247                return ret;
 248        }
 249
 250        pr_debug("Registered SCMI Protocol 0x%x\n", proto->id);
 251
 252        return 0;
 253}
 254EXPORT_SYMBOL_GPL(scmi_protocol_register);
 255
 256void scmi_protocol_unregister(const struct scmi_protocol *proto)
 257{
 258        spin_lock(&protocol_lock);
 259        idr_remove(&scmi_protocols, proto->id);
 260        spin_unlock(&protocol_lock);
 261
 262        pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id);
 263
 264        return;
 265}
 266EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
 267
 268static int __scmi_devices_unregister(struct device *dev, void *data)
 269{
 270        struct scmi_device *scmi_dev = to_scmi_dev(dev);
 271
 272        scmi_device_destroy(scmi_dev);
 273        return 0;
 274}
 275
 276static void scmi_devices_unregister(void)
 277{
 278        bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
 279}
 280
 281int __init scmi_bus_init(void)
 282{
 283        int retval;
 284
 285        retval = bus_register(&scmi_bus_type);
 286        if (retval)
 287                pr_err("scmi protocol bus register failed (%d)\n", retval);
 288
 289        return retval;
 290}
 291
 292void __exit scmi_bus_exit(void)
 293{
 294        scmi_devices_unregister();
 295        bus_unregister(&scmi_bus_type);
 296        ida_destroy(&scmi_bus_id);
 297}
 298