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