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