xref: /linux/sound/soc/sdca/sdca_class.c (revision 84318277d6334c6981ab326d4acc87c6a6ddc9b8)
1*2d877d06SCharles Keepax // SPDX-License-Identifier: GPL-2.0
2*2d877d06SCharles Keepax // Copyright (C) 2025 Cirrus Logic, Inc. and
3*2d877d06SCharles Keepax //                    Cirrus Logic International Semiconductor Ltd.
4*2d877d06SCharles Keepax 
5*2d877d06SCharles Keepax /*
6*2d877d06SCharles Keepax  * The MIPI SDCA specification is available for public downloads at
7*2d877d06SCharles Keepax  * https://www.mipi.org/mipi-sdca-v1-0-download
8*2d877d06SCharles Keepax  */
9*2d877d06SCharles Keepax 
10*2d877d06SCharles Keepax #include <linux/device.h>
11*2d877d06SCharles Keepax #include <linux/err.h>
12*2d877d06SCharles Keepax #include <linux/mod_devicetable.h>
13*2d877d06SCharles Keepax #include <linux/module.h>
14*2d877d06SCharles Keepax #include <linux/pm.h>
15*2d877d06SCharles Keepax #include <linux/pm_runtime.h>
16*2d877d06SCharles Keepax #include <linux/regmap.h>
17*2d877d06SCharles Keepax #include <linux/soundwire/sdw.h>
18*2d877d06SCharles Keepax #include <linux/soundwire/sdw_registers.h>
19*2d877d06SCharles Keepax #include <linux/soundwire/sdw_type.h>
20*2d877d06SCharles Keepax #include <sound/sdca.h>
21*2d877d06SCharles Keepax #include <sound/sdca_function.h>
22*2d877d06SCharles Keepax #include <sound/sdca_interrupts.h>
23*2d877d06SCharles Keepax #include <sound/sdca_regmap.h>
24*2d877d06SCharles Keepax #include "sdca_class.h"
25*2d877d06SCharles Keepax 
26*2d877d06SCharles Keepax #define CLASS_SDW_ATTACH_TIMEOUT_MS	5000
27*2d877d06SCharles Keepax 
28*2d877d06SCharles Keepax static int class_read_prop(struct sdw_slave *sdw)
29*2d877d06SCharles Keepax {
30*2d877d06SCharles Keepax 	struct sdw_slave_prop *prop = &sdw->prop;
31*2d877d06SCharles Keepax 
32*2d877d06SCharles Keepax 	sdw_slave_read_prop(sdw);
33*2d877d06SCharles Keepax 
34*2d877d06SCharles Keepax 	prop->use_domain_irq = true;
35*2d877d06SCharles Keepax 	prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY |
36*2d877d06SCharles Keepax 			      SDW_SCP_INT1_IMPL_DEF;
37*2d877d06SCharles Keepax 
38*2d877d06SCharles Keepax 	return 0;
39*2d877d06SCharles Keepax }
40*2d877d06SCharles Keepax 
41*2d877d06SCharles Keepax static int class_sdw_update_status(struct sdw_slave *sdw, enum sdw_slave_status status)
42*2d877d06SCharles Keepax {
43*2d877d06SCharles Keepax 	struct sdca_class_drv *drv = dev_get_drvdata(&sdw->dev);
44*2d877d06SCharles Keepax 
45*2d877d06SCharles Keepax 	switch (status) {
46*2d877d06SCharles Keepax 	case SDW_SLAVE_ATTACHED:
47*2d877d06SCharles Keepax 		dev_dbg(drv->dev, "device attach\n");
48*2d877d06SCharles Keepax 
49*2d877d06SCharles Keepax 		drv->attached = true;
50*2d877d06SCharles Keepax 
51*2d877d06SCharles Keepax 		complete(&drv->device_attach);
52*2d877d06SCharles Keepax 		break;
53*2d877d06SCharles Keepax 	case SDW_SLAVE_UNATTACHED:
54*2d877d06SCharles Keepax 		dev_dbg(drv->dev, "device detach\n");
55*2d877d06SCharles Keepax 
56*2d877d06SCharles Keepax 		drv->attached = false;
57*2d877d06SCharles Keepax 
58*2d877d06SCharles Keepax 		reinit_completion(&drv->device_attach);
59*2d877d06SCharles Keepax 		break;
60*2d877d06SCharles Keepax 	default:
61*2d877d06SCharles Keepax 		break;
62*2d877d06SCharles Keepax 	}
63*2d877d06SCharles Keepax 
64*2d877d06SCharles Keepax 	return 0;
65*2d877d06SCharles Keepax }
66*2d877d06SCharles Keepax 
67*2d877d06SCharles Keepax static const struct sdw_slave_ops class_sdw_ops = {
68*2d877d06SCharles Keepax 	.read_prop	= class_read_prop,
69*2d877d06SCharles Keepax 	.update_status	= class_sdw_update_status,
70*2d877d06SCharles Keepax };
71*2d877d06SCharles Keepax 
72*2d877d06SCharles Keepax static void class_regmap_lock(void *data)
73*2d877d06SCharles Keepax {
74*2d877d06SCharles Keepax 	struct mutex *lock = data;
75*2d877d06SCharles Keepax 
76*2d877d06SCharles Keepax 	mutex_lock(lock);
77*2d877d06SCharles Keepax }
78*2d877d06SCharles Keepax 
79*2d877d06SCharles Keepax static void class_regmap_unlock(void *data)
80*2d877d06SCharles Keepax {
81*2d877d06SCharles Keepax 	struct mutex *lock = data;
82*2d877d06SCharles Keepax 
83*2d877d06SCharles Keepax 	mutex_unlock(lock);
84*2d877d06SCharles Keepax }
85*2d877d06SCharles Keepax 
86*2d877d06SCharles Keepax static int class_wait_for_attach(struct sdca_class_drv *drv)
87*2d877d06SCharles Keepax {
88*2d877d06SCharles Keepax 	if (!drv->attached) {
89*2d877d06SCharles Keepax 		unsigned long timeout = msecs_to_jiffies(CLASS_SDW_ATTACH_TIMEOUT_MS);
90*2d877d06SCharles Keepax 		unsigned long time;
91*2d877d06SCharles Keepax 
92*2d877d06SCharles Keepax 		time = wait_for_completion_timeout(&drv->device_attach, timeout);
93*2d877d06SCharles Keepax 		if (!time) {
94*2d877d06SCharles Keepax 			dev_err(drv->dev, "timed out waiting for device re-attach\n");
95*2d877d06SCharles Keepax 			return -ETIMEDOUT;
96*2d877d06SCharles Keepax 		}
97*2d877d06SCharles Keepax 	}
98*2d877d06SCharles Keepax 
99*2d877d06SCharles Keepax 	regcache_cache_only(drv->dev_regmap, false);
100*2d877d06SCharles Keepax 
101*2d877d06SCharles Keepax 	return 0;
102*2d877d06SCharles Keepax }
103*2d877d06SCharles Keepax 
104*2d877d06SCharles Keepax static bool class_dev_regmap_volatile(struct device *dev, unsigned int reg)
105*2d877d06SCharles Keepax {
106*2d877d06SCharles Keepax 	switch (reg) {
107*2d877d06SCharles Keepax 	case SDW_SCP_SDCA_INTMASK1 ... SDW_SCP_SDCA_INTMASK4:
108*2d877d06SCharles Keepax 		return false;
109*2d877d06SCharles Keepax 	default:
110*2d877d06SCharles Keepax 		return true;
111*2d877d06SCharles Keepax 	}
112*2d877d06SCharles Keepax }
113*2d877d06SCharles Keepax 
114*2d877d06SCharles Keepax static bool class_dev_regmap_precious(struct device *dev, unsigned int reg)
115*2d877d06SCharles Keepax {
116*2d877d06SCharles Keepax 	switch (reg) {
117*2d877d06SCharles Keepax 	case SDW_SCP_SDCA_INT1 ... SDW_SCP_SDCA_INT4:
118*2d877d06SCharles Keepax 	case SDW_SCP_SDCA_INTMASK1 ... SDW_SCP_SDCA_INTMASK4:
119*2d877d06SCharles Keepax 		return false;
120*2d877d06SCharles Keepax 	default:
121*2d877d06SCharles Keepax 		return true;
122*2d877d06SCharles Keepax 	}
123*2d877d06SCharles Keepax }
124*2d877d06SCharles Keepax 
125*2d877d06SCharles Keepax static const struct regmap_config class_dev_regmap_config = {
126*2d877d06SCharles Keepax 	.name			= "sdca-device",
127*2d877d06SCharles Keepax 	.reg_bits		= 32,
128*2d877d06SCharles Keepax 	.val_bits		= 8,
129*2d877d06SCharles Keepax 
130*2d877d06SCharles Keepax 	.max_register		= SDW_SDCA_MAX_REGISTER,
131*2d877d06SCharles Keepax 	.volatile_reg		= class_dev_regmap_volatile,
132*2d877d06SCharles Keepax 	.precious_reg		= class_dev_regmap_precious,
133*2d877d06SCharles Keepax 
134*2d877d06SCharles Keepax 	.cache_type		= REGCACHE_MAPLE,
135*2d877d06SCharles Keepax 
136*2d877d06SCharles Keepax 	.lock			= class_regmap_lock,
137*2d877d06SCharles Keepax 	.unlock			= class_regmap_unlock,
138*2d877d06SCharles Keepax };
139*2d877d06SCharles Keepax 
140*2d877d06SCharles Keepax static void class_boot_work(struct work_struct *work)
141*2d877d06SCharles Keepax {
142*2d877d06SCharles Keepax 	struct sdca_class_drv *drv = container_of(work,
143*2d877d06SCharles Keepax 						  struct sdca_class_drv,
144*2d877d06SCharles Keepax 						  boot_work);
145*2d877d06SCharles Keepax 	int ret;
146*2d877d06SCharles Keepax 
147*2d877d06SCharles Keepax 	ret = class_wait_for_attach(drv);
148*2d877d06SCharles Keepax 	if (ret)
149*2d877d06SCharles Keepax 		goto err;
150*2d877d06SCharles Keepax 
151*2d877d06SCharles Keepax 	drv->irq_info = sdca_irq_allocate(drv->dev, drv->dev_regmap,
152*2d877d06SCharles Keepax 					  drv->sdw->irq);
153*2d877d06SCharles Keepax 	if (IS_ERR(drv->irq_info))
154*2d877d06SCharles Keepax 		goto err;
155*2d877d06SCharles Keepax 
156*2d877d06SCharles Keepax 	ret = sdca_dev_register_functions(drv->sdw);
157*2d877d06SCharles Keepax 	if (ret)
158*2d877d06SCharles Keepax 		goto err;
159*2d877d06SCharles Keepax 
160*2d877d06SCharles Keepax 	dev_dbg(drv->dev, "boot work complete\n");
161*2d877d06SCharles Keepax 
162*2d877d06SCharles Keepax 	pm_runtime_mark_last_busy(drv->dev);
163*2d877d06SCharles Keepax 	pm_runtime_put_autosuspend(drv->dev);
164*2d877d06SCharles Keepax 
165*2d877d06SCharles Keepax 	return;
166*2d877d06SCharles Keepax 
167*2d877d06SCharles Keepax err:
168*2d877d06SCharles Keepax 	pm_runtime_put_sync(drv->dev);
169*2d877d06SCharles Keepax }
170*2d877d06SCharles Keepax 
171*2d877d06SCharles Keepax static void class_dev_remove(void *data)
172*2d877d06SCharles Keepax {
173*2d877d06SCharles Keepax 	struct sdca_class_drv *drv = data;
174*2d877d06SCharles Keepax 
175*2d877d06SCharles Keepax 	cancel_work_sync(&drv->boot_work);
176*2d877d06SCharles Keepax 
177*2d877d06SCharles Keepax 	sdca_dev_unregister_functions(drv->sdw);
178*2d877d06SCharles Keepax }
179*2d877d06SCharles Keepax 
180*2d877d06SCharles Keepax static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id)
181*2d877d06SCharles Keepax {
182*2d877d06SCharles Keepax 	struct device *dev = &sdw->dev;
183*2d877d06SCharles Keepax 	struct sdca_device_data *data = &sdw->sdca_data;
184*2d877d06SCharles Keepax 	struct regmap_config *dev_config;
185*2d877d06SCharles Keepax 	struct sdca_class_drv *drv;
186*2d877d06SCharles Keepax 	int ret;
187*2d877d06SCharles Keepax 
188*2d877d06SCharles Keepax 	sdca_lookup_swft(sdw);
189*2d877d06SCharles Keepax 
190*2d877d06SCharles Keepax 	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
191*2d877d06SCharles Keepax 	if (!drv)
192*2d877d06SCharles Keepax 		return -ENOMEM;
193*2d877d06SCharles Keepax 
194*2d877d06SCharles Keepax 	dev_config = devm_kmemdup(dev, &class_dev_regmap_config,
195*2d877d06SCharles Keepax 				  sizeof(*dev_config), GFP_KERNEL);
196*2d877d06SCharles Keepax 	if (!dev_config)
197*2d877d06SCharles Keepax 		return -ENOMEM;
198*2d877d06SCharles Keepax 
199*2d877d06SCharles Keepax 	drv->functions = devm_kcalloc(dev, data->num_functions,
200*2d877d06SCharles Keepax 				      sizeof(*drv->functions),
201*2d877d06SCharles Keepax 				      GFP_KERNEL);
202*2d877d06SCharles Keepax 	if (!drv->functions)
203*2d877d06SCharles Keepax 		return -ENOMEM;
204*2d877d06SCharles Keepax 
205*2d877d06SCharles Keepax 	drv->dev = dev;
206*2d877d06SCharles Keepax 	drv->sdw = sdw;
207*2d877d06SCharles Keepax 	mutex_init(&drv->regmap_lock);
208*2d877d06SCharles Keepax 
209*2d877d06SCharles Keepax 	dev_set_drvdata(drv->dev, drv);
210*2d877d06SCharles Keepax 
211*2d877d06SCharles Keepax 	INIT_WORK(&drv->boot_work, class_boot_work);
212*2d877d06SCharles Keepax 	init_completion(&drv->device_attach);
213*2d877d06SCharles Keepax 
214*2d877d06SCharles Keepax 	dev_config->lock_arg = &drv->regmap_lock;
215*2d877d06SCharles Keepax 
216*2d877d06SCharles Keepax 	drv->dev_regmap = devm_regmap_init_sdw(sdw, dev_config);
217*2d877d06SCharles Keepax 	if (IS_ERR(drv->dev_regmap))
218*2d877d06SCharles Keepax 		return dev_err_probe(drv->dev, PTR_ERR(drv->dev_regmap),
219*2d877d06SCharles Keepax 				     "failed to create device regmap\n");
220*2d877d06SCharles Keepax 
221*2d877d06SCharles Keepax 	regcache_cache_only(drv->dev_regmap, true);
222*2d877d06SCharles Keepax 
223*2d877d06SCharles Keepax 	pm_runtime_set_autosuspend_delay(dev, 250);
224*2d877d06SCharles Keepax 	pm_runtime_use_autosuspend(dev);
225*2d877d06SCharles Keepax 	pm_runtime_set_active(dev);
226*2d877d06SCharles Keepax 	pm_runtime_get_noresume(dev);
227*2d877d06SCharles Keepax 
228*2d877d06SCharles Keepax 	ret = devm_pm_runtime_enable(dev);
229*2d877d06SCharles Keepax 	if (ret)
230*2d877d06SCharles Keepax 		return ret;
231*2d877d06SCharles Keepax 
232*2d877d06SCharles Keepax 	ret = devm_add_action_or_reset(dev, class_dev_remove, drv);
233*2d877d06SCharles Keepax 	if (ret)
234*2d877d06SCharles Keepax 		return ret;
235*2d877d06SCharles Keepax 
236*2d877d06SCharles Keepax 	queue_work(system_long_wq, &drv->boot_work);
237*2d877d06SCharles Keepax 
238*2d877d06SCharles Keepax 	return 0;
239*2d877d06SCharles Keepax }
240*2d877d06SCharles Keepax 
241*2d877d06SCharles Keepax static int class_runtime_suspend(struct device *dev)
242*2d877d06SCharles Keepax {
243*2d877d06SCharles Keepax 	struct sdca_class_drv *drv = dev_get_drvdata(dev);
244*2d877d06SCharles Keepax 
245*2d877d06SCharles Keepax 	/*
246*2d877d06SCharles Keepax 	 * Whilst the driver doesn't power the chip down here, going into runtime
247*2d877d06SCharles Keepax 	 * suspend lets the SoundWire bus power down, which means the driver
248*2d877d06SCharles Keepax 	 * can't communicate with the device any more.
249*2d877d06SCharles Keepax 	 */
250*2d877d06SCharles Keepax 	regcache_cache_only(drv->dev_regmap, true);
251*2d877d06SCharles Keepax 
252*2d877d06SCharles Keepax 	return 0;
253*2d877d06SCharles Keepax }
254*2d877d06SCharles Keepax 
255*2d877d06SCharles Keepax static int class_runtime_resume(struct device *dev)
256*2d877d06SCharles Keepax {
257*2d877d06SCharles Keepax 	struct sdca_class_drv *drv = dev_get_drvdata(dev);
258*2d877d06SCharles Keepax 	int ret;
259*2d877d06SCharles Keepax 
260*2d877d06SCharles Keepax 	ret = class_wait_for_attach(drv);
261*2d877d06SCharles Keepax 	if (ret)
262*2d877d06SCharles Keepax 		goto err;
263*2d877d06SCharles Keepax 
264*2d877d06SCharles Keepax 	regcache_mark_dirty(drv->dev_regmap);
265*2d877d06SCharles Keepax 
266*2d877d06SCharles Keepax 	ret = regcache_sync(drv->dev_regmap);
267*2d877d06SCharles Keepax 	if (ret) {
268*2d877d06SCharles Keepax 		dev_err(drv->dev, "failed to restore cache: %d\n", ret);
269*2d877d06SCharles Keepax 		goto err;
270*2d877d06SCharles Keepax 	}
271*2d877d06SCharles Keepax 
272*2d877d06SCharles Keepax 	return 0;
273*2d877d06SCharles Keepax 
274*2d877d06SCharles Keepax err:
275*2d877d06SCharles Keepax 	regcache_cache_only(drv->dev_regmap, true);
276*2d877d06SCharles Keepax 
277*2d877d06SCharles Keepax 	return ret;
278*2d877d06SCharles Keepax }
279*2d877d06SCharles Keepax 
280*2d877d06SCharles Keepax static const struct dev_pm_ops class_pm_ops = {
281*2d877d06SCharles Keepax 	RUNTIME_PM_OPS(class_runtime_suspend, class_runtime_resume, NULL)
282*2d877d06SCharles Keepax };
283*2d877d06SCharles Keepax 
284*2d877d06SCharles Keepax static const struct sdw_device_id class_sdw_id[] = {
285*2d877d06SCharles Keepax 	SDW_SLAVE_ENTRY(0x01FA, 0x4245, 0),
286*2d877d06SCharles Keepax 	{}
287*2d877d06SCharles Keepax };
288*2d877d06SCharles Keepax MODULE_DEVICE_TABLE(sdw, class_sdw_id);
289*2d877d06SCharles Keepax 
290*2d877d06SCharles Keepax static struct sdw_driver class_sdw_driver = {
291*2d877d06SCharles Keepax 	.driver = {
292*2d877d06SCharles Keepax 		.name		= "sdca_class",
293*2d877d06SCharles Keepax 		.pm		= pm_ptr(&class_pm_ops),
294*2d877d06SCharles Keepax 	},
295*2d877d06SCharles Keepax 
296*2d877d06SCharles Keepax 	.probe		= class_sdw_probe,
297*2d877d06SCharles Keepax 	.id_table	= class_sdw_id,
298*2d877d06SCharles Keepax 	.ops		= &class_sdw_ops,
299*2d877d06SCharles Keepax };
300*2d877d06SCharles Keepax module_sdw_driver(class_sdw_driver);
301*2d877d06SCharles Keepax 
302*2d877d06SCharles Keepax MODULE_LICENSE("GPL");
303*2d877d06SCharles Keepax MODULE_DESCRIPTION("SDCA Class Driver");
304*2d877d06SCharles Keepax MODULE_IMPORT_NS("SND_SOC_SDCA");
305