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 MODULE_DEVICE_TABLE(of, madera_of_match); 290 EXPORT_SYMBOL_GPL(madera_of_match); 291 292 static int madera_get_reset_gpio(struct madera *madera) 293 { 294 struct gpio_desc *reset; 295 int ret; 296 297 if (madera->pdata.reset) 298 return 0; 299 300 reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW); 301 if (IS_ERR(reset)) { 302 ret = PTR_ERR(reset); 303 if (ret != -EPROBE_DEFER) 304 dev_err(madera->dev, "Failed to request /RESET: %d\n", 305 ret); 306 return ret; 307 } 308 309 /* 310 * A hard reset is needed for full reset of the chip. We allow running 311 * without hard reset only because it can be useful for early 312 * prototyping and some debugging, but we need to warn it's not ideal. 313 */ 314 if (!reset) 315 dev_warn(madera->dev, 316 "Running without reset GPIO is not recommended\n"); 317 318 madera->pdata.reset = reset; 319 320 return 0; 321 } 322 323 static void madera_set_micbias_info(struct madera *madera) 324 { 325 /* 326 * num_childbias is an array because future codecs can have different 327 * childbiases for each micbias. Unspecified values default to 0. 328 */ 329 switch (madera->type) { 330 case CS47L35: 331 madera->num_micbias = 2; 332 madera->num_childbias[0] = 2; 333 madera->num_childbias[1] = 2; 334 return; 335 case CS47L85: 336 case WM1840: 337 madera->num_micbias = 4; 338 /* no child biases */ 339 return; 340 case CS47L90: 341 case CS47L91: 342 madera->num_micbias = 2; 343 madera->num_childbias[0] = 4; 344 madera->num_childbias[1] = 4; 345 return; 346 default: 347 return; 348 } 349 } 350 351 int madera_dev_init(struct madera *madera) 352 { 353 struct device *dev = madera->dev; 354 unsigned int hwid; 355 int (*patch_fn)(struct madera *) = NULL; 356 const struct mfd_cell *mfd_devs; 357 int n_devs = 0; 358 int i, ret; 359 360 dev_set_drvdata(madera->dev, madera); 361 BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier); 362 mutex_init(&madera->dapm_ptr_lock); 363 364 madera_set_micbias_info(madera); 365 366 /* 367 * We need writable hw config info that all children can share. 368 * Simplest to take one shared copy of pdata struct. 369 */ 370 if (dev_get_platdata(madera->dev)) { 371 memcpy(&madera->pdata, dev_get_platdata(madera->dev), 372 sizeof(madera->pdata)); 373 } 374 375 ret = madera_get_reset_gpio(madera); 376 if (ret) 377 return ret; 378 379 regcache_cache_only(madera->regmap, true); 380 regcache_cache_only(madera->regmap_32bit, true); 381 382 for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++) 383 madera->core_supplies[i].supply = madera_core_supplies[i]; 384 385 madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies); 386 387 /* 388 * On some codecs DCVDD could be supplied by the internal LDO1. 389 * For those we must add the LDO1 driver before requesting DCVDD 390 * No devm_ because we need to control shutdown order of children. 391 */ 392 switch (madera->type) { 393 case CS47L35: 394 case CS47L90: 395 case CS47L91: 396 break; 397 case CS47L85: 398 case WM1840: 399 ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE, 400 madera_ldo1_devs, 401 ARRAY_SIZE(madera_ldo1_devs), 402 NULL, 0, NULL); 403 if (ret) { 404 dev_err(dev, "Failed to add LDO1 child: %d\n", ret); 405 return ret; 406 } 407 break; 408 default: 409 /* No point continuing if the type is unknown */ 410 dev_err(madera->dev, "Unknown device type %d\n", madera->type); 411 return -ENODEV; 412 } 413 414 ret = devm_regulator_bulk_get(dev, madera->num_core_supplies, 415 madera->core_supplies); 416 if (ret) { 417 dev_err(dev, "Failed to request core supplies: %d\n", ret); 418 goto err_devs; 419 } 420 421 /* 422 * Don't use devres here. If the regulator is one of our children it 423 * will already have been removed before devres cleanup on this mfd 424 * driver tries to call put() on it. We need control of shutdown order. 425 */ 426 madera->dcvdd = regulator_get(madera->dev, "DCVDD"); 427 if (IS_ERR(madera->dcvdd)) { 428 ret = PTR_ERR(madera->dcvdd); 429 dev_err(dev, "Failed to request DCVDD: %d\n", ret); 430 goto err_devs; 431 } 432 433 ret = regulator_bulk_enable(madera->num_core_supplies, 434 madera->core_supplies); 435 if (ret) { 436 dev_err(dev, "Failed to enable core supplies: %d\n", ret); 437 goto err_dcvdd; 438 } 439 440 ret = regulator_enable(madera->dcvdd); 441 if (ret) { 442 dev_err(dev, "Failed to enable DCVDD: %d\n", ret); 443 goto err_enable; 444 } 445 446 madera_disable_hard_reset(madera); 447 448 regcache_cache_only(madera->regmap, false); 449 regcache_cache_only(madera->regmap_32bit, false); 450 451 /* 452 * Now we can power up and verify that this is a chip we know about 453 * before we start doing any writes to its registers. 454 */ 455 ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid); 456 if (ret) { 457 dev_err(dev, "Failed to read ID register: %d\n", ret); 458 goto err_reset; 459 } 460 461 switch (hwid) { 462 case CS47L35_SILICON_ID: 463 if (IS_ENABLED(CONFIG_MFD_CS47L35)) { 464 switch (madera->type) { 465 case CS47L35: 466 patch_fn = cs47l35_patch; 467 mfd_devs = cs47l35_devs; 468 n_devs = ARRAY_SIZE(cs47l35_devs); 469 break; 470 default: 471 break; 472 } 473 } 474 break; 475 case CS47L85_SILICON_ID: 476 if (IS_ENABLED(CONFIG_MFD_CS47L85)) { 477 switch (madera->type) { 478 case CS47L85: 479 case WM1840: 480 patch_fn = cs47l85_patch; 481 mfd_devs = cs47l85_devs; 482 n_devs = ARRAY_SIZE(cs47l85_devs); 483 break; 484 default: 485 break; 486 } 487 } 488 break; 489 case CS47L90_SILICON_ID: 490 if (IS_ENABLED(CONFIG_MFD_CS47L90)) { 491 switch (madera->type) { 492 case CS47L90: 493 case CS47L91: 494 patch_fn = cs47l90_patch; 495 mfd_devs = cs47l90_devs; 496 n_devs = ARRAY_SIZE(cs47l90_devs); 497 break; 498 default: 499 break; 500 } 501 } 502 break; 503 default: 504 dev_err(madera->dev, "Unknown device ID: %x\n", hwid); 505 ret = -EINVAL; 506 goto err_reset; 507 } 508 509 if (!n_devs) { 510 dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid, 511 madera->type_name); 512 ret = -ENODEV; 513 goto err_reset; 514 } 515 516 /* 517 * It looks like a device we support. If we don't have a hard reset 518 * we can now attempt a soft reset. 519 */ 520 if (!madera->pdata.reset) { 521 ret = madera_soft_reset(madera); 522 if (ret) 523 goto err_reset; 524 } 525 526 ret = madera_wait_for_boot(madera); 527 if (ret) { 528 dev_err(madera->dev, "Device failed initial boot: %d\n", ret); 529 goto err_reset; 530 } 531 532 ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION, 533 &madera->rev); 534 if (ret) { 535 dev_err(dev, "Failed to read revision register: %d\n", ret); 536 goto err_reset; 537 } 538 madera->rev &= MADERA_HW_REVISION_MASK; 539 540 dev_info(dev, "%s silicon revision %d\n", madera->type_name, 541 madera->rev); 542 543 /* Apply hardware patch */ 544 if (patch_fn) { 545 ret = patch_fn(madera); 546 if (ret) { 547 dev_err(madera->dev, "Failed to apply patch %d\n", ret); 548 goto err_reset; 549 } 550 } 551 552 /* Init 32k clock sourced from MCLK2 */ 553 ret = regmap_update_bits(madera->regmap, 554 MADERA_CLOCK_32K_1, 555 MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK, 556 MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2); 557 if (ret) { 558 dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret); 559 goto err_reset; 560 } 561 562 pm_runtime_set_active(madera->dev); 563 pm_runtime_enable(madera->dev); 564 pm_runtime_set_autosuspend_delay(madera->dev, 100); 565 pm_runtime_use_autosuspend(madera->dev); 566 567 /* No devm_ because we need to control shutdown order of children */ 568 ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE, 569 mfd_devs, n_devs, 570 NULL, 0, NULL); 571 if (ret) { 572 dev_err(madera->dev, "Failed to add subdevices: %d\n", ret); 573 goto err_pm_runtime; 574 } 575 576 return 0; 577 578 err_pm_runtime: 579 pm_runtime_disable(madera->dev); 580 err_reset: 581 madera_enable_hard_reset(madera); 582 regulator_disable(madera->dcvdd); 583 err_enable: 584 regulator_bulk_disable(madera->num_core_supplies, 585 madera->core_supplies); 586 err_dcvdd: 587 regulator_put(madera->dcvdd); 588 err_devs: 589 mfd_remove_devices(dev); 590 591 return ret; 592 } 593 EXPORT_SYMBOL_GPL(madera_dev_init); 594 595 int madera_dev_exit(struct madera *madera) 596 { 597 /* Prevent any IRQs being serviced while we clean up */ 598 disable_irq(madera->irq); 599 600 /* 601 * DCVDD could be supplied by a child node, we must disable it before 602 * removing the children, and prevent PM runtime from turning it back on 603 */ 604 pm_runtime_disable(madera->dev); 605 606 regulator_disable(madera->dcvdd); 607 regulator_put(madera->dcvdd); 608 609 mfd_remove_devices(madera->dev); 610 madera_enable_hard_reset(madera); 611 612 regulator_bulk_disable(madera->num_core_supplies, 613 madera->core_supplies); 614 return 0; 615 } 616 EXPORT_SYMBOL_GPL(madera_dev_exit); 617 618 MODULE_DESCRIPTION("Madera core MFD driver"); 619 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 620 MODULE_LICENSE("GPL v2"); 621