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 * sdw_get_device_id - find the matching SoundWire device id
12 * @slave: SoundWire Slave Device
13 * @drv: SoundWire Slave Driver
15 * The match is done by comparing the mfg_id and part_id from the
16 * struct sdw_device_id.
18 static const struct sdw_device_id
*
19 sdw_get_device_id(struct sdw_slave
*slave
, struct sdw_driver
*drv
)
21 const struct sdw_device_id
*id
= drv
->id_table
;
23 while (id
&& id
->mfg_id
) {
24 if (slave
->id
.mfg_id
== id
->mfg_id
&&
25 slave
->id
.part_id
== id
->part_id
)
33 static int sdw_bus_match(struct device
*dev
, struct device_driver
*ddrv
)
35 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
36 struct sdw_driver
*drv
= drv_to_sdw_driver(ddrv
);
38 return !!sdw_get_device_id(slave
, drv
);
41 int sdw_slave_modalias(const struct sdw_slave
*slave
, char *buf
, size_t size
)
43 /* modalias is sdw:m<mfg_id>p<part_id> */
45 return snprintf(buf
, size
, "sdw:m%04Xp%04X\n",
46 slave
->id
.mfg_id
, slave
->id
.part_id
);
49 static int sdw_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
51 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
54 sdw_slave_modalias(slave
, modalias
, sizeof(modalias
));
56 if (add_uevent_var(env
, "MODALIAS=%s", modalias
))
62 struct bus_type sdw_bus_type
= {
64 .match
= sdw_bus_match
,
67 EXPORT_SYMBOL_GPL(sdw_bus_type
);
69 static int sdw_drv_probe(struct device
*dev
)
71 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
72 struct sdw_driver
*drv
= drv_to_sdw_driver(dev
->driver
);
73 const struct sdw_device_id
*id
;
76 id
= sdw_get_device_id(slave
, drv
);
80 slave
->ops
= drv
->ops
;
83 * attach to power domain but don't turn on (last arg)
85 ret
= dev_pm_domain_attach(dev
, false);
86 if (ret
!= -EPROBE_DEFER
) {
87 ret
= drv
->probe(slave
, id
);
89 dev_err(dev
, "Probe of %s failed: %d\n", drv
->name
, ret
);
90 dev_pm_domain_detach(dev
, false);
97 /* device is probed so let's read the properties now */
98 if (slave
->ops
&& slave
->ops
->read_prop
)
99 slave
->ops
->read_prop(slave
);
102 * Check for valid clk_stop_timeout, use DisCo worst case value of
105 * TODO: check the timeouts and driver removal case
107 if (slave
->prop
.clk_stop_timeout
== 0)
108 slave
->prop
.clk_stop_timeout
= 300;
110 slave
->bus
->clk_stop_timeout
= max_t(u32
, slave
->bus
->clk_stop_timeout
,
111 slave
->prop
.clk_stop_timeout
);
116 static int sdw_drv_remove(struct device
*dev
)
118 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
119 struct sdw_driver
*drv
= drv_to_sdw_driver(dev
->driver
);
123 ret
= drv
->remove(slave
);
125 dev_pm_domain_detach(dev
, false);
130 static void sdw_drv_shutdown(struct device
*dev
)
132 struct sdw_slave
*slave
= dev_to_sdw_dev(dev
);
133 struct sdw_driver
*drv
= drv_to_sdw_driver(dev
->driver
);
136 drv
->shutdown(slave
);
140 * __sdw_register_driver() - register a SoundWire Slave driver
141 * @drv: driver to register
142 * @owner: owning module/driver
144 * Return: zero on success, else a negative error code.
146 int __sdw_register_driver(struct sdw_driver
*drv
, struct module
*owner
)
148 drv
->driver
.bus
= &sdw_bus_type
;
151 pr_err("driver %s didn't provide SDW probe routine\n",
156 drv
->driver
.owner
= owner
;
157 drv
->driver
.probe
= sdw_drv_probe
;
160 drv
->driver
.remove
= sdw_drv_remove
;
163 drv
->driver
.shutdown
= sdw_drv_shutdown
;
165 return driver_register(&drv
->driver
);
167 EXPORT_SYMBOL_GPL(__sdw_register_driver
);
170 * sdw_unregister_driver() - unregisters the SoundWire Slave driver
171 * @drv: driver to unregister
173 void sdw_unregister_driver(struct sdw_driver
*drv
)
175 driver_unregister(&drv
->driver
);
177 EXPORT_SYMBOL_GPL(sdw_unregister_driver
);
179 static int __init
sdw_bus_init(void)
181 return bus_register(&sdw_bus_type
);
184 static void __exit
sdw_bus_exit(void)
186 bus_unregister(&sdw_bus_type
);
189 postcore_initcall(sdw_bus_init
);
190 module_exit(sdw_bus_exit
);
192 MODULE_DESCRIPTION("SoundWire bus");
193 MODULE_LICENSE("GPL v2");