Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright(c) 2015-17 Intel Corporation.
0003 
0004 #include <linux/module.h>
0005 #include <linux/mod_devicetable.h>
0006 #include <linux/pm_domain.h>
0007 #include <linux/soundwire/sdw.h>
0008 #include <linux/soundwire/sdw_type.h>
0009 #include "bus.h"
0010 #include "sysfs_local.h"
0011 
0012 /**
0013  * sdw_get_device_id - find the matching SoundWire device id
0014  * @slave: SoundWire Slave Device
0015  * @drv: SoundWire Slave Driver
0016  *
0017  * The match is done by comparing the mfg_id and part_id from the
0018  * struct sdw_device_id.
0019  */
0020 static const struct sdw_device_id *
0021 sdw_get_device_id(struct sdw_slave *slave, struct sdw_driver *drv)
0022 {
0023     const struct sdw_device_id *id;
0024 
0025     for (id = drv->id_table; id && id->mfg_id; id++)
0026         if (slave->id.mfg_id == id->mfg_id &&
0027             slave->id.part_id == id->part_id  &&
0028             (!id->sdw_version ||
0029              slave->id.sdw_version == id->sdw_version) &&
0030             (!id->class_id ||
0031              slave->id.class_id == id->class_id))
0032             return id;
0033 
0034     return NULL;
0035 }
0036 
0037 static int sdw_bus_match(struct device *dev, struct device_driver *ddrv)
0038 {
0039     struct sdw_slave *slave;
0040     struct sdw_driver *drv;
0041     int ret = 0;
0042 
0043     if (is_sdw_slave(dev)) {
0044         slave = dev_to_sdw_dev(dev);
0045         drv = drv_to_sdw_driver(ddrv);
0046 
0047         ret = !!sdw_get_device_id(slave, drv);
0048     }
0049     return ret;
0050 }
0051 
0052 int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size)
0053 {
0054     /* modalias is sdw:m<mfg_id>p<part_id>v<version>c<class_id> */
0055 
0056     return snprintf(buf, size, "sdw:m%04Xp%04Xv%02Xc%02X\n",
0057             slave->id.mfg_id, slave->id.part_id,
0058             slave->id.sdw_version, slave->id.class_id);
0059 }
0060 
0061 int sdw_slave_uevent(struct device *dev, struct kobj_uevent_env *env)
0062 {
0063     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0064     char modalias[32];
0065 
0066     sdw_slave_modalias(slave, modalias, sizeof(modalias));
0067 
0068     if (add_uevent_var(env, "MODALIAS=%s", modalias))
0069         return -ENOMEM;
0070 
0071     return 0;
0072 }
0073 
0074 struct bus_type sdw_bus_type = {
0075     .name = "soundwire",
0076     .match = sdw_bus_match,
0077 };
0078 EXPORT_SYMBOL_GPL(sdw_bus_type);
0079 
0080 static int sdw_drv_probe(struct device *dev)
0081 {
0082     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0083     struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
0084     const struct sdw_device_id *id;
0085     const char *name;
0086     int ret;
0087 
0088     /*
0089      * fw description is mandatory to bind
0090      */
0091     if (!dev->fwnode)
0092         return -ENODEV;
0093 
0094     if (!IS_ENABLED(CONFIG_ACPI) && !dev->of_node)
0095         return -ENODEV;
0096 
0097     id = sdw_get_device_id(slave, drv);
0098     if (!id)
0099         return -ENODEV;
0100 
0101     /*
0102      * attach to power domain but don't turn on (last arg)
0103      */
0104     ret = dev_pm_domain_attach(dev, false);
0105     if (ret)
0106         return ret;
0107 
0108     mutex_lock(&slave->sdw_dev_lock);
0109 
0110     ret = drv->probe(slave, id);
0111     if (ret) {
0112         name = drv->name;
0113         if (!name)
0114             name = drv->driver.name;
0115         mutex_unlock(&slave->sdw_dev_lock);
0116 
0117         dev_err(dev, "Probe of %s failed: %d\n", name, ret);
0118         dev_pm_domain_detach(dev, false);
0119         return ret;
0120     }
0121 
0122     /* device is probed so let's read the properties now */
0123     if (drv->ops && drv->ops->read_prop)
0124         drv->ops->read_prop(slave);
0125 
0126     /* init the sysfs as we have properties now */
0127     ret = sdw_slave_sysfs_init(slave);
0128     if (ret < 0)
0129         dev_warn(dev, "Slave sysfs init failed:%d\n", ret);
0130 
0131     /*
0132      * Check for valid clk_stop_timeout, use DisCo worst case value of
0133      * 300ms
0134      *
0135      * TODO: check the timeouts and driver removal case
0136      */
0137     if (slave->prop.clk_stop_timeout == 0)
0138         slave->prop.clk_stop_timeout = 300;
0139 
0140     slave->bus->clk_stop_timeout = max_t(u32, slave->bus->clk_stop_timeout,
0141                          slave->prop.clk_stop_timeout);
0142 
0143     slave->probed = true;
0144 
0145     /*
0146      * if the probe happened after the bus was started, notify the codec driver
0147      * of the current hardware status to e.g. start the initialization.
0148      * Errors are only logged as warnings to avoid failing the probe.
0149      */
0150     if (drv->ops && drv->ops->update_status) {
0151         ret = drv->ops->update_status(slave, slave->status);
0152         if (ret < 0)
0153             dev_warn(dev, "%s: update_status failed with status %d\n", __func__, ret);
0154     }
0155 
0156     mutex_unlock(&slave->sdw_dev_lock);
0157 
0158     dev_dbg(dev, "probe complete\n");
0159 
0160     return 0;
0161 }
0162 
0163 static int sdw_drv_remove(struct device *dev)
0164 {
0165     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0166     struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
0167     int ret = 0;
0168 
0169     mutex_lock(&slave->sdw_dev_lock);
0170 
0171     slave->probed = false;
0172 
0173     if (drv->remove)
0174         ret = drv->remove(slave);
0175 
0176     mutex_unlock(&slave->sdw_dev_lock);
0177 
0178     dev_pm_domain_detach(dev, false);
0179 
0180     return ret;
0181 }
0182 
0183 static void sdw_drv_shutdown(struct device *dev)
0184 {
0185     struct sdw_slave *slave = dev_to_sdw_dev(dev);
0186     struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
0187 
0188     if (drv->shutdown)
0189         drv->shutdown(slave);
0190 }
0191 
0192 /**
0193  * __sdw_register_driver() - register a SoundWire Slave driver
0194  * @drv: driver to register
0195  * @owner: owning module/driver
0196  *
0197  * Return: zero on success, else a negative error code.
0198  */
0199 int __sdw_register_driver(struct sdw_driver *drv, struct module *owner)
0200 {
0201     const char *name;
0202 
0203     drv->driver.bus = &sdw_bus_type;
0204 
0205     if (!drv->probe) {
0206         name = drv->name;
0207         if (!name)
0208             name = drv->driver.name;
0209 
0210         pr_err("driver %s didn't provide SDW probe routine\n", name);
0211         return -EINVAL;
0212     }
0213 
0214     drv->driver.owner = owner;
0215     drv->driver.probe = sdw_drv_probe;
0216     drv->driver.remove = sdw_drv_remove;
0217     drv->driver.shutdown = sdw_drv_shutdown;
0218 
0219     return driver_register(&drv->driver);
0220 }
0221 EXPORT_SYMBOL_GPL(__sdw_register_driver);
0222 
0223 /**
0224  * sdw_unregister_driver() - unregisters the SoundWire Slave driver
0225  * @drv: driver to unregister
0226  */
0227 void sdw_unregister_driver(struct sdw_driver *drv)
0228 {
0229     driver_unregister(&drv->driver);
0230 }
0231 EXPORT_SYMBOL_GPL(sdw_unregister_driver);
0232 
0233 static int __init sdw_bus_init(void)
0234 {
0235     sdw_debugfs_init();
0236     return bus_register(&sdw_bus_type);
0237 }
0238 
0239 static void __exit sdw_bus_exit(void)
0240 {
0241     sdw_debugfs_exit();
0242     bus_unregister(&sdw_bus_type);
0243 }
0244 
0245 postcore_initcall(sdw_bus_init);
0246 module_exit(sdw_bus_exit);
0247 
0248 MODULE_DESCRIPTION("SoundWire bus");
0249 MODULE_LICENSE("GPL v2");