aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2018-10-29 11:38:13 +0530
committerManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2018-12-04 00:04:04 +0530
commit6caf3632e3269bd454d5755afc22e995c6c6499a (patch)
treecfcfe2d32ef81a99ad3188c42193f849746a0945
parente0fe786d63629465a6bc1ae6aea1a48ae0f4145e (diff)
download96b-common-6caf3632e3269bd454d5755afc22e995c6c6499a.tar.gz
PMIC support for HiKey970
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts89
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3670.dtsi25
-rw-r--r--arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi59
-rw-r--r--drivers/mfd/hi6421-pmic-core.c12
-rw-r--r--drivers/regulator/Kconfig10
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/hi6421v600-regulator.c236
-rw-r--r--include/linux/mfd/hi6421-pmic.h1
8 files changed, 433 insertions, 0 deletions
diff --git a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
index c9775b66629f..c4e627a8fc1a 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
@@ -35,6 +35,76 @@
/* expect bootloader to fill in this region */
reg = <0x0 0x0 0x0 0x0>;
};
+
+ pmic: pmic@fff24000 {
+ compatible = "hisilicon,hi6421v600-pmic";
+ reg = <0x0 0xfff24000 0x0 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ regulators {
+ ldo3: LDO3 {
+ regulator-name = "VOUT3";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-enable-ramp-delay = <120>;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "VOUT4";
+ regulator-min-microvolt = <1725000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-enable-ramp-delay = <120>;
+ };
+
+ ldo9: LDO9 { /* SDCARD I/O */
+ regulator-name = "VOUT9";
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <360>;
+ };
+
+ ldo15: LDO15 {
+ regulator-name = "VOUT15";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <120>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo16: LDO16 { /* SD VDD */
+ regulator-name = "VOUT16";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <360>;
+ };
+
+ ldo17: LDO17 {
+ regulator-name = "VOUT17";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <120>;
+ };
+
+ ldo33: LDO33 {
+ regulator-name = "VOUT33";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <120>;
+ };
+
+ ldo34: LDO34 {
+ regulator-name = "VOUT34";
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <120>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+
};
/*
@@ -354,6 +424,25 @@
"GPIO_231_HDMI_INT";
};
+&dwmmc1 {
+ bus-width = <0x4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ disable-wp;
+ cd-inverted;
+ cd-gpios = <&gpio25 5 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_pmx_func
+ &sd_clk_cfg_func
+ &sd_cfg_func>;
+ vmmc-supply = <&ldo16>;
+ vqmmc-supply = <&ldo9>;
+ status = "okay";
+};
+
&uart0 {
/* On High speed expansion header */
label = "HS-UART0";
diff --git a/arch/arm64/boot/dts/hisilicon/hi3670.dtsi b/arch/arm64/boot/dts/hisilicon/hi3670.dtsi
index a5bd6d80b226..d08b5403722b 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3670.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3670.dtsi
@@ -151,6 +151,12 @@
#clock-cells = <1>;
};
+ crg_rst: crg_rst_controller {
+ compatible = "hisilicon,hi3660-reset";
+ #reset-cells = <2>;
+ hisi,rst-syscon = <&crg_ctrl>;
+ };
+
pctrl: pctrl@e8a09000 {
compatible = "hisilicon,hi3670-pctrl", "syscon";
reg = <0x0 0xe8a09000 0x0 0x1000>;
@@ -647,5 +653,24 @@
clocks = <&sctrl HI3670_PCLK_AO_GPIO6>;
clock-names = "apb_pclk";
};
+
+ /* SD */
+ dwmmc1: dwmmc1@ff37f000 {
+ compatible = "hisilicon,hi3660-dw-mshc";
+ reg = <0x0 0xff37f000 0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg_ctrl HI3670_CLK_GATE_SD>,
+ <&crg_ctrl HI3670_HCLK_GATE_SD>;
+ clock-names = "ciu", "biu";
+ clock-frequency = <3200000>;
+ resets = <&crg_rst 0x94 18>;
+ reset-names = "reset";
+ hisilicon,peripheral-syscon = <&sctrl>;
+ card-detect-delay = <200>;
+ status = "disabled";
+ };
+
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi
index 67bb52d43619..e20e5c829178 100644
--- a/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi
@@ -214,6 +214,17 @@
pinctrl-single,function-mask = <7>;
/* pin base, nr pins & gpio function */
pinctrl-single,gpio-range = <&range 0 12 0>;
+
+ sd_pmx_func: sd_pmx_func {
+ pinctrl-single,pins = <
+ 0x000 MUX_M1 /* SD_CLK */
+ 0x004 MUX_M1 /* SD_CMD */
+ 0x008 MUX_M1 /* SD_DATA0 */
+ 0x00c MUX_M1 /* SD_DATA1 */
+ 0x010 MUX_M1 /* SD_DATA2 */
+ 0x014 MUX_M1 /* SD_DATA3 */
+ >;
+ };
};
pmx8: pinmux@ff37e800 {
@@ -221,6 +232,54 @@
reg = <0x0 0xff37e800 0x0 0x030>;
#pinctrl-cells = <1>;
pinctrl-single,register-width = <0x20>;
+
+ sd_clk_cfg_func: sd_clk_cfg_func {
+ pinctrl-single,pins = <
+ 0x000 0x0 /* SD_CLK */
+ >;
+ pinctrl-single,bias-pulldown = <
+ PULL_DIS
+ PULL_DOWN
+ PULL_DIS
+ PULL_DOWN
+ >;
+ pinctrl-single,bias-pullup = <
+ PULL_DIS
+ PULL_UP
+ PULL_DIS
+ PULL_UP
+ >;
+ pinctrl-single,drive-strength = <
+ DRIVE6_32MA
+ DRIVE6_MASK
+ >;
+ };
+
+ sd_cfg_func: sd_cfg_func {
+ pinctrl-single,pins = <
+ 0x004 0x0 /* SD_CMD */
+ 0x008 0x0 /* SD_DATA0 */
+ 0x00c 0x0 /* SD_DATA1 */
+ 0x010 0x0 /* SD_DATA2 */
+ 0x014 0x0 /* SD_DATA3 */
+ >;
+ pinctrl-single,bias-pulldown = <
+ PULL_DIS
+ PULL_DOWN
+ PULL_DIS
+ PULL_DOWN
+ >;
+ pinctrl-single,bias-pullup = <
+ PULL_UP
+ PULL_UP
+ PULL_DIS
+ PULL_UP
+ >;
+ pinctrl-single,drive-strength = <
+ DRIVE6_19MA
+ DRIVE6_MASK
+ >;
+ };
};
pmx1: pinmux@fff11000 {
diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c
index 6fb7ba272e09..92fbedb975f8 100644
--- a/drivers/mfd/hi6421-pmic-core.c
+++ b/drivers/mfd/hi6421-pmic-core.c
@@ -30,6 +30,10 @@ static const struct mfd_cell hi6421v530_devs[] = {
{ .name = "hi6421v530-regulator", },
};
+static const struct mfd_cell hi6421v600_devs[] = {
+ { .name = "hi6421v600-regulator", },
+};
+
static const struct regmap_config hi6421_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -46,6 +50,10 @@ static const struct of_device_id of_hi6421_pmic_match[] = {
.compatible = "hisilicon,hi6421v530-pmic",
.data = (void *)HI6421_V530
},
+ {
+ .compatible = "hisilicon,hi6421v600-pmic",
+ .data = (void *)HI6421_V600
+ },
{ },
};
MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match);
@@ -101,6 +109,10 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
subdevs = hi6421v530_devs;
n_subdevs = ARRAY_SIZE(hi6421v530_devs);
break;
+ case HI6421_V600:
+ subdevs = hi6421v600_devs;
+ n_subdevs = ARRAY_SIZE(hi6421v600_devs);
+ break;
default:
dev_err(&pdev->dev, "Unknown device type %d\n",
(unsigned int)type);
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 926cee0d0b5f..639bab02262b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -326,6 +326,16 @@ config REGULATOR_HI6421V530
provides 5 general purpose LDOs, and all of them come with support
to either ECO (idle) or sleep mode.
+config REGULATOR_HI6421V600
+ tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
+ depends on MFD_HI6421_PMIC && OF
+ help
+ This driver provides support for the voltage regulators on
+ HiSilicon Hi6421v600 PMU / Codec IC.
+ Hi6421v600 is a multi-function device which, on regulator part,
+ provides 8 general purpose LDOs, and all of them come with support
+ to either ECO (idle) or sleep mode.
+
config REGULATOR_HI655X
tristate "Hisilicon HI655X PMIC regulators support"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 72488ef11b8a..60458122dd5e 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
+obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
diff --git a/drivers/regulator/hi6421v600-regulator.c b/drivers/regulator/hi6421v600-regulator.c
new file mode 100644
index 000000000000..f476f52710ce
--- /dev/null
+++ b/drivers/regulator/hi6421v600-regulator.c
@@ -0,0 +1,236 @@
+/*
+ * Device driver for regulators in Hi6421V600 IC
+ *
+ * Copyright (c) 2017 HiSilicon Technologies Co., Ltd.
+ * http://www.hisilicon.com
+ * Copyright (c) 2018 Linaro Ltd.
+ * http://www.linaro.org
+ *
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mfd/hi6421-pmic.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+/*
+ * struct hi6421v600_regulator_info - hi6421v600 regulator information
+ * @desc: regulator description
+ * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
+ * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
+ */
+struct hi6421v600_regulator_info {
+ struct regulator_desc rdesc;
+ u8 mode_mask;
+ u32 eco_microamp;
+};
+
+/* HI6421v600 regulators */
+enum hi6421v600_regulator_id {
+ HI6421V600_LDO3,
+ HI6421V600_LDO4,
+ HI6421V600_LDO9,
+ HI6421V600_LDO15,
+ HI6421V600_LDO16,
+ HI6421V600_LDO17,
+ HI6421V600_LDO33,
+ HI6421V600_LDO34,
+};
+
+static const unsigned int ldo_3_voltages[] = {
+ 1500000, 1550000, 1600000, 1650000,
+ 1700000, 1725000, 1750000, 1775000,
+ 1800000, 1825000, 1850000, 1875000,
+ 1900000, 1925000, 1950000, 2000000,
+};
+
+static const unsigned int ldo_4_voltages[] = {
+ 1725000, 1750000, 1775000, 1800000,
+ 1825000, 1850000, 1875000, 1900000,
+};
+
+static const unsigned int ldo_9_voltages[] = {
+ 1750000, 1800000, 1825000, 2800000,
+ 2850000, 2950000, 3000000, 3300000,
+};
+
+static const unsigned int ldo_15_16_voltages[] = {
+ 1800000, 1850000, 2400000, 2600000,
+ 2700000, 2850000, 2950000, 3000000,
+};
+
+static const unsigned int ldo_17_33_voltages[] = {
+ 2500000, 2600000, 2700000, 2800000,
+ 3000000, 3100000, 3200000, 3300000,
+};
+
+static const unsigned int ldo_34_voltages[] = {
+ 2600000, 2700000, 2800000, 2900000,
+ 3000000, 3100000, 3200000, 3300000,
+};
+
+static const struct regulator_ops hi6421v600_ldo_ops;
+
+/*
+ * _id - LDO id name string
+ * v_table - voltage table
+ * vreg - voltage select register
+ * vmask - voltage select mask
+ * ereg - enable register
+ * emask - enable mask
+ * odelay - off/on delay time in uS
+ * ecomask - eco mode mask
+ * ecoamp - eco mode load uppler limit in uA
+ */
+#define HI6421V600_LDO(_ID, v_table, vreg, vmask, ereg, emask, \
+ odelay, ecomask, ecoamp, etime) { \
+ .rdesc = { \
+ .name = #_ID, \
+ .of_match = of_match_ptr(#_ID), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .ops = &hi6421v600_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = HI6421V600_##_ID, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(v_table), \
+ .volt_table = v_table, \
+ .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
+ .vsel_mask = vmask, \
+ .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
+ .enable_mask = emask, \
+ .enable_time = etime, \
+ .off_on_delay = odelay, \
+ }, \
+ .mode_mask = ecomask, \
+ .eco_microamp = ecoamp, \
+}
+
+/* HI6421V600 regulator information */
+
+static struct hi6421v600_regulator_info hi6421v600_regulator_info[] = {
+ HI6421V600_LDO(LDO3, ldo_3_voltages, 0x051, 0xf, 0x016, 0x1,
+ 20000, 0x2, 10000, 120),
+ HI6421V600_LDO(LDO4, ldo_4_voltages, 0x052, 0x7, 0x017, 0x1,
+ 20000, 0x6, 10000, 120),
+ HI6421V600_LDO(LDO9, ldo_9_voltages, 0x057, 0x7, 0x01C, 0x1,
+ 20000, 0x06, 10000, 360),
+ HI6421V600_LDO(LDO15, ldo_15_16_voltages, 0x05C, 0x07, 0x021, 0x01,
+ 20000, 0x06, 10000, 120),
+ HI6421V600_LDO(LDO16, ldo_15_16_voltages, 0x05D, 0x07, 0x022, 0x01,
+ 20000, 0x06, 10000, 360),
+ HI6421V600_LDO(LDO17, ldo_17_33_voltages, 0x05E, 0x07, 0x023, 0x01,
+ 20000, 0x06, 10000, 120),
+ HI6421V600_LDO(LDO33, ldo_17_33_voltages, 0x06D, 0x07, 0x032, 0x01,
+ 20000, 0x02, 10000, 120),
+ HI6421V600_LDO(LDO34, ldo_34_voltages, 0x06E, 0x07, 0x033, 0x01,
+ 20000, 0x02, 10000, 120),
+};
+
+static unsigned int hi6421v600_regulator_ldo_get_mode(
+ struct regulator_dev *rdev)
+{
+ struct hi6421v600_regulator_info *info;
+ unsigned int reg_val;
+
+ info = rdev_get_drvdata(rdev);
+ regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
+
+ if (reg_val & (info->mode_mask))
+ return REGULATOR_MODE_IDLE;
+
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int hi6421v600_regulator_ldo_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct hi6421v600_regulator_info *info;
+ unsigned int new_mode;
+
+ info = rdev_get_drvdata(rdev);
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ new_mode = 0;
+ break;
+ case REGULATOR_MODE_IDLE:
+ new_mode = info->mode_mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ info->mode_mask, new_mode);
+
+ return 0;
+}
+
+
+static const struct regulator_ops hi6421v600_ldo_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_mode = hi6421v600_regulator_ldo_get_mode,
+ .set_mode = hi6421v600_regulator_ldo_set_mode,
+};
+
+static int hi6421v600_regulator_probe(struct platform_device *pdev)
+{
+ struct hi6421_pmic *pmic;
+ struct regulator_dev *rdev;
+ struct regulator_config config = { };
+ unsigned int i;
+
+ pmic = dev_get_drvdata(pdev->dev.parent);
+ if (!pmic) {
+ dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hi6421v600_regulator_info); i++) {
+ config.dev = pdev->dev.parent;
+ config.regmap = pmic->regmap;
+ config.driver_data = &hi6421v600_regulator_info[i];
+
+ pr_info("Registering regulator %s\n", hi6421v600_regulator_info[i].rdesc.name);
+ rdev = devm_regulator_register(&pdev->dev,
+ &hi6421v600_regulator_info[i].rdesc,
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ hi6421v600_regulator_info[i].rdesc.name);
+ return PTR_ERR(rdev);
+ }
+ }
+ return 0;
+}
+
+static const struct platform_device_id hi6421v600_regulator_table[] = {
+ { .name = "hi6421v600-regulator" },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, hi6421v600_regulator_table);
+
+static struct platform_driver hi6421v600_regulator_driver = {
+ .id_table = hi6421v600_regulator_table,
+ .driver = {
+ .name = "hi6421v600-regulator",
+ },
+ .probe = hi6421v600_regulator_probe,
+};
+module_platform_driver(hi6421v600_regulator_driver);
+
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_DESCRIPTION("Hi6421v600 regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/hi6421-pmic.h b/include/linux/mfd/hi6421-pmic.h
index 2580c08db7b1..51126ba4064d 100644
--- a/include/linux/mfd/hi6421-pmic.h
+++ b/include/linux/mfd/hi6421-pmic.h
@@ -41,6 +41,7 @@ struct hi6421_pmic {
enum hi6421_type {
HI6421 = 0,
HI6421_V530,
+ HI6421_V600,
};
#endif /* __HI6421_PMIC_H */