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 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                        return id;
  33
  34        return NULL;
  35}
  36
  37static int scmi_dev_match(struct device *dev, struct device_driver *drv)
  38{
  39        struct scmi_driver *scmi_drv = to_scmi_driver(drv);
  40        struct scmi_device *scmi_dev = to_scmi_dev(dev);
  41        const struct scmi_device_id *id;
  42
  43        id = scmi_dev_match_id(scmi_dev, scmi_drv);
  44        if (id)
  45                return 1;
  46
  47        return 0;
  48}
  49
  50static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle)
  51{
  52        scmi_prot_init_fn_t fn = idr_find(&scmi_protocols, protocol_id);
  53
  54        if (unlikely(!fn))
  55                return -EINVAL;
  56        return fn(handle);
  57}
  58
  59static int scmi_dev_probe(struct device *dev)
  60{
  61        struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
  62        struct scmi_device *scmi_dev = to_scmi_dev(dev);
  63        const struct scmi_device_id *id;
  64        int ret;
  65
  66        id = scmi_dev_match_id(scmi_dev, scmi_drv);
  67        if (!id)
  68                return -ENODEV;
  69
  70        if (!scmi_dev->handle)
  71                return -EPROBE_DEFER;
  72
  73        ret = scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle);
  74        if (ret)
  75                return ret;
  76
  77        return scmi_drv->probe(scmi_dev);
  78}
  79
  80static int scmi_dev_remove(struct device *dev)
  81{
  82        struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
  83        struct scmi_device *scmi_dev = to_scmi_dev(dev);
  84
  85        if (scmi_drv->remove)
  86                scmi_drv->remove(scmi_dev);
  87
  88        return 0;
  89}
  90
  91static struct bus_type scmi_bus_type = {
  92        .name = "scmi_protocol",
  93        .match = scmi_dev_match,
  94        .probe = scmi_dev_probe,
  95        .remove = scmi_dev_remove,
  96};
  97
  98int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
  99                         const char *mod_name)
 100{
 101        int retval;
 102
 103        driver->driver.bus = &scmi_bus_type;
 104        driver->driver.name = driver->name;
 105        driver->driver.owner = owner;
 106        driver->driver.mod_name = mod_name;
 107
 108        retval = driver_register(&driver->driver);
 109        if (!retval)
 110                pr_debug("registered new scmi driver %s\n", driver->name);
 111
 112        return retval;
 113}
 114EXPORT_SYMBOL_GPL(scmi_driver_register);
 115
 116void scmi_driver_unregister(struct scmi_driver *driver)
 117{
 118        driver_unregister(&driver->driver);
 119}
 120EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 121
 122static void scmi_device_release(struct device *dev)
 123{
 124        kfree(to_scmi_dev(dev));
 125}
 126
 127struct scmi_device *
 128scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 129{
 130        int id, retval;
 131        struct scmi_device *scmi_dev;
 132
 133        scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
 134        if (!scmi_dev)
 135                return NULL;
 136
 137        id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
 138        if (id < 0)
 139                goto free_mem;
 140
 141        scmi_dev->id = id;
 142        scmi_dev->protocol_id = protocol;
 143        scmi_dev->dev.parent = parent;
 144        scmi_dev->dev.of_node = np;
 145        scmi_dev->dev.bus = &scmi_bus_type;
 146        scmi_dev->dev.release = scmi_device_release;
 147        dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
 148
 149        retval = device_register(&scmi_dev->dev);
 150        if (retval)
 151                goto put_dev;
 152
 153        return scmi_dev;
 154put_dev:
 155        put_device(&scmi_dev->dev);
 156        ida_simple_remove(&scmi_bus_id, id);
 157free_mem:
 158        kfree(scmi_dev);
 159        return NULL;
 160}
 161
 162void scmi_device_destroy(struct scmi_device *scmi_dev)
 163{
 164        scmi_handle_put(scmi_dev->handle);
 165        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
 166        device_unregister(&scmi_dev->dev);
 167}
 168
 169void scmi_set_handle(struct scmi_device *scmi_dev)
 170{
 171        scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
 172}
 173
 174int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn)
 175{
 176        int ret;
 177
 178        spin_lock(&protocol_lock);
 179        ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1,
 180                        GFP_ATOMIC);
 181        spin_unlock(&protocol_lock);
 182        if (ret != protocol_id)
 183                pr_err("unable to allocate SCMI idr slot, err %d\n", ret);
 184
 185        return ret;
 186}
 187EXPORT_SYMBOL_GPL(scmi_protocol_register);
 188
 189void scmi_protocol_unregister(int protocol_id)
 190{
 191        spin_lock(&protocol_lock);
 192        idr_remove(&scmi_protocols, protocol_id);
 193        spin_unlock(&protocol_lock);
 194}
 195EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
 196
 197static int __scmi_devices_unregister(struct device *dev, void *data)
 198{
 199        struct scmi_device *scmi_dev = to_scmi_dev(dev);
 200
 201        scmi_device_destroy(scmi_dev);
 202        return 0;
 203}
 204
 205static void scmi_devices_unregister(void)
 206{
 207        bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
 208}
 209
 210static int __init scmi_bus_init(void)
 211{
 212        int retval;
 213
 214        retval = bus_register(&scmi_bus_type);
 215        if (retval)
 216                pr_err("scmi protocol bus register failed (%d)\n", retval);
 217
 218        return retval;
 219}
 220subsys_initcall(scmi_bus_init);
 221
 222static void __exit scmi_bus_exit(void)
 223{
 224        scmi_devices_unregister();
 225        bus_unregister(&scmi_bus_type);
 226        ida_destroy(&scmi_bus_id);
 227}
 228module_exit(scmi_bus_exit);
 229