All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] MediaTek PMIC support
@ 2015-01-23 14:09 ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪)

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
patch is independent of the first 6 patches and can be merged through the
mfd maintainer trees.

Changes since v1:

- document reset bindings for infracfg/pericfg
- fix base addresses in infracfg binding example
- Remove more Email addresses from Flora Fu (She is not working at
  MediaTek anymore, her address is no longer valid)
- drop Regulator support patch, it's already in next

Sascha


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-23 14:09 ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

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
patch is independent of the first 6 patches and can be merged through the
mfd maintainer trees.

Changes since v1:

- document reset bindings for infracfg/pericfg
- fix base addresses in infracfg binding example
- Remove more Email addresses from Flora Fu (She is not working at
  MediaTek anymore, her address is no longer valid)
- drop Regulator support patch, it's already in next

Sascha

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 1/7] soc: Add MediaTek infracfg controller support
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:09   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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  |  29 +++++
 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 +++++++++++++++++++++
 6 files changed, 171 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

diff --git a/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
new file mode 100644
index 0000000..1912b83
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
@@ -0,0 +1,29 @@
+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
+- #reset-cells: 1, see below
+
+Specifying reset lines connected to the infracfg controller
+===========================================================
+
+The infracfg controller provides various reset sources to other modules.
+Device nodes using these reset sources should specify the reset lines in
+a property containing a phandle to the infracfg node and a reset index.
+See include/dt-bindings/reset-controller/<soc>-resets.h for a list of valid
+indices.
+
+Example:
+
+	infracfg: infracfg@10001000 {
+		#reset-cells = <1>;
+		compatible = "mediatek,mt8135-infracfg";
+		reg = <0 0x10001000 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");
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 1/7] soc: Add MediaTek infracfg controller support
@ 2015-01-23 14:09   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

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  |  29 +++++
 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 +++++++++++++++++++++
 6 files changed, 171 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

diff --git a/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
new file mode 100644
index 0000000..1912b83
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/infracfg.txt
@@ -0,0 +1,29 @@
+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
+- #reset-cells: 1, see below
+
+Specifying reset lines connected to the infracfg controller
+===========================================================
+
+The infracfg controller provides various reset sources to other modules.
+Device nodes using these reset sources should specify the reset lines in
+a property containing a phandle to the infracfg node and a reset index.
+See include/dt-bindings/reset-controller/<soc>-resets.h for a list of valid
+indices.
+
+Example:
+
+	infracfg: infracfg at 10001000 {
+		#reset-cells = <1>;
+		compatible = "mediatek,mt8135-infracfg";
+		reg = <0 0x10001000 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");
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 2/7] soc: Add MediaTek pericfg controller support
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:09   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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   |  29 +++++
 drivers/soc/mediatek/Kconfig                       |  10 ++
 drivers/soc/mediatek/Makefile                      |   1 +
 drivers/soc/mediatek/mtk-pericfg.c                 | 127 +++++++++++++++++++++
 4 files changed, 167 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
 create mode 100644 drivers/soc/mediatek/mtk-pericfg.c

diff --git a/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
new file mode 100644
index 0000000..3996e171
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
@@ -0,0 +1,29 @@
+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
+- #reset-cells: 1, see below
+
+Specifying reset lines connected to the pericfg controller
+==========================================================
+
+The infracfg controller provides various reset sources to other modules.
+Device nodes using these reset sources should specify the reset lines in
+a property containing a phandle to the infracfg node and a reset index.
+See include/dt-bindings/reset-controller/<soc>-resets.h for a list of valid
+indices.
+
+Example:
+
+	pericfg: pericfg@10003000 {
+		#reset-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
new file mode 100644
index 0000000..aa9a7eb
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pericfg.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_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 related	[flat|nested] 36+ messages in thread

* [PATCH 2/7] soc: Add MediaTek pericfg controller support
@ 2015-01-23 14:09   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

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   |  29 +++++
 drivers/soc/mediatek/Kconfig                       |  10 ++
 drivers/soc/mediatek/Makefile                      |   1 +
 drivers/soc/mediatek/mtk-pericfg.c                 | 127 +++++++++++++++++++++
 4 files changed, 167 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
 create mode 100644 drivers/soc/mediatek/mtk-pericfg.c

diff --git a/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
new file mode 100644
index 0000000..3996e171
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/pericfg.txt
@@ -0,0 +1,29 @@
+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
+- #reset-cells: 1, see below
+
+Specifying reset lines connected to the pericfg controller
+==========================================================
+
+The infracfg controller provides various reset sources to other modules.
+Device nodes using these reset sources should specify the reset lines in
+a property containing a phandle to the infracfg node and a reset index.
+See include/dt-bindings/reset-controller/<soc>-resets.h for a list of valid
+indices.
+
+Example:
+
+	pericfg: pericfg at 10003000 {
+		#reset-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
new file mode 100644
index 0000000..aa9a7eb
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pericfg.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_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 related	[flat|nested] 36+ messages in thread

* [PATCH 3/7] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:09   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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..1fb6295
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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..9464b37
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 related	[flat|nested] 36+ messages in thread

* [PATCH 3/7] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines
@ 2015-01-23 14:09   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

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..1fb6295
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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..9464b37
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 related	[flat|nested] 36+ messages in thread

* [PATCH 4/7] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:09   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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..77cdfd1
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -0,0 +1,1025 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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, MediaTek");
+MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver");
+MODULE_LICENSE("GPL");
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 4/7] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC
@ 2015-01-23 14:09   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

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 at 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..77cdfd1
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -0,0 +1,1025 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 at AP */
+	ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+	if (ret) {
+		dev_err(wrp->dev, "cipher data ready at AP fail, ret=%d\n", ret);
+		return ret;
+	}
+
+	/* wait for cipher data ready at PMIC */
+	ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready);
+	if (ret) {
+		dev_err(wrp->dev, "timeout waiting for cipher data ready at 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, MediaTek");
+MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver");
+MODULE_LICENSE("GPL");
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 5/7] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:10   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:10 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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 related	[flat|nested] 36+ messages in thread

