1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Core MFD support for Cirrus Logic Madera codecs 4 * 5 * Copyright (C) 2015-2018 Cirrus Logic 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; version 2. 10 */ 11 12 #include <linux/device.h> 13 #include <linux/delay.h> 14 #include <linux/err.h> 15 #include <linux/gpio.h> 16 #include <linux/mfd/core.h> 17 #include <linux/module.h> 18 #include <linux/mutex.h> 19 #include <linux/notifier.h> 20 #include <linux/of.h> 21 #include <linux/of_gpio.h> 22 #include <linux/platform_device.h> 23 #include <linux/pm_runtime.h> 24 #include <linux/regmap.h> 25 #include <linux/regulator/consumer.h> 26 #include <linux/regulator/machine.h> 27 #include <linux/regulator/of_regulator.h> 28 29 #include <linux/mfd/madera/core.h> 30 #include <linux/mfd/madera/registers.h> 31 32 #include "madera.h" 33 34 #define CS47L35_SILICON_ID 0x6360 35 #define CS47L85_SILICON_ID 0x6338 36 #define CS47L90_SILICON_ID 0x6364 37 38 #define MADERA_32KZ_MCLK2 1 39 40 static const char * const madera_core_supplies[] = { 41 "AVDD", 42 "DBVDD1", 43 }; 44 45 static const struct mfd_cell madera_ldo1_devs[] = { 46 { .name = "madera-ldo1" }, 47 }; 48 49 static const char * const cs47l35_supplies[] = { 50 "MICVDD", 51 "DBVDD2", 52 "CPVDD1", 53 "CPVDD2", 54 "SPKVDD", 55 }; 56 57 static const struct mfd_cell cs47l35_devs[] = { 58 { .name = "madera-pinctrl", }, 59 { .name = "madera-irq", }, 60 { .name = "madera-micsupp", }, 61 { .name = "madera-gpio", }, 62 { .name = "madera-extcon", }, 63 { 64 .name = "cs47l35-codec", 65 .parent_supplies = cs47l35_supplies, 66 .num_parent_supplies = ARRAY_SIZE(cs47l35_supplies), 67 }, 68 }; 69 70 static const char * const cs47l85_supplies[] = { 71 "MICVDD", 72 "DBVDD2", 73 "DBVDD3", 74 "DBVDD4", 75 "CPVDD1", 76 "CPVDD2", 77 "SPKVDDL", 78 "SPKVDDR", 79 }; 80 81 static const struct mfd_cell cs47l85_devs[] = { 82 { .name = "madera-pinctrl", }, 83 { .name = "madera-irq", }, 84 { .name = "madera-micsupp" }, 85 { .name = "madera-gpio", }, 86 { .name = "madera-extcon", }, 87 { 88 .name = "cs47l85-codec", 89 .parent_supplies = cs47l85_supplies, 90 .num_parent_supplies = ARRAY_SIZE(cs47l85_supplies), 91 }, 92 }; 93 94 static const char * const cs47l90_supplies[] = { 95 "MICVDD", 96 "DBVDD2", 97 "DBVDD3", 98 "DBVDD4", 99 "CPVDD1", 100 "CPVDD2", 101 }; 102 103 static const struct mfd_cell cs47l90_devs[] = { 104 { .name = "madera-pinctrl", }, 105 { .name = "madera-irq", }, 106 { .name = "madera-micsupp", }, 107 { .name = "madera-gpio", }, 108 { .name = "madera-extcon", }, 109 { 110 .name = "cs47l90-codec", 111 .parent_supplies = cs47l90_supplies, 112 .num_parent_supplies = ARRAY_SIZE(cs47l90_supplies), 113 }, 114 }; 115 116 /* Used by madera-i2c and madera-spi drivers */ 117 const char *madera_name_from_type(enum madera_type type) 118 { 119 switch (type) { 120 case CS47L35: 121 return "CS47L35"; 122 case CS47L85: 123 return "CS47L85"; 124 case CS47L90: 125 return "CS47L90"; 126 case CS47L91: 127 return "CS47L91"; 128 case WM1840: 129 return "WM1840"; 130 default: 131 return "Unknown"; 132 } 133 } 134 EXPORT_SYMBOL_GPL(madera_name_from_type); 135 136 #define MADERA_BOOT_POLL_INTERVAL_USEC 5000 137 #define MADERA_BOOT_POLL_TIMEOUT_USEC 25000 138 139 static int madera_wait_for_boot(struct madera *madera) 140 { 141 ktime_t timeout; 142 unsigned int val; 143 int ret = 0; 144 145 /* 146 * We can't use an interrupt as we need to runtime resume to do so, 147 * so we poll the status bit. This won't race with the interrupt 148 * handler because it will be blocked on runtime resume. 149 * The chip could NAK a read request while it is booting so ignore 150 * errors from regmap_read. 151 */ 152 timeout = ktime_add_us(ktime_get(), MADERA_BOOT_POLL_TIMEOUT_USEC); 153 regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val); 154 while (!(val & MADERA_BOOT_DONE_STS1) && 155 !ktime_after(ktime_get(), timeout)) { 156 usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2, 157 MADERA_BOOT_POLL_INTERVAL_USEC); 158 regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val); 159 } 160 161 if (!(val & MADERA_BOOT_DONE_STS1)) { 162 dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n"); 163 ret = -ETIMEDOUT; 164 } 165 166 /* 167 * BOOT_DONE defaults to unmasked on boot so we must ack it. 168 * Do this even after a timeout to avoid interrupt storms. 169 */ 170 regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1, 171 MADERA_BOOT_DONE_EINT1); 172 173 pm_runtime_mark_last_busy(madera->dev); 174 175 return ret; 176 } 177 178 static int madera_soft_reset(struct madera *madera) 179 { 180 int ret; 181 182 ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0); 183 if (ret != 0) { 184 dev_err(madera->dev, "Failed to soft reset device: %d\n", ret); 185 return ret; 186 } 187 188 /* Allow time for internal clocks to startup after reset */ 189 usleep_range(1000, 2000); 190 191 return 0; 192 } 193 194 static void madera_enable_hard_reset(struct madera *madera) 195 { 196 if (!madera->pdata.reset) 197 return; 198 199 /* 200 * There are many existing out-of-tree users of these codecs that we 201 * can't break so preserve the expected behaviour of setting the line 202 * low to assert reset. 203 */ 204 gpiod_set_raw_value_cansleep(madera->pdata.reset, 0); 205 } 206 207 static void madera_disable_hard_reset(struct madera *madera) 208 { 209 if (!madera->pdata.reset) 210 return; 211 212 gpiod_set_raw_value_cansleep(madera->pdata.reset, 1); 213 usleep_range(1000, 2000); 214 } 215 216 static int __maybe_unused madera_runtime_resume(struct device *dev) 217 { 218 struct madera *madera = dev_get_drvdata(dev); 219 int ret; 220 221 dev_dbg(dev, "Leaving sleep mode\n"); 222 223 ret = regulator_enable(madera->dcvdd); 224 if (ret) { 225 dev_err(dev, "Failed to enable DCVDD: %d\n", ret); 226 return ret; 227 } 228 229 regcache_cache_only(madera->regmap, false); 230 regcache_cache_only(madera->regmap_32bit, false); 231 232 ret = madera_wait_for_boot(madera); 233 if (ret) 234 goto err; 235 236 ret = regcache_sync(madera->regmap); 237 if (ret) { 238 dev_err(dev, "Failed to restore 16-bit register cache\n"); 239 goto err; 240 } 241 242 ret = regcache_sync(madera->regmap_32bit); 243 if (ret) { 244 dev_err(dev, "Failed to restore 32-bit register cache\n"); 245 goto err; 246 } 247 248 return 0; 249 250 err: 251 regcache_cache_only(madera->regmap_32bit, true); 252 regcache_cache_only(madera->regmap, true); 253 regulator_disable(madera->dcvdd); 254 255 return ret; 256 } 257 258 static int __maybe_unused madera_runtime_suspend(struct device *dev) 259 { 260 struct madera *madera = dev_get_drvdata(dev); 261 262 dev_dbg(madera->dev, "Entering sleep mode\n"); 263 264 regcache_cache_only(madera->regmap, true); 265 regcache_mark_dirty(madera->regmap); 266 regcache_cache_only(madera->regmap_32bit, true); 267 regcache_mark_dirty(madera->regmap_32bit); 268 269 regulator_disable(madera->dcvdd); 270 271 return 0; 272 } 273 274 const struct dev_pm_ops madera_pm_ops = { 275 SET_RUNTIME_PM_OPS(madera_runtime_suspend, 276 madera_runtime_resume, 277 NULL) 278 }; 279 EXPORT_SYMBOL_GPL(madera_pm_ops); 280 281 const struct of_device_id madera_of_match[] = { 282 { .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 }, 283 { .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 }, 284 { .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 }, 285 { .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 }, 286 { .compatible = "cirrus,wm1840", .data = (void *)WM1840 }, 287 {} 288 }; 289 EXPORT_SYMBOL_GPL(madera_of_match); 290 291 static int madera_get_reset_gpio(struct madera *madera) 292 { 293 struct gpio_desc *reset; 294 int ret; 295 296 if (madera->pdata.reset) 297 return 0; 298 299 reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW); 300 if (IS_ERR(reset)) { 301 ret = PTR_ERR(reset); 302 if (ret != -EPROBE_DEFER) 303 dev_err(madera->dev, "Failed to request /RESET: %d\n", 304 ret); 305 return ret; 306 } 307 308 /* 309 * A hard reset is needed for full reset of the chip. We allow running 310 * without hard reset only because it can be useful for early 311 * prototyping and some debugging, but we need to warn it's not ideal. 312 */ 313 if (!reset) 314 dev_warn(madera->dev, 315 "Running without reset GPIO is not recommended\n"); 316 317 madera->pdata.reset = reset; 318 319 return 0; 320 } 321 322 static void madera_set_micbias_info(struct madera *madera) 323 { 324 /* 325 * num_childbias is an array because future codecs can have different 326 * childbiases for each micbias. Unspecified values default to 0. 327 */ 328 switch (madera->type) { 329 case CS47L35: 330 madera->num_micbias = 2; 331 madera->num_childbias[0] = 2; 332 madera->num_childbias[1] = 2; 333 return; 334 case CS47L85: 335 case WM1840: 336 madera->num_micbias = 4; 337 /* no child biases */ 338 return; 339 case CS47L90: 340 case CS47L91: 341 madera->num_micbias = 2; 342 madera->num_childbias[0] = 4; 343 madera->num_childbias[1] = 4; 344 return; 345 default: 346 return; 347 } 348 } 349 350 int madera_dev_init(struct madera *madera) 351 { 352 struct device *dev = madera->dev; 353 unsigned int hwid; 354 int (*patch_fn)(struct madera *) = NULL; 355 const struct mfd_cell *mfd_devs; 356 int n_devs = 0; 357 int i, ret; 358 359 dev_set_drvdata(madera->dev, madera); 360 BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier); 361 mutex_init(&madera->dapm_ptr_lock); 362 363 madera_set_micbias_info(madera); 364 365 /* 366 * We need writable hw config info that all children can share. 367 * Simplest to take one shared copy of pdata struct. 368 */ 369 if (dev_get_platdata(madera->dev)) { 370 memcpy(&madera->pdata, dev_get_platdata(madera->dev), 371 sizeof(madera->pdata)); 372 } 373 374 ret = madera_get_reset_gpio(madera); 375 if (ret) 376 return ret; 377 378 regcache_cache_only(madera->regmap, true); 379 regcache_cache_only(madera->regmap_32bit, true); 380 381 for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++) 382 madera->core_supplies[i].supply = madera_core_supplies[i]; 383 384 madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies); 385 386 /* 387 * On some codecs DCVDD could be supplied by the internal LDO1. 388 * For those we must add the LDO1 driver before requesting DCVDD 389 * No devm_ because we need to control shutdown order of children. 390 */ 391 switch (madera->type) { 392 case CS47L35: 393 case CS47L90: 394 case CS47L91: 395 break; 396 case CS47L85: 397 case WM1840: 398 ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE, 399 madera_ldo1_devs, 400 ARRAY_SIZE(madera_ldo1_devs), 401 NULL, 0, NULL); 402 if (ret) { 403 dev_err(dev, "Failed to add LDO1 child: %d\n", ret); 404 return ret; 405 } 406 break; 407 default: 408 /* No point continuing if the type is unknown */ 409 dev_err(madera->dev, "Unknown device type %d\n", madera->type); 410 return -ENODEV; 411 } 412 413 ret = devm_regulator_bulk_get(dev, madera->num_core_supplies, 414 madera->core_supplies); 415 if (ret) { 416 dev_err(dev, "Failed to request core supplies: %d\n", ret); 417 goto err_devs; 418 } 419 420 /* 421 * Don't use devres here. If the regulator is one of our children it 422 * will already have been removed before devres cleanup on this mfd 423 * driver tries to call put() on it. We need control of shutdown order. 424 */ 425 madera->dcvdd = regulator_get(madera->dev, "DCVDD"); 426 if (IS_ERR(madera->dcvdd)) { 427 ret = PTR_ERR(madera->dcvdd); 428 dev_err(dev, "Failed to request DCVDD: %d\n", ret); 429 goto err_devs; 430 } 431 432 ret = regulator_bulk_enable(madera->num_core_supplies, 433 madera->core_supplies); 434 if (ret) { 435 dev_err(dev, "Failed to enable core supplies: %d\n", ret); 436 goto err_dcvdd; 437 } 438 439 ret = regulator_enable(madera->dcvdd); 440 if (ret) { 441 dev_err(dev, "Failed to enable DCVDD: %d\n", ret); 442 goto err_enable; 443 } 444 445 madera_disable_hard_reset(madera); 446 447 regcache_cache_only(madera->regmap, false); 448 regcache_cache_only(madera->regmap_32bit, false); 449 450 /* 451 * Now we can power up and verify that this is a chip we know about 452 * before we start doing any writes to its registers. 453 */ 454 ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid); 455 if (ret) { 456 dev_err(dev, "Failed to read ID register: %d\n", ret); 457 goto err_reset; 458 } 459 460 switch (hwid) { 461 case CS47L35_SILICON_ID: 462 if (IS_ENABLED(CONFIG_MFD_CS47L35)) { 463 switch (madera->type) { 464 case CS47L35: 465 patch_fn = cs47l35_patch; 466 mfd_devs = cs47l35_devs; 467 n_devs = ARRAY_SIZE(cs47l35_devs); 468 break; 469 default: 470 break; 471 } 472 } 473 break; 474 case CS47L85_SILICON_ID: 475 if (IS_ENABLED(CONFIG_MFD_CS47L85)) { 476 switch (madera->type) { 477 case CS47L85: 478 case WM1840: 479 patch_fn = cs47l85_patch; 480 mfd_devs = cs47l85_devs; 481 n_devs = ARRAY_SIZE(cs47l85_devs); 482 break; 483 default: 484 break; 485 } 486 } 487 break; 488 case CS47L90_SILICON_ID: 489 if (IS_ENABLED(CONFIG_MFD_CS47L90)) { 490 switch (madera->type) { 491 case CS47L90: 492 case CS47L91: 493 patch_fn = cs47l90_patch; 494 mfd_devs = cs47l90_devs; 495 n_devs = ARRAY_SIZE(cs47l90_devs); 496 break; 497 default: 498 break; 499 } 500 } 501 break; 502 default: 503 dev_err(madera->dev, "Unknown device ID: %x\n", hwid); 504 ret = -EINVAL; 505 goto err_reset; 506 } 507 508 if (!n_devs) { 509 dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid, 510 madera->type_name); 511 ret = -ENODEV; 512 goto err_reset; 513 } 514 515 /* 516 * It looks like a device we support. If we don't have a hard reset 517 * we can now attempt a soft reset. 518 */ 519 if (!madera->pdata.reset) { 520 ret = madera_soft_reset(madera); 521 if (ret) 522 goto err_reset; 523 } 524 525 ret = madera_wait_for_boot(madera); 526 if (ret) { 527 dev_err(madera->dev, "Device failed initial boot: %d\n", ret); 528 goto err_reset; 529 } 530 531 ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION, 532 &madera->rev); 533 if (ret) { 534 dev_err(dev, "Failed to read revision register: %d\n", ret); 535 goto err_reset; 536 } 537 madera->rev &= MADERA_HW_REVISION_MASK; 538 539 dev_info(dev, "%s silicon revision %d\n", madera->type_name, 540 madera->rev); 541 542 /* Apply hardware patch */ 543 if (patch_fn) { 544 ret = patch_fn(madera); 545 if (ret) { 546 dev_err(madera->dev, "Failed to apply patch %d\n", ret); 547 goto err_reset; 548 } 549 } 550 551 /* Init 32k clock sourced from MCLK2 */ 552 ret = regmap_update_bits(madera->regmap, 553 MADERA_CLOCK_32K_1, 554 MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK, 555 MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2); 556 if (ret) { 557 dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret); 558 goto err_reset; 559 } 560 561 pm_runtime_set_active(madera->dev); 562 pm_runtime_enable(madera->dev); 563 pm_runtime_set_autosuspend_delay(madera->dev, 100); 564 pm_runtime_use_autosuspend(madera->dev); 565 566 /* No devm_ because we need to control shutdown order of children */ 567 ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE, 568 mfd_devs, n_devs, 569 NULL, 0, NULL); 570 if (ret) { 571 dev_err(madera->dev, "Failed to add subdevices: %d\n", ret); 572 goto err_pm_runtime; 573 } 574 575 return 0; 576 577 err_pm_runtime: 578 pm_runtime_disable(madera->dev); 579 err_reset: 580 madera_enable_hard_reset(madera); 581 regulator_disable(madera->dcvdd); 582 err_enable: 583 regulator_bulk_disable(madera->num_core_supplies, 584 madera->core_supplies); 585 err_dcvdd: 586 regulator_put(madera->dcvdd); 587 err_devs: 588 mfd_remove_devices(dev); 589 590 return ret; 591 } 592 EXPORT_SYMBOL_GPL(madera_dev_init); 593 594 int madera_dev_exit(struct madera *madera) 595 { 596 /* Prevent any IRQs being serviced while we clean up */ 597 disable_irq(madera->irq); 598 599 /* 600 * DCVDD could be supplied by a child node, we must disable it before 601 * removing the children, and prevent PM runtime from turning it back on 602 */ 603 pm_runtime_disable(madera->dev); 604 605 regulator_disable(madera->dcvdd); 606 regulator_put(madera->dcvdd); 607 608 mfd_remove_devices(madera->dev); 609 madera_enable_hard_reset(madera); 610 611 regulator_bulk_disable(madera->num_core_supplies, 612 madera->core_supplies); 613 return 0; 614 } 615 EXPORT_SYMBOL_GPL(madera_dev_exit); 616 617 MODULE_DESCRIPTION("Madera core MFD driver"); 618 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 619 MODULE_LICENSE("GPL v2"); 620