summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mfd/lp87565.txt36
-rw-r--r--Documentation/devicetree/bindings/mfd/rk808.txt44
-rw-r--r--Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt102
-rw-r--r--drivers/clk/Kconfig15
-rw-r--r--drivers/clk/clk-bd718x7.c24
-rw-r--r--drivers/clk/clk-rk808.c64
-rw-r--r--drivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-bd70528.c232
-rw-r--r--drivers/mfd/Kconfig23
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/lp87565.c4
-rw-r--r--drivers/mfd/rk808.c192
-rw-r--r--drivers/mfd/rohm-bd70528.c316
-rw-r--r--drivers/mfd/rohm-bd718x7.c23
-rw-r--r--drivers/power/supply/Kconfig9
-rw-r--r--drivers/power/supply/Makefile1
-rw-r--r--drivers/power/supply/bd70528-charger.c743
-rw-r--r--drivers/regulator/Kconfig4
-rw-r--r--drivers/regulator/bd718x7-regulator.c25
-rw-r--r--drivers/regulator/lp87565-regulator.c18
-rw-r--r--drivers/regulator/rk808-regulator.c646
-rw-r--r--drivers/rtc/Kconfig12
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-bd70528.c500
-rw-r--r--drivers/rtc/rtc-rk808.c68
-rw-r--r--include/linux/mfd/lp87565.h2
-rw-r--r--include/linux/mfd/rk808.h175
-rw-r--r--include/linux/mfd/rohm-bd70528.h408
-rw-r--r--include/linux/mfd/rohm-bd718x7.h22
-rw-r--r--include/linux/mfd/rohm-generic.h20
31 files changed, 3640 insertions, 103 deletions
diff --git a/Documentation/devicetree/bindings/mfd/lp87565.txt b/Documentation/devicetree/bindings/mfd/lp87565.txt
index a48df7c08ab0..41671e0dc26b 100644
--- a/Documentation/devicetree/bindings/mfd/lp87565.txt
+++ b/Documentation/devicetree/bindings/mfd/lp87565.txt
@@ -41,3 +41,39 @@ lp87565_pmic: pmic@60 {
};
};
};
+
+TI LP87561 PMIC:
+
+This is a single output 4-phase regulator configuration
+
+Required properties:
+ - compatible: "ti,lp87561-q1"
+ - reg: I2C slave address.
+ - gpio-controller: Marks the device node as a GPIO Controller.
+ - #gpio-cells: Should be two. The first cell is the pin number and
+ the second cell is used to specify flags.
+ See ../gpio/gpio.txt for more information.
+ - xxx-in-supply: Phandle to parent supply node of each regulator
+ populated under regulators node. xxx should match
+ the supply_name populated in driver.
+Example:
+
+lp87561_pmic: pmic@62 {
+ compatible = "ti,lp87561-q1";
+ reg = <0x62>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ buck3210-in-supply = <&vsys_3v3>;
+
+ regulators: regulators {
+ buck3210_reg: buck3210 {
+ /* VDD_CORE */
+ regulator-name = "buck3210";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt
index 1683ec3245bc..04df07f6f793 100644
--- a/Documentation/devicetree/bindings/mfd/rk808.txt
+++ b/Documentation/devicetree/bindings/mfd/rk808.txt
@@ -3,11 +3,15 @@ RK8XX Power Management Integrated Circuit
The rk8xx family current members:
rk805
rk808
+rk809
+rk817
rk818
Required properties:
- compatible: "rockchip,rk805"
- compatible: "rockchip,rk808"
+- compatible: "rockchip,rk809"
+- compatible: "rockchip,rk817"
- compatible: "rockchip,rk818"
- reg: I2C slave address
- interrupts: the interrupt outputs of the controller.
@@ -45,6 +49,23 @@ Optional RK808 properties:
the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
very quickly with no slow ramp time.
+Optional shared RK809 and RK817 properties:
+- vcc1-supply: The input supply for DCDC_REG1
+- vcc2-supply: The input supply for DCDC_REG2
+- vcc3-supply: The input supply for DCDC_REG3
+- vcc4-supply: The input supply for DCDC_REG4
+- vcc5-supply: The input supply for LDO_REG1, LDO_REG2, LDO_REG3
+- vcc6-supply: The input supply for LDO_REG4, LDO_REG5, LDO_REG6
+- vcc7-supply: The input supply for LDO_REG7, LDO_REG8, LDO_REG9
+
+Optional RK809 properties:
+- vcc8-supply: The input supply for SWITCH_REG1
+- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2
+
+Optional RK817 properties:
+- vcc8-supply: The input supply for BOOST
+- vcc9-supply: The input supply for OTG_SWITCH
+
Optional RK818 properties:
- vcc1-supply: The input supply for DCDC_REG1
- vcc2-supply: The input supply for DCDC_REG2
@@ -86,6 +107,21 @@ number as described in RK808 datasheet.
- SWITCH_REGn
- valid values for n are 1 to 2
+Following regulators of the RK809 and RK817 PMIC blocks are supported. Note that
+the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
+number as described in RK809 and RK817 datasheets.
+
+ - DCDC_REGn
+ - valid values for n are 1 to 5 for RK809.
+ - valid values for n are 1 to 4 for RK817.
+ - LDO_REGn
+ - valid values for n are 1 to 9 for RK809.
+ - valid values for n are 1 to 9 for RK817.
+ - SWITCH_REGn
+ - valid values for n are 1 to 2 for RK809.
+ - BOOST for RK817
+ - OTG_SWITCH for RK817
+
Following regulators of the RK818 PMIC block are supported. Note that
the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
number as described in RK818 datasheet.
@@ -98,6 +134,14 @@ number as described in RK818 datasheet.
- HDMI_SWITCH
- OTG_SWITCH
+It is necessary to configure three pins for both the RK809 and RK817, the three
+pins are "gpio_ts" "gpio_gt" "gpio_slp".
+ The gpio_gt and gpio_ts pins support the gpio function.
+ The gpio_slp pin is for controlling the pmic states, as below:
+ - reset
+ - power down
+ - sleep
+
Standard regulator bindings are used inside regulator subnodes. Check
Documentation/devicetree/bindings/regulator/regulator.txt
for more details
diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt b/Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
new file mode 100644
index 000000000000..c3c02ce73cde
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
@@ -0,0 +1,102 @@
+* ROHM BD70528 Power Management Integrated Circuit bindings
+
+BD70528MWV is an ultra-low quiescent current general purpose, single-chip,
+power management IC for battery-powered portable devices. The IC
+integrates 3 ultra-low current consumption buck converters, 3 LDOs and 2
+LED Drivers. Also included are 4 GPIOs, a real-time clock (RTC), a 32kHz
+clock gate, high-accuracy VREF for use with an external ADC, flexible
+dual-input power path, 10 bit SAR ADC for battery temperature monitor and
+1S battery charger with scalable charge currents.
+
+Required properties:
+ - compatible : Should be "rohm,bd70528"
+ - reg : I2C slave address.
+ - interrupts : The interrupt line the device is connected to.
+ - interrupt-controller : To indicate BD70528 acts as an interrupt controller.
+ - #interrupt-cells : Should be 2. Usage is compliant to the 2 cells
+ variant of ../interrupt-controller/interrupts.txt
+ - gpio-controller : To indicate BD70528 acts as a GPIO controller.
+ - #gpio-cells : Should be 2. The first cell is the pin number and
+ the second cell is used to specify flags. See
+ ../gpio/gpio.txt for more information.
+ - #clock-cells : Should be 0.
+ - regulators: : List of child nodes that specify the regulators.
+ Please see ../regulator/rohm,bd70528-regulator.txt
+
+Optional properties:
+ - clock-output-names : Should contain name for output clock.
+
+Example:
+/* External oscillator */
+osc: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <1>;
+ clock-frequency = <32768>;
+ clock-output-names = "osc";
+};
+
+pmic: pmic@4b {
+ compatible = "rohm,bd70528";
+ reg = <0x4b>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <29 GPIO_ACTIVE_LOW>;
+ clocks = <&osc 0>;
+ #clock-cells = <0>;
+ clock-output-names = "bd70528-32k-out";
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-ramp-delay = <125>;
+ };
+ buck2: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-ramp-delay = <125>;
+ };
+ buck3: BUCK3 {
+ regulator-name = "buck3";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-ramp-delay = <250>;
+ };
+ ldo1: LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+ ldo2: LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo3: LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ led_ldo1: LED_LDO1 {
+ regulator-name = "led_ldo1";
+ regulator-min-microvolt = <200000>;
+ regulator-max-microvolt = <300000>;
+ };
+ led_ldo2: LED_LDO2 {
+ regulator-name = "led_ldo2";
+ regulator-min-microvolt = <200000>;
+ regulator-max-microvolt = <300000>;
+ };
+ };
+};
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index fc1e0cf44995..7376af25f947 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -53,13 +53,12 @@ config COMMON_CLK_MAX9485
This driver supports Maxim 9485 Programmable Audio Clock Generator
config COMMON_CLK_RK808
- tristate "Clock driver for RK805/RK808/RK818"
+ tristate "Clock driver for RK805/RK808/RK809/RK817/RK818"
depends on MFD_RK808
---help---
- This driver supports RK805, RK808 and RK818 crystal oscillator clock. These
- multi-function devices have two fixed-rate oscillators,
- clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
- by control register.
+ This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock.
+ These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
+ Clkout1 is always on, Clkout2 can off by control register.
config COMMON_CLK_HI655X
tristate "Clock driver for Hi655x" if EXPERT
@@ -293,10 +292,10 @@ config COMMON_CLK_STM32H7
config COMMON_CLK_BD718XX
tristate "Clock driver for ROHM BD718x7 PMIC"
- depends on MFD_ROHM_BD718XX
+ depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528
help
- This driver supports ROHM BD71837 and ROHM BD71847
- PMICs clock gates.
+ This driver supports ROHM BD71837, ROHM BD71847 and
+ ROHM BD70528 PMICs clock gates.
config COMMON_CLK_FIXED_MMIO
bool "Clock driver for Memory Mapped Fixed values"
diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c
index 60422c72d142..ae6e5baee330 100644
--- a/drivers/clk/clk-bd718x7.c
+++ b/drivers/clk/clk-bd718x7.c
@@ -8,6 +8,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mfd/rohm-bd718x7.h>
+#include <linux/mfd/rohm-bd70528.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/regmap.h>
@@ -17,7 +18,7 @@ struct bd718xx_clk {
u8 reg;
u8 mask;
struct platform_device *pdev;
- struct bd718xx *mfd;
+ struct rohm_regmap_dev *mfd;
};
static int bd71837_clk_set(struct clk_hw *hw, int status)
@@ -68,7 +69,7 @@ static int bd71837_clk_probe(struct platform_device *pdev)
int rval = -ENOMEM;
const char *parent_clk;
struct device *parent = pdev->dev.parent;
- struct bd718xx *mfd = dev_get_drvdata(parent);
+ struct rohm_regmap_dev *mfd = dev_get_drvdata(parent);
struct clk_init_data init = {
.name = "bd718xx-32k-out",
.ops = &bd71837_clk_ops,
@@ -86,9 +87,20 @@ static int bd71837_clk_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "No parent clk found\n");
return -EINVAL;
}
-
- c->reg = BD718XX_REG_OUT32K;
- c->mask = BD718XX_OUT32K_EN;
+ switch (mfd->chip_type) {
+ case ROHM_CHIP_TYPE_BD71837:
+ case ROHM_CHIP_TYPE_BD71847:
+ c->reg = BD718XX_REG_OUT32K;
+ c->mask = BD718XX_OUT32K_EN;
+ break;
+ case ROHM_CHIP_TYPE_BD70528:
+ c->reg = BD70528_REG_CLK_OUT;
+ c->mask = BD70528_CLK_OUT_EN_MASK;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown clk chip\n");
+ return -EINVAL;
+ }
c->mfd = mfd;
c->pdev = pdev;
c->hw.init = &init;
@@ -119,5 +131,5 @@ static struct platform_driver bd71837_clk = {
module_platform_driver(bd71837_clk);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
-MODULE_DESCRIPTION("BD71837 chip clk driver");
+MODULE_DESCRIPTION("BD71837/BD71847/BD70528 chip clk driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c
index 8d90bdf5b946..75f2cf0dfc9f 100644
--- a/drivers/clk/clk-rk808.c
+++ b/drivers/clk/clk-rk808.c
@@ -96,6 +96,68 @@ of_clk_rk808_get(struct of_phandle_args *clkspec, void *data)
return idx ? &rk808_clkout->clkout2_hw : &rk808_clkout->clkout1_hw;
}
+static int rk817_clkout2_enable(struct clk_hw *hw, bool enable)
+{
+ struct rk808_clkout *rk808_clkout = container_of(hw,
+ struct rk808_clkout,
+ clkout2_hw);
+ struct rk808 *rk808 = rk808_clkout->rk808;
+
+ return regmap_update_bits(rk808->regmap, RK817_SYS_CFG(1),
+ RK817_CLK32KOUT2_EN,
+ enable ? RK817_CLK32KOUT2_EN : 0);
+}
+
+static int rk817_clkout2_prepare(struct clk_hw *hw)
+{
+ return rk817_clkout2_enable(hw, true);
+}
+
+static void rk817_clkout2_unprepare(struct clk_hw *hw)
+{
+ rk817_clkout2_enable(hw, false);
+}
+
+static int rk817_clkout2_is_prepared(struct clk_hw *hw)
+{
+ struct rk808_clkout *rk808_clkout = container_of(hw,
+ struct rk808_clkout,
+ clkout2_hw);
+ struct rk808 *rk808 = rk808_clkout->rk808;
+ unsigned int val;
+
+ int ret = regmap_read(rk808->regmap, RK817_SYS_CFG(1), &val);
+
+ if (ret < 0)
+ return 0;
+
+ return (val & RK817_CLK32KOUT2_EN) ? 1 : 0;
+}
+
+static const struct clk_ops rk817_clkout2_ops = {
+ .prepare = rk817_clkout2_prepare,
+ .unprepare = rk817_clkout2_unprepare,
+ .is_prepared = rk817_clkout2_is_prepared,
+ .recalc_rate = rk808_clkout_recalc_rate,
+};
+
+static const struct clk_ops *rkpmic_get_ops(long variant)
+{
+ switch (variant) {
+ case RK809_ID:
+ case RK817_ID:
+ return &rk817_clkout2_ops;
+ /*
+ * For the default case, it match the following PMIC type.
+ * RK805_ID
+ * RK808_ID
+ * RK818_ID
+ */
+ default:
+ return &rk808_clkout2_ops;
+ }
+}
+
static int rk808_clkout_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
@@ -127,7 +189,7 @@ static int rk808_clkout_probe(struct platform_device *pdev)
return ret;
init.name = "rk808-clkout2";
- init.ops = &rk808_clkout2_ops;
+ init.ops = rkpmic_get_ops(rk808->variant);
rk808_clkout->clkout2_hw.init = &init;
/* optional override of the clockname */
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8023d03ec362..87dbbd03910d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -977,6 +977,17 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
+config GPIO_BD70528
+ tristate "ROHM BD70528 GPIO support"
+ depends on MFD_ROHM_BD70528
+ help
+ Support for GPIOs on ROHM BD70528 PMIC. There are four GPIOs
+ available on the ROHM PMIC in total. The GPIOs can also
+ generate interrupts.
+
+ This driver can also be built as a module. If so, the module
+ will be called gpio-bd70528.
+
config GPIO_BD9571MWV
tristate "ROHM BD9571 GPIO support"
depends on MFD_BD9571MWV
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 6700eee860b7..10efc4f743fe 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c
new file mode 100644
index 000000000000..fd85605d2dab
--- /dev/null
+++ b/drivers/gpio/gpio-bd70528.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 ROHM Semiconductors
+// gpio-bd70528.c ROHM BD70528MWV gpio driver
+
+#include <linux/gpio/driver.h>
+#include <linux/mfd/rohm-bd70528.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define GPIO_IN_REG(offset) (BD70528_REG_GPIO1_IN + (offset) * 2)
+#define GPIO_OUT_REG(offset) (BD70528_REG_GPIO1_OUT + (offset) * 2)
+
+struct bd70528_gpio {
+ struct rohm_regmap_dev chip;
+ struct gpio_chip gpio;
+};
+
+static int bd70528_set_debounce(struct bd70528_gpio *bdgpio,
+ unsigned int offset, unsigned int debounce)
+{
+ u8 val;
+
+ switch (debounce) {
+ case 0:
+ val = BD70528_DEBOUNCE_DISABLE;
+ break;
+ case 1 ... 15:
+ val = BD70528_DEBOUNCE_15MS;
+ break;
+ case 16 ... 30:
+ val = BD70528_DEBOUNCE_30MS;
+ break;
+ case 31 ... 50:
+ val = BD70528_DEBOUNCE_50MS;
+ break;
+ default:
+ dev_err(bdgpio->chip.dev,
+ "Invalid debouce value %u\n", debounce);
+ return -EINVAL;
+ }
+ return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset),
+ BD70528_DEBOUNCE_MASK, val);
+}
+
+static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+ int val, ret;
+
+ /* Do we need to do something to IRQs here? */
+ ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
+ if (ret) {
+ dev_err(bdgpio->chip.dev, "Could not read gpio direction\n");
+ return ret;
+ }
+
+ return !(val & BD70528_GPIO_OUT_EN_MASK);
+}
+
+static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ return regmap_update_bits(bdgpio->chip.regmap,
+ GPIO_OUT_REG(offset),
+ BD70528_GPIO_DRIVE_MASK,
+ BD70528_GPIO_OPEN_DRAIN);
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ return regmap_update_bits(bdgpio->chip.regmap,
+ GPIO_OUT_REG(offset),
+ BD70528_GPIO_DRIVE_MASK,
+ BD70528_GPIO_PUSH_PULL);
+ break;
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ return bd70528_set_debounce(bdgpio, offset,
+ pinconf_to_config_argument(config));
+ break;
+ default:
+ break;
+ }
+ return -ENOTSUPP;
+}
+
+static int bd70528_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ /* Do we need to do something to IRQs here? */
+ return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
+ BD70528_GPIO_OUT_EN_MASK,
+ BD70528_GPIO_OUT_DISABLE);
+}
+
+static void bd70528_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ int ret;
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+ u8 val = (value) ? BD70528_GPIO_OUT_HI : BD70528_GPIO_OUT_LO;
+
+ ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
+ BD70528_GPIO_OUT_MASK, val);
+ if (ret)
+ dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value);
+}
+
+static int bd70528_direction_output(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ bd70528_gpio_set(chip, offset, value);
+ return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
+ BD70528_GPIO_OUT_EN_MASK,
+ BD70528_GPIO_OUT_ENABLE);
+}
+
+#define GPIO_IN_STATE_MASK(offset) (BD70528_GPIO_IN_STATE_BASE << (offset))
+
+static int bd70528_gpio_get_o(struct bd70528_gpio *bdgpio, unsigned int offset)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
+ if (!ret)
+ ret = !!(val & BD70528_GPIO_OUT_MASK);
+ else
+ dev_err(bdgpio->chip.dev, "GPIO (out) state read failed\n");
+
+ return ret;
+}
+
+static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(bdgpio->chip.regmap, BD70528_REG_GPIO_STATE, &val);
+
+ if (!ret)
+ ret = !(val & GPIO_IN_STATE_MASK(offset));
+ else
+ dev_err(bdgpio->chip.dev, "GPIO (in) state read failed\n");
+
+ return ret;
+}
+
+static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ int ret = -EINVAL;
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ /*
+ * There is a race condition where someone might be changing the
+ * GPIO direction after we get it but before we read the value. But
+ * application design where GPIO direction may be changed just when
+ * we read GPIO value would be pointless as reader could not know
+ * whether the returned high/low state is caused by input or output.
+ * Or then there must be other ways to mitigate the issue. Thus
+ * locking would make no sense.
+ */
+ ret = bd70528_get_direction(chip, offset);
+ if (ret == 0)
+ ret = bd70528_gpio_get_o(bdgpio, offset);
+ else if (ret == 1)
+ ret = bd70528_gpio_get_i(bdgpio, offset);
+ else
+ dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n");
+
+ return ret;
+}
+
+static int bd70528_probe(struct platform_device *pdev)
+{
+ struct bd70528_gpio *bdgpio;
+ struct rohm_regmap_dev *bd70528;
+ int ret;
+
+ bd70528 = dev_get_drvdata(pdev->dev.parent);
+ if (!bd70528) {
+ dev_err(&pdev->dev, "No MFD driver data\n");
+ return -EINVAL;
+ }
+
+ bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio),
+ GFP_KERNEL);
+ if (!bdgpio)
+ return -ENOMEM;
+ bdgpio->chip.dev = &pdev->dev;
+ bdgpio->gpio.parent = pdev->dev.parent;
+ bdgpio->gpio.label = "bd70528-gpio";
+ bdgpio->gpio.owner = THIS_MODULE;
+ bdgpio->gpio.get_direction = bd70528_get_direction;
+ bdgpio->gpio.direction_input = bd70528_direction_input;
+ bdgpio->gpio.direction_output = bd70528_direction_output;
+ bdgpio->gpio.set_config = bd70528_gpio_set_config;
+ bdgpio->gpio.can_sleep = true;
+ bdgpio->gpio.get = bd70528_gpio_get;
+ bdgpio->gpio.set = bd70528_gpio_set;
+ bdgpio->gpio.ngpio = 4;
+ bdgpio->gpio.base = -1;
+#ifdef CONFIG_OF_GPIO
+ bdgpio->gpio.of_node = pdev->dev.parent->of_node;
+#endif
+ bdgpio->chip.regmap = bd70528->regmap;
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio,
+ bdgpio);
+ if (ret)
+ dev_err(&pdev->dev, "gpio_init: Failed to add bd70528-gpio\n");
+
+ return ret;
+}
+
+static struct platform_driver bd70528_gpio = {
+ .driver = {
+ .name = "bd70528-gpio"
+ },
+ .probe = bd70528_probe,
+};
+
+module_platform_driver(bd70528_gpio);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("BD70528 voltage regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 294d9567cc71..760b9e29c8e5 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1030,14 +1030,14 @@ config MFD_RC5T583
different functionality of the device.
config MFD_RK808
- tristate "Rockchip RK805/RK808/RK818 Power Management Chip"
+ tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
- If you say yes here you get support for the RK805, RK808 and RK818
- Power Management chips.
+ 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. The device supports multiple sub-devices
including interrupts, RTC, LDO & DCDC regulators, and onkey.
@@ -1890,6 +1890,23 @@ config MFD_ROHM_BD718XX
NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
and emergency shut down as well as 32,768KHz clock output.
+config MFD_ROHM_BD70528
+ tristate "ROHM BD70528 Power Management IC"
+ depends on I2C=y
+ depends on OF
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ select MFD_CORE
+ help
+ Select this option to get support for the ROHM BD70528 Power
+ Management IC. BD71837 is general purpose single-chip power
+ management IC for battery-powered portable devices. It contains
+ 3 ultra-low current consumption buck converters, 3 LDOs and 2 LED
+ drivers. Also included are 4 GPIOs, a real-time clock (RTC), a 32kHz
+ crystal oscillator, high-accuracy VREF for use with an external ADC,
+ 10 bits SAR ADC for battery temperature monitor and 1S battery
+ charger.
+
config MFD_STM32_LPTIMER
tristate "Support for STM32 Low-Power Timer"
depends on (ARCH_STM32 && OF) || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 52b1a90ff515..643d65bcb6ea 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -247,5 +247,7 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
+obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
obj-$(CONFIG_MFD_STMFX) += stmfx.o
+
diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c
index 32d2a07d4354..8ad688fe75f9 100644
--- a/drivers/mfd/lp87565.c
+++ b/drivers/mfd/lp87565.c
@@ -33,6 +33,10 @@ static const struct of_device_id of_lp87565_match_table[] = {
.compatible = "ti,lp87565-q1",
.data = (void *)LP87565_DEVICE_TYPE_LP87565_Q1,
},
+ {
+ .compatible = "ti,lp87561-q1",
+ .data = (void *)LP87565_DEVICE_TYPE_LP87561_Q1,
+ },
{}
};
MODULE_DEVICE_TABLE(of, of_lp87565_match_table);
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index 94377782d208..6ee1c461a3bb 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
+#include <linux/syscore_ops.h>
struct rk808_reg_data {
int addr;
@@ -62,6 +63,27 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
return false;
}
+static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /*
+ * Notes:
+ * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
+ * we don't use that feature. It's better to cache.
+ */
+
+ switch (reg) {
+ case RK817_SECONDS_REG ... RK817_WEEKS_REG:
+ case RK817_RTC_STATUS_REG:
+ case RK817_INT_STS_REG0:
+ case RK817_INT_STS_REG1:
+ case RK817_INT_STS_REG2:
+ case RK817_SYS_STS:
+ return true;
+ }
+
+ return true;
+}
+
static const struct regmap_config rk818_regmap_config = {
.reg_bits = 8,
.val_bits = 8,