* [PATCH 5/7] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes
@ 2015-01-23 14:10   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

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 at 10001000 {
+			#reset-cells = <1>;
+			#clock-cells = <1>;
+			compatible = "mediatek,mt8135-infracfg";
+			reg = <0 0x10001000 0 0x1000>;
+		};
+
+		pericfg: pericfg at 10003000 {
+			#reset-cells = <1>;
+			#clock-cells = <1>;
+			compatible = "mediatek,mt8135-pericfg";
+			reg = <0 0x10003000 0 0x1000>;
+		};
+
+		pwrap: pwrap at 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 at 10008000 {
 			compatible = "mediatek,mt8135-timer",
 					"mediatek,mt6577-timer";
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 6/7] ARM: dts: mt8135-evbp1: Add PMIC support
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:10   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:10 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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 related	[flat|nested] 36+ messages in thread

* [PATCH 6/7] ARM: dts: mt8135-evbp1: Add PMIC support
@ 2015-01-23 14:10   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

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 related	[flat|nested] 36+ messages in thread

* [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-23 14:10   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:10 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: linux-arm-kernel, linux-kernel, Rob Herring, Eddie Huang,
	Matthias Brugger, Samuel Ortiz, Lee Jones,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	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 |  70 +++++
 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, 770 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..25b40a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -0,0 +1,70 @@
+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/pwrap.txt
+
+This document describes the binding for mfd device and its sub module.
+
+Required properties:
+compatible: "mediatek,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";
+
+		...
+
+		pmic {
+			compatible = "mediatek,mt6397";
+
+			codec: mt6397codec {
+				compatible = "mediatek,mt6397-codec";
+			};
+
+			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..9710fca
--- /dev/null
+++ b/drivers/mfd/mt6397-core.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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, MediaTek");
+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..fa8fe24
--- /dev/null
+++ b/include/linux/mfd/mt6397/core.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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..f23a0a6
--- /dev/null
+++ b/include/linux/mfd/mt6397/registers.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 related	[flat|nested] 36+ messages in thread

* [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
@ 2015-01-23 14:10   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-23 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

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 |  70 +++++
 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, 770 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..25b40a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -0,0 +1,70 @@
+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/pwrap.txt
+
+This document describes the binding for mfd device and its sub module.
+
+Required properties:
+compatible: "mediatek,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 at 1000f000 {
+		compatible = "mediatek,mt8135-pwrap";
+
+		...
+
+		pmic {
+			compatible = "mediatek,mt6397";
+
+			codec: mt6397codec {
+				compatible = "mediatek,mt6397-codec";
+			};
+
+			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..9710fca
--- /dev/null
+++ b/drivers/mfd/mt6397-core.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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, MediaTek");
+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..fa8fe24
--- /dev/null
+++ b/include/linux/mfd/mt6397/core.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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..f23a0a6
--- /dev/null
+++ b/include/linux/mfd/mt6397/registers.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 related	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
  2015-01-23 14:10   ` Sascha Hauer
@ 2015-01-23 16:14     ` Lee Jones
  -1 siblings, 0 replies; 36+ messages in thread
From: Lee Jones @ 2015-01-23 16:14 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Olof Johansson, Arnd Bergmann, linux-arm-kernel, linux-kernel,
	Rob Herring, Eddie Huang, Matthias Brugger, Samuel Ortiz,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	Flora Fu

On Fri, 23 Jan 2015, Sascha Hauer wrote:

> 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 |  70 +++++

This should be submitted seperately, as per:

  Documentation/devicetree/bindings/submitting-patches.txt

>  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, 770 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..25b40a6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
> @@ -0,0 +1,70 @@
> +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/pwrap.txt
> +
> +This document describes the binding for mfd device and its sub module.

Nit: s/mfd/MFD/

> +Required properties:
> +compatible: "mediatek,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",

Nit: Titles with or without ':', as long as it's consistent.

Drop the comma at the end of each compatible line.

> +Example:
> +	pwrap: pwrap@1000f000 {
> +		compatible = "mediatek,mt8135-pwrap";
> +
> +		...
> +
> +		pmic {
> +			compatible = "mediatek,mt6397";
> +
> +			codec: mt6397codec {
> +				compatible = "mediatek,mt6397-codec";
> +			};
> +
> +			mt6397regulator: mt6397regulator {

s/mt6397regulator/regulator/

> +				compatible = "mediatek,mt6397-regulator";
> +
> +				mt6397_vpca15_reg: buck_vpca15 {
> +					regulator-compatible = "buck_vpca15";
> +					regulator-name = "vpca15";
> +					regulator-min-microvolt = < 850000>;

Attention to detail, whitespace.

> +					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..9710fca
> --- /dev/null
> +++ b/drivers/mfd/mt6397-core.c
> @@ -0,0 +1,251 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek

Email address?

> + * 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);

s/(1 << shift)/BIT(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);

As above.

> +	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);

Etc etc...

> +}
> +
> +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) {

Can regmap_read() return <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.  */

There are very few comments in the driver and _this_ is where it was
felt appropriate to do so?  If you put "MT6397_INT_STATUS0 + reg * 2"
directly into the call, the line will speak for itself.

Nit: There are also some whitespace issues going on.

> +			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, MediaTek");

Email.

> +MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
> +MODULE_LICENSE("GPL");

GPL v2

> +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..fa8fe24
> --- /dev/null
> +++ b/include/linux/mfd/mt6397/core.h
> @@ -0,0 +1,76 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * 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..f23a0a6
> --- /dev/null
> +++ b/include/linux/mfd/mt6397/registers.h
> @@ -0,0 +1,362 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * 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__ */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
@ 2015-01-23 16:14     ` Lee Jones
  0 siblings, 0 replies; 36+ messages in thread
From: Lee Jones @ 2015-01-23 16:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 23 Jan 2015, Sascha Hauer wrote:

> 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 |  70 +++++

This should be submitted seperately, as per:

  Documentation/devicetree/bindings/submitting-patches.txt

>  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, 770 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..25b40a6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
> @@ -0,0 +1,70 @@
> +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/pwrap.txt
> +
> +This document describes the binding for mfd device and its sub module.

Nit: s/mfd/MFD/

> +Required properties:
> +compatible: "mediatek,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",

Nit: Titles with or without ':', as long as it's consistent.

Drop the comma at the end of each compatible line.

> +Example:
> +	pwrap: pwrap at 1000f000 {
> +		compatible = "mediatek,mt8135-pwrap";
> +
> +		...
> +
> +		pmic {
> +			compatible = "mediatek,mt6397";
> +
> +			codec: mt6397codec {
> +				compatible = "mediatek,mt6397-codec";
> +			};
> +
> +			mt6397regulator: mt6397regulator {

s/mt6397regulator/regulator/

> +				compatible = "mediatek,mt6397-regulator";
> +
> +				mt6397_vpca15_reg: buck_vpca15 {
> +					regulator-compatible = "buck_vpca15";
> +					regulator-name = "vpca15";
> +					regulator-min-microvolt = < 850000>;

Attention to detail, whitespace.

> +					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..9710fca
> --- /dev/null
> +++ b/drivers/mfd/mt6397-core.c
> @@ -0,0 +1,251 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek

Email address?

> + * 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);

s/(1 << shift)/BIT(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);

As above.

> +	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);

Etc etc...

> +}
> +
> +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) {

Can regmap_read() return <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.  */

There are very few comments in the driver and _this_ is where it was
felt appropriate to do so?  If you put "MT6397_INT_STATUS0 + reg * 2"
directly into the call, the line will speak for itself.

Nit: There are also some whitespace issues going on.

> +			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, MediaTek");

Email.

> +MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
> +MODULE_LICENSE("GPL");

GPL v2

> +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..fa8fe24
> --- /dev/null
> +++ b/include/linux/mfd/mt6397/core.h
> @@ -0,0 +1,76 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * 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..f23a0a6
> --- /dev/null
> +++ b/include/linux/mfd/mt6397/registers.h
> @@ -0,0 +1,362 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * 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__ */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
  2015-01-23 16:14     ` Lee Jones
@ 2015-01-26 10:52       ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-26 10:52 UTC (permalink / raw)
  To: Lee Jones
  Cc: Olof Johansson, Arnd Bergmann, linux-arm-kernel, linux-kernel,
	Rob Herring, Eddie Huang, Matthias Brugger, Samuel Ortiz,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	Flora Fu

On Fri, Jan 23, 2015 at 04:14:40PM +0000, Lee Jones wrote:
> On Fri, 23 Jan 2015, Sascha Hauer wrote:
> 
> > 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 |  70 +++++
> 
> This should be submitted seperately, as per:
> 
>   Documentation/devicetree/bindings/submitting-patches.txt

I didn't know this document yet, thanks for noting. I thought it is still
acceptable to combine patches adding both code and the binding docs.

> 
> >  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, 770 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..25b40a6
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
> > @@ -0,0 +1,70 @@
> > +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/pwrap.txt
> > +
> > +This document describes the binding for mfd device and its sub module.
> 
> Nit: s/mfd/MFD/
> 
> > +Required properties:
> > +compatible: "mediatek,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",
> 
> Nit: Titles with or without ':', as long as it's consistent.
> 
> Drop the comma at the end of each compatible line.
> 
> > +Example:
> > +	pwrap: pwrap@1000f000 {
> > +		compatible = "mediatek,mt8135-pwrap";
> > +
> > +		...
> > +
> > +		pmic {
> > +			compatible = "mediatek,mt6397";
> > +
> > +			codec: mt6397codec {
> > +				compatible = "mediatek,mt6397-codec";
> > +			};
> > +
> > +			mt6397regulator: mt6397regulator {
> 
> s/mt6397regulator/regulator/

Dropped the label completely since consumers will point to the
individual regulators, not this node.

> > diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
> > new file mode 100644
> > index 0000000..9710fca
> > --- /dev/null
> > +++ b/drivers/mfd/mt6397-core.c
> > @@ -0,0 +1,251 @@
> > +/*
> > + * Copyright (c) 2014 MediaTek Inc.
> > + * Author: Flora Fu, MediaTek
> 
> Email address?

She does not work for MediaTek anymore. Her Email address is no longer
valid, so I removed it but kept her credits in the driver.

> > +{
> > +	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);
> 
> s/(1 << shift)/BIT(shift)/

Is it mentioned somewhere that these BIT macros shall be used? There are
quadrillions of examples for both styles in the kernel and personally I
think 1 << x is more readable.

> > +	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) {
> 
> Can regmap_read() return <0?

Yes, but not > 0 ;). Fixed.

> 
> > +			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.  */
> 
> There are very few comments in the driver and _this_ is where it was
> felt appropriate to do so?  If you put "MT6397_INT_STATUS0 + reg * 2"
> directly into the call, the line will speak for itself.

I refactored the code a bit, like write status reg once after handling
all interrupts and not after each interrupt. I also removed this comment
since it only states the obvious.

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] 36+ messages in thread

* [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
@ 2015-01-26 10:52       ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-26 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 23, 2015 at 04:14:40PM +0000, Lee Jones wrote:
> On Fri, 23 Jan 2015, Sascha Hauer wrote:
> 
> > 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 |  70 +++++
> 
> This should be submitted seperately, as per:
> 
>   Documentation/devicetree/bindings/submitting-patches.txt

I didn't know this document yet, thanks for noting. I thought it is still
acceptable to combine patches adding both code and the binding docs.

> 
> >  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, 770 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..25b40a6
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
> > @@ -0,0 +1,70 @@
> > +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/pwrap.txt
> > +
> > +This document describes the binding for mfd device and its sub module.
> 
> Nit: s/mfd/MFD/
> 
> > +Required properties:
> > +compatible: "mediatek,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",
> 
> Nit: Titles with or without ':', as long as it's consistent.
> 
> Drop the comma at the end of each compatible line.
> 
> > +Example:
> > +	pwrap: pwrap at 1000f000 {
> > +		compatible = "mediatek,mt8135-pwrap";
> > +
> > +		...
> > +
> > +		pmic {
> > +			compatible = "mediatek,mt6397";
> > +
> > +			codec: mt6397codec {
> > +				compatible = "mediatek,mt6397-codec";
> > +			};
> > +
> > +			mt6397regulator: mt6397regulator {
> 
> s/mt6397regulator/regulator/

Dropped the label completely since consumers will point to the
individual regulators, not this node.

> > diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
> > new file mode 100644
> > index 0000000..9710fca
> > --- /dev/null
> > +++ b/drivers/mfd/mt6397-core.c
> > @@ -0,0 +1,251 @@
> > +/*
> > + * Copyright (c) 2014 MediaTek Inc.
> > + * Author: Flora Fu, MediaTek
> 
> Email address?

She does not work for MediaTek anymore. Her Email address is no longer
valid, so I removed it but kept her credits in the driver.

> > +{
> > +	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);
> 
> s/(1 << shift)/BIT(shift)/

Is it mentioned somewhere that these BIT macros shall be used? There are
quadrillions of examples for both styles in the kernel and personally I
think 1 << x is more readable.

> > +	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) {
> 
> Can regmap_read() return <0?

Yes, but not > 0 ;). Fixed.

> 
> > +			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.  */
> 
> There are very few comments in the driver and _this_ is where it was
> felt appropriate to do so?  If you put "MT6397_INT_STATUS0 + reg * 2"
> directly into the call, the line will speak for itself.

I refactored the code a bit, like write status reg once after handling
all interrupts and not after each interrupt. I also removed this comment
since it only states the obvious.

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] 36+ messages in thread

* Re: [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
  2015-01-26 10:52       ` Sascha Hauer
@ 2015-01-26 11:11         ` Lee Jones
  -1 siblings, 0 replies; 36+ messages in thread
From: Lee Jones @ 2015-01-26 11:11 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Olof Johansson, Arnd Bergmann, linux-arm-kernel, linux-kernel,
	Rob Herring, Eddie Huang, Matthias Brugger, Samuel Ortiz,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	Flora Fu

On Mon, 26 Jan 2015, Sascha Hauer wrote:
> On Fri, Jan 23, 2015 at 04:14:40PM +0000, Lee Jones wrote:
> > On Fri, 23 Jan 2015, Sascha Hauer wrote:
> > 
> > > 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 |  70 +++++

[...]

> > > +	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);
> > 
> > s/(1 << shift)/BIT(shift)/
> 
> Is it mentioned somewhere that these BIT macros shall be used? There are
> quadrillions of examples for both styles in the kernel and personally I
> think 1 << x is more readable.

I haven't seen a hard and fast 'rule' per say.  I think it's left up
to the Maintainer of any given subsystem. ;)

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
@ 2015-01-26 11:11         ` Lee Jones
  0 siblings, 0 replies; 36+ messages in thread
From: Lee Jones @ 2015-01-26 11:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 26 Jan 2015, Sascha Hauer wrote:
> On Fri, Jan 23, 2015 at 04:14:40PM +0000, Lee Jones wrote:
> > On Fri, 23 Jan 2015, Sascha Hauer wrote:
> > 
> > > 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 |  70 +++++

[...]

> > > +	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);
> > 
> > s/(1 << shift)/BIT(shift)/
> 
> Is it mentioned somewhere that these BIT macros shall be used? There are
> quadrillions of examples for both styles in the kernel and personally I
> think 1 << x is more readable.

I haven't seen a hard and fast 'rule' per say.  I think it's left up
to the Maintainer of any given subsystem. ;)

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
  2015-01-26 11:11         ` Lee Jones
@ 2015-01-26 11:26           ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-26 11:26 UTC (permalink / raw)
  To: Lee Jones
  Cc: Olof Johansson, Arnd Bergmann, linux-arm-kernel, linux-kernel,
	Rob Herring, Eddie Huang, Matthias Brugger, Samuel Ortiz,
	Yingjoe Chen (陳英洲),
	Henry Chen, YH Chen (陳昱豪),
	Flora Fu

On Mon, Jan 26, 2015 at 11:11:19AM +0000, Lee Jones wrote:
> On Mon, 26 Jan 2015, Sascha Hauer wrote:
> > On Fri, Jan 23, 2015 at 04:14:40PM +0000, Lee Jones wrote:
> > > On Fri, 23 Jan 2015, Sascha Hauer wrote:
> > > > +	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);
> > > 
> > > s/(1 << shift)/BIT(shift)/
> > 
> > Is it mentioned somewhere that these BIT macros shall be used? There are
> > quadrillions of examples for both styles in the kernel and personally I
> > think 1 << x is more readable.
> 
> I haven't seen a hard and fast 'rule' per say.  I think it's left up
> to the Maintainer of any given subsystem. ;)

Ok, I know your opinion already, I hope Samuel has the same ;).
I'll change it to BIT().

Maybe I'll even change my personal opinion since I noticed that 1 << x
doesn't work for 64bit registers. Here 1UL << x must be used, but this
could easily be forgotten.

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] 36+ messages in thread

* [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC
@ 2015-01-26 11:26           ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-26 11:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 26, 2015 at 11:11:19AM +0000, Lee Jones wrote:
> On Mon, 26 Jan 2015, Sascha Hauer wrote:
> > On Fri, Jan 23, 2015 at 04:14:40PM +0000, Lee Jones wrote:
> > > On Fri, 23 Jan 2015, Sascha Hauer wrote:
> > > > +	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);
> > > 
> > > s/(1 << shift)/BIT(shift)/
> > 
> > Is it mentioned somewhere that these BIT macros shall be used? There are
> > quadrillions of examples for both styles in the kernel and personally I
> > think 1 << x is more readable.
> 
> I haven't seen a hard and fast 'rule' per say.  I think it's left up
> to the Maintainer of any given subsystem. ;)

Ok, I know your opinion already, I hope Samuel has the same ;).
I'll change it to BIT().

Maybe I'll even change my personal opinion since I noticed that 1 << x
doesn't work for 64bit registers. Here 1UL << x must be used, but this
could easily be forgotten.

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] 36+ messages in thread

* Re: [PATCH v2] MediaTek PMIC support
  2015-01-23 14:09 ` Sascha Hauer
@ 2015-01-26 11:47   ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-26 11:47 UTC (permalink / raw)
  To: Olof Johansson, Arnd Bergmann
  Cc: Samuel Ortiz, YH Chen (陳昱豪),
	linux-kernel, Henry Chen, Rob Herring, Matthias Brugger,
	Yingjoe Chen (陳英洲),
	Eddie Huang, Lee Jones, linux-arm-kernel

Olof, Arnd,

OK to put the driver into drivers/soc/mediatek? Can you take these
patches?

Sascha

On Fri, Jan 23, 2015 at 03:09:55PM +0100, Sascha Hauer wrote:
> 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
> patch is independent of the first 6 patches and can be merged through the
> mfd maintainer trees.
> 
> Changes since v1:
> 
> - document reset bindings for infracfg/pericfg
> - fix base addresses in infracfg binding example
> - Remove more Email addresses from Flora Fu (She is not working at
>   MediaTek anymore, her address is no longer valid)
> - drop Regulator support patch, it's already in next
> 
> Sascha
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
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] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-26 11:47   ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-26 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

Olof, Arnd,

OK to put the driver into drivers/soc/mediatek? Can you take these
patches?

Sascha

On Fri, Jan 23, 2015 at 03:09:55PM +0100, Sascha Hauer wrote:
> 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
> patch is independent of the first 6 patches and can be merged through the
> mfd maintainer trees.
> 
> Changes since v1:
> 
> - document reset bindings for infracfg/pericfg
> - fix base addresses in infracfg binding example
> - Remove more Email addresses from Flora Fu (She is not working at
>   MediaTek anymore, her address is no longer valid)
> - drop Regulator support patch, it's already in next
> 
> Sascha
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
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] 36+ messages in thread

* Re: [PATCH v2] MediaTek PMIC support
  2015-01-26 11:47   ` Sascha Hauer
@ 2015-01-29 12:39     ` Matthias Brugger
  -1 siblings, 0 replies; 36+ messages in thread
From: Matthias Brugger @ 2015-01-29 12:39 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz,
	YH Chen (陳昱豪),
	linux-kernel, Henry Chen, Rob Herring,
	Yingjoe Chen (陳英洲),
	Eddie Huang, Lee Jones, linux-arm-kernel, James Liao,
	Mike Turquette, Stephen Boyd

Hi Sascha,

2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> Olof, Arnd,
>
> OK to put the driver into drivers/soc/mediatek? Can you take these
> patches?

How does this patches fit together with the one James clock framework patches?
Both use the same compatible "mediatek,mt8135-infracfg" and
"mediatek,mt8135-pericfg".

I had a look on other implementations and they attach the reset
controller to the clk driver, if they share the same hw block.
Might we run into problems if we implement the clocks in the mfd, as
we need the clocks early in boot (e.g. for the timer)?

In mt6589 pericfg apart from the clocks and reset controller provides
registers for AXI bus control and USB wakeup and USB clock selection.
The infracfg block provides top AXI bus fabric control signals and
remap registers for the modem.
Mike, Stephen, what do you think. Can we implement the clk in a mfd
driver? Or do you prefer to implement the whole block in the clk
driver?

Cheers,
Matthias

>
> Sascha
>
> On Fri, Jan 23, 2015 at 03:09:55PM +0100, Sascha Hauer wrote:
>> 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
>> patch is independent of the first 6 patches and can be merged through the
>> mfd maintainer trees.
>>
>> Changes since v1:
>>
>> - document reset bindings for infracfg/pericfg
>> - fix base addresses in infracfg binding example
>> - Remove more Email addresses from Flora Fu (She is not working at
>>   MediaTek anymore, her address is no longer valid)
>> - drop Regulator support patch, it's already in next
>>
>> Sascha
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
> --
> 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 |



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-29 12:39     ` Matthias Brugger
  0 siblings, 0 replies; 36+ messages in thread
From: Matthias Brugger @ 2015-01-29 12:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha,

2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> Olof, Arnd,
>
> OK to put the driver into drivers/soc/mediatek? Can you take these
> patches?

How does this patches fit together with the one James clock framework patches?
Both use the same compatible "mediatek,mt8135-infracfg" and
"mediatek,mt8135-pericfg".

I had a look on other implementations and they attach the reset
controller to the clk driver, if they share the same hw block.
Might we run into problems if we implement the clocks in the mfd, as
we need the clocks early in boot (e.g. for the timer)?

In mt6589 pericfg apart from the clocks and reset controller provides
registers for AXI bus control and USB wakeup and USB clock selection.
The infracfg block provides top AXI bus fabric control signals and
remap registers for the modem.
Mike, Stephen, what do you think. Can we implement the clk in a mfd
driver? Or do you prefer to implement the whole block in the clk
driver?

Cheers,
Matthias

>
> Sascha
>
> On Fri, Jan 23, 2015 at 03:09:55PM +0100, Sascha Hauer wrote:
>> 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
>> patch is independent of the first 6 patches and can be merged through the
>> mfd maintainer trees.
>>
>> Changes since v1:
>>
>> - document reset bindings for infracfg/pericfg
>> - fix base addresses in infracfg binding example
>> - Remove more Email addresses from Flora Fu (She is not working at
>>   MediaTek anymore, her address is no longer valid)
>> - drop Regulator support patch, it's already in next
>>
>> Sascha
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
> --
> 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 |



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2] MediaTek PMIC support
  2015-01-29 12:39     ` Matthias Brugger
@ 2015-01-29 13:22       ` Matthias Brugger
  -1 siblings, 0 replies; 36+ messages in thread
From: Matthias Brugger @ 2015-01-29 13:22 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz,
	YH Chen (陳昱豪),
	linux-kernel, Henry Chen, Rob Herring,
	Yingjoe Chen (陳英洲),
	Eddie Huang, Lee Jones, linux-arm-kernel, James Liao,
	Mike Turquette, Stephen Boyd

2015-01-29 13:39 GMT+01:00 Matthias Brugger <matthias.bgg@gmail.com>:
> Hi Sascha,
>
> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
>> Olof, Arnd,
>>
>> OK to put the driver into drivers/soc/mediatek? Can you take these
>> patches?
>
> How does this patches fit together with the one James clock framework patches?

I forgot to send the link to the patches. Sorry for that. Here you are:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/313793.html

> Both use the same compatible "mediatek,mt8135-infracfg" and
> "mediatek,mt8135-pericfg".
>
> I had a look on other implementations and they attach the reset
> controller to the clk driver, if they share the same hw block.
> Might we run into problems if we implement the clocks in the mfd, as
> we need the clocks early in boot (e.g. for the timer)?
>
> In mt6589 pericfg apart from the clocks and reset controller provides
> registers for AXI bus control and USB wakeup and USB clock selection.
> The infracfg block provides top AXI bus fabric control signals and
> remap registers for the modem.
> Mike, Stephen, what do you think. Can we implement the clk in a mfd
> driver? Or do you prefer to implement the whole block in the clk
> driver?
>
> Cheers,
> Matthias
>
>>
>> Sascha
>>
>> On Fri, Jan 23, 2015 at 03:09:55PM +0100, Sascha Hauer wrote:
>>> 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
>>> patch is independent of the first 6 patches and can be merged through the
>>> mfd maintainer trees.
>>>
>>> Changes since v1:
>>>
>>> - document reset bindings for infracfg/pericfg
>>> - fix base addresses in infracfg binding example
>>> - Remove more Email addresses from Flora Fu (She is not working at
>>>   MediaTek anymore, her address is no longer valid)
>>> - drop Regulator support patch, it's already in next
>>>
>>> Sascha
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>>
>> --
>> 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 |
>
>
>
> --
> motzblog.wordpress.com



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-29 13:22       ` Matthias Brugger
  0 siblings, 0 replies; 36+ messages in thread
From: Matthias Brugger @ 2015-01-29 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

2015-01-29 13:39 GMT+01:00 Matthias Brugger <matthias.bgg@gmail.com>:
> Hi Sascha,
>
> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
>> Olof, Arnd,
>>
>> OK to put the driver into drivers/soc/mediatek? Can you take these
>> patches?
>
> How does this patches fit together with the one James clock framework patches?

I forgot to send the link to the patches. Sorry for that. Here you are:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/313793.html

> Both use the same compatible "mediatek,mt8135-infracfg" and
> "mediatek,mt8135-pericfg".
>
> I had a look on other implementations and they attach the reset
> controller to the clk driver, if they share the same hw block.
> Might we run into problems if we implement the clocks in the mfd, as
> we need the clocks early in boot (e.g. for the timer)?
>
> In mt6589 pericfg apart from the clocks and reset controller provides
> registers for AXI bus control and USB wakeup and USB clock selection.
> The infracfg block provides top AXI bus fabric control signals and
> remap registers for the modem.
> Mike, Stephen, what do you think. Can we implement the clk in a mfd
> driver? Or do you prefer to implement the whole block in the clk
> driver?
>
> Cheers,
> Matthias
>
>>
>> Sascha
>>
>> On Fri, Jan 23, 2015 at 03:09:55PM +0100, Sascha Hauer wrote:
>>> 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
>>> patch is independent of the first 6 patches and can be merged through the
>>> mfd maintainer trees.
>>>
>>> Changes since v1:
>>>
>>> - document reset bindings for infracfg/pericfg
>>> - fix base addresses in infracfg binding example
>>> - Remove more Email addresses from Flora Fu (She is not working at
>>>   MediaTek anymore, her address is no longer valid)
>>> - drop Regulator support patch, it's already in next
>>>
>>> Sascha
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>>
>> --
>> 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 |
>
>
>
> --
> motzblog.wordpress.com



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2] MediaTek PMIC support
  2015-01-29 12:39     ` Matthias Brugger
@ 2015-01-29 14:27       ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-29 14:27 UTC (permalink / raw)
  To: Matthias Brugger
  Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz,
	YH Chen (陳昱豪),
	linux-kernel, Henry Chen, Rob Herring,
	Yingjoe Chen (陳英洲),
	Eddie Huang, Lee Jones, linux-arm-kernel, James Liao,
	Mike Turquette, Stephen Boyd

On Thu, Jan 29, 2015 at 01:39:42PM +0100, Matthias Brugger wrote:
> Hi Sascha,
> 
> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> > Olof, Arnd,
> >
> > OK to put the driver into drivers/soc/mediatek? Can you take these
> > patches?
> 
> How does this patches fit together with the one James clock framework patches?
> Both use the same compatible "mediatek,mt8135-infracfg" and
> "mediatek,mt8135-pericfg".
> 
> I had a look on other implementations and they attach the reset
> controller to the clk driver, if they share the same hw block.
> Might we run into problems if we implement the clocks in the mfd, as
> we need the clocks early in boot (e.g. for the timer)?

>From my experience the clocks are needed by the timer before any driver
initializes.

> 
> In mt6589 pericfg apart from the clocks and reset controller provides
> registers for AXI bus control and USB wakeup and USB clock selection.
> The infracfg block provides top AXI bus fabric control signals and
> remap registers for the modem.
> Mike, Stephen, what do you think. Can we implement the clk in a mfd
> driver? Or do you prefer to implement the whole block in the clk
> driver?

Currently the clk support uses regular CLK_OF_DECLARE which handles the
clock part of pericfg/infracfg and then later a regular driver for
pericfg/infracfg comes and handles the rest of the functionality. Since
both use separate registers in the device register space it should work
fine.

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] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-29 14:27       ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-29 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 29, 2015 at 01:39:42PM +0100, Matthias Brugger wrote:
> Hi Sascha,
> 
> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> > Olof, Arnd,
> >
> > OK to put the driver into drivers/soc/mediatek? Can you take these
> > patches?
> 
> How does this patches fit together with the one James clock framework patches?
> Both use the same compatible "mediatek,mt8135-infracfg" and
> "mediatek,mt8135-pericfg".
> 
> I had a look on other implementations and they attach the reset
> controller to the clk driver, if they share the same hw block.
> Might we run into problems if we implement the clocks in the mfd, as
> we need the clocks early in boot (e.g. for the timer)?

