^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SPI bus interface to Cirrus Logic Madera codecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015-2018 Cirrus Logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mfd/madera/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "madera.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static int madera_spi_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) const struct spi_device_id *id = spi_get_device_id(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct madera *madera;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) const struct regmap_config *regmap_16bit_config = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const struct regmap_config *regmap_32bit_config = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const void *of_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) of_data = of_device_get_match_data(&spi->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (of_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) type = (unsigned long)of_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) type = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) case CS47L15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) regmap_16bit_config = &cs47l15_16bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) regmap_32bit_config = &cs47l15_32bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) case CS47L35:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) regmap_16bit_config = &cs47l35_16bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) regmap_32bit_config = &cs47l35_32bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case CS47L85:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case WM1840:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) regmap_16bit_config = &cs47l85_16bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) regmap_32bit_config = &cs47l85_32bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case CS47L90:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) case CS47L91:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) regmap_16bit_config = &cs47l90_16bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) regmap_32bit_config = &cs47l90_32bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case CS42L92:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case CS47L92:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) case CS47L93:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) regmap_16bit_config = &cs47l92_16bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) regmap_32bit_config = &cs47l92_32bit_spi_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dev_err(&spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "Unknown Madera SPI device type %ld\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) name = madera_name_from_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (!regmap_16bit_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* it's polite to say which codec isn't built into the kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dev_err(&spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "Kernel does not include support for %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) madera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!madera)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) madera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (IS_ERR(madera->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ret = PTR_ERR(madera->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev_err(&spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) "Failed to allocate 16-bit register map: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) madera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (IS_ERR(madera->regmap_32bit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ret = PTR_ERR(madera->regmap_32bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_err(&spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) "Failed to allocate 32-bit register map: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) madera->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) madera->type_name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) madera->dev = &spi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) madera->irq = spi->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return madera_dev_init(madera);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int madera_spi_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct madera *madera = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) madera_dev_exit(madera);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static const struct spi_device_id madera_spi_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { "cs47l15", CS47L15 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { "cs47l35", CS47L35 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { "cs47l85", CS47L85 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { "cs47l90", CS47L90 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { "cs47l91", CS47L91 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { "cs42l92", CS42L92 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { "cs47l92", CS47L92 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { "cs47l93", CS47L93 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { "wm1840", WM1840 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MODULE_DEVICE_TABLE(spi, madera_spi_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static struct spi_driver madera_spi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .name = "madera",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .pm = &madera_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .of_match_table = of_match_ptr(madera_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .probe = madera_spi_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .remove = madera_spi_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .id_table = madera_spi_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) module_spi_driver(madera_spi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) MODULE_DESCRIPTION("Madera SPI bus interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) MODULE_LICENSE("GPL v2");