Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * System Control and Management Interface (SCMI) Message Protocol bus layer
0004  *
0005  * Copyright (C) 2018-2021 ARM Ltd.
0006  */
0007 
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009 
0010 #include <linux/types.h>
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/slab.h>
0014 #include <linux/device.h>
0015 
0016 #include "common.h"
0017 
0018 static DEFINE_IDA(scmi_bus_id);
0019 static DEFINE_IDR(scmi_protocols);
0020 static DEFINE_SPINLOCK(protocol_lock);
0021 
0022 static const struct scmi_device_id *
0023 scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
0024 {
0025     const struct scmi_device_id *id = scmi_drv->id_table;
0026 
0027     if (!id)
0028         return NULL;
0029 
0030     for (; id->protocol_id; id++)
0031         if (id->protocol_id == scmi_dev->protocol_id) {
0032             if (!id->name)
0033                 return id;
0034             else if (!strcmp(id->name, scmi_dev->name))
0035                 return id;
0036         }
0037 
0038     return NULL;
0039 }
0040 
0041 static int scmi_dev_match(struct device *dev, struct device_driver *drv)
0042 {
0043     struct scmi_driver *scmi_drv = to_scmi_driver(drv);
0044     struct scmi_device *scmi_dev = to_scmi_dev(dev);
0045     const struct scmi_device_id *id;
0046 
0047     id = scmi_dev_match_id(scmi_dev, scmi_drv);
0048     if (id)
0049         return 1;
0050 
0051     return 0;
0052 }
0053 
0054 static int scmi_match_by_id_table(struct device *dev, void *data)
0055 {
0056     struct scmi_device *sdev = to_scmi_dev(dev);
0057     struct scmi_device_id *id_table = data;
0058 
0059     return sdev->protocol_id == id_table->protocol_id &&
0060         !strcmp(sdev->name, id_table->name);
0061 }
0062 
0063 struct scmi_device *scmi_child_dev_find(struct device *parent,
0064                     int prot_id, const char *name)
0065 {
0066     struct scmi_device_id id_table;
0067     struct device *dev;
0068 
0069     id_table.protocol_id = prot_id;
0070     id_table.name = name;
0071 
0072     dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
0073     if (!dev)
0074         return NULL;
0075 
0076     return to_scmi_dev(dev);
0077 }
0078 
0079 const struct scmi_protocol *scmi_protocol_get(int protocol_id)
0080 {
0081     const struct scmi_protocol *proto;
0082 
0083     proto = idr_find(&scmi_protocols, protocol_id);
0084     if (!proto || !try_module_get(proto->owner)) {
0085         pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id);
0086         return NULL;
0087     }
0088 
0089     pr_debug("Found SCMI Protocol 0x%x\n", protocol_id);
0090 
0091     return proto;
0092 }
0093 
0094 void scmi_protocol_put(int protocol_id)
0095 {
0096     const struct scmi_protocol *proto;
0097 
0098     proto = idr_find(&scmi_protocols, protocol_id);
0099     if (proto)
0100         module_put(proto->owner);
0101 }
0102 
0103 static int scmi_dev_probe(struct device *dev)
0104 {
0105     struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
0106     struct scmi_device *scmi_dev = to_scmi_dev(dev);
0107 
0108     if (!scmi_dev->handle)
0109         return -EPROBE_DEFER;
0110 
0111     return scmi_drv->probe(scmi_dev);
0112 }
0113 
0114 static void scmi_dev_remove(struct device *dev)
0115 {
0116     struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
0117     struct scmi_device *scmi_dev = to_scmi_dev(dev);
0118 
0119     if (scmi_drv->remove)
0120         scmi_drv->remove(scmi_dev);
0121 }
0122 
0123 static struct bus_type scmi_bus_type = {
0124     .name = "scmi_protocol",
0125     .match = scmi_dev_match,
0126     .probe = scmi_dev_probe,
0127     .remove = scmi_dev_remove,
0128 };
0129 
0130 int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
0131              const char *mod_name)
0132 {
0133     int retval;
0134 
0135     if (!driver->probe)
0136         return -EINVAL;
0137 
0138     retval = scmi_protocol_device_request(driver->id_table);
0139     if (retval)
0140         return retval;
0141 
0142     driver->driver.bus = &scmi_bus_type;
0143     driver->driver.name = driver->name;
0144     driver->driver.owner = owner;
0145     driver->driver.mod_name = mod_name;
0146 
0147     retval = driver_register(&driver->driver);
0148     if (!retval)
0149         pr_debug("registered new scmi driver %s\n", driver->name);
0150 
0151     return retval;
0152 }
0153 EXPORT_SYMBOL_GPL(scmi_driver_register);
0154 
0155 void scmi_driver_unregister(struct scmi_driver *driver)
0156 {
0157     driver_unregister(&driver->driver);
0158     scmi_protocol_device_unrequest(driver->id_table);
0159 }
0160 EXPORT_SYMBOL_GPL(scmi_driver_unregister);
0161 
0162 static void scmi_device_release(struct device *dev)
0163 {
0164     kfree(to_scmi_dev(dev));
0165 }
0166 
0167 struct scmi_device *
0168 scmi_device_create(struct device_node *np, struct device *parent, int protocol,
0169            const char *name)
0170 {
0171     int id, retval;
0172     struct scmi_device *scmi_dev;
0173 
0174     scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
0175     if (!scmi_dev)
0176         return NULL;
0177 
0178     scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
0179     if (!scmi_dev->name) {
0180         kfree(scmi_dev);
0181         return NULL;
0182     }
0183 
0184     id = ida_alloc_min(&scmi_bus_id, 1, GFP_KERNEL);
0185     if (id < 0) {
0186         kfree_const(scmi_dev->name);
0187         kfree(scmi_dev);
0188         return NULL;
0189     }
0190 
0191     scmi_dev->id = id;
0192     scmi_dev->protocol_id = protocol;
0193     scmi_dev->dev.parent = parent;
0194     scmi_dev->dev.of_node = np;
0195     scmi_dev->dev.bus = &scmi_bus_type;
0196     scmi_dev->dev.release = scmi_device_release;
0197     dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
0198 
0199     retval = device_register(&scmi_dev->dev);
0200     if (retval)
0201         goto put_dev;
0202 
0203     return scmi_dev;
0204 put_dev:
0205     kfree_const(scmi_dev->name);
0206     put_device(&scmi_dev->dev);
0207     ida_free(&scmi_bus_id, id);
0208     return NULL;
0209 }
0210 
0211 void scmi_device_destroy(struct scmi_device *scmi_dev)
0212 {
0213     kfree_const(scmi_dev->name);
0214     scmi_handle_put(scmi_dev->handle);
0215     ida_free(&scmi_bus_id, scmi_dev->id);
0216     device_unregister(&scmi_dev->dev);
0217 }
0218 
0219 void scmi_set_handle(struct scmi_device *scmi_dev)
0220 {
0221     scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
0222 }
0223 
0224 int scmi_protocol_register(const struct scmi_protocol *proto)
0225 {
0226     int ret;
0227 
0228     if (!proto) {
0229         pr_err("invalid protocol\n");
0230         return -EINVAL;
0231     }
0232 
0233     if (!proto->instance_init) {
0234         pr_err("missing init for protocol 0x%x\n", proto->id);
0235         return -EINVAL;
0236     }
0237 
0238     spin_lock(&protocol_lock);
0239     ret = idr_alloc(&scmi_protocols, (void *)proto,
0240             proto->id, proto->id + 1, GFP_ATOMIC);
0241     spin_unlock(&protocol_lock);
0242     if (ret != proto->id) {
0243         pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n",
0244                proto->id, ret);
0245         return ret;
0246     }
0247 
0248     pr_debug("Registered SCMI Protocol 0x%x\n", proto->id);
0249 
0250     return 0;
0251 }
0252 EXPORT_SYMBOL_GPL(scmi_protocol_register);
0253 
0254 void scmi_protocol_unregister(const struct scmi_protocol *proto)
0255 {
0256     spin_lock(&protocol_lock);
0257     idr_remove(&scmi_protocols, proto->id);
0258     spin_unlock(&protocol_lock);
0259 
0260     pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id);
0261 
0262     return;
0263 }
0264 EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
0265 
0266 static int __scmi_devices_unregister(struct device *dev, void *data)
0267 {
0268     struct scmi_device *scmi_dev = to_scmi_dev(dev);
0269 
0270     scmi_device_destroy(scmi_dev);
0271     return 0;
0272 }
0273 
0274 static void scmi_devices_unregister(void)
0275 {
0276     bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
0277 }
0278 
0279 int __init scmi_bus_init(void)
0280 {
0281     int retval;
0282 
0283     retval = bus_register(&scmi_bus_type);
0284     if (retval)
0285         pr_err("scmi protocol bus register failed (%d)\n", retval);
0286 
0287     return retval;
0288 }
0289 
0290 void __exit scmi_bus_exit(void)
0291 {
0292     scmi_devices_unregister();
0293     bus_unregister(&scmi_bus_type);
0294     ida_destroy(&scmi_bus_id);
0295 }