>From my experience the clocks are needed by the timer before any driver
initializes.

> 
> In mt6589 pericfg apart from the clocks and reset controller provides
> registers for AXI bus control and USB wakeup and USB clock selection.
> The infracfg block provides top AXI bus fabric control signals and
> remap registers for the modem.
> Mike, Stephen, what do you think. Can we implement the clk in a mfd
> driver? Or do you prefer to implement the whole block in the clk
> driver?

Currently the clk support uses regular CLK_OF_DECLARE which handles the
clock part of pericfg/infracfg and then later a regular driver for
pericfg/infracfg comes and handles the rest of the functionality. Since
both use separate registers in the device register space it should work
fine.

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] 36+ messages in thread

* Re: [PATCH v2] MediaTek PMIC support
  2015-01-29 14:27       ` Sascha Hauer
@ 2015-01-29 15:44         ` Matthias Brugger
  -1 siblings, 0 replies; 36+ messages in thread
From: Matthias Brugger @ 2015-01-29 15:44 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz,
	YH Chen (陳昱豪),
	linux-kernel, Henry Chen, Rob Herring,
	Yingjoe Chen (陳英洲),
	Eddie Huang, Lee Jones, linux-arm-kernel, James Liao,
	Mike Turquette, Stephen Boyd

2015-01-29 15:27 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Thu, Jan 29, 2015 at 01:39:42PM +0100, Matthias Brugger wrote:
>> Hi Sascha,
>>
>> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
>> > Olof, Arnd,
>> >
>> > OK to put the driver into drivers/soc/mediatek? Can you take these
>> > patches?
>>
>> How does this patches fit together with the one James clock framework patches?
>> Both use the same compatible "mediatek,mt8135-infracfg" and
>> "mediatek,mt8135-pericfg".
>>
>> I had a look on other implementations and they attach the reset
>> controller to the clk driver, if they share the same hw block.
>> Might we run into problems if we implement the clocks in the mfd, as
>> we need the clocks early in boot (e.g. for the timer)?
>
> From my experience the clocks are needed by the timer before any driver
> initializes.
>
>>
>> In mt6589 pericfg apart from the clocks and reset controller provides
>> registers for AXI bus control and USB wakeup and USB clock selection.
>> The infracfg block provides top AXI bus fabric control signals and
>> remap registers for the modem.
>> Mike, Stephen, what do you think. Can we implement the clk in a mfd
>> driver? Or do you prefer to implement the whole block in the clk
>> driver?
>
> Currently the clk support uses regular CLK_OF_DECLARE which handles the
> clock part of pericfg/infracfg and then later a regular driver for
> pericfg/infracfg comes and handles the rest of the functionality. Since
> both use separate registers in the device register space it should work
> fine.

