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