diff options
Diffstat (limited to 'drivers/mfd')
72 files changed, 1346 insertions, 552 deletions
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index a65447d65605..7dca1e640970 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -148,7 +148,7 @@ static struct resource onkey_resources[] = { }, }; -static struct mfd_cell onkey_devs[] = { +static const struct mfd_cell onkey_devs[] = { { .name = "88pm80x-onkey", .num_resources = 1, @@ -157,7 +157,7 @@ static struct mfd_cell onkey_devs[] = { }, }; -static struct mfd_cell regulator_devs[] = { +static const struct mfd_cell regulator_devs[] = { { .name = "88pm80x-regulator", .id = -1, diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 8a5b6ffb5afb..64751c2a1ace 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -77,7 +77,7 @@ static struct resource codec_resources[] = { }, }; -static struct mfd_cell codec_devs[] = { +static const struct mfd_cell codec_devs[] = { { .name = "88pm80x-codec", .num_resources = ARRAY_SIZE(codec_resources), diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index dd671582c9a1..49bb445d846a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -80,7 +80,7 @@ config MFD_CROS_EC_I2C config MFD_CROS_EC_SPI tristate "ChromeOS Embedded Controller (SPI)" - depends on MFD_CROS_EC && SPI + depends on MFD_CROS_EC && SPI && OF ---help--- If you say Y here, you get support for talking to the ChromeOS EC @@ -163,14 +163,10 @@ config MFD_DA9063 Additional drivers must be enabled in order to use the functionality of the device. -config MFD_MC13783 - tristate - config MFD_MC13XXX tristate depends on (SPI_MASTER || I2C) select MFD_CORE - select MFD_MC13783 help Enable support for the Freescale MC13783 and MC13892 PMICs. This driver provides common support for accessing the device, @@ -321,6 +317,19 @@ config MFD_88PM860X select individual components like voltage regulators, RTC and battery-charger under the corresponding menus. +config MFD_MAX14577 + bool "Maxim Semiconductor MAX14577 MUIC + Charger Support" + depends on I2C=y + select MFD_CORE + select REGMAP_I2C + select IRQ_DOMAIN + help + Say yes here to support for Maxim Semiconductor MAX14577. + This is a Micro-USB IC with Charger controls on chip. + This driver provides common support for accessing the device; + additional drivers must be enabled in order to use the functionality + of the device. + config MFD_MAX77686 bool "Maxim Semiconductor MAX77686 PMIC Support" depends on I2C=y @@ -725,6 +734,17 @@ config MFD_DM355EVM_MSP boards. MSP430 firmware manages resets and power sequencing, inputs from buttons and the IR remote, LEDs, an RTC, and more. +config MFD_LP3943 + tristate "TI/National Semiconductor LP3943 MFD Driver" + depends on I2C + select MFD_CORE + select REGMAP_I2C + help + Support for the TI/National Semiconductor LP3943. + This driver consists of GPIO and PWM drivers. + With these functionalities, it can be used for LED string control or + general usage such like a GPIO controller and a PWM controller. + config MFD_LP8788 bool "TI LP8788 Power Management Unit Driver" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8a28dc90fe78..5aea5ef0a62f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o +obj-$(CONFIG_MFD_LP3943) += lp3943.o obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o da9055-objs := da9055-core.o da9055-i2c.o @@ -110,6 +111,7 @@ obj-$(CONFIG_MFD_DA9055) += da9055.o da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o obj-$(CONFIG_MFD_DA9063) += da9063.o +obj-$(CONFIG_MFD_MAX14577) += max14577.o obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o obj-$(CONFIG_MFD_MAX8907) += max8907.o diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index b6c2cdc76091..aaff683cd37d 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -491,7 +491,7 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) line += 1; - handle_nested_irq(ab8500->irq_base + line); + handle_nested_irq(irq_create_mapping(ab8500->domain, line)); } return 0; @@ -1017,7 +1017,7 @@ static struct resource ab8500_temp_resources[] = { }, }; -static struct mfd_cell ab8500_bm_devs[] = { +static const struct mfd_cell ab8500_bm_devs[] = { { .name = "ab8500-charger", .of_compatible = "stericsson,ab8500-charger", @@ -1052,7 +1052,7 @@ static struct mfd_cell ab8500_bm_devs[] = { }, }; -static struct mfd_cell ab8500_devs[] = { +static const struct mfd_cell ab8500_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", @@ -1143,7 +1143,7 @@ static struct mfd_cell ab8500_devs[] = { }, }; -static struct mfd_cell ab9540_devs[] = { +static const struct mfd_cell ab9540_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", @@ -1214,7 +1214,7 @@ static struct mfd_cell ab9540_devs[] = { }; /* Device list for ab8505 */ -static struct mfd_cell ab8505_devs[] = { +static const struct mfd_cell ab8505_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", @@ -1275,7 +1275,7 @@ static struct mfd_cell ab8505_devs[] = { }, }; -static struct mfd_cell ab8540_devs[] = { +static const struct mfd_cell ab8540_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", @@ -1339,7 +1339,7 @@ static struct mfd_cell ab8540_devs[] = { }, }; -static struct mfd_cell ab8540_cut1_devs[] = { +static const struct mfd_cell ab8540_cut1_devs[] = { { .name = "ab8500-rtc", .of_compatible = "stericsson,ab8500-rtc", @@ -1348,7 +1348,7 @@ static struct mfd_cell ab8540_cut1_devs[] = { }, }; -static struct mfd_cell ab8540_cut2_devs[] = { +static const struct mfd_cell ab8540_cut2_devs[] = { { .name = "ab8540-rtc", .of_compatible = "stericsson,ab8540-rtc", diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index e33e385af0a2..d1a22aae2df5 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -1600,7 +1600,6 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p) for (line = 0; line < num_interrupt_lines; line++) { struct irq_desc *desc = irq_to_desc(line + irq_first); - struct irqaction *action = desc->action; seq_printf(s, "%3i: %6i %4i", line, num_interrupts[line], @@ -1608,7 +1607,9 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p) if (desc && desc->name) seq_printf(s, "-%-8s", desc->name); - if (action) { + if (desc && desc->action) { + struct irqaction *action = desc->action; + seq_printf(s, " %s", action->name); while ((action = action->next) != NULL) seq_printf(s, ", %s", action->name); diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 75e180ceecf3..a45aab9f6bb1 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -565,7 +565,7 @@ static inline int arizona_of_get_core_pdata(struct arizona *arizona) } #endif -static struct mfd_cell early_devs[] = { +static const struct mfd_cell early_devs[] = { { .name = "arizona-ldo1" }, }; @@ -577,7 +577,7 @@ static const char *wm5102_supplies[] = { "SPKVDDR", }; -static struct mfd_cell wm5102_devs[] = { +static const struct mfd_cell wm5102_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-extcon" }, { .name = "arizona-gpio" }, @@ -590,7 +590,7 @@ static struct mfd_cell wm5102_devs[] = { }, }; -static struct mfd_cell wm5110_devs[] = { +static const struct mfd_cell wm5110_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-extcon" }, { .name = "arizona-gpio" }, @@ -609,7 +609,7 @@ static const char *wm8997_supplies[] = { "SPKVDD", }; -static struct mfd_cell wm8997_devs[] = { +static const struct mfd_cell wm8997_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-extcon" }, { .name = "arizona-gpio" }, diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c index f161f2e00df7..c71ff0af1547 100644 --- a/drivers/mfd/as3722.c +++ b/drivers/mfd/as3722.c @@ -54,7 +54,7 @@ static const struct resource as3722_adc_resource[] = { }, }; -static struct mfd_cell as3722_devs[] = { +static const struct mfd_cell as3722_devs[] = { { .name = "as3722-pinctrl", }, @@ -74,6 +74,9 @@ static struct mfd_cell as3722_devs[] = { { .name = "as3722-power-off", }, + { + .name = "as3722-wdt", + }, }; static const struct regmap_irq as3722_irqs[] = { diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index fa22154c84e4..9f6294f2a070 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -695,7 +695,7 @@ static int ds1wm_disable(struct platform_device *pdev) return 0; } -static struct mfd_cell asic3_cell_ds1wm = { +static const struct mfd_cell asic3_cell_ds1wm = { .name = "ds1wm", .enable = ds1wm_enable, .disable = ds1wm_disable, @@ -797,7 +797,7 @@ static int asic3_mmc_disable(struct platform_device *pdev) return 0; } -static struct mfd_cell asic3_cell_mmc = { +static const struct mfd_cell asic3_cell_mmc = { .name = "tmio-mmc", .enable = asic3_mmc_enable, .disable = asic3_mmc_disable, diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 1f36885d674b..783fe2e73e1e 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -84,7 +84,7 @@ static irqreturn_t ec_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static struct mfd_cell cros_devs[] = { +static const struct mfd_cell cros_devs[] = { { .name = "cros-ec-keyb", .id = 1, diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c index 123044608b63..4f71be99a183 100644 --- a/drivers/mfd/cros_ec_i2c.c +++ b/drivers/mfd/cros_ec_i2c.c @@ -120,7 +120,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev, return ret; } -static int cros_ec_probe_i2c(struct i2c_client *client, +static int cros_ec_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { struct device *dev = &client->dev; @@ -150,7 +150,7 @@ static int cros_ec_probe_i2c(struct i2c_client *client, return 0; } -static int cros_ec_remove_i2c(struct i2c_client *client) +static int cros_ec_i2c_remove(struct i2c_client *client) { struct cros_ec_device *ec_dev = i2c_get_clientdata(client); @@ -190,8 +190,8 @@ static struct i2c_driver cros_ec_driver = { .owner = THIS_MODULE, .pm = &cros_ec_i2c_pm_ops, }, - .probe = cros_ec_probe_i2c, - .remove = cros_ec_remove_i2c, + .probe = cros_ec_i2c_probe, + .remove = cros_ec_i2c_remove, .id_table = cros_ec_i2c_id, }; diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c index 367ccb58ecb1..84af8d7a4295 100644 --- a/drivers/mfd/cros_ec_spi.c +++ b/drivers/mfd/cros_ec_spi.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/mfd/cros_ec.h> #include <linux/mfd/cros_ec_commands.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spi/spi.h> @@ -50,10 +51,11 @@ /* * Time between raising the SPI chip select (for the end of a * transaction) and dropping it again (for the next transaction). - * If we go too fast, the EC will miss the transaction. It seems - * that 50us is enough with the 16MHz STM32 EC. + * If we go too fast, the EC will miss the transaction. We know that we + * need at least 70 us with the 16 MHz STM32 EC, so go with 200 us to be + * safe. */ -#define EC_SPI_RECOVERY_TIME_NS (50 * 1000) +#define EC_SPI_RECOVERY_TIME_NS (200 * 1000) /** * struct cros_ec_spi - information about a SPI-connected EC @@ -61,10 +63,13 @@ * @spi: SPI device we are connected to * @last_transfer_ns: time that we last finished a transfer, or 0 if there * if no record + * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that + * is sent when we want to turn off CS at the end of a transaction. */ struct cros_ec_spi { struct spi_device *spi; s64 last_transfer_ns; + unsigned int end_of_msg_delay; }; static void debug_packet(struct device *dev, const char *name, u8 *ptr, @@ -75,7 +80,9 @@ static void debug_packet(struct device *dev, const char *name, u8 *ptr, dev_dbg(dev, "%s: ", name); for (i = 0; i < len; i++) - dev_cont(dev, " %02x", ptr[i]); + pr_cont(" %02x", ptr[i]); + + pr_cont("\n"); #endif } @@ -105,7 +112,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev, /* Receive data until we see the header byte */ deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS); do { - memset(&trans, '\0', sizeof(trans)); + memset(&trans, 0, sizeof(trans)); trans.cs_change = 1; trans.rx_buf = ptr = ec_dev->din; trans.len = EC_MSG_PREAMBLE_COUNT; @@ -157,7 +164,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev, dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%zd\n", todo, need_len, ptr - ec_dev->din); - memset(&trans, '\0', sizeof(trans)); + memset(&trans, 0, sizeof(trans)); trans.cs_change = 1; trans.rx_buf = ptr; trans.len = todo; @@ -217,7 +224,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev, /* Transmit phase - send our message */ debug_packet(ec_dev->dev, "out", ec_dev->dout, len); - memset(&trans, '\0', sizeof(trans)); + memset(&trans, 0, sizeof(trans)); trans.tx_buf = ec_dev->dout; trans.len = len; trans.cs_change = 1; @@ -235,6 +242,17 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev, /* turn off CS */ spi_message_init(&msg); + + if (ec_spi->end_of_msg_delay) { + /* + * Add delay for last transaction, to ensure the rising edge + * doesn't come too soon after the end of the data. + */ + memset(&trans, 0, sizeof(trans)); + trans.delay_usecs = ec_spi->end_of_msg_delay; + spi_message_add_tail(&trans, &msg); + } + final_ret = spi_sync(ec_spi->spi, &msg); ktime_get_ts(&ts); ec_spi->last_transfer_ns = timespec_to_ns(&ts); @@ -281,7 +299,18 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev, return 0; } -static int cros_ec_probe_spi(struct spi_device *spi) +static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev) +{ + struct device_node *np = dev->of_node; + u32 val; + int ret; + + ret = of_property_read_u32(np, "google,cros-ec-spi-msg-delay", &val); + if (!ret) + ec_spi->end_of_msg_delay = val; +} + +static int cros_ec_spi_probe(struct spi_device *spi) { struct device *dev = &spi->dev; struct cros_ec_device *ec_dev; @@ -302,6 +331,9 @@ static int cros_ec_probe_spi(struct spi_device *spi) if (!ec_dev) return -ENOMEM; + /* Check for any DT properties */ + cros_ec_spi_dt_probe(ec_spi, dev); + spi_set_drvdata(spi, ec_dev); ec_dev->name = "SPI"; ec_dev->dev = dev; @@ -323,7 +355,7 @@ static int cros_ec_probe_spi(struct spi_device *spi) return 0; } -static int cros_ec_remove_spi(struct spi_device *spi) +static int cros_ec_spi_remove(struct spi_device *spi) { struct cros_ec_device *ec_dev; @@ -364,12 +396,12 @@ static struct spi_driver cros_ec_driver_spi = { .owner = THIS_MODULE, .pm = &cros_ec_spi_pm_ops, }, - .probe = cros_ec_probe_spi, - .remove = cros_ec_remove_spi, + .probe = cros_ec_spi_probe, + .remove = cros_ec_spi_remove, .id_table = cros_ec_spi_id, }; module_spi_driver(cros_ec_driver_spi); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)"); diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index 2e4752a9220a..17c13012686a 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -172,7 +172,7 @@ static void cs5535_mfd_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(cs5535_mfd_pci_tbl) = { +static const struct pci_device_id cs5535_mfd_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, { 0, } diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index ea28a33576e4..25838f10b35b 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -427,7 +427,7 @@ int da9052_adc_read_temp(struct da9052 *da9052) } EXPORT_SYMBOL_GPL(da9052_adc_read_temp); -static struct mfd_cell da9052_subdev_info[] = { +static const struct mfd_cell da9052_subdev_info[] = { { .name = "da9052-regulator", .id = 1, diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c index d3670cd3c3c6..caf8dcffd0ad 100644 --- a/drivers/mfd/da9055-core.c +++ b/drivers/mfd/da9055-core.c @@ -294,7 +294,7 @@ static struct resource da9055_ld05_6_resource = { .flags = IORESOURCE_IRQ, }; -static struct mfd_cell da9055_devs[] = { +static const struct mfd_cell da9055_devs[] = { { .of_compatible = "dialog,da9055-gpio", .name = "da9055-gpio", diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index c9cf8d988406..26937cd01071 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c @@ -75,7 +75,7 @@ static struct resource da9063_hwmon_resources[] = { }; -static struct mfd_cell da9063_devs[] = { +static const struct mfd_cell da9063_devs[] = { { .name = DA9063_DRVNAME_REGULATORS, .num_resources = ARRAY_SIZE(da9063_regulators_resources), diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index b9ce60c301de..e43e6e821117 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3070,7 +3070,7 @@ static struct db8500_thsens_platform_data db8500_thsens_data = { .num_trips = 4, }; -static struct mfd_cell common_prcmu_devs[] = { +static const struct mfd_cell common_prcmu_devs[] = { { .name = "ux500_wdt", .platform_data = &db8500_wdt_pdata, @@ -3079,7 +3079,7 @@ static struct mfd_cell common_prcmu_devs[] = { }, }; -static struct mfd_cell db8500_prcmu_devs[] = { +static const struct mfd_cell db8500_prcmu_devs[] = { { .name = "db8500-prcmu-regulators", .of_compatible = "stericsson,db8500-prcmu-regulator", diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 6bf92a507b95..e88d4f6fef4c 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -114,7 +114,7 @@ static struct resource ds1wm_resources[] __initdata = { }, }; -static struct mfd_cell ds1wm_cell __initdata = { +static const struct mfd_cell ds1wm_cell __initconst = { .name = "ds1wm", .enable = ds1wm_enable, .disable = ds1wm_disable, diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 9203d47cdbb1..049fd23af54a 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -178,7 +178,7 @@ static struct mfd_cell msic_devs[] = { * These devices appear only after the MSIC driver itself is initialized so * we can guarantee that the SCU IPC interface is ready. */ -static struct mfd_cell msic_other_devs[] = { +static const struct mfd_cell msic_other_devs[] = { /* Audio codec in the MSIC */ { .id = -1, diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index fcbb2e9dfd37..81b7d88af313 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -265,7 +265,7 @@ static void cmodio_pci_remove(struct pci_dev *dev) #define PCI_VENDOR_ID_JANZ 0x13c3 /* The list of devices that this module will support */ -static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = { +static const struct pci_device_id cmodio_pci_ids[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 }, { 0, } diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 3c0e8cf6916b..7a51c0d0d4f1 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -181,7 +181,7 @@ static struct resource jz4740_battery_resources[] = { }, }; -static struct mfd_cell jz4740_adc_cells[] = { +static const struct mfd_cell jz4740_adc_cells[] = { { .id = 0, .name = "jz4740-hwmon", diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c new file mode 100644 index 000000000000..e32226836fb4 --- /dev/null +++ b/drivers/mfd/lp3943.c @@ -0,0 +1,167 @@ +/* + * TI/National Semiconductor LP3943 MFD Core Driver + * + * Copyright 2013 Texas Instruments + * + * Author: Milo Kim <milo.kim@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver structure: + * LP3943 is an integrated device capable of driving 16 output channels. + * It can be used for a GPIO expander and PWM generators. + * + * LED control General usage for a device + * ___________ ____________________________ + * + * LP3943 MFD ---- GPIO expander leds-gpio eg) HW enable pin + * | + * --- PWM generator leds-pwm eg) PWM input + * + * Internal two PWM channels are used for LED dimming effect. + * And each output pin can be used as a GPIO as well. + * The LED functionality can work with GPIOs or PWMs. + * LEDs can be controlled with legacy leds-gpio(static brightness) or + * leds-pwm drivers(dynamic brightness control). + * Alternatively, it can be used for generic GPIO and PWM controller. + * For example, a GPIO is HW enable pin of a device. + * A PWM is input pin of a backlight device. + */ + +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/mfd/core.h> +#include <linux/mfd/lp3943.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/slab.h> + +#define LP3943_MAX_REGISTERS 0x09 + +/* Register configuration for pin MUX */ +static const struct lp3943_reg_cfg lp3943_mux_cfg[] = { + /* address, mask, shift */ + { LP3943_REG_MUX0, 0x03, 0 }, + { LP3943_REG_MUX0, 0x0C, 2 }, + { LP3943_REG_MUX0, 0x30, 4 }, + { LP3943_REG_MUX0, 0xC0, 6 }, + { LP3943_REG_MUX1, 0x03, 0 }, + { LP3943_REG_MUX1, 0x0C, 2 }, + { LP3943_REG_MUX1, 0x30, 4 }, + { LP3943_REG_MUX1, 0xC0, 6 }, + { LP3943_REG_MUX2, 0x03, 0 }, + { LP3943_REG_MUX2, 0x0C, 2 }, + { LP3943_REG_MUX2, 0x30, 4 }, + { LP3943_REG_MUX2, 0xC0, 6 }, + { LP3943_REG_MUX3, 0x03, 0 }, + { LP3943_REG_MUX3, 0x0C, 2 }, + { LP3943_REG_MUX3, 0x30, 4 }, + { LP3943_REG_MUX3, 0xC0, 6 }, +}; + +static struct mfd_cell lp3943_devs[] = { + { + .name = "lp3943-pwm", + .of_compatible = "ti,lp3943-pwm", + }, + { + .name = "lp3943-gpio", + .of_compatible = "ti,lp3943-gpio", + }, +}; + +int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read) +{ + int ret; + unsigned int val; + + ret = regmap_read(lp3943->regmap, reg, &val); + if (ret < 0) + return ret; + + *read = (u8)val; + return 0; +} +EXPORT_SYMBOL_GPL(lp3943_read_byte); + +int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data) +{ + return regmap_write(lp3943->regmap, reg, data); +} +EXPORT_SYMBOL_GPL(lp3943_write_byte); + +int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data) +{ + return regmap_update_bits(lp3943->regmap, reg, mask, data); +} +EXPORT_SYMBOL_GPL(lp3943_update_bits); + +static const struct regmap_config lp3943_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = LP3943_MAX_REGISTERS, +}; + +static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id) +{ + struct lp3943 *lp3943; + struct device *dev = &cl->dev; + + lp3943 = devm_kzalloc(dev, sizeof(*lp3943), GFP_KERNEL); + if (!lp3943) + return -ENOMEM; + + lp3943->regmap = devm_regmap_init_i2c(cl, &lp3943_regmap_config); + if (IS_ERR(lp3943->regmap)) + return PTR_ERR(lp3943->regmap); + + lp3943->pdata = dev_get_platdata(dev); + lp3943->dev = dev; + lp3943->mux_cfg = lp3943_mux_cfg; + i2c_set_clientdata(cl, lp3943); + + return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs), + NULL, 0, NULL); +} + +static int lp3943_remove(struct i2c_client *cl) +{ + struct lp3943 *lp3943 = i2c_get_clientdata(cl); + + mfd_remove_devices(lp3943->dev); + return 0; +} + +static const struct i2c_device_id lp3943_ids[] = { + { "lp3943", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lp3943_ids); + +#ifdef CONFIG_OF +static const struct of_device_id lp3943_of_match[] = { + { .compatible = "ti,lp3943", }, + { } +}; +MODULE_DEVICE_TABLE(of, lp3943_of_match); +#endif + +static struct i2c_driver lp3943_driver = { + .probe = lp3943_probe, + .remove = lp3943_remove, + .driver = { + .name = "lp3943", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(lp3943_of_match), + }, + .id_table = lp3943_ids, +}; + +module_i2c_driver(lp3943_driver); + +MODULE_DESCRIPTION("LP3943 MFD Core Driver"); +MODULE_AUTHOR("Milo Kim"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c index 0f1221911018..a30bc15fe5ba 100644 --- a/drivers/mfd/lp8788.c +++ b/drivers/mfd/lp8788.c @@ -71,7 +71,7 @@ static struct resource rtc_irqs[] = { }, }; -static struct mfd_cell lp8788_devs[] = { +static const struct mfd_cell lp8788_devs[] = { /* 4 bucks */ MFD_DEV_WITH_ID(BUCK, 1), MFD_DEV_WITH_ID(BUCK, 2), diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 37edf9e989b0..be93fa261ded 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -517,7 +517,7 @@ static struct lpc_ich_info lpc_chipset_info[] = { * pci_driver, because the I/O Controller Hub has also other * functions that probably will be registered by other drivers. */ -static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { +static const struct pci_device_id lpc_ich_ids[] = { { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH}, { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0}, { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2}, diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index fbfbf0b7f97a..3bb05c03c68d 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c @@ -76,7 +76,7 @@ static struct mfd_cell wdt_sch_cell = { .ignore_resource_conflicts = true, }; -static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = { +static const struct pci_device_id lpc_sch_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) }, diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c new file mode 100644 index 000000000000..ac514fb2b877 --- /dev/null +++ b/drivers/mfd/max14577.c @@ -0,0 +1,245 @@ +/* + * max14577.c - mfd core driver for the Maxim 14577 + * + * Copyright (C) 2013 Samsung Electrnoics + * Chanwoo Choi <cw00.choi@samsung.com> + * Krzysztof Kozlowski <k.kozlowski@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This driver is based on max8997.c + */ + +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/mfd/core.h> +#include <linux/mfd/max14577.h> +#include <linux/mfd/max14577-private.h> + +static struct mfd_cell max14577_devs[] = { + { .name = "max14577-muic", }, + { + .name = "max14577-regulator", + .of_compatible = "maxim,max14577-regulator", + }, + { .name = "max14577-charger", }, +}; + +static bool max14577_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3: + return true; + default: + break; + } + return false; +} + +static const struct regmap_config max14577_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = max14577_volatile_reg, + .max_register = MAX14577_REG_END, +}; + +static const struct regmap_irq max14577_irqs[] = { + /* INT1 interrupts */ + { .reg_offset = 0, .mask = INT1_ADC_MASK, }, + { .reg_offset = 0, .mask = INT1_ADCLOW_MASK, }, + { .reg_offset = 0, .mask = INT1_ADCERR_MASK, }, + /* INT2 interrupts */ + { .reg_offset = 1, .mask = INT2_CHGTYP_MASK, }, + { .reg_offset = 1, .mask = INT2_CHGDETRUN_MASK, }, + { .reg_offset = 1, .mask = INT2_DCDTMR_MASK, }, + { .reg_offset = 1, .mask = INT2_DBCHG_MASK, }, + { .reg_offset = 1, .mask = INT2_VBVOLT_MASK, }, + /* INT3 interrupts */ + { .reg_offset = 2, .mask = INT3_EOC_MASK, }, + { .reg_offset = 2, .mask = INT3_CGMBC_MASK, }, + { .reg_offset = 2, .mask = INT3_OVP_MASK, }, + { .reg_offset = 2, .mask = INT3_MBCCHGERR_MASK, }, +}; + +static const struct regmap_irq_chip max14577_irq_chip = { + .name = "max14577", + .status_base = MAX14577_REG_INT1, + .mask_base = MAX14577_REG_INTMASK1, + .mask_invert = 1, + .num_regs = 3, + .irqs = max14577_irqs, + .num_irqs = ARRAY_SIZE(max14577_irqs), +}; + +static int max14577_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct max14577 *max14577; + struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct device_node *np = i2c->dev.of_node; + u8 reg_data; + int ret = 0; + + if (np) { + pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + i2c->dev.platform_data = pdata; + } + + if (!pdata) { + dev_err(&i2c->dev, "No platform data found.\n"); + return -EINVAL; + } + + max14577 = devm_kzalloc(&i2c->dev, sizeof(*max14577), GFP_KERNEL); + if (!max14577) + return -ENOMEM; + + i2c_set_clientdata(i2c, max14577); + max14577->dev = &i2c->dev; + max14577->i2c = i2c; + max14577->irq = i2c->irq; + + max14577->regmap = devm_regmap_init_i2c(i2c, &max14577_regmap_config); + if (IS_ERR(max14577->regmap)) { + ret = PTR_ERR(max14577->regmap); + dev_err(max14577->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID, + ®_data); + if (ret) { + dev_err(max14577->dev, "Device not found on this channel: %d\n", + ret); + return ret; + } + max14577->vendor_id = ((reg_data & DEVID_VENDORID_MASK) >> + DEVID_VENDORID_SHIFT); + max14577->device_id = ((reg_data & DEVID_DEVICEID_MASK) >> + DEVID_DEVICEID_SHIFT); + dev_info(max14577->dev, "Device ID: 0x%x, vendor: 0x%x\n", + max14577->device_id, max14577->vendor_id); + + ret = regmap_add_irq_chip(max14577->regmap, max14577->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, + &max14577_irq_chip, + &max14577->irq_data); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", + max14577->irq, ret); + return ret; + } + + ret = mfd_add_devices(max14577->dev, -1, max14577_devs, + ARRAY_SIZE(max14577_devs), NULL, 0, + regmap_irq_get_domain(max14577->irq_data)); + if (ret < 0) + goto err_mfd; + + device_init_wakeup(max14577->dev, 1); + + return 0; + +err_mfd: + regmap_del_irq_chip(max14577->irq, max14577->irq_data); + + return ret; +} + +static int max14577_i2c_remove(struct i2c_client *i2c) +{ + struct max14577 *max14577 = i2c_get_clientdata(i2c); + + mfd_remove_devices(max14577->dev); + regmap_del_irq_chip(max14577->irq, max14577->irq_data); + + return 0; +} + +static const struct i2c_device_id max14577_i2c_id[] = { + { "max14577", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); + +static int max14577_suspend(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct max14577 *max14577 = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) { + enable_irq_wake(max14577->irq); + /* + * MUIC IRQ must be disabled during suspend if this is + * a wake up source because it will be handled before + * resuming I2C. + * + * When device is woken up from suspend (e.g. by ADC change), + * an interrupt occurs before resuming I2C bus controller. + * Interrupt handler tries to read registers but this read + * will fail because I2C is still suspended. + */ + disable_irq(max14577->irq); + } + + return 0; +} + +static int max14577_resume(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct max14577 *max14577 = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) { + disable_irq_wake(max14577->irq); + enable_irq(max14577->irq); + } + + return 0; +} + +static struct of_device_id max14577_dt_match[] = { + { .compatible = "maxim,max14577", }, + {}, +}; + +static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume); + +static struct i2c_driver max14577_i2c_driver = { + .driver = { + .name = "max14577", + .owner = THIS_MODULE, + .pm = &max14577_pm, + .of_match_table = max14577_dt_match, + }, + .probe = max14577_i2c_probe, + .remove = max14577_i2c_remove, + .id_table = max14577_i2c_id, +}; + +static int __init max14577_i2c_init(void) +{ + return i2c_add_driver(&max14577_i2c_driver); +} +subsys_initcall(max14577_i2c_init); + +static void __exit max14577_i2c_exit(void) +{ + i2c_del_driver(&max14577_i2c_driver); +} +module_exit(max14577_i2c_exit); + +MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); +MODULE_DESCRIPTION("MAXIM 14577 multi-function core driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 34520cbe8afb..f53d5823a3f7 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -35,7 +35,7 @@ #define I2C_ADDR_RTC (0x0C >> 1) -static struct mfd_cell max77686_devs[] = { +static const struct mfd_cell max77686_devs[] = { { .name = "max77686-pmic", }, { .name = "max77686-rtc", }, { .name = "max77686-clk", }, @@ -104,7 +104,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686->irq_gpio = pdata->irq_gpio; max77686->irq = i2c->irq; - max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); + max77686->regmap = devm_regmap_init_i2c(i2c, &max77686_regmap_config); if (IS_ERR(max77686->regmap)) { ret = PTR_ERR(max77686->regmap); dev_err(max77686->dev, "Failed to allocate register map: %d\n", diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 9f92463f4f7e..e0859987ab6b 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -41,7 +41,7 @@ #define I2C_ADDR_MUIC (0x4A >> 1) #define I2C_ADDR_HAPTIC (0x90 >> 1) -static struct mfd_cell max77693_devs[] = { +static const struct mfd_cell max77693_devs[] = { { .name = "max77693-pmic", }, { .name = "max77693-charger", }, { .name = "max77693-flash", }, @@ -107,6 +107,12 @@ static const struct regmap_config max77693_regmap_config = { .max_register = MAX77693_PMIC_REG_END, }; +static const struct regmap_config max77693_regmap_muic_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX77693_MUIC_REG_END, +}; + static int max77693_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -153,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, * before call max77693-muic probe() function. */ max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, - &max77693_regmap_config); + &max77693_regmap_muic_config); if (IS_ERR(max77693->regmap_muic)) { ret = PTR_ERR(max77693->regmap_muic); dev_err(max77693->dev, diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c index 3bbfedc07f41..07740314b29d 100644 --- a/drivers/mfd/max8907.c +++ b/drivers/mfd/max8907.c @@ -22,7 +22,7 @@ #include <linux/regmap.h> #include <linux/slab.h> -static struct mfd_cell max8907_cells[] = { +static const struct mfd_cell max8907_cells[] = { { .name = "max8907-regulator", }, { .name = "max8907-rtc", }, }; diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index f0cc40296d8c..f3faf0c45ddd 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -45,7 +45,7 @@ static struct resource touch_resources[] = { }, }; -static struct mfd_cell touch_devs[] = { +static const struct mfd_cell touch_devs[] = { { .name = "max8925-touch", .num_resources = 1, @@ -63,7 +63,7 @@ static struct resource power_supply_resources[] = { }, }; -static struct mfd_cell power_devs[] = { +static const struct mfd_cell power_devs[] = { { .name = "max8925-power", .num_resources = 1, @@ -81,7 +81,7 @@ static struct resource rtc_resources[] = { }, }; -static struct mfd_cell rtc_devs[] = { +static const struct mfd_cell rtc_devs[] = { { .name = "max8925-rtc", .num_resources = 1, @@ -104,7 +104,7 @@ static struct resource onkey_resources[] = { }, }; -static struct mfd_cell onkey_devs[] = { +static const struct mfd_cell onkey_devs[] = { { .name = "max8925-onkey", .num_resources = 2, diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 791aea3e96ce..be88a3bf7b85 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -40,7 +40,7 @@ #define I2C_ADDR_RTC (0x0C >> 1) #define I2C_ADDR_HAPTIC (0x90 >> 1) -static struct mfd_cell max8997_devs[] = { +static const struct mfd_cell max8997_devs[] = { { .name = "max8997-pmic", }, { .name = "max8997-rtc", }, { .name = "max8997-battery", }, @@ -133,7 +133,6 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) } EXPORT_SYMBOL_GPL(max8997_update_reg); -#ifdef CONFIG_OF /* * Only the common platform data elements for max8997 are parsed here from the * device tree. Other sub-modules of max8997 such as pmic, rtc and others have @@ -164,24 +163,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( return pd; } -#else -static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( - struct device *dev) -{ - return 0; -} -#endif static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { -#ifdef CONFIG_OF - if (i2c->dev.of_node) { + if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node); return (int)match->data; } -#endif return (int)id->driver_data; } @@ -203,7 +193,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, max8997->type = max8997_i2c_get_driver_data(i2c, id); max8997->irq = i2c->irq; - if (max8997->dev->of_node) { + if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) { pdata = max8997_i2c_parse_dt_pdata(max8997->dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); @@ -228,18 +218,19 @@ static int max8997_i2c_probe(struct i2c_client *i2c, max8997_irq_init(max8997); - mfd_add_devices(max8997->dev, -1, max8997_devs, + ret = mfd_add_devices(max8997->dev, -1, max8997_devs, ARRAY_SIZE(max8997_devs), NULL, 0, NULL); + if (ret < 0) { + dev_err(max8997->dev, "failed to add MFD devices %d\n", ret); + goto err_mfd; + } /* * TODO: enable others (flash, muic, rtc, battery, ...) and * check the return value */ - if (ret < 0) - goto err_mfd; - /* MAX8997 has a power button input. */ device_init_wakeup(max8997->dev, pdata->wakeup); diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index fe6332dcabee..612ca404e150 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -37,7 +37,7 @@ #define RTC_I2C_ADDR (0x0c >> 1) -static struct mfd_cell max8998_devs[] = { +static const struct mfd_cell max8998_devs[] = { { .name = "max8998-pmic", }, { @@ -47,7 +47,7 @@ static struct mfd_cell max8998_devs[] = { }, }; -static struct mfd_cell lp3974_devs[] = { +static const struct mfd_cell lp3974_devs[] = { { .name = "lp3974-pmic", }, { @@ -175,7 +175,7 @@ static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c, if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(max8998_dt_match, i2c->dev.of_node); - return (int)match->data; + return (int)(long)match->data; } return (int)id->driver_data; diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index dbbf8ee3f592..06e64b6fcb89 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -158,9 +158,6 @@ int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val) { int ret; - if (offset > MC13XXX_NUMREGS) - return -EINVAL; - ret = regmap_read(mc13xxx->regmap, offset, val); dev_vdbg(mc13xxx->dev, "[0x%02x] -> 0x%06x\n", offset, *val); @@ -172,7 +169,7 @@ int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val) { dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val); - if (offset > MC13XXX_NUMREGS || val > 0xffffff) + if (val >= BIT(24)) return -EINVAL; return regmap_write(mc13xxx->regmap, offset, val); @@ -639,42 +636,36 @@ static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx) } #endif -int mc13xxx_common_init(struct mc13xxx *mc13xxx, - struct mc13xxx_platform_data *pdata, int irq) +int mc13xxx_common_init(struct device *dev) { + struct mc13xxx_platform_data *pdata = dev_get_platdata(dev); + struct mc13xxx *mc13xxx = dev_get_drvdata(dev); int ret; u32 revision; - mc13xxx_lock(mc13xxx); + mc13xxx->dev = dev; ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision); if (ret) - goto err_revision; + return ret; mc13xxx->variant->print_revision(mc13xxx, revision); /* mask all irqs */ ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff); if (ret) - goto err_mask; + return ret; ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff); if (ret) - goto err_mask; + return ret; - ret = request_threaded_irq(irq, NULL, mc13xxx_irq_thread, + ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx); - - if (ret) { -err_mask: -err_revision: - mc13xxx_unlock(mc13xxx); + if (ret) return ret; - } - mc13xxx->irq = irq; - - mc13xxx_unlock(mc13xxx); + mutex_init(&mc13xxx->lock); if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata) mc13xxx->flags = pdata->flags; @@ -710,13 +701,17 @@ err_revision: } EXPORT_SYMBOL_GPL(mc13xxx_common_init); -void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx) +int mc13xxx_common_exit(struct device *dev) { + struct mc13xxx *mc13xxx = dev_get_drvdata(dev); + free_irq(mc13xxx->irq, mc13xxx); + mfd_remove_devices(dev); + mutex_destroy(&mc13xxx->lock); - mfd_remove_devices(mc13xxx->dev); + return 0; } -EXPORT_SYMBOL_GPL(mc13xxx_common_cleanup); +EXPORT_SYMBOL_GPL(mc13xxx_common_exit); MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC"); MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index 898bd335cd8e..ae3addb153a2 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -10,7 +10,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/mutex.h> #include <linux/mfd/core.h> #include <linux/mfd/mc13xxx.h> #include <linux/of.h> @@ -60,7 +59,6 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mc13xxx *mc13xxx; - struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev); int ret; mc13xxx = devm_kzalloc(&client->dev, sizeof(*mc13xxx), GFP_KERNEL); @@ -69,15 +67,13 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, dev_set_drvdata(&client->dev, mc13xxx); - mc13xxx->dev = &client->dev; - mutex_init(&mc13xxx->lock); + mc13xxx->irq = client->irq; mc13xxx->regmap = devm_regmap_init_i2c(client, &mc13xxx_regmap_i2c_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); - dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", - ret); + dev_err(&client->dev, "Failed to initialize regmap: %d\n", ret); return ret; } @@ -89,18 +85,12 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, mc13xxx->variant = (void *)id->driver_data; } - ret = mc13xxx_common_init(mc13xxx, pdata, client->irq); - - return ret; + return mc13xxx_common_init(&client->dev); } static int mc13xxx_i2c_remove(struct i2c_client *client) { - struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev); - - mc13xxx_common_cleanup(mc13xxx); - - return 0; + return mc13xxx_common_exit(&client->dev); } static struct i2c_driver mc13xxx_i2c_driver = { diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 5f14ef6693c2..38ab67829791 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/mfd/core.h> #include <linux/mfd/mc13xxx.h> @@ -129,27 +128,24 @@ static struct regmap_bus regmap_mc13xxx_bus = { static int mc13xxx_spi_probe(struct spi_device *spi) { struct mc13xxx *mc13xxx; - struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev); int ret; mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; - spi_set_drvdata(spi, mc13xxx); + dev_set_drvdata(&spi->dev, mc13xxx); + spi->mode = SPI_MODE_0 | SPI_CS_HIGH; - mc13xxx->dev = &spi->dev; - mutex_init(&mc13xxx->lock); + mc13xxx->irq = spi->irq; mc13xxx->regmap = devm_regmap_init(&spi->dev, ®map_mc13xxx_bus, &spi->dev, &mc13xxx_regmap_spi_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); - dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", - ret); - spi_set_drvdata(spi, NULL); + dev_err(&spi->dev, "Failed to initialize regmap: %d\n", ret); return ret; } @@ -164,16 +160,12 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->variant = (void *)id_entry->driver_data; } - return mc13xxx_common_init(mc13xxx, pdata, spi->irq); + return mc13xxx_common_init(&spi->dev); } static int mc13xxx_spi_remove(struct spi_device *spi) { - struct mc13xxx *mc13xxx = spi_get_drvdata(spi); - - mc13xxx_common_cleanup(mc13xxx); - - return 0; + return mc13xxx_common_exit(&spi->dev); } static struct spi_driver mc13xxx_spi_driver = { diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h index 460ec5c7b18c..ae7f1659f5d1 100644 --- a/drivers/mfd/mc13xxx.h +++ b/drivers/mfd/mc13xxx.h @@ -43,9 +43,7 @@ struct mc13xxx { int adcflags; }; -int mc13xxx_common_init(struct mc13xxx *mc13xxx, - struct mc13xxx_platform_data *pdata, int irq); - -void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx); +int mc13xxx_common_init(struct device *dev); +int mc13xxx_common_exit(struct device *dev); #endif /* __DRIVERS_MFD_MC13XXX_H */ diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 142650fdc058..90b630ccc8bc 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -121,22 +121,22 @@ static u64 usbhs_dmamask = DMA_BIT_MASK(32); static inline void usbhs_write(void __iomem *base, u32 reg, u32 val) { - __raw_writel(val, base + reg); + writel_relaxed(val, base + reg); } static inline u32 usbhs_read(void __iomem *base, u32 reg) { - return __raw_readl(base + reg); + return readl_relaxed(base + reg); } static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val) { - __raw_writeb(val, base + reg); + writeb_relaxed(val, base + reg); } static inline u8 usbhs_readb(void __iomem *base, u8 reg) { - return __raw_readb(base + reg); + return readb_relaxed(base + reg); } /*-------------------------------------------------------------------------*/ diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 0d946ae14453..5ee50f779ef6 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -121,22 +121,22 @@ static DEFINE_SPINLOCK(tll_lock); /* serialize access to tll_dev */ static inline void usbtll_write(void __iomem *base, u32 reg, u32 val) { - __raw_writel(val, base + reg); + writel_relaxed(val, base + reg); } static inline u32 usbtll_read(void __iomem *base, u32 reg) { - return __raw_readl(base + reg); + return readl_relaxed(base + reg); } static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val) { - __raw_writeb(val, base + reg); + writeb_relaxed(val, base + reg); } static inline u8 usbtll_readb(void __iomem *base, u8 reg) { - return __raw_readb(base + reg); + return readb_relaxed(base + reg); } /*-------------------------------------------------------------------------*/ @@ -333,21 +333,17 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata) unsigned reg; struct usbtll_omap *tll; - spin_lock(&tll_lock); - - if (!tll_dev) { - spin_unlock(&tll_lock); + if (!tll_dev) return -ENODEV; - } - tll = dev_get_drvdata(tll_dev); + pm_runtime_get_sync(tll_dev); + spin_lock(&tll_lock); + tll = dev_get_drvdata(tll_dev); needs_tll = false; for (i = 0; i < tll->nch; i++) needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]); - pm_runtime_get_sync(tll_dev); - if (needs_tll) { void __iomem *base = tll->base; @@ -398,9 +394,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata) } } - pm_runtime_put_sync(tll_dev); - spin_unlock(&tll_lock); + pm_runtime_put_sync(tll_dev); return 0; } @@ -411,17 +406,14 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata) int i; struct usbtll_omap *tll; - spin_lock(&tll_lock); - - if (!tll_dev) { - spin_unlock(&tll_lock); + if (!tll_dev) return -ENODEV; - } - - tll = dev_get_drvdata(tll_dev); pm_runtime_get_sync(tll_dev); + spin_lock(&tll_lock); + tll = dev_get_drvdata(tll_dev); + for (i = 0; i < tll->nch; i++) { if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { int r; @@ -448,13 +440,10 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata) int i; struct usbtll_omap *tll; - spin_lock(&tll_lock); - - if (!tll_dev) { - spin_unlock(&tll_lock); + if (!tll_dev) return -ENODEV; - } + spin_lock(&tll_lock); tll = dev_get_drvdata(tll_dev); for (i = 0; i < tll->nch; i++) { @@ -464,9 +453,8 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata) } } - pm_runtime_put_sync(tll_dev); - spin_unlock(&tll_lock); + pm_runtime_put_sync(tll_dev); return 0; } diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index 346330176afc..df276ad9f40b 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -74,7 +74,7 @@ static struct deepsleep_control_data deepsleep_data[] = { #define EXT_PWR_REQ \ (RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL) -static struct mfd_cell rc5t583_subdevs[] = { +static const struct mfd_cell rc5t583_subdevs[] = { {.name = "rc5t583-gpio",}, {.name = "rc5t583-regulator",}, {.name = "rc5t583-rtc", }, diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 21b7bef73507..d346146249a2 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c @@ -56,7 +56,7 @@ static struct resource rdc321x_gpio_resources[] = { } }; -static struct mfd_cell rdc321x_sb_cells[] = { +static const struct mfd_cell rdc321x_sb_cells[] = { { .name = "rdc321x-wdt", .resources = rdc321x_wdt_resource, @@ -96,7 +96,7 @@ static void rdc321x_sb_remove(struct pci_dev *pdev) mfd_remove_devices(&pdev->dev); } -static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = { +static const struct pci_device_id rdc321x_sb_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) }, {} }; diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c index a1830986eeb7..c8f345f7e9a2 100644 --- a/drivers/mfd/retu-mfd.c +++ b/drivers/mfd/retu-mfd.c @@ -55,7 +55,7 @@ static struct resource retu_pwrbutton_res[] = { }, }; -static struct mfd_cell retu_devs[] = { +static const struct mfd_cell retu_devs[] = { { .name = "retu-wdt" }, @@ -94,7 +94,7 @@ static struct resource tahvo_usb_res[] = { }, }; -static struct mfd_cell tahvo_devs[] = { +static const struct mfd_cell tahvo_devs[] = { { .name = "tahvo-usb", .resources = tahvo_usb_res, @@ -122,7 +122,7 @@ static const struct retu_data { char *chip_name; char *companion_name; struct regmap_irq_chip *irq_chip; - struct mfd_cell *children; + const struct mfd_cell *children; int nchildren; } retu_data[] = { [0] = { diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 52801351864d..fdd34c883d86 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -49,8 +49,8 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr) static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr) { - u32 reg1; - u8 reg3; + u32 reg1 = 0; + u8 reg3 = 0; rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®1); dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1); @@ -71,7 +71,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr) static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) { - u32 reg; + u32 reg = 0; rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); @@ -191,24 +191,25 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) BPP_LDO_POWB, BPP_LDO_SUSPEND); } -static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage, + int bpp_tuned18_shift, int bpp_asic_1v8) { u8 mask, val; int err; - mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; + mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK; if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_register(pcr, SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); if (err < 0) return err; - val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; + val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_register(pcr, SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); if (err < 0) return err; - val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; + val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8; } else { return -EINVAL; } @@ -216,6 +217,18 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); } +static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + return rtl8411_do_switch_output_voltage(pcr, voltage, + BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8); +} + +static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + return rtl8411_do_switch_output_voltage(pcr, voltage, + BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0); +} + static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) { unsigned int card_exist; @@ -295,6 +308,22 @@ static const struct pcr_ops rtl8411_pcr_ops = { .force_power_down = rtl8411_force_power_down, }; +static const struct pcr_ops rtl8402_pcr_ops = { + .fetch_vendor_settings = rtl8411_fetch_vendor_settings, + .extra_init_hw = rtl8411_extra_init_hw, + .optimize_phy = NULL, + .turn_on_led = rtl8411_turn_on_led, + .turn_off_led = rtl8411_turn_off_led, + .enable_auto_blink = rtl8411_enable_auto_blink, + .disable_auto_blink = rtl8411_disable_auto_blink, + .card_power_on = rtl8411_card_power_on, + .card_power_off = rtl8411_card_power_off, + .switch_output_voltage = rtl8402_switch_output_voltage, + .cd_deglitch = rtl8411_cd_deglitch, + .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, + .force_power_down = rtl8411_force_power_down, +}; + static const struct pcr_ops rtl8411b_pcr_ops = { .fetch_vendor_settings = rtl8411b_fetch_vendor_settings, .extra_init_hw = rtl8411b_extra_init_hw, @@ -441,12 +470,10 @@ static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = { 0, }; -void rtl8411_init_params(struct rtsx_pcr *pcr) +static void rtl8411_init_common_params(struct rtsx_pcr *pcr) { pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; pcr->num_slots = 2; - pcr->ops = &rtl8411_pcr_ops; - pcr->flags = 0; pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT; pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; @@ -454,47 +481,29 @@ void rtl8411_init_params(struct rtsx_pcr *pcr) pcr->aspm_en = ASPM_L1_EN; pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14); pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10); - pcr->ic_version = rtl8411_get_ic_version(pcr); - pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl; - pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl; - pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl; - pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl; +} + +void rtl8411_init_params(struct rtsx_pcr *pcr) +{ + rtl8411_init_common_params(pcr); + pcr->ops = &rtl8411_pcr_ops; + set_pull_ctrl_tables(pcr, rtl8411); } void rtl8411b_init_params(struct rtsx_pcr *pcr) { - pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; - pcr->num_slots = 2; + rtl8411_init_common_params(pcr); pcr->ops = &rtl8411b_pcr_ops; + if (rtl8411b_is_qfn48(pcr)) + set_pull_ctrl_tables(pcr, rtl8411b_qfn48); + else + set_pull_ctrl_tables(pcr, rtl8411b_qfn64); +} - pcr->flags = 0; - pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT; - pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; - pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; - pcr->aspm_en = ASPM_L1_EN; - pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14); - pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10); - - pcr->ic_version = rtl8411_get_ic_version(pcr); - - if (rtl8411b_is_qfn48(pcr)) { - pcr->sd_pull_ctl_enable_tbl = - rtl8411b_qfn48_sd_pull_ctl_enable_tbl; - pcr->sd_pull_ctl_disable_tbl = - rtl8411b_qfn48_sd_pull_ctl_disable_tbl; - pcr->ms_pull_ctl_enable_tbl = - rtl8411b_qfn48_ms_pull_ctl_enable_tbl; - pcr->ms_pull_ctl_disable_tbl = - rtl8411b_qfn48_ms_pull_ctl_disable_tbl; - } else { - pcr->sd_pull_ctl_enable_tbl = - rtl8411b_qfn64_sd_pull_ctl_enable_tbl; - pcr->sd_pull_ctl_disable_tbl = - rtl8411b_qfn64_sd_pull_ctl_disable_tbl; - pcr->ms_pull_ctl_enable_tbl = - rtl8411b_qfn64_ms_pull_ctl_enable_tbl; - pcr->ms_pull_ctl_disable_tbl = - rtl8411b_qfn64_ms_pull_ctl_disable_tbl; - } +void rtl8402_init_params(struct rtsx_pcr *pcr) +{ + rtl8411_init_common_params(pcr); + pcr->ops = &rtl8402_pcr_ops; + set_pull_ctrl_tables(pcr, rtl8411); } diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 11e20afbdcac..1d15735f9ef9 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -50,13 +50,14 @@ static struct mfd_cell rtsx_pcr_cells[] = { }, }; -static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = { +static const struct pci_device_id rtsx_pci_ids[] = { { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { 0, } }; @@ -1061,6 +1062,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) case 0x5287: rtl8411b_init_params(pcr); break; + + case 0x5286: + rtl8402_init_params(pcr); + break; } dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", @@ -1228,8 +1233,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev) pcr->remove_pci = true; - cancel_delayed_work(&pcr->carddet_work); - cancel_delayed_work(&pcr->idle_work); + /* Disable interrupts at the pcr level */ + spin_lock_irq(&pcr->lock); + rtsx_pci_writel(pcr, RTSX_BIER, 0); + pcr->bier = 0; + spin_unlock_irq(&pcr->lock); + + cancel_delayed_work_sync(&pcr->carddet_work); + cancel_delayed_work_sync(&pcr->idle_work); mfd_remove_devices(&pcidev->dev); diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index 947e79b05ceb..07e4c2ebf05a 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -30,6 +30,7 @@ void rts5209_init_params(struct rtsx_pcr *pcr); void rts5229_init_params(struct rtsx_pcr *pcr); void rtl8411_init_params(struct rtsx_pcr *pcr); +void rtl8402_init_params(struct rtsx_pcr *pcr); void rts5227_init_params(struct rtsx_pcr *pcr); void rts5249_init_params(struct rtsx_pcr *pcr); void rtl8411b_init_params(struct rtsx_pcr *pcr); @@ -63,4 +64,12 @@ static inline u8 map_sd_drive(int idx) #define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07) #define rtl8411b_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x03) +#define set_pull_ctrl_tables(pcr, __device) \ +do { \ + pcr->sd_pull_ctl_enable_tbl = __device##_sd_pull_ctl_enable_tbl; \ + pcr->sd_pull_ctl_disable_tbl = __device##_sd_pull_ctl_disable_tbl; \ + pcr->ms_pull_ctl_enable_tbl = __device##_ms_pull_ctl_enable_tbl; \ + pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \ +} while (0) + #endif diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 54cc25546592..e4671088f075 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -31,7 +31,7 @@ #include <linux/mfd/samsung/s5m8767.h> #include <linux/regmap.h> -static struct mfd_cell s5m8751_devs[] = { +static const struct mfd_cell s5m8751_devs[] = { { .name = "s5m8751-pmic", }, { @@ -41,7 +41,7 @@ static struct mfd_cell s5m8751_devs[] = { }, }; -static struct mfd_cell s5m8763_devs[] = { +static const struct mfd_cell s5m8763_devs[] = { { .name = "s5m8763-pmic", }, { @@ -51,15 +51,17 @@ static struct mfd_cell s5m8763_devs[] = { }, }; -static struct mfd_cell s5m8767_devs[] = { +static const struct mfd_cell s5m8767_devs[] = { { .name = "s5m8767-pmic", }, { .name = "s5m-rtc", - }, + }, { + .name = "s5m8767-clk", + } }; -static struct mfd_cell s2mps11_devs[] = { +static const struct mfd_cell s2mps11_devs[] = { { .name = "s2mps11-pmic", }, { @@ -134,12 +136,12 @@ static bool s5m8763_volatile(struct device *dev, unsigned int reg) } } -static struct regmap_config sec_regmap_config = { +static const struct regmap_config sec_regmap_config = { .reg_bits = 8, .val_bits = 8, }; -static struct regmap_config s2mps11_regmap_config = { +static const struct regmap_config s2mps11_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -148,7 +150,7 @@ static struct regmap_config s2mps11_regmap_config = { .cache_type = REGCACHE_FLAT, }; -static struct regmap_config s5m8763_regmap_config = { +static const struct regmap_config s5m8763_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -157,7 +159,7 @@ static struct regmap_config s5m8763_regmap_config = { .cache_type = REGCACHE_FLAT, }; -static struct regmap_config s5m8767_regmap_config = { +static const struct regmap_config s5m8767_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -204,7 +206,7 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( struct device *dev) { - return 0; + return NULL; } #endif @@ -323,6 +325,8 @@ static int sec_pmic_probe(struct i2c_client *i2c, if (ret) goto err; + device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); + return ret; err: @@ -341,6 +345,43 @@ static int sec_pmic_remove(struct i2c_client *i2c) return 0; } +static int sec_pmic_suspend(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) { + enable_irq_wake(sec_pmic->irq); + /* + * PMIC IRQ must be disabled during suspend for RTC alarm + * to work properly. + * When device is woken up from suspend by RTC Alarm, an + * interrupt occurs before resuming I2C bus controller. + * The interrupt is handled by regmap_irq_thread which tries + * to read RTC registers. This read fails (I2C is still + * suspended) and RTC Alarm interrupt is disabled. + */ + disable_irq(sec_pmic->irq); + } + + return 0; +} + +static int sec_pmic_resume(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) { + disable_irq_wake(sec_pmic->irq); + enable_irq(sec_pmic->irq); + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); + static const struct i2c_device_id sec_pmic_id[] = { { "sec_pmic", 0 }, { } @@ -351,6 +392,7 @@ static struct i2c_driver sec_pmic_driver = { .driver = { .name = "sec_pmic", .owner = THIS_MODULE, + .pm = &sec_pmic_pm_ops, .of_match_table = of_match_ptr(sec_dt_match), }, .probe = sec_pmic_probe, diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index b441b1be27cb..4de494f51d40 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -22,7 +22,7 @@ #include <linux/mfd/samsung/s5m8763.h> #include <linux/mfd/samsung/s5m8767.h> -static struct regmap_irq s2mps11_irqs[] = { +static const struct regmap_irq s2mps11_irqs[] = { [S2MPS11_IRQ_PWRONF] = { .reg_offset = 0, .mask = S2MPS11_IRQ_PWRONF_MASK, @@ -90,7 +90,7 @@ static struct regmap_irq s2mps11_irqs[] = { }; -static struct regmap_irq s5m8767_irqs[] = { +static const struct regmap_irq s5m8767_irqs[] = { [S5M8767_IRQ_PWRR] = { .reg_offset = 0, .mask = S5M8767_IRQ_PWRR_MASK, @@ -161,7 +161,7 @@ static struct regmap_irq s5m8767_irqs[] = { }, }; -static struct regmap_irq s5m8763_irqs[] = { +static const struct regmap_irq s5m8763_irqs[] = { [S5M8763_IRQ_DCINF] = { .reg_offset = 0, .mask = S5M8763_IRQ_DCINF_MASK, @@ -236,7 +236,7 @@ static struct regmap_irq s5m8763_irqs[] = { }, }; -static struct regmap_irq_chip s2mps11_irq_chip = { +static const struct regmap_irq_chip s2mps11_irq_chip = { .name = "s2mps11", .irqs = s2mps11_irqs, .num_irqs = ARRAY_SIZE(s2mps11_irqs), @@ -246,7 +246,7 @@ static struct regmap_irq_chip s2mps11_irq_chip = { .ack_base = S2MPS11_REG_INT1, }; -static struct regmap_irq_chip s5m8767_irq_chip = { +static const struct regmap_irq_chip s5m8767_irq_chip = { .name = "s5m8767", .irqs = s5m8767_irqs, .num_irqs = ARRAY_SIZE(s5m8767_irqs), @@ -256,7 +256,7 @@ static struct regmap_irq_chip s5m8767_irq_chip = { .ack_base = S5M8767_REG_INT1, }; -static struct regmap_irq_chip s5m8763_irq_chip = { +static const struct regmap_irq_chip s5m8763_irq_chip = { .name = "s5m8763", .irqs = s5m8763_irqs, .num_irqs = ARRAY_SIZE(s5m8763_irqs), diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index c2c8c91c6c7b..e7dc441a8f8a 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1710,7 +1710,7 @@ static int sm501_plat_remove(struct platform_device *dev) return 0; } -static DEFINE_PCI_DEVICE_TABLE(sm501_pci_tbl) = { +static const struct pci_device_id sm501_pci_tbl[] = { { 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index 102a22844297..b78942ed4c67 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c @@ -65,13 +65,19 @@ #define SSBI_TIMEOUT_US 100 +enum ssbi_controller_type { + MSM_SBI_CTRL_SSBI = 0, + MSM_SBI_CTRL_SSBI2, + MSM_SBI_CTRL_PMIC_ARBITER, +}; + struct ssbi { struct device *slave; void __iomem *base; spinlock_t lock; enum ssbi_controller_type controller_type; int (*read)(struct ssbi *, u16 addr, u8 *buf, int len); - int (*write)(struct ssbi *, u16 addr, u8 *buf, int len); + int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len); }; #define to_ssbi(dev) platform_get_drvdata(to_platform_device(dev)) @@ -140,7 +146,7 @@ err: } static int -ssbi_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) +ssbi_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len) { int ret = 0; @@ -217,7 +223,7 @@ err: } static int -ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) +ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len) { u32 cmd; int ret = 0; @@ -249,7 +255,7 @@ int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len) } EXPORT_SYMBOL_GPL(ssbi_read); -int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len) +int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len) { struct ssbi *ssbi = to_ssbi(dev); unsigned long flags; @@ -311,7 +317,7 @@ static int ssbi_probe(struct platform_device *pdev) return of_platform_populate(np, NULL, NULL, &pdev->dev); } -static struct of_device_id ssbi_match_table[] = { +static const struct of_device_id ssbi_match_table[] = { { .compatible = "qcom,ssbi" }, {} }; diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c index 65c6fa671acb..5b72db07d9de 100644 --- a/drivers/mfd/sta2x11-mfd.c +++ b/drivers/mfd/sta2x11-mfd.c @@ -339,7 +339,7 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev, regmap_config->cache_type = REGCACHE_NONE; mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index], regmap_config); - WARN_ON(!mfd->regmap[index]); + WARN_ON(IS_ERR(mfd->regmap[index])); return 0; } @@ -529,7 +529,7 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev) { int err; - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); err = pci_enable_device(pdev); if (err) return err; @@ -642,7 +642,7 @@ err_disable: return err; } -static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = { +static const struct pci_device_id sta2x11_mfd_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)}, {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)}, {0,}, diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index fff63a41862c..42ccd0544513 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -297,14 +297,14 @@ static struct resource stmpe_gpio_resources[] = { }, }; -static struct mfd_cell stmpe_gpio_cell = { +static const struct mfd_cell stmpe_gpio_cell = { .name = "stmpe-gpio", .of_compatible = "st,stmpe-gpio", .resources = stmpe_gpio_resources, .num_resources = ARRAY_SIZE(stmpe_gpio_resources), }; -static struct mfd_cell stmpe_gpio_cell_noirq = { +static const struct mfd_cell stmpe_gpio_cell_noirq = { .name = "stmpe-gpio", .of_compatible = "st,stmpe-gpio", /* gpio cell resources consist of an irq only so no resources here */ @@ -325,7 +325,7 @@ static struct resource stmpe_keypad_resources[] = { }, }; -static struct mfd_cell stmpe_keypad_cell = { +static const struct mfd_cell stmpe_keypad_cell = { .name = "stmpe-keypad", .of_compatible = "st,stmpe-keypad", .resources = stmpe_keypad_resources, @@ -409,7 +409,7 @@ static struct resource stmpe_ts_resources[] = { }, }; -static struct mfd_cell stmpe_ts_cell = { +static const struct mfd_cell stmpe_ts_cell = { .name = "stmpe-ts", .of_compatible = "st,stmpe-ts", .resources = stmpe_ts_resources, @@ -1064,7 +1064,7 @@ static int stmpe_chip_init(struct stmpe *stmpe) return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); } -static int stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell) +static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell) { return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, NULL, stmpe->irq_base, stmpe->domain); diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h index ff2b09ba8797..6639f1b0fef5 100644 --- a/drivers/mfd/stmpe.h +++ b/drivers/mfd/stmpe.h @@ -38,7 +38,7 @@ static inline void stmpe_dump_bytes(const char *str, const void *buf, * enable and altfunc callbacks */ struct stmpe_variant_block { - struct mfd_cell *cell; + const struct mfd_cell *cell; int irq; enum stmpe_block block; }; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 87ea51dc6234..2cf636c267d9 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -155,7 +155,7 @@ static struct resource keypad_resources[] = { }, }; -static struct mfd_cell tc3589x_dev_gpio[] = { +static const struct mfd_cell tc3589x_dev_gpio[] = { { .name = "tc3589x-gpio", .num_resources = ARRAY_SIZE(gpio_resources), @@ -164,7 +164,7 @@ static struct mfd_cell tc3589x_dev_gpio[] = { }, }; -static struct mfd_cell tc3589x_dev_keypad[] = { +static const struct mfd_cell tc3589x_dev_keypad[] = { { .name = "tc3589x-keypad", .num_resources = ARRAY_SIZE(keypad_resources), diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index acd0f3a41044..591a331d8d83 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -126,7 +126,7 @@ static struct tmio_mmc_data tc6387xb_mmc_data = { /*--------------------------------------------------------------------------*/ -static struct mfd_cell tc6387xb_cells[] = { +static const struct mfd_cell tc6387xb_cells[] = { [TC6387XB_CELL_MMC] = { .name = "tmio-mmc", .enable = tc6387xb_mmc_enable, diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 88718abfb9ba..d4e860413bb5 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -24,6 +24,7 @@ #include <linux/pm_runtime.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/sched.h> #include <linux/mfd/ti_am335x_tscadc.h> @@ -48,32 +49,79 @@ static const struct regmap_config tscadc_regmap_config = { .val_bits = 32, }; -void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc) +void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) { - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + unsigned long flags; + + spin_lock_irqsave(&tsadc->reg_lock, flags); + tsadc->reg_se_cache = val; + if (tsadc->adc_waiting) + wake_up(&tsadc->reg_se_wait); + else if (!tsadc->adc_in_use) + tscadc_writel(tsadc, REG_SE, val); + + spin_unlock_irqrestore(&tsadc->reg_lock, flags); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache); + +static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) +{ + DEFINE_WAIT(wait); + u32 reg; + + /* + * disable TSC steps so it does not run while the ADC is using it. If + * write 0 while it is running (it just started or was already running) + * then it completes all steps that were enabled and stops then. + */ + tscadc_writel(tsadc, REG_SE, 0); + reg = tscadc_readl(tsadc, REG_ADCFSM); + if (reg & SEQ_STATUS) { + tsadc->adc_waiting = true; + prepare_to_wait(&tsadc->reg_se_wait, &wait, + TASK_UNINTERRUPTIBLE); + spin_unlock_irq(&tsadc->reg_lock); + + schedule(); + + spin_lock_irq(&tsadc->reg_lock); + finish_wait(&tsadc->reg_se_wait, &wait); + + reg = tscadc_readl(tsadc, REG_ADCFSM); + WARN_ON(reg & SEQ_STATUS); + tsadc->adc_waiting = false; + } + tsadc->adc_in_use = true; +} + +void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock_irq(&tsadc->reg_lock); + am335x_tscadc_need_adc(tsadc); + + tscadc_writel(tsadc, REG_SE, val); + spin_unlock_irq(&tsadc->reg_lock); } -EXPORT_SYMBOL_GPL(am335x_tsc_se_update); +EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); -void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc) { unsigned long flags; spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE); - tsadc->reg_se_cache |= val; - am335x_tsc_se_update(tsadc); + tsadc->adc_in_use = false; + tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); spin_unlock_irqrestore(&tsadc->reg_lock, flags); } -EXPORT_SYMBOL_GPL(am335x_tsc_se_set); +EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) { unsigned long flags; spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE); tsadc->reg_se_cache &= ~val; - am335x_tsc_se_update(tsadc); + tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); spin_unlock_irqrestore(&tsadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); @@ -181,6 +229,8 @@ static int ti_tscadc_probe(struct platform_device *pdev) } spin_lock_init(&tscadc->reg_lock); + init_waitqueue_head(&tscadc->reg_se_wait); + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -302,7 +352,6 @@ static int tscadc_resume(struct device *dev) if (tscadc_dev->tsc_cell != -1) tscadc_idle_config(tscadc_dev); - am335x_tsc_se_update(tscadc_dev); restore = tscadc_readl(tscadc_dev, REG_CTRL); tscadc_writel(tscadc_dev, REG_CTRL, (restore | CNTRLREG_TSCSSENB)); diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index dbb34f94e5e3..2bc5cfb85204 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -374,7 +374,7 @@ static const struct resource timberdale_dma_resources[] = { }, }; -static struct mfd_cell timberdale_cells_bar0_cfg0[] = { +static const struct mfd_cell timberdale_cells_bar0_cfg0[] = { { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), @@ -431,7 +431,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg0[] = { }, }; -static struct mfd_cell timberdale_cells_bar0_cfg1[] = { +static const struct mfd_cell timberdale_cells_bar0_cfg1[] = { { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), @@ -498,7 +498,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg1[] = { }, }; -static struct mfd_cell timberdale_cells_bar0_cfg2[] = { +static const struct mfd_cell timberdale_cells_bar0_cfg2[] = { { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), @@ -548,7 +548,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg2[] = { }, }; -static struct mfd_cell timberdale_cells_bar0_cfg3[] = { +static const struct mfd_cell timberdale_cells_bar0_cfg3[] = { { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), @@ -619,7 +619,7 @@ static const struct resource timberdale_sdhc_resources[] = { }, }; -static struct mfd_cell timberdale_cells_bar1[] = { +static const struct mfd_cell timberdale_cells_bar1[] = { { .name = "sdhci", .num_resources = ARRAY_SIZE(timberdale_sdhc_resources), @@ -627,7 +627,7 @@ static struct mfd_cell timberdale_cells_bar1[] = { }, }; -static struct mfd_cell timberdale_cells_bar2[] = { +static const struct mfd_cell timberdale_cells_bar2[] = { { .name = "sdhci", .num_resources = ARRAY_SIZE(timberdale_sdhc_resources), @@ -851,7 +851,7 @@ static void timb_remove(struct pci_dev *dev) kfree(priv); } -static DEFINE_PCI_DEVICE_TABLE(timberdale_pci_tbl) = { +static const struct pci_device_id timberdale_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) }, { 0 } }; diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index a081b925d10b..3b27482a174f 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -24,7 +24,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/tps6507x.h> -static struct mfd_cell tps6507x_devs[] = { +static const struct mfd_cell tps6507x_devs[] = { { .name = "tps6507x-pmic", }, diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index e6f03a733879..ba1a25d758c1 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -64,7 +64,7 @@ static struct resource charger_resources[] = { } }; -static struct mfd_cell tps65090s[] = { +static const struct mfd_cell tps65090s[] = { { .name = "tps65090-pmic", }, diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index b7be0b295575..966cf65c5c36 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -30,7 +30,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/tps65217.h> -static struct mfd_cell tps65217s[] = { +static const struct mfd_cell tps65217s[] = { { .name = "tps65217-pmic", }, @@ -170,7 +170,7 @@ static int tps65217_probe(struct i2c_client *client, "Failed to find matching dt id\n"); return -EINVAL; } - chip_id = (unsigned int)match->data; + chip_id = (unsigned int)(unsigned long)match->data; status_off = of_property_read_bool(client->dev.of_node, "ti,pmic-shutdown-controller"); } diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index ee61fd7c198d..bbd54414a75d 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -103,7 +103,7 @@ static struct resource tps6586x_rtc_resources[] = { }, }; -static struct mfd_cell tps6586x_cell[] = { +static const struct mfd_cell tps6586x_cell[] = { { .name = "tps6586x-gpio", }, @@ -124,6 +124,7 @@ struct tps6586x { struct device *dev; struct i2c_client *client; struct regmap *regmap; + int version; int irq; struct irq_chip irq_chip; @@ -208,6 +209,14 @@ int tps6586x_irq_get_virq(struct device *dev, int irq) } EXPORT_SYMBOL_GPL(tps6586x_irq_get_virq); +int tps6586x_get_version(struct device *dev) +{ + struct tps6586x *tps6586x = dev_get_drvdata(dev); + + return tps6586x->version; +} +EXPORT_SYMBOL_GPL(tps6586x_get_version); + static int __remove_subdev(struct device *dev, void *unused) { platform_device_unregister(to_platform_device(dev)); @@ -472,12 +481,38 @@ static void tps6586x_power_off(void) tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT); } +static void tps6586x_print_version(struct i2c_client *client, int version) +{ + const char *name; + + switch (version) { + case TPS658621A: + name = "TPS658621A"; + break; + case TPS658621CD: + name = "TPS658621C/D"; + break; + case TPS658623: + name = "TPS658623"; + break; + case TPS658643: + name = "TPS658643"; + break; + default: + name = "TPS6586X"; + break; + } + + dev_info(&client->dev, "Found %s, VERSIONCRC is %02x\n", name, version); +} + static int tps6586x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev); struct tps6586x *tps6586x; int ret; + int version; if (!pdata && client->dev.of_node) pdata = tps6586x_parse_dt(client); @@ -487,19 +522,18 @@ static int tps6586x_i2c_probe(struct i2c_client *client, return -ENOTSUPP; } - ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); - if (ret < 0) { - dev_err(&client->dev, "Chip ID read failed: %d\n", ret); + version = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); + if (version < 0) { + dev_err(&client->dev, "Chip ID read failed: %d\n", version); return -EIO; } - dev_info(&client->dev, "VERSIONCRC is %02x\n", ret); - tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL); - if (tps6586x == NULL) { - dev_err(&client->dev, "memory for tps6586x alloc failed\n"); + if (!tps6586x) return -ENOMEM; - } + + tps6586x->version = version; + tps6586x_print_version(client, tps6586x->version); tps6586x->client = client; tps6586x->dev = &client->dev; diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index c0f608e3ca9e..1f142d76cbbc 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -36,7 +36,7 @@ static struct resource rtc_resources[] = { } }; -static struct mfd_cell tps65910s[] = { +static const struct mfd_cell tps65910s[] = { { .name = "tps65910-gpio", }, diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index 925a044cbdf6..27a518e0eec6 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -21,7 +21,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/tps65912.h> -static struct mfd_cell tps65912s[] = { +static const struct mfd_cell tps65912s[] = { { .name = "tps65912-pmic", }, diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c index f15ee6d5cfbf..ed6c5b0956e2 100644 --- a/drivers/mfd/tps80031.c +++ b/drivers/mfd/tps80031.c @@ -44,7 +44,7 @@ static struct resource tps80031_rtc_resources[] = { }; /* TPS80031 sub mfd devices */ -static struct mfd_cell tps80031_cell[] = { +static const struct mfd_cell tps80031_cell[] = { { .name = "tps80031-pmic", }, diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 29473c2c95ae..ed718328eff1 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -47,6 +47,9 @@ #include <linux/i2c.h> #include <linux/i2c/twl.h> +/* Register descriptions for audio */ +#include <linux/mfd/twl4030-audio.h> + #include "twl-core.h" /* @@ -200,6 +203,105 @@ static struct twl_mapping twl4030_map[] = { { 2, TWL5031_BASEADD_INTERRUPTS }, }; +static struct reg_default twl4030_49_defaults[] = { + /* Audio Registers */ + { 0x01, 0x00}, /* CODEC_MODE */ + { 0x02, 0x00}, /* OPTION */ + /* 0x03 Unused */ + { 0x04, 0x00}, /* MICBIAS_CTL */ + { 0x05, 0x00}, /* ANAMICL */ + { 0x06, 0x00}, /* ANAMICR */ + { 0x07, 0x00}, /* AVADC_CTL */ + { 0x08, 0x00}, /* ADCMICSEL */ + { 0x09, 0x00}, /* DIGMIXING */ + { 0x0a, 0x0f}, /* ATXL1PGA */ + { 0x0b, 0x0f}, /* ATXR1PGA */ + { 0x0c, 0x0f}, /* AVTXL2PGA */ + { 0x0d, 0x0f}, /* AVTXR2PGA */ + { 0x0e, 0x00}, /* AUDIO_IF */ + { 0x0f, 0x00}, /* VOICE_IF */ + { 0x10, 0x3f}, /* ARXR1PGA */ + { 0x11, 0x3f}, /* ARXL1PGA */ + { 0x12, 0x3f}, /* ARXR2PGA */ + { 0x13, 0x3f}, /* ARXL2PGA */ + { 0x14, 0x25}, /* VRXPGA */ + { 0x15, 0x00}, /* VSTPGA */ + { 0x16, 0x00}, /* VRX2ARXPGA */ + { 0x17, 0x00}, /* AVDAC_CTL */ + { 0x18, 0x00}, /* ARX2VTXPGA */ + { 0x19, 0x32}, /* ARXL1_APGA_CTL*/ + { 0x1a, 0x32}, /* ARXR1_APGA_CTL*/ + { 0x1b, 0x32}, /* ARXL2_APGA_CTL*/ + { 0x1c, 0x32}, /* ARXR2_APGA_CTL*/ + { 0x1d, 0x00}, /* ATX2ARXPGA */ + { 0x1e, 0x00}, /* BT_IF */ + { 0x1f, 0x55}, /* BTPGA */ + { 0x20, 0x00}, /* BTSTPGA */ + { 0x21, 0x00}, /* EAR_CTL */ + { 0x22, 0x00}, /* HS_SEL */ + { 0x23, 0x00}, /* HS_GAIN_SET */ + { 0x24, 0x00}, /* HS_POPN_SET */ + { 0x25, 0x00}, /* PREDL_CTL */ + { 0x26, 0x00}, /* PREDR_CTL */ + { 0x27, 0x00}, /* PRECKL_CTL */ + { 0x28, 0x00}, /* PRECKR_CTL */ + { 0x29, 0x00}, /* HFL_CTL */ + { 0x2a, 0x00}, /* HFR_CTL */ + { 0x2b, 0x05}, /* ALC_CTL */ + { 0x2c, 0x00}, /* ALC_SET1 */ + { 0x2d, 0x00}, /* ALC_SET2 */ + { 0x2e, 0x00}, /* BOOST_CTL */ + { 0x2f, 0x00}, /* SOFTVOL_CTL */ + { 0x30, 0x13}, /* DTMF_FREQSEL */ + { 0x31, 0x00}, /* DTMF_TONEXT1H */ + { 0x32, 0x00}, /* DTMF_TONEXT1L */ + { 0x33, 0x00}, /* DTMF_TONEXT2H */ + { 0x34, 0x00}, /* DTMF_TONEXT2L */ + { 0x35, 0x79}, /* DTMF_TONOFF */ + { 0x36, 0x11}, /* DTMF_WANONOFF */ + { 0x37, 0x00}, /* I2S_RX_SCRAMBLE_H */ + { 0x38, 0x00}, /* I2S_RX_SCRAMBLE_M */ + { 0x39, 0x00}, /* I2S_RX_SCRAMBLE_L */ + { 0x3a, 0x06}, /* APLL_CTL */ + { 0x3b, 0x00}, /* DTMF_CTL */ + { 0x3c, 0x44}, /* DTMF_PGA_CTL2 (0x3C) */ + { 0x3d, 0x69}, /* DTMF_PGA_CTL1 (0x3D) */ + { 0x3e, 0x00}, /* MISC_SET_1 */ + { 0x3f, 0x00}, /* PCMBTMUX */ + /* 0x40 - 0x42 Unused */ + { 0x43, 0x00}, /* RX_PATH_SEL */ + { 0x44, 0x32}, /* VDL_APGA_CTL */ + { 0x45, 0x00}, /* VIBRA_CTL */ + { 0x46, 0x00}, /* VIBRA_SET */ + { 0x47, 0x00}, /* VIBRA_PWM_SET */ + { 0x48, 0x00}, /* ANAMIC_GAIN */ + { 0x49, 0x00}, /* MISC_SET_2 */ + /* End of Audio Registers */ +}; + +static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0: + case 3: + case 40: + case 41: + case 42: + return false; + default: + return true; + } +} + +static const struct regmap_range twl4030_49_volatile_ranges[] = { + regmap_reg_range(TWL4030_BASEADD_TEST, 0xff), +}; + +static const struct regmap_access_table twl4030_49_volatile_table = { + .yes_ranges = twl4030_49_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(twl4030_49_volatile_ranges), +}; + static struct regmap_config twl4030_regmap_config[4] = { { /* Address 0x48 */ @@ -212,6 +314,15 @@ static struct regmap_config twl4030_regmap_config[4] = { .reg_bits = 8, .val_bits = 8, .max_register = 0xff, + + .readable_reg = twl4030_49_nop_reg, + .writeable_reg = twl4030_49_nop_reg, + + .volatile_table = &twl4030_49_volatile_table, + + .reg_defaults = twl4030_49_defaults, + .num_reg_defaults = ARRAY_SIZE(twl4030_49_defaults), + .cache_type = REGCACHE_RBTREE, }, { /* Address 0x4a */ @@ -302,35 +413,50 @@ unsigned int twl_rev(void) EXPORT_SYMBOL(twl_rev); /** - * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 + * twl_get_regmap - Get the regmap associated with the given module * @mod_no: module number - * @value: an array of num_bytes+1 containing data to write - * @reg: register address (just offset will do) - * @num_bytes: number of bytes to transfer * - * Returns the result of operation - 0 is success + * Returns the regmap pointer or NULL in case of failure. */ -int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) +static struct regmap *twl_get_regmap(u8 mod_no) { - int ret; int sid; struct twl_client *twl; if (unlikely(!twl_priv || !twl_priv->ready)) { pr_err("%s: not initialized\n", DRIVER_NAME); - return -EPERM; + return NULL; } if (unlikely(mod_no >= twl_get_last_module())) { pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); - return -EPERM; + return NULL; } sid = twl_priv->twl_map[mod_no].sid; twl = &twl_priv->twl_modules[sid]; - ret = regmap_bulk_write(twl->regmap, - twl_priv->twl_map[mod_no].base + reg, value, - num_bytes); + return twl->regmap; +} + +/** + * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 + * @mod_no: module number + * @value: an array of num_bytes+1 containing data to write + * @reg: register address (just offset will do) + * @num_bytes: number of bytes to transfer + * + * Returns the result of operation - 0 is success + */ +int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) +{ + struct regmap *regmap = twl_get_regmap(mod_no); + int ret; + + if (!regmap) + return -EPERM; + + ret = regmap_bulk_write(regmap, twl_priv->twl_map[mod_no].base + reg, + value, num_bytes); if (ret) pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n", @@ -351,25 +477,14 @@ EXPORT_SYMBOL(twl_i2c_write); */ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) { + struct regmap *regmap = twl_get_regmap(mod_no); int ret; - int sid; - struct twl_client *twl; - if (unlikely(!twl_priv || !twl_priv->ready)) { - pr_err("%s: not initialized\n", DRIVER_NAME); - return -EPERM; - } - if (unlikely(mod_no >= twl_get_last_module())) { - pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); + if (!regmap) return -EPERM; - } - sid = twl_priv->twl_map[mod_no].sid; - twl = &twl_priv->twl_modules[sid]; - - ret = regmap_bulk_read(twl->regmap, - twl_priv->twl_map[mod_no].base + reg, value, - num_bytes); + ret = regmap_bulk_read(regmap, twl_priv->twl_map[mod_no].base + reg, + value, num_bytes); if (ret) pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n", @@ -379,6 +494,27 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) } EXPORT_SYMBOL(twl_i2c_read); +/** + * twl_regcache_bypass - Configure the regcache bypass for the regmap associated + * with the module + * @mod_no: module number + * @enable: Regcache bypass state + * + * Returns 0 else failure. + */ +int twl_set_regcache_bypass(u8 mod_no, bool enable) +{ + struct regmap *regmap = twl_get_regmap(mod_no); + + if (!regmap) + return -EPERM; + + regcache_cache_bypass(regmap, enable); + + return 0; +} +EXPORT_SYMBOL(twl_set_regcache_bypass); + /*----------------------------------------------------------------------*/ /** @@ -701,62 +837,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, usb3v1[0].dev_name = dev_name(child); } } - if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb && - twl_class_is_6030()) { - - static struct regulator_consumer_supply usb3v3; - int regulator; - - if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) { - /* this is a template that gets copied */ - struct regulator_init_data usb_fixed = { - .constraints.valid_modes_mask = - REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .constraints.valid_ops_mask = - REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }; - - if (features & TWL6032_SUBCLASS) { - usb3v3.supply = "ldousb"; - regulator = TWL6032_REG_LDOUSB; - } else { - usb3v3.supply = "vusb"; - regulator = TWL6030_REG_VUSB; - } - child = add_regulator_linked(regulator, &usb_fixed, - &usb3v3, 1, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - } - - pdata->usb->features = features; - - child = add_child(TWL_MODULE_USB, "twl6030_usb", - pdata->usb, sizeof(*pdata->usb), true, - /* irq1 = VBUS_PRES, irq0 = USB ID */ - irq_base + USBOTG_INTR_OFFSET, - irq_base + USB_PRES_INTR_OFFSET); - - if (IS_ERR(child)) - return PTR_ERR(child); - /* we need to connect regulators to this transceiver */ - if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) - usb3v3.dev_name = dev_name(child); - } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && - twl_class_is_6030()) { - if (features & TWL6032_SUBCLASS) - child = add_regulator(TWL6032_REG_LDOUSB, - pdata->ldousb, features); - else - child = add_regulator(TWL6030_REG_VUSB, - pdata->vusb, features); - - if (IS_ERR(child)) - return PTR_ERR(child); - } if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) { child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL, @@ -870,148 +950,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); } - /* twl6030 regulators */ - if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() && - !(features & TWL6032_SUBCLASS)) { - child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_V1V8, pdata->v1v8, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VPP, pdata->vpp, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VDAC, pdata->vdac, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - } - - /* 6030 and 6025 share this regulator */ - if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) { - child = add_regulator(TWL6030_REG_VANA, pdata->vana, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - } - - /* twl6032 regulators */ - if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() && - (features & TWL6032_SUBCLASS)) { - child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6032_REG_VIO, pdata->vio6025, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - } - if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci && !(features & (TPS_SUBSET | TWL5031))) { child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci", @@ -1133,6 +1071,11 @@ static int twl_remove(struct i2c_client *client) return 0; } +static struct of_dev_auxdata twl_auxdata_lookup[] = { + OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL), + { /* sentinel */ }, +}; + /* NOTE: This driver only handles a single twl4030/tps659x0 chip */ static int twl_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -1271,10 +1214,14 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); } - if (node) - status = of_platform_populate(node, NULL, NULL, &client->dev); - else + if (node) { + if (pdata) + twl_auxdata_lookup[0].platform_data = pdata->gpio; + status = of_platform_populate(node, NULL, twl_auxdata_lookup, + &client->dev); + } else { status = add_children(pdata, irq_base, id->driver_data); + } fail: if (status < 0) diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index 517eda832f79..18a607e2ca06 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c @@ -176,8 +176,9 @@ static irqreturn_t twl6030_irq_thread(int irq, void *data) int i, ret; union { u8 bytes[4]; - u32 int_sts; + __le32 int_sts; } sts; + u32 int_sts; /* sts.int_sts converted to CPU endianness */ struct twl6030_irq *pdata = data; /* read INT_STS_A, B and C in one shot using a burst read */ @@ -196,8 +197,9 @@ static irqreturn_t twl6030_irq_thread(int irq, void *data) if (sts.bytes[2] & 0x10) sts.bytes[2] |= 0x08; - for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) - if (sts.int_sts & 0x1) { + int_sts = le32_to_cpu(sts.int_sts); + for (i = 0; int_sts; int_sts >>= 1, i++) + if (int_sts & 0x1) { int module_irq = irq_find_mapping(pdata->irq_domain, pdata->irq_mapping_tbl[i]); diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 0779d5ab9ab1..75316fb33448 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -44,6 +44,54 @@ #define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1) #define TWL6040_NUM_SUPPLIES (2) +static struct reg_default twl6040_defaults[] = { + { 0x01, 0x4B }, /* REG_ASICID (ro) */ + { 0x02, 0x00 }, /* REG_ASICREV (ro) */ + { 0x03, 0x00 }, /* REG_INTID */ + { 0x04, 0x00 }, /* REG_INTMR */ + { 0x05, 0x00 }, /* REG_NCPCTRL */ + { 0x06, 0x00 }, /* REG_LDOCTL */ + { 0x07, 0x60 }, /* REG_HPPLLCTL */ + { 0x08, 0x00 }, /* REG_LPPLLCTL */ + { 0x09, 0x4A }, /* REG_LPPLLDIV */ + { 0x0A, 0x00 }, /* REG_AMICBCTL */ + { 0x0B, 0x00 }, /* REG_DMICBCTL */ + { 0x0C, 0x00 }, /* REG_MICLCTL */ + { 0x0D, 0x00 }, /* REG_MICRCTL */ + { 0x0E, 0x00 }, /* REG_MICGAIN */ + { 0x0F, 0x1B }, /* REG_LINEGAIN */ + { 0x10, 0x00 }, /* REG_HSLCTL */ + { 0x11, 0x00 }, /* REG_HSRCTL */ + { 0x12, 0x00 }, /* REG_HSGAIN */ + { 0x13, 0x00 }, /* REG_EARCTL */ + { 0x14, 0x00 }, /* REG_HFLCTL */ + { 0x15, 0x00 }, /* REG_HFLGAIN */ + { 0x16, 0x00 }, /* REG_HFRCTL */ + { 0x17, 0x00 }, /* REG_HFRGAIN */ + { 0x18, 0x00 }, /* REG_VIBCTLL */ + { 0x19, 0x00 }, /* REG_VIBDATL */ + { 0x1A, 0x00 }, /* REG_VIBCTLR */ + { 0x1B, 0x00 }, /* REG_VIBDATR */ + { 0x1C, 0x00 }, /* REG_HKCTL1 */ + { 0x1D, 0x00 }, /* REG_HKCTL2 */ + { 0x1E, 0x00 }, /* REG_GPOCTL */ + { 0x1F, 0x00 }, /* REG_ALB */ + { 0x20, 0x00 }, /* REG_DLB */ + /* 0x28, REG_TRIM1 */ + /* 0x29, REG_TRIM2 */ + /* 0x2A, REG_TRIM3 */ + /* 0x2B, REG_HSOTRIM */ + /* 0x2C, REG_HFOTRIM */ + { 0x2D, 0x08 }, /* REG_ACCCTL */ + { 0x2E, 0x00 }, /* REG_STATUS (ro) */ +}; + +static struct reg_default twl6040_patch[] = { + /* Select I2C bus access to dual access registers */ + { TWL6040_REG_ACCCTL, 0x09 }, +}; + + static bool twl6040_has_vibra(struct device_node *node) { #ifdef CONFIG_OF @@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on) if (twl6040->power_count++) goto out; + /* Allow writes to the chip */ + regcache_cache_only(twl6040->regmap, false); + if (gpio_is_valid(twl6040->audpwron)) { /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); @@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on) goto out; } } + + /* Sync with the HW */ + regcache_sync(twl6040->regmap); + /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; @@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* use manual power-down sequence */ twl6040_power_down_manual(twl6040); } + + /* Set regmap to cache only and mark it as dirty */ + regcache_cache_only(twl6040->regmap, true); + regcache_mark_dirty(twl6040->regmap); + twl6040->sysclk = 0; twl6040->mclk = 0; } @@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg) static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case TWL6040_REG_VIBCTLL: - case TWL6040_REG_VIBCTLR: - case TWL6040_REG_INTMR: + case TWL6040_REG_ASICID: + case TWL6040_REG_ASICREV: + case TWL6040_REG_INTID: + case TWL6040_REG_LPPLLCTL: + case TWL6040_REG_HPPLLCTL: + case TWL6040_REG_STATUS: + return true; + default: + return false; + } +} + +static bool twl6040_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TWL6040_REG_ASICID: + case TWL6040_REG_ASICREV: + case TWL6040_REG_STATUS: return false; default: return true; @@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) static struct regmap_config twl6040_regmap_config = { .reg_bits = 8, .val_bits = 8, + + .reg_defaults = twl6040_defaults, + .num_reg_defaults = ARRAY_SIZE(twl6040_defaults), + .max_register = TWL6040_REG_STATUS, /* 0x2e */ .readable_reg = twl6040_readable_reg, .volatile_reg = twl6040_volatile_reg, + .writeable_reg = twl6040_writeable_reg, .cache_type = REGCACHE_RBTREE, }; @@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client, /* dual-access registers controlled by I2C only */ twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL); + regmap_register_patch(twl6040->regmap, twl6040_patch, + ARRAY_SIZE(twl6040_patch)); /* * The main functionality of twl6040 to provide audio on OMAP4+ systems. @@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client, cell->name = "twl6040-gpo"; children++; + /* The chip is powered down so mark regmap to cache only and dirty */ + regcache_cache_only(twl6040->regmap, true); + regcache_mark_dirty(twl6040->regmap); + ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0, NULL); if (ret) diff --git a/drivers/mfd/viperboard.c b/drivers/mfd/viperboard.c index af2a6703f34f..e00f5340ed87 100644 --- a/drivers/mfd/viperboard.c +++ b/drivers/mfd/viperboard.c @@ -37,7 +37,7 @@ static const struct usb_device_id vprbrd_table[] = { MODULE_DEVICE_TABLE(usb, vprbrd_table); -static struct mfd_cell vprbrd_devs[] = { +static const struct mfd_cell vprbrd_devs[] = { { .name = "viperboard-gpio", }, diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c index 757ecc63338c..84f01da4875e 100644 --- a/drivers/mfd/vx855.c +++ b/drivers/mfd/vx855.c @@ -60,7 +60,7 @@ static struct resource vx855_gpio_resources[] = { }, }; -static struct mfd_cell vx855_cells[] = { +static const struct mfd_cell vx855_cells[] = { { .name = "vx855_gpio", .num_resources = ARRAY_SIZE(vx855_gpio_resources), @@ -118,7 +118,7 @@ static void vx855_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(vx855_pci_tbl) = { +static const struct pci_device_id vx855_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, { 0, } }; diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index bf8b3b5ad1fe..11632f135e8c 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -14,6 +14,7 @@ #include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/registers.h> +#include <linux/device.h> #include "arizona.h" @@ -223,6 +224,31 @@ static const struct reg_default wm5110_revb_patch[] = { { 0x80, 0x0 }, }; +static const struct reg_default wm5110_revd_patch[] = { + { 0x80, 0x3 }, + { 0x80, 0x3 }, + { 0x393, 0x27 }, + { 0x394, 0x27 }, + { 0x395, 0x27 }, + { 0x396, 0x27 }, + { 0x397, 0x27 }, + { 0x398, 0x26 }, + { 0x221, 0x90 }, + { 0x211, 0x8 }, + { 0x36c, 0x1fb }, + { 0x26e, 0x64 }, + { 0x26f, 0xea }, + { 0x270, 0x1f16 }, + { 0x51b, 0x1 }, + { 0x55b, 0x1 }, + { 0x59b, 0x1 }, + { 0x4f0, 0x633 }, + { 0x441, 0xc059 }, + { 0x209, 0x27 }, + { 0x80, 0x0 }, + { 0x80, 0x0 }, +}; + /* We use a function so we can use ARRAY_SIZE() */ int wm5110_patch(struct arizona *arizona) { @@ -235,7 +261,10 @@ int wm5110_patch(struct arizona *arizona) return regmap_register_patch(arizona->regmap, wm5110_revb_patch, ARRAY_SIZE(wm5110_revb_patch)); - + case 3: + return regmap_register_patch(arizona->regmap, + wm5110_revd_patch, + ARRAY_SIZE(wm5110_revd_patch)); default: return 0; } @@ -504,7 +533,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */ { 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */ { 0x00000210, 0x0184 }, /* R528 - LDO1 Control 1 */ - { 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */ + { 0x00000213, 0x03E4 }, /* R531 - LDO2 Control 1 */ { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ @@ -524,6 +553,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000300, 0x0000 }, /* R768 - Input Enables */ { 0x00000308, 0x0000 }, /* R776 - Input Rate */ { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */ + { 0x0000030C, 0x0002 }, /* R780 - HPF Control */ { 0x00000310, 0x2080 }, /* R784 - IN1L Control */ { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */ { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */ @@ -545,6 +575,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000328, 0x2000 }, /* R808 - IN4L Control */ { 0x00000329, 0x0180 }, /* R809 - ADC Digital Volume 4L */ { 0x0000032A, 0x0000 }, /* R810 - DMIC4L Control */ + { 0x0000032C, 0x0000 }, /* R812 - IN4R Control */ { 0x0000032D, 0x0180 }, /* R813 - ADC Digital Volume 4R */ { 0x0000032E, 0x0000 }, /* R814 - DMIC4R Control */ { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ @@ -598,6 +629,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x0000043D, 0x0180 }, /* R1085 - DAC Digital Volume 6R */ { 0x0000043E, 0x0080 }, /* R1086 - DAC Volume Limit 6R */ { 0x0000043F, 0x0800 }, /* R1087 - Noise Gate Select 6R */ + { 0x00000440, 0x8FFF }, /* R1088 - DRE Enable */ { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ { 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */ { 0x00000480, 0x0040 }, /* R1152 - Class W ANC Threshold 1 */ @@ -606,6 +638,9 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ { 0x00000492, 0x0069 }, /* R1170 - PDM SPK2 CTRL 1 */ { 0x00000493, 0x0000 }, /* R1171 - PDM SPK2 CTRL 2 */ + { 0x000004A0, 0x3480 }, /* R1184 - HP1 Short Circuit Ctrl */ + { 0x000004A1, 0x3480 }, /* R1185 - HP2 Short Circuit Ctrl */ + { 0x000004A2, 0x3480 }, /* R1186 - HP3 Short Circuit Ctrl */ { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ @@ -882,6 +917,38 @@ static const struct reg_default wm5110_reg_default[] = { { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ + { 0x00000750, 0x0000 }, /* R1872 - AIF2TX3MIX Input 1 Source */ + { 0x00000751, 0x0080 }, /* R1873 - AIF2TX3MIX Input 1 Volume */ + { 0x00000752, 0x0000 }, /* R1874 - AIF2TX3MIX Input 2 Source */ + { 0x00000753, 0x0080 }, /* R1875 - AIF2TX3MIX Input 2 Volume */ + { 0x00000754, 0x0000 }, /* R1876 - AIF2TX3MIX Input 3 Source */ + { 0x00000755, 0x0080 }, /* R1877 - AIF2TX3MIX Input 3 Volume */ + { 0x00000756, 0x0000 }, /* R1878 - AIF2TX3MIX Input 4 Source */ + { 0x00000757, 0x0080 }, /* R1879 - AIF2TX3MIX Input 4 Volume */ + { 0x00000758, 0x0000 }, /* R1880 - AIF2TX4MIX Input 1 Source */ + { 0x00000759, 0x0080 }, /* R1881 - AIF2TX4MIX Input 1 Volume */ + { 0x0000075A, 0x0000 }, /* R1882 - AIF2TX4MIX Input 2 Source */ + { 0x0000075B, 0x0080 }, /* R1883 - AIF2TX4MIX Input 2 Volume */ + { 0x0000075C, 0x0000 }, /* R1884 - AIF2TX4MIX Input 3 Source */ + { 0x0000075D, 0x0080 }, /* R1885 - AIF2TX4MIX Input 3 Volume */ + { 0x0000075E, 0x0000 }, /* R1886 - AIF2TX4MIX Input 4 Source */ + { 0x0000075F, 0x0080 }, /* R1887 - AIF2TX4MIX Input 4 Volume */ + { 0x00000760, 0x0000 }, /* R1888 - AIF2TX5MIX Input 1 Source */ + { 0x00000761, 0x0080 }, /* R1889 - AIF2TX5MIX Input 1 Volume */ + { 0x00000762, 0x0000 }, /* R1890 - AIF2TX5MIX Input 2 Source */ + { 0x00000763, 0x0080 }, /* R1891 - AIF2TX5MIX Input 2 Volume */ + { 0x00000764, 0x0000 }, /* R1892 - AIF2TX5MIX Input 3 Source */ + { 0x00000765, 0x0080 }, /* R1893 - AIF2TX5MIX Input 3 Volume */ + { 0x00000766, 0x0000 }, /* R1894 - AIF2TX5MIX Input 4 Source */ + { 0x00000767, 0x0080 }, /* R1895 - AIF2TX5MIX Input 4 Volume */ + { 0x00000768, 0x0000 }, /* R1896 - AIF2TX6MIX Input 1 Source */ + { 0x00000769, 0x0080 }, /* R1897 - AIF2TX6MIX Input 1 Volume */ + { 0x0000076A, 0x0000 }, /* R1898 - AIF2TX6MIX Input 2 Source */ + { 0x0000076B, 0x0080 }, /* R1899 - AIF2TX6MIX Input 2 Volume */ + { 0x0000076C, 0x0000 }, /* R1900 - AIF2TX6MIX Input 3 Source */ + { 0x0000076D, 0x0080 }, /* R1901 - AIF2TX6MIX Input 3 Volume */ + { 0x0000076E, 0x0000 }, /* R1902 - AIF2TX6MIX Input 4 Source */ + { 0x0000076F, 0x0080 }, /* R1903 - AIF2TX6MIX Input 4 Volume */ { 0x00000780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */ { 0x00000781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */ { 0x00000782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */ @@ -1342,6 +1409,64 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00001404, 0x0000 }, /* R5124 - DSP4 Status 1 */ }; +static bool wm5110_is_rev_b_adsp_memory(unsigned int reg) +{ + if ((reg >= 0x100000 && reg < 0x103000) || + (reg >= 0x180000 && reg < 0x181000) || + (reg >= 0x190000 && reg < 0x192000) || + (reg >= 0x1a8000 && reg < 0x1a9000) || + (reg >= 0x200000 && reg < 0x209000) || + (reg >= 0x280000 && reg < 0x281000) || + (reg >= 0x290000 && reg < 0x29a000) || + (reg >= 0x2a8000 && reg < 0x2aa000) || + (reg >= 0x300000 && reg < 0x30f000) || + (reg >= 0x380000 && reg < 0x382000) || + (reg >= 0x390000 && reg < 0x39e000) || + (reg >= 0x3a8000 && reg < 0x3b6000) || + (reg >= 0x400000 && reg < 0x403000) || + (reg >= 0x480000 && reg < 0x481000) || + (reg >= 0x490000 && reg < 0x492000) || + (reg >= 0x4a8000 && reg < 0x4a9000)) + return true; + else + return false; +} + +static bool wm5110_is_rev_d_adsp_memory(unsigned int reg) +{ + if ((reg >= 0x100000 && reg < 0x106000) || + (reg >= 0x180000 && reg < 0x182000) || + (reg >= 0x190000 && reg < 0x198000) || + (reg >= 0x1a8000 && reg < 0x1aa000) || + (reg >= 0x200000 && reg < 0x20f000) || + (reg >= 0x280000 && reg < 0x282000) || + (reg >= 0x290000 && reg < 0x29c000) || + (reg >= 0x2a6000 && reg < 0x2b4000) || + (reg >= 0x300000 && reg < 0x30f000) || + (reg >= 0x380000 && reg < 0x382000) || + (reg >= 0x390000 && reg < 0x3a2000) || + (reg >= 0x3a6000 && reg < 0x3b4000) || + (reg >= 0x400000 && reg < 0x406000) || + (reg >= 0x480000 && reg < 0x482000) || + (reg >= 0x490000 && reg < 0x498000) || + (reg >= 0x4a8000 && reg < 0x4aa000)) + return true; + else + return false; +} + +static bool wm5110_is_adsp_memory(struct device *dev, unsigned int reg) +{ + struct arizona *arizona = dev_get_drvdata(dev); + + switch (arizona->rev) { + case 0 ... 2: + return wm5110_is_rev_b_adsp_memory(reg); + default: + return wm5110_is_rev_d_adsp_memory(reg); + } +} + static bool wm5110_readable_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -1460,6 +1585,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_INPUT_ENABLES_STATUS: case ARIZONA_INPUT_RATE: case ARIZONA_INPUT_VOLUME_RAMP: + case ARIZONA_HPF_CONTROL: case ARIZONA_IN1L_CONTROL: case ARIZONA_ADC_DIGITAL_VOLUME_1L: case ARIZONA_DMIC1L_CONTROL: @@ -1481,6 +1607,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_IN4L_CONTROL: case ARIZONA_ADC_DIGITAL_VOLUME_4L: case ARIZONA_DMIC4L_CONTROL: + case ARIZONA_IN4R_CONTROL: case ARIZONA_ADC_DIGITAL_VOLUME_4R: case ARIZONA_DMIC4R_CONTROL: case ARIZONA_OUTPUT_ENABLES_1: @@ -1536,12 +1663,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_DAC_DIGITAL_VOLUME_6R: case ARIZONA_DAC_VOLUME_LIMIT_6R: case ARIZONA_NOISE_GATE_SELECT_6R: + case ARIZONA_DRE_ENABLE: case ARIZONA_DAC_AEC_CONTROL_1: case ARIZONA_NOISE_GATE_CONTROL: case ARIZONA_PDM_SPK1_CTRL_1: case ARIZONA_PDM_SPK1_CTRL_2: case ARIZONA_PDM_SPK2_CTRL_1: case ARIZONA_PDM_SPK2_CTRL_2: + case ARIZONA_HP1_SHORT_CIRCUIT_CTRL: + case ARIZONA_HP2_SHORT_CIRCUIT_CTRL: + case ARIZONA_HP3_SHORT_CIRCUIT_CTRL: case ARIZONA_AIF1_BCLK_CTRL: case ARIZONA_AIF1_TX_PIN_CTRL: case ARIZONA_AIF1_RX_PIN_CTRL: @@ -1820,6 +1951,38 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME: case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE: case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME: case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE: case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME: case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE: @@ -2331,7 +2494,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_DSP4_SCRATCH_3: return true; default: - return false; + return wm5110_is_adsp_memory(dev, reg); } } @@ -2407,16 +2570,18 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_DSP4_SCRATCH_3: return true; default: - return false; + return wm5110_is_adsp_memory(dev, reg); } } +#define WM5110_MAX_REGISTER 0x4a9fff + const struct regmap_config wm5110_spi_regmap = { .reg_bits = 32, .pad_bits = 16, .val_bits = 16, - .max_register = ARIZONA_DSP1_STATUS_2, + .max_register = WM5110_MAX_REGISTER, .readable_reg = wm5110_readable_register, .volatile_reg = wm5110_volatile_register, @@ -2430,7 +2595,7 @@ const struct regmap_config wm5110_i2c_regmap = { .reg_bits = 32, .val_bits = 16, - .max_register = ARIZONA_DSP1_STATUS_2, + .max_register = WM5110_MAX_REGISTER, .readable_reg = wm5110_readable_register, .volatile_reg = wm5110_volatile_register, diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 5c459f469224..28366a90e1ad 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1011,7 +1011,7 @@ static struct resource wm831x_wdt_resources[] = { }, }; -static struct mfd_cell wm8310_devs[] = { +static const struct mfd_cell wm8310_devs[] = { { .name = "wm831x-backup", }, @@ -1165,7 +1165,7 @@ static struct mfd_cell wm8310_devs[] = { }, }; -static struct mfd_cell wm8311_devs[] = { +static const struct mfd_cell wm8311_devs[] = { { .name = "wm831x-backup", }, @@ -1295,7 +1295,7 @@ static struct mfd_cell wm8311_devs[] = { }, }; -static struct mfd_cell wm8312_devs[] = { +static const struct mfd_cell wm8312_devs[] = { { .name = "wm831x-backup", }, @@ -1449,7 +1449,7 @@ static struct mfd_cell wm8312_devs[] = { }, }; -static struct mfd_cell wm8320_devs[] = { +static const struct mfd_cell wm8320_devs[] = { { .name = "wm831x-backup", }, @@ -1578,7 +1578,7 @@ static struct mfd_cell wm8320_devs[] = { }, }; -static struct mfd_cell touch_devs[] = { +static const struct mfd_cell touch_devs[] = { { .name = "wm831x-touch", .num_resources = ARRAY_SIZE(wm831x_touch_resources), @@ -1586,7 +1586,7 @@ static struct mfd_cell touch_devs[] = { }, }; -static struct mfd_cell rtc_devs[] = { +static const struct mfd_cell rtc_devs[] = { { .name = "wm831x-rtc", .num_resources = ARRAY_SIZE(wm831x_rtc_resources), @@ -1594,7 +1594,7 @@ static struct mfd_cell rtc_devs[] = { }, }; -static struct mfd_cell backlight_devs[] = { +static const struct mfd_cell backlight_devs[] = { { .name = "wm831x-backlight", }, diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 2b29caebc9cf..a4cbefe5430f 100644 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c @@ -64,11 +64,13 @@ static int wm831x_i2c_suspend(struct device *dev) return wm831x_device_suspend(wm831x); } -static void wm831x_i2c_shutdown(struct i2c_client *i2c) +static int wm831x_i2c_poweroff(struct device *dev) { - struct wm831x *wm831x = i2c_get_clientdata(i2c); + struct wm831x *wm831x = dev_get_drvdata(dev); wm831x_device_shutdown(wm831x); + + return 0; } static const struct i2c_device_id wm831x_i2c_id[] = { @@ -85,6 +87,7 @@ MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); static const struct dev_pm_ops wm831x_pm_ops = { .suspend = wm831x_i2c_suspend, + .poweroff = wm831x_i2c_poweroff, }; static struct i2c_driver wm831x_i2c_driver = { @@ -95,7 +98,6 @@ static struct i2c_driver wm831x_i2c_driver = { }, .probe = wm831x_i2c_probe, .remove = wm831x_i2c_remove, - .shutdown = wm831x_i2c_shutdown, .id_table = wm831x_i2c_id, }; diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 07de3cc5a0d9..b8a5e3b34ec7 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c @@ -66,16 +66,19 @@ static int wm831x_spi_suspend(struct device *dev) return wm831x_device_suspend(wm831x); } -static void wm831x_spi_shutdown(struct spi_device *spi) +static int wm831x_spi_poweroff(struct device *dev) { - struct wm831x *wm831x = spi_get_drvdata(spi); + struct wm831x *wm831x = dev_get_drvdata(dev); wm831x_device_shutdown(wm831x); + + return 0; } static const struct dev_pm_ops wm831x_spi_pm = { .freeze = wm831x_spi_suspend, .suspend = wm831x_spi_suspend, + .poweroff = wm831x_spi_poweroff, }; static const struct spi_device_id wm831x_spi_ids[] = { @@ -99,7 +102,6 @@ static struct spi_driver wm831x_spi_driver = { .id_table = wm831x_spi_ids, .probe = wm831x_spi_probe, .remove = wm831x_spi_remove, - .shutdown = wm831x_spi_shutdown, }; static int __init wm831x_spi_init(void) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 030827511667..ba04f1bc70eb 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -33,7 +33,7 @@ #include "wm8994.h" -static struct mfd_cell wm8994_regulator_devs[] = { +static const struct mfd_cell wm8994_regulator_devs[] = { { .name = "wm8994-ldo", .id = 1, @@ -62,7 +62,7 @@ static struct resource wm8994_gpio_resources[] = { }, }; -static struct mfd_cell wm8994_devs[] = { +static const struct mfd_cell wm8994_devs[] = { { .name = "wm8994-codec", .num_resources = ARRAY_SIZE(wm8994_codec_resources), |