]>
git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/soundwire/bus_type.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright(c) 2015-17 Intel Corporation.
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>
11 #include "sysfs_local.h"
14 * sdw_get_device_id - find the matching SoundWire device id
15 * @slave: SoundWire Slave Device
16 * @drv: SoundWire Slave Driver
18 * The match is done by comparing the mfg_id and part_id from the
19 * struct sdw_device_id.
21 static const struct sdw_device_id
*
22 sdw_get_device_id(struct sdw_slave
*slave
, struct sdw_driver
*drv
)
24 const struct sdw_device_id
*id
;
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
&&
30 slave
->id
.sdw_version
== id
->sdw_version
) &&
32 slave
->id
.class_id
== id
->class_id
))
38 static int sdw_bus_match(struct device
*dev
, struct device_driver
*ddrv
)
40 struct sdw_slave
*slave
;
41 struct sdw_driver
*drv
;
44 if (is_sdw_slave(dev
)) {
45 slave
= dev_to_sdw_dev(dev
);
46 drv
= drv_to_sdw_driver(ddrv
);
48 ret
= !!sdw_get_device_id(slave
, drv
);
53 int sdw_slave_modalias(const struct sdw_slave
*slave
, char *buf
, size_t size
)
55 /* modalias is sdw:m<mfg_id>p<part_id>v<version>c<class_id> */
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
);
62 int sdw_slave_uevent(const struct device
*dev
, struct kobj_uevent_env
*env
)
64 const struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
67 sdw_slave_modalias(slave
, modalias
, sizeof(modalias
));
69 if (add_uevent_var(env
, "MODALIAS=%s", modalias
))
75 struct bus_type sdw_bus_type
= {
77 .match
= sdw_bus_match
,
79 EXPORT_SYMBOL_GPL(sdw_bus_type
);
81 static int sdw_drv_probe(struct device
*dev
)
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
;
90 * fw description is mandatory to bind
95 if (!IS_ENABLED(CONFIG_ACPI
) && !dev
->of_node
)
98 id
= sdw_get_device_id(slave
, drv
);
103 * attach to power domain but don't turn on (last arg)
105 ret
= dev_pm_domain_attach(dev
, false);
109 ret
= drv
->probe(slave
, id
);
113 name
= drv
->driver
.name
;
115 dev_err(dev
, "Probe of %s failed: %d\n", name
, ret
);
116 dev_pm_domain_detach(dev
, false);
120 mutex_lock(&slave
->sdw_dev_lock
);
122 /* device is probed so let's read the properties now */
123 if (drv
->ops
&& drv
->ops
->read_prop
)
124 drv
->ops
->read_prop(slave
);
126 if (slave
->prop
.use_domain_irq
)
127 sdw_irq_create_mapping(slave
);
129 /* init the sysfs as we have properties now */
130 ret
= sdw_slave_sysfs_init(slave
);
132 dev_warn(dev
, "Slave sysfs init failed:%d\n", ret
);
135 * Check for valid clk_stop_timeout, use DisCo worst case value of
138 * TODO: check the timeouts and driver removal case
140 if (slave
->prop
.clk_stop_timeout
== 0)
141 slave
->prop
.clk_stop_timeout
= 300;
143 slave
->bus
->clk_stop_timeout
= max_t(u32
, slave
->bus
->clk_stop_timeout
,
144 slave
->prop
.clk_stop_timeout
);
146 slave
->probed
= true;
149 * if the probe happened after the bus was started, notify the codec driver
150 * of the current hardware status to e.g. start the initialization.
151 * Errors are only logged as warnings to avoid failing the probe.
153 if (drv
->ops
&& drv
->ops
->update_status
) {
154 ret
= drv
->ops
->update_status(slave
, slave
->status
);
156 dev_warn(dev
, "%s: update_status failed with status %d\n", __func__
, ret
);
159 mutex_unlock(&slave
->sdw_dev_lock
);
161 dev_dbg(dev
, "probe complete\n");
166 static int sdw_drv_remove(struct device
*dev
)
168 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
169 struct sdw_driver
*drv
= drv_to_sdw_driver(dev
->driver
);
172 mutex_lock(&slave
->sdw_dev_lock
);
174 slave
->probed
= false;
176 if (slave
->prop
.use_domain_irq
)
177 sdw_irq_dispose_mapping(slave
);
179 mutex_unlock(&slave
->sdw_dev_lock
);
182 ret
= drv
->remove(slave
);
184 dev_pm_domain_detach(dev
, false);
189 static void sdw_drv_shutdown(struct device
*dev
)
191 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
192 struct sdw_driver
*drv
= drv_to_sdw_driver(dev
->driver
);
195 drv
->shutdown(slave
);
199 * __sdw_register_driver() - register a SoundWire Slave driver
200 * @drv: driver to register
201 * @owner: owning module/driver
203 * Return: zero on success, else a negative error code.
205 int __sdw_register_driver(struct sdw_driver
*drv
, struct module
*owner
)
209 drv
->driver
.bus
= &sdw_bus_type
;
214 name
= drv
->driver
.name
;
216 pr_err("driver %s didn't provide SDW probe routine\n", name
);
220 drv
->driver
.owner
= owner
;
221 drv
->driver
.probe
= sdw_drv_probe
;
222 drv
->driver
.remove
= sdw_drv_remove
;
223 drv
->driver
.shutdown
= sdw_drv_shutdown
;
225 return driver_register(&drv
->driver
);
227 EXPORT_SYMBOL_GPL(__sdw_register_driver
);
230 * sdw_unregister_driver() - unregisters the SoundWire Slave driver
231 * @drv: driver to unregister
233 void sdw_unregister_driver(struct sdw_driver
*drv
)
235 driver_unregister(&drv
->driver
);
237 EXPORT_SYMBOL_GPL(sdw_unregister_driver
);
239 static int __init
sdw_bus_init(void)
242 return bus_register(&sdw_bus_type
);
245 static void __exit
sdw_bus_exit(void)
248 bus_unregister(&sdw_bus_type
);
251 postcore_initcall(sdw_bus_init
);
252 module_exit(sdw_bus_exit
);
254 MODULE_DESCRIPTION("SoundWire bus");
255 MODULE_LICENSE("GPL v2");