It should work until some driver start to use request and map, as you
provide the whole register space.
If you want to implement drivers for pericfg/infracfg like this, why
don't you implement the reset controller in drivers/reset?

Anyway I'm not really happy with the solution of having several device
drivers for the same dts compatible string.

>
> 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 |



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-29 15:44         ` Matthias Brugger
  0 siblings, 0 replies; 36+ messages in thread
From: Matthias Brugger @ 2015-01-29 15:44 UTC (permalink / raw)
  To: linux-arm-kernel

2015-01-29 15:27 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Thu, Jan 29, 2015 at 01:39:42PM +0100, Matthias Brugger wrote:
>> Hi Sascha,
>>
>> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
>> > Olof, Arnd,
>> >
>> > OK to put the driver into drivers/soc/mediatek? Can you take these
>> > patches?
>>
>> How does this patches fit together with the one James clock framework patches?
>> Both use the same compatible "mediatek,mt8135-infracfg" and
>> "mediatek,mt8135-pericfg".
>>
>> I had a look on other implementations and they attach the reset
>> controller to the clk driver, if they share the same hw block.
>> Might we run into problems if we implement the clocks in the mfd, as
>> we need the clocks early in boot (e.g. for the timer)?
>
> From my experience the clocks are needed by the timer before any driver
> initializes.
>
>>
>> In mt6589 pericfg apart from the clocks and reset controller provides
>> registers for AXI bus control and USB wakeup and USB clock selection.
>> The infracfg block provides top AXI bus fabric control signals and
>> remap registers for the modem.
>> Mike, Stephen, what do you think. Can we implement the clk in a mfd
>> driver? Or do you prefer to implement the whole block in the clk
>> driver?
>
> Currently the clk support uses regular CLK_OF_DECLARE which handles the
> clock part of pericfg/infracfg and then later a regular driver for
> pericfg/infracfg comes and handles the rest of the functionality. Since
> both use separate registers in the device register space it should work
> fine.

It should work until some driver start to use request and map, as you
provide the whole register space.
If you want to implement drivers for pericfg/infracfg like this, why
don't you implement the reset controller in drivers/reset?

Anyway I'm not really happy with the solution of having several device
drivers for the same dts compatible string.

>
> 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 |



-- 
motzblog.wordpress.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2] MediaTek PMIC support
  2015-01-29 15:44         ` Matthias Brugger
