diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 28 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 3 | ||||
-rw-r--r-- | drivers/mfd/act8846.c | 4 | ||||
-rw-r--r-- | drivers/mfd/atmel-flexcom.c | 9 | ||||
-rw-r--r-- | drivers/mfd/atmel-smc.c | 355 | ||||
-rw-r--r-- | drivers/mfd/axp20x-i2c.c | 8 | ||||
-rw-r--r-- | drivers/mfd/axp20x.c | 36 | ||||
-rw-r--r-- | drivers/mfd/core.c | 5 | ||||
-rw-r--r-- | drivers/mfd/da9053.c | 11 | ||||
-rw-r--r-- | drivers/mfd/da9063.c | 15 | ||||
-rw-r--r-- | drivers/mfd/lp3972.c | 4 | ||||
-rw-r--r-- | drivers/mfd/mc13xxx.c | 13 | ||||
-rw-r--r-- | drivers/mfd/mc34704.c | 5 | ||||
-rw-r--r-- | drivers/mfd/mc9sdz60.c | 4 | ||||
-rw-r--r-- | drivers/mfd/pca9450.c | 127 | ||||
-rw-r--r-- | drivers/mfd/rave-sp.c | 25 | ||||
-rw-r--r-- | drivers/mfd/rk808.c | 10 | ||||
-rw-r--r-- | drivers/mfd/rn5t568.c | 38 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd718x7.c | 140 | ||||
-rw-r--r-- | drivers/mfd/stm32-timers.c | 8 | ||||
-rw-r--r-- | drivers/mfd/stmpe-i2c.c | 10 | ||||
-rw-r--r-- | drivers/mfd/stpmic1.c | 9 | ||||
-rw-r--r-- | drivers/mfd/superio.c | 6 | ||||
-rw-r--r-- | drivers/mfd/syscon.c | 24 | ||||
-rw-r--r-- | drivers/mfd/twl4030.c | 4 | ||||
-rw-r--r-- | drivers/mfd/twl6030.c | 4 |
26 files changed, 780 insertions, 125 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 5fd1a0aaa8..5189364c2c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -64,12 +64,21 @@ config RAVE_SP_CORE config MFD_STPMIC1 depends on I2C + select REGMAP_I2C bool "STPMIC1 MFD driver" help Select this to support communication with the STPMIC1. +config MFD_PCA9450 + depends on I2C + select REGMAP_I2C + bool "PCA9450 MFD driver" + help + Select this to support communication with the PCA9450 PMIC. + config MFD_RN568PMIC depends on I2C + select REGMAP_I2C bool "Ricoh RN5T568 MFD driver" help Select this to support communication with the Ricoh RN5T568 PMIC. @@ -111,6 +120,7 @@ config MFD_ATMEL_FLEXCOM config MFD_RK808 tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip" depends on I2C && OFDEVICE + select REGMAP_I2C help If you say yes here you get support for the RK805, RK808, RK809, RK817 and RK818 Power Management chips. @@ -120,9 +130,27 @@ config MFD_RK808 config MFD_AXP20X_I2C tristate "X-Powers AXP series PMICs with I2C" depends on I2C && OFDEVICE + select REGMAP_I2C help If you say Y here you get support for the X-Powers AXP series power management ICs (PMICs) controlled with I2C. This driver currently only provide a character device in /dev. +config MFD_ROHM_BD718XX + tristate "ROHM BD71837 Power Management IC" + depends on I2C=y + depends on OFDEVICE + select REGMAP_I2C + help + Select this option to get support for the ROHM BD71837 + Power Management ICs. BD71837 is designed to power processors like + NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring + and emergency shut down as well as 32,768KHz clock output. + + This driver currently only provide a character device in /dev. + +config MFD_ATMEL_SMC + bool + select MFD_SYSCON + endmenu diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index a3cb90e883..00f3eacf3c 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -23,3 +23,6 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o obj-$(CONFIG_MFD_RK808) += rk808.o obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o axp20x.o +obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o +obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o +obj-$(CONFIG_MFD_PCA9450) += pca9450.o diff --git a/drivers/mfd/act8846.c b/drivers/mfd/act8846.c index 0e2ac8471e..f15310f507 100644 --- a/drivers/mfd/act8846.c +++ b/drivers/mfd/act8846.c @@ -110,7 +110,7 @@ static struct cdev_operations act8846_fops = { .write = act8846_write, }; -static int act8846_probe(struct device_d *dev) +static int act8846_probe(struct device *dev) { if (act8846_dev) return -EBUSY; @@ -127,7 +127,7 @@ static int act8846_probe(struct device_d *dev) return 0; } -static struct driver_d act8846_driver = { +static struct driver act8846_driver = { .name = DRIVERNAME, .probe = act8846_probe, }; diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c index 996d4850ee..58e94c4889 100644 --- a/drivers/mfd/atmel-flexcom.c +++ b/drivers/mfd/atmel-flexcom.c @@ -20,14 +20,14 @@ #define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \ FLEX_MR_OPMODE_MASK) -static int atmel_flexcom_probe(struct device_d *dev) +static int atmel_flexcom_probe(struct device *dev) { struct resource *res; struct clk *clk; u32 opmode; int err; - err = of_property_read_u32(dev->device_node, + err = of_property_read_u32(dev->of_node, "atmel,flexcom-mode", &opmode); if (err) return err; @@ -57,15 +57,16 @@ static int atmel_flexcom_probe(struct device_d *dev) clk_disable(clk); - return of_platform_populate(dev->device_node, NULL, dev); + return of_platform_populate(dev->of_node, NULL, dev); } static const struct of_device_id atmel_flexcom_of_match[] = { { .compatible = "atmel,sama5d2-flexcom" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match); -static struct driver_d atmel_flexcom_driver = { +static struct driver atmel_flexcom_driver = { .probe = atmel_flexcom_probe, .name = "atmel_flexcom", .of_compatible = atmel_flexcom_of_match, diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c new file mode 100644 index 0000000000..9432aa2c68 --- /dev/null +++ b/drivers/mfd/atmel-smc.c @@ -0,0 +1,355 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Atmel SMC (Static Memory Controller) helper functions. + * + * Copyright (C) 2017 Atmel + * Copyright (C) 2017 Free Electrons + * + * Author: Boris Brezillon <boris.brezillon@free-electrons.com> + */ + +#include <linux/mfd/syscon/atmel-smc.h> +#include <linux/string.h> +#include <linux/export.h> +#include <linux/regmap.h> +#include <linux/bitops.h> + +/** + * atmel_smc_cs_conf_init - initialize a SMC CS conf + * @conf: the SMC CS conf to initialize + * + * Set all fields to 0 so that one can start defining a new config. + */ +void atmel_smc_cs_conf_init(struct atmel_smc_cs_conf *conf) +{ + memset(conf, 0, sizeof(*conf)); +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_init); + +/** + * atmel_smc_cs_encode_ncycles - encode a number of MCK clk cycles in the + * format expected by the SMC engine + * @ncycles: number of MCK clk cycles + * @msbpos: position of the MSB part of the timing field + * @msbwidth: width of the MSB part of the timing field + * @msbfactor: factor applied to the MSB + * @encodedval: param used to store the encoding result + * + * This function encodes the @ncycles value as described in the datasheet + * (section "SMC Setup/Pulse/Cycle/Timings Register"). This is a generic + * helper which called with different parameter depending on the encoding + * scheme. + * + * If the @ncycles value is too big to be encoded, -ERANGE is returned and + * the encodedval is contains the maximum val. Otherwise, 0 is returned. + */ +static int atmel_smc_cs_encode_ncycles(unsigned int ncycles, + unsigned int msbpos, + unsigned int msbwidth, + unsigned int msbfactor, + unsigned int *encodedval) +{ + unsigned int lsbmask = GENMASK(msbpos - 1, 0); + unsigned int msbmask = GENMASK(msbwidth - 1, 0); + unsigned int msb, lsb; + int ret = 0; + + msb = ncycles / msbfactor; + lsb = ncycles % msbfactor; + + if (lsb > lsbmask) { + lsb = 0; + msb++; + } + + /* + * Let's just put the maximum we can if the requested setting does + * not fit in the register field. + * We still return -ERANGE in case the caller cares. + */ + if (msb > msbmask) { + msb = msbmask; + lsb = lsbmask; + ret = -ERANGE; + } + + *encodedval = (msb << msbpos) | lsb; + + return ret; +} + +/** + * atmel_smc_cs_conf_set_timing - set the SMC CS conf Txx parameter to a + * specific value + * @conf: SMC CS conf descriptor + * @shift: the position of the Txx field in the TIMINGS register + * @ncycles: value (expressed in MCK clk cycles) to assign to this Txx + * parameter + * + * This function encodes the @ncycles value as described in the datasheet + * (section "SMC Timings Register"), and then stores the result in the + * @conf->timings field at @shift position. + * + * Returns -EINVAL if shift is invalid, -ERANGE if ncycles does not fit in + * the field, and 0 otherwise. + */ +int atmel_smc_cs_conf_set_timing(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles) +{ + unsigned int val; + int ret; + + if (shift != ATMEL_HSMC_TIMINGS_TCLR_SHIFT && + shift != ATMEL_HSMC_TIMINGS_TADL_SHIFT && + shift != ATMEL_HSMC_TIMINGS_TAR_SHIFT && + shift != ATMEL_HSMC_TIMINGS_TRR_SHIFT && + shift != ATMEL_HSMC_TIMINGS_TWB_SHIFT) + return -EINVAL; + + /* + * The formula described in atmel datasheets (section "HSMC Timings + * Register"): + * + * ncycles = (Txx[3] * 64) + Txx[2:0] + */ + ret = atmel_smc_cs_encode_ncycles(ncycles, 3, 1, 64, &val); + conf->timings &= ~GENMASK(shift + 3, shift); + conf->timings |= val << shift; + + return ret; +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_timing); + +/** + * atmel_smc_cs_conf_set_setup - set the SMC CS conf xx_SETUP parameter to a + * specific value + * @conf: SMC CS conf descriptor + * @shift: the position of the xx_SETUP field in the SETUP register + * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_SETUP + * parameter + * + * This function encodes the @ncycles value as described in the datasheet + * (section "SMC Setup 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 + * the field, and 0 otherwise. + */ +int atmel_smc_cs_conf_set_setup(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles) +{ + unsigned int val; + int ret; + + if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NCS_WR_SHIFT && + shift != ATMEL_SMC_NRD_SHIFT && shift != ATMEL_SMC_NCS_RD_SHIFT) + return -EINVAL; + + /* + * The formula described in atmel datasheets (section "SMC Setup + * Register"): + * + * ncycles = (128 * xx_SETUP[5]) + xx_SETUP[4:0] + */ + ret = atmel_smc_cs_encode_ncycles(ncycles, 5, 1, 128, &val); + conf->setup &= ~GENMASK(shift + 7, shift); + conf->setup |= val << shift; + + return ret; +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_setup); + +/** + * atmel_smc_cs_conf_set_pulse - set the SMC CS conf xx_PULSE parameter to a + * specific value + * @conf: SMC CS conf descriptor + * @shift: the position of the xx_PULSE field in the PULSE register + * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_PULSE + * parameter + * + * This function encodes the @ncycles value as described in the datasheet + * (section "SMC Pulse 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 + * the field, and 0 otherwise. + */ +int atmel_smc_cs_conf_set_pulse(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles) +{ + unsigned int val; + int ret; + + if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NCS_WR_SHIFT && + shift != ATMEL_SMC_NRD_SHIFT && shift != ATMEL_SMC_NCS_RD_SHIFT) + return -EINVAL; + + /* + * The formula described in atmel datasheets (section "SMC Pulse + * Register"): + * + * ncycles = (256 * xx_PULSE[6]) + xx_PULSE[5:0] + */ + ret = atmel_smc_cs_encode_ncycles(ncycles, 6, 1, 256, &val); + conf->pulse &= ~GENMASK(shift + 7, shift); + conf->pulse |= val << shift; + + return ret; +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_pulse); + +/** + * atmel_smc_cs_conf_set_cycle - set the SMC CS conf xx_CYCLE parameter to a + * specific value + * @conf: SMC CS conf descriptor + * @shift: the position of the xx_CYCLE field in the CYCLE register + * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_CYCLE + * parameter + * + * This function encodes the @ncycles value as described in the datasheet + * (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 + * the field, and 0 otherwise. + */ +int atmel_smc_cs_conf_set_cycle(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles) +{ + unsigned int val; + int ret; + + if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NRD_SHIFT) + return -EINVAL; + + /* + * The formula described in atmel datasheets (section "SMC Cycle + * Register"): + * + * ncycles = (xx_CYCLE[8:7] * 256) + xx_CYCLE[6:0] + */ + ret = atmel_smc_cs_encode_ncycles(ncycles, 7, 2, 256, &val); + conf->cycle &= ~GENMASK(shift + 15, shift); + conf->cycle |= val << shift; + + return ret; +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_cycle); + +/** + * atmel_smc_cs_conf_apply - apply an SMC CS conf + * @regmap: the SMC regmap + * @cs: the CS id + * @conf: the SMC CS conf to apply + * + * Applies an SMC CS configuration. + * Only valid on at91sam9/avr32 SoCs. + */ +void atmel_smc_cs_conf_apply(struct regmap *regmap, int cs, + const struct atmel_smc_cs_conf *conf) +{ + regmap_write(regmap, ATMEL_SMC_SETUP(cs), conf->setup); + regmap_write(regmap, ATMEL_SMC_PULSE(cs), conf->pulse); + regmap_write(regmap, ATMEL_SMC_CYCLE(cs), conf->cycle); + regmap_write(regmap, ATMEL_SMC_MODE(cs), conf->mode); +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply); + +/** + * atmel_hsmc_cs_conf_apply - apply an SMC CS conf + * @regmap: the HSMC regmap + * @cs: the CS id + * @layout: the layout of registers + * @conf: the SMC CS conf to apply + * + * Applies an SMC CS configuration. + * Only valid on post-sama5 SoCs. + */ +void atmel_hsmc_cs_conf_apply(struct regmap *regmap, + const struct atmel_hsmc_reg_layout *layout, + int cs, const struct atmel_smc_cs_conf *conf) +{ + regmap_write(regmap, ATMEL_HSMC_SETUP(layout, cs), conf->setup); + regmap_write(regmap, ATMEL_HSMC_PULSE(layout, cs), conf->pulse); + regmap_write(regmap, ATMEL_HSMC_CYCLE(layout, cs), conf->cycle); + regmap_write(regmap, ATMEL_HSMC_TIMINGS(layout, cs), conf->timings); + regmap_write(regmap, ATMEL_HSMC_MODE(layout, cs), conf->mode); +} +EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_apply); + +/** + * atmel_smc_cs_conf_get - retrieve the current SMC CS conf + * @regmap: the SMC regmap + * @cs: the CS id + * @conf: the SMC CS conf object to store the current conf + * + * Retrieve the SMC CS configuration. + * Only valid on at91sam9/avr32 SoCs. + */ +void atmel_smc_cs_conf_get(struct regmap *regmap, int cs, + struct atmel_smc_cs_conf *conf) +{ + regmap_read(regmap, ATMEL_SMC_SETUP(cs), &conf->setup); + regmap_read(regmap, ATMEL_SMC_PULSE(cs), &conf->pulse); + regmap_read(regmap, ATMEL_SMC_CYCLE(cs), &conf->cycle); + regmap_read(regmap, ATMEL_SMC_MODE(cs), &conf->mode); +} +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_get); + +/** + * atmel_hsmc_cs_conf_get - retrieve the current SMC CS conf + * @regmap: the HSMC regmap + * @cs: the CS id + * @layout: the layout of registers + * @conf: the SMC CS conf object to store the current conf + * + * Retrieve the SMC CS configuration. + * Only valid on post-sama5 SoCs. + */ +void atmel_hsmc_cs_conf_get(struct regmap *regmap, + const struct atmel_hsmc_reg_layout *layout, + int cs, struct atmel_smc_cs_conf *conf) +{ + regmap_read(regmap, ATMEL_HSMC_SETUP(layout, cs), &conf->setup); + regmap_read(regmap, ATMEL_HSMC_PULSE(layout, cs), &conf->pulse); + regmap_read(regmap, ATMEL_HSMC_CYCLE(layout, cs), &conf->cycle); + regmap_read(regmap, ATMEL_HSMC_TIMINGS(layout, cs), &conf->timings); + regmap_read(regmap, ATMEL_HSMC_MODE(layout, cs), &conf->mode); +} +EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_get); + +static const struct atmel_hsmc_reg_layout sama5d3_reg_layout = { + .timing_regs_offset = 0x600, +}; + +static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = { + .timing_regs_offset = 0x700, +}; + +static const struct of_device_id atmel_smc_ids[] = { + { .compatible = "atmel,at91sam9260-smc", .data = NULL }, + { .compatible = "atmel,sama5d3-smc", .data = &sama5d3_reg_layout }, + { .compatible = "atmel,sama5d2-smc", .data = &sama5d2_reg_layout }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, atmel_smc_ids); + +/** + * atmel_hsmc_get_reg_layout - retrieve the layout of HSMC registers + * @np: the HSMC regmap + * + * Retrieve the layout of HSMC registers. + * + * Returns NULL in case of SMC, a struct atmel_hsmc_reg_layout pointer + * in HSMC case, otherwise ERR_PTR(-EINVAL). + */ +const struct atmel_hsmc_reg_layout * +atmel_hsmc_get_reg_layout(struct device_node *np) +{ + const struct of_device_id *match; + + match = of_match_node(atmel_smc_ids, np); + + return match ? match->data : ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL_GPL(atmel_hsmc_get_reg_layout); diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index d0f6a0f394..bfd93902b4 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c @@ -19,9 +19,9 @@ #include <i2c/i2c.h> #include <module.h> #include <linux/mfd/axp20x.h> -#include <regmap.h> +#include <linux/regmap.h> -static int axp20x_i2c_probe(struct device_d *dev) +static int axp20x_i2c_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct axp20x_dev *axp20x; @@ -51,14 +51,16 @@ static const struct of_device_id axp20x_i2c_of_match[] = { { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID }, { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, + { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID }, { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, { }, }; +MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); -static struct driver_d axp20x_i2c_driver = { +static struct driver axp20x_i2c_driver = { .name = "axp20x-i2c", .probe = axp20x_i2c_probe, .of_compatible = DRV_OF_COMPAT(axp20x_i2c_of_match), diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index da1e8ce35a..666b9ea98c 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -23,7 +23,7 @@ #include <module.h> #include <of.h> #include <of_device.h> -#include <regmap.h> +#include <linux/regmap.h> #include <regulator.h> #define AXP20X_OFF BIT(7) @@ -38,6 +38,7 @@ static const char * const axp20x_model_names[] = { "AXP221", "AXP223", "AXP288", + "AXP313A", "AXP803", "AXP806", "AXP809", @@ -68,6 +69,12 @@ static const struct regmap_config axp288_regmap_config = { .max_register = AXP288_FG_TUNE5, }; +static const struct regmap_config axp313a_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = AXP313A_POK_CONTROL, +}; + static const struct regmap_config axp806_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -141,6 +148,9 @@ static const struct mfd_cell axp152_cells[] = { { .name = "axp20x-pek", }, + { + .name = "axp20x-regulator", + }, }; static const struct mfd_cell axp288_cells[] = { @@ -157,6 +167,13 @@ static const struct mfd_cell axp288_cells[] = { }, }; +static const struct mfd_cell axp313a_cells[] = { + { + .name = "axp313a-regulator" + }, +}; + + static const struct mfd_cell axp803_cells[] = { { .name = "axp221-pek", @@ -231,7 +248,7 @@ static void axp20x_power_off(struct poweroff_handler *handler) int axp20x_match_device(struct axp20x_dev *axp20x) { - struct device_d *dev = axp20x->dev; + struct device *dev = axp20x->dev; const struct of_device_id *of_id; of_id = of_match_device(dev->driver->of_compatible, dev); @@ -268,6 +285,11 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->nr_cells = ARRAY_SIZE(axp288_cells); axp20x->regmap_cfg = &axp288_regmap_config; break; + case AXP313A_ID: + axp20x->cells = axp313a_cells; + axp20x->nr_cells = ARRAY_SIZE(axp313a_cells); + axp20x->regmap_cfg = &axp313a_regmap_config; + break; case AXP803_ID: axp20x->nr_cells = ARRAY_SIZE(axp803_cells); axp20x->cells = axp803_cells; @@ -326,9 +348,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) * property "x-powers,master-mode" to override the default. */ if (axp20x->variant == AXP806_ID) { - if (of_property_read_bool(axp20x->dev->device_node, + if (of_property_read_bool(axp20x->dev->of_node, "x-powers,master-mode") || - of_property_read_bool(axp20x->dev->device_node, + of_property_read_bool(axp20x->dev->of_node, "x-powers,self-working-mode")) regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE); @@ -337,6 +359,8 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE); } + axp20x->dev->priv = axp20x; + ret = mfd_add_devices(axp20x->dev, axp20x->cells, axp20x->nr_cells); if (ret) return dev_err_probe(axp20x->dev, ret, "failed to add MFD devices\n"); @@ -346,11 +370,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) axp20x->poweroff.poweroff = axp20x_power_off; axp20x->poweroff.priority = 200; - if (axp20x->variant != AXP288_ID) + if (!(axp20x->variant == AXP288_ID) || (axp20x->variant == AXP313A_ID)) poweroff_handler_register(&axp20x->poweroff); - dev_info(axp20x->dev, "AXP20X driver loaded\n"); - return 0; } EXPORT_SYMBOL(axp20x_device_probe); diff --git a/drivers/mfd/core.c b/drivers/mfd/core.c index 495427ae9c..0868bbb905 100644 --- a/drivers/mfd/core.c +++ b/drivers/mfd/core.c @@ -3,9 +3,10 @@ #include <linux/mfd/core.h> #include <driver.h> -int mfd_add_devices(struct device_d *parent, const struct mfd_cell *cells, int n_devs) +int mfd_add_devices(struct device *parent, const struct mfd_cell *cells, + int n_devs) { - struct device_d *dev; + struct device *dev; int ret, i; for (i = 0; i < n_devs; i++) { diff --git a/drivers/mfd/da9053.c b/drivers/mfd/da9053.c index 99827c9689..cbfb62cef9 100644 --- a/drivers/mfd/da9053.c +++ b/drivers/mfd/da9053.c @@ -77,7 +77,7 @@ struct da9053_priv { struct watchdog wd; struct i2c_client *client; - struct device_d *dev; + struct device *dev; struct restart_handler restart; }; @@ -137,7 +137,7 @@ static int da9053_enable_multiwrite(struct da9053_priv *da9053) static int da9053_set_timeout(struct watchdog *wd, unsigned timeout) { struct da9053_priv *da9053 = wd_to_da9053_priv(wd); - struct device_d *dev = da9053->dev; + struct device *dev = da9053->dev; unsigned scale = 0; int ret; u8 val; @@ -251,7 +251,7 @@ static void __noreturn da9053_force_system_reset(struct restart_handler *rst) hang(); } -static int da9053_probe(struct device_d *dev) +static int da9053_probe(struct device *dev) { struct da9053_priv *da9053; int ret; @@ -272,7 +272,7 @@ static int da9053_probe(struct device_d *dev) da9053_detect_reset_source(da9053); - da9053->restart.priority = of_get_restart_priority(dev->device_node); + da9053->restart.of_node = dev->of_node; da9053->restart.name = "da9063"; da9053->restart.restart = &da9053_force_system_reset; @@ -288,8 +288,9 @@ static __maybe_unused struct of_device_id da9053_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, da9053_dt_ids); -static struct driver_d da9053_driver = { +static struct driver da9053_driver = { .name = DRIVERNAME, .probe = da9053_probe, .of_compatible = DRV_OF_COMPAT(da9053_dt_ids), diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c index a4e5226f3c..04bcad8804 100644 --- a/drivers/mfd/da9063.c +++ b/drivers/mfd/da9063.c @@ -22,7 +22,7 @@ struct da9063 { struct i2c_client *client; /* dummy client for accessing bank #1 */ struct i2c_client *client1; - struct device_d *dev; + struct device *dev; unsigned int timeout; uint64_t last_ping; }; @@ -253,7 +253,7 @@ static int da9063_watchdog_ping(struct da9063 *priv) static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout) { struct da9063 *priv = container_of(wd, struct da9063, wd); - struct device_d *dev = priv->dev; + struct device *dev = priv->dev; unsigned int scale = 0; int ret; @@ -356,7 +356,7 @@ static struct da906x_device_data const da9062_device_data = { .init = da9062_device_init, }; -static int da9063_probe(struct device_d *dev) +static int da9063_probe(struct device *dev) { struct da9063 *priv = NULL; struct da906x_device_data const *dev_data; @@ -383,7 +383,7 @@ static int da9063_probe(struct device_d *dev) da9063_detect_reset_source(priv); - priv->restart.priority = of_get_restart_priority(dev->device_node); + priv->restart.of_node = dev->of_node; priv->restart.name = "da9063"; priv->restart.restart = &da9063_restart; @@ -399,8 +399,8 @@ static int da9063_probe(struct device_d *dev) goto on_error; } - if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) - return of_platform_populate(dev->device_node, NULL, dev); + if (IS_ENABLED(CONFIG_OFDEVICE) && dev->of_node) + return of_platform_populate(dev->of_node, NULL, dev); return 0; @@ -426,8 +426,9 @@ static struct of_device_id const da906x_dt_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, da906x_dt_ids); -static struct driver_d da9063_driver = { +static struct driver da9063_driver = { .name = "da9063", .probe = da9063_probe, .id_table = da9063_id, diff --git a/drivers/mfd/lp3972.c b/drivers/mfd/lp3972.c index 934c4fe038..d72f697da5 100644 --- a/drivers/mfd/lp3972.c +++ b/drivers/mfd/lp3972.c @@ -63,7 +63,7 @@ static struct cdev_operations lp_fops = { .read = lp_read, }; -static int lp_probe(struct device_d *dev) +static int lp_probe(struct device *dev) { if (lp_dev) return -EBUSY; @@ -80,7 +80,7 @@ static int lp_probe(struct device_d *dev) return 0; } -static struct driver_d lp_driver = { +static struct driver lp_driver = { .name = DRIVERNAME, .probe = lp_probe, }; diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c index 1851950406..1e06a24b45 100644 --- a/drivers/mfd/mc13xxx.c +++ b/drivers/mfd/mc13xxx.c @@ -11,7 +11,7 @@ #include <errno.h> #include <malloc.h> #include <of.h> -#include <regmap.h> +#include <linux/regmap.h> #include <i2c/i2c.h> #include <spi/spi.h> @@ -22,7 +22,7 @@ #define MC13XXX_NUMREGS 0x3f struct mc13xxx { - struct device_d *dev; + struct device *dev; struct regmap *map; union { struct i2c_client *client; @@ -300,7 +300,7 @@ static const struct regmap_config mc13xxx_regmap_i2c_config = { }; #endif -static int __init mc13xxx_probe(struct device_d *dev) +static int __init mc13xxx_probe(struct device *dev) { struct mc13xxx_devtype *devtype; int ret, rev; @@ -353,7 +353,7 @@ static int __init mc13xxx_probe(struct device_d *dev) if (mc13xxx_init_callback) mc13xxx_init_callback(mc_dev); - if (of_property_read_bool(dev->device_node, "fsl,mc13xxx-uses-adc")) + if (of_property_read_bool(dev->of_node, "fsl,mc13xxx-uses-adc")) mc13xxx_adc_probe(dev, mc_dev); return 0; @@ -387,8 +387,9 @@ static __maybe_unused struct of_device_id mc13xxx_dt_ids[] = { { .compatible = "fsl,mc34708", .data = &mc34708_devtype, }, { } }; +MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids); -static __maybe_unused struct driver_d mc13xxx_i2c_driver = { +static __maybe_unused struct driver mc13xxx_i2c_driver = { .name = "mc13xxx-i2c", .probe = mc13xxx_probe, .id_table = mc13xxx_ids, @@ -399,7 +400,7 @@ static __maybe_unused struct driver_d mc13xxx_i2c_driver = { coredevice_i2c_driver(mc13xxx_i2c_driver); #endif -static __maybe_unused struct driver_d mc13xxx_spi_driver = { +static __maybe_unused struct driver mc13xxx_spi_driver = { .name = "mc13xxx-spi", .probe = mc13xxx_probe, .id_table = mc13xxx_ids, diff --git a/drivers/mfd/mc34704.c b/drivers/mfd/mc34704.c index 732542e34f..7a893ef8b7 100644 --- a/drivers/mfd/mc34704.c +++ b/drivers/mfd/mc34704.c @@ -93,7 +93,7 @@ static struct cdev_operations mc34704_fops = { .write = mc34704_write, }; -static int mc34704_probe(struct device_d *dev) +static int mc34704_probe(struct device *dev) { if (mc34704_dev) return -EBUSY; @@ -114,8 +114,9 @@ static __maybe_unused struct of_device_id mc34704_dt_ids[] = { { .compatible = "fsl,mc34704", }, { } }; +MODULE_DEVICE_TABLE(of, mc34704_dt_ids); -static struct driver_d mc34704_driver = { +static struct driver mc34704_driver = { .name = DRIVERNAME, .probe = mc34704_probe, .of_compatible = DRV_OF_COMPAT(mc34704_dt_ids), diff --git a/drivers/mfd/mc9sdz60.c b/drivers/mfd/mc9sdz60.c index f55733dae9..1f8a5611b4 100644 --- a/drivers/mfd/mc9sdz60.c +++ b/drivers/mfd/mc9sdz60.c @@ -105,7 +105,7 @@ static struct cdev_operations mc_fops = { .write = mc_write, }; -static int mc_probe(struct device_d *dev) +static int mc_probe(struct device *dev) { if (mc_dev) return -EBUSY; @@ -122,7 +122,7 @@ static int mc_probe(struct device_d *dev) return 0; } -static struct driver_d mc_driver = { +static struct driver mc_driver = { .name = DRIVERNAME, .probe = mc_probe, }; diff --git a/drivers/mfd/pca9450.c b/drivers/mfd/pca9450.c new file mode 100644 index 0000000000..8fa5363f8a --- /dev/null +++ b/drivers/mfd/pca9450.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Holger Assmann, Pengutronix + */ + +#include <common.h> +#include <driver.h> +#include <errno.h> +#include <i2c/i2c.h> +#include <init.h> +#include <mfd/pca9450.h> +#include <of.h> +#include <regmap.h> +#include <reset_source.h> + +#define REASON_PMIC_RST 0x10 +#define REASON_SW_RST 0x20 +#define REASON_WDOG 0x40 +#define REASON_PWON 0x80 + +static const struct regmap_config pca9450_regmap_i2c_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x2E, +}; + +static int pca9450_get_reset_source(struct device *dev, struct regmap *map) +{ + enum reset_src_type type; + int reg; + int ret; + + ret = regmap_read(map, PCA9450_PWRON_STAT, ®); + if (ret) + return ret; + + switch (reg) { + case REASON_PWON: + dev_dbg(dev, "Power ON triggered by PMIC_ON_REQ.\n"); + type = RESET_POR; + break; + case REASON_WDOG: + dev_dbg(dev, "Detected cold reset by WDOGB pin\n"); + type = RESET_WDG; + break; + case REASON_SW_RST: + dev_dbg(dev, "Detected cold reset by SW_RST\n"); + type = RESET_RST; + break; + case REASON_PMIC_RST: + dev_dbg(dev, "Detected cold reset by PMIC_RST_B\n"); + type = RESET_EXT; + break; + default: + dev_warn(dev, "Could not determine reset reason.\n"); + type = RESET_UKWN; + } + + reset_source_set_device(dev, type); + + return 0; +}; + +static struct regmap *pca9450_map; + +static void (*pca9450_init_callback)(struct regmap *map); + +int pca9450_register_init_callback(void(*callback)(struct regmap *map)) +{ + if (pca9450_init_callback) + return -EBUSY; + + pca9450_init_callback = callback; + + if (pca9450_map) + pca9450_init_callback(pca9450_map); + + return 0; +} + +static int __init pca9450_probe(struct device *dev) +{ + struct regmap *regmap; + int reg; + int ret; + + regmap = regmap_init_i2c(to_i2c_client(dev), &pca9450_regmap_i2c_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = regmap_register_cdev(regmap, NULL); + if (ret) + return ret; + + ret = regmap_read(regmap, PCA9450_REG_DEV_ID, ®); + if (ret) { + dev_err(dev, "Unable to read PMIC Chip ID\n"); + return ret; + } + + /* Chip ID defined in bits [7:4] */ + dev_info(dev, "PMIC Chip ID: 0x%x\n", (reg >> 4)); + + if (pca9450_init_callback) + pca9450_init_callback(regmap); + pca9450_map = regmap; + + pca9450_get_reset_source(dev,regmap); + + return of_platform_populate(dev->of_node, NULL, dev); +} + +static __maybe_unused struct of_device_id pca9450_dt_ids[] = { + { .compatible = "nxp,pca9450a" }, + { .compatible = "nxp,pca9450c" }, + { .compatible = "nxp,pca9451a" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pca9450_dt_ids); + +static struct driver pca9450_i2c_driver = { + .name = "pca9450-i2c", + .probe = pca9450_probe, + .of_compatible = DRV_OF_COMPAT(pca9450_dt_ids), +}; + +coredevice_i2c_driver(pca9450_i2c_driver); diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index 30d4bde5dc..c7968b75f5 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -185,7 +185,7 @@ struct rave_sp_variant { * @part_number_bootloader: Bootloader version */ struct rave_sp { - struct device_d dev; + struct device dev; struct serdev_device *serdev; struct rave_sp_deframer deframer; unsigned int ackid; @@ -310,7 +310,7 @@ int rave_sp_exec(struct rave_sp *sp, void *__data, size_t data_size, void *reply_data, size_t reply_data_size) { - struct device_d *dev = sp->serdev->dev; + struct device *dev = sp->serdev->dev; struct rave_sp_reply reply = { .data = reply_data, .length = reply_data_size, @@ -366,7 +366,7 @@ static void rave_sp_receive_event(struct rave_sp *sp, static void rave_sp_receive_reply(struct rave_sp *sp, const unsigned char *data, size_t length) { - struct device_d *dev = sp->serdev->dev; + struct device *dev = sp->serdev->dev; struct rave_sp_reply *reply; const size_t payload_length = length - 2; @@ -402,7 +402,7 @@ static void rave_sp_receive_frame(struct rave_sp *sp, const size_t checksum_length = sp->variant->checksum->length; const size_t payload_length = length - checksum_length; const u8 *crc_reported = &data[payload_length]; - struct device_d *dev = sp->serdev->dev; + struct device *dev = sp->serdev->dev; u8 crc_calculated[checksum_length]; print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE, 16, 1, @@ -430,7 +430,7 @@ static void rave_sp_receive_frame(struct rave_sp *sp, static int rave_sp_receive_buf(struct serdev_device *serdev, const unsigned char *buf, size_t size) { - struct device_d *dev = serdev->dev; + struct device *dev = serdev->dev; struct rave_sp *sp = dev->priv; struct rave_sp_deframer *deframer = &sp->deframer; const unsigned char *src = buf; @@ -603,7 +603,7 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command) } } -static const char *devm_rave_sp_version(struct device_d *dev, +static const char *devm_rave_sp_version(struct device *dev, struct rave_sp_version *version) { /* @@ -666,7 +666,7 @@ static int rave_sp_emulated_get_status(struct rave_sp *sp, static int rave_sp_get_status(struct rave_sp *sp) { - struct device_d *dev = sp->serdev->dev; + struct device *dev = sp->serdev->dev; struct rave_sp_status status; const char *mode; int ret; @@ -731,6 +731,7 @@ static const struct of_device_id __maybe_unused rave_sp_dt_ids[] = { { .compatible = "zii,rave-sp-rdu2", .data = &rave_sp_rdu2 }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, rave_sp_dt_ids); static int rave_sp_req_ip_addr(struct param_d *p, void *context) { @@ -766,7 +767,7 @@ static int rave_sp_req_ip_addr(struct param_d *p, void *context) static int rave_sp_add_params(struct rave_sp *sp) { - struct device_d *dev = &sp->dev; + struct device *dev = &sp->dev; struct param_d *p; int ret; @@ -788,14 +789,14 @@ static int rave_sp_add_params(struct rave_sp *sp) return PTR_ERR_OR_ZERO(p); } -static int rave_sp_probe(struct device_d *dev) +static int rave_sp_probe(struct device *dev) { struct serdev_device *serdev = to_serdev_device(dev->parent); struct rave_sp *sp; u32 baud; int ret; - if (of_property_read_u32(dev->device_node, "current-speed", &baud)) { + if (of_property_read_u32(dev->of_node, "current-speed", &baud)) { dev_err(dev, "'current-speed' is not specified in device node\n"); return -EINVAL; @@ -850,10 +851,10 @@ static int rave_sp_probe(struct device_d *dev) return ret; } - return of_platform_populate(dev->device_node, NULL, dev); + return of_platform_populate(dev->of_node, NULL, dev); } -static struct driver_d rave_sp_drv = { +static struct driver rave_sp_drv = { .name = "rave-sp", .probe = rave_sp_probe, .of_compatible = DRV_OF_COMPAT(rave_sp_dt_ids), diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 1b5b9d3a17..77493a7b5b 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -21,7 +21,7 @@ #include <driver.h> #include <poweroff.h> #include <of.h> -#include <regmap.h> +#include <linux/regmap.h> struct rk808_reg_data { int addr; @@ -224,6 +224,7 @@ static void rk808_poweroff(struct poweroff_handler *handler) reg = RK808_DEVCTRL_REG, bit = DEV_OFF_RST; break; + case RK809_ID: case RK817_ID: reg = RK817_SYS_CFG(3); bit = DEV_OFF; @@ -246,10 +247,10 @@ static void rk808_poweroff(struct poweroff_handler *handler) hang(); } -static int rk808_probe(struct device_d *dev) +static int rk808_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; struct rk808 *rk808; const struct rk808_reg_data *pre_init_reg; const struct mfd_cell *cells; @@ -380,8 +381,9 @@ static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk818" }, { }, }; +MODULE_DEVICE_TABLE(of, rk808_of_match); -static struct driver_d rk808_i2c_driver = { +static struct driver rk808_i2c_driver = { .name = "rk808", .of_compatible = rk808_of_match, .probe = rk808_probe, diff --git a/drivers/mfd/rn5t568.c b/drivers/mfd/rn5t568.c index c1c792cbec..f1e2eeb0c8 100644 --- a/drivers/mfd/rn5t568.c +++ b/drivers/mfd/rn5t568.c @@ -13,32 +13,10 @@ #include <i2c/i2c.h> #include <init.h> #include <of.h> -#include <regmap.h> +#include <linux/regmap.h> #include <reset_source.h> #include <restart.h> - -#define RN5T568_LSIVER 0x00 -#define RN5T568_OTPVER 0x01 -#define RN5T568_PONHIS 0x09 -# define RN5T568_PONHIS_ON_EXTINPON BIT(3) -# define RN5T568_PONHIS_ON_REPWRPON BIT(1) -# define RN5T568_PONHIS_ON_PWRONPON BIT(0) -#define RN5T568_POFFHIS 0x0a -# define RN5T568_POFFHIS_N_OEPOFF BIT(7) -# define RN5T568_POFFHIS_DCLIMPOFF BIT(6) -# define RN5T568_POFFHIS_WDGPOFF BIT(5) -# define RN5T568_POFFHIS_CPUPOFF BIT(4) -# define RN5T568_POFFHIS_IODETPOFF BIT(3) -# define RN5T568_POFFHIS_VINDETPOFF BIT(2) -# define RN5T568_POFFHIS_TSHUTPOFF BIT(1) -# define RN5T568_POFFHIS_PWRONPOFF BIT(0) -#define RN5T568_SLPCNT 0x0e -# define RN5T568_SLPCNT_SWPPWROFF BIT(0) -#define RN5T568_REPCNT 0x0f -# define RN5T568_REPCNT_OFF_RESETO_16MS 0x30 -# define RN5T568_REPCNT_OFF_REPWRTIM_1000MS 0x06 -# define RN5T568_REPCNT_OFF_REPWRON BIT(0) -#define RN5T568_MAX_REG 0xbc +#include <mfd/rn5t568.h> struct rn5t568 { struct restart_handler restart; @@ -52,7 +30,8 @@ static void rn5t568_restart(struct restart_handler *rst) regmap_write(rn5t568->regmap, RN5T568_SLPCNT, RN5T568_SLPCNT_SWPPWROFF); } -static int rn5t568_reset_reason_detect(struct device_d *dev, struct regmap *regmap) +static int rn5t568_reset_reason_detect(struct device *dev, + struct regmap *regmap) { unsigned int reg; int ret; @@ -111,7 +90,7 @@ static const struct regmap_config rn5t568_regmap_config = { .max_register = RN5T568_MAX_REG, }; -static int __init rn5t568_i2c_probe(struct device_d *dev) +static int __init rn5t568_i2c_probe(struct device *dev) { struct rn5t568 *pmic_instance; unsigned char reg[2]; @@ -138,7 +117,7 @@ static int __init rn5t568_i2c_probe(struct device_d *dev) regmap_write(pmic_instance->regmap, RN5T568_REPCNT, RN5T568_REPCNT_OFF_RESETO_16MS | RN5T568_REPCNT_OFF_REPWRTIM_1000MS | RN5T568_REPCNT_OFF_REPWRON); - pmic_instance->restart.priority = of_get_restart_priority(dev->device_node); + pmic_instance->restart.of_node = dev->of_node; pmic_instance->restart.name = "RN5T568"; pmic_instance->restart.restart = &rn5t568_restart; restart_handler_register(&pmic_instance->restart); @@ -148,15 +127,16 @@ static int __init rn5t568_i2c_probe(struct device_d *dev) if (ret) dev_warn(dev, "Failed to query reset reason\n"); - return of_platform_populate(dev->device_node, NULL, dev); + return of_platform_populate(dev->of_node, NULL, dev); } static __maybe_unused const struct of_device_id rn5t568_of_match[] = { { .compatible = "ricoh,rn5t568", .data = NULL, }, { } }; +MODULE_DEVICE_TABLE(of, rn5t568_of_match); -static struct driver_d rn5t568_i2c_driver = { +static struct driver rn5t568_i2c_driver = { .name = "rn5t568-i2c", .probe = rn5t568_i2c_probe, .of_compatible = DRV_OF_COMPAT(rn5t568_of_match), diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c new file mode 100644 index 0000000000..e317a29ce5 --- /dev/null +++ b/drivers/mfd/rohm-bd718x7.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Copyright (C) 2018 ROHM Semiconductors +// +// ROHM BD71837MWV and BD71847MWV PMIC driver +// +// Datasheet for BD71837MWV available from +// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e + +#include <common.h> +#include <i2c/i2c.h> +#include <mfd/bd71837.h> +#include <linux/mfd/core.h> +#include <driver.h> +#include <poweroff.h> +#include <of.h> +#include <linux/regmap.h> + +static struct mfd_cell bd71837_mfd_cells[] = { + { .name = "gpio-keys", }, + { .name = "bd71837-clk", }, + { .name = "bd71837-pmic", }, +}; + +static struct mfd_cell bd71847_mfd_cells[] = { + { .name = "gpio-keys", }, + { .name = "bd71847-clk", }, + { .name = "bd71847-pmic", }, +}; + +static const struct regmap_config bd718xx_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = BD718XX_MAX_REGISTER - 1, +}; + +static int bd718xx_init_press_duration(struct regmap *regmap, + struct device *dev) +{ + u32 short_press_ms, long_press_ms; + u32 short_press_value, long_press_value; + int ret; + + ret = of_property_read_u32(dev->of_node, "rohm,short-press-ms", + &short_press_ms); + if (!ret) { + short_press_value = min(15u, (short_press_ms + 250) / 500); + ret = regmap_update_bits(regmap, BD718XX_PWRONCONFIG0, + BD718XX_PWRBTN_PRESS_DURATION_MASK, + short_press_value); + if (ret) { + dev_err(dev, "Failed to init pwron short press\n"); + return ret; + } + } + + ret = of_property_read_u32(dev->of_node, "rohm,long-press-ms", + &long_press_ms); + if (!ret) { + long_press_value = min(15u, (long_press_ms + 500) / 1000); + ret = regmap_update_bits(regmap, BD718XX_PWRONCONFIG1, + BD718XX_PWRBTN_PRESS_DURATION_MASK, + long_press_value); + if (ret) { + dev_err(dev, "Failed to init pwron long press\n"); + return ret; + } + } + + return 0; +} + +static int bd718xx_i2c_probe(struct device *dev) +{ + struct i2c_client *i2c = to_i2c_client(dev); + struct regmap *regmap; + int ret; + unsigned int chip_type; + struct mfd_cell *mfd; + int cells; + + chip_type = (unsigned int)(uintptr_t)device_get_match_data(dev); + switch (chip_type) { + case ROHM_CHIP_TYPE_BD71837: + mfd = bd71837_mfd_cells; + cells = ARRAY_SIZE(bd71837_mfd_cells); + break; + case ROHM_CHIP_TYPE_BD71847: + mfd = bd71847_mfd_cells; + cells = ARRAY_SIZE(bd71847_mfd_cells); + break; + default: + dev_err(dev, "Unknown device type"); + return -EINVAL; + } + + regmap = regmap_init_i2c(i2c, &bd718xx_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "regmap initialization failed\n"); + return PTR_ERR(regmap); + } + + ret = bd718xx_init_press_duration(regmap, dev); + if (ret) + return ret; + + ret = mfd_add_devices(dev, mfd, cells); + if (ret) + dev_err(dev, "Failed to create subdevices\n"); + + return regmap_register_cdev(regmap, NULL); +} + +static const struct of_device_id bd718xx_of_match[] = { + { + .compatible = "rohm,bd71837", + .data = (void *)ROHM_CHIP_TYPE_BD71837, + }, + { + .compatible = "rohm,bd71847", + .data = (void *)ROHM_CHIP_TYPE_BD71847, + }, + { + .compatible = "rohm,bd71850", + .data = (void *)ROHM_CHIP_TYPE_BD71847, + }, + { } +}; +MODULE_DEVICE_TABLE(of, bd718xx_of_match); + +static struct driver bd718xx_i2c_driver = { + .name = "rohm-bd718x7", + .of_match_table = bd718xx_of_match, + .probe = bd718xx_i2c_probe, +}; +coredevice_i2c_driver(bd718xx_i2c_driver); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("ROHM BD71837/BD71847 Power Management IC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c index 4814c06a62..3b47800105 100644 --- a/drivers/mfd/stm32-timers.c +++ b/drivers/mfd/stm32-timers.c @@ -11,6 +11,7 @@ #include <io.h> #include <linux/bitfield.h> #include <linux/mfd/stm32-timers.h> +#include <linux/regmap.h> #include <of.h> #include <linux/reset.h> @@ -34,7 +35,7 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata) regmap_write(ddata->regmap, TIM_ARR, 0x0); } -static int stm32_timers_probe(struct device_d *dev) +static int stm32_timers_probe(struct device *dev) { struct stm32_timers *ddata; struct resource *res; @@ -58,15 +59,16 @@ static int stm32_timers_probe(struct device_d *dev) dev->priv = ddata; - return of_platform_populate(dev->device_node, NULL, dev); + return of_platform_populate(dev->of_node, NULL, dev); } static const struct of_device_id stm32_timers_of_match[] = { { .compatible = "st,stm32-timers", }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(of, stm32_timers_of_match); -static struct driver_d stm32_timers_driver = { +static struct driver stm32_timers_driver = { .name = "stm32-timers", .probe = stm32_timers_probe, .of_compatible = stm32_timers_of_match, diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 37cf6b8b36..08dc48246e 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -95,17 +95,17 @@ static struct cdev_operations stmpe_fops = { .write = stmpe_write, }; -static struct stmpe_platform_data *stmpe_of_probe(struct device_d *dev) +static struct stmpe_platform_data *stmpe_of_probe(struct device *dev) { struct stmpe_platform_data *pdata; struct device_node *node; - if (!IS_ENABLED(CONFIG_OFDEVICE) || !dev->device_node) + if (!IS_ENABLED(CONFIG_OFDEVICE) || !dev->of_node) return NULL; pdata = xzalloc(sizeof(*pdata)); - for_each_child_of_node(dev->device_node, node) { + for_each_child_of_node(dev->of_node, node) { if (!strcmp(node->name, "stmpe_gpio")) { pdata->blocks |= STMPE_BLOCK_GPIO; } @@ -114,7 +114,7 @@ static struct stmpe_platform_data *stmpe_of_probe(struct device_d *dev) return pdata; } -static int stmpe_probe(struct device_d *dev) +static int stmpe_probe(struct device *dev) { struct stmpe_platform_data *pdata = dev->platform_data; struct stmpe *stmpe_dev; @@ -156,7 +156,7 @@ static struct platform_device_id stmpe_i2c_id[] = { { } }; -static struct driver_d stmpe_driver = { +static struct driver stmpe_driver = { .name = DRIVERNAME, .probe = stmpe_probe, .id_table = stmpe_i2c_id, diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c index 1de5afa2ef..9985673aa6 100644 --- a/drivers/mfd/stpmic1.c +++ b/drivers/mfd/stpmic1.c @@ -9,7 +9,7 @@ #include <i2c/i2c.h> #include <init.h> #include <of.h> -#include <regmap.h> +#include <linux/regmap.h> #include <linux/mfd/stpmic1.h> static const struct regmap_config stpmic1_regmap_i2c_config = { @@ -18,7 +18,7 @@ static const struct regmap_config stpmic1_regmap_i2c_config = { .max_register = 0xB3, }; -static int __init stpmic1_probe(struct device_d *dev) +static int __init stpmic1_probe(struct device *dev) { struct regmap *regmap; u32 reg; @@ -39,15 +39,16 @@ static int __init stpmic1_probe(struct device_d *dev) } dev_info(dev, "PMIC Chip Version: 0x%x\n", reg); - return of_platform_populate(dev->device_node, NULL, dev); + return of_platform_populate(dev->of_node, NULL, dev); } static __maybe_unused struct of_device_id stpmic1_dt_ids[] = { { .compatible = "st,stpmic1" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, stpmic1_dt_ids); -static struct driver_d stpmic1_i2c_driver = { +static struct driver stpmic1_i2c_driver = { .name = "stpmic1-i2c", .probe = stpmic1_probe, .of_compatible = DRV_OF_COMPAT(stpmic1_dt_ids), diff --git a/drivers/mfd/superio.c b/drivers/mfd/superio.c index bfb2f15dd2..16d0bba450 100644 --- a/drivers/mfd/superio.c +++ b/drivers/mfd/superio.c @@ -7,11 +7,11 @@ #include <common.h> #include <superio.h> -#include <regmap.h> +#include <linux/regmap.h> -struct device_d *superio_func_add(struct superio_chip *siochip, const char *name) +struct device *superio_func_add(struct superio_chip *siochip, const char *name) { - struct device_d *dev; + struct device *dev; int ret; dev = device_alloc(name, DEVICE_ID_DYNAMIC); diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index d0f2f0917e..3c2e1241fd 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -16,6 +16,7 @@ #include <of_address.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/regmap.h> #include <mfd/syscon.h> @@ -73,8 +74,6 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) syscon_config.val_bits = reg_io_width * 8; syscon_config.max_register = resource_size(&res) - reg_io_width; - list_add_tail(&syscon->list, &syscon_list); - syscon->regmap = regmap_init_mmio_clk(NULL, NULL, syscon->base, &syscon_config); @@ -92,6 +91,8 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) } } + list_add_tail(&syscon->list, &syscon_list); + return syscon; err_map: @@ -142,21 +143,6 @@ static void __iomem *syscon_node_to_base(struct device_node *np) return syscon->base; } -void __iomem *syscon_base_lookup_by_pdevname(const char *s) -{ - struct syscon *syscon; - struct device_d *dev; - - for_each_device(dev) { - if (!strcmp(dev_name(dev), s)) { - syscon = dev->priv; - return syscon->base; - } - } - - return ERR_PTR(-ENODEV); -} - void __iomem *syscon_base_lookup_by_phandle(struct device_node *np, const char *property) { @@ -231,7 +217,7 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, return regmap; } -static int syscon_probe(struct device_d *dev) +static int syscon_probe(struct device *dev) { struct syscon *syscon; struct resource *res; @@ -257,7 +243,7 @@ static struct platform_device_id syscon_ids[] = { { } }; -static struct driver_d syscon_driver = { +static struct driver syscon_driver = { .name = "syscon", .probe = syscon_probe, .id_table = syscon_ids, diff --git a/drivers/mfd/twl4030.c b/drivers/mfd/twl4030.c index 072a49cb62..7acf9b18bd 100644 --- a/drivers/mfd/twl4030.c +++ b/drivers/mfd/twl4030.c @@ -26,7 +26,7 @@ struct twl4030 *twl4030_get(void) } EXPORT_SYMBOL(twl4030_get); -static int twl_probe(struct device_d *dev) +static int twl_probe(struct device *dev) { if (twl_dev) return -EBUSY; @@ -43,7 +43,7 @@ static int twl_probe(struct device_d *dev) return 0; } -static struct driver_d twl_driver = { +static struct driver twl_driver = { .name = DRIVERNAME, .probe = twl_probe, }; diff --git a/drivers/mfd/twl6030.c b/drivers/mfd/twl6030.c index 1ed0e25c3a..d7a7d9baf8 100644 --- a/drivers/mfd/twl6030.c +++ b/drivers/mfd/twl6030.c @@ -23,7 +23,7 @@ struct twl6030 *twl6030_get(void) } EXPORT_SYMBOL(twl6030_get); -static int twl_probe(struct device_d *dev) +static int twl_probe(struct device *dev) { if (twl_dev) return -EBUSY; @@ -61,7 +61,7 @@ static int twl_probe(struct device_d *dev) return 0; } -static struct driver_d twl_driver = { +static struct driver twl_driver = { .name = DRIVERNAME, .probe = twl_probe, }; |