at v6.19 249 lines 5.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2// Copyright(c) 2015-17 Intel Corporation. 3 4#include <linux/module.h> 5#include <linux/mod_devicetable.h> 6#include <linux/pm_domain.h> 7#include <linux/soundwire/sdw.h> 8#include <linux/soundwire/sdw_type.h> 9#include "bus.h" 10#include "irq.h" 11#include "sysfs_local.h" 12 13/** 14 * sdw_get_device_id - find the matching SoundWire device id 15 * @slave: SoundWire Slave Device 16 * @drv: SoundWire Slave Driver 17 * 18 * The match is done by comparing the mfg_id and part_id from the 19 * struct sdw_device_id. 20 */ 21static const struct sdw_device_id * 22sdw_get_device_id(struct sdw_slave *slave, const struct sdw_driver *drv) 23{ 24 const struct sdw_device_id *id; 25 26 for (id = drv->id_table; id && id->mfg_id; id++) 27 if (slave->id.mfg_id == id->mfg_id && 28 slave->id.part_id == id->part_id && 29 (!id->sdw_version || 30 slave->id.sdw_version == id->sdw_version) && 31 (!id->class_id || 32 slave->id.class_id == id->class_id)) 33 return id; 34 35 return NULL; 36} 37 38static int sdw_bus_match(struct device *dev, const struct device_driver *ddrv) 39{ 40 struct sdw_slave *slave; 41 const struct sdw_driver *drv; 42 int ret = 0; 43 44 if (is_sdw_slave(dev)) { 45 slave = dev_to_sdw_dev(dev); 46 drv = drv_to_sdw_driver(ddrv); 47 48 ret = !!sdw_get_device_id(slave, drv); 49 } 50 return ret; 51} 52 53int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size) 54{ 55 /* modalias is sdw:m<mfg_id>p<part_id>v<version>c<class_id> */ 56 57 return snprintf(buf, size, "sdw:m%04Xp%04Xv%02Xc%02X\n", 58 slave->id.mfg_id, slave->id.part_id, 59 slave->id.sdw_version, slave->id.class_id); 60} 61 62int sdw_slave_uevent(const struct device *dev, struct kobj_uevent_env *env) 63{ 64 const struct sdw_slave *slave = dev_to_sdw_dev(dev); 65 char modalias[32]; 66 67 sdw_slave_modalias(slave, modalias, sizeof(modalias)); 68 69 if (add_uevent_var(env, "MODALIAS=%s", modalias)) 70 return -ENOMEM; 71 72 return 0; 73} 74 75const struct bus_type sdw_bus_type = { 76 .name = "soundwire", 77 .match = sdw_bus_match, 78}; 79EXPORT_SYMBOL_GPL(sdw_bus_type); 80 81static int sdw_drv_probe(struct device *dev) 82{ 83 struct sdw_slave *slave = dev_to_sdw_dev(dev); 84 struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); 85 const struct sdw_device_id *id; 86 int ret; 87 88 /* 89 * fw description is mandatory to bind 90 */ 91 if (!dev->fwnode) 92 return -ENODEV; 93 94 if (!IS_ENABLED(CONFIG_ACPI) && !dev->of_node) 95 return -ENODEV; 96 97 id = sdw_get_device_id(slave, drv); 98 if (!id) 99 return -ENODEV; 100 101 /* 102 * attach to power domain but don't turn on (last arg) 103 */ 104 ret = dev_pm_domain_attach(dev, 0); 105 if (ret) 106 return ret; 107 108 ret = ida_alloc_max(&slave->bus->slave_ida, SDW_FW_MAX_DEVICES - 1, GFP_KERNEL); 109 if (ret < 0) { 110 dev_err(dev, "Failed to allocated ID: %d\n", ret); 111 return ret; 112 } 113 slave->index = ret; 114 115 ret = drv->probe(slave, id); 116 if (ret) { 117 ida_free(&slave->bus->slave_ida, slave->index); 118 return ret; 119 } 120 121 mutex_lock(&slave->sdw_dev_lock); 122 123 /* device is probed so let's read the properties now */ 124 if (drv->ops && drv->ops->read_prop) 125 drv->ops->read_prop(slave); 126 127 if (slave->prop.use_domain_irq) 128 sdw_irq_create_mapping(slave); 129 130 /* init the dynamic sysfs attributes we need */ 131 ret = sdw_slave_sysfs_dpn_init(slave); 132 if (ret < 0) 133 dev_warn(dev, "failed to initialise sysfs: %d\n", ret); 134 135 /* 136 * Check for valid clk_stop_timeout, use DisCo worst case value of 137 * 300ms 138 * 139 * TODO: check the timeouts and driver removal case 140 */ 141 if (slave->prop.clk_stop_timeout == 0) 142 slave->prop.clk_stop_timeout = 300; 143 144 slave->bus->clk_stop_timeout = max_t(u32, slave->bus->clk_stop_timeout, 145 slave->prop.clk_stop_timeout); 146 147 slave->probed = true; 148 149 /* 150 * if the probe happened after the bus was started, notify the codec driver 151 * of the current hardware status to e.g. start the initialization. 152 * Errors are only logged as warnings to avoid failing the probe. 153 */ 154 if (drv->ops && drv->ops->update_status) { 155 ret = drv->ops->update_status(slave, slave->status); 156 if (ret < 0) 157 dev_warn(dev, "failed to update status at probe: %d\n", ret); 158 } 159 160 mutex_unlock(&slave->sdw_dev_lock); 161 162 dev_dbg(dev, "probe complete\n"); 163 164 return 0; 165} 166 167static int sdw_drv_remove(struct device *dev) 168{ 169 struct sdw_slave *slave = dev_to_sdw_dev(dev); 170 struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); 171 int ret = 0; 172 173 mutex_lock(&slave->sdw_dev_lock); 174 175 slave->probed = false; 176 177 mutex_unlock(&slave->sdw_dev_lock); 178 179 if (drv->remove) 180 ret = drv->remove(slave); 181 182 ida_free(&slave->bus->slave_ida, slave->index); 183 184 return ret; 185} 186 187static void sdw_drv_shutdown(struct device *dev) 188{ 189 struct sdw_slave *slave = dev_to_sdw_dev(dev); 190 struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); 191 192 if (drv->shutdown) 193 drv->shutdown(slave); 194} 195 196/** 197 * __sdw_register_driver() - register a SoundWire Slave driver 198 * @drv: driver to register 199 * @owner: owning module/driver 200 * 201 * Return: zero on success, else a negative error code. 202 */ 203int __sdw_register_driver(struct sdw_driver *drv, struct module *owner) 204{ 205 drv->driver.bus = &sdw_bus_type; 206 207 if (!drv->probe) { 208 pr_err("driver %s didn't provide SDW probe routine\n", 209 drv->driver.name); 210 return -EINVAL; 211 } 212 213 drv->driver.owner = owner; 214 drv->driver.probe = sdw_drv_probe; 215 drv->driver.remove = sdw_drv_remove; 216 drv->driver.shutdown = sdw_drv_shutdown; 217 drv->driver.dev_groups = sdw_attr_groups; 218 219 return driver_register(&drv->driver); 220} 221EXPORT_SYMBOL_GPL(__sdw_register_driver); 222 223/** 224 * sdw_unregister_driver() - unregisters the SoundWire Slave driver 225 * @drv: driver to unregister 226 */ 227void sdw_unregister_driver(struct sdw_driver *drv) 228{ 229 driver_unregister(&drv->driver); 230} 231EXPORT_SYMBOL_GPL(sdw_unregister_driver); 232 233static int __init sdw_bus_init(void) 234{ 235 sdw_debugfs_init(); 236 return bus_register(&sdw_bus_type); 237} 238 239static void __exit sdw_bus_exit(void) 240{ 241 sdw_debugfs_exit(); 242 bus_unregister(&sdw_bus_type); 243} 244 245postcore_initcall(sdw_bus_init); 246module_exit(sdw_bus_exit); 247 248MODULE_DESCRIPTION("SoundWire bus"); 249MODULE_LICENSE("GPL v2");