@ 2015-01-29 16:18           ` Sascha Hauer
  -1 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-29 16:18 UTC (permalink / raw)
  To: Matthias Brugger
  Cc: Olof Johansson, Arnd Bergmann, Samuel Ortiz,
	YH Chen (陳昱豪),
	linux-kernel, Henry Chen, Rob Herring,
	Yingjoe Chen (陳英洲),
	Eddie Huang, Lee Jones, linux-arm-kernel, James Liao,
	Mike Turquette, Stephen Boyd

On Thu, Jan 29, 2015 at 04:44:19PM +0100, Matthias Brugger wrote:
> 2015-01-29 15:27 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> > On Thu, Jan 29, 2015 at 01:39:42PM +0100, Matthias Brugger wrote:
> >> Hi Sascha,
> >>
> >> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> >> > Olof, Arnd,
> >> >
> >> > OK to put the driver into drivers/soc/mediatek? Can you take these
> >> > patches?
> >>
> >> How does this patches fit together with the one James clock framework patches?
> >> Both use the same compatible "mediatek,mt8135-infracfg" and
> >> "mediatek,mt8135-pericfg".
> >>
> >> I had a look on other implementations and they attach the reset
> >> controller to the clk driver, if they share the same hw block.
> >> Might we run into problems if we implement the clocks in the mfd, as
> >> we need the clocks early in boot (e.g. for the timer)?
> >
> > From my experience the clocks are needed by the timer before any driver
> > initializes.
> >
> >>
> >> In mt6589 pericfg apart from the clocks and reset controller provides
> >> registers for AXI bus control and USB wakeup and USB clock selection.
> >> The infracfg block provides top AXI bus fabric control signals and
> >> remap registers for the modem.
> >> Mike, Stephen, what do you think. Can we implement the clk in a mfd
> >> driver? Or do you prefer to implement the whole block in the clk
> >> driver?
> >
> > Currently the clk support uses regular CLK_OF_DECLARE which handles the
> > clock part of pericfg/infracfg and then later a regular driver for
> > pericfg/infracfg comes and handles the rest of the functionality. Since
> > both use separate registers in the device register space it should work
> > fine.
> 
> It should work until some driver start to use request and map, as you
> provide the whole register space.

Why do you think so? The clock driver continues working after the
pericfg/infracfg drivers have probed.

> If you want to implement drivers for pericfg/infracfg like this, why
> don't you implement the reset controller in drivers/reset?

I want to have a single driver for pericfg/infracfg, the clk support
only bypasses this since it's needed so early. Otherwise I would
register the clocks from the pericfg/infracfg probe function.

BTW in earlier versions we had a syscon binding so that child devices
such as the reset driver could access the registers via regmap. Anyway,
since

bdb0066 mfd: syscon: Decouple syscon interface from platform devices

syscon devices no longer probe by themselves, so we can't put the reset
controller and stuff as child devices under the syscon node anymore.

> 
> Anyway I'm not really happy with the solution of having several device
> drivers for the same dts compatible string.

Me neither, but what do you want to do about it?

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] 36+ messages in thread

* [PATCH v2] MediaTek PMIC support
@ 2015-01-29 16:18           ` Sascha Hauer
  0 siblings, 0 replies; 36+ messages in thread
From: Sascha Hauer @ 2015-01-29 16:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 29, 2015 at 04:44:19PM +0100, Matthias Brugger wrote:
> 2015-01-29 15:27 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> > On Thu, Jan 29, 2015 at 01:39:42PM +0100, Matthias Brugger wrote:
> >> Hi Sascha,
> >>
> >> 2015-01-26 12:47 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> >> > Olof, Arnd,
> >> >
> >> > OK to put the driver into drivers/soc/mediatek? Can you take these
> >> > patches?
> >>
> >> How does this patches fit together with the one James clock framework patches?
> >> Both use the same compatible "mediatek,mt8135-infracfg" and
> >> "mediatek,mt8135-pericfg".
> >>
> >> I had a look on other implementations and they attach the reset
> >> controller to the clk driver, if they share the same hw block.
> >> Might we run into problems if we implement the clocks in the mfd, as
> >> we need the clocks early in boot (e.g. for the timer)?
> >
> > From my experience the clocks are needed by the timer before any driver
> > initializes.
> >
> >>
> >> In mt6589 pericfg apart from the clocks and reset controller provides
> >> registers for AXI bus control and USB wakeup and USB clock selection.
> >> The infracfg block provides top AXI bus fabric control signals and
> >> remap registers for the modem.
> >> Mike, Stephen, what do you think. Can we implement the clk in a mfd
> >> driver? Or do you prefer to implement the whole block in the clk
> >> driver?
> >
> > Currently the clk support uses regular CLK_OF_DECLARE which handles the
> > clock part of pericfg/infracfg and then later a regular driver for
> > pericfg/infracfg comes and handles the rest of the functionality. Since
> > both use separate registers in the device register space it should work
> > fine.
> 
> It should work until some driver start to use request and map, as you
> provide the whole register space.

