Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 07/12] pinctrl: samsung: Remove dead code
From: Marek Szyprowski @ 2017-01-16  6:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484549107-5957-1-git-send-email-m.szyprowski@samsung.com>

'enable' parameter has been removed a while ago, so all code for handling
it can be simply removed.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/pinctrl/samsung/pinctrl-samsung.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index b11e67e85460..7648a280c0f4 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -350,7 +350,7 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
 
 /* enable or disable a pinmux function */
 static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
-					unsigned group, bool enable)
+					unsigned group)
 {
 	struct samsung_pinctrl_drv_data *drvdata;
 	const struct samsung_pin_bank_type *type;
@@ -380,8 +380,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
 
 	data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
 	data &= ~(mask << shift);
-	if (enable)
-		data |= func->val << shift;
+	data |= func->val << shift;
 	writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
 
 	spin_unlock_irqrestore(&bank->slock, flags);
@@ -392,7 +391,7 @@ static int samsung_pinmux_set_mux(struct pinctrl_dev *pctldev,
 				  unsigned selector,
 				  unsigned group)
 {
-	samsung_pinmux_setup(pctldev, selector, group, true);
+	samsung_pinmux_setup(pctldev, selector, group);
 	return 0;
 }
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 08/12] pinctrl: samsung: Use generic of_device_get_match_data helper
From: Marek Szyprowski @ 2017-01-16  6:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484549107-5957-1-git-send-email-m.szyprowski@samsung.com>

Replace custom code with generic helper.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/pinctrl/samsung/pinctrl-samsung.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 7648a280c0f4..86f23842f681 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/irqdomain.h>
+#include <linux/of_device.h>
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
 
@@ -955,15 +956,13 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev,
 	return 0;
 }
 
-static const struct of_device_id samsung_pinctrl_dt_match[];
-
 /* retrieve the soc specific data */
 static const struct samsung_pin_ctrl *
 samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
 			     struct platform_device *pdev)
 {
 	int id;
-	const struct of_device_id *match;
+	const struct samsung_pin_ctrl *match_data;
 	struct device_node *node = pdev->dev.of_node;
 	struct device_node *np;
 	const struct samsung_pin_bank_data *bdata;
@@ -978,8 +977,8 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev,
 		dev_err(&pdev->dev, "failed to get alias id\n");
 		return ERR_PTR(-ENOENT);
 	}
-	match = of_match_node(samsung_pinctrl_dt_match, node);
-	ctrl = (struct samsung_pin_ctrl *)match->data + id;
+	match_data = of_device_get_match_data(&pdev->dev);
+	ctrl = match_data + id;
 
 	d->suspend = ctrl->suspend;
 	d->resume = ctrl->resume;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 09/12] pinctrl: samsung: Add infrastructure for pin-bank retention control
From: Marek Szyprowski @ 2017-01-16  6:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484549107-5957-1-git-send-email-m.szyprowski@samsung.com>

Pad retention control after suspend/resume cycle should be done from pin
controller driver instead of PMU (power management unit) driver to avoid
possible ordering and logical dependencies. Till now it worked fine only
because PMU driver registered its sys_ops after pin controller.

This patch adds infrastructure to handle pad retention during pin control
driver resume.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/pinctrl/samsung/pinctrl-samsung.c | 12 ++++++---
 drivers/pinctrl/samsung/pinctrl-samsung.h | 42 +++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 86f23842f681..95a84086a2e9 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1075,6 +1075,9 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
 		ctrl->eint_gpio_init(drvdata);
 	if (ctrl->eint_wkup_init)
 		ctrl->eint_wkup_init(drvdata);
+	if (ctrl->retention_data && ctrl->retention_data->init)
+		drvdata->retention_ctrl = ctrl->retention_data->init(drvdata,
+							  ctrl->retention_data);
 
 	platform_set_drvdata(pdev, drvdata);
 
@@ -1127,15 +1130,15 @@ static void samsung_pinctrl_suspend_dev(
 
 	if (drvdata->suspend)
 		drvdata->suspend(drvdata);
+	if (drvdata->retention_ctrl && drvdata->retention_ctrl->on)
+		drvdata->retention_ctrl->on(drvdata);
+
 }
 
 /**
  * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device
  *
  * Restore one of the banks that was saved during suspend.
- *
- * We don't bother doing anything complicated to avoid glitching lines since
- * we're called before pad retention is turned off.
  */
 static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
 {
@@ -1174,6 +1177,9 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
 			if (widths[type])
 				writel(bank->pm_save[type], reg + offs[type]);
 	}
+
+	if (drvdata->retention_ctrl && drvdata->retention_ctrl->off)
+		drvdata->retention_ctrl->off(drvdata);
 }
 
 /**
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 6f7ce7539a00..6079142422f8 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -185,10 +185,48 @@ struct samsung_pin_bank {
 };
 
 /**
+ * struct samsung_retention_data: runtime pin-bank retention control data.
+ * @regs: array of PMU registers to control pad retention.
+ * @nr_regs: number of registers in @regs array.
+ * @value: value to store to registers to turn off retention.
+ * @refcnt: atomic counter if retention control affects more than one bank.
+ * @priv: retention control code private data
+ * @on: platform specific callback to enter retention mode.
+ * @off: platform specific callback to exit retention mode.
+ **/
+struct samsung_retention_ctrl {
+	const u32	*regs;
+	int		nr_regs;
+	u32		value;
+	atomic_t	*refcnt;
+	void		*priv;
+	void		(*on)(struct samsung_pinctrl_drv_data *);
+	void		(*off)(struct samsung_pinctrl_drv_data *);
+};
+
+/**
+ * struct samsung_retention_data: represent a pin-bank retention control data.
+ * @regs: array of PMU registers to control pad retention.
+ * @nr_regs: number of registers in @regs array.
+ * @value: value to store to registers to turn off retention.
+ * @refcnt: atomic counter if retention control affects more than one bank.
+ * @init: platform specific callback to initialize retention control.
+ **/
+struct samsung_retention_data {
+	const u32	*regs;
+	int		nr_regs;
+	u32		value;
+	atomic_t	*refcnt;
+	struct samsung_retention_ctrl *(*init)(struct samsung_pinctrl_drv_data *,
+					const struct samsung_retention_data *);
+};
+
+/**
  * struct samsung_pin_ctrl: represent a pin controller.
  * @pin_banks: list of pin banks included in this controller.
  * @nr_banks: number of pin banks.
  * @nr_ext_resources: number of the extra base address for pin banks.
+ * @retention_data: configuration data for retention control.
  * @eint_gpio_init: platform specific callback to setup the external gpio
  *	interrupts for the controller.
  * @eint_wkup_init: platform specific callback to setup the external wakeup
@@ -198,6 +236,7 @@ struct samsung_pin_ctrl {
 	const struct samsung_pin_bank_data *pin_banks;
 	u32		nr_banks;
 	int		nr_ext_resources;
+	const struct samsung_retention_data *retention_data;
 
 	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
 	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
@@ -219,6 +258,7 @@ struct samsung_pin_ctrl {
  * @nr_function: number of such pin functions.
  * @pin_base: starting system wide pin number.
  * @nr_pins: number of pins supported by the controller.
+ * @retention_ctrl: retention control runtime data.
  */
 struct samsung_pinctrl_drv_data {
 	struct list_head		node;
@@ -238,6 +278,8 @@ struct samsung_pinctrl_drv_data {
 	unsigned int			pin_base;
 	unsigned int			nr_pins;
 
+	const struct samsung_retention_ctrl *retention_ctrl;
+
 	void (*suspend)(struct samsung_pinctrl_drv_data *);
 	void (*resume)(struct samsung_pinctrl_drv_data *);
 };
-- 
1.9.1

^ permalink raw reply related

* [PATCH 10/12] pinctrl: samsung: Move retention control from mach-exynos to the pinctrl driver
From: Marek Szyprowski @ 2017-01-16  6:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484549107-5957-1-git-send-email-m.szyprowski@samsung.com>

This patch moves pad retention control from PMU driver to Exynos pin
controller driver. This helps to avoid possible ordering and logical
dependencies between machine, PMU and pin control code. Till now it
worked fine only because sys_ops for PMU and pin controller were called
in registration order.
This is also a preparation for adding new features to Exynos pin
controller driver, like runtime power management and suspending
individual pin controllers, which might be a part of some power domain.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-exynos/suspend.c           |  64 -------------
 drivers/pinctrl/samsung/pinctrl-exynos.c | 149 +++++++++++++++++++++++++++++++
 2 files changed, 149 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index 25e7c5326259..312d3a886e92 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -57,7 +57,6 @@ struct exynos_wkup_irq {
 struct exynos_pm_data {
 	const struct exynos_wkup_irq *wkup_irq;
 	unsigned int wake_disable_mask;
-	const unsigned int *release_ret_regs;
 
 	void (*pm_prepare)(void);
 	void (*pm_resume_prepare)(void);
@@ -95,47 +94,6 @@ struct exynos_pm_data {
 	{ /* sentinel */ },
 };
 
-static const unsigned int exynos_release_ret_regs[] = {
-	S5P_PAD_RET_MAUDIO_OPTION,
-	S5P_PAD_RET_GPIO_OPTION,
-	S5P_PAD_RET_UART_OPTION,
-	S5P_PAD_RET_MMCA_OPTION,
-	S5P_PAD_RET_MMCB_OPTION,
-	S5P_PAD_RET_EBIA_OPTION,
-	S5P_PAD_RET_EBIB_OPTION,
-	REG_TABLE_END,
-};
-
-static const unsigned int exynos3250_release_ret_regs[] = {
-	S5P_PAD_RET_MAUDIO_OPTION,
-	S5P_PAD_RET_GPIO_OPTION,
-	S5P_PAD_RET_UART_OPTION,
-	S5P_PAD_RET_MMCA_OPTION,
-	S5P_PAD_RET_MMCB_OPTION,
-	S5P_PAD_RET_EBIA_OPTION,
-	S5P_PAD_RET_EBIB_OPTION,
-	S5P_PAD_RET_MMC2_OPTION,
-	S5P_PAD_RET_SPI_OPTION,
-	REG_TABLE_END,
-};
-
-static const unsigned int exynos5420_release_ret_regs[] = {
-	EXYNOS_PAD_RET_DRAM_OPTION,
-	EXYNOS_PAD_RET_MAUDIO_OPTION,
-	EXYNOS_PAD_RET_JTAG_OPTION,
-	EXYNOS5420_PAD_RET_GPIO_OPTION,
-	EXYNOS5420_PAD_RET_UART_OPTION,
-	EXYNOS5420_PAD_RET_MMCA_OPTION,
-	EXYNOS5420_PAD_RET_MMCB_OPTION,
-	EXYNOS5420_PAD_RET_MMCC_OPTION,
-	EXYNOS5420_PAD_RET_HSI_OPTION,
-	EXYNOS_PAD_RET_EBIA_OPTION,
-	EXYNOS_PAD_RET_EBIB_OPTION,
-	EXYNOS5420_PAD_RET_SPI_OPTION,
-	EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
-	REG_TABLE_END,
-};
-
 static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
 {
 	const struct exynos_wkup_irq *wkup_irq;
@@ -441,15 +399,6 @@ static int exynos5420_pm_suspend(void)
 	return 0;
 }
 
-static void exynos_pm_release_retention(void)
-{
-	unsigned int i;
-
-	for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++)
-		pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR,
-				pm_data->release_ret_regs[i]);
-}
-
 static void exynos_pm_resume(void)
 {
 	u32 cpuid = read_cpuid_part();
@@ -457,9 +406,6 @@ static void exynos_pm_resume(void)
 	if (exynos_pm_central_resume())
 		goto early_wakeup;
 
-	/* For release retention */
-	exynos_pm_release_retention();
-
 	if (cpuid == ARM_CPU_PART_CORTEX_A9)
 		scu_enable(S5P_VA_SCU);
 
@@ -481,9 +427,6 @@ static void exynos3250_pm_resume(void)
 	if (exynos_pm_central_resume())
 		goto early_wakeup;
 
-	/* For release retention */
-	exynos_pm_release_retention();
-
 	pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
 
 	if (call_firmware_op(resume) == -ENOSYS
@@ -521,9 +464,6 @@ static void exynos5420_pm_resume(void)
 	if (exynos_pm_central_resume())
 		goto early_wakeup;
 
-	/* For release retention */
-	exynos_pm_release_retention();
-
 	pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
 
 early_wakeup:
@@ -636,7 +576,6 @@ static void exynos_suspend_finish(void)
 static const struct exynos_pm_data exynos3250_pm_data = {
 	.wkup_irq	= exynos3250_wkup_irq,
 	.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
-	.release_ret_regs = exynos3250_release_ret_regs,
 	.pm_suspend	= exynos_pm_suspend,
 	.pm_resume	= exynos3250_pm_resume,
 	.pm_prepare	= exynos3250_pm_prepare,
@@ -646,7 +585,6 @@ static void exynos_suspend_finish(void)
 static const struct exynos_pm_data exynos4_pm_data = {
 	.wkup_irq	= exynos4_wkup_irq,
 	.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
-	.release_ret_regs = exynos_release_ret_regs,
 	.pm_suspend	= exynos_pm_suspend,
 	.pm_resume	= exynos_pm_resume,
 	.pm_prepare	= exynos_pm_prepare,
@@ -656,7 +594,6 @@ static void exynos_suspend_finish(void)
 static const struct exynos_pm_data exynos5250_pm_data = {
 	.wkup_irq	= exynos5250_wkup_irq,
 	.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
-	.release_ret_regs = exynos_release_ret_regs,
 	.pm_suspend	= exynos_pm_suspend,
 	.pm_resume	= exynos_pm_resume,
 	.pm_prepare	= exynos_pm_prepare,
@@ -666,7 +603,6 @@ static void exynos_suspend_finish(void)
 static const struct exynos_pm_data exynos5420_pm_data = {
 	.wkup_irq	= exynos5250_wkup_irq,
 	.wake_disable_mask = (0x7F << 7) | (0x1F << 1),
-	.release_ret_regs = exynos5420_release_ret_regs,
 	.pm_resume_prepare = exynos5420_prepare_pm_resume,
 	.pm_resume	= exynos5420_pm_resume,
 	.pm_suspend	= exynos5420_pm_suspend,
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 70b94ad10cc1..652d3eabe1e5 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -28,7 +28,10 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/regmap.h>
 #include <linux/err.h>
+#include <linux/soc/samsung/exynos-pmu.h>
+#include <linux/soc/samsung/exynos-regs-pmu.h>
 
 #include "pinctrl-samsung.h"
 #include "pinctrl-exynos.h"
@@ -690,6 +693,58 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 	},
 };
 
+/* Pad retention control code for accessing PMU regmap */
+static atomic_t exynos_shared_retention_refcnt;
+
+static void exynos_retention_on(struct samsung_pinctrl_drv_data *drvdata)
+{
+	if (drvdata->retention_ctrl->refcnt)
+		atomic_inc(drvdata->retention_ctrl->refcnt);
+}
+
+static void exynos_retention_off(struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct regmap *pmu_regs = drvdata->retention_ctrl->priv;
+	int i;
+
+	if (drvdata->retention_ctrl->refcnt &&
+	    !atomic_dec_and_test(drvdata->retention_ctrl->refcnt))
+		return;
+
+	for (i = 0; i < drvdata->retention_ctrl->nr_regs; i++)
+		regmap_write(pmu_regs, drvdata->retention_ctrl->regs[i],
+			     drvdata->retention_ctrl->value);
+}
+
+static struct samsung_retention_ctrl *
+exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
+		      const struct samsung_retention_data *data)
+{
+	struct samsung_retention_ctrl *ctrl;
+	struct regmap *pmu_regs;
+
+	ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return NULL;
+
+	pmu_regs = exynos_get_pmu_regs();
+	if (!pmu_regs) {
+		dev_err(drvdata->dev,
+			"failed to lookup PMU regmap, no support for pad retention\n");
+		return NULL;
+	}
+
+	ctrl->priv = pmu_regs;
+	ctrl->regs = data->regs;
+	ctrl->nr_regs = data->nr_regs;
+	ctrl->value = data->value;
+	ctrl->refcnt = data->refcnt;
+	ctrl->on = exynos_retention_on;
+	ctrl->off = exynos_retention_off;
+
+	return ctrl;
+}
+
 /* pin banks of exynos3250 pin-controller 0 */
 static const struct samsung_pin_bank_data exynos3250_pin_banks0[] __initconst = {
 	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@@ -722,6 +777,30 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 };
 
 /*
+ * PMU pad retention groups for Exynos3250 doesn't match pin banks, so handle
+ * them all together
+ */
+static const u32 exynos3250_retention_regs[] = {
+	S5P_PAD_RET_MAUDIO_OPTION,
+	S5P_PAD_RET_GPIO_OPTION,
+	S5P_PAD_RET_UART_OPTION,
+	S5P_PAD_RET_MMCA_OPTION,
+	S5P_PAD_RET_MMCB_OPTION,
+	S5P_PAD_RET_EBIA_OPTION,
+	S5P_PAD_RET_EBIB_OPTION,
+	S5P_PAD_RET_MMC2_OPTION,
+	S5P_PAD_RET_SPI_OPTION,
+};
+
+static const struct samsung_retention_data exynos3250_retention_data __initconst = {
+	.regs	 = exynos3250_retention_regs,
+	.nr_regs = ARRAY_SIZE(exynos3250_retention_regs),
+	.value	 = EXYNOS_WAKEUP_FROM_LOWPWR,
+	.refcnt	 = &exynos_shared_retention_refcnt,
+	.init	 = exynos_retention_init,
+};
+
+/*
  * Samsung pinctrl driver data for Exynos3250 SoC. Exynos3250 SoC includes
  * two gpio/pin-mux/pinconfig controllers.
  */
@@ -733,6 +812,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos3250_retention_data,
 	}, {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos3250_pin_banks1,
@@ -741,6 +821,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_wkup_init = exynos_eint_wkup_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos3250_retention_data,
 	},
 };
 
@@ -793,6 +874,36 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 	EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
 };
 
+/* PMU pad retention groups registers for Exynos4 (without audio) */
+static const u32 exynos4_retention_regs[] = {
+	S5P_PAD_RET_GPIO_OPTION,
+	S5P_PAD_RET_UART_OPTION,
+	S5P_PAD_RET_MMCA_OPTION,
+	S5P_PAD_RET_MMCB_OPTION,
+	S5P_PAD_RET_EBIA_OPTION,
+	S5P_PAD_RET_EBIB_OPTION,
+};
+
+static const struct samsung_retention_data exynos4_retention_data __initconst = {
+	.regs	 = exynos4_retention_regs,
+	.nr_regs = ARRAY_SIZE(exynos4_retention_regs),
+	.value	 = EXYNOS_WAKEUP_FROM_LOWPWR,
+	.refcnt	 = &exynos_shared_retention_refcnt,
+	.init	 = exynos_retention_init,
+};
+
+/* PMU retention control for audio pins can be tied to audio pin bank */
+static const u32 exynos4_audio_retention_regs[] = {
+	S5P_PAD_RET_MAUDIO_OPTION,
+};
+
+static const struct samsung_retention_data exynos4_audio_retention_data __initconst = {
+	.regs	 = exynos4_audio_retention_regs,
+	.nr_regs = ARRAY_SIZE(exynos4_audio_retention_regs),
+	.value	 = EXYNOS_WAKEUP_FROM_LOWPWR,
+	.init	 = exynos_retention_init,
+};
+
 /*
  * Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
  * three gpio/pin-mux/pinconfig controllers.
@@ -805,6 +916,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_retention_data,
 	}, {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos4210_pin_banks1,
@@ -813,10 +925,12 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_wkup_init = exynos_eint_wkup_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_retention_data,
 	}, {
 		/* pin-controller instance 2 data */
 		.pin_banks	= exynos4210_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks2),
