diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 18 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mfd/atmel-smc.c | 2 | ||||
-rw-r--r-- | drivers/mfd/da9052-core.c | 26 | ||||
-rw-r--r-- | drivers/mfd/da9062-core.c | 6 | ||||
-rw-r--r-- | drivers/mfd/dm355evm_msp.c | 2 | ||||
-rw-r--r-- | drivers/mfd/retu-mfd.c | 12 | ||||
-rw-r--r-- | drivers/mfd/rk808.c | 147 | ||||
-rw-r--r-- | drivers/mfd/stm32-lptimer.c | 107 | ||||
-rw-r--r-- | drivers/mfd/tps6105x.c | 8 | ||||
-rw-r--r-- | drivers/mfd/twl-core.c | 6 | ||||
-rw-r--r-- | drivers/mfd/twl4030-audio.c | 2 | ||||
-rw-r--r-- | drivers/mfd/twl4030-irq.c | 2 | ||||
-rw-r--r-- | drivers/mfd/twl4030-power.c | 2 | ||||
-rw-r--r-- | drivers/mfd/twl6030-irq.c | 2 |
15 files changed, 321 insertions, 22 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 94ad2c1..7a01e70a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -951,13 +951,13 @@ config MFD_RC5T583 different functionality of the device. config MFD_RK808 - tristate "Rockchip RK808/RK818 Power Management Chip" + tristate "Rockchip RK805/RK808/RK818 Power Management Chip" depends on I2C && OF select MFD_CORE select REGMAP_I2C select REGMAP_IRQ help - If you say yes here you get support for the RK808 and RK818 + If you say yes here you get support for the RK805, RK808 and RK818 Power Management chips. This driver provides common support for accessing the device through I2C interface. The device supports multiple sub-devices @@ -1723,6 +1723,20 @@ config MFD_STW481X in various ST Microelectronics and ST-Ericsson embedded Nomadik series. +config MFD_STM32_LPTIMER + tristate "Support for STM32 Low-Power Timer" + depends on (ARCH_STM32 && OF) || COMPILE_TEST + select MFD_CORE + select REGMAP + select REGMAP_MMIO + help + Select this option to enable STM32 Low-Power Timer driver + used for PWM, IIO Trigger, IIO Encoder and Counter. Shared + resources are also dealt with here. + + To compile this driver as a module, choose M here: the + module will be called stm32-lptimer. + config MFD_STM32_TIMERS tristate "Support for STM32 Timers" depends on (ARCH_STM32 && OF) || COMPILE_TEST diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 080793b..b80b1a3 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -221,5 +221,6 @@ obj-$(CONFIG_MFD_MT6397) += mt6397-core.o obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o +obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c index 954cf0f..20cc0ea 100644 --- a/drivers/mfd/atmel-smc.c +++ b/drivers/mfd/atmel-smc.c @@ -206,7 +206,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_pulse); * parameter * * This function encodes the @ncycles value as described in the datasheet - * (section "SMC Pulse Register"), and then stores the result in the + * (section "SMC Cycle Register"), and then stores the result in the * @conf->setup field at @shift position. * * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index a88c206..a23a3a1 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -18,6 +18,7 @@ #include <linux/mfd/core.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/property.h> #include <linux/mfd/da9052/da9052.h> #include <linux/mfd/da9052/pdata.h> @@ -519,9 +520,6 @@ static const struct mfd_cell da9052_subdev_info[] = { .name = "da9052-wled3", }, { - .name = "da9052-tsi", - }, - { .name = "da9052-bat", }, { @@ -529,6 +527,10 @@ static const struct mfd_cell da9052_subdev_info[] = { }, }; +static const struct mfd_cell da9052_tsi_subdev_info[] = { + { .name = "da9052-tsi" }, +}; + const struct regmap_config da9052_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -619,9 +621,27 @@ int da9052_device_init(struct da9052 *da9052, u8 chip_id) goto err; } + /* + * Check if touchscreen pins are used are analogue input instead + * of having a touchscreen connected to them. The analogue input + * functionality will be provided by hwmon driver (if enabled). + */ + if (!device_property_read_bool(da9052->dev, "dlg,tsi-as-adc")) { + ret = mfd_add_devices(da9052->dev, PLATFORM_DEVID_AUTO, + da9052_tsi_subdev_info, + ARRAY_SIZE(da9052_tsi_subdev_info), + NULL, 0, NULL); + if (ret) { + dev_err(da9052->dev, "failed to add TSI subdev: %d\n", + ret); + goto err; + } + } + return 0; err: + mfd_remove_devices(da9052->dev); da9052_irq_exit(da9052); return ret; diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index fbe0f24..fe18115 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -645,6 +645,9 @@ static const struct regmap_range da9062_aa_readable_ranges[] = { .range_min = DA9062AA_VLDO1_B, .range_max = DA9062AA_VLDO4_B, }, { + .range_min = DA9062AA_BBAT_CONT, + .range_max = DA9062AA_BBAT_CONT, + }, { .range_min = DA9062AA_INTERFACE, .range_max = DA9062AA_CONFIG_E, }, { @@ -721,6 +724,9 @@ static const struct regmap_range da9062_aa_writeable_ranges[] = { .range_min = DA9062AA_VLDO1_B, .range_max = DA9062AA_VLDO4_B, }, { + .range_min = DA9062AA_BBAT_CONT, + .range_max = DA9062AA_BBAT_CONT, + }, { .range_min = DA9062AA_GP_ID_0, .range_max = DA9062AA_GP_ID_19, }, diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 86eca61..2a27567 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -18,7 +18,7 @@ #include <linux/gpio.h> #include <linux/leds.h> #include <linux/i2c.h> -#include <linux/i2c/dm355evm_msp.h> +#include <linux/mfd/dm355evm_msp.h> /* diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c index d4c114a..e7d27b7 100644 --- a/drivers/mfd/retu-mfd.c +++ b/drivers/mfd/retu-mfd.c @@ -302,15 +302,23 @@ static int retu_remove(struct i2c_client *i2c) } static const struct i2c_device_id retu_id[] = { - { "retu-mfd", 0 }, - { "tahvo-mfd", 0 }, + { "retu", 0 }, + { "tahvo", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, retu_id); +static const struct of_device_id retu_of_match[] = { + { .compatible = "nokia,retu" }, + { .compatible = "nokia,tahvo" }, + { } +}; +MODULE_DEVICE_TABLE(of, retu_of_match); + static struct i2c_driver retu_driver = { .driver = { .name = "retu-mfd", + .of_match_table = retu_of_match, }, .probe = retu_probe, .remove = retu_remove, diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index fd087cb..216fbf6 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -70,6 +70,14 @@ static const struct regmap_config rk818_regmap_config = { .volatile_reg = rk808_is_volatile_reg, }; +static const struct regmap_config rk805_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK805_OFF_SOURCE_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + static const struct regmap_config rk808_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -86,6 +94,34 @@ static struct resource rtc_resources[] = { } }; +static struct resource rk805_key_resources[] = { + { + .start = RK805_IRQ_PWRON_FALL, + .end = RK805_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK805_IRQ_PWRON_RISE, + .end = RK805_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + } +}; + +static const struct mfd_cell rk805s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { .name = "rk805-pinctrl", }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, + { .name = "rk805-pwrkey", + .num_resources = ARRAY_SIZE(rk805_key_resources), + .resources = &rk805_key_resources[0], + }, +}; + static const struct mfd_cell rk808s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -106,6 +142,20 @@ static const struct mfd_cell rk818s[] = { }, }; +static const struct rk808_reg_data rk805_pre_init_reg[] = { + {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, + RK805_BUCK1_2_ILMAX_4000MA}, + {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, + RK805_BUCK1_2_ILMAX_4000MA}, + {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, + RK805_BUCK3_ILMAX_3000MA}, + {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, + RK805_BUCK4_ILMAX_3500MA}, + {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, + {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN}, + {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, +}; + static const struct rk808_reg_data rk808_pre_init_reg[] = { { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, @@ -135,6 +185,41 @@ static const struct rk808_reg_data rk818_pre_init_reg[] = { VB_LO_SEL_3500MV }, }; +static const struct regmap_irq rk805_irqs[] = { + [RK805_IRQ_PWRON_RISE] = { + .mask = RK805_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_VB_LOW] = { + .mask = RK805_IRQ_VB_LOW_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON] = { + .mask = RK805_IRQ_PWRON_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_LP] = { + .mask = RK805_IRQ_PWRON_LP_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_HOTDIE] = { + .mask = RK805_IRQ_HOTDIE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_ALARM] = { + .mask = RK805_IRQ_RTC_ALARM_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_PERIOD] = { + .mask = RK805_IRQ_RTC_PERIOD_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_FALL] = { + .mask = RK805_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, +}; + static const struct regmap_irq rk808_irqs[] = { /* INT_STS */ [RK808_IRQ_VOUT_LO] = { @@ -247,6 +332,17 @@ static const struct regmap_irq rk818_irqs[] = { }, }; +static struct regmap_irq_chip rk805_irq_chip = { + .name = "rk805", + .irqs = rk805_irqs, + .num_irqs = ARRAY_SIZE(rk805_irqs), + .num_regs = 1, + .status_base = RK805_INT_STS_REG, + .mask_base = RK805_INT_STS_MSK_REG, + .ack_base = RK805_INT_STS_REG, + .init_ack_masked = true, +}; + static const struct regmap_irq_chip rk808_irq_chip = { .name = "rk808", .irqs = rk808_irqs, @@ -272,6 +368,25 @@ static const struct regmap_irq_chip rk818_irq_chip = { }; static struct i2c_client *rk808_i2c_client; + +static void rk805_device_shutdown(void) +{ + int ret; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + if (!rk808) { + dev_warn(&rk808_i2c_client->dev, + "have no rk805, so do nothing here\n"); + return; + } + + ret = regmap_update_bits(rk808->regmap, + RK805_DEV_CTRL_REG, + DEV_OFF, DEV_OFF); + if (ret) + dev_err(&rk808_i2c_client->dev, "power off error!\n"); +} + static void rk808_device_shutdown(void) { int ret; @@ -309,6 +424,7 @@ static void rk818_device_shutdown(void) } static const struct of_device_id rk808_of_match[] = { + { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk818" }, { }, @@ -325,7 +441,7 @@ static int rk808_probe(struct i2c_client *client, void (*pm_pwroff_fn)(void); int nr_pre_init_regs; int nr_cells; - int pm_off = 0; + int pm_off = 0, msb, lsb; int ret; int i; @@ -333,16 +449,34 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; - rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB); - if (rk808->variant < 0) { - dev_err(&client->dev, "Failed to read the chip id at 0x%02x\n", + /* Read chip variant */ + msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB); + if (msb < 0) { + dev_err(&client->dev, "failed to read the chip id at 0x%x\n", RK808_ID_MSB); - return rk808->variant; + return msb; + } + + lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB); + if (lsb < 0) { + dev_err(&client->dev, "failed to read the chip id at 0x%x\n", + RK808_ID_LSB); + return lsb; } - dev_dbg(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); + rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); switch (rk808->variant) { + case RK805_ID: + rk808->regmap_cfg = &rk805_regmap_config; + rk808->regmap_irq_chip = &rk805_irq_chip; + pre_init_reg = rk805_pre_init_reg; + nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); + cells = rk805s; + nr_cells = ARRAY_SIZE(rk805s); + pm_pwroff_fn = rk805_device_shutdown; + break; case RK808_ID: rk808->regmap_cfg = &rk808_regmap_config; rk808->regmap_irq_chip = &rk808_irq_chip; @@ -435,6 +569,7 @@ static int rk808_remove(struct i2c_client *client) } static const struct i2c_device_id rk808_ids[] = { + { "rk805" }, { "rk808" }, { "rk818" }, { }, diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c new file mode 100644 index 0000000..075330a --- /dev/null +++ b/drivers/mfd/stm32-lptimer.c @@ -0,0 +1,107 @@ +/* + * STM32 Low-Power Timer parent driver. + * + * Copyright (C) STMicroelectronics 2017 + * + * Author: Fabrice Gasnier <fabrice.gasnier@st.com> + * + * Inspired by Benjamin Gaignard's stm32-timers driver + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/mfd/stm32-lptimer.h> +#include <linux/module.h> +#include <linux/of_platform.h> + +#define STM32_LPTIM_MAX_REGISTER 0x3fc + +static const struct regmap_config stm32_lptimer_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = sizeof(u32), + .max_register = STM32_LPTIM_MAX_REGISTER, +}; + +static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata) +{ + u32 val; + int ret; + + /* + * Quadrature encoder mode bit can only be written and read back when + * Low-Power Timer supports it. + */ + ret = regmap_update_bits(ddata->regmap, STM32_LPTIM_CFGR, + STM32_LPTIM_ENC, STM32_LPTIM_ENC); + if (ret) + return ret; + + ret = regmap_read(ddata->regmap, STM32_LPTIM_CFGR, &val); + if (ret) + return ret; + + ret = regmap_update_bits(ddata->regmap, STM32_LPTIM_CFGR, + STM32_LPTIM_ENC, 0); + if (ret) + return ret; + + ddata->has_encoder = !!(val & STM32_LPTIM_ENC); + + return 0; +} + +static int stm32_lptimer_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct stm32_lptimer *ddata; + struct resource *res; + void __iomem *mmio; + int ret; + + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mmio = devm_ioremap_resource(dev, res); + if (IS_ERR(mmio)) + return PTR_ERR(mmio); + + ddata->regmap = devm_regmap_init_mmio_clk(dev, "mux", mmio, + &stm32_lptimer_regmap_cfg); + if (IS_ERR(ddata->regmap)) + return PTR_ERR(ddata->regmap); + + ddata->clk = devm_clk_get(dev, NULL); + if (IS_ERR(ddata->clk)) + return PTR_ERR(ddata->clk); + + ret = stm32_lptimer_detect_encoder(ddata); + if (ret) + return ret; + + platform_set_drvdata(pdev, ddata); + + return devm_of_platform_populate(&pdev->dev); +} + +static const struct of_device_id stm32_lptimer_of_match[] = { + { .compatible = "st,stm32-lptimer", }, + {}, +}; +MODULE_DEVICE_TABLE(of, stm32_lptimer_of_match); + +static struct platform_driver stm32_lptimer_driver = { + .probe = stm32_lptimer_probe, + .driver = { + .name = "stm32-lptimer", + .of_match_table = stm32_lptimer_of_match, + }, +}; +module_platform_driver(stm32_lptimer_driver); + +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics STM32 Low-Power Timer"); +MODULE_ALIAS("platform:stm32-lptimer"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index baa12ea..187848c 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -173,9 +173,17 @@ static const struct i2c_device_id tps6105x_id[] = { }; MODULE_DEVICE_TABLE(i2c, tps6105x_id); +static const struct of_device_id tps6105x_of_match[] = { + { .compatible = "ti,tps61050" }, + { .compatible = "ti,tps61052" }, + { }, +}; +MODULE_DEVICE_TABLE(of, tps6105x_of_match); + static struct i2c_driver tps6105x_driver = { .driver = { .name = "tps6105x", + .of_match_table = tps6105x_of_match, }, .probe = tps6105x_probe, .remove = tps6105x_remove, diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index c64615d..2a09dde 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -44,7 +44,7 @@ #include <linux/regulator/machine.h> #include <linux/i2c.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> /* Register descriptions for audio */ #include <linux/mfd/twl4030-audio.h> @@ -173,7 +173,7 @@ static struct twl_private *twl_priv; static struct twl_mapping twl4030_map[] = { /* * NOTE: don't change this table without updating the - * <linux/i2c/twl.h> defines for TWL4030_MODULE_* + * <linux/mfd/twl.h> defines for TWL4030_MODULE_* * so they continue to match the order in this table. */ @@ -344,7 +344,7 @@ static const struct regmap_config twl4030_regmap_config[4] = { static struct twl_mapping twl6030_map[] = { /* * NOTE: don't change this table without updating the - * <linux/i2c/twl.h> defines for TWL4030_MODULE_* + * <linux/mfd/twl.h> defines for TWL4030_MODULE_* * so they continue to match the order in this table. */ diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index 0a16064..da16bf4 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -30,7 +30,7 @@ #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_platform.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include <linux/mfd/core.h> #include <linux/mfd/twl4030-audio.h> diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 378c02d..b16c16f 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -33,7 +33,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/irqdomain.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include "twl-core.h" diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index f4b2c29..6b36932 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -25,7 +25,7 @@ #include <linux/module.h> #include <linux/pm.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index 5357450..e3ec8df 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c @@ -35,7 +35,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/kthread.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include <linux/platform_device.h> #include <linux/suspend.h> #include <linux/of.h> |