Why do you think so? The clock driver continues working after the
pericfg/infracfg drivers have probed.

> If you want to implement drivers for pericfg/infracfg like this, why
> don't you implement the reset controller in drivers/reset?

I want to have a single driver for pericfg/infracfg, the clk support
only bypasses this since it's needed so early. Otherwise I would
register the clocks from the pericfg/infracfg probe function.

BTW in earlier versions we had a syscon binding so that child devices
such as the reset driver could access the registers via regmap. Anyway,
since

bdb0066 mfd: syscon: Decouple syscon interface from platform devices

syscon devices no longer probe by themselves, so we can't put the reset
controller and stuff as child devices under the syscon node anymore.

> 
> Anyway I'm not really happy with the solution of having several device
> drivers for the same dts compatible string.

Me neither, but what do you want to do about it?

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] 36+ messages in thread

end of thread, other threads:[~2015-01-29 16:18 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-23 14:09 [PATCH v2] MediaTek PMIC support Sascha Hauer
2015-01-23 14:09 ` Sascha Hauer
2015-01-23 14:09 ` [PATCH 1/7] soc: Add MediaTek infracfg controller support Sascha Hauer
2015-01-23 14:09   ` Sascha Hauer
2015-01-23 14:09 ` [PATCH 2/7] soc: Add MediaTek pericfg " Sascha Hauer
2015-01-23 14:09   ` Sascha Hauer
2015-01-23 14:09 ` [PATCH 3/7] dt: bindings: Add MediaTek MT8135/MT8173 reset controller defines Sascha Hauer
2015-01-23 14:09   ` Sascha Hauer
2015-01-23 14:09 ` [PATCH 4/7] soc: mediatek: Add PMIC wrapper for MT8135 and MT6397 SoC Sascha Hauer
2015-01-23 14:09   ` Sascha Hauer
2015-01-23 14:10 ` [PATCH 5/7] ARM: dts: mt8135: Add pericfg, infracfg and pmic wrapper nodes Sascha Hauer
2015-01-23 14:10   ` Sascha Hauer
2015-01-23 14:10 ` [PATCH 6/7] ARM: dts: mt8135-evbp1: Add PMIC support Sascha Hauer
2015-01-23 14:10   ` Sascha Hauer
2015-01-23 14:10 ` [PATCH 7/7] mfd: Add support for the MediaTek MT6397 PMIC Sascha Hauer
2015-01-23 14:10   ` Sascha Hauer
2015-01-23 16:14   ` Lee Jones
2015-01-23 16:14     ` Lee Jones
2015-01-26 10:52     ` Sascha Hauer
2015-01-26 10:52       ` Sascha Hauer
2015-01-26 11:11       ` Lee Jones
2015-01-26 11:11         ` Lee Jones
2015-01-26 11:26         ` Sascha Hauer
2015-01-26 11:26           ` Sascha Hauer
2015-01-26 11:47 ` [PATCH v2] MediaTek PMIC support Sascha Hauer
2015-01-26 11:47   ` Sascha Hauer
2015-01-29 12:39   ` Matthias Brugger
2015-01-29 12:39     ` Matthias Brugger
2015-01-29 13:22     ` Matthias Brugger
2015-01-29 13:22       ` Matthias Brugger
2015-01-29 14:27     ` Sascha Hauer
2015-01-29 14:27       ` Sascha Hauer
2015-01-29 15:44       ` Matthias Brugger
2015-01-29 15:44         ` Matthias Brugger
2015-01-29 16:18         ` Sascha Hauer
2015-01-29 16:18           ` Sascha Hauer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.