+		.retention_data	= &exynos4_audio_retention_data,
 	},
 };
 
@@ -890,6 +1004,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_retention_data,
 	}, {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos4x12_pin_banks1,
@@ -898,6 +1013,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_wkup_init = exynos_eint_wkup_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_retention_data,
 	}, {
 		/* pin-controller instance 2 data */
 		.pin_banks	= exynos4x12_pin_banks2,
@@ -905,6 +1021,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_audio_retention_data,
 	}, {
 		/* pin-controller instance 3 data */
 		.pin_banks	= exynos4x12_pin_banks3,
@@ -984,6 +1101,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_wkup_init = exynos_eint_wkup_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_retention_data,
 	}, {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos5250_pin_banks1,
@@ -991,6 +1109,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_retention_data,
 	}, {
 		/* pin-controller instance 2 data */
 		.pin_banks	= exynos5250_pin_banks2,
@@ -1005,6 +1124,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &exynos4_audio_retention_data,
 	},
 };
 
@@ -1231,6 +1351,30 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
 };
 
+/* PMU pad retention groups registers for Exynos5420 (without audio) */
+static const u32 exynos5420_retention_regs[] = {
+	EXYNOS_PAD_RET_DRAM_OPTION,
+	EXYNOS_PAD_RET_JTAG_OPTION,
+	EXYNOS5420_PAD_RET_GPIO_OPTION,
+	EXYNOS5420_PAD_RET_UART_OPTION,
+	EXYNOS5420_PAD_RET_MMCA_OPTION,
+	EXYNOS5420_PAD_RET_MMCB_OPTION,
+	EXYNOS5420_PAD_RET_MMCC_OPTION,
+	EXYNOS5420_PAD_RET_HSI_OPTION,
+	EXYNOS_PAD_RET_EBIA_OPTION,
+	EXYNOS_PAD_RET_EBIB_OPTION,
+	EXYNOS5420_PAD_RET_SPI_OPTION,
+	EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
+};
+
+static const struct samsung_retention_data exynos5420_retention_data __initconst = {
+	.regs	 = exynos5420_retention_regs,
+	.nr_regs = ARRAY_SIZE(exynos5420_retention_regs),
+	.value	 = EXYNOS_WAKEUP_FROM_LOWPWR,
+	.refcnt	 = &exynos_shared_retention_refcnt,
+	.init	 = exynos_retention_init,
+};
+
 /*
  * Samsung pinctrl driver data for Exynos5420 SoC. Exynos5420 SoC includes
  * four gpio/pin-mux/pinconfig controllers.
@@ -1242,26 +1386,31 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks0),
 		.eint_gpio_init = exynos_eint_gpio_init,
 		.eint_wkup_init = exynos_eint_wkup_init,
+		.retention_data	= &exynos5420_retention_data,
 	}, {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos5420_pin_banks1,
 		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks1),
 		.eint_gpio_init = exynos_eint_gpio_init,
+		.retention_data	= &exynos5420_retention_data,
 	}, {
 		/* pin-controller instance 2 data */
 		.pin_banks	= exynos5420_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks2),
 		.eint_gpio_init = exynos_eint_gpio_init,
+		.retention_data	= &exynos5420_retention_data,
 	}, {
 		/* pin-controller instance 3 data */
 		.pin_banks	= exynos5420_pin_banks3,
 		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks3),
 		.eint_gpio_init = exynos_eint_gpio_init,
+		.retention_data	= &exynos5420_retention_data,
 	}, {
 		/* pin-controller instance 4 data */
 		.pin_banks	= exynos5420_pin_banks4,
 		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks4),
 		.eint_gpio_init = exynos_eint_gpio_init,
+		.retention_data	= &exynos4_audio_retention_data,
 	},
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 11/12] pinctrl: samsung: Move retention control from mach-s5pv210 to the pinctrl driver
From: Marek Szyprowski @ 2017-01-16  6:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484549107-5957-1-git-send-email-m.szyprowski@samsung.com>

This patch moves pad retention control from S5PV210 machine code to
Exynos pin controller driver. This helps to avoid possible ordering
and logical dependencies between machine and pin control code. Till
now it worked fine only because sys_ops for machine code and pin
controller were called in registration order.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-s5pv210/pm.c               |  7 ----
 arch/arm/mach-s5pv210/regs-clock.h       |  4 ---
 drivers/pinctrl/samsung/pinctrl-exynos.c | 56 ++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 21b4b13c5ab7..7d69666de5ba 100644
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -155,13 +155,6 @@ static void s5pv210_suspend_finish(void)
  */
 static void s5pv210_pm_resume(void)
 {
-	u32 tmp;
-
-	tmp = __raw_readl(S5P_OTHERS);
-	tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\
-		S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
-	__raw_writel(tmp , S5P_OTHERS);
-
 	s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
 }
 
diff --git a/arch/arm/mach-s5pv210/regs-clock.h b/arch/arm/mach-s5pv210/regs-clock.h
index 4640f0f03c12..fb3eb77412db 100644
--- a/arch/arm/mach-s5pv210/regs-clock.h
+++ b/arch/arm/mach-s5pv210/regs-clock.h
@@ -188,10 +188,6 @@
 #define S5P_SLEEP_CFG_USBOSC_EN		(1 << 1)
 
 /* OTHERS Resgister */
-#define S5P_OTHERS_RET_IO		(1 << 31)
-#define S5P_OTHERS_RET_CF		(1 << 30)
-#define S5P_OTHERS_RET_MMC		(1 << 29)
-#define S5P_OTHERS_RET_UART		(1 << 28)
 #define S5P_OTHERS_USB_SIG_MASK		(1 << 16)
 
 /* S5P_DAC_CONTROL */
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 652d3eabe1e5..fdadc9cbcfce 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -24,6 +24,7 @@
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
@@ -643,6 +644,60 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 			exynos_pinctrl_resume_bank(drvdata, bank);
 }
 
+/* Retention control for S5PV210 are located at the end of clock controller */
+#define S5P_OTHERS 0xE000
+
+#define S5P_OTHERS_RET_IO		(1 << 31)
+#define S5P_OTHERS_RET_CF		(1 << 30)
+#define S5P_OTHERS_RET_MMC		(1 << 29)
+#define S5P_OTHERS_RET_UART		(1 << 28)
+
+static void s5pv210_retention_off(struct samsung_pinctrl_drv_data *drvdata)
+{
+	void *clk_base = drvdata->retention_ctrl->priv;
+	u32 tmp;
+
+	tmp = __raw_readl(clk_base + S5P_OTHERS);
+	tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF | S5P_OTHERS_RET_MMC |
+		S5P_OTHERS_RET_UART);
+	__raw_writel(tmp, clk_base + S5P_OTHERS);
+}
+
+static struct samsung_retention_ctrl *
+s5pv210_retention_init(struct samsung_pinctrl_drv_data *drvdata,
+		       const struct samsung_retention_data *data)
+{
+	struct samsung_retention_ctrl *ctrl;
+	struct device_node *np;
+	void *clk_base;
+
+	ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return NULL;
+
+	np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
+	if (!np) {
+		pr_err("%s: failed to find clock controller DT node\n",
+			__func__);
+		return NULL;
+	}
+
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("%s: failed to map clock registers\n", __func__);
+		return NULL;
+	}
+
+	ctrl->priv = clk_base;
+	ctrl->off = s5pv210_retention_off;
+
+	return ctrl;
+}
+
+static const struct samsung_retention_data s5pv210_retention_data __initconst = {
+	.init	 = s5pv210_retention_init,
+};
+
 /* pin banks of s5pv210 pin-controller */
 static const struct samsung_pin_bank_data s5pv210_pin_bank[] __initconst = {
 	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@@ -690,6 +745,7 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 		.eint_wkup_init = exynos_eint_wkup_init,
 		.suspend	= exynos_pinctrl_suspend,
 		.resume		= exynos_pinctrl_resume,
+		.retention_data	= &s5pv210_retention_data,
 	},
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 12/12] pinctrl: samsung: Replace syscore ops with standard platform device pm_ops
From: Marek Szyprowski @ 2017-01-16  6:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484549107-5957-1-git-send-email-m.szyprowski@samsung.com>

Once the dependency on PMU driver (for pad retention control) has been
removed, there is no reason to use syscore_ops based suspend/resume.
This patch replaces it with standard platform device pm_ops based solution.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 drivers/pinctrl/samsung/pinctrl-samsung.c | 72 ++++++-------------------------
 1 file changed, 13 insertions(+), 59 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 95a84086a2e9..48acf5908b84 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -29,7 +29,6 @@
 #include <linux/irqdomain.h>
 #include <linux/of_device.h>
 #include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
 
 #include "../core.h"
 #include "pinctrl-samsung.h"
@@ -49,9 +48,6 @@
 	{ "samsung,pin-val", PINCFG_TYPE_DAT },
 };
 
-/* Global list of devices (struct samsung_pinctrl_drv_data) */
-static LIST_HEAD(drvdata_list);
-
 static unsigned int pin_base;
 
 static int samsung_get_group_count(struct pinctrl_dev *pctldev)
@@ -1081,22 +1077,18 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, drvdata);
 
-	/* Add to the global list */
-	list_add_tail(&drvdata->node, &drvdata_list);
-
 	return 0;
 }
 
 #ifdef CONFIG_PM
-
 /**
- * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device
+ * samsung_pinctrl_suspend - save pinctrl state for suspend
  *
  * Save data for all banks handled by this device.
  */
-static void samsung_pinctrl_suspend_dev(
-	struct samsung_pinctrl_drv_data *drvdata)
+static int samsung_pinctrl_suspend(struct device *dev)
 {
+	struct samsung_pinctrl_drv_data *drvdata = dev_get_drvdata(dev);
 	int i;
 
 	for (i = 0; i < drvdata->nr_banks; i++) {
@@ -1133,15 +1125,17 @@ static void samsung_pinctrl_suspend_dev(
 	if (drvdata->retention_ctrl && drvdata->retention_ctrl->on)
 		drvdata->retention_ctrl->on(drvdata);
 
+	return 0;
 }
 
 /**
- * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device
+ * samsung_pinctrl_resume - restore pinctrl state from suspend
  *
  * Restore one of the banks that was saved during suspend.
  */
-static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
+static int samsung_pinctrl_resume(struct device *dev)
 {
+	struct samsung_pinctrl_drv_data *drvdata = dev_get_drvdata(dev);
 	int i;
 
 	if (drvdata->resume)
@@ -1180,48 +1174,10 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
 
 	if (drvdata->retention_ctrl && drvdata->retention_ctrl->off)
 		drvdata->retention_ctrl->off(drvdata);
-}
-
-/**
- * samsung_pinctrl_suspend - save pinctrl state for suspend
- *
- * Save data for all banks across all devices.
- */
-static int samsung_pinctrl_suspend(void)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	list_for_each_entry(drvdata, &drvdata_list, node) {
-		samsung_pinctrl_suspend_dev(drvdata);
-	}
-
 	return 0;
 }
-
-/**
- * samsung_pinctrl_resume - restore pinctrl state for suspend
- *
- * Restore data for all banks across all devices.
- */
-static void samsung_pinctrl_resume(void)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	list_for_each_entry_reverse(drvdata, &drvdata_list, node) {
-		samsung_pinctrl_resume_dev(drvdata);
-	}
-}
-
-#else
-#define samsung_pinctrl_suspend		NULL
-#define samsung_pinctrl_resume		NULL
 #endif
 
-static struct syscore_ops samsung_pinctrl_syscore_ops = {
-	.suspend	= samsung_pinctrl_suspend,
-	.resume		= samsung_pinctrl_resume,
-};
-
 static const struct of_device_id samsung_pinctrl_dt_match[] = {
 #ifdef CONFIG_PINCTRL_EXYNOS
 	{ .compatible = "samsung,exynos3250-pinctrl",
@@ -1263,25 +1219,23 @@ static void samsung_pinctrl_resume(void)
 };
 MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
 
+static const struct dev_pm_ops samsung_pinctrl_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(samsung_pinctrl_suspend,
+				     samsung_pinctrl_resume)
+};
+
 static struct platform_driver samsung_pinctrl_driver = {
 	.probe		= samsung_pinctrl_probe,
 	.driver = {
 		.name	= "samsung-pinctrl",
 		.of_match_table = samsung_pinctrl_dt_match,
 		.suppress_bind_attrs = true,
+		.pm = &samsung_pinctrl_pm_ops,
 	},
 };
 
 static int __init samsung_pinctrl_drv_register(void)
 {
-	/*
-	 * Register syscore ops for save/restore of registers across suspend.
-	 * It's important to ensure that this driver is running at an earlier
-	 * initcall level than any arch-specific init calls that install syscore
-	 * ops that turn off pad retention (like exynos_pm_resume).
-	 */
-	register_syscore_ops(&samsung_pinctrl_syscore_ops);
-
 	return platform_driver_register(&samsung_pinctrl_driver);
 }
 postcore_initcall(samsung_pinctrl_drv_register);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v4 3/3] thermal: zx2967: add thermal driver for ZTE's zx2967 family
From: Shawn Guo @ 2017-01-16  6:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484304418-17489-3-git-send-email-baoyou.xie@linaro.org>

On Fri, Jan 13, 2017 at 06:46:58PM +0800, Baoyou Xie wrote:
> This patch adds thermal driver for ZTE's zx2967 family.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>

Reviewed-by: Shawn Guo <shawnguo@kernel.org>

^ permalink raw reply

* [PATCH v1 1/3] dt: bindings: add documentation for zx2967 family reset controller
From: Shawn Guo @ 2017-01-16  7:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484377530-30635-1-git-send-email-baoyou.xie@linaro.org>

On Sat, Jan 14, 2017 at 03:05:28PM +0800, Baoyou Xie wrote:
> This patch adds dt-binding documentation for zx2967 family
> reset controller.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>

Reviewed-by: Shawn Guo <shawnguo@kernel.org>

^ permalink raw reply

* [PATCH v2 5/7] clk: sunxi-ng: Add sun5i CCU driver
From: Chen-Yu Tsai @ 2017-01-16  7:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <da6a80f9368f5a7df9e8f9a8266f4dd62e4b6127.1484035021.git-series.maxime.ripard@free-electrons.com>

