summaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig36
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/act8846.c4
-rw-r--r--drivers/mfd/atmel-flexcom.c9
-rw-r--r--drivers/mfd/atmel-smc.c355
-rw-r--r--drivers/mfd/axp20x-i2c.c73
-rw-r--r--drivers/mfd/axp20x.c382
-rw-r--r--drivers/mfd/core.c5
-rw-r--r--drivers/mfd/da9053.c11
-rw-r--r--drivers/mfd/da9063.c15
-rw-r--r--drivers/mfd/lp3972.c4
-rw-r--r--drivers/mfd/mc13xxx.c13
-rw-r--r--drivers/mfd/mc34704.c5
-rw-r--r--drivers/mfd/mc9sdz60.c4
-rw-r--r--drivers/mfd/pca9450.c127
-rw-r--r--drivers/mfd/rave-sp.c25
-rw-r--r--drivers/mfd/rk808.c10
-rw-r--r--drivers/mfd/rn5t568.c38
-rw-r--r--drivers/mfd/rohm-bd718x7.c140
-rw-r--r--drivers/mfd/stm32-timers.c8
-rw-r--r--drivers/mfd/stmpe-i2c.c10
-rw-r--r--drivers/mfd/stpmic1.c9
-rw-r--r--drivers/mfd/superio.c6
-rw-r--r--drivers/mfd/syscon.c24
-rw-r--r--drivers/mfd/twl4030.c4
-rw-r--r--drivers/mfd/twl6030.c4
26 files changed, 1210 insertions, 115 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6c6b65dacf..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,10 +120,37 @@ 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.
This driver provides common support for accessing the device
through I2C interface.
+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 7b5d0398d1..00f3eacf3c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -22,3 +22,7 @@ obj-$(CONFIG_SMSC_SUPERIO) += smsc-superio.o
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
new file mode 100644
index 0000000000..bfd93902b4
--- /dev/null
+++ b/drivers/mfd/axp20x-i2c.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * I2C driver for the X-Powers' Power Management ICs
+ *
+ * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
+ * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
+ * as well as configurable GPIOs.
+ *
+ * This driver supports the I2C variants.
+ *
+ * Copyright (C) 2014 Carlo Caione
+ *
+ * Author: Carlo Caione <carlo@caione.org>
+ */
+
+#include <common.h>
+#include <of.h>
+#include <linux/err.h>
+#include <i2c/i2c.h>
+#include <module.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regmap.h>
+
+static int axp20x_i2c_probe(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct axp20x_dev *axp20x;
+ int ret;
+
+ axp20x = xzalloc(sizeof(*axp20x));
+
+ axp20x->dev = dev;
+
+ ret = axp20x_match_device(axp20x);
+ if (ret)
+ return ret;
+
+ axp20x->regmap = regmap_init_i2c(client, axp20x->regmap_cfg);
+ if (IS_ERR(axp20x->regmap))
+ return dev_err_probe(dev, PTR_ERR(axp20x->regmap),
+ "regmap init failed\n");
+
+ ret = axp20x_device_probe(axp20x);
+ if (ret)
+ return ret;
+
+ return regmap_register_cdev(axp20x->regmap, NULL);
+}
+
+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 axp20x_i2c_driver = {
+ .name = "axp20x-i2c",
+ .probe = axp20x_i2c_probe,
+ .of_compatible = DRV_OF_COMPAT(axp20x_i2c_of_match),
+};
+
+coredevice_i2c_driver(axp20x_i2c_driver);
+
+MODULE_DESCRIPTION("PMIC MFD I2C driver for AXP20X");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
new file mode 100644
index 0000000000..666b9ea98c
--- /dev/null
+++ b/drivers/mfd/axp20x.c
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MFD core driver for the X-Powers' Power Management ICs
+ *
+ * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
+ * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
+ * as well as configurable GPIOs.
+ *
+ * This file contains the interface independent core functions.
+ *
+ * Copyright (C) 2014 Carlo Caione
+ *
+ * Author: Carlo Caione <carlo@caione.org>
+ */
+
+#include <common.h>
+#include <linux/bitops.h>
+#include <clock.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/mfd/core.h>
+#include <module.h>
+#include <of.h>
+#include <of_device.h>
+#include <linux/regmap.h>
+#include <regulator.h>
+
+#define AXP20X_OFF BIT(7)
+
+#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE 0
+#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
+
+static const char * const axp20x_model_names[] = {
+ "AXP152",
+ "AXP202",
+ "AXP209",
+ "AXP221",
+ "AXP223",
+ "AXP288",
+ "AXP313A",
+ "AXP803",
+ "AXP806",
+ "AXP809",
+ "AXP813",
+};
+
+static const struct regmap_config axp152_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = AXP152_PWM1_DUTY_CYCLE,
+};
+
+static const struct regmap_config axp20x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = AXP20X_OCV(AXP20X_OCV_MAX),
+};
+
+static const struct regmap_config axp22x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = AXP22X_BATLOW_THRES1,
+};
+
+static const struct regmap_config axp288_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .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,
+ .max_register = AXP806_REG_ADDR_EXT,
+};
+
+static const struct mfd_cell axp20x_cells[] = {
+ {
+ .name = "axp20x-gpio",
+ /* .of_compatible = "x-powers,axp209-gpio", */
+ }, {
+ .name = "axp20x-pek",
+ }, {
+ .name = "axp20x-regulator",
+ }, {
+ .name = "axp20x-adc",
+ /* .of_compatible = "x-powers,axp209-adc", */
+ }, {
+ .name = "axp20x-battery-power-supply",
+ /* .of_compatible = "x-powers,axp209-battery-power-supply", */
+ }, {
+ .name = "axp20x-ac-power-supply",
+ /* .of_compatible = "x-powers,axp202-ac-power-supply", */
+ }, {
+ .name = "axp20x-usb-power-supply",
+ /* .of_compatible = "x-powers,axp202-usb-power-supply", */
+ },
+};
+
+static const struct mfd_cell axp221_cells[] = {
+ {
+ .name = "axp221-pek",
+ }, {
+ .name = "axp20x-regulator",
+ }, {
+ .name = "axp22x-adc",
+ /* .of_compatible = "x-powers,axp221-adc", */
+ }, {
+ .name = "axp20x-ac-power-supply",
+ /* .of_compatible = "x-powers,axp221-ac-power-supply", */
+ }, {
+ .name = "axp20x-battery-power-supply",
+ /* .of_compatible = "x-powers,axp221-battery-power-supply", */
+ }, {
+ .name = "axp20x-usb-power-supply",
+ /* .of_compatible = "x-powers,axp221-usb-power-supply", */
+ },
+};
+
+static const struct mfd_cell axp223_cells[] = {
+ {
+ .name = "axp221-pek",
+ }, {
+ .name = "axp22x-adc",
+ /* .of_compatible = "x-powers,axp221-adc", */
+ }, {
+ .name = "axp20x-battery-power-supply",
+ /* .of_compatible = "x-powers,axp221-battery-power-supply", */
+ }, {
+ .name = "axp20x-regulator",
+ }, {
+ .name = "axp20x-ac-power-supply",
+ /* .of_compatible = "x-powers,axp221-ac-power-supply", */
+ }, {
+ .name = "axp20x-usb-power-supply",
+ /* .of_compatible = "x-powers,axp223-usb-power-supply", */
+ },
+};
+
+static const struct mfd_cell axp152_cells[] = {
+ {
+ .name = "axp20x-pek",
+ },
+ {
+ .name = "axp20x-regulator",
+ },
+};
+
+static const struct mfd_cell axp288_cells[] = {
+ {
+ .name = "axp288_adc",
+ }, {
+ .name = "axp288_extcon",
+ }, {
+ .name = "axp288_charger",
+ }, {
+ .name = "axp221-pek",
+ }, {
+ .name = "axp288_pmic_acpi",
+ },
+};
+
+static const struct mfd_cell axp313a_cells[] = {
+ {
+ .name = "axp313a-regulator"
+ },
+};
+
+
+static const struct mfd_cell axp803_cells[] = {
+ {
+ .name = "axp221-pek",
+ }, {
+ .name = "axp20x-gpio",
+ /* .of_compatible = "x-powers,axp813-gpio", */
+ }, {
+ .name = "axp813-adc",
+ /* .of_compatible = "x-powers,axp813-adc", */
+ }, {
+ .name = "axp20x-battery-power-supply",
+ /* .of_compatible = "x-powers,axp813-battery-power-supply", */
+ }, {
+ .name = "axp20x-ac-power-supply",
+ /* .of_compatible = "x-powers,axp813-ac-power-supply", */
+ }, {
+ .name = "axp20x-usb-power-supply",
+ /* .of_compatible = "x-powers,axp813-usb-power-supply", */
+ },
+ { .name = "axp20x-regulator" },
+};
+
+static const struct mfd_cell axp806_cells[] = {
+ {
+ .name = "axp20x-regulator",
+ },
+};
+
+static const struct mfd_cell axp809_cells[] = {
+ {
+ .name = "axp221-pek",
+ }, {
+ .name = "axp20x-regulator",
+ },
+};
+
+static const struct mfd_cell axp813_cells[] = {
+ {
+ .name = "axp221-pek",
+ }, {
+ .name = "axp20x-regulator",
+ }, {
+ .name = "axp20x-gpio",
+ /* .of_compatible = "x-powers,axp813-gpio", */
+ }, {
+ .name = "axp813-adc",
+ /* .of_compatible = "x-powers,axp813-adc", */
+ }, {
+ .name = "axp20x-battery-power-supply",
+ /* .of_compatible = "x-powers,axp813-battery-power-supply", */
+ }, {
+ .name = "axp20x-ac-power-supply",
+ /* .of_compatible = "x-powers,axp813-ac-power-supply", */
+ }, {
+ .name = "axp20x-usb-power-supply",
+ /* .of_compatible = "x-powers,axp813-usb-power-supply", */
+ },
+};
+
+static void axp20x_power_off(struct poweroff_handler *handler)
+{
+ struct axp20x_dev *axp20x = container_of(handler, struct axp20x_dev, poweroff);
+
+ regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
+
+ shutdown_barebox();
+
+ /* Give capacitors etc. time to drain to avoid kernel panic msg. */
+ mdelay(500);
+ hang();
+}
+
+int axp20x_match_device(struct axp20x_dev *axp20x)
+{
+ struct device *dev = axp20x->dev;
+ const struct of_device_id *of_id;
+
+ of_id = of_match_device(dev->driver->of_compatible, dev);
+ if (!of_id) {
+ dev_err(dev, "Unable to match OF ID\n");
+ return -ENODEV;
+ }
+ axp20x->variant = (long)of_id->data;
+
+ switch (axp20x->variant) {
+ case AXP152_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp152_cells);
+ axp20x->cells = axp152_cells;
+ axp20x->regmap_cfg = &axp152_regmap_config;
+ break;
+ case AXP202_ID:
+ case AXP209_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
+ axp20x->cells = axp20x_cells;
+ axp20x->regmap_cfg = &axp20x_regmap_config;
+ break;
+ case AXP221_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp221_cells);
+ axp20x->cells = axp221_cells;
+ axp20x->regmap_cfg = &axp22x_regmap_config;
+ break;
+ case AXP223_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp223_cells);
+ axp20x->cells = axp223_cells;
+ axp20x->regmap_cfg = &axp22x_regmap_config;
+ break;
+ case AXP288_ID:
+ axp20x->cells = axp288_cells;
+ 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;
+ axp20x->regmap_cfg = &axp288_regmap_config;
+ break;
+ case AXP806_ID:
+ /*
+ * Don't register the power key part if in slave mode or
+ * if there is no interrupt line.
+ */
+ axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
+ axp20x->cells = axp806_cells;
+ axp20x->regmap_cfg = &axp806_regmap_config;
+ break;
+ case AXP809_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp809_cells);
+ axp20x->cells = axp809_cells;
+ axp20x->regmap_cfg = &axp22x_regmap_config;
+ break;
+ case AXP813_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp813_cells);
+ axp20x->cells = axp813_cells;
+ axp20x->regmap_cfg = &axp288_regmap_config;
+ break;
+ default:
+ dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
+ return -EINVAL;
+ }
+ dev_info(dev, "AXP20x variant %s found\n",
+ axp20x_model_names[axp20x->variant]);
+
+ return 0;
+}
+EXPORT_SYMBOL(axp20x_match_device);
+
+int axp20x_device_probe(struct axp20x_dev *axp20x)
+{
+ int ret;
+
+ /*
+ * The AXP806 supports either master/standalone or slave mode.
+ * Slave mode allows sharing the serial bus, even with multiple
+ * AXP806 which all have the same hardware address.
+ *
+ * This is done with extra "serial interface address extension",
+ * or AXP806_BUS_ADDR_EXT, and "register address extension", or
+ * AXP806_REG_ADDR_EXT, registers. The former is read-only, with
+ * 1 bit customizable at the factory, and 1 bit depending on the
+ * state of an external pin. The latter is writable. The device
+ * will only respond to operations to its other registers when
+ * the these device addressing bits (in the upper 4 bits of the
+ * registers) match.
+ *
+ * By default we support an AXP806 chained to an AXP809 in slave
+ * mode. Boards which use an AXP806 in master mode can set the
+ * property "x-powers,master-mode" to override the default.
+ */
+ if (axp20x->variant == AXP806_ID) {
+ if (of_property_read_bool(axp20x->dev->of_node,
+ "x-powers,master-mode") ||
+ 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);
+ else
+ regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
+ 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");
+
+
+ axp20x->poweroff.name = "axp20x-poweroff";
+ axp20x->poweroff.poweroff = axp20x_power_off;
+ axp20x->poweroff.priority = 200;
+
+ if (!(axp20x->variant == AXP288_ID) || (axp20x->variant == AXP313A_ID))
+ poweroff_handler_register(&axp20x->poweroff);
+
+ return 0;
+}
+EXPORT_SYMBOL(axp20x_device_probe);
+
+MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_LICENSE("GPL");
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, &reg);
+ 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, &reg);
+ 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,
};