* [RESEND PATCH v5 2/5] regulator: rk808: Add regulator driver for RK818
2016-06-02 6:50 [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Wadim Egorov
@ 2016-06-02 6:50 ` Wadim Egorov
2016-06-02 6:50 ` [RESEND PATCH v5 3/5] mfd: dt-bindings: Add RK818 device tree bindings document Wadim Egorov
` (3 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: Wadim Egorov @ 2016-06-02 6:50 UTC (permalink / raw)
To: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip
Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lee.jones, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
Add support for the rk818 regulator. The regulator module consists
of 4 DCDCs, 9 LDOs, 1 switch and 1 BOOST converter which is used to
power OTG and HDMI5V.
The output voltages are configurable and are meant to supply power
to the main processor and other components.
Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
Acked-by: Mark Brown <broonie@kernel.org>
---
drivers/regulator/Kconfig | 4 +-
drivers/regulator/rk808-regulator.c | 143 ++++++++++++++++++++++++++++++++++--
2 files changed, 138 insertions(+), 9 deletions(-)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 144cbf5..9852777 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -626,11 +626,11 @@ config REGULATOR_RC5T583
outputs which can be controlled by i2c communication.
config REGULATOR_RK808
- tristate "Rockchip RK808 Power regulators"
+ tristate "Rockchip RK808/RK818 Power regulators"
depends on MFD_RK808
help
Select this option to enable the power regulator of ROCKCHIP
- PMIC RK808.
+ PMIC RK808 and RK818.
This driver supports the control of different power rails of device
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 40d07ba..5f412a5 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -1,11 +1,15 @@
/*
- * Regulator driver for Rockchip RK808
+ * Regulator driver for Rockchip RK808/RK818
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
* Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com>
*
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ *
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
@@ -32,6 +36,12 @@
#define RK808_BUCK4_VSEL_MASK 0xf
#define RK808_LDO_VSEL_MASK 0x1f
+#define RK818_BUCK_VSEL_MASK 0x3f
+#define RK818_BUCK4_VSEL_MASK 0x1f
+#define RK818_LDO_VSEL_MASK 0x1f
+#define RK818_LDO3_ON_VSEL_MASK 0xf
+#define RK818_BOOST_ON_VSEL_MASK 0xe0
+
/* Ramp rate definitions for buck1 / buck2 only */
#define RK808_RAMP_RATE_OFFSET 3
#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET)
@@ -454,6 +464,108 @@ static const struct regulator_desc rk808_reg[] = {
RK808_DCDC_EN_REG, BIT(6)),
};
+static const struct regulator_desc rk818_reg[] = {
+ {
+ .name = "DCDC_REG1",
+ .supply_name = "vcc1",
+ .of_match = of_match_ptr("DCDC_REG1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK818_ID_DCDC1,
+ .ops = &rk808_reg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK818_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK818_DCDC_EN_REG,
+ .enable_mask = BIT(0),
+ .owner = THIS_MODULE,
+ }, {
+ .name = "DCDC_REG2",
+ .supply_name = "vcc2",
+ .of_match = of_match_ptr("DCDC_REG2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK818_ID_DCDC2,
+ .ops = &rk808_reg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK818_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK818_DCDC_EN_REG,
+ .enable_mask = BIT(1),
+ .owner = THIS_MODULE,
+ }, {
+ .name = "DCDC_REG3",
+ .supply_name = "vcc3",
+ .of_match = of_match_ptr("DCDC_REG3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK818_ID_DCDC3,
+ .ops = &rk808_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 1,
+ .enable_reg = RK818_DCDC_EN_REG,
+ .enable_mask = BIT(2),
+ .owner = THIS_MODULE,
+ },
+ RK8XX_DESC(RK818_ID_DCDC4, "DCDC_REG4", "vcc4", 1800, 3600, 100,
+ RK818_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK,
+ RK818_DCDC_EN_REG, BIT(3), 0),
+ RK8XX_DESC(RK818_ID_BOOST, "DCDC_BOOST", "boost", 4700, 5400, 100,
+ RK818_BOOST_LDO9_ON_VSEL_REG, RK818_BOOST_ON_VSEL_MASK,
+ RK818_DCDC_EN_REG, BIT(4), 0),
+ RK8XX_DESC(RK818_ID_LDO1, "LDO_REG1", "vcc6", 1800, 3400, 100,
+ RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(0), 400),
+ RK8XX_DESC(RK818_ID_LDO2, "LDO_REG2", "vcc6", 1800, 3400, 100,
+ RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(1), 400),
+ {
+ .name = "LDO_REG3",
+ .supply_name = "vcc7",
+ .of_match = of_match_ptr("LDO_REG3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK818_ID_LDO3,
+ .ops = &rk808_reg_ops_ranges,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 16,
+ .linear_ranges = rk808_ldo3_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges),
+ .vsel_reg = RK818_LDO3_ON_VSEL_REG,
+ .vsel_mask = RK818_LDO3_ON_VSEL_MASK,
+ .enable_reg = RK818_LDO_EN_REG,
+ .enable_mask = BIT(2),
+ .enable_time = 400,
+ .owner = THIS_MODULE,
+ },
+ RK8XX_DESC(RK818_ID_LDO4, "LDO_REG4", "vcc8", 1800, 3400, 100,
+ RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(3), 400),
+ RK8XX_DESC(RK818_ID_LDO5, "LDO_REG5", "vcc7", 1800, 3400, 100,
+ RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(4), 400),
+ RK8XX_DESC(RK818_ID_LDO6, "LDO_REG6", "vcc8", 800, 2500, 100,
+ RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(5), 400),
+ RK8XX_DESC(RK818_ID_LDO7, "LDO_REG7", "vcc7", 800, 2500, 100,
+ RK818_LDO7_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(6), 400),
+ RK8XX_DESC(RK818_ID_LDO8, "LDO_REG8", "vcc8", 1800, 3400, 100,
+ RK818_LDO8_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(7), 400),
+ RK8XX_DESC(RK818_ID_LDO9, "LDO_REG9", "vcc9", 1800, 3400, 100,
+ RK818_BOOST_LDO9_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+ RK818_DCDC_EN_REG, BIT(5), 400),
+ RK8XX_DESC_SWITCH(RK818_ID_SWITCH, "SWITCH_REG", "vcc9",
+ RK818_DCDC_EN_REG, BIT(6)),
+ RK8XX_DESC_SWITCH(RK818_ID_HDMI_SWITCH, "HDMI_SWITCH", "h_5v",
+ RK818_H5V_EN_REG, BIT(0)),
+ RK8XX_DESC_SWITCH(RK818_ID_OTG_SWITCH, "OTG_SWITCH", "usb",
+ RK818_DCDC_EN_REG, BIT(7)),
+};
+
static int rk808_regulator_dt_parse_pdata(struct device *dev,
struct device *client_dev,
struct regmap *map,
@@ -499,7 +611,8 @@ static int rk808_regulator_probe(struct platform_device *pdev)
struct regulator_config config = {};
struct regulator_dev *rk808_rdev;
struct rk808_regulator_data *pdata;
- int ret, i;
+ const struct regulator_desc *regulators;
+ int ret, i, nregulators;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -512,14 +625,29 @@ static int rk808_regulator_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pdata);
+ switch (rk808->variant) {
+ case RK808_ID:
+ regulators = rk808_reg;
+ nregulators = RK808_NUM_REGULATORS;
+ break;
+ case RK818_ID:
+ regulators = rk818_reg;
+ nregulators = RK818_NUM_REGULATORS;
+ break;
+ default:
+ dev_err(&client->dev, "unsupported RK8XX ID %lu\n",
+ rk808->variant);
+ return -EINVAL;
+ }
+
config.dev = &client->dev;
config.driver_data = pdata;
config.regmap = rk808->regmap;
/* Instantiate the regulators */
- for (i = 0; i < RK808_NUM_REGULATORS; i++) {
+ for (i = 0; i < nregulators; i++) {
rk808_rdev = devm_regulator_register(&pdev->dev,
- &rk808_reg[i], &config);
+ ®ulators[i], &config);
if (IS_ERR(rk808_rdev)) {
dev_err(&client->dev,
"failed to register %d regulator\n", i);
@@ -540,8 +668,9 @@ static struct platform_driver rk808_regulator_driver = {
module_platform_driver(rk808_regulator_driver);
-MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs");
-MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>");
-MODULE_AUTHOR("Zhang Qing<zhangqing@rock-chips.com>");
+MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
+MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rk808-regulator");
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RESEND PATCH v5 3/5] mfd: dt-bindings: Add RK818 device tree bindings document
2016-06-02 6:50 [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Wadim Egorov
2016-06-02 6:50 ` [RESEND PATCH v5 2/5] regulator: rk808: Add regulator driver for RK818 Wadim Egorov
@ 2016-06-02 6:50 ` Wadim Egorov
2016-06-08 14:23 ` Lee Jones
2016-06-02 6:50 ` [RESEND PATCH v5 4/5] clk: Kconfig: Name RK818 in Kconfig for COMMON_CLK_RK808 Wadim Egorov
` (2 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Wadim Egorov @ 2016-06-02 6:50 UTC (permalink / raw)
To: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip
Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lee.jones, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
Add device tree bindings documentation for Rockchip's RK818 PMIC.
Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/mfd/rk808.txt | 37 +++++++++++++++++++++++--
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt
index 4ca6aab..9636ae8 100644
--- a/Documentation/devicetree/bindings/mfd/rk808.txt
+++ b/Documentation/devicetree/bindings/mfd/rk808.txt
@@ -1,7 +1,11 @@
-RK808 Power Management Integrated Circuit
+RK8XX Power Management Integrated Circuit
+
+The rk8xx family current members:
+rk808
+rk818
Required properties:
-- compatible: "rockchip,rk808"
+- compatible: "rockchip,rk808", "rockchip,rk818"
- reg: I2C slave address
- interrupt-parent: The parent interrupt controller.
- interrupts: the interrupt outputs of the controller.
@@ -13,6 +17,8 @@ Optional properties:
default output clock name
- rockchip,system-power-controller: Telling whether or not this pmic is controlling
the system power.
+
+Optional RK808 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
@@ -29,7 +35,20 @@ Optional properties:
the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
very quickly with no slow ramp time.
-Regulators: All the regulators of RK808 to be instantiated shall be
+Optional RK818 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
+- boost-supply: The input supply for DCDC_BOOST
+- vcc6-supply: The input supply for LDO_REG1 and LDO_REG2
+- vcc7-supply: The input supply for LDO_REG3, LDO_REG5 and LDO_REG7
+- vcc8-supply: The input supply for LDO_REG4, LDO_REG6 and LDO_REG8
+- vcc9-supply: The input supply for LDO_REG9 and SWITCH_REG
+- h_5v-supply: The input supply for HDMI_SWITCH
+- usb-supply: The input supply for OTG_SWITCH
+
+Regulators: All the regulators of RK8XX to be instantiated shall be
listed in a child node named 'regulators'. Each regulator is represented
by a child node of the 'regulators' node.
@@ -48,6 +67,18 @@ number as described in RK808 datasheet.
- SWITCH_REGn
- valid values for n are 1 to 2
+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.
+
+ - DCDC_REGn
+ - valid values for n are 1 to 4.
+ - LDO_REGn
+ - valid values for n are 1 to 9.
+ - SWITCH_REG
+ - HDMI_SWITCH
+ - OTG_SWITCH
+
Standard regulator bindings are used inside regulator subnodes. Check
Documentation/devicetree/bindings/regulator/regulator.txt
for more details
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 3/5] mfd: dt-bindings: Add RK818 device tree bindings document
2016-06-02 6:50 ` [RESEND PATCH v5 3/5] mfd: dt-bindings: Add RK818 device tree bindings document Wadim Egorov
@ 2016-06-08 14:23 ` Lee Jones
0 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2016-06-08 14:23 UTC (permalink / raw)
To: Wadim Egorov
Cc: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip,
robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
On Thu, 02 Jun 2016, Wadim Egorov wrote:
> Add device tree bindings documentation for Rockchip's RK818 PMIC.
>
> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
> Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Lee Jones <lee.jones@linaro.org>
> ---
> Documentation/devicetree/bindings/mfd/rk808.txt | 37 +++++++++++++++++++++++--
> 1 file changed, 34 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt
> index 4ca6aab..9636ae8 100644
> --- a/Documentation/devicetree/bindings/mfd/rk808.txt
> +++ b/Documentation/devicetree/bindings/mfd/rk808.txt
> @@ -1,7 +1,11 @@
> -RK808 Power Management Integrated Circuit
> +RK8XX Power Management Integrated Circuit
> +
> +The rk8xx family current members:
> +rk808
> +rk818
>
> Required properties:
> -- compatible: "rockchip,rk808"
> +- compatible: "rockchip,rk808", "rockchip,rk818"
> - reg: I2C slave address
> - interrupt-parent: The parent interrupt controller.
> - interrupts: the interrupt outputs of the controller.
> @@ -13,6 +17,8 @@ Optional properties:
> default output clock name
> - rockchip,system-power-controller: Telling whether or not this pmic is controlling
> the system power.
> +
> +Optional RK808 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
> @@ -29,7 +35,20 @@ Optional properties:
> the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
> very quickly with no slow ramp time.
>
> -Regulators: All the regulators of RK808 to be instantiated shall be
> +Optional RK818 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
> +- boost-supply: The input supply for DCDC_BOOST
> +- vcc6-supply: The input supply for LDO_REG1 and LDO_REG2
> +- vcc7-supply: The input supply for LDO_REG3, LDO_REG5 and LDO_REG7
> +- vcc8-supply: The input supply for LDO_REG4, LDO_REG6 and LDO_REG8
> +- vcc9-supply: The input supply for LDO_REG9 and SWITCH_REG
> +- h_5v-supply: The input supply for HDMI_SWITCH
> +- usb-supply: The input supply for OTG_SWITCH
> +
> +Regulators: All the regulators of RK8XX to be instantiated shall be
> listed in a child node named 'regulators'. Each regulator is represented
> by a child node of the 'regulators' node.
>
> @@ -48,6 +67,18 @@ number as described in RK808 datasheet.
> - SWITCH_REGn
> - valid values for n are 1 to 2
>
> +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.
> +
> + - DCDC_REGn
> + - valid values for n are 1 to 4.
> + - LDO_REGn
> + - valid values for n are 1 to 9.
> + - SWITCH_REG
> + - HDMI_SWITCH
> + - OTG_SWITCH
> +
> Standard regulator bindings are used inside regulator subnodes. Check
> Documentation/devicetree/bindings/regulator/regulator.txt
> for more details
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RESEND PATCH v5 4/5] clk: Kconfig: Name RK818 in Kconfig for COMMON_CLK_RK808
2016-06-02 6:50 [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Wadim Egorov
2016-06-02 6:50 ` [RESEND PATCH v5 2/5] regulator: rk808: Add regulator driver for RK818 Wadim Egorov
2016-06-02 6:50 ` [RESEND PATCH v5 3/5] mfd: dt-bindings: Add RK818 device tree bindings document Wadim Egorov
@ 2016-06-02 6:50 ` Wadim Egorov
2016-07-06 22:22 ` Michael Turquette
2016-06-02 6:50 ` [RESEND PATCH v5 5/5] rtc: Kconfig: Name RK818 in Kconfig for RTC_DRV_RK808 Wadim Egorov
2016-06-08 14:17 ` [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Lee Jones
4 siblings, 1 reply; 16+ messages in thread
From: Wadim Egorov @ 2016-06-02 6:50 UTC (permalink / raw)
To: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip
Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lee.jones, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
The RK808 and RK818 PMICs are using a similar register map.
We can reuse the clk driver for the RK818 PMIC. So let's add
the RK818 in the Kconfig description.
Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
---
drivers/clk/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 53ddba2..87b9fd2 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -49,10 +49,10 @@ config COMMON_CLK_MAX77802
This driver supports Maxim 77802 crystal oscillator clock.
config COMMON_CLK_RK808
- tristate "Clock driver for RK808"
+ tristate "Clock driver for RK808/RK818"
depends on MFD_RK808
---help---
- This driver supports RK808 crystal oscillator clock. These
+ This driver supports 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.
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 4/5] clk: Kconfig: Name RK818 in Kconfig for COMMON_CLK_RK808
2016-06-02 6:50 ` [RESEND PATCH v5 4/5] clk: Kconfig: Name RK818 in Kconfig for COMMON_CLK_RK808 Wadim Egorov
@ 2016-07-06 22:22 ` Michael Turquette
0 siblings, 0 replies; 16+ messages in thread
From: Michael Turquette @ 2016-07-06 22:22 UTC (permalink / raw)
To: Wadim Egorov, linux-kernel, linux-clk, rtc-linux, devicetree,
linux-rockchip
Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, sboyd,
lee.jones, lgirdwood, broonie, a.zummo, alexandre.belloni,
dianders, zyw
Quoting Wadim Egorov (2016-06-01 23:50:27)
> The RK808 and RK818 PMICs are using a similar register map.
> We can reuse the clk driver for the RK818 PMIC. So let's add
> the RK818 in the Kconfig description.
> =
> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
> Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Applied.
Regards,
Mike
> ---
> drivers/clk/Kconfig | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
> =
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 53ddba2..87b9fd2 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -49,10 +49,10 @@ config COMMON_CLK_MAX77802
> This driver supports Maxim 77802 crystal oscillator clock.
> =
> config COMMON_CLK_RK808
> - tristate "Clock driver for RK808"
> + tristate "Clock driver for RK808/RK818"
> depends on MFD_RK808
> ---help---
> - This driver supports RK808 crystal oscillator clock. These
> + This driver supports 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.
> -- =
> 1.9.1
>=20
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RESEND PATCH v5 5/5] rtc: Kconfig: Name RK818 in Kconfig for RTC_DRV_RK808
2016-06-02 6:50 [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Wadim Egorov
` (2 preceding siblings ...)
2016-06-02 6:50 ` [RESEND PATCH v5 4/5] clk: Kconfig: Name RK818 in Kconfig for COMMON_CLK_RK808 Wadim Egorov
@ 2016-06-02 6:50 ` Wadim Egorov
2016-06-08 14:17 ` [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Lee Jones
4 siblings, 0 replies; 16+ messages in thread
From: Wadim Egorov @ 2016-06-02 6:50 UTC (permalink / raw)
To: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip
Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lee.jones, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
The RK808 and RK818 PMICs are using a similar register map.
We can reuse the rtc driver for the RK818 PMIC. So let's add
the RK818 in the Kconfig description.
Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
drivers/rtc/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 18639e0..2faed74 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -324,11 +324,11 @@ config RTC_DRV_MAX77686
will be called rtc-max77686.
config RTC_DRV_RK808
- tristate "Rockchip RK808 RTC"
+ tristate "Rockchip RK808/RK818 RTC"
depends on MFD_RK808
help
If you say yes here you will get support for the
- RTC of RK808 PMIC.
+ RTC of RK808 and RK818 PMIC.
This driver can also be built as a module. If so, the module
will be called rk808-rtc.
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-06-02 6:50 [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Wadim Egorov
` (3 preceding siblings ...)
2016-06-02 6:50 ` [RESEND PATCH v5 5/5] rtc: Kconfig: Name RK818 in Kconfig for RTC_DRV_RK808 Wadim Egorov
@ 2016-06-08 14:17 ` Lee Jones
2016-06-09 8:23 ` Wadim Egorov
4 siblings, 1 reply; 16+ messages in thread
From: Lee Jones @ 2016-06-08 14:17 UTC (permalink / raw)
To: Wadim Egorov
Cc: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip,
robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
On Thu, 02 Jun 2016, Wadim Egorov wrote:
> The RK818 chip is a power management IC for multimedia and handheld
"Power Management IC (PMIC)"
> devices. It contains the following components:
>
> - Regulators
> - RTC
> - Clkout
Clocking
> - battery support
Battery support
> Both chips RK808 and RK818 are using a similar register map.
"Both RK808 ad RK818 chips"
> So we can reuse the RTC and Clkout functionality.
Swap '.' for ','.
> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
> ---
> drivers/mfd/Kconfig | 4 +-
> drivers/mfd/rk808.c | 231 ++++++++++++++++++++++++++++++++++++++--------
> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
> 3 files changed, 350 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 1bcf601..7ba464b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -839,13 +839,13 @@ config MFD_RC5T583
> different functionality of the device.
>
> config MFD_RK808
> - tristate "Rockchip RK808 Power Management chip"
> + tristate "Rockchip RK808/RK818 Power Management chip"
"Chip"
> depends on I2C && OF
> select MFD_CORE
> select REGMAP_I2C
> select REGMAP_IRQ
> help
> - If you say yes here you get support for the RK808
> + If you say yes here you get support for the RK808 and RK818
> Power Management chips.
> This driver provides common support for accessing the device
> through I2C interface. The device supports multiple sub-devices
> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
> index 49d7f62..3cf9724 100644
> --- a/drivers/mfd/rk808.c
> +++ b/drivers/mfd/rk808.c
> @@ -1,11 +1,15 @@
> /*
> - * MFD core driver for Rockchip RK808
> + * MFD core driver for Rockchip RK808/RK818
> *
> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
> *
> * Author: Chris Zhong <zyw@rock-chips.com>
> * Author: Zhang Qing <zhangqing@rock-chips.com>
> *
> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
> + *
> + * Author: Wadim Egorov <w.egorov@phytec.de>
> + *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms and conditions of the GNU General Public License,
> * version 2, as published by the Free Software Foundation.
> @@ -22,12 +26,7 @@
> #include <linux/mfd/core.h>
> #include <linux/module.h>
> #include <linux/regmap.h>
> -
> -struct rk808_reg_data {
> - int addr;
> - int mask;
> - int value;
> -};
Why are you moving this to the header?
> +#include <linux/of_device.h>
>
> static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
> {
> @@ -57,6 +56,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
> return false;
> }
>
> +static const struct regmap_config rk818_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = RK818_USB_CTRL_REG,
> + .cache_type = REGCACHE_RBTREE,
> + .volatile_reg = rk808_is_volatile_reg,
> +};
> +
> static const struct regmap_config rk808_regmap_config = {
> .reg_bits = 8,
> .val_bits = 8,
> @@ -83,7 +90,17 @@ static const struct mfd_cell rk808s[] = {
> },
> };
>
> -static const struct rk808_reg_data pre_init_reg[] = {
> +static const struct mfd_cell rk818s[] = {
> + { .name = "rk808-clkout", },
How does this differ to a normal -clock driver?
> + { .name = "rk808-regulator", },
> + {
> + .name = "rk808-rtc",
> + .num_resources = ARRAY_SIZE(rtc_resources),
> + .resources = &rtc_resources[0],
.resources = rtc_resources, ?
> + },
> +};
> +
> +static const struct rk8xx_reg_data rk808_pre_init_reg[] = {
> { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
> { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
> { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
> @@ -94,6 +111,22 @@ static const struct rk808_reg_data pre_init_reg[] = {
> VB_LO_SEL_3500MV },
> };
>
> +static const struct rk8xx_reg_data rk818_pre_init_reg[] = {
> + { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,
> + RK818_USB_ILMIN_2000MA },
> + /* close charger when usb lower then 3.4V */
> + { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, (0x7 << 4) },
> + /* no action when vref */
> + { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },
> + /* enable HDMI 5V */
> + { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
> + /* improve efficiency */
> + { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
> + { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
> + { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
> + { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | VB_LO_SEL_3500MV },
> +};
The alignment here looks odd.
> static const struct regmap_irq rk808_irqs[] = {
> /* INT_STS */
> [RK808_IRQ_VOUT_LO] = {
> @@ -136,6 +169,76 @@ static const struct regmap_irq rk808_irqs[] = {
> },
> };
>
> +static const struct regmap_irq rk818_irqs[] = {
> + /* INT_STS */
> + [RK818_IRQ_VOUT_LO] = {
> + .mask = RK818_IRQ_VOUT_LO_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_VB_LO] = {
> + .mask = RK818_IRQ_VB_LO_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_PWRON] = {
> + .mask = RK818_IRQ_PWRON_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_PWRON_LP] = {
> + .mask = RK818_IRQ_PWRON_LP_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_HOTDIE] = {
> + .mask = RK818_IRQ_HOTDIE_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_RTC_ALARM] = {
> + .mask = RK818_IRQ_RTC_ALARM_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_RTC_PERIOD] = {
> + .mask = RK818_IRQ_RTC_PERIOD_MSK,
> + .reg_offset = 0,
> + },
> + [RK818_IRQ_USB_OV] = {
> + .mask = RK818_IRQ_USB_OV_MSK,
> + .reg_offset = 0,
> + },
> +
> + /* INT_STS2 */
> + [RK818_IRQ_PLUG_IN] = {
> + .mask = RK818_IRQ_PLUG_IN_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_PLUG_OUT] = {
> + .mask = RK818_IRQ_PLUG_OUT_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_CHG_OK] = {
> + .mask = RK818_IRQ_CHG_OK_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_CHG_TE] = {
> + .mask = RK818_IRQ_CHG_TE_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_CHG_TS1] = {
> + .mask = RK818_IRQ_CHG_TS1_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_TS2] = {
> + .mask = RK818_IRQ_TS2_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_CHG_CVTLIM] = {
> + .mask = RK818_IRQ_CHG_CVTLIM_MSK,
> + .reg_offset = 1,
> + },
> + [RK818_IRQ_DISCHG_ILIM] = {
> + .mask = RK818_IRQ_DISCHG_ILIM_MSK,
> + .reg_offset = 1,
> + },
> +};
> +
> static struct regmap_irq_chip rk808_irq_chip = {
> .name = "rk808",
> .irqs = rk808_irqs,
> @@ -148,6 +251,18 @@ static struct regmap_irq_chip rk808_irq_chip = {
> .init_ack_masked = true,
> };
>
> +static struct regmap_irq_chip rk818_irq_chip = {
> + .name = "rk818",
> + .irqs = rk818_irqs,
> + .num_irqs = ARRAY_SIZE(rk818_irqs),
> + .num_regs = 2,
> + .irq_reg_stride = 2,
> + .status_base = RK818_INT_STS_REG1,
> + .mask_base = RK818_INT_STS_MSK_REG1,
> + .ack_base = RK818_INT_STS_REG1,
> + .init_ack_masked = true,
> +};
> +
> static struct i2c_client *rk808_i2c_client;
> static void rk808_device_shutdown(void)
> {
> @@ -167,6 +282,48 @@ static void rk808_device_shutdown(void)
> dev_err(&rk808_i2c_client->dev, "power off error!\n");
> }
>
> +static const struct of_device_id rk808_of_match[] = {
> + { .compatible = "rockchip,rk808", .data = (void *) RK808_ID },
> + { .compatible = "rockchip,rk818", .data = (void *) RK818_ID },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, rk808_of_match);
> +
> +static int rk8xx_match_device(struct rk808 *rk808, struct device *dev)
If you're going to do it this way, please switch these parameters.
It's more common to return the pointer however.
> +{
> + const struct of_device_id *of_id;
> +
> + of_id = of_match_device(rk808_of_match, dev);
> + if (!of_id) {
> + dev_err(dev, "Unable to match OF ID\n");
> + return -ENODEV;
> + }
> + rk808->variant = (long) of_id->data;
> +
> + switch (rk808->variant) {
> + case RK808_ID:
> + rk808->nr_cells = ARRAY_SIZE(rk808s);
> + rk808->cells = rk808s;
> + rk808->regmap_cfg = &rk808_regmap_config;
> + rk808->regmap_irq_chip = &rk808_irq_chip;
> + rk808->pre_init_reg = rk808_pre_init_reg;
> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
> + break;
> + case RK818_ID:
> + rk808->nr_cells = ARRAY_SIZE(rk818s);
> + rk808->cells = rk818s;
> + rk808->regmap_cfg = &rk818_regmap_config;
> + rk808->regmap_irq_chip = &rk818_irq_chip;
> + rk808->pre_init_reg = rk818_pre_init_reg;
> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
> + break;
> + default:
> + dev_err(dev, "unsupported RK8XX ID %lu\n", rk808->variant);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> static int rk808_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> @@ -176,46 +333,52 @@ static int rk808_probe(struct i2c_client *client,
> int ret;
> int i;
>
> - if (!client->irq) {
> - dev_err(&client->dev, "No interrupt support, no core IRQ\n");
> - return -EINVAL;
> - }
> -
> rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
> if (!rk808)
> return -ENOMEM;
>
> - rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config);
> + ret = rk8xx_match_device(rk808, &client->dev);
Is there a way to dynamically probe the device? No device ID you can
read directly from the silicon?
> + if (ret)
> + return ret;
> +
> + rk808->i2c = client;
> + i2c_set_clientdata(client, rk808);
> +
> + rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg);
> if (IS_ERR(rk808->regmap)) {
> dev_err(&client->dev, "regmap initialization failed\n");
> return PTR_ERR(rk808->regmap);
> }
>
> - for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) {
> - ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr,
> - pre_init_reg[i].mask,
> - pre_init_reg[i].value);
> - if (ret) {
> - dev_err(&client->dev,
> - "0x%x write err\n", pre_init_reg[i].addr);
> - return ret;
> - }
> + if (!client->irq) {
> + dev_err(&client->dev, "No interrupt support, no core IRQ\n");
> + return -EINVAL;
> }
>
> ret = regmap_add_irq_chip(rk808->regmap, client->irq,
> IRQF_ONESHOT, -1,
> - &rk808_irq_chip, &rk808->irq_data);
> + rk808->regmap_irq_chip, &rk808->irq_data);
> if (ret) {
> dev_err(&client->dev, "Failed to add irq_chip %d\n", ret);
> return ret;
> }
>
> - rk808->i2c = client;
> - i2c_set_clientdata(client, rk808);
> + for (i = 0; i < rk808->nr_pre_init_regs; i++) {
> + ret = regmap_update_bits(rk808->regmap,
> + rk808->pre_init_reg[i].addr,
> + rk808->pre_init_reg[i].mask,
> + rk808->pre_init_reg[i].value);
> + if (ret) {
> + dev_err(&client->dev,
> + "0x%x write err\n",
> + rk808->pre_init_reg[i].addr);
> + return ret;
> + }
> + }
>
> - ret = devm_mfd_add_devices(&client->dev, -1,
> - rk808s, ARRAY_SIZE(rk808s), NULL, 0,
> - regmap_irq_get_domain(rk808->irq_data));
> + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
> + rk808->cells, rk808->nr_cells, NULL, 0,
> + regmap_irq_get_domain(rk808->irq_data));
> if (ret) {
> dev_err(&client->dev, "failed to add MFD devices %d\n", ret);
> goto err_irq;
> @@ -245,14 +408,9 @@ static int rk808_remove(struct i2c_client *client)
> return 0;
> }
>
> -static const struct of_device_id rk808_of_match[] = {
> - { .compatible = "rockchip,rk808" },
> - { },
> -};
> -MODULE_DEVICE_TABLE(of, rk808_of_match);
> -
> static const struct i2c_device_id rk808_ids[] = {
> { "rk808" },
> + { "rk818" },
> { },
> };
> MODULE_DEVICE_TABLE(i2c, rk808_ids);
> @@ -272,4 +430,5 @@ module_i2c_driver(rk808_i2c_driver);
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
> MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
> -MODULE_DESCRIPTION("RK808 PMIC driver");
> +MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
> +MODULE_DESCRIPTION("RK808/RK818 PMIC driver");
> diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
> index 441b6ee..5ce810c 100644
> --- a/include/linux/mfd/rk808.h
> +++ b/include/linux/mfd/rk808.h
> @@ -1,11 +1,15 @@
> /*
> - * rk808.h for Rockchip RK808
> + * Register definitions for Rockchip's RK808/RK818 PMIC
> *
> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
> *
> * Author: Chris Zhong <zyw@rock-chips.com>
> * Author: Zhang Qing <zhangqing@rock-chips.com>
> *
> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
> + *
> + * Author: Wadim Egorov <w.egorov@phytec.de>
> + *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms and conditions of the GNU General Public License,
> * version 2, as published by the Free Software Foundation.
> @@ -16,8 +20,8 @@
> * more details.
> */
>
> -#ifndef __LINUX_REGULATOR_rk808_H
> -#define __LINUX_REGULATOR_rk808_H
> +#ifndef __LINUX_REGULATOR_RK808_H
> +#define __LINUX_REGULATOR_RK808_H
>
> #include <linux/regulator/machine.h>
> #include <linux/regmap.h>
> @@ -28,7 +32,7 @@
>
> #define RK808_DCDC1 0 /* (0+RK808_START) */
> #define RK808_LDO1 4 /* (4+RK808_START) */
> -#define RK808_NUM_REGULATORS 14
> +#define RK808_NUM_REGULATORS 14
>
> enum rk808_reg {
> RK808_ID_DCDC1,
> @@ -115,7 +119,92 @@ enum rk808_reg {
> #define RK808_INT_STS_MSK_REG2 0x4f
> #define RK808_IO_POL_REG 0x50
>
> -/* IRQ Definitions */
> +/* RK818 */
> +#define RK818_DCDC1 0
> +#define RK818_LDO1 4
> +#define RK818_NUM_REGULATORS 17
> +
> +enum rk818_reg {
> + RK818_ID_DCDC1,
> + RK818_ID_DCDC2,
> + RK818_ID_DCDC3,
> + RK818_ID_DCDC4,
> + RK818_ID_BOOST,
> + RK818_ID_LDO1,
> + RK818_ID_LDO2,
> + RK818_ID_LDO3,
> + RK818_ID_LDO4,
> + RK818_ID_LDO5,
> + RK818_ID_LDO6,
> + RK818_ID_LDO7,
> + RK818_ID_LDO8,
> + RK818_ID_LDO9,
> + RK818_ID_SWITCH,
> + RK818_ID_HDMI_SWITCH,
> + RK818_ID_OTG_SWITCH,
> +};
> +
> +#define RK818_DCDC_EN_REG 0x23
> +#define RK818_LDO_EN_REG 0x24
> +#define RK818_SLEEP_SET_OFF_REG1 0x25
> +#define RK818_SLEEP_SET_OFF_REG2 0x26
> +#define RK818_DCDC_UV_STS_REG 0x27
> +#define RK818_DCDC_UV_ACT_REG 0x28
> +#define RK818_LDO_UV_STS_REG 0x29
> +#define RK818_LDO_UV_ACT_REG 0x2a
> +#define RK818_DCDC_PG_REG 0x2b
> +#define RK818_LDO_PG_REG 0x2c
> +#define RK818_VOUT_MON_TDB_REG 0x2d
> +#define RK818_BUCK1_CONFIG_REG 0x2e
> +#define RK818_BUCK1_ON_VSEL_REG 0x2f
> +#define RK818_BUCK1_SLP_VSEL_REG 0x30
> +#define RK818_BUCK2_CONFIG_REG 0x32
> +#define RK818_BUCK2_ON_VSEL_REG 0x33
> +#define RK818_BUCK2_SLP_VSEL_REG 0x34
> +#define RK818_BUCK3_CONFIG_REG 0x36
> +#define RK818_BUCK4_CONFIG_REG 0x37
> +#define RK818_BUCK4_ON_VSEL_REG 0x38
> +#define RK818_BUCK4_SLP_VSEL_REG 0x39
> +#define RK818_BOOST_CONFIG_REG 0x3a
> +#define RK818_LDO1_ON_VSEL_REG 0x3b
> +#define RK818_LDO1_SLP_VSEL_REG 0x3c
> +#define RK818_LDO2_ON_VSEL_REG 0x3d
> +#define RK818_LDO2_SLP_VSEL_REG 0x3e
> +#define RK818_LDO3_ON_VSEL_REG 0x3f
> +#define RK818_LDO3_SLP_VSEL_REG 0x40
> +#define RK818_LDO4_ON_VSEL_REG 0x41
> +#define RK818_LDO4_SLP_VSEL_REG 0x42
> +#define RK818_LDO5_ON_VSEL_REG 0x43
> +#define RK818_LDO5_SLP_VSEL_REG 0x44
> +#define RK818_LDO6_ON_VSEL_REG 0x45
> +#define RK818_LDO6_SLP_VSEL_REG 0x46
> +#define RK818_LDO7_ON_VSEL_REG 0x47
> +#define RK818_LDO7_SLP_VSEL_REG 0x48
> +#define RK818_LDO8_ON_VSEL_REG 0x49
> +#define RK818_LDO8_SLP_VSEL_REG 0x4a
> +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54
> +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55
> +#define RK818_DEVCTRL_REG 0x4b
> +#define RK818_INT_STS_REG1 0X4c
> +#define RK818_INT_STS_MSK_REG1 0x4d
> +#define RK818_INT_STS_REG2 0x4e
> +#define RK818_INT_STS_MSK_REG2 0x4f
> +#define RK818_IO_POL_REG 0x50
> +#define RK818_H5V_EN_REG 0x52
> +#define RK818_SLEEP_SET_OFF_REG3 0x53
> +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54
> +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55
> +#define RK818_BOOST_CTRL_REG 0x56
> +#define RK818_DCDC_ILMAX 0x90
> +#define RK818_USB_CTRL_REG 0xa1
> +
> +#define RK818_H5V_EN BIT(0)
> +#define RK818_REF_RDY_CTRL BIT(1)
> +#define RK818_USB_ILIM_SEL_MASK 0xf
> +#define RK818_USB_ILMIN_2000MA 0x7
> +#define RK818_USB_CHG_SD_VSEL_MASK 0x70
> +
> +/* RK808 IRQ Definitions */
> #define RK808_IRQ_VOUT_LO 0
> #define RK808_IRQ_VB_LO 1
> #define RK808_IRQ_PWRON 2
> @@ -137,6 +226,43 @@ enum rk808_reg {
> #define RK808_IRQ_PLUG_IN_INT_MSK BIT(0)
> #define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1)
>
> +/* RK818 IRQ Definitions */
> +#define RK818_IRQ_VOUT_LO 0
> +#define RK818_IRQ_VB_LO 1
> +#define RK818_IRQ_PWRON 2
> +#define RK818_IRQ_PWRON_LP 3
> +#define RK818_IRQ_HOTDIE 4
> +#define RK818_IRQ_RTC_ALARM 5
> +#define RK818_IRQ_RTC_PERIOD 6
> +#define RK818_IRQ_USB_OV 7
> +#define RK818_IRQ_PLUG_IN 8
> +#define RK818_IRQ_PLUG_OUT 9
> +#define RK818_IRQ_CHG_OK 10
> +#define RK818_IRQ_CHG_TE 11
> +#define RK818_IRQ_CHG_TS1 12
> +#define RK818_IRQ_TS2 13
> +#define RK818_IRQ_CHG_CVTLIM 14
> +#define RK818_IRQ_DISCHG_ILIM 7
> +
> +#define RK818_IRQ_VOUT_LO_MSK BIT(0)
> +#define RK818_IRQ_VB_LO_MSK BIT(1)
> +#define RK818_IRQ_PWRON_MSK BIT(2)
> +#define RK818_IRQ_PWRON_LP_MSK BIT(3)
> +#define RK818_IRQ_HOTDIE_MSK BIT(4)
> +#define RK818_IRQ_RTC_ALARM_MSK BIT(5)
> +#define RK818_IRQ_RTC_PERIOD_MSK BIT(6)
> +#define RK818_IRQ_USB_OV_MSK BIT(7)
> +#define RK818_IRQ_PLUG_IN_MSK BIT(0)
> +#define RK818_IRQ_PLUG_OUT_MSK BIT(1)
> +#define RK818_IRQ_CHG_OK_MSK BIT(2)
> +#define RK818_IRQ_CHG_TE_MSK BIT(3)
> +#define RK818_IRQ_CHG_TS1_MSK BIT(4)
> +#define RK818_IRQ_TS2_MSK BIT(5)
> +#define RK818_IRQ_CHG_CVTLIM_MSK BIT(6)
> +#define RK818_IRQ_DISCHG_ILIM_MSK BIT(7)
> +
> +#define RK818_NUM_IRQ 16
> +
> #define RK808_VBAT_LOW_2V8 0x00
> #define RK808_VBAT_LOW_2V9 0x01
> #define RK808_VBAT_LOW_3V0 0x02
> @@ -191,9 +317,27 @@ enum {
> BOOST_ILMIN_250MA,
> };
>
> +enum {
> + RK808_ID,
> + RK818_ID,
> +};
> +
> +struct rk8xx_reg_data {
> + int addr;
> + int mask;
> + int value;
> +};
> +
> struct rk808 {
> - struct i2c_client *i2c;
> - struct regmap_irq_chip_data *irq_data;
> - struct regmap *regmap;
> + struct i2c_client *i2c;
> + struct regmap_irq_chip_data *irq_data;
> + struct regmap *regmap;
> + long variant;
> + int nr_cells;
> + const struct mfd_cell *cells;
> + const struct regmap_config *regmap_cfg;
> + const struct regmap_irq_chip *regmap_irq_chip;
> + const struct rk8xx_reg_data *pre_init_reg;
> + int nr_pre_init_regs;
> };
> -#endif /* __LINUX_REGULATOR_rk808_H */
> +#endif /* __LINUX_REGULATOR_RK808_H */
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-06-08 14:17 ` [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support Lee Jones
@ 2016-06-09 8:23 ` Wadim Egorov
2016-06-09 11:12 ` Lee Jones
2016-07-06 3:15 ` Andy Yan
0 siblings, 2 replies; 16+ messages in thread
From: Wadim Egorov @ 2016-06-09 8:23 UTC (permalink / raw)
To: Lee Jones
Cc: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip,
robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
Hi,
On 08.06.2016 16:17, Lee Jones wrote:
> On Thu, 02 Jun 2016, Wadim Egorov wrote:
>
>> The RK818 chip is a power management IC for multimedia and handheld
> "Power Management IC (PMIC)"
>
>> devices. It contains the following components:
>>
>> - Regulators
>> - RTC
>> - Clkout
> Clocking
>
>> - battery support
> Battery support
>
>> Both chips RK808 and RK818 are using a similar register map.
> "Both RK808 ad RK818 chips"
>
>> So we can reuse the RTC and Clkout functionality.
> Swap '.' for ','.
>
>> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
>> ---
>> drivers/mfd/Kconfig | 4 +-
>> drivers/mfd/rk808.c | 231 ++++++++++++++++++++++++++++++++++++++--------
>> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
>> 3 files changed, 350 insertions(+), 47 deletions(-)
>>
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>> index 1bcf601..7ba464b 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -839,13 +839,13 @@ config MFD_RC5T583
>> different functionality of the device.
>>
>> config MFD_RK808
>> - tristate "Rockchip RK808 Power Management chip"
>> + tristate "Rockchip RK808/RK818 Power Management chip"
> "Chip"
>
>> depends on I2C && OF
>> select MFD_CORE
>> select REGMAP_I2C
>> select REGMAP_IRQ
>> help
>> - If you say yes here you get support for the RK808
>> + If you say yes here you get support for the RK808 and RK818
>> Power Management chips.
>> This driver provides common support for accessing the device
>> through I2C interface. The device supports multiple sub-devices
>> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
>> index 49d7f62..3cf9724 100644
>> --- a/drivers/mfd/rk808.c
>> +++ b/drivers/mfd/rk808.c
>> @@ -1,11 +1,15 @@
>> /*
>> - * MFD core driver for Rockchip RK808
>> + * MFD core driver for Rockchip RK808/RK818
>> *
>> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
>> *
>> * Author: Chris Zhong <zyw@rock-chips.com>
>> * Author: Zhang Qing <zhangqing@rock-chips.com>
>> *
>> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
>> + *
>> + * Author: Wadim Egorov <w.egorov@phytec.de>
>> + *
>> * This program is free software; you can redistribute it and/or modify it
>> * under the terms and conditions of the GNU General Public License,
>> * version 2, as published by the Free Software Foundation.
>> @@ -22,12 +26,7 @@
>> #include <linux/mfd/core.h>
>> #include <linux/module.h>
>> #include <linux/regmap.h>
>> -
>> -struct rk808_reg_data {
>> - int addr;
>> - int mask;
>> - int value;
>> -};
> Why are you moving this to the header?
It is now part of the rk808 struct.
>
>> +#include <linux/of_device.h>
>>
>> static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>> {
>> @@ -57,6 +56,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>> return false;
>> }
>>
>> +static const struct regmap_config rk818_regmap_config = {
>> + .reg_bits = 8,
>> + .val_bits = 8,
>> + .max_register = RK818_USB_CTRL_REG,
>> + .cache_type = REGCACHE_RBTREE,
>> + .volatile_reg = rk808_is_volatile_reg,
>> +};
>> +
>> static const struct regmap_config rk808_regmap_config = {
>> .reg_bits = 8,
>> .val_bits = 8,
>> @@ -83,7 +90,17 @@ static const struct mfd_cell rk808s[] = {
>> },
>> };
>>
>> -static const struct rk808_reg_data pre_init_reg[] = {
>> +static const struct mfd_cell rk818s[] = {
>> + { .name = "rk808-clkout", },
> How does this differ to a normal -clock driver?
I don't know. It is a normal clock driver.
>
>> + { .name = "rk808-regulator", },
>> + {
>> + .name = "rk808-rtc",
>> + .num_resources = ARRAY_SIZE(rtc_resources),
>> + .resources = &rtc_resources[0],
> .resources = rtc_resources, ?
>
>> + },
>> +};
>> +
>> +static const struct rk8xx_reg_data rk808_pre_init_reg[] = {
>> { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
>> { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
>> { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
>> @@ -94,6 +111,22 @@ static const struct rk808_reg_data pre_init_reg[] = {
>> VB_LO_SEL_3500MV },
>> };
>>
>> +static const struct rk8xx_reg_data rk818_pre_init_reg[] = {
>> + { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,
>> + RK818_USB_ILMIN_2000MA },
>> + /* close charger when usb lower then 3.4V */
>> + { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, (0x7 << 4) },
>> + /* no action when vref */
>> + { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },
>> + /* enable HDMI 5V */
>> + { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
>> + /* improve efficiency */
>> + { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
>> + { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
>> + { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
>> + { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | VB_LO_SEL_3500MV },
>> +};
> The alignment here looks odd.
I will fix it in the next version.
>
>> static const struct regmap_irq rk808_irqs[] = {
>> /* INT_STS */
>> [RK808_IRQ_VOUT_LO] = {
>> @@ -136,6 +169,76 @@ static const struct regmap_irq rk808_irqs[] = {
>> },
>> };
>>
>> +static const struct regmap_irq rk818_irqs[] = {
>> + /* INT_STS */
>> + [RK818_IRQ_VOUT_LO] = {
>> + .mask = RK818_IRQ_VOUT_LO_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_VB_LO] = {
>> + .mask = RK818_IRQ_VB_LO_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_PWRON] = {
>> + .mask = RK818_IRQ_PWRON_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_PWRON_LP] = {
>> + .mask = RK818_IRQ_PWRON_LP_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_HOTDIE] = {
>> + .mask = RK818_IRQ_HOTDIE_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_RTC_ALARM] = {
>> + .mask = RK818_IRQ_RTC_ALARM_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_RTC_PERIOD] = {
>> + .mask = RK818_IRQ_RTC_PERIOD_MSK,
>> + .reg_offset = 0,
>> + },
>> + [RK818_IRQ_USB_OV] = {
>> + .mask = RK818_IRQ_USB_OV_MSK,
>> + .reg_offset = 0,
>> + },
>> +
>> + /* INT_STS2 */
>> + [RK818_IRQ_PLUG_IN] = {
>> + .mask = RK818_IRQ_PLUG_IN_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_PLUG_OUT] = {
>> + .mask = RK818_IRQ_PLUG_OUT_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_CHG_OK] = {
>> + .mask = RK818_IRQ_CHG_OK_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_CHG_TE] = {
>> + .mask = RK818_IRQ_CHG_TE_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_CHG_TS1] = {
>> + .mask = RK818_IRQ_CHG_TS1_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_TS2] = {
>> + .mask = RK818_IRQ_TS2_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_CHG_CVTLIM] = {
>> + .mask = RK818_IRQ_CHG_CVTLIM_MSK,
>> + .reg_offset = 1,
>> + },
>> + [RK818_IRQ_DISCHG_ILIM] = {
>> + .mask = RK818_IRQ_DISCHG_ILIM_MSK,
>> + .reg_offset = 1,
>> + },
>> +};
>> +
>> static struct regmap_irq_chip rk808_irq_chip = {
>> .name = "rk808",
>> .irqs = rk808_irqs,
>> @@ -148,6 +251,18 @@ static struct regmap_irq_chip rk808_irq_chip = {
>> .init_ack_masked = true,
>> };
>>
>> +static struct regmap_irq_chip rk818_irq_chip = {
>> + .name = "rk818",
>> + .irqs = rk818_irqs,
>> + .num_irqs = ARRAY_SIZE(rk818_irqs),
>> + .num_regs = 2,
>> + .irq_reg_stride = 2,
>> + .status_base = RK818_INT_STS_REG1,
>> + .mask_base = RK818_INT_STS_MSK_REG1,
>> + .ack_base = RK818_INT_STS_REG1,
>> + .init_ack_masked = true,
>> +};
>> +
>> static struct i2c_client *rk808_i2c_client;
>> static void rk808_device_shutdown(void)
>> {
>> @@ -167,6 +282,48 @@ static void rk808_device_shutdown(void)
>> dev_err(&rk808_i2c_client->dev, "power off error!\n");
>> }
>>
>> +static const struct of_device_id rk808_of_match[] = {
>> + { .compatible = "rockchip,rk808", .data = (void *) RK808_ID },
>> + { .compatible = "rockchip,rk818", .data = (void *) RK818_ID },
>> + { },
>> +};
>> +MODULE_DEVICE_TABLE(of, rk808_of_match);
>> +
>> +static int rk8xx_match_device(struct rk808 *rk808, struct device *dev)
> If you're going to do it this way, please switch these parameters.
>
> It's more common to return the pointer however.
If it's more common I will return a pointer to rk808.
>
>> +{
>> + const struct of_device_id *of_id;
>> +
>> + of_id = of_match_device(rk808_of_match, dev);
>> + if (!of_id) {
>> + dev_err(dev, "Unable to match OF ID\n");
>> + return -ENODEV;
>> + }
>> + rk808->variant = (long) of_id->data;
>> +
>> + switch (rk808->variant) {
>> + case RK808_ID:
>> + rk808->nr_cells = ARRAY_SIZE(rk808s);
>> + rk808->cells = rk808s;
>> + rk808->regmap_cfg = &rk808_regmap_config;
>> + rk808->regmap_irq_chip = &rk808_irq_chip;
>> + rk808->pre_init_reg = rk808_pre_init_reg;
>> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
>> + break;
>> + case RK818_ID:
>> + rk808->nr_cells = ARRAY_SIZE(rk818s);
>> + rk808->cells = rk818s;
>> + rk808->regmap_cfg = &rk818_regmap_config;
>> + rk808->regmap_irq_chip = &rk818_irq_chip;
>> + rk808->pre_init_reg = rk818_pre_init_reg;
>> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
>> + break;
>> + default:
>> + dev_err(dev, "unsupported RK8XX ID %lu\n", rk808->variant);
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> static int rk808_probe(struct i2c_client *client,
>> const struct i2c_device_id *id)
>> {
>> @@ -176,46 +333,52 @@ static int rk808_probe(struct i2c_client *client,
>> int ret;
>> int i;
>>
>> - if (!client->irq) {
>> - dev_err(&client->dev, "No interrupt support, no core IRQ\n");
>> - return -EINVAL;
>> - }
>> -
>> rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
>> if (!rk808)
>> return -ENOMEM;
>>
>> - rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config);
>> + ret = rk8xx_match_device(rk808, &client->dev);
> Is there a way to dynamically probe the device? No device ID you can
> read directly from the silicon?
AFAIK there is no device ID register. At least it is not documented in
the manual.
Wadim
>
>> + if (ret)
>> + return ret;
>> +
>> + rk808->i2c = client;
>> + i2c_set_clientdata(client, rk808);
>> +
>> + rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg);
>> if (IS_ERR(rk808->regmap)) {
>> dev_err(&client->dev, "regmap initialization failed\n");
>> return PTR_ERR(rk808->regmap);
>> }
>>
>> - for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) {
>> - ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr,
>> - pre_init_reg[i].mask,
>> - pre_init_reg[i].value);
>> - if (ret) {
>> - dev_err(&client->dev,
>> - "0x%x write err\n", pre_init_reg[i].addr);
>> - return ret;
>> - }
>> + if (!client->irq) {
>> + dev_err(&client->dev, "No interrupt support, no core IRQ\n");
>> + return -EINVAL;
>> }
>>
>> ret = regmap_add_irq_chip(rk808->regmap, client->irq,
>> IRQF_ONESHOT, -1,
>> - &rk808_irq_chip, &rk808->irq_data);
>> + rk808->regmap_irq_chip, &rk808->irq_data);
>> if (ret) {
>> dev_err(&client->dev, "Failed to add irq_chip %d\n", ret);
>> return ret;
>> }
>>
>> - rk808->i2c = client;
>> - i2c_set_clientdata(client, rk808);
>> + for (i = 0; i < rk808->nr_pre_init_regs; i++) {
>> + ret = regmap_update_bits(rk808->regmap,
>> + rk808->pre_init_reg[i].addr,
>> + rk808->pre_init_reg[i].mask,
>> + rk808->pre_init_reg[i].value);
>> + if (ret) {
>> + dev_err(&client->dev,
>> + "0x%x write err\n",
>> + rk808->pre_init_reg[i].addr);
>> + return ret;
>> + }
>> + }
>>
>> - ret = devm_mfd_add_devices(&client->dev, -1,
>> - rk808s, ARRAY_SIZE(rk808s), NULL, 0,
>> - regmap_irq_get_domain(rk808->irq_data));
>> + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
>> + rk808->cells, rk808->nr_cells, NULL, 0,
>> + regmap_irq_get_domain(rk808->irq_data));
>> if (ret) {
>> dev_err(&client->dev, "failed to add MFD devices %d\n", ret);
>> goto err_irq;
>> @@ -245,14 +408,9 @@ static int rk808_remove(struct i2c_client *client)
>> return 0;
>> }
>>
>> -static const struct of_device_id rk808_of_match[] = {
>> - { .compatible = "rockchip,rk808" },
>> - { },
>> -};
>> -MODULE_DEVICE_TABLE(of, rk808_of_match);
>> -
>> static const struct i2c_device_id rk808_ids[] = {
>> { "rk808" },
>> + { "rk818" },
>> { },
>> };
>> MODULE_DEVICE_TABLE(i2c, rk808_ids);
>> @@ -272,4 +430,5 @@ module_i2c_driver(rk808_i2c_driver);
>> MODULE_LICENSE("GPL");
>> MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
>> MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
>> -MODULE_DESCRIPTION("RK808 PMIC driver");
>> +MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
>> +MODULE_DESCRIPTION("RK808/RK818 PMIC driver");
>> diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
>> index 441b6ee..5ce810c 100644
>> --- a/include/linux/mfd/rk808.h
>> +++ b/include/linux/mfd/rk808.h
>> @@ -1,11 +1,15 @@
>> /*
>> - * rk808.h for Rockchip RK808
>> + * Register definitions for Rockchip's RK808/RK818 PMIC
>> *
>> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
>> *
>> * Author: Chris Zhong <zyw@rock-chips.com>
>> * Author: Zhang Qing <zhangqing@rock-chips.com>
>> *
>> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
>> + *
>> + * Author: Wadim Egorov <w.egorov@phytec.de>
>> + *
>> * This program is free software; you can redistribute it and/or modify it
>> * under the terms and conditions of the GNU General Public License,
>> * version 2, as published by the Free Software Foundation.
>> @@ -16,8 +20,8 @@
>> * more details.
>> */
>>
>> -#ifndef __LINUX_REGULATOR_rk808_H
>> -#define __LINUX_REGULATOR_rk808_H
>> +#ifndef __LINUX_REGULATOR_RK808_H
>> +#define __LINUX_REGULATOR_RK808_H
>>
>> #include <linux/regulator/machine.h>
>> #include <linux/regmap.h>
>> @@ -28,7 +32,7 @@
>>
>> #define RK808_DCDC1 0 /* (0+RK808_START) */
>> #define RK808_LDO1 4 /* (4+RK808_START) */
>> -#define RK808_NUM_REGULATORS 14
>> +#define RK808_NUM_REGULATORS 14
>>
>> enum rk808_reg {
>> RK808_ID_DCDC1,
>> @@ -115,7 +119,92 @@ enum rk808_reg {
>> #define RK808_INT_STS_MSK_REG2 0x4f
>> #define RK808_IO_POL_REG 0x50
>>
>> -/* IRQ Definitions */
>> +/* RK818 */
>> +#define RK818_DCDC1 0
>> +#define RK818_LDO1 4
>> +#define RK818_NUM_REGULATORS 17
>> +
>> +enum rk818_reg {
>> + RK818_ID_DCDC1,
>> + RK818_ID_DCDC2,
>> + RK818_ID_DCDC3,
>> + RK818_ID_DCDC4,
>> + RK818_ID_BOOST,
>> + RK818_ID_LDO1,
>> + RK818_ID_LDO2,
>> + RK818_ID_LDO3,
>> + RK818_ID_LDO4,
>> + RK818_ID_LDO5,
>> + RK818_ID_LDO6,
>> + RK818_ID_LDO7,
>> + RK818_ID_LDO8,
>> + RK818_ID_LDO9,
>> + RK818_ID_SWITCH,
>> + RK818_ID_HDMI_SWITCH,
>> + RK818_ID_OTG_SWITCH,
>> +};
>> +
>> +#define RK818_DCDC_EN_REG 0x23
>> +#define RK818_LDO_EN_REG 0x24
>> +#define RK818_SLEEP_SET_OFF_REG1 0x25
>> +#define RK818_SLEEP_SET_OFF_REG2 0x26
>> +#define RK818_DCDC_UV_STS_REG 0x27
>> +#define RK818_DCDC_UV_ACT_REG 0x28
>> +#define RK818_LDO_UV_STS_REG 0x29
>> +#define RK818_LDO_UV_ACT_REG 0x2a
>> +#define RK818_DCDC_PG_REG 0x2b
>> +#define RK818_LDO_PG_REG 0x2c
>> +#define RK818_VOUT_MON_TDB_REG 0x2d
>> +#define RK818_BUCK1_CONFIG_REG 0x2e
>> +#define RK818_BUCK1_ON_VSEL_REG 0x2f
>> +#define RK818_BUCK1_SLP_VSEL_REG 0x30
>> +#define RK818_BUCK2_CONFIG_REG 0x32
>> +#define RK818_BUCK2_ON_VSEL_REG 0x33
>> +#define RK818_BUCK2_SLP_VSEL_REG 0x34
>> +#define RK818_BUCK3_CONFIG_REG 0x36
>> +#define RK818_BUCK4_CONFIG_REG 0x37
>> +#define RK818_BUCK4_ON_VSEL_REG 0x38
>> +#define RK818_BUCK4_SLP_VSEL_REG 0x39
>> +#define RK818_BOOST_CONFIG_REG 0x3a
>> +#define RK818_LDO1_ON_VSEL_REG 0x3b
>> +#define RK818_LDO1_SLP_VSEL_REG 0x3c
>> +#define RK818_LDO2_ON_VSEL_REG 0x3d
>> +#define RK818_LDO2_SLP_VSEL_REG 0x3e
>> +#define RK818_LDO3_ON_VSEL_REG 0x3f
>> +#define RK818_LDO3_SLP_VSEL_REG 0x40
>> +#define RK818_LDO4_ON_VSEL_REG 0x41
>> +#define RK818_LDO4_SLP_VSEL_REG 0x42
>> +#define RK818_LDO5_ON_VSEL_REG 0x43
>> +#define RK818_LDO5_SLP_VSEL_REG 0x44
>> +#define RK818_LDO6_ON_VSEL_REG 0x45
>> +#define RK818_LDO6_SLP_VSEL_REG 0x46
>> +#define RK818_LDO7_ON_VSEL_REG 0x47
>> +#define RK818_LDO7_SLP_VSEL_REG 0x48
>> +#define RK818_LDO8_ON_VSEL_REG 0x49
>> +#define RK818_LDO8_SLP_VSEL_REG 0x4a
>> +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54
>> +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55
>> +#define RK818_DEVCTRL_REG 0x4b
>> +#define RK818_INT_STS_REG1 0X4c
>> +#define RK818_INT_STS_MSK_REG1 0x4d
>> +#define RK818_INT_STS_REG2 0x4e
>> +#define RK818_INT_STS_MSK_REG2 0x4f
>> +#define RK818_IO_POL_REG 0x50
>> +#define RK818_H5V_EN_REG 0x52
>> +#define RK818_SLEEP_SET_OFF_REG3 0x53
>> +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54
>> +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55
>> +#define RK818_BOOST_CTRL_REG 0x56
>> +#define RK818_DCDC_ILMAX 0x90
>> +#define RK818_USB_CTRL_REG 0xa1
>> +
>> +#define RK818_H5V_EN BIT(0)
>> +#define RK818_REF_RDY_CTRL BIT(1)
>> +#define RK818_USB_ILIM_SEL_MASK 0xf
>> +#define RK818_USB_ILMIN_2000MA 0x7
>> +#define RK818_USB_CHG_SD_VSEL_MASK 0x70
>> +
>> +/* RK808 IRQ Definitions */
>> #define RK808_IRQ_VOUT_LO 0
>> #define RK808_IRQ_VB_LO 1
>> #define RK808_IRQ_PWRON 2
>> @@ -137,6 +226,43 @@ enum rk808_reg {
>> #define RK808_IRQ_PLUG_IN_INT_MSK BIT(0)
>> #define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1)
>>
>> +/* RK818 IRQ Definitions */
>> +#define RK818_IRQ_VOUT_LO 0
>> +#define RK818_IRQ_VB_LO 1
>> +#define RK818_IRQ_PWRON 2
>> +#define RK818_IRQ_PWRON_LP 3
>> +#define RK818_IRQ_HOTDIE 4
>> +#define RK818_IRQ_RTC_ALARM 5
>> +#define RK818_IRQ_RTC_PERIOD 6
>> +#define RK818_IRQ_USB_OV 7
>> +#define RK818_IRQ_PLUG_IN 8
>> +#define RK818_IRQ_PLUG_OUT 9
>> +#define RK818_IRQ_CHG_OK 10
>> +#define RK818_IRQ_CHG_TE 11
>> +#define RK818_IRQ_CHG_TS1 12
>> +#define RK818_IRQ_TS2 13
>> +#define RK818_IRQ_CHG_CVTLIM 14
>> +#define RK818_IRQ_DISCHG_ILIM 7
>> +
>> +#define RK818_IRQ_VOUT_LO_MSK BIT(0)
>> +#define RK818_IRQ_VB_LO_MSK BIT(1)
>> +#define RK818_IRQ_PWRON_MSK BIT(2)
>> +#define RK818_IRQ_PWRON_LP_MSK BIT(3)
>> +#define RK818_IRQ_HOTDIE_MSK BIT(4)
>> +#define RK818_IRQ_RTC_ALARM_MSK BIT(5)
>> +#define RK818_IRQ_RTC_PERIOD_MSK BIT(6)
>> +#define RK818_IRQ_USB_OV_MSK BIT(7)
>> +#define RK818_IRQ_PLUG_IN_MSK BIT(0)
>> +#define RK818_IRQ_PLUG_OUT_MSK BIT(1)
>> +#define RK818_IRQ_CHG_OK_MSK BIT(2)
>> +#define RK818_IRQ_CHG_TE_MSK BIT(3)
>> +#define RK818_IRQ_CHG_TS1_MSK BIT(4)
>> +#define RK818_IRQ_TS2_MSK BIT(5)
>> +#define RK818_IRQ_CHG_CVTLIM_MSK BIT(6)
>> +#define RK818_IRQ_DISCHG_ILIM_MSK BIT(7)
>> +
>> +#define RK818_NUM_IRQ 16
>> +
>> #define RK808_VBAT_LOW_2V8 0x00
>> #define RK808_VBAT_LOW_2V9 0x01
>> #define RK808_VBAT_LOW_3V0 0x02
>> @@ -191,9 +317,27 @@ enum {
>> BOOST_ILMIN_250MA,
>> };
>>
>> +enum {
>> + RK808_ID,
>> + RK818_ID,
>> +};
>> +
>> +struct rk8xx_reg_data {
>> + int addr;
>> + int mask;
>> + int value;
>> +};
>> +
>> struct rk808 {
>> - struct i2c_client *i2c;
>> - struct regmap_irq_chip_data *irq_data;
>> - struct regmap *regmap;
>> + struct i2c_client *i2c;
>> + struct regmap_irq_chip_data *irq_data;
>> + struct regmap *regmap;
>> + long variant;
>> + int nr_cells;
>> + const struct mfd_cell *cells;
>> + const struct regmap_config *regmap_cfg;
>> + const struct regmap_irq_chip *regmap_irq_chip;
>> + const struct rk8xx_reg_data *pre_init_reg;
>> + int nr_pre_init_regs;
>> };
>> -#endif /* __LINUX_REGULATOR_rk808_H */
>> +#endif /* __LINUX_REGULATOR_RK808_H */
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-06-09 8:23 ` Wadim Egorov
@ 2016-06-09 11:12 ` Lee Jones
2016-06-09 13:11 ` Wadim Egorov
2016-07-06 3:15 ` Andy Yan
1 sibling, 1 reply; 16+ messages in thread
From: Lee Jones @ 2016-06-09 11:12 UTC (permalink / raw)
To: Wadim Egorov
Cc: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip,
robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
On Thu, 09 Jun 2016, Wadim Egorov wrote:
> On 08.06.2016 16:17, Lee Jones wrote:
> > On Thu, 02 Jun 2016, Wadim Egorov wrote:
> >
> >> The RK818 chip is a power management IC for multimedia and handheld
> > "Power Management IC (PMIC)"
> >
> >> devices. It contains the following components:
> >>
> >> - Regulators
> >> - RTC
> >> - Clkout
> > Clocking
> >
> >> - battery support
> > Battery support
> >
> >> Both chips RK808 and RK818 are using a similar register map.
> > "Both RK808 ad RK818 chips"
> >
> >> So we can reuse the RTC and Clkout functionality.
> > Swap '.' for ','.
> >
> >> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
> >> ---
> >> drivers/mfd/Kconfig | 4 +-
> >> drivers/mfd/rk808.c | 231 ++++++++++++++++++++++++++++++++++++++--------
> >> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
> >> 3 files changed, 350 insertions(+), 47 deletions(-)
[...]
> >> -struct rk808_reg_data {
> >> - int addr;
> >> - int mask;
> >> - int value;
> >> -};
> > Why are you moving this to the header?
>
> It is now part of the rk808 struct.
Why?
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-06-09 11:12 ` Lee Jones
@ 2016-06-09 13:11 ` Wadim Egorov
2016-06-09 15:28 ` Lee Jones
0 siblings, 1 reply; 16+ messages in thread
From: Wadim Egorov @ 2016-06-09 13:11 UTC (permalink / raw)
To: Lee Jones
Cc: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip,
robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
On 09.06.2016 13:12, Lee Jones wrote:
> On Thu, 09 Jun 2016, Wadim Egorov wrote:
>> On 08.06.2016 16:17, Lee Jones wrote:
>>> On Thu, 02 Jun 2016, Wadim Egorov wrote:
>>>
>>>> The RK818 chip is a power management IC for multimedia and handheld
>>> "Power Management IC (PMIC)"
>>>
>>>> devices. It contains the following components:
>>>>
>>>> - Regulators
>>>> - RTC
>>>> - Clkout
>>> Clocking
>>>
>>>> - battery support
>>> Battery support
>>>
>>>> Both chips RK808 and RK818 are using a similar register map.
>>> "Both RK808 ad RK818 chips"
>>>
>>>> So we can reuse the RTC and Clkout functionality.
>>> Swap '.' for ','.
>>>
>>>> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
>>>> ---
>>>> drivers/mfd/Kconfig | 4 +-
>>>> drivers/mfd/rk808.c | 231 ++++++++++++++++++++++++++++++++++++++--------
>>>> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
>>>> 3 files changed, 350 insertions(+), 47 deletions(-)
> [...]
>
>>>> -struct rk808_reg_data {
>>>> - int addr;
>>>> - int mask;
>>>> - int value;
>>>> -};
>>> Why are you moving this to the header?
>> It is now part of the rk808 struct.
> Why?
>
For me it seemed reasonable. My idea was to have only one chip variant
check.
I can move the rk808_reg_data struct back to the c file, check for the
chip variant within the probe function and initialize the proper
reg_data variable.
This would also apply to the mfd_cell variables.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-06-09 13:11 ` Wadim Egorov
@ 2016-06-09 15:28 ` Lee Jones
0 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2016-06-09 15:28 UTC (permalink / raw)
To: Wadim Egorov
Cc: linux-kernel, linux-clk, rtc-linux, devicetree, linux-rockchip,
robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
mturquette, sboyd, lgirdwood, broonie, a.zummo,
alexandre.belloni, dianders, zyw
On Thu, 09 Jun 2016, Wadim Egorov wrote:
>
>
> On 09.06.2016 13:12, Lee Jones wrote:
> > On Thu, 09 Jun 2016, Wadim Egorov wrote:
> >> On 08.06.2016 16:17, Lee Jones wrote:
> >>> On Thu, 02 Jun 2016, Wadim Egorov wrote:
> >>>
> >>>> The RK818 chip is a power management IC for multimedia and handheld
> >>> "Power Management IC (PMIC)"
> >>>
> >>>> devices. It contains the following components:
> >>>>
> >>>> - Regulators
> >>>> - RTC
> >>>> - Clkout
> >>> Clocking
> >>>
> >>>> - battery support
> >>> Battery support
> >>>
> >>>> Both chips RK808 and RK818 are using a similar register map.
> >>> "Both RK808 ad RK818 chips"
> >>>
> >>>> So we can reuse the RTC and Clkout functionality.
> >>> Swap '.' for ','.
> >>>
> >>>> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
> >>>> ---
> >>>> drivers/mfd/Kconfig | 4 +-
> >>>> drivers/mfd/rk808.c | 231 ++++++++++++++++++++++++++++++++++++++--------
> >>>> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
> >>>> 3 files changed, 350 insertions(+), 47 deletions(-)
> > [...]
> >
> >>>> -struct rk808_reg_data {
> >>>> - int addr;
> >>>> - int mask;
> >>>> - int value;
> >>>> -};
> >>> Why are you moving this to the header?
> >> It is now part of the rk808 struct.
> > Why?
> >
> For me it seemed reasonable. My idea was to have only one chip variant
> check.
>
> I can move the rk808_reg_data struct back to the c file, check for the
> chip variant within the probe function and initialize the proper
> reg_data variable.
> This would also apply to the mfd_cell variables.
'struct rk808' should only contain information you wish to share with
your subordinate/child devices. Any data only used in the parent/MFD
driver should be declared, initialised and used only the latter. No
need to export.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-06-09 8:23 ` Wadim Egorov
2016-06-09 11:12 ` Lee Jones
@ 2016-07-06 3:15 ` Andy Yan
2016-07-06 8:03 ` Wadim Egorov
1 sibling, 1 reply; 16+ messages in thread
From: Andy Yan @ 2016-07-06 3:15 UTC (permalink / raw)
To: Wadim Egorov, Lee Jones
Cc: mark.rutland, devicetree, a.zummo, pawel.moll, rtc-linux,
ijc+devicetree, mturquette, sboyd, linux-kernel, lgirdwood,
linux-rockchip, robh+dt, alexandre.belloni, broonie, dianders,
galak, zyw, linux-clk
Hi Wadim:
On 2016年06月09日 16:23, Wadim Egorov wrote:
> Hi,
>
> On 08.06.2016 16:17, Lee Jones wrote:
>> On Thu, 02 Jun 2016, Wadim Egorov wrote:
>>
>>> The RK818 chip is a power management IC for multimedia and handheld
>> "Power Management IC (PMIC)"
>>
>>> devices. It contains the following components:
>>>
>>> - Regulators
>>> - RTC
>>> - Clkout
>> Clocking
>>
>>> - battery support
>> Battery support
>>
>>> Both chips RK808 and RK818 are using a similar register map.
>> "Both RK808 ad RK818 chips"
>>
>>> So we can reuse the RTC and Clkout functionality.
>> Swap '.' for ','.
>>
>>> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
>>> ---
>>> drivers/mfd/Kconfig | 4 +-
>>> drivers/mfd/rk808.c | 231 ++++++++++++++++++++++++++++++++++++++--------
>>> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
>>> 3 files changed, 350 insertions(+), 47 deletions(-)
>>>
>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>> index 1bcf601..7ba464b 100644
>>> --- a/drivers/mfd/Kconfig
>>> +++ b/drivers/mfd/Kconfig
>>> @@ -839,13 +839,13 @@ config MFD_RC5T583
>>> different functionality of the device.
>>>
>>> config MFD_RK808
>>> - tristate "Rockchip RK808 Power Management chip"
>>> + tristate "Rockchip RK808/RK818 Power Management chip"
>> "Chip"
>>
>>> depends on I2C && OF
>>> select MFD_CORE
>>> select REGMAP_I2C
>>> select REGMAP_IRQ
>>> help
>>> - If you say yes here you get support for the RK808
>>> + If you say yes here you get support for the RK808 and RK818
>>> Power Management chips.
>>> This driver provides common support for accessing the device
>>> through I2C interface. The device supports multiple sub-devices
>>> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
>>> index 49d7f62..3cf9724 100644
>>> --- a/drivers/mfd/rk808.c
>>> +++ b/drivers/mfd/rk808.c
>>> @@ -1,11 +1,15 @@
>>> /*
>>> - * MFD core driver for Rockchip RK808
>>> + * MFD core driver for Rockchip RK808/RK818
>>> *
>>> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
>>> *
>>> * Author: Chris Zhong <zyw@rock-chips.com>
>>> * Author: Zhang Qing <zhangqing@rock-chips.com>
>>> *
>>> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
>>> + *
>>> + * Author: Wadim Egorov <w.egorov@phytec.de>
>>> + *
>>> * This program is free software; you can redistribute it and/or modify it
>>> * under the terms and conditions of the GNU General Public License,
>>> * version 2, as published by the Free Software Foundation.
>>> @@ -22,12 +26,7 @@
>>> #include <linux/mfd/core.h>
>>> #include <linux/module.h>
>>> #include <linux/regmap.h>
>>> -
>>> -struct rk808_reg_data {
>>> - int addr;
>>> - int mask;
>>> - int value;
>>> -};
>> Why are you moving this to the header?
> It is now part of the rk808 struct.
>
>>> +#include <linux/of_device.h>
>>>
>>> static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>>> {
>>> @@ -57,6 +56,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>>> return false;
>>> }
>>>
>>> +static const struct regmap_config rk818_regmap_config = {
>>> + .reg_bits = 8,
>>> + .val_bits = 8,
>>> + .max_register = RK818_USB_CTRL_REG,
>>> + .cache_type = REGCACHE_RBTREE,
>>> + .volatile_reg = rk808_is_volatile_reg,
>>> +};
>>> +
>>> static const struct regmap_config rk808_regmap_config = {
>>> .reg_bits = 8,
>>> .val_bits = 8,
>>> @@ -83,7 +90,17 @@ static const struct mfd_cell rk808s[] = {
>>> },
>>> };
>>>
>>> -static const struct rk808_reg_data pre_init_reg[] = {
>>> +static const struct mfd_cell rk818s[] = {
>>> + { .name = "rk808-clkout", },
>> How does this differ to a normal -clock driver?
> I don't know. It is a normal clock driver.
>
>>> + { .name = "rk808-regulator", },
>>> + {
>>> + .name = "rk808-rtc",
>>> + .num_resources = ARRAY_SIZE(rtc_resources),
>>> + .resources = &rtc_resources[0],
>> .resources = rtc_resources, ?
>>
>>> + },
>>> +};
>>> +
>>> +static const struct rk8xx_reg_data rk808_pre_init_reg[] = {
>>> { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
>>> { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
>>> { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
>>> @@ -94,6 +111,22 @@ static const struct rk808_reg_data pre_init_reg[] = {
>>> VB_LO_SEL_3500MV },
>>> };
>>>
>>> +static const struct rk8xx_reg_data rk818_pre_init_reg[] = {
>>> + { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,
>>> + RK818_USB_ILMIN_2000MA },
>>> + /* close charger when usb lower then 3.4V */
>>> + { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, (0x7 << 4) },
>>> + /* no action when vref */
>>> + { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },
>>> + /* enable HDMI 5V */
>>> + { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
>>> + /* improve efficiency */
>>> + { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
>>> + { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
>>> + { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
>>> + { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | VB_LO_SEL_3500MV },
>>> +};
>> The alignment here looks odd.
> I will fix it in the next version.
>
>>> static const struct regmap_irq rk808_irqs[] = {
>>> /* INT_STS */
>>> [RK808_IRQ_VOUT_LO] = {
>>> @@ -136,6 +169,76 @@ static const struct regmap_irq rk808_irqs[] = {
>>> },
>>> };
>>>
>>> +static const struct regmap_irq rk818_irqs[] = {
>>> + /* INT_STS */
>>> + [RK818_IRQ_VOUT_LO] = {
>>> + .mask = RK818_IRQ_VOUT_LO_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_VB_LO] = {
>>> + .mask = RK818_IRQ_VB_LO_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_PWRON] = {
>>> + .mask = RK818_IRQ_PWRON_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_PWRON_LP] = {
>>> + .mask = RK818_IRQ_PWRON_LP_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_HOTDIE] = {
>>> + .mask = RK818_IRQ_HOTDIE_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_RTC_ALARM] = {
>>> + .mask = RK818_IRQ_RTC_ALARM_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_RTC_PERIOD] = {
>>> + .mask = RK818_IRQ_RTC_PERIOD_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> + [RK818_IRQ_USB_OV] = {
>>> + .mask = RK818_IRQ_USB_OV_MSK,
>>> + .reg_offset = 0,
>>> + },
>>> +
>>> + /* INT_STS2 */
>>> + [RK818_IRQ_PLUG_IN] = {
>>> + .mask = RK818_IRQ_PLUG_IN_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_PLUG_OUT] = {
>>> + .mask = RK818_IRQ_PLUG_OUT_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_CHG_OK] = {
>>> + .mask = RK818_IRQ_CHG_OK_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_CHG_TE] = {
>>> + .mask = RK818_IRQ_CHG_TE_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_CHG_TS1] = {
>>> + .mask = RK818_IRQ_CHG_TS1_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_TS2] = {
>>> + .mask = RK818_IRQ_TS2_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_CHG_CVTLIM] = {
>>> + .mask = RK818_IRQ_CHG_CVTLIM_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> + [RK818_IRQ_DISCHG_ILIM] = {
>>> + .mask = RK818_IRQ_DISCHG_ILIM_MSK,
>>> + .reg_offset = 1,
>>> + },
>>> +};
>>> +
>>> static struct regmap_irq_chip rk808_irq_chip = {
>>> .name = "rk808",
>>> .irqs = rk808_irqs,
>>> @@ -148,6 +251,18 @@ static struct regmap_irq_chip rk808_irq_chip = {
>>> .init_ack_masked = true,
>>> };
>>>
>>> +static struct regmap_irq_chip rk818_irq_chip = {
>>> + .name = "rk818",
>>> + .irqs = rk818_irqs,
>>> + .num_irqs = ARRAY_SIZE(rk818_irqs),
>>> + .num_regs = 2,
>>> + .irq_reg_stride = 2,
>>> + .status_base = RK818_INT_STS_REG1,
>>> + .mask_base = RK818_INT_STS_MSK_REG1,
>>> + .ack_base = RK818_INT_STS_REG1,
>>> + .init_ack_masked = true,
>>> +};
>>> +
>>> static struct i2c_client *rk808_i2c_client;
>>> static void rk808_device_shutdown(void)
>>> {
>>> @@ -167,6 +282,48 @@ static void rk808_device_shutdown(void)
>>> dev_err(&rk808_i2c_client->dev, "power off error!\n");
>>> }
>>>
>>> +static const struct of_device_id rk808_of_match[] = {
>>> + { .compatible = "rockchip,rk808", .data = (void *) RK808_ID },
>>> + { .compatible = "rockchip,rk818", .data = (void *) RK818_ID },
>>> + { },
>>> +};
>>> +MODULE_DEVICE_TABLE(of, rk808_of_match);
>>> +
>>> +static int rk8xx_match_device(struct rk808 *rk808, struct device *dev)
>> If you're going to do it this way, please switch these parameters.
>>
>> It's more common to return the pointer however.
> If it's more common I will return a pointer to rk808.
>
>>> +{
>>> + const struct of_device_id *of_id;
>>> +
>>> + of_id = of_match_device(rk808_of_match, dev);
>>> + if (!of_id) {
>>> + dev_err(dev, "Unable to match OF ID\n");
>>> + return -ENODEV;
>>> + }
>>> + rk808->variant = (long) of_id->data;
>>> +
>>> + switch (rk808->variant) {
>>> + case RK808_ID:
>>> + rk808->nr_cells = ARRAY_SIZE(rk808s);
>>> + rk808->cells = rk808s;
>>> + rk808->regmap_cfg = &rk808_regmap_config;
>>> + rk808->regmap_irq_chip = &rk808_irq_chip;
>>> + rk808->pre_init_reg = rk808_pre_init_reg;
>>> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
>>> + break;
>>> + case RK818_ID:
>>> + rk808->nr_cells = ARRAY_SIZE(rk818s);
>>> + rk808->cells = rk818s;
>>> + rk808->regmap_cfg = &rk818_regmap_config;
>>> + rk808->regmap_irq_chip = &rk818_irq_chip;
>>> + rk808->pre_init_reg = rk818_pre_init_reg;
>>> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
>>> + break;
>>> + default:
>>> + dev_err(dev, "unsupported RK8XX ID %lu\n", rk808->variant);
>>> + return -EINVAL;
>>> + }
>>> +
>>> + return 0;
>>> +}
>>> static int rk808_probe(struct i2c_client *client,
>>> const struct i2c_device_id *id)
>>> {
>>> @@ -176,46 +333,52 @@ static int rk808_probe(struct i2c_client *client,
>>> int ret;
>>> int i;
>>>
>>> - if (!client->irq) {
>>> - dev_err(&client->dev, "No interrupt support, no core IRQ\n");
>>> - return -EINVAL;
>>> - }
>>> -
>>> rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
>>> if (!rk808)
>>> return -ENOMEM;
>>>
>>> - rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config);
>>> + ret = rk8xx_match_device(rk808, &client->dev);
>> Is there a way to dynamically probe the device? No device ID you can
>> read directly from the silicon?
> AFAIK there is no device ID register. At least it is not documented in
> the manual.
register 0x17 and 0x18 is the ID register, 0x17 is the MSB, 0x18 is LSB
for RK818, register 0x17 is 0x81, 0x18 is 0x81
>
> Wadim
>
>>> + if (ret)
>>> + return ret;
>>> +
>>> + rk808->i2c = client;
>>> + i2c_set_clientdata(client, rk808);
>>> +
>>> + rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg);
>>> if (IS_ERR(rk808->regmap)) {
>>> dev_err(&client->dev, "regmap initialization failed\n");
>>> return PTR_ERR(rk808->regmap);
>>> }
>>>
>>> - for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) {
>>> - ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr,
>>> - pre_init_reg[i].mask,
>>> - pre_init_reg[i].value);
>>> - if (ret) {
>>> - dev_err(&client->dev,
>>> - "0x%x write err\n", pre_init_reg[i].addr);
>>> - return ret;
>>> - }
>>> + if (!client->irq) {
>>> + dev_err(&client->dev, "No interrupt support, no core IRQ\n");
>>> + return -EINVAL;
>>> }
>>>
>>> ret = regmap_add_irq_chip(rk808->regmap, client->irq,
>>> IRQF_ONESHOT, -1,
>>> - &rk808_irq_chip, &rk808->irq_data);
>>> + rk808->regmap_irq_chip, &rk808->irq_data);
>>> if (ret) {
>>> dev_err(&client->dev, "Failed to add irq_chip %d\n", ret);
>>> return ret;
>>> }
>>>
>>> - rk808->i2c = client;
>>> - i2c_set_clientdata(client, rk808);
>>> + for (i = 0; i < rk808->nr_pre_init_regs; i++) {
>>> + ret = regmap_update_bits(rk808->regmap,
>>> + rk808->pre_init_reg[i].addr,
>>> + rk808->pre_init_reg[i].mask,
>>> + rk808->pre_init_reg[i].value);
>>> + if (ret) {
>>> + dev_err(&client->dev,
>>> + "0x%x write err\n",
>>> + rk808->pre_init_reg[i].addr);
>>> + return ret;
>>> + }
>>> + }
>>>
>>> - ret = devm_mfd_add_devices(&client->dev, -1,
>>> - rk808s, ARRAY_SIZE(rk808s), NULL, 0,
>>> - regmap_irq_get_domain(rk808->irq_data));
>>> + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
>>> + rk808->cells, rk808->nr_cells, NULL, 0,
>>> + regmap_irq_get_domain(rk808->irq_data));
>>> if (ret) {
>>> dev_err(&client->dev, "failed to add MFD devices %d\n", ret);
>>> goto err_irq;
>>> @@ -245,14 +408,9 @@ static int rk808_remove(struct i2c_client *client)
>>> return 0;
>>> }
>>>
>>> -static const struct of_device_id rk808_of_match[] = {
>>> - { .compatible = "rockchip,rk808" },
>>> - { },
>>> -};
>>> -MODULE_DEVICE_TABLE(of, rk808_of_match);
>>> -
>>> static const struct i2c_device_id rk808_ids[] = {
>>> { "rk808" },
>>> + { "rk818" },
>>> { },
>>> };
>>> MODULE_DEVICE_TABLE(i2c, rk808_ids);
>>> @@ -272,4 +430,5 @@ module_i2c_driver(rk808_i2c_driver);
>>> MODULE_LICENSE("GPL");
>>> MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
>>> MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
>>> -MODULE_DESCRIPTION("RK808 PMIC driver");
>>> +MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
>>> +MODULE_DESCRIPTION("RK808/RK818 PMIC driver");
>>> diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
>>> index 441b6ee..5ce810c 100644
>>> --- a/include/linux/mfd/rk808.h
>>> +++ b/include/linux/mfd/rk808.h
>>> @@ -1,11 +1,15 @@
>>> /*
>>> - * rk808.h for Rockchip RK808
>>> + * Register definitions for Rockchip's RK808/RK818 PMIC
>>> *
>>> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
>>> *
>>> * Author: Chris Zhong <zyw@rock-chips.com>
>>> * Author: Zhang Qing <zhangqing@rock-chips.com>
>>> *
>>> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
>>> + *
>>> + * Author: Wadim Egorov <w.egorov@phytec.de>
>>> + *
>>> * This program is free software; you can redistribute it and/or modify it
>>> * under the terms and conditions of the GNU General Public License,
>>> * version 2, as published by the Free Software Foundation.
>>> @@ -16,8 +20,8 @@
>>> * more details.
>>> */
>>>
>>> -#ifndef __LINUX_REGULATOR_rk808_H
>>> -#define __LINUX_REGULATOR_rk808_H
>>> +#ifndef __LINUX_REGULATOR_RK808_H
>>> +#define __LINUX_REGULATOR_RK808_H
>>>
>>> #include <linux/regulator/machine.h>
>>> #include <linux/regmap.h>
>>> @@ -28,7 +32,7 @@
>>>
>>> #define RK808_DCDC1 0 /* (0+RK808_START) */
>>> #define RK808_LDO1 4 /* (4+RK808_START) */
>>> -#define RK808_NUM_REGULATORS 14
>>> +#define RK808_NUM_REGULATORS 14
>>>
>>> enum rk808_reg {
>>> RK808_ID_DCDC1,
>>> @@ -115,7 +119,92 @@ enum rk808_reg {
>>> #define RK808_INT_STS_MSK_REG2 0x4f
>>> #define RK808_IO_POL_REG 0x50
>>>
>>> -/* IRQ Definitions */
>>> +/* RK818 */
>>> +#define RK818_DCDC1 0
>>> +#define RK818_LDO1 4
>>> +#define RK818_NUM_REGULATORS 17
>>> +
>>> +enum rk818_reg {
>>> + RK818_ID_DCDC1,
>>> + RK818_ID_DCDC2,
>>> + RK818_ID_DCDC3,
>>> + RK818_ID_DCDC4,
>>> + RK818_ID_BOOST,
>>> + RK818_ID_LDO1,
>>> + RK818_ID_LDO2,
>>> + RK818_ID_LDO3,
>>> + RK818_ID_LDO4,
>>> + RK818_ID_LDO5,
>>> + RK818_ID_LDO6,
>>> + RK818_ID_LDO7,
>>> + RK818_ID_LDO8,
>>> + RK818_ID_LDO9,
>>> + RK818_ID_SWITCH,
>>> + RK818_ID_HDMI_SWITCH,
>>> + RK818_ID_OTG_SWITCH,
>>> +};
>>> +
>>> +#define RK818_DCDC_EN_REG 0x23
>>> +#define RK818_LDO_EN_REG 0x24
>>> +#define RK818_SLEEP_SET_OFF_REG1 0x25
>>> +#define RK818_SLEEP_SET_OFF_REG2 0x26
>>> +#define RK818_DCDC_UV_STS_REG 0x27
>>> +#define RK818_DCDC_UV_ACT_REG 0x28
>>> +#define RK818_LDO_UV_STS_REG 0x29
>>> +#define RK818_LDO_UV_ACT_REG 0x2a
>>> +#define RK818_DCDC_PG_REG 0x2b
>>> +#define RK818_LDO_PG_REG 0x2c
>>> +#define RK818_VOUT_MON_TDB_REG 0x2d
>>> +#define RK818_BUCK1_CONFIG_REG 0x2e
>>> +#define RK818_BUCK1_ON_VSEL_REG 0x2f
>>> +#define RK818_BUCK1_SLP_VSEL_REG 0x30
>>> +#define RK818_BUCK2_CONFIG_REG 0x32
>>> +#define RK818_BUCK2_ON_VSEL_REG 0x33
>>> +#define RK818_BUCK2_SLP_VSEL_REG 0x34
>>> +#define RK818_BUCK3_CONFIG_REG 0x36
>>> +#define RK818_BUCK4_CONFIG_REG 0x37
>>> +#define RK818_BUCK4_ON_VSEL_REG 0x38
>>> +#define RK818_BUCK4_SLP_VSEL_REG 0x39
>>> +#define RK818_BOOST_CONFIG_REG 0x3a
>>> +#define RK818_LDO1_ON_VSEL_REG 0x3b
>>> +#define RK818_LDO1_SLP_VSEL_REG 0x3c
>>> +#define RK818_LDO2_ON_VSEL_REG 0x3d
>>> +#define RK818_LDO2_SLP_VSEL_REG 0x3e
>>> +#define RK818_LDO3_ON_VSEL_REG 0x3f
>>> +#define RK818_LDO3_SLP_VSEL_REG 0x40
>>> +#define RK818_LDO4_ON_VSEL_REG 0x41
>>> +#define RK818_LDO4_SLP_VSEL_REG 0x42
>>> +#define RK818_LDO5_ON_VSEL_REG 0x43
>>> +#define RK818_LDO5_SLP_VSEL_REG 0x44
>>> +#define RK818_LDO6_ON_VSEL_REG 0x45
>>> +#define RK818_LDO6_SLP_VSEL_REG 0x46
>>> +#define RK818_LDO7_ON_VSEL_REG 0x47
>>> +#define RK818_LDO7_SLP_VSEL_REG 0x48
>>> +#define RK818_LDO8_ON_VSEL_REG 0x49
>>> +#define RK818_LDO8_SLP_VSEL_REG 0x4a
>>> +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54
>>> +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55
>>> +#define RK818_DEVCTRL_REG 0x4b
>>> +#define RK818_INT_STS_REG1 0X4c
>>> +#define RK818_INT_STS_MSK_REG1 0x4d
>>> +#define RK818_INT_STS_REG2 0x4e
>>> +#define RK818_INT_STS_MSK_REG2 0x4f
>>> +#define RK818_IO_POL_REG 0x50
>>> +#define RK818_H5V_EN_REG 0x52
>>> +#define RK818_SLEEP_SET_OFF_REG3 0x53
>>> +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54
>>> +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55
>>> +#define RK818_BOOST_CTRL_REG 0x56
>>> +#define RK818_DCDC_ILMAX 0x90
>>> +#define RK818_USB_CTRL_REG 0xa1
>>> +
>>> +#define RK818_H5V_EN BIT(0)
>>> +#define RK818_REF_RDY_CTRL BIT(1)
>>> +#define RK818_USB_ILIM_SEL_MASK 0xf
>>> +#define RK818_USB_ILMIN_2000MA 0x7
>>> +#define RK818_USB_CHG_SD_VSEL_MASK 0x70
>>> +
>>> +/* RK808 IRQ Definitions */
>>> #define RK808_IRQ_VOUT_LO 0
>>> #define RK808_IRQ_VB_LO 1
>>> #define RK808_IRQ_PWRON 2
>>> @@ -137,6 +226,43 @@ enum rk808_reg {
>>> #define RK808_IRQ_PLUG_IN_INT_MSK BIT(0)
>>> #define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1)
>>>
>>> +/* RK818 IRQ Definitions */
>>> +#define RK818_IRQ_VOUT_LO 0
>>> +#define RK818_IRQ_VB_LO 1
>>> +#define RK818_IRQ_PWRON 2
>>> +#define RK818_IRQ_PWRON_LP 3
>>> +#define RK818_IRQ_HOTDIE 4
>>> +#define RK818_IRQ_RTC_ALARM 5
>>> +#define RK818_IRQ_RTC_PERIOD 6
>>> +#define RK818_IRQ_USB_OV 7
>>> +#define RK818_IRQ_PLUG_IN 8
>>> +#define RK818_IRQ_PLUG_OUT 9
>>> +#define RK818_IRQ_CHG_OK 10
>>> +#define RK818_IRQ_CHG_TE 11
>>> +#define RK818_IRQ_CHG_TS1 12
>>> +#define RK818_IRQ_TS2 13
>>> +#define RK818_IRQ_CHG_CVTLIM 14
>>> +#define RK818_IRQ_DISCHG_ILIM 7
>>> +
>>> +#define RK818_IRQ_VOUT_LO_MSK BIT(0)
>>> +#define RK818_IRQ_VB_LO_MSK BIT(1)
>>> +#define RK818_IRQ_PWRON_MSK BIT(2)
>>> +#define RK818_IRQ_PWRON_LP_MSK BIT(3)
>>> +#define RK818_IRQ_HOTDIE_MSK BIT(4)
>>> +#define RK818_IRQ_RTC_ALARM_MSK BIT(5)
>>> +#define RK818_IRQ_RTC_PERIOD_MSK BIT(6)
>>> +#define RK818_IRQ_USB_OV_MSK BIT(7)
>>> +#define RK818_IRQ_PLUG_IN_MSK BIT(0)
>>> +#define RK818_IRQ_PLUG_OUT_MSK BIT(1)
>>> +#define RK818_IRQ_CHG_OK_MSK BIT(2)
>>> +#define RK818_IRQ_CHG_TE_MSK BIT(3)
>>> +#define RK818_IRQ_CHG_TS1_MSK BIT(4)
>>> +#define RK818_IRQ_TS2_MSK BIT(5)
>>> +#define RK818_IRQ_CHG_CVTLIM_MSK BIT(6)
>>> +#define RK818_IRQ_DISCHG_ILIM_MSK BIT(7)
>>> +
>>> +#define RK818_NUM_IRQ 16
>>> +
>>> #define RK808_VBAT_LOW_2V8 0x00
>>> #define RK808_VBAT_LOW_2V9 0x01
>>> #define RK808_VBAT_LOW_3V0 0x02
>>> @@ -191,9 +317,27 @@ enum {
>>> BOOST_ILMIN_250MA,
>>> };
>>>
>>> +enum {
>>> + RK808_ID,
>>> + RK818_ID,
>>> +};
>>> +
>>> +struct rk8xx_reg_data {
>>> + int addr;
>>> + int mask;
>>> + int value;
>>> +};
>>> +
>>> struct rk808 {
>>> - struct i2c_client *i2c;
>>> - struct regmap_irq_chip_data *irq_data;
>>> - struct regmap *regmap;
>>> + struct i2c_client *i2c;
>>> + struct regmap_irq_chip_data *irq_data;
>>> + struct regmap *regmap;
>>> + long variant;
>>> + int nr_cells;
>>> + const struct mfd_cell *cells;
>>> + const struct regmap_config *regmap_cfg;
>>> + const struct regmap_irq_chip *regmap_irq_chip;
>>> + const struct rk8xx_reg_data *pre_init_reg;
>>> + int nr_pre_init_regs;
>>> };
>>> -#endif /* __LINUX_REGULATOR_rk808_H */
>>> +#endif /* __LINUX_REGULATOR_RK808_H */
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-07-06 3:15 ` Andy Yan
@ 2016-07-06 8:03 ` Wadim Egorov
2016-07-06 8:56 ` Andy Yan
2016-08-05 12:22 ` Lee Jones
0 siblings, 2 replies; 16+ messages in thread
From: Wadim Egorov @ 2016-07-06 8:03 UTC (permalink / raw)
To: Andy Yan, Lee Jones
Cc: mark.rutland, devicetree, a.zummo, pawel.moll, rtc-linux,
ijc+devicetree, mturquette, sboyd, linux-kernel, lgirdwood,
linux-rockchip, robh+dt, alexandre.belloni, broonie, dianders,
galak, zyw, linux-clk
Hi Andy,
On 06.07.2016 05:15, Andy Yan wrote:
> Hi Wadim:
>
> On 2016=E5=B9=B406=E6=9C=8809=E6=97=A5 16:23, Wadim Egorov wrote:
>> Hi,
>>
>> On 08.06.2016 16:17, Lee Jones wrote:
>>> On Thu, 02 Jun 2016, Wadim Egorov wrote:
>>>
>>>> The RK818 chip is a power management IC for multimedia and handheld
>>> "Power Management IC (PMIC)"
>>>
>>>> devices. It contains the following components:
>>>>
>>>> - Regulators
>>>> - RTC
>>>> - Clkout
>>> Clocking
>>>
>>>> - battery support
>>> Battery support
>>>
>>>> Both chips RK808 and RK818 are using a similar register map.
>>> "Both RK808 ad RK818 chips"
>>>
>>>> So we can reuse the RTC and Clkout functionality.
>>> Swap '.' for ','.
>>>
>>>> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
>>>> ---
>>>> drivers/mfd/Kconfig | 4 +-
>>>> drivers/mfd/rk808.c | 231
>>>> ++++++++++++++++++++++++++++++++++++++--------
>>>> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
>>>> 3 files changed, 350 insertions(+), 47 deletions(-)
>>>>
>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>> index 1bcf601..7ba464b 100644
>>>> --- a/drivers/mfd/Kconfig
>>>> +++ b/drivers/mfd/Kconfig
>>>> @@ -839,13 +839,13 @@ config MFD=5FRC5T583
>>>> different functionality of the device.
>>>> config MFD=5FRK808
>>>> - tristate "Rockchip RK808 Power Management chip"
>>>> + tristate "Rockchip RK808/RK818 Power Management chip"
>>> "Chip"
>>>
>>>> depends on I2C && OF
>>>> select MFD=5FCORE
>>>> select REGMAP=5FI2C
>>>> select REGMAP=5FIRQ
>>>> help
>>>> - If you say yes here you get support for the RK808
>>>> + If you say yes here you get support for the RK808 and RK818
>>>> Power Management chips.
>>>> This driver provides common support for accessing the device
>>>> through I2C interface. The device supports multiple
>>>> sub-devices
>>>> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
>>>> index 49d7f62..3cf9724 100644
>>>> --- a/drivers/mfd/rk808.c
>>>> +++ b/drivers/mfd/rk808.c
>>>> @@ -1,11 +1,15 @@
>>>> /*
>>>> - * MFD core driver for Rockchip RK808
>>>> + * MFD core driver for Rockchip RK808/RK818
>>>> *
>>>> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
>>>> *
>>>> * Author: Chris Zhong <zyw@rock-chips.com>
>>>> * Author: Zhang Qing <zhangqing@rock-chips.com>
>>>> *
>>>> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
>>>> + *
>>>> + * Author: Wadim Egorov <w.egorov@phytec.de>
>>>> + *
>>>> * This program is free software; you can redistribute it and/or
>>>> modify it
>>>> * under the terms and conditions of the GNU General Public License,
>>>> * version 2, as published by the Free Software Foundation.
>>>> @@ -22,12 +26,7 @@
>>>> #include <linux/mfd/core.h>
>>>> #include <linux/module.h>
>>>> #include <linux/regmap.h>
>>>> -
>>>> -struct rk808=5Freg=5Fdata {
>>>> - int addr;
>>>> - int mask;
>>>> - int value;
>>>> -};
>>> Why are you moving this to the header?
>> It is now part of the rk808 struct.
>>
>>>> +#include <linux/of=5Fdevice.h>
>>>> static bool rk808=5Fis=5Fvolatile=5Freg(struct device *dev, unsign=
ed
>>>> int reg)
>>>> {
>>>> @@ -57,6 +56,14 @@ static bool rk808=5Fis=5Fvolatile=5Freg(struct devi=
ce
>>>> *dev, unsigned int reg)
>>>> return false;
>>>> }
>>>> +static const struct regmap=5Fconfig rk818=5Fregmap=5Fconfig =3D {
>>>> + .reg=5Fbits =3D 8,
>>>> + .val=5Fbits =3D 8,
>>>> + .max=5Fregister =3D RK818=5FUSB=5FCTRL=5FREG,
>>>> + .cache=5Ftype =3D REGCACHE=5FRBTREE,
>>>> + .volatile=5Freg =3D rk808=5Fis=5Fvolatile=5Freg,
>>>> +};
>>>> +
>>>> static const struct regmap=5Fconfig rk808=5Fregmap=5Fconfig =3D {
>>>> .reg=5Fbits =3D 8,
>>>> .val=5Fbits =3D 8,
>>>> @@ -83,7 +90,17 @@ static const struct mfd=5Fcell rk808s[] =3D {
>>>> },
>>>> };
>>>> -static const struct rk808=5Freg=5Fdata pre=5Finit=5Freg[] =3D {
>>>> +static const struct mfd=5Fcell rk818s[] =3D {
>>>> + { .name =3D "rk808-clkout", },
>>> How does this differ to a normal -clock driver?
>> I don't know. It is a normal clock driver.
>>
>>>> + { .name =3D "rk808-regulator", },
>>>> + {
>>>> + .name =3D "rk808-rtc",
>>>> + .num=5Fresources =3D ARRAY=5FSIZE(rtc=5Fresources),
>>>> + .resources =3D &rtc=5Fresources[0],
>>> .resources =3D rtc=5Fresources, ?
>>>
>>>> + },
>>>> +};
>>>> +
>>>> +static const struct rk8xx=5Freg=5Fdata rk808=5Fpre=5Finit=5Freg[] =3D=
{
>>>> { RK808=5FBUCK3=5FCONFIG=5FREG, BUCK=5FILMIN=5FMASK, BUCK=5FILM=
IN=5F150MA },
>>>> { RK808=5FBUCK4=5FCONFIG=5FREG, BUCK=5FILMIN=5FMASK, BUCK=5FILM=
IN=5F200MA },
>>>> { RK808=5FBOOST=5FCONFIG=5FREG, BOOST=5FILMIN=5FMASK, BOOST=5FIL=
MIN=5F100MA },
>>>> @@ -94,6 +111,22 @@ static const struct rk808=5Freg=5Fdata
>>>> pre=5Finit=5Freg[] =3D {
>>>> VB=5FLO=5FSEL=5F3500MV },
>>>> };
>>>> +static const struct rk8xx=5Freg=5Fdata rk818=5Fpre=5Finit=5Freg[] =
=3D {
>>>> + { RK818=5FUSB=5FCTRL=5FREG, RK818=5FUSB=5FILIM=5FSEL=5FMASK,
>>>> + RK818=5FUSB=5FILMIN=5F2000MA },
>>>> + /* close charger when usb lower then 3.4V */
>>>> + { RK818=5FUSB=5FCTRL=5FREG, RK818=5FUSB=5FCHG=5FSD=5FVSEL=5FMA=
SK, (0x7 <<
>>>> 4) },
>>>> + /* no action when vref */
>>>> + { RK818=5FH5V=5FEN=5FREG, BIT(1), RK818=5FREF=5FRDY=5FC=
TRL },
>>>> + /* enable HDMI 5V */
>>>> + { RK818=5FH5V=5FEN=5FREG, BIT(0), RK818=5FH5V=5FEN },
>>>> + /* improve efficiency */
>>>> + { RK818=5FBUCK2=5FCONFIG=5FREG, BUCK2=5FRATE=5FMASK, BUCK=5FIL=
MIN=5F250MA },
>>>> + { RK818=5FBUCK4=5FCONFIG=5FREG, BUCK=5FILMIN=5FMASK, BUCK=5FIL=
MIN=5F250MA },
>>>> + { RK818=5FBOOST=5FCONFIG=5FREG, BOOST=5FILMIN=5FMASK, =20
>>>> BOOST=5FILMIN=5F100MA },
>>>> + { RK808=5FVB=5FMON=5FREG, MASK=5FALL, VB=5FLO=5FACT |
>>>> VB=5FLO=5FSEL=5F3500MV },
>>>> +};
>>> The alignment here looks odd.
>> I will fix it in the next version.
>>
>>>> static const struct regmap=5Firq rk808=5Firqs[] =3D {
>>>> /* INT=5FSTS */
>>>> [RK808=5FIRQ=5FVOUT=5FLO] =3D {
>>>> @@ -136,6 +169,76 @@ static const struct regmap=5Firq rk808=5Firqs[] =
=3D {
>>>> },
>>>> };
>>>> +static const struct regmap=5Firq rk818=5Firqs[] =3D {
>>>> + /* INT=5FSTS */
>>>> + [RK818=5FIRQ=5FVOUT=5FLO] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FVOUT=5FLO=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FVB=5FLO] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FVB=5FLO=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FPWRON] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FPWRON=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FPWRON=5FLP] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FPWRON=5FLP=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FHOTDIE] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FHOTDIE=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FRTC=5FALARM] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FRTC=5FALARM=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FRTC=5FPERIOD] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FRTC=5FPERIOD=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> + [RK818=5FIRQ=5FUSB=5FOV] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FUSB=5FOV=5FMSK,
>>>> + .reg=5Foffset =3D 0,
>>>> + },
>>>> +
>>>> + /* INT=5FSTS2 */
>>>> + [RK818=5FIRQ=5FPLUG=5FIN] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FPLUG=5FIN=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FPLUG=5FOUT] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FPLUG=5FOUT=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FCHG=5FOK] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FCHG=5FOK=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FCHG=5FTE] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FCHG=5FTE=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FCHG=5FTS1] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FCHG=5FTS1=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FTS2] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FTS2=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FCHG=5FCVTLIM] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FCHG=5FCVTLIM=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> + [RK818=5FIRQ=5FDISCHG=5FILIM] =3D {
>>>> + .mask =3D RK818=5FIRQ=5FDISCHG=5FILIM=5FMSK,
>>>> + .reg=5Foffset =3D 1,
>>>> + },
>>>> +};
>>>> +
>>>> static struct regmap=5Firq=5Fchip rk808=5Firq=5Fchip =3D {
>>>> .name =3D "rk808",
>>>> .irqs =3D rk808=5Firqs,
>>>> @@ -148,6 +251,18 @@ static struct regmap=5Firq=5Fchip rk808=5Firq=5Fc=
hip =3D {
>>>> .init=5Fack=5Fmasked =3D true,
>>>> };
>>>> +static struct regmap=5Firq=5Fchip rk818=5Firq=5Fchip =3D {
>>>> + .name =3D "rk818",
>>>> + .irqs =3D rk818=5Firqs,
>>>> + .num=5Firqs =3D ARRAY=5FSIZE(rk818=5Firqs),
>>>> + .num=5Fregs =3D 2,
>>>> + .irq=5Freg=5Fstride =3D 2,
>>>> + .status=5Fbase =3D RK818=5FINT=5FSTS=5FREG1,
>>>> + .mask=5Fbase =3D RK818=5FINT=5FSTS=5FMSK=5FREG1,
>>>> + .ack=5Fbase =3D RK818=5FINT=5FSTS=5FREG1,
>>>> + .init=5Fack=5Fmasked =3D true,
>>>> +};
>>>> +
>>>> static struct i2c=5Fclient *rk808=5Fi2c=5Fclient;
>>>> static void rk808=5Fdevice=5Fshutdown(void)
>>>> {
>>>> @@ -167,6 +282,48 @@ static void rk808=5Fdevice=5Fshutdown(void)
>>>> dev=5Ferr(&rk808=5Fi2c=5Fclient->dev, "power off error!\n");
>>>> }
>>>> +static const struct of=5Fdevice=5Fid rk808=5Fof=5Fmatch[] =3D {
>>>> + { .compatible =3D "rockchip,rk808", .data =3D (void *) RK808=5FID=
},
>>>> + { .compatible =3D "rockchip,rk818", .data =3D (void *) RK818=5FID=
},
>>>> + { },
>>>> +};
>>>> +MODULE=5FDEVICE=5FTABLE(of, rk808=5Fof=5Fmatch);
>>>> +
>>>> +static int rk8xx=5Fmatch=5Fdevice(struct rk808 *rk808, struct device
>>>> *dev)
>>> If you're going to do it this way, please switch these parameters.
>>>
>>> It's more common to return the pointer however.
>> If it's more common I will return a pointer to rk808.
>>
>>>> +{
>>>> + const struct of=5Fdevice=5Fid *of=5Fid;
>>>> +
>>>> + of=5Fid =3D of=5Fmatch=5Fdevice(rk808=5Fof=5Fmatch, dev);
>>>> + if (!of=5Fid) {
>>>> + dev=5Ferr(dev, "Unable to match OF ID\n");
>>>> + return -ENODEV;
>>>> + }
>>>> + rk808->variant =3D (long) of=5Fid->data;
>>>> +
>>>> + switch (rk808->variant) {
>>>> + case RK808=5FID:
>>>> + rk808->nr=5Fcells =3D ARRAY=5FSIZE(rk808s);
>>>> + rk808->cells =3D rk808s;
>>>> + rk808->regmap=5Fcfg =3D &rk808=5Fregmap=5Fconfig;
>>>> + rk808->regmap=5Firq=5Fchip =3D &rk808=5Firq=5Fchip;
>>>> + rk808->pre=5Finit=5Freg =3D rk808=5Fpre=5Finit=5Freg;
>>>> + rk808->nr=5Fpre=5Finit=5Fregs =3D ARRAY=5FSIZE(rk808=5Fpre=5F=
init=5Freg);
>>>> + break;
>>>> + case RK818=5FID:
>>>> + rk808->nr=5Fcells =3D ARRAY=5FSIZE(rk818s);
>>>> + rk808->cells =3D rk818s;
>>>> + rk808->regmap=5Fcfg =3D &rk818=5Fregmap=5Fconfig;
>>>> + rk808->regmap=5Firq=5Fchip =3D &rk818=5Firq=5Fchip;
>>>> + rk808->pre=5Finit=5Freg =3D rk818=5Fpre=5Finit=5Freg;
>>>> + rk808->nr=5Fpre=5Finit=5Fregs =3D ARRAY=5FSIZE(rk818=5Fpre=5F=
init=5Freg);
>>>> + break;
>>>> + default:
>>>> + dev=5Ferr(dev, "unsupported RK8XX ID %lu\n", rk808->variant);
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +}
>>>> static int rk808=5Fprobe(struct i2c=5Fclient *client,
>>>> const struct i2c=5Fdevice=5Fid *id)
>>>> {
>>>> @@ -176,46 +333,52 @@ static int rk808=5Fprobe(struct i2c=5Fclient
>>>> *client,
>>>> int ret;
>>>> int i;
>>>> - if (!client->irq) {
>>>> - dev=5Ferr(&client->dev, "No interrupt support, no core IRQ\n"=
);
>>>> - return -EINVAL;
>>>> - }
>>>> -
>>>> rk808 =3D devm=5Fkzalloc(&client->dev, sizeof(*rk808), GFP=5FKER=
NEL);
>>>> if (!rk808)
>>>> return -ENOMEM;
>>>> - rk808->regmap =3D devm=5Fregmap=5Finit=5Fi2c(client,
>>>> &rk808=5Fregmap=5Fconfig);
>>>> + ret =3D rk8xx=5Fmatch=5Fdevice(rk808, &client->dev);
>>> Is there a way to dynamically probe the device? No device ID you can
>>> read directly from the silicon?
>> AFAIK there is no device ID register. At least it is not documented in
>> the manual.
>
> register 0x17 and 0x18 is the ID register, 0x17 is the MSB, 0x18 is LSB
>
> for RK818, register 0x17 is 0x81, 0x18 is 0x81
thank you for sharing this information. I have no RK808 PMIC device
here, so I would also need the IDs for RK808.
Lee, you have already applied this series. But I can't find the patches
in your kernel tree.
I would like to read the device ID from the register in the probe function.
Do you want me to base my changes on top of this series or send a new
version?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-07-06 8:03 ` Wadim Egorov
@ 2016-07-06 8:56 ` Andy Yan
2016-08-05 12:22 ` Lee Jones
1 sibling, 0 replies; 16+ messages in thread
From: Andy Yan @ 2016-07-06 8:56 UTC (permalink / raw)
To: Wadim Egorov, Lee Jones
Cc: mark.rutland, devicetree, a.zummo, pawel.moll, rtc-linux,
ijc+devicetree, mturquette, sboyd, linux-kernel, lgirdwood,
linux-rockchip, robh+dt, alexandre.belloni, broonie, dianders,
galak, zyw, linux-clk
Hi Wadim:
On 2016年07月06日 16:03, Wadim Egorov wrote:
> Hi Andy,
>
> On 06.07.2016 05:15, Andy Yan wrote:
>> Hi Wadim:
>>
>> On 2016年06月09日 16:23, Wadim Egorov wrote:
>>> Hi,
>>>
>>> On 08.06.2016 16:17, Lee Jones wrote:
>>>> On Thu, 02 Jun 2016, Wadim Egorov wrote:
>>>>
>>>>> The RK818 chip is a power management IC for multimedia and handheld
>>>> "Power Management IC (PMIC)"
>>>>
>>>>> devices. It contains the following components:
>>>>>
>>>>> - Regulators
>>>>> - RTC
>>>>> - Clkout
>>>> Clocking
>>>>
>>>>> - battery support
>>>> Battery support
>>>>
>>>>> Both chips RK808 and RK818 are using a similar register map.
>>>> "Both RK808 ad RK818 chips"
>>>>
>>>>> So we can reuse the RTC and Clkout functionality.
>>>> Swap '.' for ','.
>>>>
>>>>> Signed-off-by: Wadim Egorov <w.egorov@phytec.de>
>>>>> ---
>>>>> drivers/mfd/Kconfig | 4 +-
>>>>> drivers/mfd/rk808.c | 231
>>>>> ++++++++++++++++++++++++++++++++++++++--------
>>>>> include/linux/mfd/rk808.h | 162 ++++++++++++++++++++++++++++++--
>>>>> 3 files changed, 350 insertions(+), 47 deletions(-)
>>>>>
>>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>>> index 1bcf601..7ba464b 100644
>>>>> --- a/drivers/mfd/Kconfig
>>>>> +++ b/drivers/mfd/Kconfig
>>>>> @@ -839,13 +839,13 @@ config MFD_RC5T583
>>>>> different functionality of the device.
>>>>> config MFD_RK808
>>>>> - tristate "Rockchip RK808 Power Management chip"
>>>>> + tristate "Rockchip RK808/RK818 Power Management chip"
>>>> "Chip"
>>>>
>>>>> depends on I2C && OF
>>>>> select MFD_CORE
>>>>> select REGMAP_I2C
>>>>> select REGMAP_IRQ
>>>>> help
>>>>> - If you say yes here you get support for the RK808
>>>>> + If you say yes here you get support for the RK808 and RK818
>>>>> Power Management chips.
>>>>> This driver provides common support for accessing the device
>>>>> through I2C interface. The device supports multiple
>>>>> sub-devices
>>>>> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
>>>>> index 49d7f62..3cf9724 100644
>>>>> --- a/drivers/mfd/rk808.c
>>>>> +++ b/drivers/mfd/rk808.c
>>>>> @@ -1,11 +1,15 @@
>>>>> /*
>>>>> - * MFD core driver for Rockchip RK808
>>>>> + * MFD core driver for Rockchip RK808/RK818
>>>>> *
>>>>> * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
>>>>> *
>>>>> * Author: Chris Zhong <zyw@rock-chips.com>
>>>>> * Author: Zhang Qing <zhangqing@rock-chips.com>
>>>>> *
>>>>> + * Copyright (C) 2016 PHYTEC Messtechnik GmbH
>>>>> + *
>>>>> + * Author: Wadim Egorov <w.egorov@phytec.de>
>>>>> + *
>>>>> * This program is free software; you can redistribute it and/or
>>>>> modify it
>>>>> * under the terms and conditions of the GNU General Public License,
>>>>> * version 2, as published by the Free Software Foundation.
>>>>> @@ -22,12 +26,7 @@
>>>>> #include <linux/mfd/core.h>
>>>>> #include <linux/module.h>
>>>>> #include <linux/regmap.h>
>>>>> -
>>>>> -struct rk808_reg_data {
>>>>> - int addr;
>>>>> - int mask;
>>>>> - int value;
>>>>> -};
>>>> Why are you moving this to the header?
>>> It is now part of the rk808 struct.
>>>
>>>>> +#include <linux/of_device.h>
>>>>> static bool rk808_is_volatile_reg(struct device *dev, unsigned
>>>>> int reg)
>>>>> {
>>>>> @@ -57,6 +56,14 @@ static bool rk808_is_volatile_reg(struct device
>>>>> *dev, unsigned int reg)
>>>>> return false;
>>>>> }
>>>>> +static const struct regmap_config rk818_regmap_config = {
>>>>> + .reg_bits = 8,
>>>>> + .val_bits = 8,
>>>>> + .max_register = RK818_USB_CTRL_REG,
>>>>> + .cache_type = REGCACHE_RBTREE,
>>>>> + .volatile_reg = rk808_is_volatile_reg,
>>>>> +};
>>>>> +
>>>>> static const struct regmap_config rk808_regmap_config = {
>>>>> .reg_bits = 8,
>>>>> .val_bits = 8,
>>>>> @@ -83,7 +90,17 @@ static const struct mfd_cell rk808s[] = {
>>>>> },
>>>>> };
>>>>> -static const struct rk808_reg_data pre_init_reg[] = {
>>>>> +static const struct mfd_cell rk818s[] = {
>>>>> + { .name = "rk808-clkout", },
>>>> How does this differ to a normal -clock driver?
>>> I don't know. It is a normal clock driver.
>>>
>>>>> + { .name = "rk808-regulator", },
>>>>> + {
>>>>> + .name = "rk808-rtc",
>>>>> + .num_resources = ARRAY_SIZE(rtc_resources),
>>>>> + .resources = &rtc_resources[0],
>>>> .resources = rtc_resources, ?
>>>>
>>>>> + },
>>>>> +};
>>>>> +
>>>>> +static const struct rk8xx_reg_data rk808_pre_init_reg[] = {
>>>>> { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
>>>>> { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
>>>>> { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
>>>>> @@ -94,6 +111,22 @@ static const struct rk808_reg_data
>>>>> pre_init_reg[] = {
>>>>> VB_LO_SEL_3500MV },
>>>>> };
>>>>> +static const struct rk8xx_reg_data rk818_pre_init_reg[] = {
>>>>> + { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,
>>>>> + RK818_USB_ILMIN_2000MA },
>>>>> + /* close charger when usb lower then 3.4V */
>>>>> + { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, (0x7 <<
>>>>> 4) },
>>>>> + /* no action when vref */
>>>>> + { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },
>>>>> + /* enable HDMI 5V */
>>>>> + { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
>>>>> + /* improve efficiency */
>>>>> + { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
>>>>> + { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
>>>>> + { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK,
>>>>> BOOST_ILMIN_100MA },
>>>>> + { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
>>>>> VB_LO_SEL_3500MV },
>>>>> +};
>>>> The alignment here looks odd.
>>> I will fix it in the next version.
>>>
>>>>> static const struct regmap_irq rk808_irqs[] = {
>>>>> /* INT_STS */
>>>>> [RK808_IRQ_VOUT_LO] = {
>>>>> @@ -136,6 +169,76 @@ static const struct regmap_irq rk808_irqs[] = {
>>>>> },
>>>>> };
>>>>> +static const struct regmap_irq rk818_irqs[] = {
>>>>> + /* INT_STS */
>>>>> + [RK818_IRQ_VOUT_LO] = {
>>>>> + .mask = RK818_IRQ_VOUT_LO_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_VB_LO] = {
>>>>> + .mask = RK818_IRQ_VB_LO_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_PWRON] = {
>>>>> + .mask = RK818_IRQ_PWRON_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_PWRON_LP] = {
>>>>> + .mask = RK818_IRQ_PWRON_LP_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_HOTDIE] = {
>>>>> + .mask = RK818_IRQ_HOTDIE_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_RTC_ALARM] = {
>>>>> + .mask = RK818_IRQ_RTC_ALARM_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_RTC_PERIOD] = {
>>>>> + .mask = RK818_IRQ_RTC_PERIOD_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> + [RK818_IRQ_USB_OV] = {
>>>>> + .mask = RK818_IRQ_USB_OV_MSK,
>>>>> + .reg_offset = 0,
>>>>> + },
>>>>> +
>>>>> + /* INT_STS2 */
>>>>> + [RK818_IRQ_PLUG_IN] = {
>>>>> + .mask = RK818_IRQ_PLUG_IN_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_PLUG_OUT] = {
>>>>> + .mask = RK818_IRQ_PLUG_OUT_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_CHG_OK] = {
>>>>> + .mask = RK818_IRQ_CHG_OK_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_CHG_TE] = {
>>>>> + .mask = RK818_IRQ_CHG_TE_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_CHG_TS1] = {
>>>>> + .mask = RK818_IRQ_CHG_TS1_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_TS2] = {
>>>>> + .mask = RK818_IRQ_TS2_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_CHG_CVTLIM] = {
>>>>> + .mask = RK818_IRQ_CHG_CVTLIM_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> + [RK818_IRQ_DISCHG_ILIM] = {
>>>>> + .mask = RK818_IRQ_DISCHG_ILIM_MSK,
>>>>> + .reg_offset = 1,
>>>>> + },
>>>>> +};
>>>>> +
>>>>> static struct regmap_irq_chip rk808_irq_chip = {
>>>>> .name = "rk808",
>>>>> .irqs = rk808_irqs,
>>>>> @@ -148,6 +251,18 @@ static struct regmap_irq_chip rk808_irq_chip = {
>>>>> .init_ack_masked = true,
>>>>> };
>>>>> +static struct regmap_irq_chip rk818_irq_chip = {
>>>>> + .name = "rk818",
>>>>> + .irqs = rk818_irqs,
>>>>> + .num_irqs = ARRAY_SIZE(rk818_irqs),
>>>>> + .num_regs = 2,
>>>>> + .irq_reg_stride = 2,
>>>>> + .status_base = RK818_INT_STS_REG1,
>>>>> + .mask_base = RK818_INT_STS_MSK_REG1,
>>>>> + .ack_base = RK818_INT_STS_REG1,
>>>>> + .init_ack_masked = true,
>>>>> +};
>>>>> +
>>>>> static struct i2c_client *rk808_i2c_client;
>>>>> static void rk808_device_shutdown(void)
>>>>> {
>>>>> @@ -167,6 +282,48 @@ static void rk808_device_shutdown(void)
>>>>> dev_err(&rk808_i2c_client->dev, "power off error!\n");
>>>>> }
>>>>> +static const struct of_device_id rk808_of_match[] = {
>>>>> + { .compatible = "rockchip,rk808", .data = (void *) RK808_ID },
>>>>> + { .compatible = "rockchip,rk818", .data = (void *) RK818_ID },
>>>>> + { },
>>>>> +};
>>>>> +MODULE_DEVICE_TABLE(of, rk808_of_match);
>>>>> +
>>>>> +static int rk8xx_match_device(struct rk808 *rk808, struct device
>>>>> *dev)
>>>> If you're going to do it this way, please switch these parameters.
>>>>
>>>> It's more common to return the pointer however.
>>> If it's more common I will return a pointer to rk808.
>>>
>>>>> +{
>>>>> + const struct of_device_id *of_id;
>>>>> +
>>>>> + of_id = of_match_device(rk808_of_match, dev);
>>>>> + if (!of_id) {
>>>>> + dev_err(dev, "Unable to match OF ID\n");
>>>>> + return -ENODEV;
>>>>> + }
>>>>> + rk808->variant = (long) of_id->data;
>>>>> +
>>>>> + switch (rk808->variant) {
>>>>> + case RK808_ID:
>>>>> + rk808->nr_cells = ARRAY_SIZE(rk808s);
>>>>> + rk808->cells = rk808s;
>>>>> + rk808->regmap_cfg = &rk808_regmap_config;
>>>>> + rk808->regmap_irq_chip = &rk808_irq_chip;
>>>>> + rk808->pre_init_reg = rk808_pre_init_reg;
>>>>> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
>>>>> + break;
>>>>> + case RK818_ID:
>>>>> + rk808->nr_cells = ARRAY_SIZE(rk818s);
>>>>> + rk808->cells = rk818s;
>>>>> + rk808->regmap_cfg = &rk818_regmap_config;
>>>>> + rk808->regmap_irq_chip = &rk818_irq_chip;
>>>>> + rk808->pre_init_reg = rk818_pre_init_reg;
>>>>> + rk808->nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
>>>>> + break;
>>>>> + default:
>>>>> + dev_err(dev, "unsupported RK8XX ID %lu\n", rk808->variant);
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> static int rk808_probe(struct i2c_client *client,
>>>>> const struct i2c_device_id *id)
>>>>> {
>>>>> @@ -176,46 +333,52 @@ static int rk808_probe(struct i2c_client
>>>>> *client,
>>>>> int ret;
>>>>> int i;
>>>>> - if (!client->irq) {
>>>>> - dev_err(&client->dev, "No interrupt support, no core IRQ\n");
>>>>> - return -EINVAL;
>>>>> - }
>>>>> -
>>>>> rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
>>>>> if (!rk808)
>>>>> return -ENOMEM;
>>>>> - rk808->regmap = devm_regmap_init_i2c(client,
>>>>> &rk808_regmap_config);
>>>>> + ret = rk8xx_match_device(rk808, &client->dev);
>>>> Is there a way to dynamically probe the device? No device ID you can
>>>> read directly from the silicon?
>>> AFAIK there is no device ID register. At least it is not documented in
>>> the manual.
>> register 0x17 and 0x18 is the ID register, 0x17 is the MSB, 0x18 is LSB
>>
>> for RK818, register 0x17 is 0x81, 0x18 is 0x81
> thank you for sharing this information. I have no RK808 PMIC device
> here, so I would also need the IDs for RK808.
I have checked with the RK808 IC designer, the values of register
0x17 and 0x18 are both 0x00.
>
> Lee, you have already applied this series. But I can't find the patches
> in your kernel tree.
> I would like to read the device ID from the register in the probe function.
> Do you want me to base my changes on top of this series or send a new
> version?
>
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RESEND PATCH v5 1/5] mfd: RK808: Add RK818 support
2016-07-06 8:03 ` Wadim Egorov
2016-07-06 8:56 ` Andy Yan
@ 2016-08-05 12:22 ` Lee Jones
1 sibling, 0 replies; 16+ messages in thread
From: Lee Jones @ 2016-08-05 12:22 UTC (permalink / raw)
To: Wadim Egorov
Cc: Andy Yan, mark.rutland, devicetree, a.zummo, pawel.moll,
rtc-linux, ijc+devicetree, mturquette, sboyd, linux-kernel,
lgirdwood, linux-rockchip, robh+dt, alexandre.belloni, broonie,
dianders, galak, zyw, linux-clk
[...]
> Lee, you have already applied this series. But I can't find the patches
> in your kernel tree.
> I would like to read the device ID from the register in the probe function.
> Do you want me to base my changes on top of this series or send a new
> version?
Please rebase and resend the series.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 16+ messages in thread