LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* MediaTek PMIC support
@ 2015-01-20 9:47 Sascha Hauer
2015-01-20 9:47 ` [PATCH 1/8] soc: Add MediaTek infracfg controller support Sascha Hauer
` (7 more replies)
0 siblings, 8 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown
This series adds initial support for the MediaTek MT6397 PMIC and the
necessary infrastructure to attach it on the MT8135 / MT8173 SoCs.
The infrastructure includes:
- pericfg / infracfg controller support
The pericfg / infracfg controllers contain miscellaneous registers for
reset controllers and clocks.
- PMIC wrapper support
On MediaTek MT8135, MT8173 and other SoCs the PMIC is connected via
SPI. The SPI master interface is not directly visible to the CPU, but
only through the PMIC wrapper inside the SoC. The communication between
the SoC and the PMIC can optionally be encrypted. Also a non standard
Dual IO SPI mode can be used to increase speed. The MT8135 also supports
a special feature named "IP Pairing". With IP Pairing the pins of some
SoC internal peripherals can be on the PMIC. The signals of these pins
are routed over the SPI bus using the pwrap bridge. Because of these
optional non SPI conform features the PMIC driver is not implemented as
a SPI bus master driver.
The MT6397 PMIC itself is implemented as a regular mfd device driver which
uses regmap to access the PMIC registers.
This series also adds regulator support for the MT6397 PMIC.
The first 6 patches can be merged through the ARM SoC tree. The mfd/regulator
patches are independent of the first 6 patches and can be merged through the
mfd/regulator maintainer trees.
Sascha
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/8] soc: Add MediaTek infracfg controller support
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 16:14 ` Mark Rutland
2015-01-20 9:47 ` [PATCH 2/8] soc: Add MediaTek pericfg " Sascha Hauer
` (6 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown,
Sascha Hauer
This adds support for the MediaTek infracfg controller found
on the MT8135/MT8173 SoCs. The infracfg controller contains
miscellaneous registers for controlling peripheral resets and
clocks.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
.../devicetree/bindings/soc/mediatek/infracfg.txt | 19 +++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/mediatek/Kconfig | 12 ++
drivers/soc/mediatek/Makefile | 1 +
drivers/soc/mediatek/mtk-infracfg.c | 127 ++++++++++++++++++++
drivers/soc/mediatek/mtk-pericfg.c | 128 +++++++++++++++++++++
7 files changed, 289 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
create mode 100644 drivers/soc/mediatek/Kconfig
create mode 100644 drivers/soc/mediatek/Makefile
create mode 100644 drivers/soc/mediatek/mtk-infracfg.c
create mode 100644 drivers/soc/mediatek/mtk-pericfg.c
diff --git a/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
new file mode 100644
index 0000000..042083a
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
@@ -0,0 +1,19 @@
+MediaTek infracfg Controller
+
+The infracfg controller contains miscellaneous registers for controlling
+clocks, resets and bus settings.
+
+Required properties:
+- compatible: must be one of:
+ mediatek,mt8135-infracfg
+ mediatek,mt8173-infracfg
+- reg: Address range for the infracfg controller
+
+Example:
+
+ infracfg: infracfg@10003000 {
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ compatible = "mediatek,mt8135-infracfg";
+ reg = <0 0x10003000 0 0x1000>;
+ };
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 76d6bd4..d8bde82f0 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,5 +1,6 @@
menu "SOC (System On Chip) specific Drivers"
+source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/ti/Kconfig"
source "drivers/soc/versatile/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 063113d..70042b2 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
# Makefile for the Linux Kernel SOC specific device drivers.
#
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
new file mode 100644
index 0000000..3ad39fe
--- /dev/null
+++ b/drivers/soc/mediatek/Kconfig
@@ -0,0 +1,12 @@
+#
+# MediaTek SoC drivers
+#
+config MTK_INFRACFG
+ tristate "MediaTek infracfg controller support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select REGMAP
+ help
+ The MediaTek infracfg controller found on MT8135 and MT8173 SoCs
+ contains several miscellaneous registers for clock, reset and bus
+ settings. Say yes here if you want to run your kernel on one of these
+ SoCs.
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
new file mode 100644
index 0000000..dbeb627
--- /dev/null
+++ b/drivers/soc/mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
new file mode 100644
index 0000000..3bbd39b
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-infracfg.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+struct mtk_infracfg {
+ struct regmap *regmap;
+ struct reset_controller_dev rcdev;
+};
+
+static int mtk_infracfg_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtk_infracfg *data = container_of(rcdev, struct mtk_infracfg, rcdev);
+
+ return regmap_update_bits(data->regmap, 0x30 + ((id / 32) << 2), BIT(id % 32), ~0u);
+}
+
+static int mtk_infracfg_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtk_infracfg *data = container_of(rcdev, struct mtk_infracfg, rcdev);
+
+ return regmap_update_bits(data->regmap, 0x30 + ((id / 32) << 2), BIT(id % 32), 0);
+}
+
+static int mtk_infracfg_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = mtk_infracfg_reset_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return mtk_infracfg_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_infracfg_reset_ops = {
+ .assert = mtk_infracfg_reset_assert,
+ .deassert = mtk_infracfg_reset_deassert,
+ .reset = mtk_infracfg_reset,
+};
+
+static struct regmap_config mtk_infracfg_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int mtk_infracfg_probe(struct platform_device *pdev)
+{
+ struct mtk_infracfg *data;
+ struct resource *res;
+ void __iomem *base;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ data->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &mtk_infracfg_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = 64;
+ data->rcdev.ops = &mtk_infracfg_reset_ops;
+ data->rcdev.of_node = pdev->dev.of_node;
+
+ return reset_controller_register(&data->rcdev);
+}
+
+static int mtk_infracfg_remove(struct platform_device *pdev)
+{
+ struct mtk_infracfg *data = platform_get_drvdata(pdev);
+
+ reset_controller_unregister(&data->rcdev);
+
+ return 0;
+}
+
+static const struct of_device_id mtk_infracfg_dt_ids[] = {
+ {
+ .compatible = "mediatek,mt8173-infracfg",
+ }, {
+ .compatible = "mediatek,mt8135-infracfg",
+ }, {
+ /* sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, mtk_infracfg_dt_ids);
+
+static struct platform_driver mtk_infracfg_driver = {
+ .probe = mtk_infracfg_probe,
+ .remove = mtk_infracfg_remove,
+ .driver = {
+ .name = "mtk-infracfg",
+ .of_match_table = mtk_infracfg_dt_ids,
+ },
+};
+
+module_platform_driver(mtk_infracfg_driver);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("MediaTek infracfg controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/mediatek/mtk-pericfg.c b/drivers/soc/mediatek/mtk-pericfg.c
new file mode 100644
index 0000000..b7ee902
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pericfg.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu <flora.fu@mediatek.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+struct mtk_pericfg {
+ struct regmap *regmap;
+ struct reset_controller_dev rcdev;
+};
+
+static int mtk_pericfg_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtk_pericfg *data = container_of(rcdev, struct mtk_pericfg, rcdev);
+
+ return regmap_update_bits(data->regmap, (id / 32) << 2, BIT(id % 32), ~0);
+}
+
+static int mtk_pericfg_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtk_pericfg *data = container_of(rcdev, struct mtk_pericfg, rcdev);
+
+ return regmap_update_bits(data->regmap, (id / 32) << 2, BIT(id % 32), 0);
+}
+
+static int mtk_pericfg_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = mtk_pericfg_reset_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return mtk_pericfg_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_pericfg_reset_ops = {
+ .assert = mtk_pericfg_reset_assert,
+ .deassert = mtk_pericfg_reset_deassert,
+ .reset = mtk_pericfg_reset,
+};
+
+static struct regmap_config mtk_pericfg_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int mtk_pericfg_probe(struct platform_device *pdev)
+{
+ struct mtk_pericfg *data;
+ struct resource *res;
+ void __iomem *base;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ data->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &mtk_pericfg_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = 64;
+ data->rcdev.ops = &mtk_pericfg_reset_ops;
+ data->rcdev.of_node = pdev->dev.of_node;
+
+ return reset_controller_register(&data->rcdev);
+}
+
+static int mtk_pericfg_remove(struct platform_device *pdev)
+{
+ struct mtk_pericfg *data = platform_get_drvdata(pdev);
+
+ reset_controller_unregister(&data->rcdev);
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pericfg_dt_ids[] = {
+ {
+ .compatible = "mediatek,mt8173-pericfg",
+ }, {
+ .compatible = "mediatek,mt8135-pericfg",
+ }, {
+ /* sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, mtk_pericfg_dt_ids);
+
+static struct platform_driver mtk_pericfg_driver = {
+ .probe = mtk_pericfg_probe,
+ .remove = mtk_pericfg_remove,
+ .driver = {
+ .name = "mtk-pericfg",
+ .of_match_table = mtk_pericfg_dt_ids,
+ },
+};
+
+module_platform_driver(mtk_pericfg_driver);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("MediaTek pericfg controller");
+MODULE_LICENSE("GPL");
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/8] soc: Add MediaTek pericfg controller support
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
2015-01-20 9:47 ` [PATCH 1/8] soc: Add MediaTek infracfg controller support Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 13:18 ` Yingjoe Chen
2015-01-20 16:15 ` Mark Rutland
2015-01-20 9:47 ` [PATCH 3/8] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines Sascha Hauer
` (5 subsequent siblings)
7 siblings, 2 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown,
Sascha Hauer
This adds support for the MediaTek pericfg controller found
on the MT8135/MT8173 SoCs. The pericfg controller contains
miscellaneous registers for controlling peripheral resets and
clocks.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
.../devicetree/bindings/soc/mediatek/pericfg.txt | 19 +++++++++++++++++++
drivers/soc/mediatek/Kconfig | 10 ++++++++++
drivers/soc/mediatek/Makefile | 1 +
drivers/soc/mediatek/mtk-pericfg.c | 1 -
4 files changed, 30 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
diff --git a/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
new file mode 100644
index 0000000..81d1aee
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
@@ -0,0 +1,19 @@
+MediaTek pericfg Controller
+
+The pericfg controller contains miscellaneous registers for controlling
+clocks, resets and bus settings.
+
+Required properties:
+- compatible: must be one of:
+ mediatek,mt8135-pericfg
+ mediatek,mt8173-pericfg
+- reg: Address range for the pericfg controller
+
+Example:
+
+ pericfg: pericfg@10003000 {
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ compatible = "mediatek,mt8135-pericfg";
+ reg = <0 0x10003000 0 0x1000>;
+ };
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 3ad39fe..9bdb88f 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -10,3 +10,13 @@ config MTK_INFRACFG
contains several miscellaneous registers for clock, reset and bus
settings. Say yes here if you want to run your kernel on one of these
SoCs.
+
+config MTK_PERICFG
+ tristate "MediaTek pericfg controller support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select REGMAP
+ help
+ The MediaTek pericfg controller found on MT8135 and MT8173 SoCs
+ contains several miscellaneous registers for clock, reset and bus
+ settings. Say yes here if you want to run your kernel on one of these
+ SoCs.
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index dbeb627..e67be7c 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+obj-$(CONFIG_MTK_PERICFG) += mtk-pericfg.o
diff --git a/drivers/soc/mediatek/mtk-pericfg.c b/drivers/soc/mediatek/mtk-pericfg.c
index b7ee902..aa9a7eb 100644
--- a/drivers/soc/mediatek/mtk-pericfg.c
+++ b/drivers/soc/mediatek/mtk-pericfg.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2014 MediaTek Inc.
- * Author: Flora Fu <flora.fu@mediatek.com>
*
* 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
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/8] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
2015-01-20 9:47 ` [PATCH 1/8] soc: Add MediaTek infracfg controller support Sascha Hauer
2015-01-20 9:47 ` [PATCH 2/8] soc: Add MediaTek pericfg " Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 4/8] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC Sascha Hauer
` (4 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown,
Sascha Hauer
This adds the reset defines for the MT8135/MT8173 pericfg and infracfg
controllers. Needed for device trees to specify the reset numbers in
pericfg / infracfg reset consumers
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
.../dt-bindings/reset-controller/mt8135-resets.h | 64 ++++++++++++++++++++++
.../dt-bindings/reset-controller/mt8173-resets.h | 63 +++++++++++++++++++++
2 files changed, 127 insertions(+)
create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h
create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h
diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
new file mode 100644
index 0000000..b9add04
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
+
+/* INFRACFG resets */
+#define MT8135_INFRA_EMI_REG_RST 0
+#define MT8135_INFRA_DRAMC0_A0_RST 1
+#define MT8135_INFRA_CCIF0_RST 2
+#define MT8135_INFRA_APCIRQ_EINT_RST 3
+#define MT8135_INFRA_APXGPT_RST 4
+#define MT8135_INFRA_SCPSYS_RST 5
+#define MT8135_INFRA_CCIF1_RST 6
+#define MT8135_INFRA_PMIC_WRAP_RST 7
+#define MT8135_INFRA_KP_RST 8
+#define MT8135_INFRA_EMI_RST 32
+#define MT8135_INFRA_DRAMC0_RST 34
+#define MT8135_INFRA_SMI_RST 35
+#define MT8135_INFRA_M4U_RST 36
+
+/* PERICFG resets */
+#define MT8135_PERI_UART0_SW_RST 0
+#define MT8135_PERI_UART1_SW_RST 1
+#define MT8135_PERI_UART2_SW_RST 2
+#define MT8135_PERI_UART3_SW_RST 3
+#define MT8135_PERI_IRDA_SW_RST 4
+#define MT8135_PERI_PTP_SW_RST 5
+#define MT8135_PERI_AP_HIF_SW_RST 6
+#define MT8135_PERI_GPCU_SW_RST 7
+#define MT8135_PERI_MD_HIF_SW_RST 8
+#define MT8135_PERI_NLI_SW_RST 9
+#define MT8135_PERI_AUXADC_SW_RST 10
+#define MT8135_PERI_DMA_SW_RST 11
+#define MT8135_PERI_NFI_SW_RST 14
+#define MT8135_PERI_PWM_SW_RST 15
+#define MT8135_PERI_THERM_SW_RST 16
+#define MT8135_PERI_MSDC0_SW_RST 17
+#define MT8135_PERI_MSDC1_SW_RST 18
+#define MT8135_PERI_MSDC2_SW_RST 19
+#define MT8135_PERI_MSDC3_SW_RST 20
+#define MT8135_PERI_I2C0_SW_RST 22
+#define MT8135_PERI_I2C1_SW_RST 23
+#define MT8135_PERI_I2C2_SW_RST 24
+#define MT8135_PERI_I2C3_SW_RST 25
+#define MT8135_PERI_I2C4_SW_RST 26
+#define MT8135_PERI_I2C5_SW_RST 27
+#define MT8135_PERI_I2C6_SW_RST 28
+#define MT8135_PERI_USB_SW_RST 29
+#define MT8135_PERI_SPI1_SW_RST 33
+#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
new file mode 100644
index 0000000..7648ed5
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
+
+/* INFRACFG resets */
+#define MT8173_INFRA_EMI_REG_RST 0
+#define MT8173_INFRA_DRAMC0_A0_RST 1
+#define MT8173_INFRA_APCIRQ_EINT_RST 3
+#define MT8173_INFRA_APXGPT_RST 4
+#define MT8173_INFRA_SCPSYS_RST 5
+#define MT8173_INFRA_KP_RST 6
+#define MT8173_INFRA_PMIC_WRAP_RST 7
+#define MT8173_INFRA_MPIP_RST 8
+#define MT8173_INFRA_CEC_RST 9
+#define MT8173_INFRA_EMI_RST 32
+#define MT8173_INFRA_DRAMC0_RST 34
+#define MT8173_INFRA_APMIXEDSYS_RST 35
+#define MT8173_INFRA_MIPI_DSI_RST 36
+#define MT8173_INFRA_TRNG_RST 37
+#define MT8173_INFRA_SYSIRQ_RST 38
+#define MT8173_INFRA_MIPI_CSI_RST 39
+#define MT8173_INFRA_GCE_FAXI_RST 40
+#define MT8173_INFRA_MMIOMMURST 47
+
+
+/* PERICFG resets */
+#define MT8173_PERI_UART0_SW_RST 0
+#define MT8173_PERI_UART1_SW_RST 1
+#define MT8173_PERI_UART2_SW_RST 2
+#define MT8173_PERI_UART3_SW_RST 3
+#define MT8173_PERI_IRRX_SW_RST 4
+#define MT8173_PERI_PWM_SW_RST 8
+#define MT8173_PERI_AUXADC_SW_RST 10
+#define MT8173_PERI_DMA_SW_RST 11
+#define MT8173_PERI_I2C6_SW_RST 13
+#define MT8173_PERI_NFI_SW_RST 14
+#define MT8173_PERI_THERM_SW_RST 16
+#define MT8173_PERI_MSDC2_SW_RST 17
+#define MT8173_PERI_MSDC3_SW_RST 18
+#define MT8173_PERI_MSDC0_SW_RST 19
+#define MT8173_PERI_MSDC1_SW_RST 20
+#define MT8173_PERI_I2C0_SW_RST 22
+#define MT8173_PERI_I2C1_SW_RST 23
+#define MT8173_PERI_I2C2_SW_RST 24
+#define MT8173_PERI_I2C3_SW_RST 25
+#define MT8173_PERI_I2C4_SW_RST 26
+#define MT8173_PERI_HDMI_SW_RST 29
+#define MT8173_PERI_SPI0_SW_RST 33
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 4/8] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
` (2 preceding siblings ...)
2015-01-20 9:47 ` [PATCH 3/8] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 5/8] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes Sascha Hauer
` (3 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown, Flora Fu,
Sascha Hauer
From: Flora Fu <flora.fu@mediatek.com>
This adds support for the PMIC wrapper found on MediaTek MT8135 and
MT8173 SoCs.
On MediaTek MT8135, MT8173 and other SoCs the PMIC is connected via
SPI. The SPI master interface is not directly visible to the CPU, but
only through the PMIC wrapper inside the SoC. The communication between
the SoC and the PMIC can optionally be encrypted. Also a non standard
Dual IO SPI mode can be used to increase speed. The MT8135 also supports
a special feature named "IP Pairing". With IP Pairing the pins of some
SoC internal peripherals can be on the PMIC. The signals of these pins
are routed over the SPI bus using the pwrap bridge. Because of these
optional non SPI conform features the PMIC driver is not implemented as
a SPI bus master driver.
Signed-off-by: Flora Fu, MediaTek
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
.../devicetree/bindings/soc/mediatek/pwrap.txt | 56 ++
drivers/soc/mediatek/Kconfig | 9 +
drivers/soc/mediatek/Makefile | 1 +
drivers/soc/mediatek/mtk-pmic-wrap.c | 1025 ++++++++++++++++++++
4 files changed, 1091 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
create mode 100644 drivers/soc/mediatek/mtk-pmic-wrap.c
diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
new file mode 100644
index 0000000..66cc528
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
@@ -0,0 +1,56 @@
+MediaTek PMIC Wrapper Driver
+
+This document describes the binding for the MediaTek PMIC wrapper.
+
+On MediaTek MT8135, MT8173 and other SoCs the PMIC is connected via
+SPI. The SPI master interface is not directly visible to the CPU, but
+only through the PMIC wrapper inside the SoC. The communication between
+the SoC and the PMIC can optionally be encrypted. Also a non standard
+Dual IO SPI mode can be used to increase speed.
+
+IP Pairing
+
+on MT8135 the pins of some SoC internal peripherals can be on the PMIC.
+The signals of these pins are routed over the SPI bus using the pwrap
+bridge. In the binding description below the properties needed for bridging
+are marked with "IP Pairing". These are optional on SoCs which do not support
+IP Pairing
+
+Required properties in pwrap device node.
+- compatible: "mediatek,mt8135-pwrap" or "mediatek,mt8173-pwrap"
+- interrupts: IRQ for pwrap in SOC
+- reg-names: Must include the following entries:
+ "pwrap": Main registers base
+ "pwrap-bridge": bridge base (IP Pairing)
+- reg: Must contain an entry for each entry in reg-names.
+- reset-names: Must include the following entries:
+ "pwrap"
+ "pwrap-bridge" (IP Pairing)
+- resets: Must contain an entry for each entry in reset-names.
+- clock-names: Must include the following entries:
+ "spi": SPI bus clock
+ "wrap": Main module clock
+- clocks: Must contain an entry for each entry in clock-names.
+
+Optional properities:
+- pmic: Mediatek PMIC MFD is the child device of pwrap
+ See the following for child node definitions:
+ Documentation/devicetree/bindings/mfd/mt6397.txt
+
+Example:
+ pwrap: pwrap@1000f000 {
+ compatible = "mediatek,mt8135-pwrap";
+ reg = <0 0x1000f000 0 0x1000>,
+ <0 0x11017000 0 0x1000>;
+ reg-names = "pwrap", "pwrap-bridge";
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>,
+ <&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
+ reset-names = "pwrap", "pwrap-bridge";
+ clocks = <&clk26m>, <&clk26m>;
+ clock-names = "spi", "wrap";
+
+ pmic {
+ compatible = "mediatek,mt6397";
+ };
+ };
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 9bdb88f..a50f263 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -20,3 +20,12 @@ config MTK_PERICFG
contains several miscellaneous registers for clock, reset and bus
settings. Say yes here if you want to run your kernel on one of these
SoCs.
+
+config MTK_PMIC_WRAP
+ tristate "MediaTek PMIC Wrapper Support"
+ depends on ARCH_MEDIATEK
+ select REGMAP
+ help
+ Say yes here to add support for MediaTek PMIC Wrapper found
+ on the MT8135 and MT8173 SoCs. The PMIC wrapper is a proprietary
+ hardware to connect the PMIC.
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index e67be7c..a6caa32 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
obj-$(CONFIG_MTK_PERICFG) += mtk-pericfg.o
+obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
new file mode 100644
index 0000000..4989b0f
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -0,0 +1,1025 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#define DEBUG
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define PWRAP_MT8135_BRIDGE_IORD_ARB_EN 0x4
+#define PWRAP_MT8135_BRIDGE_WACS3_EN 0x10
+#define PWRAP_MT8135_BRIDGE_INIT_DONE3 0x14
+#define PWRAP_MT8135_BRIDGE_WACS4_EN 0x24
+#define PWRAP_MT8135_BRIDGE_INIT_DONE4 0x28
+#define PWRAP_MT8135_BRIDGE_INT_EN 0x38
+#define PWRAP_MT8135_BRIDGE_TIMER_EN 0x48
+#define PWRAP_MT8135_BRIDGE_WDT_UNIT 0x50
+#define PWRAP_MT8135_BRIDGE_WDT_SRC_EN 0x54
+
+/* macro for wrapper status */
+#define PWRAP_GET_WACS_RDATA(x) (((x) >> 0) & 0x0000ffff)
+#define PWRAP_GET_WACS_FSM(x) (((x) >> 16) & 0x00000007)
+#define PWRAP_GET_WACS_REQ(x) (((x) >> 19) & 0x00000001)
+#define PWRAP_STATE_SYNC_IDLE0 (1 << 20)
+#define PWRAP_STATE_INIT_DONE0 (1 << 21)
+
+/* macro for WACS FSM */
+#define PWRAP_WACS_FSM_IDLE 0x00
+#define PWRAP_WACS_FSM_REQ 0x02
+#define PWRAP_WACS_FSM_WFDLE 0x04
+#define PWRAP_WACS_FSM_WFVLDCLR 0x06
+#define PWRAP_WACS_INIT_DONE 0x01
+#define PWRAP_WACS_WACS_SYNC_IDLE 0x01
+#define PWRAP_WACS_SYNC_BUSY 0x00
+
+/* macro for device wrapper default value */
+#define PWRAP_DEW_READ_TEST_VAL 0x5aa5
+#define PWRAP_DEW_WRITE_TEST_VAL 0xa55a
+
+/* macro for manual command */
+#define PWRAP_MAN_CMD_SPI_WRITE (1 << 13)
+#define PWRAP_MAN_CMD_OP_CSH (0x0 << 8)
+#define PWRAP_MAN_CMD_OP_CSL (0x1 << 8)
+#define PWRAP_MAN_CMD_OP_CK (0x2 << 8)
+#define PWRAP_MAN_CMD_OP_OUTS (0x8 << 8)
+#define PWRAP_MAN_CMD_OP_OUTD (0x9 << 8)
+#define PWRAP_MAN_CMD_OP_OUTQ (0xa << 8)
+
+/* macro for slave device wrapper registers */
+#define PWRAP_DEW_BASE 0xbc00
+#define PWRAP_DEW_EVENT_OUT_EN (PWRAP_DEW_BASE + 0x0)
+#define PWRAP_DEW_DIO_EN (PWRAP_DEW_BASE + 0x2)
+#define PWRAP_DEW_EVENT_SRC_EN (PWRAP_DEW_BASE + 0x4)
+#define PWRAP_DEW_EVENT_SRC (PWRAP_DEW_BASE + 0x6)
+#define PWRAP_DEW_EVENT_FLAG (PWRAP_DEW_BASE + 0x8)
+#define PWRAP_DEW_READ_TEST (PWRAP_DEW_BASE + 0xa)
+#define PWRAP_DEW_WRITE_TEST (PWRAP_DEW_BASE + 0xc)
+#define PWRAP_DEW_CRC_EN (PWRAP_DEW_BASE + 0xe)
+#define PWRAP_DEW_CRC_VAL (PWRAP_DEW_BASE + 0x10)
+#define PWRAP_DEW_MON_GRP_SEL (PWRAP_DEW_BASE + 0x12)
+#define PWRAP_DEW_MON_FLAG_SEL (PWRAP_DEW_BASE + 0x14)
+#define PWRAP_DEW_EVENT_TEST (PWRAP_DEW_BASE + 0x16)
+#define PWRAP_DEW_CIPHER_KEY_SEL (PWRAP_DEW_BASE + 0x18)
+#define PWRAP_DEW_CIPHER_IV_SEL (PWRAP_DEW_BASE + 0x1a)
+#define PWRAP_DEW_CIPHER_LOAD (PWRAP_DEW_BASE + 0x1c)
+#define PWRAP_DEW_CIPHER_START (PWRAP_DEW_BASE + 0x1e)
+#define PWRAP_DEW_CIPHER_RDY (PWRAP_DEW_BASE + 0x20)
+#define PWRAP_DEW_CIPHER_MODE (PWRAP_DEW_BASE + 0x22)
+#define PWRAP_DEW_CIPHER_SWRST (PWRAP_DEW_BASE + 0x24)
+#define PWRAP_MT8173_DEW_CIPHER_IV0 (PWRAP_DEW_BASE + 0x26)
+#define PWRAP_MT8173_DEW_CIPHER_IV1 (PWRAP_DEW_BASE + 0x28)
+#define PWRAP_MT8173_DEW_CIPHER_IV2 (PWRAP_DEW_BASE + 0x2a)
+#define PWRAP_MT8173_DEW_CIPHER_IV3 (PWRAP_DEW_BASE + 0x2c)
+#define PWRAP_MT8173_DEW_CIPHER_IV4 (PWRAP_DEW_BASE + 0x2e)
+#define PWRAP_MT8173_DEW_CIPHER_IV5 (PWRAP_DEW_BASE + 0x30)
+
+/*
+ * FIXME: These shouldn't be here. These registers are on the PMIC,
+ * so they should be touched in the PMIC driver, not the driver
+ * granting access to it.
+ */
+#define MT6397_WRP_CKPDN 0x011a
+#define MT6397_WRP_RST_CON 0x0120
+#define MT6397_TOP_CKCON2 0x012a
+#define MT6397_TOP_CKCON3 0x01d4
+
+enum pwrap_regs {
+ PWRAP_MUX_SEL,
+ PWRAP_WRAP_EN,
+ PWRAP_DIO_EN,
+ PWRAP_SIDLY,
+ PWRAP_CSHEXT_WRITE,
+ PWRAP_CSHEXT_READ,
+ PWRAP_CSLEXT_START,
+ PWRAP_CSLEXT_END,
+ PWRAP_STAUPD_PRD,
+ PWRAP_STAUPD_GRPEN,
+ PWRAP_STAUPD_MAN_TRIG,
+ PWRAP_STAUPD_STA,
+ PWRAP_WRAP_STA,
+ PWRAP_HARB_INIT,
+ PWRAP_HARB_HPRIO,
+ PWRAP_HIPRIO_ARB_EN,
+ PWRAP_HARB_STA0,
+ PWRAP_HARB_STA1,
+ PWRAP_MAN_EN,
+ PWRAP_MAN_CMD,
+ PWRAP_MAN_RDATA,
+ PWRAP_MAN_VLDCLR,
+ PWRAP_WACS0_EN,
+ PWRAP_INIT_DONE0,
+ PWRAP_WACS0_CMD,
+ PWRAP_WACS0_RDATA,
+ PWRAP_WACS0_VLDCLR,
+ PWRAP_WACS1_EN,
+ PWRAP_INIT_DONE1,
+ PWRAP_WACS1_CMD,
+ PWRAP_WACS1_RDATA,
+ PWRAP_WACS1_VLDCLR,
+ PWRAP_WACS2_EN,
+ PWRAP_INIT_DONE2,
+ PWRAP_WACS2_CMD,
+ PWRAP_WACS2_RDATA,
+ PWRAP_WACS2_VLDCLR,
+ PWRAP_INT_EN,
+ PWRAP_INT_FLG_RAW,
+ PWRAP_INT_FLG,
+ PWRAP_INT_CLR,
+ PWRAP_SIG_ADR,
+ PWRAP_SIG_MODE,
+ PWRAP_SIG_VALUE,
+ PWRAP_SIG_ERRVAL,
+ PWRAP_CRC_EN,
+ PWRAP_TIMER_EN,
+ PWRAP_TIMER_STA,
+ PWRAP_WDT_UNIT,
+ PWRAP_WDT_SRC_EN,
+ PWRAP_WDT_FLG,
+ PWRAP_DEBUG_INT_SEL,
+ PWRAP_CIPHER_KEY_SEL,
+ PWRAP_CIPHER_IV_SEL,
+ PWRAP_CIPHER_RDY,
+ PWRAP_CIPHER_MODE,
+ PWRAP_CIPHER_SWRST,
+ PWRAP_DCM_EN,
+ PWRAP_DCM_DBC_PRD,
+
+ /* MT8135 only regs */
+ PWRAP_CSHEXT,
+ PWRAP_EVENT_IN_EN,
+ PWRAP_EVENT_DST_EN,
+ PWRAP_RRARB_INIT,
+ PWRAP_RRARB_EN,
+ PWRAP_RRARB_STA0,
+ PWRAP_RRARB_STA1,
+ PWRAP_EVENT_STA,
+ PWRAP_EVENT_STACLR,
+ PWRAP_CIPHER_LOAD,
+ PWRAP_CIPHER_START,
+
+ /* MT8173 only regs */
+ PWRAP_RDDMY,
+ PWRAP_SI_CK_CON,
+ PWRAP_DVFS_ADR0,
+ PWRAP_DVFS_WDATA0,
+ PWRAP_DVFS_ADR1,
+ PWRAP_DVFS_WDATA1,
+ PWRAP_DVFS_ADR2,
+ PWRAP_DVFS_WDATA2,
+ PWRAP_DVFS_ADR3,
+ PWRAP_DVFS_WDATA3,
+ PWRAP_DVFS_ADR4,
+ PWRAP_DVFS_WDATA4,
+ PWRAP_DVFS_ADR5,
+ PWRAP_DVFS_WDATA5,
+ PWRAP_DVFS_ADR6,
+ PWRAP_DVFS_WDATA6,
+ PWRAP_DVFS_ADR7,
+ PWRAP_DVFS_WDATA7,
+ PWRAP_SPMINF_STA,
+ PWRAP_CIPHER_EN,
+};
+
+static int mt8173_regs[] = {
+ [PWRAP_MUX_SEL] = 0x0,
+ [PWRAP_WRAP_EN] = 0x4,
+ [PWRAP_DIO_EN] = 0x8,
+ [PWRAP_SIDLY] = 0xc,
+ [PWRAP_RDDMY] = 0x10,
+ [PWRAP_SI_CK_CON] = 0x14,
+ [PWRAP_CSHEXT_WRITE] = 0x18,
+ [PWRAP_CSHEXT_READ] = 0x1c,
+ [PWRAP_CSLEXT_START] = 0x20,
+ [PWRAP_CSLEXT_END] = 0x24,
+ [PWRAP_STAUPD_PRD] = 0x28,
+ [PWRAP_STAUPD_GRPEN] = 0x2c,
+ [PWRAP_STAUPD_MAN_TRIG] = 0x40,
+ [PWRAP_STAUPD_STA] = 0x44,
+ [PWRAP_WRAP_STA] = 0x48,
+ [PWRAP_HARB_INIT] = 0x4c,
+ [PWRAP_HARB_HPRIO] = 0x50,
+ [PWRAP_HIPRIO_ARB_EN] = 0x54,
+ [PWRAP_HARB_STA0] = 0x58,
+ [PWRAP_HARB_STA1] = 0x5c,
+ [PWRAP_MAN_EN] = 0x60,
+ [PWRAP_MAN_CMD] = 0x64,
+ [PWRAP_MAN_RDATA] = 0x68,
+ [PWRAP_MAN_VLDCLR] = 0x6c,
+ [PWRAP_WACS0_EN] = 0x70,
+ [PWRAP_INIT_DONE0] = 0x74,
+ [PWRAP_WACS0_CMD] = 0x78,
+ [PWRAP_WACS0_RDATA] = 0x7c,
+ [PWRAP_WACS0_VLDCLR] = 0x80,
+ [PWRAP_WACS1_EN] = 0x84,
+ [PWRAP_INIT_DONE1] = 0x88,
+ [PWRAP_WACS1_CMD] = 0x8c,
+ [PWRAP_WACS1_RDATA] = 0x90,
+ [PWRAP_WACS1_VLDCLR] = 0x94,
+ [PWRAP_WACS2_EN] = 0x98,
+ [PWRAP_INIT_DONE2] = 0x9c,
+ [PWRAP_WACS2_CMD] = 0xa0,
+ [PWRAP_WACS2_RDATA] = 0xa4,
+ [PWRAP_WACS2_VLDCLR] = 0xa8,
+ [PWRAP_INT_EN] = 0xac,
+ [PWRAP_INT_FLG_RAW] = 0xb0,
+ [PWRAP_INT_FLG] = 0xb4,
+ [PWRAP_INT_CLR] = 0xb8,
+ [PWRAP_SIG_ADR] = 0xbc,
+ [PWRAP_SIG_MODE] = 0xc0,
+ [PWRAP_SIG_VALUE] = 0xc4,
+ [PWRAP_SIG_ERRVAL] = 0xc8,
+ [PWRAP_CRC_EN] = 0xcc,
+ [PWRAP_TIMER_EN] = 0xd0,
+ [PWRAP_TIMER_STA] = 0xd4,
+ [PWRAP_WDT_UNIT] = 0xd8,
+ [PWRAP_WDT_SRC_EN] = 0xdc,
+ [PWRAP_WDT_FLG] = 0xe0,
+ [PWRAP_DEBUG_INT_SEL] = 0xe4,
+ [PWRAP_DVFS_ADR0] = 0xe8,
+ [PWRAP_DVFS_WDATA0] = 0xec,
+ [PWRAP_DVFS_ADR1] = 0xf0,
+ [PWRAP_DVFS_WDATA1] = 0xf4,
+ [PWRAP_DVFS_ADR2] = 0xf8,
+ [PWRAP_DVFS_WDATA2] = 0xfc,
+ [PWRAP_DVFS_ADR3] = 0x100,
+ [PWRAP_DVFS_WDATA3] = 0x104,
+ [PWRAP_DVFS_ADR4] = 0x108,
+ [PWRAP_DVFS_WDATA4] = 0x10c,
+ [PWRAP_DVFS_ADR5] = 0x110,
+ [PWRAP_DVFS_WDATA5] = 0x114,
+ [PWRAP_DVFS_ADR6] = 0x118,
+ [PWRAP_DVFS_WDATA6] = 0x11c,
+ [PWRAP_DVFS_ADR7] = 0x120,
+ [PWRAP_DVFS_WDATA7] = 0x124,
+ [PWRAP_SPMINF_STA] = 0x128,
+ [PWRAP_CIPHER_KEY_SEL] = 0x12c,
+ [PWRAP_CIPHER_IV_SEL] = 0x130,
+ [PWRAP_CIPHER_EN] = 0x134,
+ [PWRAP_CIPHER_RDY] = 0x138,
+ [PWRAP_CIPHER_MODE] = 0x13c,
+ [PWRAP_CIPHER_SWRST] = 0x140,
+ [PWRAP_DCM_EN] = 0x144,
+ [PWRAP_DCM_DBC_PRD] = 0x148,
+};
+
+static int mt8135_regs[] = {
+ [PWRAP_MUX_SEL] = 0x0,
+ [PWRAP_WRAP_EN] = 0x4,
+ [PWRAP_DIO_EN] = 0x8,
+ [PWRAP_SIDLY] = 0xc,
+ [PWRAP_CSHEXT] = 0x10,
+ [PWRAP_CSHEXT_WRITE] = 0x14,
+ [PWRAP_CSHEXT_READ] = 0x18,
+ [PWRAP_CSLEXT_START] = 0x1c,
+ [PWRAP_CSLEXT_END] = 0x20,
+ [PWRAP_STAUPD_PRD] = 0x24,
+ [PWRAP_STAUPD_GRPEN] = 0x28,
+ [PWRAP_STAUPD_MAN_TRIG] = 0x2c,
+ [PWRAP_STAUPD_STA] = 0x30,
+ [PWRAP_EVENT_IN_EN] = 0x34,
+ [PWRAP_EVENT_DST_EN] = 0x38,
+ [PWRAP_WRAP_STA] = 0x3c,
+ [PWRAP_RRARB_INIT] = 0x40,
+ [PWRAP_RRARB_EN] = 0x44,
+ [PWRAP_RRARB_STA0] = 0x48,
+ [PWRAP_RRARB_STA1] = 0x4c,
+ [PWRAP_HARB_INIT] = 0x50,
+ [PWRAP_HARB_HPRIO] = 0x54,
+ [PWRAP_HIPRIO_ARB_EN] = 0x58,
+ [PWRAP_HARB_STA0] = 0x5c,
+ [PWRAP_HARB_STA1] = 0x60,
+ [PWRAP_MAN_EN] = 0x64,
+ [PWRAP_MAN_CMD] = 0x68,
+ [PWRAP_MAN_RDATA] = 0x6c,
+ [PWRAP_MAN_VLDCLR] = 0x70,
+ [PWRAP_WACS0_EN] = 0x74,
+ [PWRAP_INIT_DONE0] = 0x78,
+ [PWRAP_WACS0_CMD] = 0x7c,
+ [PWRAP_WACS0_RDATA] = 0x80,
+ [PWRAP_WACS0_VLDCLR] = 0x84,
+ [PWRAP_WACS1_EN] = 0x88,
+ [PWRAP_INIT_DONE1] = 0x8c,
+ [PWRAP_WACS1_CMD] = 0x90,
+ [PWRAP_WACS1_RDATA] = 0x94,
+ [PWRAP_WACS1_VLDCLR] = 0x98,
+ [PWRAP_WACS2_EN] = 0x9c,
+ [PWRAP_INIT_DONE2] = 0xa0,
+ [PWRAP_WACS2_CMD] = 0xa4,
+ [PWRAP_WACS2_RDATA] = 0xa8,
+ [PWRAP_WACS2_VLDCLR] = 0xac,
+ [PWRAP_INT_EN] = 0xb0,
+ [PWRAP_INT_FLG_RAW] = 0xb4,
+ [PWRAP_INT_FLG] = 0xb8,
+ [PWRAP_INT_CLR] = 0xbc,
+ [PWRAP_SIG_ADR] = 0xc0,
+ [PWRAP_SIG_MODE] = 0xc4,
+ [PWRAP_SIG_VALUE] = 0xc8,
+ [PWRAP_SIG_ERRVAL] = 0xcc,
+ [PWRAP_CRC_EN] = 0xd0,
+ [PWRAP_EVENT_STA] = 0xd4,
+ [PWRAP_EVENT_STACLR] = 0xd8,
+ [PWRAP_TIMER_EN] = 0xdc,
+ [PWRAP_TIMER_STA] = 0xe0,
+ [PWRAP_WDT_UNIT] = 0xe4,
+ [PWRAP_WDT_SRC_EN] = 0xe8,
+ [PWRAP_WDT_FLG] = 0xec,
+ [PWRAP_DEBUG_INT_SEL] = 0xf0,
+ [PWRAP_CIPHER_KEY_SEL] = 0x134,
+ [PWRAP_CIPHER_IV_SEL] = 0x138,
+ [PWRAP_CIPHER_LOAD] = 0x13c,
+ [PWRAP_CIPHER_START] = 0x140,
+ [PWRAP_CIPHER_RDY] = 0x144,
+ [PWRAP_CIPHER_MODE] = 0x148,
+ [PWRAP_CIPHER_SWRST] = 0x14c,
+ [PWRAP_DCM_EN] = 0x15c,
+ [PWRAP_DCM_DBC_PRD] = 0x160,
+};
+
+enum pwrap_type {
+ PWRAP_MT8135,
+ PWRAP_MT8173,
+};
+
+struct pmic_wrapper_type {
+ int *regs;
+ enum pwrap_type type;
+ u32 arb_en_all;
+};
+
+static struct pmic_wrapper_type pwrap_mt8135 = {
+ .regs = mt8135_regs,
+ .type = PWRAP_MT8135,
+ .arb_en_all = 0x1ff,
+};
+
+static struct pmic_wrapper_type pwrap_mt8173 = {
+ .regs = mt8173_regs,
+ .type = PWRAP_MT8173,
+ .arb_en_all = 0x3f,
+};
+
+struct pmic_wrapper {
+ struct device *dev;
+ void __iomem *base;
+ struct regmap *regmap;
+ int *regs;
+ enum pwrap_type type;
+ u32 arb_en_all;
+ struct clk *clk_spi;
+ struct clk *clk_wrap;
+ struct reset_control *rstc;
+
+ struct reset_control *rstc_bridge;
+ void __iomem *bridge_base;
+};
+
+static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp)
+{
+ return wrp->type == PWRAP_MT8135;
+}
+
+static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp)
+{
+ return wrp->type == PWRAP_MT8173;
+}
+
+static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg)
+{
+ return readl(wrp->base + wrp->regs[reg]);
+}
+
+static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg)
+{
+ writel(val, wrp->base + wrp->regs[reg]);
+}
+
+static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp)
+{
+ u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+ return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE;
+}
+
+static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp)
+{
+ u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+ return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR;
+}
+
+static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp)
+{
+ return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0;
+}
+
+static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp)
+{
+ u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+ return (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE) &&
+ (val & PWRAP_STATE_SYNC_IDLE0);
+}
+
+static int pwrap_wait_for_state(struct pmic_wrapper *wrp,
+ bool (*fp)(struct pmic_wrapper *))
+{
+ unsigned long timeout;
+
+ timeout = jiffies + usecs_to_jiffies(255);
+
+ do {
+ if (time_after(jiffies, timeout))
+ return fp(wrp) ? 0 : -ETIMEDOUT;
+ if (fp(wrp))
+ return 0;
+ } while (1);
+}
+
+static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
+{
+ int ret;
+ u32 val;
+
+ val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+ if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR)
+ pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ if (ret)
+ return ret;
+
+ pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata,
+ PWRAP_WACS2_CMD);
+
+ return 0;
+}
+
+static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
+{
+ int ret;
+ u32 val;
+
+ val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+ if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR)
+ pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ if (ret)
+ return ret;
+
+ pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD);
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr);
+ if (ret)
+ return ret;
+
+ *rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA));
+
+ return 0;
+}
+
+static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata)
+{
+ return pwrap_read(context, adr, rdata);
+}
+
+static int pwrap_regmap_write(void *context, u32 adr, u32 wdata)
+{
+ return pwrap_write(context, adr, wdata);
+}
+
+static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
+{
+ int ret, i;
+
+ pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN);
+ pwrap_writel(wrp, 0, PWRAP_WRAP_EN);
+ pwrap_writel(wrp, 1, PWRAP_MUX_SEL);
+ pwrap_writel(wrp, 1, PWRAP_MAN_EN);
+ pwrap_writel(wrp, 0, PWRAP_DIO_EN);
+
+ pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSL,
+ PWRAP_MAN_CMD);
+ pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
+ PWRAP_MAN_CMD);
+ pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSH,
+ PWRAP_MAN_CMD);
+
+ for (i = 0; i < 4; i++)
+ pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
+ PWRAP_MAN_CMD);
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle);
+ if (ret) {
+ dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
+ pwrap_writel(wrp, 0, PWRAP_MAN_EN);
+ pwrap_writel(wrp, 0, PWRAP_MUX_SEL);
+
+ return 0;
+}
+
+/*
+ * pwrap_init_sidly - configure serial input delay
+ *
+ * This configures the serial input delay. We can configure 0, 2, 4 or 6ns
+ * delay. Do a read test with all possible values and chose the best delay.
+ */
+static int pwrap_init_sidly(struct pmic_wrapper *wrp)
+{
+ u32 rdata;
+ u32 i;
+ u32 pass = 0;
+ signed char dly[16] = {
+ -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1
+ };
+
+ for (i = 0; i < 4; i++) {
+ pwrap_writel(wrp, i, PWRAP_SIDLY);
+ pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+ printk("%s: 0x%04x\n", __func__, rdata);
+ if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+ dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
+ pass |= 1 << i;
+ }
+ }
+
+ if (dly[pass] < 0) {
+ dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n",
+ pass);
+ return -EIO;
+ }
+
+ pwrap_writel(wrp, dly[pass], PWRAP_SIDLY);
+
+ return 0;
+}
+
+static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
+{
+ u32 wdata;
+ u32 rdata;
+ unsigned long rate_spi;
+ int ck_mhz;
+
+ rate_spi = clk_get_rate(wrp->clk_spi);
+
+ if (rate_spi > 26000000)
+ ck_mhz = 26;
+ else if (rate_spi > 18)
+ ck_mhz = 18;
+ else
+ ck_mhz = 0;
+
+ pwrap_read(wrp, MT6397_TOP_CKCON2, &rdata);
+ wdata = rdata & ~(0x3 << 10);
+
+ if (ck_mhz == 18)
+ wdata |= 0x1 << 10;
+
+ if (pwrap_write(wrp, MT6397_TOP_CKCON2, wdata)) {
+ dev_err(wrp->dev, "Enable PMIC TOP_CKCON2 fail\n");
+ return -EFAULT;
+ }
+
+ switch (ck_mhz) {
+ case 18:
+ if (pwrap_is_mt8135(wrp))
+ pwrap_writel(wrp, 0xc, PWRAP_CSHEXT);
+ pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE);
+ pwrap_writel(wrp, 0xc, PWRAP_CSHEXT_READ);
+ pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+ pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
+ break;
+ case 26:
+ if (pwrap_is_mt8135(wrp))
+ pwrap_writel(wrp, 0x4, PWRAP_CSHEXT);
+ pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
+ pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+ pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+ pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
+ break;
+ case 0:
+ if (pwrap_is_mt8135(wrp))
+ pwrap_writel(wrp, 0xf, PWRAP_CSHEXT);
+ pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_WRITE);
+ pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_READ);
+ pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_START);
+ pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_END);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Enable PMIC side reg clock */
+ if (pwrap_write(wrp, MT6397_WRP_CKPDN, 0) ||
+ pwrap_write(wrp, MT6397_WRP_RST_CON, 0)) {
+ dev_err(wrp->dev, "Enable PMIC fail\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
+{
+ return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
+}
+
+static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+{
+ u32 rdata;
+ int ret;
+
+ ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
+ if (ret)
+ return 0;
+
+ return rdata == 1;
+}
+
+static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+{
+ int ret;
+ u32 rdata;
+
+ pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST);
+ pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST);
+ pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL);
+ pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL);
+
+ if (pwrap_is_mt8135(wrp)) {
+ pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD);
+ pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
+ } else {
+ pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
+ }
+
+ /* Config cipher mode @PMIC */
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
+
+ /* wait for cipher data ready@AP */
+ ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+ if (ret) {
+ dev_err(wrp->dev, "cipher data ready@AP fail, ret=%d\n", ret);
+ return ret;
+ }
+
+ /* wait for cipher data ready@PMIC */
+ ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready);
+ if (ret) {
+ dev_err(wrp->dev, "timeout waiting for cipher data ready@PMIC\n");
+ return ret;
+ }
+
+ /* wait for cipher mode idle */
+ pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+ if (ret) {
+ dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
+ return ret;
+ }
+
+ pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE);
+
+ /* Write Test */
+ if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
+ pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
+ (rdata != PWRAP_DEW_WRITE_TEST_VAL)) {
+ dev_err(wrp->dev, "rdata=0x%04X\n", rdata);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int pwrap_init(struct pmic_wrapper *wrp)
+{
+ int ret;
+ u32 rdata;
+
+ reset_control_reset(wrp->rstc);
+ if (wrp->rstc_bridge)
+ reset_control_reset(wrp->rstc_bridge);
+
+ if (pwrap_is_mt8173(wrp)) {
+ /* Enable DCM */
+ pwrap_writel(wrp, 3, PWRAP_DCM_EN);
+ pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+ }
+
+ /* Reset SPI slave */
+ ret = pwrap_reset_spislave(wrp);
+ if (ret)
+ return ret;
+
+ pwrap_writel(wrp, 1, PWRAP_WRAP_EN);
+
+ pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+ pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
+
+ ret = pwrap_init_reg_clock(wrp);
+ if (ret)
+ return ret;
+
+ /* Setup serial input delay */
+ ret = pwrap_init_sidly(wrp);
+ if (ret)
+ return ret;
+
+ if (pwrap_is_mt8173(wrp)) {
+ /*
+ * Enable PMIC
+ * (May not be necessary, depending on S/W partition)
+ * set dewrap clock bit and clear dewrap reset bit
+ */
+ if (pwrap_write(wrp, MT6397_WRP_CKPDN, 0) ||
+ pwrap_write(wrp, MT6397_WRP_RST_CON, 0)) {
+ dev_err(wrp->dev, "Enable PMIC fail\n");
+ return -EFAULT;
+ }
+ }
+
+ /* Enable dual IO mode */
+ pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1);
+
+ /* Check IDLE & INIT_DONE in advance */
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+ if (ret) {
+ dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
+ pwrap_writel(wrp, 1, PWRAP_DIO_EN);
+
+ /* Read Test */
+ pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+ if (rdata != PWRAP_DEW_READ_TEST_VAL) {
+ dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n",
+ PWRAP_DEW_READ_TEST_VAL, rdata);
+ return -EFAULT;
+ }
+
+ /* Enable encryption */
+ ret = pwrap_init_cipher(wrp);
+ if (ret)
+ return ret;
+
+ /* Signature checking - using CRC */
+ if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
+ return -EFAULT;
+
+ pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
+ pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
+ pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR);
+ pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+ if (pwrap_is_mt8135(wrp))
+ pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN);
+
+ pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
+ pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
+ pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
+ pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+ pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+ pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
+
+ /* switch event pin from usbdl mode to normal mode @ MT6397 */
+ if (pwrap_read(wrp, MT6397_TOP_CKCON3, &rdata) ||
+ pwrap_write(wrp, MT6397_TOP_CKCON3, (rdata & 0x0007))) {
+ dev_err(wrp->dev, "switch event pin fail\n");
+ return -EFAULT;
+ }
+
+ if (pwrap_is_mt8135(wrp)) {
+ /* enable pwrap events and pwrap bridge in AP side */
+ pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN);
+ pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN);
+ writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN);
+ writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN);
+ writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN);
+ writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT);
+ writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN);
+ writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN);
+ writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
+
+ /* enable PMIC event out and sources */
+ if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+ pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+ dev_err(wrp->dev, "enable dewrap fail\n");
+ return -EFAULT;
+ }
+ } else {
+ /* PMIC_DEWRAP enables */
+ if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+ pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+ dev_err(wrp->dev, "enable dewrap fail\n");
+ return -EFAULT;
+ }
+ }
+
+ /* Setup the init done registers */
+ pwrap_writel(wrp, 1, PWRAP_INIT_DONE2);
+ pwrap_writel(wrp, 1, PWRAP_INIT_DONE0);
+ pwrap_writel(wrp, 1, PWRAP_INIT_DONE1);
+
+ if (pwrap_is_mt8135(wrp)) {
+ writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3);
+ writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4);
+ }
+
+ return 0;
+}
+
+static irqreturn_t pwrap_interrupt(int irqno, void *dev_id)
+{
+ u32 rdata;
+ struct pmic_wrapper *wrp = dev_id;
+
+ rdata = pwrap_readl(wrp, PWRAP_INT_FLG);
+
+ dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata);
+
+ pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR);
+
+ return IRQ_HANDLED;
+}
+
+static const struct regmap_config pwrap_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .reg_read = pwrap_regmap_read,
+ .reg_write = pwrap_regmap_write,
+};
+
+static struct of_device_id of_pwrap_match_tbl[] = {
+ {
+ .compatible = "mediatek,mt8135-pwrap",
+ .data = &pwrap_mt8135,
+ }, {
+ .compatible = "mediatek,mt8173-pwrap",
+ .data = &pwrap_mt8173,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl);
+
+static int pwrap_probe(struct platform_device *pdev)
+{
+ int ret, irq;
+ struct pmic_wrapper *wrp;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(of_pwrap_match_tbl, &pdev->dev);
+ const struct pmic_wrapper_type *type;
+ struct resource *res;
+
+ wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL);
+ if (!wrp)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, wrp);
+
+ type = of_id->data;
+ wrp->regs = type->regs;
+ wrp->type = type->type;
+ wrp->arb_en_all = type->arb_en_all;
+ wrp->dev = &pdev->dev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap");
+ wrp->base = devm_ioremap_resource(wrp->dev, res);
+ if (IS_ERR(wrp->base))
+ return PTR_ERR(wrp->base);
+
+ wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap");
+ if (IS_ERR(wrp->rstc)) {
+ ret = PTR_ERR(wrp->rstc);
+ dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret);
+ return ret;
+ }
+
+ if (pwrap_is_mt8135(wrp)) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "pwrap-bridge");
+ wrp->bridge_base = devm_ioremap_resource(wrp->dev, res);
+ if (IS_ERR(wrp->bridge_base))
+ return PTR_ERR(wrp->bridge_base);
+
+ wrp->rstc_bridge = devm_reset_control_get(wrp->dev, "pwrap-bridge");
+ if (IS_ERR(wrp->rstc_bridge)) {
+ ret = PTR_ERR(wrp->rstc_bridge);
+ dev_dbg(wrp->dev, "cannot get pwrap-bridge reset: %d\n", ret);
+ return ret;
+ }
+ }
+
+ wrp->clk_spi = devm_clk_get(wrp->dev, "spi");
+ if (IS_ERR(wrp->clk_spi)) {
+ dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_spi));
+ return PTR_ERR(wrp->clk_spi);
+ }
+
+ wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap");
+ if (IS_ERR(wrp->clk_wrap)) {
+ dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_wrap));
+ return PTR_ERR(wrp->clk_wrap);
+ }
+
+ ret = clk_prepare_enable(wrp->clk_spi);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(wrp->clk_wrap);
+ if (ret)
+ goto err_out1;
+
+ /* Enable internal dynamic clock */
+ pwrap_writel(wrp, 1, PWRAP_DCM_EN);
+ pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+
+ /*
+ * The PMIC could already be initialized by the bootloader.
+ * Skip initialization here in this case.
+ */
+ if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) {
+ ret = pwrap_init(wrp);
+ if (ret) {
+ dev_dbg(wrp->dev, "init failed with %d\n", ret);
+ goto err_out2;
+ }
+ }
+
+ if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) {
+ dev_dbg(wrp->dev, "initialization isn't finished\n");
+ return -ENODEV;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
+ "mt-pmic-pwrap", wrp);
+ if (ret)
+ goto err_out2;
+
+ wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config);
+ if (IS_ERR(wrp->regmap))
+ return ret;
+
+ ret = of_platform_populate(np, NULL, NULL, wrp->dev);
+ if (ret) {
+ dev_dbg(wrp->dev, "failed to create child devices at %s\n",
+ np->full_name);
+ goto err_out2;
+ }
+
+ return 0;
+
+err_out2:
+ clk_disable_unprepare(wrp->clk_wrap);
+err_out1:
+ clk_disable_unprepare(wrp->clk_spi);
+
+ return ret;
+}
+
+static struct platform_driver pwrap_drv = {
+ .driver = {
+ .name = "mt-pmic-pwrap",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_pwrap_match_tbl),
+ },
+ .probe = pwrap_probe,
+};
+
+module_platform_driver(pwrap_drv);
+
+MODULE_AUTHOR("Flora Fu");
+MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver");
+MODULE_LICENSE("GPL");
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 5/8] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
` (3 preceding siblings ...)
2015-01-20 9:47 ` [PATCH 4/8] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 6/8] ARM: dts: mt8135-evbp1: Add PMIC support Sascha Hauer
` (2 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown,
Sascha Hauer
This adds the perisys, infracfg and pmic wrapper nodes to the
MediaTek MT8135 dtsi file.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/boot/dts/mt8135.dtsi | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index 7d56a98..14ba41d 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -14,6 +14,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset-controller/mt8135-resets.h>
#include "skeleton64.dtsi"
/ {
@@ -86,6 +87,12 @@
clock-frequency = <32000>;
#clock-cells = <0>;
};
+
+ clk_26m: clk26m {
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ #clock-cells = <0>;
+ };
};
soc {
@@ -94,6 +101,33 @@
compatible = "simple-bus";
ranges;
+ infracfg: infracfg@10001000 {
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ compatible = "mediatek,mt8135-infracfg";
+ reg = <0 0x10001000 0 0x1000>;
+ };
+
+ pericfg: pericfg@10003000 {
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ compatible = "mediatek,mt8135-pericfg";
+ reg = <0 0x10003000 0 0x1000>;
+ };
+
+ pwrap: pwrap@1000f000 {
+ compatible = "mediatek,mt8135-pwrap";
+ reg = <0 0x1000f000 0 0x1000>,
+ <0 0x11017000 0 0x1000>;
+ reg-names = "pwrap-base", "pwrap-bridge-base";
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>,
+ <&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
+ reset-names = "pwrap", "pwrap-bridge";
+ clocks = <&clk_26m>, <&clk_26m>;
+ clock-names = "spi", "wrap";
+ };
+
timer: timer@10008000 {
compatible = "mediatek,mt8135-timer",
"mediatek,mt6577-timer";
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 6/8] ARM: dts: mt8135-evbp1: Add PMIC support
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
` (4 preceding siblings ...)
2015-01-20 9:47 ` [PATCH 5/8] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 7/8] mfd: Add support for the MediaTek MT6397 PMIC Sascha Hauer
2015-01-20 9:47 ` [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator Sascha Hauer
7 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown,
Sascha Hauer
The MT8135 eval board contains a MT6397 PMIC. This adds the
corresponding device node to the dts file.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/boot/dts/mt8135-evbp1.dts | 193 +++++++++++++++++++++++++++++++++++++
1 file changed, 193 insertions(+)
diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts
index a5adf97..3be2c8b 100644
--- a/arch/arm/boot/dts/mt8135-evbp1.dts
+++ b/arch/arm/boot/dts/mt8135-evbp1.dts
@@ -23,3 +23,196 @@
reg = <0 0x80000000 0 0x40000000>;
};
};
+
+&pwrap {
+ pmic: mt6397 {
+ compatible = "mediatek,mt6397";
+
+ mt6397regulator: mt6397regulator {
+ compatible = "mediatek,mt6397-regulator";
+
+ mt6397_vpca15_reg: buck_vpca15 {
+ regulator-compatible = "buck_vpca15";
+ regulator-name = "vpca15";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vpca7_reg: buck_vpca7 {
+ regulator-compatible = "buck_vpca7";
+ regulator-name = "vpca7";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vsramca15_reg: buck_vsramca15 {
+ regulator-compatible = "buck_vsramca15";
+ regulator-name = "vsramca15";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vsramca7_reg: buck_vsramca7 {
+ regulator-compatible = "buck_vsramca7";
+ regulator-name = "vsramca7";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vcore_reg: buck_vcore {
+ regulator-compatible = "buck_vcore";
+ regulator-name = "vcore";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vgpu_reg: buck_vgpu {
+ regulator-compatible = "buck_vgpu";
+ regulator-name = "vgpu";
+ regulator-min-microvolt = < 700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <115>;
+ };
+
+ mt6397_vdrm_reg: buck_vdrm {
+ regulator-compatible = "buck_vdrm";
+ regulator-name = "vdrm";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vio18_reg: buck_vio18 {
+ regulator-compatible = "buck_vio18";
+ regulator-name = "vio18";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vtcxo_reg: ldo_vtcxo {
+ regulator-compatible = "ldo_vtcxo";
+ regulator-name = "vtcxo";
+ regulator-always-on;
+ };
+
+ mt6397_va28_reg: ldo_va28 {
+ regulator-compatible = "ldo_va28";
+ regulator-name = "va28";
+ regulator-always-on;
+ };
+
+ mt6397_vcama_reg: ldo_vcama {
+ regulator-compatible = "ldo_vcama";
+ regulator-name = "vcama";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vio28_reg: ldo_vio28 {
+ regulator-compatible = "ldo_vio28";
+ regulator-name = "vio28";
+ regulator-always-on;
+ };
+
+ mt6397_vusb_reg: ldo_vusb {
+ regulator-compatible = "ldo_vusb";
+ regulator-name = "vusb";
+ };
+
+ mt6397_vmc_reg: ldo_vmc {
+ regulator-compatible = "ldo_vmc";
+ regulator-name = "vmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vmch_reg: ldo_vmch {
+ regulator-compatible = "ldo_vmch";
+ regulator-name = "vmch";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vemc_3v3_reg: ldo_vemc3v3 {
+ regulator-compatible = "ldo_vemc3v3";
+ regulator-name = "vemc_3v3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp1_reg: ldo_vgp1 {
+ regulator-compatible = "ldo_vgp1";
+ regulator-name = "vcamd";
+ regulator-min-microvolt = <1220000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <240>;
+ };
+
+ mt6397_vgp2_reg: ldo_vgp2 {
+ regulator-compatible = "ldo_vgp2";
+ regulator-name = "vcamio";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp3_reg: ldo_vgp3 {
+ regulator-compatible = "ldo_vgp3";
+ regulator-name = "vcamaf";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp4_reg: ldo_vgp4 {
+ regulator-compatible = "ldo_vgp4";
+ regulator-name = "vgp4";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp5_reg: ldo_vgp5 {
+ regulator-compatible = "ldo_vgp5";
+ regulator-name = "vgp5";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp6_reg: ldo_vgp6 {
+ regulator-compatible = "ldo_vgp6";
+ regulator-name = "vgp6";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vibr_reg: ldo_vibr {
+ regulator-compatible = "ldo_vibr";
+ regulator-name = "vibr";
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+ };
+ };
+};
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 7/8] mfd: Add support for the MediaTek MT6397 PMIC
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
` (5 preceding siblings ...)
2015-01-20 9:47 ` [PATCH 6/8] ARM: dts: mt8135-evbp1: Add PMIC support Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator Sascha Hauer
7 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown, Flora Fu,
Sascha Hauer
From: Flora Fu <flora.fu@mediatek.com>
This adds support for the MediaTek MT6397 PMIC. This is a
multifunction device with the following sub modules:
- Regulator
- RTC
- Audio codec
- GPIO
- Clock
It is interfaced to the host controller using SPI interface by a proprietary
hardware called PMIC wrapper or pwrap. MT6397 MFD is a child device of the
pwrap.
Signed-off-by: Flora Fu, MediaTek
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Lee Jones <lee.jones@linaro.org>
---
Documentation/devicetree/bindings/mfd/mt6397.txt | 75 +++++
drivers/mfd/Kconfig | 10 +
drivers/mfd/Makefile | 1 +
drivers/mfd/mt6397-core.c | 251 ++++++++++++++++
include/linux/mfd/mt6397/core.h | 76 +++++
include/linux/mfd/mt6397/registers.h | 362 +++++++++++++++++++++++
6 files changed, 775 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/mt6397.txt
create mode 100644 drivers/mfd/mt6397-core.c
create mode 100644 include/linux/mfd/mt6397/core.h
create mode 100644 include/linux/mfd/mt6397/registers.h
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
new file mode 100644
index 0000000..64ef408
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -0,0 +1,75 @@
+MediaTek MT6397 Multifunction Device Driver
+
+MT6397 is a multifunction device with the following sub modules:
+- Regulator
+- RTC
+- Audio codec
+- GPIO
+- Clock
+
+It is interfaced to host controller using SPI interface by a proprietary hardware
+called PMIC wrapper or pwrap. MT6397 MFD is a child device of pwrap.
+See the following for pwarp node definitions:
+Documentation/devicetree/bindings/soc/mediatek,mt8135-pwrap.txt
+
+This document describes the binding for mfd device and its sub module.
+
+Required properties:
+compatible: "mediatek,mt6397"
+
+Optional properties:
+- codec: Audio codec
+- pinctrl: GPIO in mt6397
+- rtc: RTC
+- clock: clocks in mt6397
+- regulators: regulators in mt6397
+
+Example:
+ pwrap: pwrap@1000f000 {
+ compatible = "mediatek,mt8135-pwrap";
+ reg = <0 0x1000f000 0 0x1000>,
+ <0 0x11017000 0 0x1000>;
+ reg-names = "pwrap-base", "pwrap-bridge-base";
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&infrarst MT8135_INFRA_PMIC_WRAP_RST>,
+ <&perirst MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
+ reset-names = "infra-pwrap-rst",
+ "peri-pwrap-bridge-rst";
+ clocks = <&pmicspi_sel>, <&clk26m>;
+ clock-names = "pmicspi-sel", "pmicspi-parent";
+
+ pmic {
+ compatible = "mediatek,mt6397";
+
+ codec: mt6397codec {
+ compatible = "mediatek,mt6397-codec";
+ };
+
+ pinctrl@0x0000C000 {
+ compatible = "mediatek,mt6397-pinctrl";
+ reg = <0 0x0000C000 0 0x0108>;
+ gpio-controller;
+ };
+
+ mt6397regulator: mt6397regulator {
+ compatible = "mediatek,mt6397-regulator";
+
+ mt6397_vpca15_reg: buck_vpca15 {
+ regulator-compatible = "buck_vpca15";
+ regulator-name = "vpca15";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ };
+
+ mt6397_vgp4_reg: ldo_vgp4 {
+ regulator-compatible = "ldo_vgp4";
+ regulator-name = "vgp4";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+ };
+ };
+ };
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2e6b731..7782e95 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -489,6 +489,16 @@ config MFD_MAX8998
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_MT6397
+ tristate "MediaTek MT6397 PMIC Support"
+ select MFD_CORE
+ select IRQ_DOMAIN
+ help
+ Say yes here to add support for MediaTek MT6397 PMIC. This is
+ a Power Management IC. This driver provides common support for
+ accessing the device; additional drivers must be enabled in order
+ to use the functionality of the device.
+
config MFD_MENF21BMC
tristate "MEN 14F021P00 Board Management Controller Support"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 53467e2..329d4ed 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -179,3 +179,4 @@ obj-$(CONFIG_MFD_DLN2) += dln2.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
+obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
new file mode 100644
index 0000000..f5db6f5
--- /dev/null
+++ b/drivers/mfd/mt6397-core.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6397/registers.h>
+
+static const struct mfd_cell mt6397_devs[] = {
+ {
+ .name = "mt6397-rtc",
+ .of_compatible = "mediatek,mt6397-rtc",
+ }, {
+ .name = "mt6397-regulator",
+ .of_compatible = "mediatek,mt6397-regulator",
+ }, {
+ .name = "mt6397-codec",
+ .of_compatible = "mediatek,mt6397-codec",
+ }, {
+ .name = "mt6397-clk",
+ .of_compatible = "mediatek,mt6397-clk",
+ },
+};
+
+static inline u32 mt6397_irq_shift(int irq)
+{
+ return irq & 0xf;
+}
+
+static inline u32 mt6397_irq_reg(int irq)
+{
+ return irq >> 4;
+}
+
+static void mt6397_irq_lock(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+
+ mutex_lock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_sync_unlock(struct irq_data *data)
+{
+ int i;
+ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+
+ regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
+ regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
+
+ mutex_unlock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_mask(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+ int shift = mt6397_irq_shift(data->hwirq);
+ int reg = mt6397_irq_reg(data->hwirq);
+ int reg_ofs = MT6397_INT_CON0 + reg * 2;
+
+ mt6397->irq_masks_cur[reg] &= ~(1 << shift);
+ regmap_write(mt6397->regmap, reg_ofs, mt6397->irq_masks_cur[reg]);
+}
+
+static void mt6397_irq_unmask(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+ int shift = mt6397_irq_shift(data->hwirq);
+ int reg = mt6397_irq_reg(data->hwirq);
+ int reg_ofs = MT6397_INT_CON0 + reg * 2;
+
+ mt6397->irq_masks_cur[reg] |= (1 << shift);
+ regmap_write(mt6397->regmap, reg_ofs, mt6397->irq_masks_cur[reg]);
+}
+
+static void mt6397_irq_ack(struct irq_data *data)
+{
+ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+ int shift = mt6397_irq_shift(data->hwirq);
+ int reg = mt6397_irq_reg(data->hwirq);
+ int reg_ofs = MT6397_INT_STATUS0 + reg * 2;
+
+ regmap_write(mt6397->regmap, reg_ofs, 1 << shift);
+}
+
+static struct irq_chip mt6397_irq_chip = {
+ .name = "mt6397-irq",
+ .irq_bus_lock = mt6397_irq_lock,
+ .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
+ .irq_mask = mt6397_irq_mask,
+ .irq_unmask = mt6397_irq_unmask,
+ .irq_ack = mt6397_irq_ack,
+};
+
+static irqreturn_t mt6397_irq_thread(int irq, void *data)
+{
+ struct mt6397_chip *mt6397 = data;
+ int irq_reg[MT6397_IRQ_GROUP_NR];
+ int i, cur_irq, ret;
+
+ for (i = 0; i < MT6397_IRQ_GROUP_NR; i++) {
+ ret = regmap_read(mt6397->regmap,
+ MT6397_INT_STATUS0 + i * 2, &irq_reg[i]);
+ if (ret > 0) {
+ dev_err(mt6397->dev,
+ "failed to read interrupt status [0x%x]\n",
+ MT6397_INT_STATUS0 + i * 2);
+ return IRQ_NONE;
+ }
+ }
+
+ for (i = 0; i < MT6397_IRQ_NR; i++) {
+ int shift = mt6397_irq_shift(i);
+ int reg = mt6397_irq_reg(i);
+ int reg_ofs = MT6397_INT_STATUS0 + reg * 2;
+
+ if (irq_reg[reg] & (1 << shift)) {
+ cur_irq = irq_find_mapping(mt6397->irq_domain, i);
+ if (cur_irq)
+ handle_nested_irq(cur_irq);
+
+ /* write 1 to status bit to clear the event. */
+ regmap_write(mt6397->regmap, reg_ofs, 1 << shift);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct mt6397_chip *mt6397 = d->host_data;
+
+ irq_set_chip_data(irq, mt6397);
+ irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
+ irq_set_nested_thread(irq, 1);
+ set_irq_flags(irq, IRQF_VALID);
+
+ return 0;
+}
+
+static struct irq_domain_ops mt6397_irq_domain_ops = {
+ .map = mt6397_irq_domain_map,
+};
+
+static int mt6397_irq_init(struct mt6397_chip *mt6397)
+{
+ int ret;
+
+ mutex_init(&mt6397->irqlock);
+
+ /* Mask all interrupt sources */
+ regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
+ regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
+
+ mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
+ MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
+ if (!mt6397->irq_domain) {
+ dev_err(mt6397->dev, "could not create irq domain\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
+ mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
+ if (ret) {
+ dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
+ mt6397->irq, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt6397_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct mt6397_chip *mt6397;
+
+ mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
+ if (!mt6397)
+ return -ENOMEM;
+
+ mt6397->dev = &pdev->dev;
+ /*
+ * mt6397 MFD is child device of soc pmic wrapper.
+ * Regmap is set from its parent.
+ */
+ mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!mt6397->regmap)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, mt6397);
+
+ mt6397->irq = platform_get_irq(pdev, 0);
+ if (mt6397->irq > 0) {
+ ret = mt6397_irq_init(mt6397);
+ if (ret)
+ return ret;
+ }
+
+ ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
+ ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
+ if (ret)
+ dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
+
+ return ret;
+}
+
+static int mt6397_remove(struct platform_device *pdev)
+{
+ mfd_remove_devices(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id mt6397_of_match[] = {
+ { .compatible = "mediatek,mt6397" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mt6397_of_match);
+
+static struct platform_driver mt6397_driver = {
+ .probe = mt6397_probe,
+ .remove = mt6397_remove,
+ .driver = {
+ .name = "mt6397",
+ .of_match_table = of_match_ptr(mt6397_of_match),
+ },
+};
+
+module_platform_driver(mt6397_driver);
+
+MODULE_AUTHOR("Flora Fu");
+MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt6397");
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
new file mode 100644
index 0000000..82380bb
--- /dev/null
+++ b/include/linux/mfd/mt6397/core.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu <flora.fu@mediatek.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_MT6397_CORE_H__
+#define __MFD_MT6397_CORE_H__
+
+enum PMIC_INT_CON_GRP {
+ GRP_INT_CON0 = 0,
+ GRP_INT_CON1,
+ MT6397_IRQ_GROUP_NR,
+};
+
+enum PMIC_INT_STATUS_GRP {
+ GRP_INT_STATUS0 = 0,
+ GRP_INT_STATUS1,
+ MT6397_IRQ_STATUS_GROUP_NR,
+};
+
+enum PMIC_INT_STATUS {
+ RG_INT_STATUS_SPKL_AB = 0,
+ RG_INT_STATUS_SPKR_AB,
+ RG_INT_STATUS_SPKL,
+ RG_INT_STATUS_SPKR,
+ RG_INT_STATUS_BAT_L,
+ RG_INT_STATUS_BAT_H,
+ RG_INT_STATUS_FG_BAT_L,
+ RG_INT_STATUS_FG_BAT_H,
+ RG_INT_STATUS_WATCHDOG,
+ RG_INT_STATUS_PWRKEY,
+ RG_INT_STATUS_THR_L,
+ RG_INT_STATUS_THR_H,
+ RG_INT_STATUS_VBATON_UNDET,
+ RG_INT_STATUS_BVALID_DET,
+ RG_INT_STATUS_CHRDET,
+ RG_INT_STATUS_OV,
+ RG_INT_STATUS_LDO,
+ RG_INT_STATUS_HOMEKEY,
+ RG_INT_STATUS_ACCDET,
+ RG_INT_STATUS_AUDIO,
+ RG_INT_STATUS_RTC,
+ RG_INT_STATUS_PWRKEY_RSTB,
+ RG_INT_STATUS_HDMI_SIFM,
+ RG_INT_STATUS_HDMI_CEC,
+ RG_INT_STATUS_VCA15,
+ RG_INT_STATUS_VSRMCA15,
+ RG_INT_STATUS_VCORE,
+ RG_INT_STATUS_VGPU,
+ RG_INT_STATUS_VIO18,
+ RG_INT_STATUS_VPCA7,
+ RG_INT_STATUS_VSRMCA7,
+ RG_INT_STATUS_VDRM,
+ MT6397_IRQ_NR,
+};
+
+struct mt6397_chip {
+ struct device *dev;
+ struct regmap *regmap;
+ struct irq_domain *irq_domain;
+ struct mutex irqlock;
+ int irq;
+ u16 irq_masks_cur[MT6397_IRQ_GROUP_NR];
+ u16 irq_masks_cache[MT6397_IRQ_GROUP_NR];
+};
+
+#endif /* __MFD_MT6397_CORE_H__ */
diff --git a/include/linux/mfd/mt6397/registers.h b/include/linux/mfd/mt6397/registers.h
new file mode 100644
index 0000000..b39a5a5
--- /dev/null
+++ b/include/linux/mfd/mt6397/registers.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu <flora.fu@mediatek.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_MT6397_REGISTERS_H__
+#define __MFD_MT6397_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6397_CID 0x0100
+#define MT6397_TOP_CKPDN 0x0102
+#define MT6397_TOP_CKPDN_SET 0x0104
+#define MT6397_TOP_CKPDN_CLR 0x0106
+#define MT6397_TOP_CKPDN2 0x0108
+#define MT6397_TOP_CKPDN2_SET 0x010A
+#define MT6397_TOP_CKPDN2_CLR 0x010C
+#define MT6397_TOP_GPIO_CKPDN 0x010E
+#define MT6397_TOP_RST_CON 0x0114
+#define MT6397_WRP_CKPDN 0x011A
+#define MT6397_WRP_RST_CON 0x0120
+#define MT6397_TOP_RST_MISC 0x0126
+#define MT6397_TOP_CKCON1 0x0128
+#define MT6397_TOP_CKCON2 0x012A
+#define MT6397_TOP_CKTST1 0x012C
+#define MT6397_TOP_CKTST2 0x012E
+#define MT6397_OC_DEG_EN 0x0130
+#define MT6397_OC_CTL0 0x0132
+#define MT6397_OC_CTL1 0x0134
+#define MT6397_OC_CTL2 0x0136
+#define MT6397_INT_RSV 0x0138
+#define MT6397_TEST_CON0 0x013A
+#define MT6397_TEST_CON1 0x013C
+#define MT6397_STATUS0 0x013E
+#define MT6397_STATUS1 0x0140
+#define MT6397_PGSTATUS 0x0142
+#define MT6397_CHRSTATUS 0x0144
+#define MT6397_OCSTATUS0 0x0146
+#define MT6397_OCSTATUS1 0x0148
+#define MT6397_OCSTATUS2 0x014A
+#define MT6397_HDMI_PAD_IE 0x014C
+#define MT6397_TEST_OUT_L 0x014E
+#define MT6397_TEST_OUT_H 0x0150
+#define MT6397_TDSEL_CON 0x0152
+#define MT6397_RDSEL_CON 0x0154
+#define MT6397_GPIO_SMT_CON0 0x0156
+#define MT6397_GPIO_SMT_CON1 0x0158
+#define MT6397_GPIO_SMT_CON2 0x015A
+#define MT6397_GPIO_SMT_CON3 0x015C
+#define MT6397_DRV_CON0 0x015E
+#define MT6397_DRV_CON1 0x0160
+#define MT6397_DRV_CON2 0x0162
+#define MT6397_DRV_CON3 0x0164
+#define MT6397_DRV_CON4 0x0166
+#define MT6397_DRV_CON5 0x0168
+#define MT6397_DRV_CON6 0x016A
+#define MT6397_DRV_CON7 0x016C
+#define MT6397_DRV_CON8 0x016E
+#define MT6397_DRV_CON9 0x0170
+#define MT6397_DRV_CON10 0x0172
+#define MT6397_DRV_CON11 0x0174
+#define MT6397_DRV_CON12 0x0176
+#define MT6397_INT_CON0 0x0178
+#define MT6397_INT_CON1 0x017E
+#define MT6397_INT_STATUS0 0x0184
+#define MT6397_INT_STATUS1 0x0186
+#define MT6397_FQMTR_CON0 0x0188
+#define MT6397_FQMTR_CON1 0x018A
+#define MT6397_FQMTR_CON2 0x018C
+#define MT6397_EFUSE_DOUT_0_15 0x01C4
+#define MT6397_EFUSE_DOUT_16_31 0x01C6
+#define MT6397_EFUSE_DOUT_32_47 0x01C8
+#define MT6397_EFUSE_DOUT_48_63 0x01CA
+#define MT6397_SPI_CON 0x01CC
+#define MT6397_TOP_CKPDN3 0x01CE
+#define MT6397_TOP_CKCON3 0x01D4
+#define MT6397_EFUSE_DOUT_64_79 0x01D6
+#define MT6397_EFUSE_DOUT_80_95 0x01D8
+#define MT6397_EFUSE_DOUT_96_111 0x01DA
+#define MT6397_EFUSE_DOUT_112_127 0x01DC
+#define MT6397_EFUSE_DOUT_128_143 0x01DE
+#define MT6397_EFUSE_DOUT_144_159 0x01E0
+#define MT6397_EFUSE_DOUT_160_175 0x01E2
+#define MT6397_EFUSE_DOUT_176_191 0x01E4
+#define MT6397_EFUSE_DOUT_192_207 0x01E6
+#define MT6397_EFUSE_DOUT_208_223 0x01E8
+#define MT6397_EFUSE_DOUT_224_239 0x01EA
+#define MT6397_EFUSE_DOUT_240_255 0x01EC
+#define MT6397_EFUSE_DOUT_256_271 0x01EE
+#define MT6397_EFUSE_DOUT_272_287 0x01F0
+#define MT6397_EFUSE_DOUT_288_300 0x01F2
+#define MT6397_EFUSE_DOUT_304_319 0x01F4
+#define MT6397_BUCK_CON0 0x0200
+#define MT6397_BUCK_CON1 0x0202
+#define MT6397_BUCK_CON2 0x0204
+#define MT6397_BUCK_CON3 0x0206
+#define MT6397_BUCK_CON4 0x0208
+#define MT6397_BUCK_CON5 0x020A
+#define MT6397_BUCK_CON6 0x020C
+#define MT6397_BUCK_CON7 0x020E
+#define MT6397_BUCK_CON8 0x0210
+#define MT6397_BUCK_CON9 0x0212
+#define MT6397_VCA15_CON0 0x0214
+#define MT6397_VCA15_CON1 0x0216
+#define MT6397_VCA15_CON2 0x0218
+#define MT6397_VCA15_CON3 0x021A
+#define MT6397_VCA15_CON4 0x021C
+#define MT6397_VCA15_CON5 0x021E
+#define MT6397_VCA15_CON6 0x0220
+#define MT6397_VCA15_CON7 0x0222
+#define MT6397_VCA15_CON8 0x0224
+#define MT6397_VCA15_CON9 0x0226
+#define MT6397_VCA15_CON10 0x0228
+#define MT6397_VCA15_CON11 0x022A
+#define MT6397_VCA15_CON12 0x022C
+#define MT6397_VCA15_CON13 0x022E
+#define MT6397_VCA15_CON14 0x0230
+#define MT6397_VCA15_CON15 0x0232
+#define MT6397_VCA15_CON16 0x0234
+#define MT6397_VCA15_CON17 0x0236
+#define MT6397_VCA15_CON18 0x0238
+#define MT6397_VSRMCA15_CON0 0x023A
+#define MT6397_VSRMCA15_CON1 0x023C
+#define MT6397_VSRMCA15_CON2 0x023E
+#define MT6397_VSRMCA15_CON3 0x0240
+#define MT6397_VSRMCA15_CON4 0x0242
+#define MT6397_VSRMCA15_CON5 0x0244
+#define MT6397_VSRMCA15_CON6 0x0246
+#define MT6397_VSRMCA15_CON7 0x0248
+#define MT6397_VSRMCA15_CON8 0x024A
+#define MT6397_VSRMCA15_CON9 0x024C
+#define MT6397_VSRMCA15_CON10 0x024E
+#define MT6397_VSRMCA15_CON11 0x0250
+#define MT6397_VSRMCA15_CON12 0x0252
+#define MT6397_VSRMCA15_CON13 0x0254
+#define MT6397_VSRMCA15_CON14 0x0256
+#define MT6397_VSRMCA15_CON15 0x0258
+#define MT6397_VSRMCA15_CON16 0x025A
+#define MT6397_VSRMCA15_CON17 0x025C
+#define MT6397_VSRMCA15_CON18 0x025E
+#define MT6397_VSRMCA15_CON19 0x0260
+#define MT6397_VSRMCA15_CON20 0x0262
+#define MT6397_VSRMCA15_CON21 0x0264
+#define MT6397_VCORE_CON0 0x0266
+#define MT6397_VCORE_CON1 0x0268
+#define MT6397_VCORE_CON2 0x026A
+#define MT6397_VCORE_CON3 0x026C
+#define MT6397_VCORE_CON4 0x026E
+#define MT6397_VCORE_CON5 0x0270
+#define MT6397_VCORE_CON6 0x0272
+#define MT6397_VCORE_CON7 0x0274
+#define MT6397_VCORE_CON8 0x0276
+#define MT6397_VCORE_CON9 0x0278
+#define MT6397_VCORE_CON10 0x027A
+#define MT6397_VCORE_CON11 0x027C
+#define MT6397_VCORE_CON12 0x027E
+#define MT6397_VCORE_CON13 0x0280
+#define MT6397_VCORE_CON14 0x0282
+#define MT6397_VCORE_CON15 0x0284
+#define MT6397_VCORE_CON16 0x0286
+#define MT6397_VCORE_CON17 0x0288
+#define MT6397_VCORE_CON18 0x028A
+#define MT6397_VGPU_CON0 0x028C
+#define MT6397_VGPU_CON1 0x028E
+#define MT6397_VGPU_CON2 0x0290
+#define MT6397_VGPU_CON3 0x0292
+#define MT6397_VGPU_CON4 0x0294
+#define MT6397_VGPU_CON5 0x0296
+#define MT6397_VGPU_CON6 0x0298
+#define MT6397_VGPU_CON7 0x029A
+#define MT6397_VGPU_CON8 0x029C
+#define MT6397_VGPU_CON9 0x029E
+#define MT6397_VGPU_CON10 0x02A0
+#define MT6397_VGPU_CON11 0x02A2
+#define MT6397_VGPU_CON12 0x02A4
+#define MT6397_VGPU_CON13 0x02A6
+#define MT6397_VGPU_CON14 0x02A8
+#define MT6397_VGPU_CON15 0x02AA
+#define MT6397_VGPU_CON16 0x02AC
+#define MT6397_VGPU_CON17 0x02AE
+#define MT6397_VGPU_CON18 0x02B0
+#define MT6397_VIO18_CON0 0x0300
+#define MT6397_VIO18_CON1 0x0302
+#define MT6397_VIO18_CON2 0x0304
+#define MT6397_VIO18_CON3 0x0306
+#define MT6397_VIO18_CON4 0x0308
+#define MT6397_VIO18_CON5 0x030A
+#define MT6397_VIO18_CON6 0x030C
+#define MT6397_VIO18_CON7 0x030E
+#define MT6397_VIO18_CON8 0x0310
+#define MT6397_VIO18_CON9 0x0312
+#define MT6397_VIO18_CON10 0x0314
+#define MT6397_VIO18_CON11 0x0316
+#define MT6397_VIO18_CON12 0x0318
+#define MT6397_VIO18_CON13 0x031A
+#define MT6397_VIO18_CON14 0x031C
+#define MT6397_VIO18_CON15 0x031E
+#define MT6397_VIO18_CON16 0x0320
+#define MT6397_VIO18_CON17 0x0322
+#define MT6397_VIO18_CON18 0x0324
+#define MT6397_VPCA7_CON0 0x0326
+#define MT6397_VPCA7_CON1 0x0328
+#define MT6397_VPCA7_CON2 0x032A
+#define MT6397_VPCA7_CON3 0x032C
+#define MT6397_VPCA7_CON4 0x032E
+#define MT6397_VPCA7_CON5 0x0330
+#define MT6397_VPCA7_CON6 0x0332
+#define MT6397_VPCA7_CON7 0x0334
+#define MT6397_VPCA7_CON8 0x0336
+#define MT6397_VPCA7_CON9 0x0338
+#define MT6397_VPCA7_CON10 0x033A
+#define MT6397_VPCA7_CON11 0x033C
+#define MT6397_VPCA7_CON12 0x033E
+#define MT6397_VPCA7_CON13 0x0340
+#define MT6397_VPCA7_CON14 0x0342
+#define MT6397_VPCA7_CON15 0x0344
+#define MT6397_VPCA7_CON16 0x0346
+#define MT6397_VPCA7_CON17 0x0348
+#define MT6397_VPCA7_CON18 0x034A
+#define MT6397_VSRMCA7_CON0 0x034C
+#define MT6397_VSRMCA7_CON1 0x034E
+#define MT6397_VSRMCA7_CON2 0x0350
+#define MT6397_VSRMCA7_CON3 0x0352
+#define MT6397_VSRMCA7_CON4 0x0354
+#define MT6397_VSRMCA7_CON5 0x0356
+#define MT6397_VSRMCA7_CON6 0x0358
+#define MT6397_VSRMCA7_CON7 0x035A
+#define MT6397_VSRMCA7_CON8 0x035C
+#define MT6397_VSRMCA7_CON9 0x035E
+#define MT6397_VSRMCA7_CON10 0x0360
+#define MT6397_VSRMCA7_CON11 0x0362
+#define MT6397_VSRMCA7_CON12 0x0364
+#define MT6397_VSRMCA7_CON13 0x0366
+#define MT6397_VSRMCA7_CON14 0x0368
+#define MT6397_VSRMCA7_CON15 0x036A
+#define MT6397_VSRMCA7_CON16 0x036C
+#define MT6397_VSRMCA7_CON17 0x036E
+#define MT6397_VSRMCA7_CON18 0x0370
+#define MT6397_VSRMCA7_CON19 0x0372
+#define MT6397_VSRMCA7_CON20 0x0374
+#define MT6397_VSRMCA7_CON21 0x0376
+#define MT6397_VDRM_CON0 0x0378
+#define MT6397_VDRM_CON1 0x037A
+#define MT6397_VDRM_CON2 0x037C
+#define MT6397_VDRM_CON3 0x037E
+#define MT6397_VDRM_CON4 0x0380
+#define MT6397_VDRM_CON5 0x0382
+#define MT6397_VDRM_CON6 0x0384
+#define MT6397_VDRM_CON7 0x0386
+#define MT6397_VDRM_CON8 0x0388
+#define MT6397_VDRM_CON9 0x038A
+#define MT6397_VDRM_CON10 0x038C
+#define MT6397_VDRM_CON11 0x038E
+#define MT6397_VDRM_CON12 0x0390
+#define MT6397_VDRM_CON13 0x0392
+#define MT6397_VDRM_CON14 0x0394
+#define MT6397_VDRM_CON15 0x0396
+#define MT6397_VDRM_CON16 0x0398
+#define MT6397_VDRM_CON17 0x039A
+#define MT6397_VDRM_CON18 0x039C
+#define MT6397_BUCK_K_CON0 0x039E
+#define MT6397_BUCK_K_CON1 0x03A0
+#define MT6397_ANALDO_CON0 0x0400
+#define MT6397_ANALDO_CON1 0x0402
+#define MT6397_ANALDO_CON2 0x0404
+#define MT6397_ANALDO_CON3 0x0406
+#define MT6397_ANALDO_CON4 0x0408
+#define MT6397_ANALDO_CON5 0x040A
+#define MT6397_ANALDO_CON6 0x040C
+#define MT6397_ANALDO_CON7 0x040E
+#define MT6397_DIGLDO_CON0 0x0410
+#define MT6397_DIGLDO_CON1 0x0412
+#define MT6397_DIGLDO_CON2 0x0414
+#define MT6397_DIGLDO_CON3 0x0416
+#define MT6397_DIGLDO_CON4 0x0418
+#define MT6397_DIGLDO_CON5 0x041A
+#define MT6397_DIGLDO_CON6 0x041C
+#define MT6397_DIGLDO_CON7 0x041E
+#define MT6397_DIGLDO_CON8 0x0420
+#define MT6397_DIGLDO_CON9 0x0422
+#define MT6397_DIGLDO_CON10 0x0424
+#define MT6397_DIGLDO_CON11 0x0426
+#define MT6397_DIGLDO_CON12 0x0428
+#define MT6397_DIGLDO_CON13 0x042A
+#define MT6397_DIGLDO_CON14 0x042C
+#define MT6397_DIGLDO_CON15 0x042E
+#define MT6397_DIGLDO_CON16 0x0430
+#define MT6397_DIGLDO_CON17 0x0432
+#define MT6397_DIGLDO_CON18 0x0434
+#define MT6397_DIGLDO_CON19 0x0436
+#define MT6397_DIGLDO_CON20 0x0438
+#define MT6397_DIGLDO_CON21 0x043A
+#define MT6397_DIGLDO_CON22 0x043C
+#define MT6397_DIGLDO_CON23 0x043E
+#define MT6397_DIGLDO_CON24 0x0440
+#define MT6397_DIGLDO_CON25 0x0442
+#define MT6397_DIGLDO_CON26 0x0444
+#define MT6397_DIGLDO_CON27 0x0446
+#define MT6397_DIGLDO_CON28 0x0448
+#define MT6397_DIGLDO_CON29 0x044A
+#define MT6397_DIGLDO_CON30 0x044C
+#define MT6397_DIGLDO_CON31 0x044E
+#define MT6397_DIGLDO_CON32 0x0450
+#define MT6397_DIGLDO_CON33 0x045A
+#define MT6397_SPK_CON0 0x0600
+#define MT6397_SPK_CON1 0x0602
+#define MT6397_SPK_CON2 0x0604
+#define MT6397_SPK_CON3 0x0606
+#define MT6397_SPK_CON4 0x0608
+#define MT6397_SPK_CON5 0x060A
+#define MT6397_SPK_CON6 0x060C
+#define MT6397_SPK_CON7 0x060E
+#define MT6397_SPK_CON8 0x0610
+#define MT6397_SPK_CON9 0x0612
+#define MT6397_SPK_CON10 0x0614
+#define MT6397_SPK_CON11 0x0616
+#define MT6397_AUDDAC_CON0 0x0700
+#define MT6397_AUDBUF_CFG0 0x0702
+#define MT6397_AUDBUF_CFG1 0x0704
+#define MT6397_AUDBUF_CFG2 0x0706
+#define MT6397_AUDBUF_CFG3 0x0708
+#define MT6397_AUDBUF_CFG4 0x070A
+#define MT6397_IBIASDIST_CFG0 0x070C
+#define MT6397_AUDACCDEPOP_CFG0 0x070E
+#define MT6397_AUD_IV_CFG0 0x0710
+#define MT6397_AUDCLKGEN_CFG0 0x0712
+#define MT6397_AUDLDO_CFG0 0x0714
+#define MT6397_AUDLDO_CFG1 0x0716
+#define MT6397_AUDNVREGGLB_CFG0 0x0718
+#define MT6397_AUD_NCP0 0x071A
+#define MT6397_AUDPREAMP_CON0 0x071C
+#define MT6397_AUDADC_CON0 0x071E
+#define MT6397_AUDADC_CON1 0x0720
+#define MT6397_AUDADC_CON2 0x0722
+#define MT6397_AUDADC_CON3 0x0724
+#define MT6397_AUDADC_CON4 0x0726
+#define MT6397_AUDADC_CON5 0x0728
+#define MT6397_AUDADC_CON6 0x072A
+#define MT6397_AUDDIGMI_CON0 0x072C
+#define MT6397_AUDLSBUF_CON0 0x072E
+#define MT6397_AUDLSBUF_CON1 0x0730
+#define MT6397_AUDENCSPARE_CON0 0x0732
+#define MT6397_AUDENCCLKSQ_CON0 0x0734
+#define MT6397_AUDPREAMPGAIN_CON0 0x0736
+#define MT6397_ZCD_CON0 0x0738
+#define MT6397_ZCD_CON1 0x073A
+#define MT6397_ZCD_CON2 0x073C
+#define MT6397_ZCD_CON3 0x073E
+#define MT6397_ZCD_CON4 0x0740
+#define MT6397_ZCD_CON5 0x0742
+#define MT6397_NCP_CLKDIV_CON0 0x0744
+#define MT6397_NCP_CLKDIV_CON1 0x0746
+
+#endif /* __MFD_MT6397_REGISTERS_H__ */
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
` (6 preceding siblings ...)
2015-01-20 9:47 ` [PATCH 7/8] mfd: Add support for the MediaTek MT6397 PMIC Sascha Hauer
@ 2015-01-20 9:47 ` Sascha Hauer
2015-01-20 10:07 ` Paul Bolle
2015-01-21 8:26 ` Sascha Hauer
7 siblings, 2 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 9:47 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown, Flora Fu,
Sascha Hauer, Liam Girdwood
From: Flora Fu <flora.fu@mediatek.com>
This adds support for the regulators on the MediaTek MT6397
Multifunction device.
Signed-off-by: Flora Fu, MediaTek
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
---
Documentation/devicetree/bindings/mfd/mt6397.txt | 41 ++-
.../bindings/regulator/mt6397-regulator.txt | 217 ++++++++++++++
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6397-regulator.c | 332 +++++++++++++++++++++
include/linux/regulator/mt6397-regulator.h | 49 +++
6 files changed, 626 insertions(+), 23 deletions(-)
create mode 100644 Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
create mode 100644 drivers/regulator/mt6397-regulator.c
create mode 100644 include/linux/regulator/mt6397-regulator.h
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
index 64ef408..25b40a6 100644
--- a/Documentation/devicetree/bindings/mfd/mt6397.txt
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -10,33 +10,34 @@ MT6397 is a multifunction device with the following sub modules:
It is interfaced to host controller using SPI interface by a proprietary hardware
called PMIC wrapper or pwrap. MT6397 MFD is a child device of pwrap.
See the following for pwarp node definitions:
-Documentation/devicetree/bindings/soc/mediatek,mt8135-pwrap.txt
+Documentation/devicetree/bindings/soc/pwrap.txt
This document describes the binding for mfd device and its sub module.
Required properties:
compatible: "mediatek,mt6397"
-Optional properties:
-- codec: Audio codec
-- pinctrl: GPIO in mt6397
-- rtc: RTC
-- clock: clocks in mt6397
-- regulators: regulators in mt6397
+Optional subnodes:
+
+- rtc:
+ Required properties:
+ - compatible: "mediatek,mt6397-rtc",
+- regulators
+ Required properties:
+ - compatible: "mediatek,mt6397-regulator",
+ see Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
+- codec
+ Required properties:
+ - compatible: "mediatek,mt6397-codec",
+- clk
+ Required properties:
+ - compatible: "mediatek,mt6397-clk",
Example:
pwrap: pwrap@1000f000 {
compatible = "mediatek,mt8135-pwrap";
- reg = <0 0x1000f000 0 0x1000>,
- <0 0x11017000 0 0x1000>;
- reg-names = "pwrap-base", "pwrap-bridge-base";
- interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
- resets = <&infrarst MT8135_INFRA_PMIC_WRAP_RST>,
- <&perirst MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
- reset-names = "infra-pwrap-rst",
- "peri-pwrap-bridge-rst";
- clocks = <&pmicspi_sel>, <&clk26m>;
- clock-names = "pmicspi-sel", "pmicspi-parent";
+
+ ...
pmic {
compatible = "mediatek,mt6397";
@@ -45,12 +46,6 @@ Example:
compatible = "mediatek,mt6397-codec";
};
- pinctrl@0x0000C000 {
- compatible = "mediatek,mt6397-pinctrl";
- reg = <0 0x0000C000 0 0x0108>;
- gpio-controller;
- };
-
mt6397regulator: mt6397regulator {
compatible = "mediatek,mt6397-regulator";
diff --git a/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
new file mode 100644
index 0000000..a42b1d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
@@ -0,0 +1,217 @@
+Mediatek MT6397 Regulator Driver
+
+Required properties:
+- compatible: "mediatek,mt6397-regulator"
+- mt6397regulator: List of regulators provided by this controller. It is named
+ according to its regulator type, buck_<name> and ldo_<name>.
+ The definition for each of these nodes is defined using the standard binding
+ for regulators at Documentation/devicetree/bindings/regulator/regulator.txt.
+
+The valid names for regulators are::
+BUCK:
+ buck_vpca15, buck_vpca7, buck_vsramca15, buck_vsramca7, buck_vcore, buck_vgpu,
+ buck_vdrm, buck_vio18
+LDO:
+ ldo_vtcxo, ldo_va28, ldo_vcama, ldo_vio28, ldo_vusb, ldo_vmc, ldo_vmch,
+ ldo_vemc3v3, ldo_vgp1, ldo_vgp2, ldo_vgp3, ldo_vgp4, ldo_vgp5, ldo_vgp6,
+ ldo_vibr
+
+Example:
+ pmic {
+ compatible = "mediatek,mt6397";
+
+ mt6397regulator: mt6397regulator {
+ compatible = "mediatek,mt6397-regulator";
+
+ mt6397_vpca15_reg: buck_vpca15 {
+ regulator-compatible = "buck_vpca15";
+ regulator-name = "vpca15";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <200>;
+ };
+
+ mt6397_vpca7_reg: buck_vpca7 {
+ regulator-compatible = "buck_vpca7";
+ regulator-name = "vpca7";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <115>;
+ };
+
+ mt6397_vsramca15_reg: buck_vsramca15 {
+ regulator-compatible = "buck_vsramca15";
+ regulator-name = "vsramca15";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <115>;
+
+ };
+
+ mt6397_vsramca7_reg: buck_vsramca7 {
+ regulator-compatible = "buck_vsramca7";
+ regulator-name = "vsramca7";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <115>;
+
+ };
+
+ mt6397_vcore_reg: buck_vcore {
+ regulator-compatible = "buck_vcore";
+ regulator-name = "vcore";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <115>;
+ };
+
+ mt6397_vgpu_reg: buck_vgpu {
+ regulator-compatible = "buck_vgpu";
+ regulator-name = "vgpu";
+ regulator-min-microvolt = < 700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <115>;
+ };
+
+ mt6397_vdrm_reg: buck_vdrm {
+ regulator-compatible = "buck_vdrm";
+ regulator-name = "vdrm";
+ regulator-min-microvolt = < 800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <500>;
+ };
+
+ mt6397_vio18_reg: buck_vio18 {
+ regulator-compatible = "buck_vio18";
+ regulator-name = "vio18";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2120000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <500>;
+ };
+
+ mt6397_vtcxo_reg: ldo_vtcxo {
+ regulator-compatible = "ldo_vtcxo";
+ regulator-name = "vtcxo";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <90>;
+ };
+
+ mt6397_va28_reg: ldo_va28 {
+ regulator-compatible = "ldo_va28";
+ regulator-name = "va28";
+ /* fixed output 2.8 V */
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vcama_reg: ldo_vcama {
+ regulator-compatible = "ldo_vcama";
+ regulator-name = "vcama";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vio28_reg: ldo_vio28 {
+ regulator-compatible = "ldo_vio28";
+ regulator-name = "vio28";
+ /* fixed output 2.8 V */
+ regulator-enable-ramp-delay = <240>;
+ };
+
+ mt6397_usb_reg: ldo_vusb {
+ regulator-compatible = "ldo_vusb";
+ regulator-name = "vusb";
+ /* fixed output 3.3 V */
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vmc_reg: ldo_vmc {
+ regulator-compatible = "ldo_vmc";
+ regulator-name = "vmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vmch_reg: ldo_vmch {
+ regulator-compatible = "ldo_vmch";
+ regulator-name = "vmch";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vemc_3v3_reg: ldo_vemc3v3 {
+ regulator-compatible = "ldo_vemc3v3";
+ regulator-name = "vemc_3v3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp1_reg: ldo_vgp1 {
+ regulator-compatible = "ldo_vgp1";
+ regulator-name = "vcamd";
+ regulator-min-microvolt = <1220000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <240>;
+ };
+
+ mt6397_vgp2_reg: ldo_vgp2 {
+ egulator-compatible = "ldo_vgp2";
+ regulator-name = "vcamio";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp3_reg: ldo_vgp3 {
+ regulator-compatible = "ldo_vgp3";
+ regulator-name = "vcamaf";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp4_reg: ldo_vgp4 {
+ regulator-compatible = "ldo_vgp4";
+ regulator-name = "vgp4";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp5_reg: ldo_vgp5 {
+ regulator-compatible = "ldo_vgp5";
+ regulator-name = "vgp5";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vgp6_reg: ldo_vgp6 {
+ regulator-compatible = "ldo_vgp6";
+ regulator-name = "vgp6";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+
+ mt6397_vibr_reg: ldo_vibr {
+ regulator-compatible = "ldo_vibr";
+ regulator-name = "vibr";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+ };
+ };
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c3a60b5..f622d06 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -433,6 +433,15 @@ config REGULATOR_MC13892
Say y here to support the regulators found on the Freescale MC13892
PMIC.
+config REGULATOR_MT6397
+ tristate "MediaTek MT6397 PMIC"
+ depends on MFD_MT6397
+ help
+ Say y here to select this option to enable the power regulator of
+ MediaTek MT6397 PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_PALMAS
tristate "TI Palmas PMIC Regulators"
depends on MFD_PALMAS
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 1f28ebf..1a0fbc3 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
+obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
new file mode 100644
index 0000000..a5b2f47
--- /dev/null
+++ b/drivers/regulator/mt6397-regulator.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu <flora.fu@mediatek.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6397/registers.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/mt6397-regulator.h>
+#include <linux/regulator/of_regulator.h>
+
+/*
+ * MT6397 regulators' information
+ *
+ * @desc: standard fields of regulator description.
+ * @qi: Mask for query enable signal status of regulators
+ * @vselon_reg: Register sections for hardware control mode of bucks
+ * @vselctrl_reg: Register for controlling the buck control mode.
+ * @vselctrl_mask: Mask for query buck's voltage control mode.
+ */
+struct mt6397_regulator_info {
+ struct regulator_desc desc;
+ u32 qi;
+ u32 vselon_reg;
+ u32 vselctrl_reg;
+ u32 vselctrl_mask;
+};
+
+#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
+ vosel, vosel_mask, voselon, vosel_ctrl) \
+[MT6397_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6397_volt_range_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6397_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min)/step + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(0), \
+ }, \
+ .qi = BIT(13), \
+ .vselon_reg = voselon, \
+ .vselctrl_reg = vosel_ctrl, \
+ .vselctrl_mask = BIT(1), \
+}
+
+#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
+ vosel_mask) \
+[MT6397_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6397_volt_table_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6397_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(ldo_volt_table), \
+ .volt_table = ldo_volt_table, \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ }, \
+ .qi = BIT(15), \
+}
+
+#define MT6397_REG_FIXED(match, vreg, enreg, enbit, volt) \
+[MT6397_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6397_volt_fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6397_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = 1, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(enbit), \
+ .min_uV = volt, \
+ }, \
+ .qi = BIT(15), \
+}
+
+static const struct regulator_linear_range buck_volt_range1[] = {
+ REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
+};
+
+static const struct regulator_linear_range buck_volt_range2[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
+};
+
+static const struct regulator_linear_range buck_volt_range3[] = {
+ REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
+};
+
+static const u32 ldo_volt_table1[] = {
+ 1500000, 1800000, 2500000, 2800000,
+};
+
+static const u32 ldo_volt_table2[] = {
+ 1800000, 3300000,
+};
+
+static const u32 ldo_volt_table3[] = {
+ 3000000, 3300000,
+};
+
+static const u32 ldo_volt_table4[] = {
+ 1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static const u32 ldo_volt_table5[] = {
+ 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static const u32 ldo_volt_table5_v2[] = {
+ 1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static const u32 ldo_volt_table6[] = {
+ 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
+};
+
+static const u32 ldo_volt_table7[] = {
+ 1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static int mt6397_get_status(struct regulator_dev *rdev)
+{
+ int ret;
+ u32 regval;
+ struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(rdev->regmap, info->desc.enable_reg, ®val);
+ if (ret != 0) {
+ dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
+ return ret;
+ }
+
+ return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
+}
+
+static struct regulator_ops mt6397_volt_range_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6397_get_status,
+};
+
+static struct regulator_ops mt6397_volt_table_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6397_get_status,
+};
+
+static struct regulator_ops mt6397_volt_fixed_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6397_get_status,
+};
+
+/* The array is indexed by id(MT6397_ID_XXX) */
+static struct mt6397_regulator_info mt6397_regulators[] = {
+ MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
+ buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
+ MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+ MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
+ buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
+ MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+ MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
+ buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
+ 0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+ MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
+ buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
+ 0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+ MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
+ buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
+ MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+ MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
+ MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
+ MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+ MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
+ MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
+ MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+ MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
+ buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
+ MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+ MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
+ MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
+ MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
+ MT6397_ANALDO_CON2, 15, MT6397_ANALDO_CON6, 0xC0),
+ MT6397_REG_FIXED("ldo_vio28", VIO28, MT6397_DIGLDO_CON0, 14, 2800000),
+ MT6397_REG_FIXED("ldo_vusb", VUSB, MT6397_DIGLDO_CON1, 14, 3300000),
+ MT6397_LDO("ldo_vmc", VMC, ldo_volt_table2,
+ MT6397_DIGLDO_CON2, 12, MT6397_DIGLDO_CON29, 0x10),
+ MT6397_LDO("ldo_vmch", VMCH, ldo_volt_table3,
+ MT6397_DIGLDO_CON3, 14, MT6397_DIGLDO_CON17, 0x80),
+ MT6397_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table3,
+ MT6397_DIGLDO_CON4, 14, MT6397_DIGLDO_CON18, 0x10),
+ MT6397_LDO("ldo_vgp1", VGP1, ldo_volt_table4,
+ MT6397_DIGLDO_CON5, 15, MT6397_DIGLDO_CON19, 0xE0),
+ MT6397_LDO("ldo_vgp2", VGP2, ldo_volt_table5,
+ MT6397_DIGLDO_CON6, 15, MT6397_DIGLDO_CON20, 0xE0),
+ MT6397_LDO("ldo_vgp3", VGP3, ldo_volt_table5,
+ MT6397_DIGLDO_CON7, 15, MT6397_DIGLDO_CON21, 0xE0),
+ MT6397_LDO("ldo_vgp4", VGP4, ldo_volt_table5,
+ MT6397_DIGLDO_CON8, 15, MT6397_DIGLDO_CON22, 0xE0),
+ MT6397_LDO("ldo_vgp5", VGP5, ldo_volt_table6,
+ MT6397_DIGLDO_CON9, 15, MT6397_DIGLDO_CON23, 0xE0),
+ MT6397_LDO("ldo_vgp6", VGP6, ldo_volt_table5,
+ MT6397_DIGLDO_CON10, 15, MT6397_DIGLDO_CON33, 0xE0),
+ MT6397_LDO("ldo_vibr", VIBR, ldo_volt_table7,
+ MT6397_DIGLDO_CON24, 15, MT6397_DIGLDO_CON25, 0xE00),
+};
+
+static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
+{
+ struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
+ int i;
+ u32 regval;
+
+ for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
+ if (mt6397_regulators[i].vselctrl_reg) {
+ if (regmap_read(mt6397->regmap,
+ mt6397_regulators[i].vselctrl_reg,
+ ®val) < 0) {
+ dev_err(&pdev->dev,
+ "Failed to read buck ctrl\n");
+ return -EIO;
+ }
+
+ if (regval & mt6397_regulators[i].vselctrl_mask) {
+ mt6397_regulators[i].desc.vsel_reg =
+ mt6397_regulators[i].vselon_reg;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mt6397_regulator_probe(struct platform_device *pdev)
+{
+ struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+ int i;
+ u32 reg_value, version;
+
+ /* Query buck controller to select activated voltage register part */
+ if (mt6397_set_buck_vosel_reg(pdev))
+ return -EIO;
+
+ /* Read PMIC chip revision to update constraints and voltage table */
+ if (regmap_read(mt6397->regmap, MT6397_CID, ®_value) < 0) {
+ dev_err(&pdev->dev, "Failed to read Chip ID\n");
+ return -EIO;
+ }
+ dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
+
+ version = (reg_value & 0xFF);
+ switch (version) {
+ case MT6397_REGULATOR_ID91:
+ mt6397_regulators[MT6397_ID_VGP2].desc.volt_table =
+ ldo_volt_table5_v2;
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
+ config.dev = &pdev->dev;
+ config.driver_data = &mt6397_regulators[i];
+ config.regmap = mt6397->regmap;
+ rdev = devm_regulator_register(&pdev->dev,
+ &mt6397_regulators[i].desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ mt6397_regulators[i].desc.name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static struct platform_driver mt6397_regulator_driver = {
+ .driver = {
+ .name = "mt6397-regulator",
+ },
+ .probe = mt6397_regulator_probe,
+};
+
+module_platform_driver(mt6397_regulator_driver);
+
+MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
+MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt6397-regulator");
diff --git a/include/linux/regulator/mt6397-regulator.h b/include/linux/regulator/mt6397-regulator.h
new file mode 100644
index 0000000..30cc596
--- /dev/null
+++ b/include/linux/regulator/mt6397-regulator.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu <flora.fu@mediatek.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_REGULATOR_MT6397_H
+#define __LINUX_REGULATOR_MT6397_H
+
+enum {
+ MT6397_ID_VPCA15 = 0,
+ MT6397_ID_VPCA7,
+ MT6397_ID_VSRAMCA15,
+ MT6397_ID_VSRAMCA7,
+ MT6397_ID_VCORE,
+ MT6397_ID_VGPU,
+ MT6397_ID_VDRM,
+ MT6397_ID_VIO18 = 7,
+ MT6397_ID_VTCXO,
+ MT6397_ID_VA28,
+ MT6397_ID_VCAMA,
+ MT6397_ID_VIO28,
+ MT6397_ID_VUSB,
+ MT6397_ID_VMC,
+ MT6397_ID_VMCH,
+ MT6397_ID_VEMC3V3,
+ MT6397_ID_VGP1,
+ MT6397_ID_VGP2,
+ MT6397_ID_VGP3,
+ MT6397_ID_VGP4,
+ MT6397_ID_VGP5,
+ MT6397_ID_VGP6,
+ MT6397_ID_VIBR,
+ MT6397_ID_RG_MAX,
+};
+
+#define MT6397_MAX_REGULATOR MT6397_ID_RG_MAX
+#define MT6397_REGULATOR_ID97 0x97
+#define MT6397_REGULATOR_ID91 0x91
+
+#endif /* __LINUX_REGULATOR_MT6397_H */
--
2.1.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator
2015-01-20 9:47 ` [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator Sascha Hauer
@ 2015-01-20 10:07 ` Paul Bolle
2015-01-20 10:54 ` Sascha Hauer
2015-01-21 8:26 ` Sascha Hauer
1 sibling, 1 reply; 18+ messages in thread
From: Paul Bolle @ 2015-01-20 10:07 UTC (permalink / raw)
To: Sascha Hauer
Cc: Olof Johansson, Arnd Bergmann, linux-arm-kernel, linux-kernel,
Rob Herring, Eddie Huang, Matthias Brugger, Samuel Ortiz,
Lee Jones, Mark Brown, Flora Fu, Liam Girdwood
On Tue, 2015-01-20 at 10:47 +0100, Sascha Hauer wrote:
> From: Flora Fu <flora.fu@mediatek.com>
>
> This adds support for the regulators on the MediaTek MT6397
> Multifunction device.
>
> Signed-off-by: Flora Fu, MediaTek
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Liam Girdwood <lgirdwood@gmail.com>
> Cc: Mark Brown <broonie@kernel.org>
> ---
> Documentation/devicetree/bindings/mfd/mt6397.txt | 41 ++-
This looks new for linux-next ...
> .../bindings/regulator/mt6397-regulator.txt | 217 ++++++++++++++
but this is already in linux-next. See linux-next commit 269675757901
("regulator: Add document for MT6397 regulator"). And ...
> drivers/regulator/Kconfig | 9 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/mt6397-regulator.c | 332 +++++++++++++++++++++
> include/linux/regulator/mt6397-regulator.h | 49 +++
these are too. See linux-next commit 0425e2420c0a ("egulator: mt6397:
Add support for MT6397 regulator"). Unless there are difference that
can't be spotted by looking at the diffstats of those commist, that is.
I only noticed because I was looking at the progress of the patch that
adds MFD_MT6397, and found this series. (MFD_MT6397 is added in 7/8, by
the way.)
> 6 files changed, 626 insertions(+), 23 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
> create mode 100644 drivers/regulator/mt6397-regulator.c
> create mode 100644 include/linux/regulator/mt6397-regulator.h
Paul Bolle
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator
2015-01-20 10:07 ` Paul Bolle
@ 2015-01-20 10:54 ` Sascha Hauer
0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 10:54 UTC (permalink / raw)
To: Paul Bolle
Cc: Olof Johansson, Arnd Bergmann, linux-arm-kernel, linux-kernel,
Rob Herring, Eddie Huang, Matthias Brugger, Samuel Ortiz,
Lee Jones, Mark Brown, Liam Girdwood
On Tue, Jan 20, 2015 at 11:07:04AM +0100, Paul Bolle wrote:
> On Tue, 2015-01-20 at 10:47 +0100, Sascha Hauer wrote:
> > From: Flora Fu <flora.fu@mediatek.com>
> >
> > This adds support for the regulators on the MediaTek MT6397
> > Multifunction device.
> >
> > Signed-off-by: Flora Fu, MediaTek
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Liam Girdwood <lgirdwood@gmail.com>
> > Cc: Mark Brown <broonie@kernel.org>
> > ---
> > Documentation/devicetree/bindings/mfd/mt6397.txt | 41 ++-
>
> This looks new for linux-next ...
>
> > .../bindings/regulator/mt6397-regulator.txt | 217 ++++++++++++++
>
> but this is already in linux-next. See linux-next commit 269675757901
> ("regulator: Add document for MT6397 regulator"). And ...
>
> > drivers/regulator/Kconfig | 9 +
> > drivers/regulator/Makefile | 1 +
> > drivers/regulator/mt6397-regulator.c | 332 +++++++++++++++++++++
> > include/linux/regulator/mt6397-regulator.h | 49 +++
>
> these are too. See linux-next commit 0425e2420c0a ("egulator: mt6397:
> Add support for MT6397 regulator"). Unless there are difference that
> can't be spotted by looking at the diffstats of those commist, that is.
It seems Mark already merged the regulator part to his tree. Ok, in this
case you can ignore the regulator patch in this series. I think I haven't
made changes to the regulator part in this series.
The other patches are still needed though.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] soc: Add MediaTek pericfg controller support
2015-01-20 9:47 ` [PATCH 2/8] soc: Add MediaTek pericfg " Sascha Hauer
@ 2015-01-20 13:18 ` Yingjoe Chen
2015-01-20 13:27 ` Sascha Hauer
2015-01-20 16:15 ` Mark Rutland
1 sibling, 1 reply; 18+ messages in thread
From: Yingjoe Chen @ 2015-01-20 13:18 UTC (permalink / raw)
To: Sascha Hauer
Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz, Mark Brown,
linux-kernel, Rob Herring, Matthias Brugger, Eddie Huang,
Lee Jones, linux-arm-kernel
On Tue, 2015-01-20 at 10:47 +0100, Sascha Hauer wrote:
<...>
> diff --git a/drivers/soc/mediatek/mtk-pericfg.c b/drivers/soc/mediatek/mtk-pericfg.c
> index b7ee902..aa9a7eb 100644
> --- a/drivers/soc/mediatek/mtk-pericfg.c
> +++ b/drivers/soc/mediatek/mtk-pericfg.c
> @@ -1,6 +1,5 @@
> /*
> * Copyright (c) 2014 MediaTek Inc.
> - * Author: Flora Fu <flora.fu@mediatek.com>
> *
> * 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
Hi Sascha,
I believe you want to add mtk-pericfg.c here instead of adding it in
first patch and only change author here.
Joe.C
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] soc: Add MediaTek pericfg controller support
2015-01-20 13:18 ` Yingjoe Chen
@ 2015-01-20 13:27 ` Sascha Hauer
0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-20 13:27 UTC (permalink / raw)
To: Yingjoe Chen
Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz, Mark Brown,
linux-kernel, Rob Herring, Matthias Brugger, Eddie Huang,
Lee Jones, linux-arm-kernel
Hi Joe,
On Tue, Jan 20, 2015 at 09:18:30PM +0800, Yingjoe Chen wrote:
> On Tue, 2015-01-20 at 10:47 +0100, Sascha Hauer wrote:
> <...>
> > diff --git a/drivers/soc/mediatek/mtk-pericfg.c b/drivers/soc/mediatek/mtk-pericfg.c
> > index b7ee902..aa9a7eb 100644
> > --- a/drivers/soc/mediatek/mtk-pericfg.c
> > +++ b/drivers/soc/mediatek/mtk-pericfg.c
> > @@ -1,6 +1,5 @@
> > /*
> > * Copyright (c) 2014 MediaTek Inc.
> > - * Author: Flora Fu <flora.fu@mediatek.com>
> > *
> > * 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
>
> Hi Sascha,
>
> I believe you want to add mtk-pericfg.c here instead of adding it in
> first patch and only change author here.
Indeed. Fixed for the next round.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] soc: Add MediaTek infracfg controller support
2015-01-20 9:47 ` [PATCH 1/8] soc: Add MediaTek infracfg controller support Sascha Hauer
@ 2015-01-20 16:14 ` Mark Rutland
2015-01-21 8:14 ` Sascha Hauer
0 siblings, 1 reply; 18+ messages in thread
From: Mark Rutland @ 2015-01-20 16:14 UTC (permalink / raw)
To: Sascha Hauer
Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz, Mark Brown,
linux-kernel, Rob Herring, Matthias Brugger, Eddie Huang,
Lee Jones, linux-arm-kernel
On Tue, Jan 20, 2015 at 09:47:04AM +0000, Sascha Hauer wrote:
> This adds support for the MediaTek infracfg controller found
> on the MT8135/MT8173 SoCs. The infracfg controller contains
> miscellaneous registers for controlling peripheral resets and
> clocks.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> .../devicetree/bindings/soc/mediatek/infracfg.txt | 19 +++
> drivers/soc/Kconfig | 1 +
> drivers/soc/Makefile | 1 +
> drivers/soc/mediatek/Kconfig | 12 ++
> drivers/soc/mediatek/Makefile | 1 +
> drivers/soc/mediatek/mtk-infracfg.c | 127 ++++++++++++++++++++
> drivers/soc/mediatek/mtk-pericfg.c | 128 +++++++++++++++++++++
> 7 files changed, 289 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
> create mode 100644 drivers/soc/mediatek/Kconfig
> create mode 100644 drivers/soc/mediatek/Makefile
> create mode 100644 drivers/soc/mediatek/mtk-infracfg.c
> create mode 100644 drivers/soc/mediatek/mtk-pericfg.c
>
> diff --git a/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
> new file mode 100644
> index 0000000..042083a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
> @@ -0,0 +1,19 @@
> +MediaTek infracfg Controller
> +
> +The infracfg controller contains miscellaneous registers for controlling
> +clocks, resets and bus settings.
> +
> +Required properties:
> +- compatible: must be one of:
> + mediatek,mt8135-infracfg
> + mediatek,mt8173-infracfg
> +- reg: Address range for the infracfg controller
> +
> +Example:
> +
> + infracfg: infracfg@10003000 {
> + #reset-cells = <1>;
> + #clock-cells = <1>;
These weren't listed as required or optional above.
Please document these, along with the values a given clock-specifier or
reset-specifier may take.
> + compatible = "mediatek,mt8135-infracfg";
> + reg = <0 0x10003000 0 0x1000>;
> + };
Thanks,
Mark.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] soc: Add MediaTek pericfg controller support
2015-01-20 9:47 ` [PATCH 2/8] soc: Add MediaTek pericfg " Sascha Hauer
2015-01-20 13:18 ` Yingjoe Chen
@ 2015-01-20 16:15 ` Mark Rutland
2015-01-21 8:17 ` Sascha Hauer
1 sibling, 1 reply; 18+ messages in thread
From: Mark Rutland @ 2015-01-20 16:15 UTC (permalink / raw)
To: Sascha Hauer
Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz, Mark Brown,
linux-kernel, Rob Herring, Matthias Brugger, Eddie Huang,
Lee Jones, linux-arm-kernel
On Tue, Jan 20, 2015 at 09:47:05AM +0000, Sascha Hauer wrote:
> This adds support for the MediaTek pericfg controller found
> on the MT8135/MT8173 SoCs. The pericfg controller contains
> miscellaneous registers for controlling peripheral resets and
> clocks.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> .../devicetree/bindings/soc/mediatek/pericfg.txt | 19 +++++++++++++++++++
> drivers/soc/mediatek/Kconfig | 10 ++++++++++
> drivers/soc/mediatek/Makefile | 1 +
> drivers/soc/mediatek/mtk-pericfg.c | 1 -
> 4 files changed, 30 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
>
> diff --git a/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
> new file mode 100644
> index 0000000..81d1aee
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
> @@ -0,0 +1,19 @@
> +MediaTek pericfg Controller
> +
> +The pericfg controller contains miscellaneous registers for controlling
> +clocks, resets and bus settings.
> +
> +Required properties:
> +- compatible: must be one of:
> + mediatek,mt8135-pericfg
> + mediatek,mt8173-pericfg
> +- reg: Address range for the pericfg controller
> +
> +Example:
> +
> + pericfg: pericfg@10003000 {
> + #reset-cells = <1>;
> + #clock-cells = <1>;
> + compatible = "mediatek,mt8135-pericfg";
> + reg = <0 0x10003000 0 0x1000>;
> + };
This looks identical to the infracfg (same address too). Is that
deliberate?
Mark.
> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> index 3ad39fe..9bdb88f 100644
> --- a/drivers/soc/mediatek/Kconfig
> +++ b/drivers/soc/mediatek/Kconfig
> @@ -10,3 +10,13 @@ config MTK_INFRACFG
> contains several miscellaneous registers for clock, reset and bus
> settings. Say yes here if you want to run your kernel on one of these
> SoCs.
> +
> +config MTK_PERICFG
> + tristate "MediaTek pericfg controller support"
> + depends on ARCH_MEDIATEK || COMPILE_TEST
> + select REGMAP
> + help
> + The MediaTek pericfg controller found on MT8135 and MT8173 SoCs
> + contains several miscellaneous registers for clock, reset and bus
> + settings. Say yes here if you want to run your kernel on one of these
> + SoCs.
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index dbeb627..e67be7c 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1 +1,2 @@
> obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
> +obj-$(CONFIG_MTK_PERICFG) += mtk-pericfg.o
> diff --git a/drivers/soc/mediatek/mtk-pericfg.c b/drivers/soc/mediatek/mtk-pericfg.c
> index b7ee902..aa9a7eb 100644
> --- a/drivers/soc/mediatek/mtk-pericfg.c
> +++ b/drivers/soc/mediatek/mtk-pericfg.c
> @@ -1,6 +1,5 @@
> /*
> * Copyright (c) 2014 MediaTek Inc.
> - * Author: Flora Fu <flora.fu@mediatek.com>
> *
> * 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
> --
> 2.1.4
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] soc: Add MediaTek infracfg controller support
2015-01-20 16:14 ` Mark Rutland
@ 2015-01-21 8:14 ` Sascha Hauer
0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-21 8:14 UTC (permalink / raw)
To: Mark Rutland
Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz, Mark Brown,
linux-kernel, Rob Herring, Matthias Brugger, Eddie Huang,
Lee Jones, linux-arm-kernel
On Tue, Jan 20, 2015 at 04:14:03PM +0000, Mark Rutland wrote:
> On Tue, Jan 20, 2015 at 09:47:04AM +0000, Sascha Hauer wrote:
> > This adds support for the MediaTek infracfg controller found
> > on the MT8135/MT8173 SoCs. The infracfg controller contains
> > miscellaneous registers for controlling peripheral resets and
> > clocks.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> > .../devicetree/bindings/soc/mediatek/infracfg.txt | 19 +++
> > drivers/soc/Kconfig | 1 +
> > drivers/soc/Makefile | 1 +
> > drivers/soc/mediatek/Kconfig | 12 ++
> > drivers/soc/mediatek/Makefile | 1 +
> > drivers/soc/mediatek/mtk-infracfg.c | 127 ++++++++++++++++++++
> > drivers/soc/mediatek/mtk-pericfg.c | 128 +++++++++++++++++++++
> > 7 files changed, 289 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
> > create mode 100644 drivers/soc/mediatek/Kconfig
> > create mode 100644 drivers/soc/mediatek/Makefile
> > create mode 100644 drivers/soc/mediatek/mtk-infracfg.c
> > create mode 100644 drivers/soc/mediatek/mtk-pericfg.c
> >
> > diff --git a/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
> > new file mode 100644
> > index 0000000..042083a
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
> > @@ -0,0 +1,19 @@
> > +MediaTek infracfg Controller
> > +
> > +The infracfg controller contains miscellaneous registers for controlling
> > +clocks, resets and bus settings.
> > +
> > +Required properties:
> > +- compatible: must be one of:
> > + mediatek,mt8135-infracfg
> > + mediatek,mt8173-infracfg
> > +- reg: Address range for the infracfg controller
> > +
> > +Example:
> > +
> > + infracfg: infracfg@10003000 {
> > + #reset-cells = <1>;
> > + #clock-cells = <1>;
>
> These weren't listed as required or optional above.
>
> Please document these, along with the values a given clock-specifier or
> reset-specifier may take.
I documented #reset-cells and dropped #clock-cells for now.
Documentation for #clock-cells can be added along with the clock support
later.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] soc: Add MediaTek pericfg controller support
2015-01-20 16:15 ` Mark Rutland
@ 2015-01-21 8:17 ` Sascha Hauer
0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-21 8:17 UTC (permalink / raw)
To: Mark Rutland
Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz, Mark Brown,
linux-kernel, Rob Herring, Matthias Brugger, Eddie Huang,
Lee Jones, linux-arm-kernel
On Tue, Jan 20, 2015 at 04:15:55PM +0000, Mark Rutland wrote:
> > +
> > + pericfg: pericfg@10003000 {
> > + #reset-cells = <1>;
> > + #clock-cells = <1>;
> > + compatible = "mediatek,mt8135-pericfg";
> > + reg = <0 0x10003000 0 0x1000>;
> > + };
>
> This looks identical to the infracfg (same address too). Is that
> deliberate?
Both controllers indeed control clocks and resets, but with a different
register layout, so the nodes really look identical. I'll change the
address to the real address of the MT8135 pericfg though to make the
example more realistic.
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator
2015-01-20 9:47 ` [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator Sascha Hauer
2015-01-20 10:07 ` Paul Bolle
@ 2015-01-21 8:26 ` Sascha Hauer
1 sibling, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-01-21 8:26 UTC (permalink / raw)
To: Olof Johansson, Arnd Bergmann
Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
Matthias Brugger, Samuel Ortiz, Lee Jones, Mark Brown, Flora Fu,
Liam Girdwood
On Tue, Jan 20, 2015 at 10:47:11AM +0100, Sascha Hauer wrote:
> From: Flora Fu <flora.fu@mediatek.com>
>
> This adds support for the regulators on the MediaTek MT6397
> Multifunction device.
>
> Signed-off-by: Flora Fu, MediaTek
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Liam Girdwood <lgirdwood@gmail.com>
> Cc: Mark Brown <broonie@kernel.org>
> ---
> Documentation/devicetree/bindings/mfd/mt6397.txt | 41 ++-
> .../bindings/regulator/mt6397-regulator.txt | 217 ++++++++++++++
> drivers/regulator/Kconfig | 9 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/mt6397-regulator.c | 332 +++++++++++++++++++++
> include/linux/regulator/mt6397-regulator.h | 49 +++
> 6 files changed, 626 insertions(+), 23 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
> create mode 100644 drivers/regulator/mt6397-regulator.c
> create mode 100644 include/linux/regulator/mt6397-regulator.h
>
> diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
I'll move this documentation update to the patch adding the MFD driver
where it belongs to. I'll drop the reset of this patch since it's already
in Linux-next.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2015-01-21 8:26 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-20 9:47 MediaTek PMIC support Sascha Hauer
2015-01-20 9:47 ` [PATCH 1/8] soc: Add MediaTek infracfg controller support Sascha Hauer
2015-01-20 16:14 ` Mark Rutland
2015-01-21 8:14 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 2/8] soc: Add MediaTek pericfg " Sascha Hauer
2015-01-20 13:18 ` Yingjoe Chen
2015-01-20 13:27 ` Sascha Hauer
2015-01-20 16:15 ` Mark Rutland
2015-01-21 8:17 ` Sascha Hauer
2015-01-20 9:47 ` [PATCH 3/8] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines Sascha Hauer
2015-01-20 9:47 ` [PATCH 4/8] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC Sascha Hauer
2015-01-20 9:47 ` [PATCH 5/8] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes Sascha Hauer
2015-01-20 9:47 ` [PATCH 6/8] ARM: dts: mt8135-evbp1: Add PMIC support Sascha Hauer
2015-01-20 9:47 ` [PATCH 7/8] mfd: Add support for the MediaTek MT6397 PMIC Sascha Hauer
2015-01-20 9:47 ` [PATCH 8/8] regulator: MT6397: Add support for MT6397 regulator Sascha Hauer
2015-01-20 10:07 ` Paul Bolle
2015-01-20 10:54 ` Sascha Hauer
2015-01-21 8:26 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).