1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * CS40L50 Advanced Haptic Driver with waveform memory, 4 * integrated DSP, and closed-loop algorithms 5 * 6 * Copyright 2024 Cirrus Logic, Inc. 7 * 8 * Author: James Ogletree <james.ogletree@cirrus.com> 9 */ 10 11 #include <linux/firmware/cirrus/cs_dsp.h> 12 #include <linux/firmware/cirrus/wmfw.h> 13 #include <linux/mfd/core.h> 14 #include <linux/mfd/cs40l50.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/regulator/consumer.h> 17 18 static const struct mfd_cell cs40l50_devs[] = { 19 { .name = "cs40l50-codec", }, 20 { .name = "cs40l50-vibra", }, 21 }; 22 23 const struct regmap_config cs40l50_regmap = { 24 .reg_bits = 32, 25 .reg_stride = 4, 26 .val_bits = 32, 27 .reg_format_endian = REGMAP_ENDIAN_BIG, 28 .val_format_endian = REGMAP_ENDIAN_BIG, 29 }; 30 EXPORT_SYMBOL_GPL(cs40l50_regmap); 31 32 static const char * const cs40l50_supplies[] = { 33 "vdd-io", 34 }; 35 36 static const struct regmap_irq cs40l50_reg_irqs[] = { 37 REGMAP_IRQ_REG(CS40L50_DSP_QUEUE_IRQ, CS40L50_IRQ1_INT_2_OFFSET, 38 CS40L50_DSP_QUEUE_MASK), 39 REGMAP_IRQ_REG(CS40L50_AMP_SHORT_IRQ, CS40L50_IRQ1_INT_1_OFFSET, 40 CS40L50_AMP_SHORT_MASK), 41 REGMAP_IRQ_REG(CS40L50_TEMP_ERR_IRQ, CS40L50_IRQ1_INT_8_OFFSET, 42 CS40L50_TEMP_ERR_MASK), 43 REGMAP_IRQ_REG(CS40L50_BST_UVP_IRQ, CS40L50_IRQ1_INT_9_OFFSET, 44 CS40L50_BST_UVP_MASK), 45 REGMAP_IRQ_REG(CS40L50_BST_SHORT_IRQ, CS40L50_IRQ1_INT_9_OFFSET, 46 CS40L50_BST_SHORT_MASK), 47 REGMAP_IRQ_REG(CS40L50_BST_ILIMIT_IRQ, CS40L50_IRQ1_INT_9_OFFSET, 48 CS40L50_BST_ILIMIT_MASK), 49 REGMAP_IRQ_REG(CS40L50_UVLO_VDDBATT_IRQ, CS40L50_IRQ1_INT_10_OFFSET, 50 CS40L50_UVLO_VDDBATT_MASK), 51 REGMAP_IRQ_REG(CS40L50_GLOBAL_ERROR_IRQ, CS40L50_IRQ1_INT_18_OFFSET, 52 CS40L50_GLOBAL_ERROR_MASK), 53 }; 54 55 static struct regmap_irq_chip cs40l50_irq_chip = { 56 .name = "cs40l50", 57 .status_base = CS40L50_IRQ1_INT_1, 58 .mask_base = CS40L50_IRQ1_MASK_1, 59 .ack_base = CS40L50_IRQ1_INT_1, 60 .num_regs = 22, 61 .irqs = cs40l50_reg_irqs, 62 .num_irqs = ARRAY_SIZE(cs40l50_reg_irqs), 63 .runtime_pm = true, 64 }; 65 66 int cs40l50_dsp_write(struct device *dev, struct regmap *regmap, u32 val) 67 { 68 int i, ret; 69 u32 ack; 70 71 /* Device NAKs if hibernating, so optionally retry */ 72 for (i = 0; i < CS40L50_DSP_TIMEOUT_COUNT; i++) { 73 ret = regmap_write(regmap, CS40L50_DSP_QUEUE, val); 74 if (!ret) 75 break; 76 77 usleep_range(CS40L50_DSP_POLL_US, CS40L50_DSP_POLL_US + 100); 78 } 79 80 /* If the write never took place, no need to check for the ACK */ 81 if (i == CS40L50_DSP_TIMEOUT_COUNT) { 82 dev_err(dev, "Timed out writing %#X to DSP: %d\n", val, ret); 83 return ret; 84 } 85 86 ret = regmap_read_poll_timeout(regmap, CS40L50_DSP_QUEUE, ack, !ack, 87 CS40L50_DSP_POLL_US, 88 CS40L50_DSP_POLL_US * CS40L50_DSP_TIMEOUT_COUNT); 89 if (ret) 90 dev_err(dev, "DSP failed to ACK %#X: %d\n", val, ret); 91 92 return ret; 93 } 94 EXPORT_SYMBOL_GPL(cs40l50_dsp_write); 95 96 static const struct cs_dsp_region cs40l50_dsp_regions[] = { 97 { .type = WMFW_HALO_PM_PACKED, .base = CS40L50_PMEM_0 }, 98 { .type = WMFW_HALO_XM_PACKED, .base = CS40L50_XMEM_PACKED_0 }, 99 { .type = WMFW_HALO_YM_PACKED, .base = CS40L50_YMEM_PACKED_0 }, 100 { .type = WMFW_ADSP2_XM, .base = CS40L50_XMEM_UNPACKED24_0 }, 101 { .type = WMFW_ADSP2_YM, .base = CS40L50_YMEM_UNPACKED24_0 }, 102 }; 103 104 static const struct reg_sequence cs40l50_internal_vamp_config[] = { 105 { CS40L50_BST_LPMODE_SEL, CS40L50_DCM_LOW_POWER }, 106 { CS40L50_BLOCK_ENABLES2, CS40L50_OVERTEMP_WARN }, 107 }; 108 109 static const struct reg_sequence cs40l50_irq_mask_override[] = { 110 { CS40L50_IRQ1_MASK_2, CS40L50_IRQ_MASK_2_OVERRIDE }, 111 { CS40L50_IRQ1_MASK_20, CS40L50_IRQ_MASK_20_OVERRIDE }, 112 }; 113 114 static int cs40l50_wseq_init(struct cs40l50 *cs40l50) 115 { 116 struct cs_dsp *dsp = &cs40l50->dsp; 117 118 cs40l50->wseqs[CS40L50_STANDBY].ctl = cs_dsp_get_ctl(dsp, "STANDBY_SEQUENCE", 119 WMFW_ADSP2_XM, 120 CS40L50_PM_ALGO); 121 if (!cs40l50->wseqs[CS40L50_STANDBY].ctl) { 122 dev_err(cs40l50->dev, "Control not found for standby sequence\n"); 123 return -ENOENT; 124 } 125 126 cs40l50->wseqs[CS40L50_ACTIVE].ctl = cs_dsp_get_ctl(dsp, "ACTIVE_SEQUENCE", 127 WMFW_ADSP2_XM, 128 CS40L50_PM_ALGO); 129 if (!cs40l50->wseqs[CS40L50_ACTIVE].ctl) { 130 dev_err(cs40l50->dev, "Control not found for active sequence\n"); 131 return -ENOENT; 132 } 133 134 cs40l50->wseqs[CS40L50_PWR_ON].ctl = cs_dsp_get_ctl(dsp, "PM_PWR_ON_SEQ", 135 WMFW_ADSP2_XM, 136 CS40L50_PM_ALGO); 137 if (!cs40l50->wseqs[CS40L50_PWR_ON].ctl) { 138 dev_err(cs40l50->dev, "Control not found for power-on sequence\n"); 139 return -ENOENT; 140 } 141 142 return cs_dsp_wseq_init(&cs40l50->dsp, cs40l50->wseqs, ARRAY_SIZE(cs40l50->wseqs)); 143 } 144 145 static int cs40l50_dsp_config(struct cs40l50 *cs40l50) 146 { 147 int ret; 148 149 /* Configure internal V_AMP supply */ 150 ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_internal_vamp_config, 151 ARRAY_SIZE(cs40l50_internal_vamp_config)); 152 if (ret) 153 return ret; 154 155 ret = cs_dsp_wseq_multi_write(&cs40l50->dsp, &cs40l50->wseqs[CS40L50_PWR_ON], 156 cs40l50_internal_vamp_config, CS_DSP_WSEQ_FULL, 157 ARRAY_SIZE(cs40l50_internal_vamp_config), false); 158 if (ret) 159 return ret; 160 161 /* Override firmware defaults for IRQ masks */ 162 ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_irq_mask_override, 163 ARRAY_SIZE(cs40l50_irq_mask_override)); 164 if (ret) 165 return ret; 166 167 return cs_dsp_wseq_multi_write(&cs40l50->dsp, &cs40l50->wseqs[CS40L50_PWR_ON], 168 cs40l50_irq_mask_override, CS_DSP_WSEQ_FULL, 169 ARRAY_SIZE(cs40l50_irq_mask_override), false); 170 } 171 172 static int cs40l50_dsp_post_run(struct cs_dsp *dsp) 173 { 174 struct cs40l50 *cs40l50 = container_of(dsp, struct cs40l50, dsp); 175 int ret; 176 177 ret = cs40l50_wseq_init(cs40l50); 178 if (ret) 179 return ret; 180 181 ret = cs40l50_dsp_config(cs40l50); 182 if (ret) { 183 dev_err(cs40l50->dev, "Failed to configure DSP: %d\n", ret); 184 return ret; 185 } 186 187 ret = devm_mfd_add_devices(cs40l50->dev, PLATFORM_DEVID_NONE, cs40l50_devs, 188 ARRAY_SIZE(cs40l50_devs), NULL, 0, NULL); 189 if (ret) 190 dev_err(cs40l50->dev, "Failed to add child devices: %d\n", ret); 191 192 return ret; 193 } 194 195 static const struct cs_dsp_client_ops client_ops = { 196 .post_run = cs40l50_dsp_post_run, 197 }; 198 199 static void cs40l50_dsp_remove(void *data) 200 { 201 cs_dsp_remove(data); 202 } 203 204 static int cs40l50_dsp_init(struct cs40l50 *cs40l50) 205 { 206 int ret; 207 208 cs40l50->dsp.num = 1; 209 cs40l50->dsp.type = WMFW_HALO; 210 cs40l50->dsp.dev = cs40l50->dev; 211 cs40l50->dsp.regmap = cs40l50->regmap; 212 cs40l50->dsp.base = CS40L50_CORE_BASE; 213 cs40l50->dsp.base_sysinfo = CS40L50_SYS_INFO_ID; 214 cs40l50->dsp.mem = cs40l50_dsp_regions; 215 cs40l50->dsp.num_mems = ARRAY_SIZE(cs40l50_dsp_regions); 216 cs40l50->dsp.no_core_startstop = true; 217 cs40l50->dsp.client_ops = &client_ops; 218 219 ret = cs_dsp_halo_init(&cs40l50->dsp); 220 if (ret) 221 return ret; 222 223 return devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_remove, 224 &cs40l50->dsp); 225 } 226 227 static int cs40l50_reset_dsp(struct cs40l50 *cs40l50) 228 { 229 int ret; 230 231 mutex_lock(&cs40l50->lock); 232 233 if (cs40l50->dsp.running) 234 cs_dsp_stop(&cs40l50->dsp); 235 236 if (cs40l50->dsp.booted) 237 cs_dsp_power_down(&cs40l50->dsp); 238 239 ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_SHUTDOWN); 240 if (ret) 241 goto err_mutex; 242 243 ret = cs_dsp_power_up(&cs40l50->dsp, cs40l50->fw, "cs40l50.wmfw", 244 cs40l50->bin, "cs40l50.bin", "cs40l50"); 245 if (ret) 246 goto err_mutex; 247 248 ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_SYSTEM_RESET); 249 if (ret) 250 goto err_mutex; 251 252 ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_PREVENT_HIBER); 253 if (ret) 254 goto err_mutex; 255 256 ret = cs_dsp_run(&cs40l50->dsp); 257 err_mutex: 258 mutex_unlock(&cs40l50->lock); 259 260 return ret; 261 } 262 263 static void cs40l50_dsp_power_down(void *data) 264 { 265 cs_dsp_power_down(data); 266 } 267 268 static void cs40l50_dsp_stop(void *data) 269 { 270 cs_dsp_stop(data); 271 } 272 273 static void cs40l50_dsp_bringup(const struct firmware *bin, void *context) 274 { 275 struct cs40l50 *cs40l50 = context; 276 u32 nwaves; 277 int ret; 278 279 /* Wavetable is optional; bringup DSP regardless */ 280 cs40l50->bin = bin; 281 282 ret = cs40l50_reset_dsp(cs40l50); 283 if (ret) { 284 dev_err(cs40l50->dev, "Failed to reset DSP: %d\n", ret); 285 goto err_fw; 286 } 287 288 ret = regmap_read(cs40l50->regmap, CS40L50_NUM_WAVES, &nwaves); 289 if (ret) 290 goto err_fw; 291 292 dev_info(cs40l50->dev, "%u RAM effects loaded\n", nwaves); 293 294 /* Add teardown actions for first-time bringup */ 295 ret = devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_power_down, 296 &cs40l50->dsp); 297 if (ret) { 298 dev_err(cs40l50->dev, "Failed to add power down action: %d\n", ret); 299 goto err_fw; 300 } 301 302 ret = devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_stop, &cs40l50->dsp); 303 if (ret) 304 dev_err(cs40l50->dev, "Failed to add stop action: %d\n", ret); 305 err_fw: 306 release_firmware(cs40l50->bin); 307 release_firmware(cs40l50->fw); 308 } 309 310 static void cs40l50_request_firmware(const struct firmware *fw, void *context) 311 { 312 struct cs40l50 *cs40l50 = context; 313 int ret; 314 315 if (!fw) { 316 dev_err(cs40l50->dev, "No firmware file found\n"); 317 return; 318 } 319 320 cs40l50->fw = fw; 321 322 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, CS40L50_WT, 323 cs40l50->dev, GFP_KERNEL, cs40l50, 324 cs40l50_dsp_bringup); 325 if (ret) { 326 dev_err(cs40l50->dev, "Failed to request %s: %d\n", CS40L50_WT, ret); 327 release_firmware(cs40l50->fw); 328 } 329 } 330 331 struct cs40l50_irq { 332 const char *name; 333 int virq; 334 }; 335 336 static struct cs40l50_irq cs40l50_irqs[] = { 337 { "DSP", }, 338 { "Global", }, 339 { "Boost UVLO", }, 340 { "Boost current limit", }, 341 { "Boost short", }, 342 { "Boost undervolt", }, 343 { "Overtemp", }, 344 { "Amp short", }, 345 }; 346 347 static const struct reg_sequence cs40l50_err_rls[] = { 348 { CS40L50_ERR_RLS, CS40L50_GLOBAL_ERR_RLS_SET }, 349 { CS40L50_ERR_RLS, CS40L50_GLOBAL_ERR_RLS_CLEAR }, 350 }; 351 352 static irqreturn_t cs40l50_hw_err(int irq, void *data) 353 { 354 struct cs40l50 *cs40l50 = data; 355 int ret = 0, i; 356 357 mutex_lock(&cs40l50->lock); 358 359 /* Log hardware interrupt and execute error release sequence */ 360 for (i = 1; i < ARRAY_SIZE(cs40l50_irqs); i++) { 361 if (cs40l50_irqs[i].virq == irq) { 362 dev_err(cs40l50->dev, "%s error\n", cs40l50_irqs[i].name); 363 ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_err_rls, 364 ARRAY_SIZE(cs40l50_err_rls)); 365 break; 366 } 367 } 368 369 mutex_unlock(&cs40l50->lock); 370 return IRQ_RETVAL(!ret); 371 } 372 373 static irqreturn_t cs40l50_dsp_queue(int irq, void *data) 374 { 375 struct cs40l50 *cs40l50 = data; 376 u32 rd_ptr, val, wt_ptr; 377 int ret = 0; 378 379 mutex_lock(&cs40l50->lock); 380 381 /* Read from DSP queue, log, and update read pointer */ 382 while (!ret) { 383 ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_WT, &wt_ptr); 384 if (ret) 385 break; 386 387 ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, &rd_ptr); 388 if (ret) 389 break; 390 391 /* Check if queue is empty */ 392 if (wt_ptr == rd_ptr) 393 break; 394 395 ret = regmap_read(cs40l50->regmap, rd_ptr, &val); 396 if (ret) 397 break; 398 399 dev_dbg(cs40l50->dev, "DSP payload: %#X", val); 400 401 rd_ptr += sizeof(u32); 402 403 if (rd_ptr > CS40L50_DSP_QUEUE_END) 404 rd_ptr = CS40L50_DSP_QUEUE_BASE; 405 406 ret = regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, rd_ptr); 407 } 408 409 mutex_unlock(&cs40l50->lock); 410 411 return IRQ_RETVAL(!ret); 412 } 413 414 static int cs40l50_irq_init(struct cs40l50 *cs40l50) 415 { 416 int ret, i, virq; 417 418 ret = devm_regmap_add_irq_chip(cs40l50->dev, cs40l50->regmap, cs40l50->irq, 419 IRQF_ONESHOT | IRQF_SHARED, 0, 420 &cs40l50_irq_chip, &cs40l50->irq_data); 421 if (ret) { 422 dev_err(cs40l50->dev, "Failed adding IRQ chip\n"); 423 return ret; 424 } 425 426 for (i = 0; i < ARRAY_SIZE(cs40l50_irqs); i++) { 427 virq = regmap_irq_get_virq(cs40l50->irq_data, i); 428 if (virq < 0) { 429 dev_err(cs40l50->dev, "Failed getting virq for %s\n", 430 cs40l50_irqs[i].name); 431 return virq; 432 } 433 434 cs40l50_irqs[i].virq = virq; 435 436 /* Handle DSP and hardware interrupts separately */ 437 ret = devm_request_threaded_irq(cs40l50->dev, virq, NULL, 438 i ? cs40l50_hw_err : cs40l50_dsp_queue, 439 IRQF_ONESHOT | IRQF_SHARED, 440 cs40l50_irqs[i].name, cs40l50); 441 if (ret) { 442 return dev_err_probe(cs40l50->dev, ret, 443 "Failed requesting %s IRQ\n", 444 cs40l50_irqs[i].name); 445 } 446 } 447 448 return 0; 449 } 450 451 static int cs40l50_get_model(struct cs40l50 *cs40l50) 452 { 453 int ret; 454 455 ret = regmap_read(cs40l50->regmap, CS40L50_DEVID, &cs40l50->devid); 456 if (ret) 457 return ret; 458 459 if (cs40l50->devid != CS40L50_DEVID_A) 460 return -EINVAL; 461 462 ret = regmap_read(cs40l50->regmap, CS40L50_REVID, &cs40l50->revid); 463 if (ret) 464 return ret; 465 466 if (cs40l50->revid < CS40L50_REVID_B0) 467 return -EINVAL; 468 469 dev_dbg(cs40l50->dev, "Cirrus Logic CS40L50 rev. %02X\n", cs40l50->revid); 470 471 return 0; 472 } 473 474 static int cs40l50_pm_runtime_setup(struct device *dev) 475 { 476 int ret; 477 478 pm_runtime_set_autosuspend_delay(dev, CS40L50_AUTOSUSPEND_MS); 479 pm_runtime_use_autosuspend(dev); 480 pm_runtime_get_noresume(dev); 481 ret = pm_runtime_set_active(dev); 482 if (ret) 483 return ret; 484 485 return devm_pm_runtime_enable(dev); 486 } 487 488 int cs40l50_probe(struct cs40l50 *cs40l50) 489 { 490 struct device *dev = cs40l50->dev; 491 int ret; 492 493 mutex_init(&cs40l50->lock); 494 495 cs40l50->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 496 if (IS_ERR(cs40l50->reset_gpio)) 497 return dev_err_probe(dev, PTR_ERR(cs40l50->reset_gpio), 498 "Failed getting reset GPIO\n"); 499 500 ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(cs40l50_supplies), 501 cs40l50_supplies); 502 if (ret) 503 return dev_err_probe(dev, ret, "Failed getting supplies\n"); 504 505 /* Ensure minimum reset pulse width */ 506 usleep_range(CS40L50_RESET_PULSE_US, CS40L50_RESET_PULSE_US + 100); 507 508 gpiod_set_value_cansleep(cs40l50->reset_gpio, 0); 509 510 /* Wait for control port to be ready */ 511 usleep_range(CS40L50_CP_READY_US, CS40L50_CP_READY_US + 100); 512 513 ret = cs40l50_get_model(cs40l50); 514 if (ret) 515 return dev_err_probe(dev, ret, "Failed to get part number\n"); 516 517 ret = cs40l50_dsp_init(cs40l50); 518 if (ret) 519 return dev_err_probe(dev, ret, "Failed to initialize DSP\n"); 520 521 ret = cs40l50_pm_runtime_setup(dev); 522 if (ret) 523 return dev_err_probe(dev, ret, "Failed to initialize runtime PM\n"); 524 525 ret = cs40l50_irq_init(cs40l50); 526 if (ret) 527 return ret; 528 529 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, CS40L50_FW, 530 dev, GFP_KERNEL, cs40l50, cs40l50_request_firmware); 531 if (ret) 532 return dev_err_probe(dev, ret, "Failed to request %s\n", CS40L50_FW); 533 534 pm_runtime_mark_last_busy(dev); 535 pm_runtime_put_autosuspend(dev); 536 537 return 0; 538 } 539 EXPORT_SYMBOL_GPL(cs40l50_probe); 540 541 int cs40l50_remove(struct cs40l50 *cs40l50) 542 { 543 gpiod_set_value_cansleep(cs40l50->reset_gpio, 1); 544 545 return 0; 546 } 547 EXPORT_SYMBOL_GPL(cs40l50_remove); 548 549 static int cs40l50_runtime_suspend(struct device *dev) 550 { 551 struct cs40l50 *cs40l50 = dev_get_drvdata(dev); 552 553 return regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE, CS40L50_ALLOW_HIBER); 554 } 555 556 static int cs40l50_runtime_resume(struct device *dev) 557 { 558 struct cs40l50 *cs40l50 = dev_get_drvdata(dev); 559 560 return cs40l50_dsp_write(dev, cs40l50->regmap, CS40L50_PREVENT_HIBER); 561 } 562 563 EXPORT_GPL_DEV_PM_OPS(cs40l50_pm_ops) = { 564 RUNTIME_PM_OPS(cs40l50_runtime_suspend, cs40l50_runtime_resume, NULL) 565 }; 566 567 MODULE_DESCRIPTION("CS40L50 Advanced Haptic Driver"); 568 MODULE_AUTHOR("James Ogletree, Cirrus Logic Inc. <james.ogletree@cirrus.com>"); 569 MODULE_LICENSE("GPL"); 570 MODULE_IMPORT_NS(FW_CS_DSP); 571