On Tue, Jan 10, 2017 at 3:57 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The Allwinner A10s, A13, R8 and NextThing GR8 are all based on the same
> silicon, and all share the same clocks.
>
> However, they're not packaged in the same way, and therefore not all the
> controllers are actually available on all these SoCs.
>
> Introduce a clock controller driver for all these SoCs with different
> compatibles to take that into account.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig     |   10 +-
>  drivers/clk/sunxi-ng/Makefile    |    1 +-
>  drivers/clk/sunxi-ng/ccu-sun5i.c | 1008 +++++++++++++++++++++++++++++++-
>  drivers/clk/sunxi-ng/ccu-sun5i.h |   68 ++-
>  4 files changed, 1087 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun5i.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun5i.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index 8454c6e3dd65..fc5d85016839 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -64,6 +64,16 @@ config SUN50I_A64_CCU
>         select SUNXI_CCU_PHASE
>         default ARM64 && ARCH_SUNXI
>
> +config SUN5I_CCU
> +       bool "Support for the Allwinner sun5i family CCM"
> +       select SUNXI_CCU_DIV
> +       select SUNXI_CCU_NK
> +       select SUNXI_CCU_NKM
> +       select SUNXI_CCU_NM
> +       select SUNXI_CCU_MP
> +       select SUNXI_CCU_PHASE
> +       default MACH_SUN5I
> +
>  config SUN6I_A31_CCU
>         bool "Support for the Allwinner A31/A31s CCU"
>         select SUNXI_CCU_DIV
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 24fbc6e5deb8..d3fc917314e9 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_SUNXI_CCU_MP)    += ccu_mp.o
>
>  # SoC support
>  obj-$(CONFIG_SUN50I_A64_CCU)   += ccu-sun50i-a64.o
> +obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
>  obj-$(CONFIG_SUN8I_A23_CCU)    += ccu-sun8i-a23.o
>  obj-$(CONFIG_SUN8I_A33_CCU)    += ccu-sun8i-a33.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c
> new file mode 100644
> index 000000000000..3d44a2bef11f
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c
> @@ -0,0 +1,1008 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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/clk-provider.h>
> +#include <linux/of_address.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_div.h"
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +#include "ccu_mult.h"
> +#include "ccu_nk.h"
> +#include "ccu_nkm.h"
> +#include "ccu_nkmp.h"
> +#include "ccu_nm.h"
> +#include "ccu_phase.h"
> +
> +#include "ccu-sun5i.h"
> +
> +static struct ccu_nkmp pll_core_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .m              = _SUNXI_CCU_DIV(0, 2),
> +       .p              = _SUNXI_CCU_DIV(16, 2),
> +       .common         = {
> +               .reg            = 0x000,
> +               .hw.init        = CLK_HW_INIT("pll-core",
> +                                             "hosc",
> +                                             &ccu_nkmp_ops,
> +                                             0),
> +       },
> +};
> +
> +/*
> + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
> + * the base (2x, 4x and 8x), and one variable divider (the one true
> + * pll audio).
> + *
> + * We don't have any need for the variable divider for now, so we just
> + * hardcode it to match with the clock names
> + */
> +#define SUN5I_PLL_AUDIO_REG    0x008
> +
> +static struct ccu_nm pll_audio_base_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 7, 0),
> +
> +       /*
> +        * The datasheet is wrong here, this doesn't have any
> +        * offset
> +        */
> +       .m              = _SUNXI_CCU_DIV_OFFSET(0, 5, 0),
> +       .common         = {
> +               .reg            = 0x008,
> +               .hw.init        = CLK_HW_INIT("pll-audio-base",
> +                                             "hosc",
> +                                             &ccu_nm_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_mult pll_video0_clk = {
> +       .enable         = BIT(31),
> +       .mult           = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127),
> +       .frac           = _SUNXI_CCU_FRAC(BIT(15), BIT(14),
> +                                         270000000, 297000000),
> +       .common         = {
> +               .reg            = 0x010,
> +               .features       = CCU_FEATURE_FRACTIONAL,
> +               .hw.init        = CLK_HW_INIT("pll-video0",
> +                                             "osc3M",
> +                                             &ccu_mult_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_nkmp pll_ve_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .m              = _SUNXI_CCU_DIV(0, 2),
> +       .p              = _SUNXI_CCU_DIV(16, 2),
> +       .common         = {
> +               .reg            = 0x018,
> +               .hw.init        = CLK_HW_INIT("pll-ve",
> +                                             "hosc",
> +                                             &ccu_nkmp_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_nk pll_ddr_base_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .common         = {
> +               .reg            = 0x020,
> +               .hw.init        = CLK_HW_INIT("pll-ddr-base",
> +                                             "hosc",
> +                                             &ccu_nk_ops,
> +                                             0),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_ddr_clk, "pll-ddr", "pll-ddr-base", 0x020, 0, 2,
> +                  CLK_IS_CRITICAL);
> +
> +static struct ccu_div pll_ddr_other_clk = {
> +       .div            = _SUNXI_CCU_DIV_FLAGS(16, 2, CLK_DIVIDER_POWER_OF_TWO),
> +
> +       .common         = {
> +               .reg            = 0x020,
> +               .hw.init        = CLK_HW_INIT("pll-ddr-other", "pll-ddr-base",
> +                                             &ccu_div_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_nk pll_periph_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .fixed_post_div = 2,
> +       .common         = {
> +               .reg            = 0x028,
> +               .features       = CCU_FEATURE_FIXED_POSTDIV,
> +               .hw.init        = CLK_HW_INIT("pll-periph",
> +                                             "hosc",
> +                                             &ccu_nk_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_mult pll_video1_clk = {
> +       .enable         = BIT(31),
> +       .mult           = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127),
> +       .frac           = _SUNXI_CCU_FRAC(BIT(15), BIT(14),
> +                                 270000000, 297000000),
> +       .common         = {
> +               .reg            = 0x030,
> +               .features       = CCU_FEATURE_FRACTIONAL,
> +               .hw.init        = CLK_HW_INIT("pll-video1",
> +                                             "osc3M",
> +                                             &ccu_mult_ops,
> +                                             0),
> +       },
> +};
> +
> +static SUNXI_CCU_GATE(hosc_clk,        "hosc", "osc24M", 0x050, BIT(0), 0);
> +
> +#define SUN5I_AHB_REG  0x054
> +static const char * const cpu_parents[] = { "osc32k", "hosc",
> +                                           "pll-core" , "pll-periph" };
> +static const struct ccu_mux_fixed_prediv cpu_predivs[] = {
> +       { .index = 3, .div = 3, },
> +};
> +static struct ccu_mux cpu_clk = {
> +       .mux            = {
> +               .shift          = 16,
> +               .width          = 2,
> +               .fixed_predivs  = cpu_predivs,
> +               .n_predivs      = ARRAY_SIZE(cpu_predivs),
> +       },
> +       .common         = {
> +               .reg            = 0x054,
> +               .features       = CCU_FEATURE_FIXED_PREDIV,
> +               .hw.init        = CLK_HW_INIT_PARENTS("cpu",
> +                                                     cpu_parents,
> +                                                     &ccu_mux_ops,
> +                                                     CLK_IS_CRITICAL),
> +       }
> +};
> +
> +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x054, 0, 2, 0);
> +
> +static const char * const ahb_parents[] = { "axi" , "cpu", "pll-periph" };
> +static const struct ccu_mux_fixed_prediv ahb_predivs[] = {
> +       { .index = 2, .div = 2, },
> +};
> +static struct ccu_div ahb_clk = {
> +       .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
> +       .mux            = {
> +               .shift          = 6,
> +               .width          = 2,
> +               .fixed_predivs  = ahb_predivs,
> +               .n_predivs      = ARRAY_SIZE(ahb_predivs),
> +       },
> +
> +       .common         = {
> +               .reg            = 0x054,
> +               .hw.init        = CLK_HW_INIT_PARENTS("ahb",
> +                                                     ahb_parents,
> +                                                     &ccu_div_ops,
> +                                                     0),
> +       },
> +};
> +
> +static struct clk_div_table apb0_div_table[] = {
> +       { .val = 0, .div = 2 },
> +       { .val = 1, .div = 2 },
> +       { .val = 2, .div = 4 },
> +       { .val = 3, .div = 8 },
> +       { /* Sentinel */ },
> +};
> +static SUNXI_CCU_DIV_TABLE(apb0_clk, "apb0", "ahb",
> +                          0x054, 8, 2, apb0_div_table, 0);
> +
> +static const char * const apb1_parents[] = { "hosc", "pll-periph", "osc32k" };
> +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x058,
> +                            0, 5,      /* M */
> +                            16, 2,     /* P */
> +                            24, 2,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_GATE(axi_dram_clk,    "axi-dram",     "axi",
> +                     0x05c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(ahb_otg_clk,     "ahb-otg",      "ahb",
> +                     0x060, BIT(0), 0);
> +static SUNXI_CCU_GATE(ahb_ehci_clk,    "ahb-ehci",     "ahb",
> +                     0x060, BIT(1), 0);
> +static SUNXI_CCU_GATE(ahb_ohci_clk,    "ahb-ohci",     "ahb",
> +                     0x060, BIT(2), 0);
> +static SUNXI_CCU_GATE(ahb_ss_clk,      "ahb-ss",       "ahb",
> +                     0x060, BIT(5), 0);
> +static SUNXI_CCU_GATE(ahb_dma_clk,     "ahb-dma",      "ahb",
> +                     0x060, BIT(6), 0);
> +static SUNXI_CCU_GATE(ahb_bist_clk,    "ahb-bist",     "ahb",
> +                     0x060, BIT(6), 0);
> +static SUNXI_CCU_GATE(ahb_mmc0_clk,    "ahb-mmc0",     "ahb",
> +                     0x060, BIT(8), 0);
> +static SUNXI_CCU_GATE(ahb_mmc1_clk,    "ahb-mmc1",     "ahb",
> +                     0x060, BIT(9), 0);
> +static SUNXI_CCU_GATE(ahb_mmc2_clk,    "ahb-mmc2",     "ahb",
> +                     0x060, BIT(10), 0);
> +static SUNXI_CCU_GATE(ahb_nand_clk,    "ahb-nand",     "ahb",
> +                     0x060, BIT(13), 0);
> +static SUNXI_CCU_GATE(ahb_sdram_clk,   "ahb-sdram",    "ahb",
> +                     0x060, BIT(14), CLK_IS_CRITICAL);
> +static SUNXI_CCU_GATE(ahb_emac_clk,    "ahb-emac",     "ahb",
> +                     0x060, BIT(17), 0);
> +static SUNXI_CCU_GATE(ahb_ts_clk,      "ahb-ts",       "ahb",
> +                     0x060, BIT(18), 0);
> +static SUNXI_CCU_GATE(ahb_spi0_clk,    "ahb-spi0",     "ahb",
> +                     0x060, BIT(20), 0);
> +static SUNXI_CCU_GATE(ahb_spi1_clk,    "ahb-spi1",     "ahb",
> +                     0x060, BIT(21), 0);
> +static SUNXI_CCU_GATE(ahb_spi2_clk,    "ahb-spi2",     "ahb",
> +                     0x060, BIT(22), 0);
> +static SUNXI_CCU_GATE(ahb_gps_clk,     "ahb-gps",      "ahb",
> +                     0x060, BIT(26), 0);
> +static SUNXI_CCU_GATE(ahb_hstimer_clk, "ahb-hstimer",  "ahb",
> +                     0x060, BIT(28), 0);
> +
> +static SUNXI_CCU_GATE(ahb_ve_clk,      "ahb-ve",       "ahb",
> +                     0x064, BIT(0), 0);
> +static SUNXI_CCU_GATE(ahb_tve_clk,     "ahb-tve",      "ahb",
> +                     0x064, BIT(2), 0);
> +static SUNXI_CCU_GATE(ahb_lcd_clk,     "ahb-lcd",      "ahb",
> +                     0x064, BIT(4), 0);
> +static SUNXI_CCU_GATE(ahb_csi_clk,     "ahb-csi",      "ahb",
> +                     0x064, BIT(8), 0);
> +static SUNXI_CCU_GATE(ahb_hdmi_clk,    "ahb-hdmi",     "ahb",
> +                     0x064, BIT(11), 0);
> +static SUNXI_CCU_GATE(ahb_de_be_clk,   "ahb-de-be",    "ahb",
> +                     0x064, BIT(12), 0);
> +static SUNXI_CCU_GATE(ahb_de_fe_clk,   "ahb-de-fe",    "ahb",
> +                     0x064, BIT(14), 0);
> +static SUNXI_CCU_GATE(ahb_iep_clk,     "ahb-iep",      "ahb",
> +                     0x064, BIT(19), 0);
> +static SUNXI_CCU_GATE(ahb_gpu_clk,     "ahb-gpu",      "ahb",
> +                     0x064, BIT(20), 0);
> +
> +static SUNXI_CCU_GATE(apb0_codec_clk,  "apb0-codec",   "apb0",
> +                     0x068, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb0_spdif_clk,  "apb0-spdif",   "apb0",
> +                     0x068, BIT(1), 0);
> +static SUNXI_CCU_GATE(apb0_i2s_clk,    "apb0-i2s",     "apb0",
> +                     0x068, BIT(3), 0);
> +static SUNXI_CCU_GATE(apb0_pio_clk,    "apb0-pio",     "apb0",
> +                     0x068, BIT(5), 0);
> +static SUNXI_CCU_GATE(apb0_ir_clk,     "apb0-ir",      "apb0",
> +                     0x068, BIT(6), 0);
> +static SUNXI_CCU_GATE(apb0_keypad_clk, "apb0-keypad",  "apb0",
> +                     0x068, BIT(10), 0);
> +
> +static SUNXI_CCU_GATE(apb1_i2c0_clk,   "apb1-i2c0",    "apb1",
> +                     0x06c, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb1_i2c1_clk,   "apb1-i2c1",    "apb1",
> +                     0x06c, BIT(1), 0);
> +static SUNXI_CCU_GATE(apb1_i2c2_clk,   "apb1-i2c2",    "apb1",
> +                     0x06c, BIT(2), 0);
> +static SUNXI_CCU_GATE(apb1_uart0_clk,  "apb1-uart0",   "apb1",
> +                     0x06c, BIT(16), 0);
> +static SUNXI_CCU_GATE(apb1_uart1_clk,  "apb1-uart1",   "apb1",
> +                     0x06c, BIT(17), 0);
> +static SUNXI_CCU_GATE(apb1_uart2_clk,  "apb1-uart2",   "apb1",
> +                     0x06c, BIT(18), 0);
> +static SUNXI_CCU_GATE(apb1_uart3_clk,  "apb1-uart3",   "apb1",
> +                     0x06c, BIT(19), 0);
> +
> +static const char * const mod0_default_parents[] = { "hosc", "pll-periph",
> +                                                    "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents, 0x098,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents, 0x09c,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir", mod0_default_parents, 0x0b0,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +                                           "pll-audio-2x", "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s_clk, "i2s", i2s_parents,
> +                              0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static const char * const spdif_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +                                           "pll-audio-2x", "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", spdif_parents,
> +                              0x0c0, 16, 2, BIT(31), 0);

CLK_SET_RATE_PARENT?

> +
> +static const char * const keypad_parents[] = { "hosc", "losc"};
> +static const u8 keypad_table[] = { 0, 2 };
> +static struct ccu_mp keypad_clk = {
> +       .enable         = BIT(31),
> +       .m              = _SUNXI_CCU_DIV(8, 5),
> +       .p              = _SUNXI_CCU_DIV(20, 2),
> +       .mux            = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table),
> +
> +       .common         = {
> +               .reg            = 0x0c4,
> +               .hw.init        = CLK_HW_INIT_PARENTS("keypad",
> +                                                     keypad_parents,
> +                                                     &ccu_mp_ops,
> +                                                     0),
> +       },
> +};
> +
> +static SUNXI_CCU_GATE(usb_ohci_clk,    "usb-ohci",     "pll-periph",
> +                     0x0cc, BIT(6), 0);
> +static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",     "pll-periph",
> +                     0x0cc, BIT(8), 0);
> +static SUNXI_CCU_GATE(usb_phy1_clk,    "usb-phy1",     "pll-periph",
> +                     0x0cc, BIT(9), 0);
> +
> +static const char * const gps_parents[] = { "hosc", "pll-periph",
> +                                           "pll-video1", "pll-ve" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(gps_clk, "gps", gps_parents,
> +                                0x0d0, 0, 3, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(dram_ve_clk,     "dram-ve",      "pll-ddr",
> +                     0x100, BIT(0), 0);
> +static SUNXI_CCU_GATE(dram_csi_clk,    "dram-csi",     "pll-ddr",
> +                     0x100, BIT(1), 0);
> +static SUNXI_CCU_GATE(dram_ts_clk,     "dram-ts",      "pll-ddr",
> +                     0x100, BIT(3), 0);
> +static SUNXI_CCU_GATE(dram_tve_clk,    "dram-tve",     "pll-ddr",
> +                     0x100, BIT(5), 0);
> +static SUNXI_CCU_GATE(dram_de_fe_clk,  "dram-de-fe",   "pll-ddr",
> +                     0x100, BIT(25), 0);
> +static SUNXI_CCU_GATE(dram_de_be_clk,  "dram-de-be",   "pll-ddr",
> +                     0x100, BIT(26), 0);
> +static SUNXI_CCU_GATE(dram_ace_clk,    "dram-ace",     "pll-ddr",
> +                     0x100, BIT(29), 0);
> +static SUNXI_CCU_GATE(dram_iep_clk,    "dram-iep",     "pll-ddr",
> +                     0x100, BIT(31), 0);
> +
> +static const char * const de_parents[] = { "pll-video0", "pll-video1",
> +                                          "pll-ddr-other" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_be_clk, "de-be", de_parents,
> +                                0x104, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe_clk, "de-fe", de_parents,
> +                                0x10c, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char * const tcon_parents[] = { "pll-video0", "pll-video1",
> +                                            "pll-video0-2x", "pll-video1-2x" };
> +static SUNXI_CCU_MUX_WITH_GATE(tcon_ch0_clk, "tcon-ch0-sclk", tcon_parents,
> +                              0x118, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(tcon_ch1_sclk2_clk, "tcon-ch1-sclk2",
> +                                tcon_parents,
> +                                0x12c, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_GATE(tcon_ch1_sclk1_clk, "tcon-ch1-sclk1", "tcon-ch1-sclk2",
> +                            0x12c, 11, 1, BIT(15), CLK_SET_RATE_PARENT);
> +
> +static const char * const csi_parents[] = { "hosc", "pll-video0", "pll-video1",
> +                                           "pll-video0-2x", "pll-video1-2x" };
> +static const u8 csi_table[] = { 0, 1, 2, 5, 6 };
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_clk, "csi",
> +                                      csi_parents, csi_table,
> +                                      0x134, 0, 5, 24, 2, BIT(31), 0);

Not sure how CSI works, but you might need CLK_SET_RATE_PARENT?

> +
> +static SUNXI_CCU_GATE(ve_clk,          "ve",           "pll-ve",
> +                     0x13c, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE(codec_clk,       "codec",        "pll-audio",
> +                     0x140, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE(avs_clk,         "avs",          "hosc",
> +                     0x144, BIT(31), 0);
> +
> +static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-2x" };
> +static const u8 hdmi_table[] = { 0, 2 };
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi_clk, "hdmi",
> +                                      hdmi_parents, hdmi_table,
> +                                      0x150, 0, 4, 24, 2, BIT(31),
> +                                      CLK_SET_RATE_PARENT);
> +
> +static const char * const gpu_parents[] = { "pll-video0", "pll-ve",
> +                                           "pll-ddr-other", "pll-video1",
> +                                           "pll-video1-2x" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents,
> +                                0x154, 0, 4, 24, 3, BIT(31), 0);
> +
> +static const char * const mbus_parents[] = { "hosc", "pll-periph", "pll-ddr" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
> +                                 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_GATE(iep_clk,         "iep",          "de-be",
> +                     0x160, BIT(31), 0);
> +
> +static struct ccu_common *sun5i_a10s_ccu_clks[] = {
> +       &hosc_clk.common,
> +       &pll_core_clk.common,
> +       &pll_audio_base_clk.common,
> +       &pll_video0_clk.common,
> +       &pll_ve_clk.common,
> +       &pll_ddr_base_clk.common,
> +       &pll_ddr_clk.common,
> +       &pll_ddr_other_clk.common,
> +       &pll_periph_clk.common,
> +       &pll_video1_clk.common,
> +       &cpu_clk.common,
> +       &axi_clk.common,
> +       &ahb_clk.common,
> +       &apb0_clk.common,
> +       &apb1_clk.common,
> +       &axi_dram_clk.common,
> +       &ahb_otg_clk.common,
> +       &ahb_ehci_clk.common,
> +       &ahb_ohci_clk.common,
> +       &ahb_ss_clk.common,
> +       &ahb_dma_clk.common,
> +       &ahb_bist_clk.common,
> +       &ahb_mmc0_clk.common,
> +       &ahb_mmc1_clk.common,
> +       &ahb_mmc2_clk.common,
> +       &ahb_nand_clk.common,
> +       &ahb_sdram_clk.common,
> +       &ahb_emac_clk.common,
> +       &ahb_ts_clk.common,
> +       &ahb_spi0_clk.common,
> +       &ahb_spi1_clk.common,
> +       &ahb_spi2_clk.common,
> +       &ahb_gps_clk.common,
> +       &ahb_hstimer_clk.common,
> +       &ahb_ve_clk.common,
> +       &ahb_tve_clk.common,
> +       &ahb_lcd_clk.common,
> +       &ahb_csi_clk.common,
> +       &ahb_hdmi_clk.common,
> +       &ahb_de_be_clk.common,
> +       &ahb_de_fe_clk.common,
> +       &ahb_iep_clk.common,
> +       &ahb_gpu_clk.common,
> +       &apb0_codec_clk.common,
> +       &apb0_spdif_clk.common,
> +       &apb0_i2s_clk.common,
> +       &apb0_pio_clk.common,
> +       &apb0_ir_clk.common,
> +       &apb0_keypad_clk.common,
> +       &apb1_i2c0_clk.common,
> +       &apb1_i2c1_clk.common,
> +       &apb1_i2c2_clk.common,
> +       &apb1_uart0_clk.common,
> +       &apb1_uart1_clk.common,
> +       &apb1_uart2_clk.common,
> +       &apb1_uart3_clk.common,
> +       &nand_clk.common,
> +       &mmc0_clk.common,
> +       &mmc1_clk.common,
> +       &mmc2_clk.common,
> +       &ts_clk.common,
> +       &ss_clk.common,
> +       &spi0_clk.common,
> +       &spi1_clk.common,
> +       &spi2_clk.common,
> +       &ir_clk.common,
> +       &i2s_clk.common,
> +       &spdif_clk.common,
> +       &keypad_clk.common,
> +       &usb_ohci_clk.common,
> +       &usb_phy0_clk.common,
> +       &usb_phy1_clk.common,
> +       &gps_clk.common,
> +       &dram_ve_clk.common,
> +       &dram_csi_clk.common,
> +       &dram_ts_clk.common,
> +       &dram_tve_clk.common,
> +       &dram_de_fe_clk.common,
> +       &dram_de_be_clk.common,
> +       &dram_ace_clk.common,
> +       &dram_iep_clk.common,
> +       &de_be_clk.common,
> +       &de_fe_clk.common,
> +       &tcon_ch0_clk.common,
> +       &tcon_ch1_sclk2_clk.common,
> +       &tcon_ch1_sclk1_clk.common,
> +       &csi_clk.common,
> +       &ve_clk.common,
> +       &codec_clk.common,
> +       &avs_clk.common,
> +       &hdmi_clk.common,
> +       &gpu_clk.common,
> +       &mbus_clk.common,
> +       &iep_clk.common,
> +};
> +
> +static CLK_FIXED_FACTOR(osc3M_clk, "osc3M", "hosc", 8, 1, 0);

As I mentioned for the last version, we don't really need this.
It can be represented as a pre-divider. But it's just an
implementation detail.

> +/* We hardcode the divider to 4 for now */
> +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
> +                       "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> +                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> +                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> +                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
> +                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
> +                       "pll-video1", 1, 2, CLK_SET_RATE_PARENT);
> +
> +static struct clk_hw_onecell_data sun5i_a10s_hw_clks = {
> +       .hws    = {
> +               [CLK_HOSC]              = &hosc_clk.common.hw,
> +               [CLK_OSC3M]             = &osc3M_clk.hw,
> +               [CLK_PLL_CORE]          = &pll_core_clk.common.hw,
> +               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
> +               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
> +               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
> +               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
> +               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
> +               [CLK_PLL_VIDEO0]        = &pll_video0_clk.common.hw,
> +               [CLK_PLL_VIDEO0_2X]     = &pll_video0_2x_clk.hw,
> +               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
> +               [CLK_PLL_DDR_BASE]      = &pll_ddr_base_clk.common.hw,
> +               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
> +               [CLK_PLL_DDR_OTHER]     = &pll_ddr_other_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.common.hw,
> +               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
> +               [CLK_PLL_VIDEO1_2X]     = &pll_video1_2x_clk.hw,
> +               [CLK_CPU]               = &cpu_clk.common.hw,
> +               [CLK_AXI]               = &axi_clk.common.hw,
> +               [CLK_AHB]               = &ahb_clk.common.hw,
> +               [CLK_APB0]              = &apb0_clk.common.hw,
> +               [CLK_APB1]              = &apb1_clk.common.hw,
> +               [CLK_DRAM_AXI]          = &axi_dram_clk.common.hw,
> +               [CLK_AHB_OTG]           = &ahb_otg_clk.common.hw,
> +               [CLK_AHB_EHCI]          = &ahb_ehci_clk.common.hw,
> +               [CLK_AHB_OHCI]          = &ahb_ohci_clk.common.hw,
> +               [CLK_AHB_SS]            = &ahb_ss_clk.common.hw,
> +               [CLK_AHB_DMA]           = &ahb_dma_clk.common.hw,
> +               [CLK_AHB_BIST]          = &ahb_bist_clk.common.hw,
> +               [CLK_AHB_MMC0]          = &ahb_mmc0_clk.common.hw,
> +               [CLK_AHB_MMC1]          = &ahb_mmc1_clk.common.hw,
> +               [CLK_AHB_MMC2]          = &ahb_mmc2_clk.common.hw,
> +               [CLK_AHB_NAND]          = &ahb_nand_clk.common.hw,
> +               [CLK_AHB_SDRAM]         = &ahb_sdram_clk.common.hw,
> +               [CLK_AHB_EMAC]          = &ahb_emac_clk.common.hw,
> +               [CLK_AHB_TS]            = &ahb_ts_clk.common.hw,
> +               [CLK_AHB_SPI0]          = &ahb_spi0_clk.common.hw,
> +               [CLK_AHB_SPI1]          = &ahb_spi1_clk.common.hw,
> +               [CLK_AHB_SPI2]          = &ahb_spi2_clk.common.hw,
> +               [CLK_AHB_GPS]           = &ahb_gps_clk.common.hw,
> +               [CLK_AHB_HSTIMER]       = &ahb_hstimer_clk.common.hw,
> +               [CLK_AHB_VE]            = &ahb_ve_clk.common.hw,
> +               [CLK_AHB_TVE]           = &ahb_tve_clk.common.hw,
> +               [CLK_AHB_LCD]           = &ahb_lcd_clk.common.hw,
> +               [CLK_AHB_CSI]           = &ahb_csi_clk.common.hw,
> +               [CLK_AHB_HDMI]          = &ahb_hdmi_clk.common.hw,
> +               [CLK_AHB_DE_BE]         = &ahb_de_be_clk.common.hw,
> +               [CLK_AHB_DE_FE]         = &ahb_de_fe_clk.common.hw,
> +               [CLK_AHB_IEP]           = &ahb_iep_clk.common.hw,
> +               [CLK_AHB_GPU]           = &ahb_gpu_clk.common.hw,
> +               [CLK_APB0_CODEC]        = &apb0_codec_clk.common.hw,
> +               [CLK_APB0_I2S]          = &apb0_i2s_clk.common.hw,
> +               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
> +               [CLK_APB0_IR]           = &apb0_ir_clk.common.hw,
> +               [CLK_APB0_KEYPAD]       = &apb0_keypad_clk.common.hw,
> +               [CLK_APB1_I2C0]         = &apb1_i2c0_clk.common.hw,
> +               [CLK_APB1_I2C1]         = &apb1_i2c1_clk.common.hw,
> +               [CLK_APB1_I2C2]         = &apb1_i2c2_clk.common.hw,
> +               [CLK_APB1_UART0]        = &apb1_uart0_clk.common.hw,
> +               [CLK_APB1_UART1]        = &apb1_uart1_clk.common.hw,
> +               [CLK_APB1_UART2]        = &apb1_uart2_clk.common.hw,
> +               [CLK_APB1_UART3]        = &apb1_uart3_clk.common.hw,
> +               [CLK_NAND]              = &nand_clk.common.hw,
> +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> +               [CLK_MMC2]              = &mmc2_clk.common.hw,
> +               [CLK_TS]                = &ts_clk.common.hw,
> +               [CLK_SS]                = &ss_clk.common.hw,
> +               [CLK_SPI0]              = &spi0_clk.common.hw,
> +               [CLK_SPI1]              = &spi1_clk.common.hw,
> +               [CLK_SPI2]              = &spi2_clk.common.hw,
> +               [CLK_IR]                = &ir_clk.common.hw,
> +               [CLK_I2S]               = &i2s_clk.common.hw,
> +               [CLK_KEYPAD]            = &keypad_clk.common.hw,
> +               [CLK_USB_OHCI]          = &usb_ohci_clk.common.hw,
> +               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
> +               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
> +               [CLK_GPS]               = &gps_clk.common.hw,
> +               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
> +               [CLK_DRAM_CSI]          = &dram_csi_clk.common.hw,
> +               [CLK_DRAM_TS]           = &dram_ts_clk.common.hw,
> +               [CLK_DRAM_TVE]          = &dram_tve_clk.common.hw,
> +               [CLK_DRAM_DE_FE]        = &dram_de_fe_clk.common.hw,
> +               [CLK_DRAM_DE_BE]        = &dram_de_be_clk.common.hw,
> +               [CLK_DRAM_ACE]          = &dram_ace_clk.common.hw,
> +               [CLK_DRAM_IEP]          = &dram_iep_clk.common.hw,
> +               [CLK_DE_BE]             = &de_be_clk.common.hw,
> +               [CLK_DE_FE]             = &de_fe_clk.common.hw,
> +               [CLK_TCON_CH0]          = &tcon_ch0_clk.common.hw,
> +               [CLK_TCON_CH1_SCLK]     = &tcon_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON_CH1]          = &tcon_ch1_sclk1_clk.common.hw,
> +               [CLK_CSI]               = &csi_clk.common.hw,
> +               [CLK_VE]                = &ve_clk.common.hw,
> +               [CLK_CODEC]             = &codec_clk.common.hw,
> +               [CLK_AVS]               = &avs_clk.common.hw,
> +               [CLK_HDMI]              = &hdmi_clk.common.hw,
> +               [CLK_GPU]               = &gpu_clk.common.hw,
> +               [CLK_MBUS]              = &mbus_clk.common.hw,
> +               [CLK_IEP]               = &iep_clk.common.hw,
> +       },
> +       .num    = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun5i_a10s_ccu_resets[] = {
> +       [RST_USB_PHY0]          =  { 0x0cc, BIT(0) },
> +       [RST_USB_PHY1]          =  { 0x0cc, BIT(1) },
> +
> +       [RST_GPS]               =  { 0x0d0, BIT(30) },
> +
> +       [RST_DE_BE]             =  { 0x104, BIT(30) },
> +
> +       [RST_DE_FE]             =  { 0x10c, BIT(30) },
> +
> +       [RST_TVE]               =  { 0x118, BIT(29) },
> +       [RST_LCD]               =  { 0x118, BIT(30) },
> +
> +       [RST_CSI]               =  { 0x134, BIT(30) },
> +
> +       [RST_VE]                =  { 0x13c, BIT(0) },
> +
> +       [RST_GPU]               =  { 0x154, BIT(30) },
> +
> +       [RST_IEP]               =  { 0x160, BIT(30) },
> +};
> +
> +static const struct sunxi_ccu_desc sun5i_a10s_ccu_desc = {
> +       .ccu_clks       = sun5i_a10s_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun5i_a10s_ccu_clks),
> +
> +       .hw_clks        = &sun5i_a10s_hw_clks,
> +
> +       .resets         = sun5i_a10s_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun5i_a10s_ccu_resets),
> +};
> +
> +static struct clk_hw_onecell_data sun5i_a13_hw_clks = {

I selfishly want a comment on what's missing/different.

> +       .hws    = {
> +               [CLK_HOSC]              = &hosc_clk.common.hw,
> +               [CLK_OSC3M]             = &osc3M_clk.hw,
> +               [CLK_PLL_CORE]          = &pll_core_clk.common.hw,
> +               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
> +               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
> +               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
> +               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
> +               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
> +               [CLK_PLL_VIDEO0]        = &pll_video0_clk.common.hw,
> +               [CLK_PLL_VIDEO0_2X]     = &pll_video0_2x_clk.hw,
> +               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
> +               [CLK_PLL_DDR_BASE]      = &pll_ddr_base_clk.common.hw,
> +               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
> +               [CLK_PLL_DDR_OTHER]     = &pll_ddr_other_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.common.hw,
> +               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
> +               [CLK_PLL_VIDEO1_2X]     = &pll_video1_2x_clk.hw,
> +               [CLK_CPU]               = &cpu_clk.common.hw,
> +               [CLK_AXI]               = &axi_clk.common.hw,
> +               [CLK_AHB]               = &ahb_clk.common.hw,
> +               [CLK_APB0]              = &apb0_clk.common.hw,
> +               [CLK_APB1]              = &apb1_clk.common.hw,
> +               [CLK_DRAM_AXI]          = &axi_dram_clk.common.hw,
> +               [CLK_AHB_OTG]           = &ahb_otg_clk.common.hw,
> +               [CLK_AHB_EHCI]          = &ahb_ehci_clk.common.hw,
> +               [CLK_AHB_OHCI]          = &ahb_ohci_clk.common.hw,
> +               [CLK_AHB_SS]            = &ahb_ss_clk.common.hw,
> +               [CLK_AHB_DMA]           = &ahb_dma_clk.common.hw,
> +               [CLK_AHB_BIST]          = &ahb_bist_clk.common.hw,
> +               [CLK_AHB_MMC0]          = &ahb_mmc0_clk.common.hw,
> +               [CLK_AHB_MMC1]          = &ahb_mmc1_clk.common.hw,
> +               [CLK_AHB_MMC2]          = &ahb_mmc2_clk.common.hw,
> +               [CLK_AHB_NAND]          = &ahb_nand_clk.common.hw,
> +               [CLK_AHB_SDRAM]         = &ahb_sdram_clk.common.hw,
> +               [CLK_AHB_EMAC]          = &ahb_emac_clk.common.hw,
> +               [CLK_AHB_SPI0]          = &ahb_spi0_clk.common.hw,
> +               [CLK_AHB_SPI1]          = &ahb_spi1_clk.common.hw,
> +               [CLK_AHB_SPI2]          = &ahb_spi2_clk.common.hw,
> +               [CLK_AHB_HSTIMER]       = &ahb_hstimer_clk.common.hw,
> +               [CLK_AHB_VE]            = &ahb_ve_clk.common.hw,
> +               [CLK_AHB_TVE]           = &ahb_tve_clk.common.hw,
> +               [CLK_AHB_LCD]           = &ahb_lcd_clk.common.hw,
> +               [CLK_AHB_CSI]           = &ahb_csi_clk.common.hw,
> +               [CLK_AHB_DE_BE]         = &ahb_de_be_clk.common.hw,
> +               [CLK_AHB_DE_FE]         = &ahb_de_fe_clk.common.hw,
> +               [CLK_AHB_IEP]           = &ahb_iep_clk.common.hw,
> +               [CLK_AHB_GPU]           = &ahb_gpu_clk.common.hw,
> +               [CLK_APB0_CODEC]        = &apb0_codec_clk.common.hw,
> +               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
> +               [CLK_APB0_IR]           = &apb0_ir_clk.common.hw,
> +               [CLK_APB1_I2C0]         = &apb1_i2c0_clk.common.hw,
> +               [CLK_APB1_I2C1]         = &apb1_i2c1_clk.common.hw,
> +               [CLK_APB1_I2C2]         = &apb1_i2c2_clk.common.hw,
> +               [CLK_APB1_UART0]        = &apb1_uart0_clk.common.hw,
> +               [CLK_APB1_UART1]        = &apb1_uart1_clk.common.hw,
> +               [CLK_APB1_UART2]        = &apb1_uart2_clk.common.hw,
> +               [CLK_APB1_UART3]        = &apb1_uart3_clk.common.hw,
> +               [CLK_NAND]              = &nand_clk.common.hw,
> +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> +               [CLK_MMC2]              = &mmc2_clk.common.hw,
> +               [CLK_SS]                = &ss_clk.common.hw,
> +               [CLK_SPI0]              = &spi0_clk.common.hw,
> +               [CLK_SPI1]              = &spi1_clk.common.hw,
> +               [CLK_SPI2]              = &spi2_clk.common.hw,
> +               [CLK_IR]                = &ir_clk.common.hw,
> +               [CLK_USB_OHCI]          = &usb_ohci_clk.common.hw,
> +               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
> +               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
> +               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
> +               [CLK_DRAM_CSI]          = &dram_csi_clk.common.hw,
> +               [CLK_DRAM_TVE]          = &dram_tve_clk.common.hw,
> +               [CLK_DRAM_DE_FE]        = &dram_de_fe_clk.common.hw,
> +               [CLK_DRAM_DE_BE]        = &dram_de_be_clk.common.hw,
> +               [CLK_DRAM_ACE]          = &dram_ace_clk.common.hw,
> +               [CLK_DRAM_IEP]          = &dram_iep_clk.common.hw,
> +               [CLK_DE_BE]             = &de_be_clk.common.hw,
> +               [CLK_DE_FE]             = &de_fe_clk.common.hw,
> +               [CLK_TCON_CH0]          = &tcon_ch0_clk.common.hw,
> +               [CLK_TCON_CH1_SCLK]     = &tcon_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON_CH1]          = &tcon_ch1_sclk1_clk.common.hw,
> +               [CLK_CSI]               = &csi_clk.common.hw,
> +               [CLK_VE]                = &ve_clk.common.hw,
> +               [CLK_CODEC]             = &codec_clk.common.hw,
> +               [CLK_AVS]               = &avs_clk.common.hw,
> +               [CLK_GPU]               = &gpu_clk.common.hw,
> +               [CLK_MBUS]              = &mbus_clk.common.hw,
> +               [CLK_IEP]               = &iep_clk.common.hw,
> +       },
> +       .num    = CLK_NUMBER,
> +};
> +
> +static const struct sunxi_ccu_desc sun5i_a13_ccu_desc = {
> +       .ccu_clks       = sun5i_a10s_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun5i_a10s_ccu_clks),
> +
> +       .hw_clks        = &sun5i_a13_hw_clks,
> +
> +       .resets         = sun5i_a10s_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun5i_a10s_ccu_resets),
> +};
> +
> +static struct clk_hw_onecell_data sun5i_gr8_hw_clks = {
> +       .hws    = {
> +               [CLK_HOSC]              = &hosc_clk.common.hw,
> +               [CLK_OSC3M]             = &osc3M_clk.hw,
> +               [CLK_PLL_CORE]          = &pll_core_clk.common.hw,
> +               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
> +               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
> +               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
> +               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
> +               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
> +               [CLK_PLL_VIDEO0]        = &pll_video0_clk.common.hw,
> +               [CLK_PLL_VIDEO0_2X]     = &pll_video0_2x_clk.hw,
> +               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
> +               [CLK_PLL_DDR_BASE]      = &pll_ddr_base_clk.common.hw,
> +               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
> +               [CLK_PLL_DDR_OTHER]     = &pll_ddr_other_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.common.hw,
> +               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
> +               [CLK_PLL_VIDEO1_2X]     = &pll_video1_2x_clk.hw,
> +               [CLK_CPU]               = &cpu_clk.common.hw,
> +               [CLK_AXI]               = &axi_clk.common.hw,
> +               [CLK_AHB]               = &ahb_clk.common.hw,
> +               [CLK_APB0]              = &apb0_clk.common.hw,
> +               [CLK_APB1]              = &apb1_clk.common.hw,
> +               [CLK_DRAM_AXI]          = &axi_dram_clk.common.hw,
> +               [CLK_AHB_OTG]           = &ahb_otg_clk.common.hw,
> +               [CLK_AHB_EHCI]          = &ahb_ehci_clk.common.hw,
> +               [CLK_AHB_OHCI]          = &ahb_ohci_clk.common.hw,
> +               [CLK_AHB_SS]            = &ahb_ss_clk.common.hw,
> +               [CLK_AHB_DMA]           = &ahb_dma_clk.common.hw,
> +               [CLK_AHB_BIST]          = &ahb_bist_clk.common.hw,
> +               [CLK_AHB_MMC0]          = &ahb_mmc0_clk.common.hw,
> +               [CLK_AHB_MMC1]          = &ahb_mmc1_clk.common.hw,
> +               [CLK_AHB_MMC2]          = &ahb_mmc2_clk.common.hw,
> +               [CLK_AHB_NAND]          = &ahb_nand_clk.common.hw,
> +               [CLK_AHB_SDRAM]         = &ahb_sdram_clk.common.hw,
> +               [CLK_AHB_SPI0]          = &ahb_spi0_clk.common.hw,
> +               [CLK_AHB_SPI2]          = &ahb_spi2_clk.common.hw,
> +               [CLK_AHB_HSTIMER]       = &ahb_hstimer_clk.common.hw,
> +               [CLK_AHB_VE]            = &ahb_ve_clk.common.hw,
> +               [CLK_AHB_TVE]           = &ahb_tve_clk.common.hw,
> +               [CLK_AHB_LCD]           = &ahb_lcd_clk.common.hw,
> +               [CLK_AHB_CSI]           = &ahb_csi_clk.common.hw,
> +               [CLK_AHB_DE_BE]         = &ahb_de_be_clk.common.hw,
> +               [CLK_AHB_DE_FE]         = &ahb_de_fe_clk.common.hw,
> +               [CLK_AHB_IEP]           = &ahb_iep_clk.common.hw,
> +               [CLK_AHB_GPU]           = &ahb_gpu_clk.common.hw,
> +               [CLK_APB0_CODEC]        = &apb0_codec_clk.common.hw,
> +               [CLK_APB0_SPDIF]        = &apb0_spdif_clk.common.hw,
> +               [CLK_APB0_I2S]          = &apb0_i2s_clk.common.hw,
> +               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
> +               [CLK_APB0_IR]           = &apb0_ir_clk.common.hw,
> +               [CLK_APB1_I2C0]         = &apb1_i2c0_clk.common.hw,
> +               [CLK_APB1_I2C1]         = &apb1_i2c1_clk.common.hw,
> +               [CLK_APB1_I2C2]         = &apb1_i2c2_clk.common.hw,
> +               [CLK_APB1_UART0]        = &apb1_uart0_clk.common.hw,
> +               [CLK_APB1_UART1]        = &apb1_uart1_clk.common.hw,
> +               [CLK_APB1_UART2]        = &apb1_uart2_clk.common.hw,
> +               [CLK_APB1_UART3]        = &apb1_uart3_clk.common.hw,
> +               [CLK_NAND]              = &nand_clk.common.hw,
> +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> +               [CLK_MMC2]              = &mmc2_clk.common.hw,
> +               [CLK_SS]                = &ss_clk.common.hw,
> +               [CLK_SPI0]              = &spi0_clk.common.hw,
> +               [CLK_SPI2]              = &spi2_clk.common.hw,
> +               [CLK_IR]                = &ir_clk.common.hw,
> +               [CLK_I2S]               = &i2s_clk.common.hw,
> +               [CLK_SPDIF]             = &spdif_clk.common.hw,
> +               [CLK_USB_OHCI]          = &usb_ohci_clk.common.hw,
> +               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
> +               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
> +               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
> +               [CLK_DRAM_CSI]          = &dram_csi_clk.common.hw,
> +               [CLK_DRAM_TVE]          = &dram_tve_clk.common.hw,
> +               [CLK_DRAM_DE_FE]        = &dram_de_fe_clk.common.hw,
> +               [CLK_DRAM_DE_BE]        = &dram_de_be_clk.common.hw,
> +               [CLK_DRAM_ACE]          = &dram_ace_clk.common.hw,
> +               [CLK_DRAM_IEP]          = &dram_iep_clk.common.hw,
> +               [CLK_DE_BE]             = &de_be_clk.common.hw,
> +               [CLK_DE_FE]             = &de_fe_clk.common.hw,
> +               [CLK_TCON_CH0]          = &tcon_ch0_clk.common.hw,
> +               [CLK_TCON_CH1_SCLK]     = &tcon_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON_CH1]          = &tcon_ch1_sclk1_clk.common.hw,
> +               [CLK_CSI]               = &csi_clk.common.hw,
> +               [CLK_VE]                = &ve_clk.common.hw,
> +               [CLK_CODEC]             = &codec_clk.common.hw,
> +               [CLK_AVS]               = &avs_clk.common.hw,
> +               [CLK_GPU]               = &gpu_clk.common.hw,
> +               [CLK_MBUS]              = &mbus_clk.common.hw,
> +               [CLK_IEP]               = &iep_clk.common.hw,
> +       },
> +       .num    = CLK_NUMBER,
> +};
> +
> +static const struct sunxi_ccu_desc sun5i_gr8_ccu_desc = {
> +       .ccu_clks       = sun5i_a10s_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun5i_a10s_ccu_clks),
> +
> +       .hw_clks        = &sun5i_gr8_hw_clks,
> +
> +       .resets         = sun5i_a10s_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun5i_a10s_ccu_resets),
> +};
> +
> +static void __init sun5i_ccu_init(struct device_node *node,
> +                                 const struct sunxi_ccu_desc *desc)
> +{
> +       void __iomem *reg;
> +       u32 val;
> +
> +       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%s: Could not map the clock registers\n",
> +                      of_node_full_name(node));
> +               return;
> +       }
> +
> +       /* Force the PLL-Audio-1x divider to 4 */
> +       val = readl(reg + SUN5I_PLL_AUDIO_REG);
> +       val &= ~GENMASK(19, 16);
> +       writel(val | (3 << 16), reg + SUN5I_PLL_AUDIO_REG);
> +
> +       /*
> +        * Use the peripheral PLL as the AHB parent, instead of CPU /
> +        * AXI which have rate changes due to cpufreq.
> +        *
> +        * This is especially a big deal for the HS timer whose parent
> +        * clock is AHB.
> +        */
> +       val = readl(reg + SUN5I_AHB_REG);
> +       val &= ~GENMASK(7, 6);
> +       writel(val | (2 << 6), reg + SUN5I_AHB_REG);
> +
> +       sunxi_ccu_probe(node, reg, desc);
> +}
> +
> +static void __init sun5i_a10s_ccu_setup(struct device_node *node)
> +{
> +       sun5i_ccu_init(node, &sun5i_a10s_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun5i_a10s_ccu, "allwinner,sun5i-a10s-ccu",
> +              sun5i_a10s_ccu_setup);
> +
> +static void __init sun5i_a13_ccu_setup(struct device_node *node)
> +{
> +       sun5i_ccu_init(node, &sun5i_a13_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun5i_a13_ccu, "allwinner,sun5i-a13-ccu",
> +              sun5i_a13_ccu_setup);
> +
> +static void __init sun5i_gr8_ccu_setup(struct device_node *node)
> +{
> +       sun5i_ccu_init(node, &sun5i_gr8_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun5i_gr8_ccu, "nextthing,gr8-ccu",
> +              sun5i_gr8_ccu_setup);

It should be possible to do a standard platform driver, right?
The rest looks good, though I did not go through the list of
clocks for the A13 and GR8.

Regards
ChenYu

> diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.h b/drivers/clk/sunxi-ng/ccu-sun5i.h
> new file mode 100644
> index 000000000000..5bacf65cc89d
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun5i.h
> @@ -0,0 +1,68 @@
> +/*
> + * Copyright 2016 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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 _CCU_SUN5I_H_
> +#define _CCU_SUN5I_H_
> +
> +#include <dt-bindings/clock/sun5i-ccu.h>
> +#include <dt-bindings/reset/sun5i-ccu.h>
> +
> +/* The HOSC is exported */
> +#define CLK_OSC3M              2
> +#define CLK_PLL_CORE           3
> +#define CLK_PLL_AUDIO_BASE     4
> +#define CLK_PLL_AUDIO          5
> +#define CLK_PLL_AUDIO_2X       6
> +#define CLK_PLL_AUDIO_4X       7
> +#define CLK_PLL_AUDIO_8X       8
> +#define CLK_PLL_VIDEO0         9
> +#define CLK_PLL_VIDEO0_2X      10
> +#define CLK_PLL_VE             11
> +#define CLK_PLL_DDR_BASE       12
> +#define CLK_PLL_DDR            13
> +#define CLK_PLL_DDR_OTHER      14
> +#define CLK_PLL_PERIPH         15
> +#define CLK_PLL_VIDEO1         16
> +#define CLK_PLL_VIDEO1_2X      17
> +
> +/* The CPU clock is exported */
> +
> +#define CLK_AXI                        19
> +#define CLK_AHB                        20
> +#define CLK_APB0               21
> +#define CLK_APB1               22
> +#define CLK_DRAM_AXI           23
> +
> +/* AHB gates are exported */
> +/* APB0 gates are exported */
> +/* APB1 gates are exported */
> +/* Modules clocks are exported */
> +/* USB clocks are exported */
> +/* GPS clock is exported */
> +/* DRAM gates are exported */
> +/* More display modules clocks are exported */
> +
> +#define CLK_TCON_CH1_SCLK      92
> +
> +/* The rest of the module clocks are exported */
> +
> +#define CLK_MBUS               100
> +
> +/* And finally the IEP clock */
> +
> +#define CLK_NUMBER             (CLK_IEP + 1)
> +
> +#endif /* _CCU_SUN5I_H_ */
> --
> git-series 0.8.11

^ permalink raw reply

* [PATCH 1/1] iommu/arm-smmu: Fix for ThunderX erratum #27704
From: Tomasz Nowicki @ 2017-01-16  7:16 UTC (permalink / raw)
  To: linux-arm-kernel

The goal of erratum #27704 workaround was to make sure that ASIDs and VMIDs
are unique across all SMMU instances on affected Cavium systems.

Currently, the workaround code partitions ASIDs and VMIDs by increasing
global cavium_smmu_context_count which in turn becomes the base ASID and VMID
value for the given SMMU instance upon the context bank initialization.

For systems with multiple SMMU instances this approach implies the risk
of crossing 8-bit ASID, like for 1-socket CN88xx capable of 4 SMMUv2,
128 context banks each:
SMMU_0 (0-127 ASID RANGE)
SMMU_1 (127-255 ASID RANGE)
SMMU_2 (256-383 ASID RANGE) <--- crossing 8-bit ASID
SMMU_3 (384-511 ASID RANGE) <--- crossing 8-bit ASID

Since now we use 8-bit ASID (SMMU_CBn_TCR2.AS = 0) we effectively misconfigure
ASID[15:8] bits of SMMU_CBn_TTBRm register for SMMU_2/3. Moreover, we still
assume non-zero ASID[15:8] bits upon context invalidation. In the end,
except SMMU_0/1 devices all other devices under other SMMUs will fail on guest
power off/on. Since we try to invalidate TLB with 16-bit ASID but we actually
have 8-bit zero padded 16-bit entry.

This patch adds 16-bit ASID support for stage-1 AArch64 contexts so that
we use ASIDs consistently for all SMMU instances.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Reviewed-by: Tirumalesh Chalamarla  <Tirumalesh.Chalamarla@cavium.com>
---
 drivers/iommu/arm-smmu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a60cded..476fab9 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -260,6 +260,7 @@ enum arm_smmu_s2cr_privcfg {
 
 #define TTBCR2_SEP_SHIFT		15
 #define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_AS			(1 << 4)
 
 #define TTBRn_ASID_SHIFT		48
 
@@ -778,6 +779,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
 			reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
 			reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
 			reg2 |= TTBCR2_SEP_UPSTREAM;
+			if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
+				reg2 |= TTBCR2_AS;
 		}
 		if (smmu->version > ARM_SMMU_V1)
 			writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 6/7] ARM: sun5i: Convert to CCU
From: Chen-Yu Tsai @ 2017-01-16  7:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a1638ea1b11aa011e4f261877a8c23ec8b88df2c.1484035021.git-series.maxime.ripard@free-electrons.com>

On Tue, Jan 10, 2017 at 3:57 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Now that we have drivers for all of them, convert all the SoCs that share
> the sun5i DTSI to the new CCU driver.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH v2 7/7] ARM: gr8: Convert to CCU
From: Chen-Yu Tsai @ 2017-01-16  7:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <94871a4361ecff107ab4791de2bd0f85992794b7.1484035021.git-series.maxime.ripard@free-electrons.com>

On Tue, Jan 10, 2017 at 3:57 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Now that we have a driver for the GR8, we can convert our DT to it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH v6 2/3] input: tm2-touchkey: Add touchkey driver support for TM2
From: Jaechul Lee @ 2017-01-16  7:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170115071110.GA24007@dtor-ws>

Dear Dmitry Torokhov,

On Sat, Jan 14, 2017 at 11:11:10PM -0800, Dmitry Torokhov wrote:
> Hi Jaechul,
> 
> On Mon, Jan 09, 2017 at 04:22:14PM +0900, Jaechul Lee wrote:
> > +static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
> > +{
> > +	struct tm2_touchkey_data *touchkey = devid;
> > +	u32 data;
> > +
> > +	data = i2c_smbus_read_byte_data(touchkey->client,
> > +					TM2_TOUCHKEY_KEYCODE_REG);
> > +
> > +	if (data < 0) {
> 
> You declared data as u32 so it will never be negative.

Yes, it won't be negative.

> 
> > +		dev_err(&touchkey->client->dev, "Failed to read i2c data\n");
> > +		return IRQ_HANDLED;
> > +	}
> > +
> > +	touchkey->keycode_type = data & TM2_TOUCHKEY_BIT_KEYCODE;
> > +	touchkey->pressed = !(data & TM2_TOUCHKEY_BIT_PRESS_EV);
> 
> There is no need to store this in touchkey structure as you are not
> going to use it past this function.

I agree with you. it doesn't need to store variables in touchkey structure.

> 
> Does the version of the patch below work for you?

I found that the condition is inverted.
if data & TM2_TOUCHKEY_BIT_PRESS_EV is true, it means touchkey is released.

it should be changed like this.

	if (data & TM2_TOUCHKEY_BIT_PRESS_EV) {
		input_report_key(touchkey->input_dev, KEY_PHONE, 0);
		input_report_key(touchkey->input_dev, KEY_BACK, 0);
	} else {
		input_report_key(touchkey->input_dev, key, 1);
	}

I will prepare for patch v7 based on your modifications.
Thank you very much for your reviews.

Best Regards,
Jaechul

> 
> Thanks.
> 
> -- 
> Dmitry
> 
> 
> Input: tm2-touchkey - add touchkey driver support for TM2
> 
> From: Jaechul Lee <jcsing.lee@samsung.com>
> 
> This patch adds support for the TM2 touch key and led functionality.
> 
> The driver interfaces with userspace through an input device and
> reports KEY_PHONE and KEY_BACK event types. LED brightness can be
> controlled by "/sys/class/leds/tm2-touchkey/brightness".
> 
> Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
> Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
> Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
> Reviewed-by: Andi Shyti <andi.shyti@samsung.com>
> Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
> Patchwork-Id: 9504149
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>  drivers/input/keyboard/Kconfig        |   11 +
>  drivers/input/keyboard/Makefile       |    1 
>  drivers/input/keyboard/tm2-touchkey.c |  286 +++++++++++++++++++++++++++++++++
>  3 files changed, 298 insertions(+)
>  create mode 100644 drivers/input/keyboard/tm2-touchkey.c
> 
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index cbd75cf44739..97acd6524ad7 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -666,6 +666,17 @@ config KEYBOARD_TC3589X
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called tc3589x-keypad.
>  
> +config KEYBOARD_TM2_TOUCHKEY
> +	tristate "TM2 touchkey support"
> +	depends on I2C
> +	depends on LEDS_CLASS
> +	help
> +	  Say Y here to enable device driver for tm2-touchkey with
> +	  LED control for the Exynos5433 TM2 board.
> +
> +	  To compile this driver as a module, choose M here.
> +	  module will be called tm2-touchkey.
> +
>  config KEYBOARD_TWL4030
>  	tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
>  	depends on TWL4030_CORE
> diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
> index d9f4cfcf3410..7d9acff819a7 100644
> --- a/drivers/input/keyboard/Makefile
> +++ b/drivers/input/keyboard/Makefile
> @@ -61,6 +61,7 @@ obj-$(CONFIG_KEYBOARD_SUN4I_LRADC)	+= sun4i-lradc-keys.o
>  obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
>  obj-$(CONFIG_KEYBOARD_TC3589X)		+= tc3589x-keypad.o
>  obj-$(CONFIG_KEYBOARD_TEGRA)		+= tegra-kbc.o
> +obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY)	+= tm2-touchkey.o
>  obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
>  obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
>  obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
> diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
> new file mode 100644
> index 000000000000..79bc2d2bd4b9
> --- /dev/null
> +++ b/drivers/input/keyboard/tm2-touchkey.c
> @@ -0,0 +1,286 @@
> +/*
> + * TM2 touchkey device driver
> + *
> + * Copyright 2005 Phil Blundell
> + * Copyright 2016 Samsung Electronics Co., Ltd.
> + *
> + * Author: Beomho Seo <beomho.seo@samsung.com>
> + * Author: Jaechul Lee <jcsing.lee@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/i2c.h>
> +#include <linux/input.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/pm.h>
> +#include <linux/regulator/consumer.h>
> +
> +#define TM2_TOUCHKEY_DEV_NAME		"tm2-touchkey"
> +#define TM2_TOUCHKEY_KEYCODE_REG	0x03
> +#define TM2_TOUCHKEY_BASE_REG		0x00
> +#define TM2_TOUCHKEY_CMD_LED_ON		0x10
> +#define TM2_TOUCHKEY_CMD_LED_OFF	0x20
> +#define TM2_TOUCHKEY_BIT_PRESS_EV	BIT(3)
> +#define TM2_TOUCHKEY_BIT_KEYCODE	GENMASK(2, 0)
> +#define TM2_TOUCHKEY_LED_VOLTAGE_MIN	2500000
> +#define TM2_TOUCHKEY_LED_VOLTAGE_MAX	3300000
> +
> +enum {
> +	TM2_TOUCHKEY_KEY_MENU = 0x1,
> +	TM2_TOUCHKEY_KEY_BACK,
> +};
> +
> +struct tm2_touchkey_data {
> +	struct i2c_client *client;
> +	struct input_dev *input_dev;
> +	struct led_classdev led_dev;
> +	struct regulator *vdd;
> +	struct regulator_bulk_data regulators[2];
> +};
> +
> +static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
> +					    enum led_brightness brightness)
> +{
> +	struct tm2_touchkey_data *touchkey =
> +		container_of(led_dev, struct tm2_touchkey_data, led_dev);
> +	u32 volt;
> +	u8 data;
> +
> +	if (brightness == LED_OFF) {
> +		volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN;
> +		data = TM2_TOUCHKEY_CMD_LED_OFF;
> +	} else {
> +		volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX;
> +		data = TM2_TOUCHKEY_CMD_LED_ON;
> +	}
> +
> +	regulator_set_voltage(touchkey->vdd, volt, volt);
> +	i2c_smbus_write_byte_data(touchkey->client,
> +				  TM2_TOUCHKEY_BASE_REG, data);
> +}
> +
> +static int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey)
> +{
> +	int error;
> +
> +	error = regulator_bulk_enable(ARRAY_SIZE(touchkey->regulators),
> +				      touchkey->regulators);
> +	if (error)
> +		return error;
> +
> +	/* waiting for device initialization, at least 150ms */
> +	msleep(150);
> +
> +	return 0;
> +}
> +
> +static void tm2_touchkey_power_disable(void *data)
> +{
> +	struct tm2_touchkey_data *touchkey = data;
> +
> +	regulator_bulk_disable(ARRAY_SIZE(touchkey->regulators),
> +			       touchkey->regulators);
> +}
> +
> +static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
> +{
> +	struct tm2_touchkey_data *touchkey = devid;
> +	int data;
> +	int key;
> +
> +	data = i2c_smbus_read_byte_data(touchkey->client,
> +					TM2_TOUCHKEY_KEYCODE_REG);
> +	if (data < 0) {
> +		dev_err(&touchkey->client->dev,
> +			"failed to read i2c data: %d\n", data);
> +		goto out;
> +	}
> +
> +	switch (data & TM2_TOUCHKEY_BIT_KEYCODE) {
> +	case TM2_TOUCHKEY_KEY_MENU:
> +		key = KEY_PHONE;
> +		break;
> +
> +	case TM2_TOUCHKEY_KEY_BACK:
> +		key = KEY_BACK;
> +		break;
> +
> +	default:
> +		dev_warn(&touchkey->client->dev,
> +			 "unhandled keycode, data %#02x\n", data);
> +		goto out;
> +	}
> +
> +	if (data & TM2_TOUCHKEY_BIT_PRESS_EV) {
> +		input_report_key(touchkey->input_dev, key, 1);
> +	} else {
> +		input_report_key(touchkey->input_dev, KEY_PHONE, 0);
> +		input_report_key(touchkey->input_dev, KEY_BACK, 0);
> +	}
> +
> +	input_sync(touchkey->input_dev);
> +
> +out:
> +	return IRQ_HANDLED;
> +}
> +
> +static int tm2_touchkey_probe(struct i2c_client *client,
> +			      const struct i2c_device_id *id)
> +{
> +	struct tm2_touchkey_data *touchkey;
> +	int error;
> +
> +	if (!i2c_check_functionality(client->adapter,
> +			I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) {
> +		dev_err(&client->dev, "incompatible I2C adapter\n");
> +		return -EIO;
> +	}
> +
> +	touchkey = devm_kzalloc(&client->dev, sizeof(*touchkey), GFP_KERNEL);
> +	if (!touchkey)
> +		return -ENOMEM;
> +
> +	touchkey->client = client;
> +	i2c_set_clientdata(client, touchkey);
> +
> +	touchkey->regulators[0].supply = "vcc";
> +	touchkey->regulators[1].supply = "vdd";
> +	error = devm_regulator_bulk_get(&client->dev,
> +					ARRAY_SIZE(touchkey->regulators),
> +					touchkey->regulators);
> +	if (error) {
> +		dev_err(&client->dev, "failed to get regulators: %d\n", error);
> +		return error;
> +	}
> +
> +	/* Save VDD for easy access */
> +	touchkey->vdd = touchkey->regulators[1].consumer;
> +
> +	error = tm2_touchkey_power_enable(touchkey);
> +	if (error) {
> +		dev_err(&client->dev, "failed to power up device: %d\n", error);
> +		return error;
> +	}
> +
> +	error = devm_add_action_or_reset(&client->dev,
> +					 tm2_touchkey_power_disable, touchkey);
> +	if (error) {
> +		dev_err(&client->dev,
> +			"failed to install poweroff handler: %d\n", error);
> +		return error;
> +	}
> +
> +	/* input device */
> +	touchkey->input_dev = devm_input_allocate_device(&client->dev);
> +	if (!touchkey->input_dev) {
> +		dev_err(&client->dev, "failed to allocate input device\n");
> +		return -ENOMEM;
> +	}
> +
> +	touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME;
> +	touchkey->input_dev->id.bustype = BUS_I2C;
> +
> +	input_set_capability(touchkey->input_dev, EV_KEY, KEY_PHONE);
> +	input_set_capability(touchkey->input_dev, EV_KEY, KEY_BACK);
> +
> +	input_set_drvdata(touchkey->input_dev, touchkey);
> +
> +	error = input_register_device(touchkey->input_dev);
> +	if (error) {
> +		dev_err(&client->dev,
> +			"failed to register input device: %d\n", error);
> +		return error;
> +	}
> +
> +	error = devm_request_threaded_irq(&client->dev, client->irq,
> +					  NULL, tm2_touchkey_irq_handler,
> +					  IRQF_ONESHOT,
> +					  TM2_TOUCHKEY_DEV_NAME, touchkey);
> +	if (error) {
> +		dev_err(&client->dev,
> +			"failed to request threaded irq: %d\n", error);
> +		return error;
> +	}
> +
> +	/* led device */
> +	touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
> +	touchkey->led_dev.brightness = LED_FULL;
> +	touchkey->led_dev.max_brightness = LED_FULL;
> +	touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set;
> +
> +	error = devm_led_classdev_register(&client->dev, &touchkey->led_dev);
> +	if (error) {
> +		dev_err(&client->dev,
> +			"failed to register touchkey led: %d\n", error);
> +		return error;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused tm2_touchkey_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client);
> +
> +	disable_irq(client->irq);
> +	tm2_touchkey_power_disable(touchkey);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused tm2_touchkey_resume(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client);
> +	int ret;
> +
> +	enable_irq(client->irq);
> +
> +	ret = tm2_touchkey_power_enable(touchkey);
> +	if (ret)
> +		dev_err(dev, "failed to enable power: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
> +			 tm2_touchkey_suspend, tm2_touchkey_resume);
> +
> +static const struct i2c_device_id tm2_touchkey_id_table[] = {
> +	{ TM2_TOUCHKEY_DEV_NAME, 0 },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
> +
> +static const struct of_device_id tm2_touchkey_of_match[] = {
> +	{ .compatible = "cypress,tm2-touchkey", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match);
> +
> +static struct i2c_driver tm2_touchkey_driver = {
> +	.driver = {
> +		.name = TM2_TOUCHKEY_DEV_NAME,
> +		.pm = &tm2_touchkey_pm_ops,
> +		.of_match_table = of_match_ptr(tm2_touchkey_of_match),
> +	},
> +	.probe = tm2_touchkey_probe,
> +	.id_table = tm2_touchkey_id_table,
> +};
> +module_i2c_driver(tm2_touchkey_driver);
> +
> +MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
> +MODULE_AUTHOR("Jaechul Lee <jcsing.lee@samsung.com>");
> +MODULE_DESCRIPTION("Samsung touchkey driver");
> +MODULE_LICENSE("GPL v2");
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/1] iommu/arm-smmu: Fix for ThunderX erratum #27704
From: Tomasz Nowicki @ 2017-01-16  7:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484550967-6328-1-git-send-email-tn@semihalf.com>

My apologise for not adding 2nd version info of this patch to mail subject.

Thanks,
Tomasz

On 16.01.2017 08:16, Tomasz Nowicki wrote:
> The goal of erratum #27704 workaround was to make sure that ASIDs and VMIDs
> are unique across all SMMU instances on affected Cavium systems.
>
> Currently, the workaround code partitions ASIDs and VMIDs by increasing
> global cavium_smmu_context_count which in turn becomes the base ASID and VMID
> value for the given SMMU instance upon the context bank initialization.
>
> For systems with multiple SMMU instances this approach implies the risk
> of crossing 8-bit ASID, like for 1-socket CN88xx capable of 4 SMMUv2,
> 128 context banks each:
> SMMU_0 (0-127 ASID RANGE)
> SMMU_1 (127-255 ASID RANGE)
> SMMU_2 (256-383 ASID RANGE) <--- crossing 8-bit ASID
> SMMU_3 (384-511 ASID RANGE) <--- crossing 8-bit ASID
>
> Since now we use 8-bit ASID (SMMU_CBn_TCR2.AS = 0) we effectively misconfigure
> ASID[15:8] bits of SMMU_CBn_TTBRm register for SMMU_2/3. Moreover, we still
> assume non-zero ASID[15:8] bits upon context invalidation. In the end,
> except SMMU_0/1 devices all other devices under other SMMUs will fail on guest
> power off/on. Since we try to invalidate TLB with 16-bit ASID but we actually
> have 8-bit zero padded 16-bit entry.
>
> This patch adds 16-bit ASID support for stage-1 AArch64 contexts so that
> we use ASIDs consistently for all SMMU instances.
>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> Reviewed-by: Robin Murphy <robin.murphy@arm.com>
> Reviewed-by: Tirumalesh Chalamarla  <Tirumalesh.Chalamarla@cavium.com>
> ---
>  drivers/iommu/arm-smmu.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index a60cded..476fab9 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -260,6 +260,7 @@ enum arm_smmu_s2cr_privcfg {
>
>  #define TTBCR2_SEP_SHIFT		15
>  #define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
> +#define TTBCR2_AS			(1 << 4)
>
>  #define TTBRn_ASID_SHIFT		48
>
> @@ -778,6 +779,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
>  			reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
>  			reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
>  			reg2 |= TTBCR2_SEP_UPSTREAM;
> +			if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
> +				reg2 |= TTBCR2_AS;
>  		}
>  		if (smmu->version > ARM_SMMU_V1)
>  			writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
>

^ permalink raw reply

* [PATCH v1 3/3] reset: zx2967: add reset controller driver for ZTE's zx2967 family
From: Shawn Guo @ 2017-01-16  7:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484377530-30635-3-git-send-email-baoyou.xie@linaro.org>

On Sat, Jan 14, 2017 at 03:05:30PM +0800, Baoyou Xie wrote:
> This patch adds reset controller driver for ZTE's zx2967 family.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
>  drivers/reset/Kconfig        |   6 ++
>  drivers/reset/Makefile       |   1 +
>  drivers/reset/reset-zx2967.c | 136 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 143 insertions(+)
>  create mode 100644 drivers/reset/reset-zx2967.c
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 172dc96..972d077 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -92,6 +92,12 @@ config RESET_ZYNQ
>  	help
>  	  This enables the reset controller driver for Xilinx Zynq SoCs.
>  
> +config RESET_ZX2967
> +	bool "ZX2967 Reset Driver"
> +	depends on ARCH_ZX || COMPILE_TEST
> +	help
> +	  This enables the reset controller driver for ZTE zx2967 family.
> +

The config options seem to be sorted alphabetically, so RESET_ZX2967
should be put before RESET_ZYNQ.

>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
>  source "drivers/reset/tegra/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 13b346e..807b77b 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
>  obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
>  obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
> +obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o

Ditto

> diff --git a/drivers/reset/reset-zx2967.c b/drivers/reset/reset-zx2967.c
> new file mode 100644
> index 0000000..63f9c41
> --- /dev/null
> +++ b/drivers/reset/reset-zx2967.c
> @@ -0,0 +1,136 @@
> +/*
> + * ZTE's zx2967 family thermal sensor driver
> + *
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +
> +struct zx2967_reset {
> +	void __iomem			*reg_base;
> +	spinlock_t			lock;
> +	struct reset_controller_dev	rcdev;
> +};
> +
> +static int zx2967_reset_assert(struct reset_controller_dev *rcdev,
> +			   unsigned long id)
> +{
> +	struct zx2967_reset *reset = NULL;
> +	int bank = id / 32;
> +	int offset = id % 32;
> +	unsigned int reg;
> +	unsigned long flags;
> +
> +	reset = container_of(rcdev, struct zx2967_reset, rcdev);
> +
> +	spin_lock_irqsave(&reset->lock, flags);
> +
> +	reg = readl(reset->reg_base + (bank * 4));
> +	writel(reg & ~BIT(offset), reset->reg_base + (bank * 4));
> +	reg = readl(reset->reg_base + (bank * 4));
> +
> +	spin_unlock_irqrestore(&reset->lock, flags);
> +
> +	return 0;
> +}
> +
> +static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
> +			     unsigned long id)
> +{
> +	struct zx2967_reset *reset = NULL;
> +	int bank = id / 32;
> +	int offset = id % 32;
> +	unsigned int reg;
> +	unsigned long flags;
> +
> +	reset = container_of(rcdev, struct zx2967_reset, rcdev);
> +
> +	spin_lock_irqsave(&reset->lock, flags);
> +
> +	reg = readl(reset->reg_base + (bank * 4));
> +	writel(reg | BIT(offset), reset->reg_base + (bank * 4));
> +	reg = readl(reset->reg_base + (bank * 4));
> +
> +	spin_unlock_irqrestore(&reset->lock, flags);
> +
> +	return 0;
> +}
> +
> +static struct reset_control_ops zx2967_reset_ops = {
> +	.assert		= zx2967_reset_assert,
> +	.deassert	= zx2967_reset_deassert,
> +};
> +
> +static int zx2967_reset_probe(struct platform_device *pdev)
> +{
> +	struct zx2967_reset *reset;
> +	struct resource *res;
> +
> +	reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
> +	if (!reset)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	reset->reg_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(reset->reg_base))
> +		return PTR_ERR(reset->reg_base);
> +
> +	spin_lock_init(&reset->lock);
> +
> +	reset->rcdev.owner = THIS_MODULE;
> +	reset->rcdev.nr_resets = resource_size(res) * 8;
> +	reset->rcdev.ops = &zx2967_reset_ops;
> +	reset->rcdev.of_node = pdev->dev.of_node;
> +
> +	dev_info(&pdev->dev, "reset controller cnt:%d",
> +		  reset->rcdev.nr_resets);
> +
> +	return reset_controller_register(&reset->rcdev);

Use devm_reset_controller_register(), then we can save the call to
reset_controller_unregister().

Shawn

> +}
> +
> +static int zx2967_reset_remove(struct platform_device *pdev)
> +{
> +	struct zx2967_reset *reset = platform_get_drvdata(pdev);
> +
> +	reset_controller_unregister(&reset->rcdev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id zx2967_reset_dt_ids[] = {
> +	 { .compatible = "zte,zx296718-reset", },
> +	 {},
> +};
> +MODULE_DEVICE_TABLE(of, zx2967_reset_dt_ids);
> +
> +static struct platform_driver zx2967_reset_driver = {
> +	.probe	= zx2967_reset_probe,
> +	.remove	= zx2967_reset_remove,
> +	.driver = {
> +		.name		= "zx2967-reset",
> +		.of_match_table	= zx2967_reset_dt_ids,
> +	},
> +};
> +
> +static int __init zx2967_reset_init(void)
> +{
> +	return platform_driver_register(&zx2967_reset_driver);
> +}
> +arch_initcall(zx2967_reset_init);
> +
> +static void __exit zx2967_reset_exit(void)
> +{
> +	platform_driver_unregister(&zx2967_reset_driver);
> +}
> +module_exit(zx2967_reset_exit);
> +
> +MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
> +MODULE_DESCRIPTION("ZTE zx2967 Reset Controller Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.7.4
> 

^ permalink raw reply

* USB: OHCI: high softirq load
From: Antoine Aubert @ 2017-01-16  7:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Im working on a AT91SAM9G25cu board
(arch/arm/boot/dts/at91-kizboxmini.dts). We use linux-4.1.31, and when
OHCI is enabled, I got some wired effects.

eg with 3 FTDI pluged, interrupts: more than 3.5k/s, cpu softirq > 24%,
loadavg > 0.5

This issue disappear when disabling OHCI and use EHCI only.

What are the usual causes, and where to begin with ?

Thanks in advance,

-- 
Antoine Aubert
a.aubert at overkiz.com

^ permalink raw reply

* [PATCH v1 3/3] reset: zx2967: add reset controller driver for ZTE's zx2967 family
From: Shawn Guo @ 2017-01-16  7:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484377530-30635-3-git-send-email-baoyou.xie@linaro.org>

On Sat, Jan 14, 2017 at 03:05:30PM +0800, Baoyou Xie wrote:
> +static int zx2967_reset_assert(struct reset_controller_dev *rcdev,
> +			   unsigned long id)
> +{
> +	struct zx2967_reset *reset = NULL;
> +	int bank = id / 32;
> +	int offset = id % 32;
> +	unsigned int reg;

u32 is probably better for register value.

> +	unsigned long flags;
> +
> +	reset = container_of(rcdev, struct zx2967_reset, rcdev);
> +
> +	spin_lock_irqsave(&reset->lock, flags);
> +
> +	reg = readl(reset->reg_base + (bank * 4));
> +	writel(reg & ~BIT(offset), reset->reg_base + (bank * 4));
> +	reg = readl(reset->reg_base + (bank * 4));

Is this read on the register is necessary?  If so, we should probably
have a comment for that.

> +
> +	spin_unlock_irqrestore(&reset->lock, flags);
> +
> +	return 0;
> +}
> +
> +static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
> +			     unsigned long id)

Please indent the line right after parentheses.

> +{
> +	struct zx2967_reset *reset = NULL;
> +	int bank = id / 32;
> +	int offset = id % 32;
> +	unsigned int reg;
> +	unsigned long flags;
> +
> +	reset = container_of(rcdev, struct zx2967_reset, rcdev);
> +
> +	spin_lock_irqsave(&reset->lock, flags);
> +
> +	reg = readl(reset->reg_base + (bank * 4));
> +	writel(reg | BIT(offset), reset->reg_base + (bank * 4));
> +	reg = readl(reset->reg_base + (bank * 4));
> +
> +	spin_unlock_irqrestore(&reset->lock, flags);
> +
> +	return 0;
> +}

Only difference between these two functions is only one line.  Should we
consolidate them a bit?

Shawn

^ permalink raw reply

* [PATCH v3 2/3] USB3/DWC3: Add property "snps, incr-burst-type-adjustment" for INCR burst type
From: Jerry Huang @ 2017-01-16  8:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqJuifiSQAt-6FgtYYSukAnjzOLuTGEsO-Spn5LxkU-iwQ@mail.gmail.com>

> -----Original Message-----
> From: Jerry Huang
> Sent: Wednesday, January 04, 2017 10:25 AM
> To: 'Rob Herring' <robh@kernel.org>
> Cc: balbi at kernel.org; mark.rutland at arm.com; catalin.marinas at arm.com;
> will.deacon at arm.com; linux at armlinux.org.uk; devicetree at vger.kernel.org;
> linux-usb at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Subject: RE: [PATCH v3 2/3] USB3/DWC3: Add property "snps, incr-burst-
> type-adjustment" for INCR burst type
> 
> Hi, Rob,
> 
> > -----Original Message-----
> > From: Rob Herring [mailto:robh at kernel.org]
> > Sent: Wednesday, January 04, 2017 5:24 AM
> > To: Jerry Huang <jerry.huang@nxp.com>
> > Cc: balbi at kernel.org; mark.rutland at arm.com; catalin.marinas at arm.com;
> > will.deacon at arm.com; linux at armlinux.org.uk;
> > devicetree at vger.kernel.org; linux-usb at vger.kernel.org;
> > linux-kernel at vger.kernel.org; linux-arm- kernel at lists.infradead.org
> > Subject: Re: [PATCH v3 2/3] USB3/DWC3: Add property "snps, incr-burst-
> > type-adjustment" for INCR burst type
> >
> > On Thu, Dec 22, 2016 at 8:52 PM, Jerry Huang <jerry.huang@nxp.com>
> wrote:
> > > Hi, Rob,
> > >> -----Original Message-----
> > >> From: Rob Herring [mailto:robh at kernel.org]
> > >> Sent: Friday, December 23, 2016 2:45 AM
> > >> To: Jerry Huang <jerry.huang@nxp.com>
> > >> Cc: balbi at kernel.org; mark.rutland at arm.com;
> > >> catalin.marinas at arm.com; will.deacon at arm.com;
> > >> linux at armlinux.org.uk; devicetree at vger.kernel.org;
> > >> linux-usb at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> > >> kernel at lists.infradead.org
> > >> Subject: Re: [PATCH v3 2/3] USB3/DWC3: Add property "snps,
> > >> incr-burst- type-adjustment" for INCR burst type
> > >>
> > >> On Mon, Dec 19, 2016 at 05:25:53PM +0800, Changming Huang wrote:
> > >> > New property "snps,incr-burst-type-adjustment = <x>, <y>" for
> > >> > USB3.0
> > >> DWC3.
> > >> > Field "x": 1/0 - undefined length INCR burst type enable or not;
> > >> > Field
> > >> > "y": INCR4/INCR8/INCR16/INCR32/INCR64/INCR128/INCR256 burst
> type.
> > >> >
> > >> > While enabling undefined length INCR burst type and INCR16 burst
> > >> > type, get better write performance on NXP Layerscape platform:
> > >> > around 3% improvement (from 364MB/s to 375MB/s).
> > >> >
> > >> > Signed-off-by: Changming Huang <jerry.huang@nxp.com>
> > >> > ---
> > >> > Changes in v3:
> > >> >   - add new property for INCR burst in usb node.
> > >> >
> > >> >  Documentation/devicetree/bindings/usb/dwc3.txt |    5 +++++
> > >> >  arch/arm/boot/dts/ls1021a.dtsi                 |    1 +
> > >> >  arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi |    3 +++
> > >> >  arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi |    2 ++
> > >> >  4 files changed, 11 insertions(+)
> > >> >
> > >> > diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt
> > >> > b/Documentation/devicetree/bindings/usb/dwc3.txt
> > >> > index e3e6983..8c405a3 100644
> > >> > --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> > >> > +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> > >> > @@ -55,6 +55,10 @@ Optional properties:
> > >> >     fladj_30mhz_sdbnd signal is invalid or incorrect.
> > >> >
> > >> >   - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to
> > >> > be
> > >> reallocated.
> > >> > + - snps,incr-burst-type-adjustment: Value for INCR burst type of
> > >> GSBUSCFG0
> > >> > +   register, undefined length INCR burst type enable and INCRx type.
> > >> > +   First field is for undefined length INCR burst type enable or not.
> > >> > +   Second field is for largest INCRx type enabled.
> > >>
> > >> Why do you need the first field? Is the 2nd field used if the 1st is 0?
> > >> If not, then just use the presence of the property to enable or not.
> > > The first field is one switch.
> > > When it is 1, means undefined length INCR burst type enabled, we can
> > > use
> > any length less than or equal to the largest-enabled burst length of
> > INCR4/8/16/32/64/128/256.
> > > When it is zero, means INCRx burst mode enabled, we can use one
> > > fixed
> > burst length of 1/4/8/16/32/64/128/256 byte.
> > > So, the 2nd field is used if the 1st is 0, we need to select one
> > > largest burst
> > length the USB controller can support.
> > > If we don't want to change the value of this register (use the
> > > default value),
> > we don't need to add this property to usb node.
> >
> > Just make this a single value with 0 meaning INCR and 4/8/16/etc being
> INCRx.
> Maybe, I didn't describe it clearly.
> According to DWC3 spec, the value "0" of field INCRBrstEna means INCRx
> burst mode, 1 means INCR burst mode.
> Regardless of the value of INCRBrstEna [bit0], we need to modify the other
> field bit[1,2,3,4,5,6,7] to one INCR burst type  for the platform supported.
> Ad you mentioned, if we just use a single value with 0 meaning INCR and
> 4/8/16/etc being INCRx.
> I understand totally that when it is none-zero, we can use it for INCR burst
> mode.
> Then, when it is 0, how to select the INCRx value?
> 
> So, I think we still need two vaue to specify INCRBrstEna and INCRx burst
> type.
Hi, Balbi, 
It seems there is no feedback for my comment, so these patches can be accepted?

^ permalink raw reply

* [PATCH v29 9/9] Documentation: dt: chosen properties for arm64 kdump
From: AKASHI Takahiro @ 2017-01-16  8:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113111756.GC26120@leverpostej>

On Fri, Jan 13, 2017 at 11:17:56AM +0000, Mark Rutland wrote:
> On Fri, Jan 13, 2017 at 06:13:49PM +0900, AKASHI Takahiro wrote:
> > On Thu, Jan 12, 2017 at 03:39:45PM +0000, Mark Rutland wrote:
> > > On Wed, Dec 28, 2016 at 01:37:34PM +0900, AKASHI Takahiro wrote:
> > > > +linux,crashkernel-base
> > > > +linux,crashkernel-size
> > > > +----------------------
> > > > +
> > > > +These properties (currently used on PowerPC and arm64) indicates
> > > > +the base address and the size, respectively, of the reserved memory
> > > > +range for crash dump kernel.
> > > 
> > > From this description, it's not clear to me what the (expected)
> > > consumers of this property are, nor what is expected to provide it.
> > > 
> > > In previous rounds of review, I had assumed that this was used to
> > > describe a preference to the first kernel as to what region of memory
> > > should be used for a subsequent kdump kernel. Looking around, I'm not
> > > sure if I was correct in that assessment.
> > > 
> > > I see that arch/powerpc seems to consume this property to configure
> > > crashk_res, but it also rewrites it based on crashk_res, presumably for
> > > the benefit of userspace. It's not clear to me how on powerpc the kdump
> > > kernel knows its memory range -- is more DT modification done in the
> > > kernel and/or userspace?
> > 
> > I don't believe that powerpc will rewrite the property any way.
> > As far as I know from *the source code*, powerpc kernel retrieves
> > the memory range for crash dump kernel from a kernel command line, i.e.
> > crashkernel=, and then exposes it through DT to userspace (assuming
> > kexec-tools).
> 
> The rewriting I describe is in export_crashk_values() in
> arch/powerpc/kernel/machine_kexec.c, where the code deletes existing the
> properties, and adds new ones, to the DT exposed to userspace.
> 
> So I think we're just quibbling over the definition of "rewrite".

Gotcha

> > > arm64 we should either ensure that /proc/iomem is consistently usable
> > > (and have userspace consistently use it), or we should expose a new file
> > > specifically to expose this information.
> > 
> > The thing that I had in my mind when adding this property is that
> > /proc/iomem would be obsolete in the future, then we should have
> > an alternative in hand.
> 
> Ok.
> 
> My disagreement is with using the DT as a channel to convey information
> from the kernel to userspace.
> 
> I'm more than happy for a new file or other mechanism to express this
> information. For example, we could add
> /sys/kernel/kexec_crash_{base,size} or similar.

It may make sense because /sys/kernel/kexec_crash_size already exists,
so why not kexec_crash_base?
My concern, however, is that this kind of interface might prevent us from
allowing multiple regions to be reserved for crash dump kernel in the future.
(There is an assumption that we have only one region at least on arm64 though.)

Thanks,
-Takahiro AKASHI

> 
> > > Further, I do not think we need this property. It makes more sense to me
> > > for the preference of a a region to be described to the *first* kernel
> > > using the command line consistently.
> > > 
> > > So I think we should drop this property, and not use it on arm64. Please
> > > document this as powerpc only.
> > 
> > OK, but if we drop the property from arm64 code, we have no reason
> > to leave its description in this patch.
> > (In fact, there are a few more (undocumented) properties that only ppc
> > uses for kdump.)
> 
> I'm happy to drop it, then.
> 
> > > > +linux,usable-memory-range
> > > > +-------------------------
> > > > +
> > > > +This property (currently used only on arm64) holds the memory range,
> > > > +the base address and the size, which can be used as system ram on
> > > > +the *current* kernel. Note that, if this property is present, any memory
> > > > +regions under "memory" nodes in DT blob or ones marked as "conventional
> > > > +memory" in EFI memory map should be ignored.
> > > 
> > > Could you please replace this with:
> > > 
> > >   This property (arm64 only) holds a base address and size, describing a
> > >   limited region in which memory may be considered available for use by
> > >   the kernel. Memory outside of this range is not available for use.
> > >   
> > >   This property describes a limitation: memory within this range is only
> > >   valid when also described through another mechanism that the kernel
> > >   would otherwise use to determine available memory (e.g. memory nodes
> > >   or the EFI memory map). Valid memory may be sparse within the range.
> > 
> > Sure.
> 
> Cheers!
> 
> Thanks,
> Mark.

^ permalink raw reply

* [PATCH V7 1/4] Documentation/devicetree/bindings: b850v3_lvds_dp
From: Peter Senna Tschudin @ 2017-01-16  8:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6276161.johxDync2u@avalon>

On Tue, Jan 10, 2017 at 11:04:58PM +0200, Laurent Pinchart wrote:
> Hi Peter,

Laurent!

> 
> On Saturday 07 Jan 2017 01:29:52 Peter Senna Tschudin wrote:
> > On 04 January, 2017 21:39 CET, Rob Herring wrote:
> > > On Tue, Jan 3, 2017 at 5:34 PM, Peter Senna Tschudin wrote:
> > >> On 03 January, 2017 23:51 CET, Rob Herring <robh@kernel.org> wrote:
> > >>> On Sun, Jan 01, 2017 at 09:24:29PM +0100, Peter Senna Tschudin wrote:
> > >>>> Devicetree bindings documentation for the GE B850v3 LVDS/DP++
> > >>>> display bridge.
> > >>>> 
> > >>>> Cc: Martyn Welch <martyn.welch@collabora.co.uk>
> > >>>> Cc: Martin Donnelly <martin.donnelly@ge.com>
> > >>>> Cc: Javier Martinez Canillas <javier@dowhile0.org>
> > >>>> Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> > >>>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> > >>>> Cc: Rob Herring <robh@kernel.org>
> > >>>> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > >>>> Signed-off-by: Peter Senna Tschudin <peter.senna@collabora.com>
> > >>>> ---
> > >>>> There was an Acked-by from Rob Herring <robh@kernel.org> for V6, but
> > >>>> I changed the bindings to use i2c_new_secondary_device() so I
> > >>>> removed it from the commit message.
> > >>>> 
> > >>>>  .../devicetree/bindings/ge/b850v3-lvds-dp.txt      | 39 ++++++++++++++
> > >>> Generally, bindings are not organized by vendor. Put in
> > >>> bindings/display/bridge/... instead.
> > >> 
> > >> Will change that.
> > >> 
> > >>>>  1 file changed, 39 insertions(+)
> > >>>>  create mode 100644
> > >>>>  Documentation/devicetree/bindings/ge/b850v3-lvds-dp.txt
> > >>>> 
> > >>>> diff --git a/Documentation/devicetree/bindings/ge/b850v3-lvds-dp.txt
> > >>>> b/Documentation/devicetree/bindings/ge/b850v3-lvds-dp.txt new file
> > >>>> mode 100644
> > >>>> index 0000000..1bc6ebf
> > >>>> --- /dev/null
> > >>>> +++ b/Documentation/devicetree/bindings/ge/b850v3-lvds-dp.txt
> > >>>> @@ -0,0 +1,39 @@
> > >>>> +Driver for GE B850v3 LVDS/DP++ display bridge
> > >>>> +
> > >>>> +Required properties:
> > >>>> +  - compatible : should be "ge,b850v3-lvds-dp".
> > >>> 
> > >>> Isn't '-lvds-dp' redundant? The part# should be enough.
> > >> 
> > >> b850v3 is the name of the product, this is why the proposed name. What
> > >> about, b850v3-dp2 dp2 indicating the second DP output?
> > >
> > > Humm, b850v3 is the board name? This node should be the name of the bridge
> > > chip.
> >
> > From the cover letter:
> > 
> > -- // --
> > There are two physical bridges on the video signal pipeline: a STDP4028(LVDS
> > to DP) and a STDP2690(DP to DP++).  The hardware and firmware made it
> > complicated for this binding to comprise two device tree nodes, as the
> > design goal is to configure both bridges based on the LVDS signal, which
> > leave the driver powerless to control the video processing pipeline. The
> > two bridges behaves as a single bridge, and the driver is only needed for
> > telling the host about EDID / HPD, and for giving the host powers to ack
> > interrupts. The video signal pipeline is as follows:
> > 
> >   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
> > -- // --
> 
> You forgot to prefix your patch series with [HACK] ;-)
> 
> How about fixing the issues that make the two DT nodes solution difficult ? 
> What are they ?

The Firmware and the hardware design. Both bridges, with stock firmware,
are fully capable of providig EDID information and handling interrupts.
But on this specific design, with this specific firmware, I need to read
EDID from one bridge, and handle interrupts on the other. Back when I
was starting the development I could not come up with a proper way to
split EDID and interrupts between two bridges in a way that would result
in a fully functional connector. Did I miss something?


> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

^ permalink raw reply

* [PATCH v1 2/2] arm: dts: mt2701: add nor flash node
From: Boris Brezillon @ 2017-01-16  8:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e7fa1542-f0e2-0e45-23b3-25d6491ae40d@gmail.com>

On Sun, 15 Jan 2017 01:23:48 +0100
Marek Vasut <marek.vasut@gmail.com> wrote:

> On 01/14/2017 09:29 AM, Boris Brezillon wrote:
> > On Fri, 13 Jan 2017 18:33:40 +0100
> > Marek Vasut <marek.vasut@gmail.com> wrote:
> >   
> >> On 01/13/2017 05:56 PM, Boris Brezillon wrote:  
> >>> On Fri, 13 Jan 2017 17:44:12 +0100
> >>> Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>     
> >>>> On 01/13/2017 05:28 PM, Boris Brezillon wrote:    
> >>>>> On Fri, 13 Jan 2017 17:13:55 +0100
> >>>>> Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>>>       
> >>>>>> On 01/13/2017 04:12 PM, Matthias Brugger wrote:      
> >>>>>>>
> >>>>>>>
> >>>>>>> On 13/01/17 15:17, Boris Brezillon wrote:        
> >>>>>>>> On Fri, 13 Jan 2017 15:13:29 +0800
> >>>>>>>> Guochun Mao <guochun.mao@mediatek.com> wrote:
> >>>>>>>>        
> >>>>>>>>> Add Mediatek nor flash node.
> >>>>>>>>>
> >>>>>>>>> Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
> >>>>>>>>> ---
> >>>>>>>>>  arch/arm/boot/dts/mt2701-evb.dts |   25 +++++++++++++++++++++++++
> >>>>>>>>>  arch/arm/boot/dts/mt2701.dtsi    |   12 ++++++++++++
> >>>>>>>>>  2 files changed, 37 insertions(+)
> >>>>>>>>>
> >>>>>>>>> diff --git a/arch/arm/boot/dts/mt2701-evb.dts
> >>>>>>>>> b/arch/arm/boot/dts/mt2701-evb.dts
> >>>>>>>>> index 082ca88..85e5ae8 100644
> >>>>>>>>> --- a/arch/arm/boot/dts/mt2701-evb.dts
> >>>>>>>>> +++ b/arch/arm/boot/dts/mt2701-evb.dts
> >>>>>>>>> @@ -24,6 +24,31 @@
> >>>>>>>>>      };
> >>>>>>>>>  };
> >>>>>>>>>
> >>>>>>>>> +&nor_flash {
> >>>>>>>>> +    pinctrl-names = "default";
> >>>>>>>>> +    pinctrl-0 = <&nor_pins_default>;
> >>>>>>>>> +    status = "okay";
> >>>>>>>>> +    flash at 0 {
> >>>>>>>>> +        compatible = "jedec,spi-nor";
> >>>>>>>>> +        reg = <0>;
> >>>>>>>>> +    };
> >>>>>>>>> +};
> >>>>>>>>> +
> >>>>>>>>> +&pio {
> >>>>>>>>> +    nor_pins_default: nor {
> >>>>>>>>> +        pins1 {
> >>>>>>>>> +            pinmux = <MT2701_PIN_240_EXT_XCS__FUNC_EXT_XCS>,
> >>>>>>>>> +                 <MT2701_PIN_241_EXT_SCK__FUNC_EXT_SCK>,
> >>>>>>>>> +                 <MT2701_PIN_239_EXT_SDIO0__FUNC_EXT_SDIO0>,
> >>>>>>>>> +                 <MT2701_PIN_238_EXT_SDIO1__FUNC_EXT_SDIO1>,
> >>>>>>>>> +                 <MT2701_PIN_237_EXT_SDIO2__FUNC_EXT_SDIO2>,
> >>>>>>>>> +                 <MT2701_PIN_236_EXT_SDIO3__FUNC_EXT_SDIO3>;
> >>>>>>>>> +            drive-strength = <MTK_DRIVE_4mA>;
> >>>>>>>>> +            bias-pull-up;
> >>>>>>>>> +        };
> >>>>>>>>> +    };
> >>>>>>>>> +};
> >>>>>>>>> +
> >>>>>>>>>  &uart0 {
> >>>>>>>>>      status = "okay";
> >>>>>>>>>  };
> >>>>>>>>> diff --git a/arch/arm/boot/dts/mt2701.dtsi
> >>>>>>>>> b/arch/arm/boot/dts/mt2701.dtsi
> >>>>>>>>> index bdf8954..1eefce4 100644
> >>>>>>>>> --- a/arch/arm/boot/dts/mt2701.dtsi
> >>>>>>>>> +++ b/arch/arm/boot/dts/mt2701.dtsi
> >>>>>>>>> @@ -227,6 +227,18 @@
> >>>>>>>>>          status = "disabled";
> >>>>>>>>>      };
> >>>>>>>>>
> >>>>>>>>> +    nor_flash: spi at 11014000 {
> >>>>>>>>> +        compatible = "mediatek,mt2701-nor",
> >>>>>>>>> +                 "mediatek,mt8173-nor";        
> >>>>>>>>
> >>>>>>>> Why define both here? Is "mediatek,mt8173-nor" really providing a
> >>>>>>>> subset of the features supported by "mediatek,mt2701-nor"?
> >>>>>>>>        
> >>>>>>>
> >>>>>>> I think even if the ip block is the same, we should provide both
> >>>>>>> bindings, just in case in the future we find out that mt2701 has some
> >>>>>>> hidden bug, feature or bug-feature. This way even if we update the
> >>>>>>> driver, we stay compatible with older device tree blobs in the wild.
> >>>>>>>
> >>>>>>> We can drop the mt2701-nor in the bindings definition if you want.       
> >>>>>
> >>>>> Oh, sorry, I misunderstood. What I meant is that if you want to
> >>>>> list/support all possible compatibles, maybe you should just put one
> >>>>> compatible in your DT and patch your driver (+ binding doc) to define
> >>>>> all of them.      
> >>>>
> >>>> Uh, what ? I lost you here :-)  
> > 
> > I mean adding a new entry in the mtk_nor_of_ids table (in
> > mtk-quadspi.c) so that the mediatek,mt2701-nor compatible string can be
> > matched directly, and you won't need to define 2 compatible strings in
> > your device tree.  
> 
> But then you grow the table in the driver, is that what we want if we
> can avoid that ?

The space you save by not growing the mtk_nor_of_ids table is lost in
your dtbs, so I'm not sure the size argument is relevant here. Also,
note that distros are shipping a lot of dtbs, and you're likely to have
several boards based on the mt2701 SoC, so, for this specific use case,
it's better to make the in-driver of-id table grow than specifying 2
compatibles in the DT. But as I said, I'm not sure we should rely on
this argument to decide which approach to choose (we're talking about a
few bytes here).

> 
> >>>>    
> >>>>>> This exactly. We should have a DT compat in the form:
> >>>>>> compatible = "vendor,<soc>-block", "vendor,<oldest-compat-soc>-block";
> >>>>>> Then if we find a problem in the future, we can match on the
> >>>>>> "vendor,<soc>-block" and still support the old DTs.      
> >>>>>
> >>>>> Not sure it's only in term of whose IP appeared first. My understanding
> >>>>> is that it's a way to provide inheritance. For example:
> >>>>>
> >>>>> 	"<soc-vendor>,<ip-version>", "<ip-vendor>,<ip-version>";
> >>>>>
> >>>>> or
> >>>>>
> >>>>> 	"<soc-vendor>,<full-featured-ip-version>","<soc-vendor>,<basic-feature-ip-version>";
> >>>>>
> >>>>> BTW, which one is the oldest between mt8173 and mt2701? :-)      
> >>>>
> >>>> And that's another thing and I agree with you, but I don't think that's
> >>>> what we're discussing in this thread. But (!), OT, I think we should
> >>>> codify the rules in Documentation/ . This discussion came up multiple
> >>>> times recently.
> >>>>
> >>>> And my question still stands, what do we put into the DT here, IMO
> >>>> compatible = "mediatek,mt2701-nor", "mediatek,mt8173-nor";    
> >>>
> >>> I'd say
> >>>
> >>> 	compatible = "mediatek,mt8173-nor";
> >>>
> >>> because both compatible are referring to very specific IP version. It's
> >>> not the same as    
> >>
> >> But then you don't have the ability to handle a block in this particular
> >> SoC in case there's a bug found in it in the future,
> >> so IMO it should be:
> >>
> >> compatible = "mediatek,mt2701-nor", "mediatek,mt8173-nor";  
> > 
> > Sorry again, I meant
> > 
> > 	compatible = "mediatek,mt2701-nor";
> >   
> >>  
> >>> 	compatible = "mediatek,mt8173-nor", "mediatek,mt81xx-nor";    
> >>
> >> This doesn't look right, since here we add two new compatibles ...  
> > 
> > That was just an example to describe how compatible inheritance works
> > (at least that's my understanding of it), it does not apply to this
> > particular use case.  
> 
> Well this is OK I guess, but then you can also use "mediatek,mt8173-nor"
> as the oldest supported compatible and be done with it, no ? It looks a
> bit crappy though, I admit that ...
> 

Let's stop bikeshedding and wait for DT maintainers feedback
before taking a decision ;-).

Rob, Mark, any opinion?

^ permalink raw reply

* [PATCH v3 2/3] USB3/DWC3: Add property "snps, incr-burst-type-adjustment" for INCR burst type
From: Felipe Balbi @ 2017-01-16  8:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <DB5PR0401MB18132BB4CDE32EEA8F479E55FE7D0@DB5PR0401MB1813.eurprd04.prod.outlook.com>


Hi,

Jerry Huang <jerry.huang@nxp.com> writes:
>> > On Thu, Dec 22, 2016 at 8:52 PM, Jerry Huang <jerry.huang@nxp.com>
>> wrote:
>> > > Hi, Rob,
>> > >> -----Original Message-----
>> > >> From: Rob Herring [mailto:robh at kernel.org]
>> > >> Sent: Friday, December 23, 2016 2:45 AM
>> > >> To: Jerry Huang <jerry.huang@nxp.com>
>> > >> Cc: balbi at kernel.org; mark.rutland at arm.com;
>> > >> catalin.marinas at arm.com; will.deacon at arm.com;
>> > >> linux at armlinux.org.uk; devicetree at vger.kernel.org;
>> > >> linux-usb at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
>> > >> kernel at lists.infradead.org
>> > >> Subject: Re: [PATCH v3 2/3] USB3/DWC3: Add property "snps,
>> > >> incr-burst- type-adjustment" for INCR burst type
>> > >>
>> > >> On Mon, Dec 19, 2016 at 05:25:53PM +0800, Changming Huang wrote:
>> > >> > New property "snps,incr-burst-type-adjustment = <x>, <y>" for
>> > >> > USB3.0
>> > >> DWC3.
>> > >> > Field "x": 1/0 - undefined length INCR burst type enable or not;
>> > >> > Field
>> > >> > "y": INCR4/INCR8/INCR16/INCR32/INCR64/INCR128/INCR256 burst
>> type.
>> > >> >
>> > >> > While enabling undefined length INCR burst type and INCR16 burst
>> > >> > type, get better write performance on NXP Layerscape platform:
>> > >> > around 3% improvement (from 364MB/s to 375MB/s).
>> > >> >
>> > >> > Signed-off-by: Changming Huang <jerry.huang@nxp.com>
>> > >> > ---
>> > >> > Changes in v3:
>> > >> >   - add new property for INCR burst in usb node.
>> > >> >
>> > >> >  Documentation/devicetree/bindings/usb/dwc3.txt |    5 +++++
>> > >> >  arch/arm/boot/dts/ls1021a.dtsi                 |    1 +
>> > >> >  arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi |    3 +++
>> > >> >  arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi |    2 ++
>> > >> >  4 files changed, 11 insertions(+)
>> > >> >
>> > >> > diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt
>> > >> > b/Documentation/devicetree/bindings/usb/dwc3.txt
>> > >> > index e3e6983..8c405a3 100644
>> > >> > --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>> > >> > +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>> > >> > @@ -55,6 +55,10 @@ Optional properties:
>> > >> >     fladj_30mhz_sdbnd signal is invalid or incorrect.
>> > >> >
>> > >> >   - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to
>> > >> > be
>> > >> reallocated.
>> > >> > + - snps,incr-burst-type-adjustment: Value for INCR burst type of
>> > >> GSBUSCFG0
>> > >> > +   register, undefined length INCR burst type enable and INCRx type.
>> > >> > +   First field is for undefined length INCR burst type enable or not.
>> > >> > +   Second field is for largest INCRx type enabled.
>> > >>
>> > >> Why do you need the first field? Is the 2nd field used if the 1st is 0?
>> > >> If not, then just use the presence of the property to enable or not.
>> > > The first field is one switch.
>> > > When it is 1, means undefined length INCR burst type enabled, we can
>> > > use
>> > any length less than or equal to the largest-enabled burst length of
>> > INCR4/8/16/32/64/128/256.
>> > > When it is zero, means INCRx burst mode enabled, we can use one
>> > > fixed
>> > burst length of 1/4/8/16/32/64/128/256 byte.
>> > > So, the 2nd field is used if the 1st is 0, we need to select one
>> > > largest burst
>> > length the USB controller can support.
>> > > If we don't want to change the value of this register (use the
>> > > default value),
>> > we don't need to add this property to usb node.
>> >
>> > Just make this a single value with 0 meaning INCR and 4/8/16/etc being
>> INCRx.
>> Maybe, I didn't describe it clearly.
>> According to DWC3 spec, the value "0" of field INCRBrstEna means INCRx
>> burst mode, 1 means INCR burst mode.
>> Regardless of the value of INCRBrstEna [bit0], we need to modify the other
>> field bit[1,2,3,4,5,6,7] to one INCR burst type  for the platform supported.
>> Ad you mentioned, if we just use a single value with 0 meaning INCR and
>> 4/8/16/etc being INCRx.
>> I understand totally that when it is none-zero, we can use it for INCR burst
>> mode.
>> Then, when it is 0, how to select the INCRx value?
>> 
>> So, I think we still need two vaue to specify INCRBrstEna and INCRx burst
>> type.
> Hi, Balbi, 
> It seems there is no feedback for my comment, so these patches can be accepted?

probably not, we need to really understand what information we need so
it can be described properly. The last thing we want is unnecessary DT
properties.

It seems to me that we can extrapolate INCRBrstEna based on which burst
modes are enabled. If only 0 is passed, then that bit should be 1, if 0
and any other size is passed, then that bit should be 0, no?

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170116/7f31264e/attachment-0001.sig>

^ permalink raw reply

* [v2 2/3] ARM: dts: STM32 Add USB FS host mode support
From: Alexandre Torgue @ 2017-01-16  8:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170116020958.62767-2-bruherrera@gmail.com>

Hi Bruno,

On 01/16/2017 03:09 AM, Bruno Herrera wrote:
> This patch adds the USB pins and nodes for USB HS/FS cores working at FS speed,
> using embedded PHY.
>
> Signed-off-by: Bruno Herrera <bruherrera@gmail.com>

Sorry, but what is patch 1 & pacth 3 status ?

For this one, can split it in 3 patches (one patch for SOC and one for 
each board) please.


> ---
>  arch/arm/boot/dts/stm32f429-disco.dts | 30 ++++++++++++++++++++++++++++++
>  arch/arm/boot/dts/stm32f429.dtsi      | 35 ++++++++++++++++++++++++++++++++++-
>  arch/arm/boot/dts/stm32f469-disco.dts | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 94 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/stm32f429-disco.dts
> index 7d0415e..374c5ed 100644
> --- a/arch/arm/boot/dts/stm32f429-disco.dts
> +++ b/arch/arm/boot/dts/stm32f429-disco.dts
> @@ -88,6 +88,16 @@
>  			gpios = <&gpioa 0 0>;
>  		};
>  	};
> +
> +	/* This turns on vbus for otg for host mode (dwc2) */
> +	vcc5v_otg: vcc5v-otg-regulator {
> +		compatible = "regulator-fixed";
> +		gpio = <&gpioc 4 0>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&usbotg_pwren_h>;
> +		regulator-name = "vcc5_host1";
> +		regulator-always-on;
> +	};
>  };
>
>  &clk_hse {
> @@ -99,3 +109,23 @@
>  	pinctrl-names = "default";
>  	status = "okay";
>  };
> +
> +&usbotg_hs {
> +	compatible = "st,stm32-fsotg", "snps,dwc2";
> +	dr_mode = "host";
> +	pinctrl-0 = <&usbotg_fs_pins_b>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&pinctrl {
> +	usb-host {
> +		usbotg_pwren_h: usbotg-pwren-h {
> +			pins {
> +				pinmux = <STM32F429_PC4_FUNC_GPIO>;
> +				bias-disable;
> +				drive-push-pull;
> +			};
> +		};
> +	};
> +};

Pinctrl muxing has to be defined/declared in stm32f429.dtsi


> diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
> index e4dae0e..bc07aa8 100644
> --- a/arch/arm/boot/dts/stm32f429.dtsi
> +++ b/arch/arm/boot/dts/stm32f429.dtsi
> @@ -206,7 +206,7 @@
>  			reg = <0x40007000 0x400>;
>  		};
>
> -		pin-controller {
> +		pinctrl: pin-controller {
>  			#address-cells = <1>;
>  			#size-cells = <1>;
>  			compatible = "st,stm32f429-pinctrl";
> @@ -316,6 +316,30 @@
>  				};
>  			};
>
> +			usbotg_fs_pins_a: usbotg_fs at 0 {
> +				pins {
> +					pinmux = <STM32F429_PA10_FUNC_OTG_FS_ID>,
> +						 <STM32F429_PA11_FUNC_OTG_FS_DM>,
> +						 <STM32F429_PA12_FUNC_OTG_FS_DP>;
> +					bias-disable;
> +					drive-push-pull;
> +					slew-rate = <2>;
> +				};
> +			};
> +
> +			usbotg_fs_pins_b: usbotg_fs at 1 {
> +				pins {
> +					pinmux = <STM32F429_PB12_FUNC_OTG_HS_ID>,
> +						 <STM32F429_PB14_FUNC_OTG_HS_DM>,
> +						 <STM32F429_PB15_FUNC_OTG_HS_DP>;
> +					bias-disable;
> +					drive-push-pull;
> +					slew-rate = <2>;
> +				};
> +			};
> +
> +
> +
>  			usbotg_hs_pins_a: usbotg_hs at 0 {
>  				pins {
>  					pinmux = <STM32F429_PH4_FUNC_OTG_HS_ULPI_NXT>,
> @@ -420,6 +444,15 @@
>  			status = "disabled";
>  		};
>
> +		usbotg_fs: usb at 50000000 {
> +			compatible = "st,stm32f4xx-fsotg", "snps,dwc2";
> +			reg = <0x50000000 0x40000>;
> +			interrupts = <67>;
> +			clocks = <&rcc 0 39>;
> +			clock-names = "otg";
> +			status = "disabled";
> +		};
> +
>  		rng: rng at 50060800 {
>  			compatible = "st,stm32-rng";
>  			reg = <0x50060800 0x400>;
> diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
> index 8877c00..8ae6763 100644
> --- a/arch/arm/boot/dts/stm32f469-disco.dts
> +++ b/arch/arm/boot/dts/stm32f469-disco.dts
> @@ -68,6 +68,17 @@
>  	soc {
>  		dma-ranges = <0xc0000000 0x0 0x10000000>;
>  	};
> +
> +	/* This turns on vbus for otg for host mode (dwc2) */
> +	vcc5v_otg: vcc5v-otg-regulator {
> +		compatible = "regulator-fixed";
> +		enable-active-high;
> +		gpio = <&gpiob 2 0>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&usbotg_pwren_h>;
> +		regulator-name = "vcc5_host1";
> +		regulator-always-on;
> +	};
>  };
>
>  &rcc {
> @@ -81,3 +92,22 @@
>  &usart3 {
>  	status = "okay";
>  };
> +
> +&usbotg_fs {
> +	dr_mode = "host";
> +	pinctrl-0 = <&usbotg_fs_pins_a>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&pinctrl {
> +	usb-host {
> +		usbotg_pwren_h: usbotg-pwren-h {
> +			pins {
> +				pinmux = <STM32F429_PB2_FUNC_GPIO>;
> +				bias-disable;
> +				drive-push-pull;
> +			};
> +		};
> +	};
> +};
Same. Note that if you have 2 configuration for one feature (like it is 
here for "usbotg_pwren_h"), you could index it. Not that I'm adding a 
dedidacted pinctroller for stm32f469.

Br
Alex
>

^ permalink raw reply

* [PATCH] rtc: stm32: use 0 instead of ~PWR_CR_DBP in regmap_update_bits
From: Amelie Delaunay @ 2017-01-16  8:57 UTC (permalink / raw)
  To: linux-arm-kernel

Using the ~ operator on a BIT() constant results in a large 'unsigned long'
constant that won't fit into an 'unsigned int' function argument on 64-bit
architectures, resulting in a harmless build warning in x86 allmodconfig:

drivers/rtc/rtc-stm32.c: In function 'stm32_rtc_probe':
drivers/rtc/rtc-stm32.c:651:51: error: large integer implicitly truncated to unsigned type [-Werror=overflow]
  regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);

As PWR_CR_DBP mask prevents other bits to be cleared, replace all
~PWR_CR_DBP by 0.

Fixes: 4e64350f42e2 ("rtc: add STM32 RTC driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
 drivers/rtc/rtc-stm32.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 8c599f5..03c97c1 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -648,7 +648,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 err:
 	clk_disable_unprepare(rtc->ck_rtc);
 
-	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
+	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
 
 	device_init_wakeup(&pdev->dev, false);
 
@@ -670,7 +670,7 @@ static int stm32_rtc_remove(struct platform_device *pdev)
 	clk_disable_unprepare(rtc->ck_rtc);
 
 	/* Enable backup domain write protection */
-	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
+	regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
 
 	device_init_wakeup(&pdev->dev, false);
 
-- 
1.9.1

^ permalink raw reply related

* USB: OHCI: high softirq load
From: Boris Brezillon @ 2017-01-16  9:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bd83e3b2-b329-3635-2917-0ffe61d3535f@overkiz.com>

Hi Antoine,

On Mon, 16 Jan 2017 08:45:58 +0100
Antoine Aubert <a.aubert@overkiz.com> wrote:

> Hi,
> 
> Im working on a AT91SAM9G25cu board
> (arch/arm/boot/dts/at91-kizboxmini.dts). We use linux-4.1.31, and when
> OHCI is enabled, I got some wired effects.

Can you test on a more recent kernel (4.9 or 4.10-rc4)?

> 
> eg with 3 FTDI pluged, interrupts: more than 3.5k/s, cpu softirq > 24%,
> loadavg > 0.5

Can you check which interrupt is triggered (cat /proc/interrupts), and
enable debug messages in drivers/usb/host/ohci-at91.c?

Thanks,

Boris

> 
> This issue disappear when disabling OHCI and use EHCI only.
> 
> What are the usual causes, and where to begin with ?
> 
> Thanks in advance,
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox