All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] Basical Allwinner R329 support
@ 2021-08-02  6:21 ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

This patchset tries to add basical support for Allwinner R329 SoC to the
Linux kernel, including clock/pintrl driver and MMC support.

Three patches from the H616 patchset, which are used to support the RTC
with linear day, are attached into this patchset. Other RTC-related
patches of that patchset is not included, because the binding of the
clock part there is still under discussion.

Then I added RTC binding and support (which is now only a struct
addition). I added RTC into this patchset, with the same reason that
H616 patchset contains RTC, which is to make the clock tree correct at
the first inclusion.

After RTC, main basical SoC-specific part, pinctrl and CCU, come. The
R329 CCU is something special because PLLs are in R-CCU, no main CCU.

MMC support is added here because it's also a simple struct addition
work, no main driver code change needed.

Finally it comes the DT part. The DT binding of MaixSense, the device
that I am working on now, is added. Then the DTSI for R329 SoC, the DTSI
file for Sipeed Maix IIA SoM (which is utilized on MaixSense) and the
main DT file for MaixSense are added.

Andre Przywara (3):
  rtc: sun6i: Fix time overflow handling
  rtc: sun6i: Add support for linear day storage
  rtc: sun6i: Add support for broken-down alarm registers

Icenowy Zheng (14):
  dt-bindings: rtc: sun6i: add compatible string for R329 RTC
  rtc: sun6i: add support for R329 RTC
  dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
  pinctrl: sunxi: add support for R329 CPUX pin controller
  pinctrl: sunxi: add support for R329 R-PIO pin controller
  dt-bindings: clock: sunxi-ng: add compatibles for R329 CCUs
  clk: sunxi=ng: add support for R329 R-CCU
  clk: sunxi-ng: add support for Allwinner R329 CCU
  dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
  mmc: sunxi: add support for R329 MMC controllers
  dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
  arm64: allwinner: dts: add DTSI file for R329 SoC
  arm64: allwinner: dts: r329: add DTSI file for Sipeed Maix IIA
  arm64: allwinner: dts: r329: add support for Sipeed MaixSense

 .../devicetree/bindings/arm/sunxi.yaml        |   6 +
 .../clock/allwinner,sun4i-a10-ccu.yaml        |   4 +
 .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml |   1 +
 .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml  |   4 +
 .../bindings/rtc/allwinner,sun6i-a31-rtc.yaml |   6 +-
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun50i-r329-maix-iia.dtsi   |  34 ++
 .../dts/allwinner/sun50i-r329-maixsense.dts   |  37 ++
 .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++
 drivers/clk/sunxi-ng/Kconfig                  |  10 +
 drivers/clk/sunxi-ng/Makefile                 |   2 +
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 +++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
 drivers/clk/sunxi-ng/ccu-sun50i-r329.c        | 526 ++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329.h        |  32 ++
 drivers/mmc/host/sunxi-mmc.c                  |  10 +
 drivers/pinctrl/sunxi/Kconfig                 |  10 +
 drivers/pinctrl/sunxi/Makefile                |   2 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c | 292 ++++++++++
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c   | 410 ++++++++++++++
 drivers/rtc/rtc-sun6i.c                       | 154 +++--
 include/dt-bindings/clock/sun50i-r329-ccu.h   |  73 +++
 include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
 include/dt-bindings/reset/sun50i-r329-ccu.h   |  45 ++
 include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 +
 25 files changed, 2320 insertions(+), 47 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
 create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

-- 
2.30.2


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

* [PATCH 00/17] Basical Allwinner R329 support
@ 2021-08-02  6:21 ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

This patchset tries to add basical support for Allwinner R329 SoC to the
Linux kernel, including clock/pintrl driver and MMC support.

Three patches from the H616 patchset, which are used to support the RTC
with linear day, are attached into this patchset. Other RTC-related
patches of that patchset is not included, because the binding of the
clock part there is still under discussion.

Then I added RTC binding and support (which is now only a struct
addition). I added RTC into this patchset, with the same reason that
H616 patchset contains RTC, which is to make the clock tree correct at
the first inclusion.

After RTC, main basical SoC-specific part, pinctrl and CCU, come. The
R329 CCU is something special because PLLs are in R-CCU, no main CCU.

MMC support is added here because it's also a simple struct addition
work, no main driver code change needed.

Finally it comes the DT part. The DT binding of MaixSense, the device
that I am working on now, is added. Then the DTSI for R329 SoC, the DTSI
file for Sipeed Maix IIA SoM (which is utilized on MaixSense) and the
main DT file for MaixSense are added.

Andre Przywara (3):
  rtc: sun6i: Fix time overflow handling
  rtc: sun6i: Add support for linear day storage
  rtc: sun6i: Add support for broken-down alarm registers

Icenowy Zheng (14):
  dt-bindings: rtc: sun6i: add compatible string for R329 RTC
  rtc: sun6i: add support for R329 RTC
  dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
  pinctrl: sunxi: add support for R329 CPUX pin controller
  pinctrl: sunxi: add support for R329 R-PIO pin controller
  dt-bindings: clock: sunxi-ng: add compatibles for R329 CCUs
  clk: sunxi=ng: add support for R329 R-CCU
  clk: sunxi-ng: add support for Allwinner R329 CCU
  dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
  mmc: sunxi: add support for R329 MMC controllers
  dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
  arm64: allwinner: dts: add DTSI file for R329 SoC
  arm64: allwinner: dts: r329: add DTSI file for Sipeed Maix IIA
  arm64: allwinner: dts: r329: add support for Sipeed MaixSense

 .../devicetree/bindings/arm/sunxi.yaml        |   6 +
 .../clock/allwinner,sun4i-a10-ccu.yaml        |   4 +
 .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml |   1 +
 .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml  |   4 +
 .../bindings/rtc/allwinner,sun6i-a31-rtc.yaml |   6 +-
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun50i-r329-maix-iia.dtsi   |  34 ++
 .../dts/allwinner/sun50i-r329-maixsense.dts   |  37 ++
 .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++
 drivers/clk/sunxi-ng/Kconfig                  |  10 +
 drivers/clk/sunxi-ng/Makefile                 |   2 +
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 +++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
 drivers/clk/sunxi-ng/ccu-sun50i-r329.c        | 526 ++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329.h        |  32 ++
 drivers/mmc/host/sunxi-mmc.c                  |  10 +
 drivers/pinctrl/sunxi/Kconfig                 |  10 +
 drivers/pinctrl/sunxi/Makefile                |   2 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c | 292 ++++++++++
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c   | 410 ++++++++++++++
 drivers/rtc/rtc-sun6i.c                       | 154 +++--
 include/dt-bindings/clock/sun50i-r329-ccu.h   |  73 +++
 include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
 include/dt-bindings/reset/sun50i-r329-ccu.h   |  45 ++
 include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 +
 25 files changed, 2320 insertions(+), 47 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
 create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 01/17] rtc: sun6i: Fix time overflow handling
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:21   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

From: Andre Przywara <andre.przywara@arm.com>

Using "unsigned long" for UNIX timestamps is never a good idea, and
comparing the value of such a variable against U32_MAX does not do
anything useful on 32-bit systems.

Use the proper time64_t type when dealing with timestamps, and avoid
cutting down the time range unnecessarily. This also fixes the flawed
check for the alarm time being too far into the future.

The check for this condition is actually somewhat theoretical, as the
RTC counts till 2033 only anyways, and 2^32 seconds from now is not
before the year 2157 - at which point I hope nobody will be using this
hardware anymore.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/rtc/rtc-sun6i.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index adec1b14a8de..c551ebf0ac00 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -138,7 +138,7 @@ struct sun6i_rtc_dev {
 	const struct sun6i_rtc_clk_data *data;
 	void __iomem *base;
 	int irq;
-	unsigned long alarm;
+	time64_t alarm;
 
 	struct clk_hw hw;
 	struct clk_hw *int_osc;
@@ -510,10 +510,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
 	struct rtc_time *alrm_tm = &wkalrm->time;
 	struct rtc_time tm_now;
-	unsigned long time_now = 0;
-	unsigned long time_set = 0;
-	unsigned long time_gap = 0;
-	int ret = 0;
+	time64_t time_now, time_set;
+	int ret;
 
 	ret = sun6i_rtc_gettime(dev, &tm_now);
 	if (ret < 0) {
@@ -528,9 +526,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 		return -EINVAL;
 	}
 
-	time_gap = time_set - time_now;
-
-	if (time_gap > U32_MAX) {
+	if ((time_set - time_now) > U32_MAX) {
 		dev_err(dev, "Date too far in the future\n");
 		return -EINVAL;
 	}
@@ -539,7 +535,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	writel(0, chip->base + SUN6I_ALRM_COUNTER);
 	usleep_range(100, 300);
 
-	writel(time_gap, chip->base + SUN6I_ALRM_COUNTER);
+	writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
 	chip->alarm = time_set;
 
 	sun6i_rtc_setaie(wkalrm->enabled, chip);
-- 
2.30.2


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

* [PATCH 01/17] rtc: sun6i: Fix time overflow handling
@ 2021-08-02  6:21   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

From: Andre Przywara <andre.przywara@arm.com>

Using "unsigned long" for UNIX timestamps is never a good idea, and
comparing the value of such a variable against U32_MAX does not do
anything useful on 32-bit systems.

Use the proper time64_t type when dealing with timestamps, and avoid
cutting down the time range unnecessarily. This also fixes the flawed
check for the alarm time being too far into the future.

The check for this condition is actually somewhat theoretical, as the
RTC counts till 2033 only anyways, and 2^32 seconds from now is not
before the year 2157 - at which point I hope nobody will be using this
hardware anymore.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/rtc/rtc-sun6i.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index adec1b14a8de..c551ebf0ac00 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -138,7 +138,7 @@ struct sun6i_rtc_dev {
 	const struct sun6i_rtc_clk_data *data;
 	void __iomem *base;
 	int irq;
-	unsigned long alarm;
+	time64_t alarm;
 
 	struct clk_hw hw;
 	struct clk_hw *int_osc;
@@ -510,10 +510,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
 	struct rtc_time *alrm_tm = &wkalrm->time;
 	struct rtc_time tm_now;
-	unsigned long time_now = 0;
-	unsigned long time_set = 0;
-	unsigned long time_gap = 0;
-	int ret = 0;
+	time64_t time_now, time_set;
+	int ret;
 
 	ret = sun6i_rtc_gettime(dev, &tm_now);
 	if (ret < 0) {
@@ -528,9 +526,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 		return -EINVAL;
 	}
 
-	time_gap = time_set - time_now;
-
-	if (time_gap > U32_MAX) {
+	if ((time_set - time_now) > U32_MAX) {
 		dev_err(dev, "Date too far in the future\n");
 		return -EINVAL;
 	}
@@ -539,7 +535,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	writel(0, chip->base + SUN6I_ALRM_COUNTER);
 	usleep_range(100, 300);
 
-	writel(time_gap, chip->base + SUN6I_ALRM_COUNTER);
+	writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
 	chip->alarm = time_set;
 
 	sun6i_rtc_setaie(wkalrm->enabled, chip);
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 02/17] rtc: sun6i: Add support for linear day storage
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:21   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

From: Andre Przywara <andre.przywara@arm.com>

Newer versions of the Allwinner RTC, as for instance found in the H616
SoC, no longer store a broken-down day/month/year representation in the
RTC_DAY_REG, but just a linear day number.
The user manual does not give any indication about the expected epoch
time of this day count, but the BSP kernel uses the UNIX epoch, which
allows easy support due to existing conversion functions in the kernel.

Allow tagging a compatible string with a flag, and use that to mark
those new RTCs. Then convert between a UNIX day number (converted into
seconds) and the broken-down day representation using mktime64() and
time64_to_tm() in the set_time/get_time functions.

That enables support for the RTC in those new chips.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/rtc/rtc-sun6i.c | 69 +++++++++++++++++++++++++++--------------
 1 file changed, 46 insertions(+), 23 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index c551ebf0ac00..a980d4e7408d 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -110,6 +110,8 @@
 #define SUN6I_YEAR_MIN				1970
 #define SUN6I_YEAR_OFF				(SUN6I_YEAR_MIN - 1900)
 
+#define SECS_PER_DAY				(24 * 3600ULL)
+
 /*
  * There are other differences between models, including:
  *
@@ -133,12 +135,15 @@ struct sun6i_rtc_clk_data {
 	unsigned int has_auto_swt : 1;
 };
 
+#define RTC_LINEAR_DAY	BIT(0)
+
 struct sun6i_rtc_dev {
 	struct rtc_device *rtc;
 	const struct sun6i_rtc_clk_data *data;
 	void __iomem *base;
 	int irq;
 	time64_t alarm;
+	unsigned long flags;
 
 	struct clk_hw hw;
 	struct clk_hw *int_osc;
@@ -467,22 +472,30 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 	} while ((date != readl(chip->base + SUN6I_RTC_YMD)) ||
 		 (time != readl(chip->base + SUN6I_RTC_HMS)));
 
+	if (chip->flags & RTC_LINEAR_DAY) {
+		/*
+		 * Newer chips store a linear day number, the manual
+		 * does not mandate any epoch base. The BSP driver uses
+		 * the UNIX epoch, let's just copy that, as it's the
+		 * easiest anyway.
+		 */
+		rtc_time64_to_tm((date & 0xffff) * SECS_PER_DAY, rtc_tm);
+	} else {
+		rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
+		rtc_tm->tm_mon  = SUN6I_DATE_GET_MON_VALUE(date) - 1;
+		rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
+
+		/*
+		 * switch from (data_year->min)-relative offset to
+		 * a (1900)-relative one
+		 */
+		rtc_tm->tm_year += SUN6I_YEAR_OFF;
+	}
+
 	rtc_tm->tm_sec  = SUN6I_TIME_GET_SEC_VALUE(time);
 	rtc_tm->tm_min  = SUN6I_TIME_GET_MIN_VALUE(time);
 	rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time);
 
-	rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
-	rtc_tm->tm_mon  = SUN6I_DATE_GET_MON_VALUE(date);
-	rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
-
-	rtc_tm->tm_mon  -= 1;
-
-	/*
-	 * switch from (data_year->min)-relative offset to
-	 * a (1900)-relative one
-	 */
-	rtc_tm->tm_year += SUN6I_YEAR_OFF;
-
 	return 0;
 }
 
@@ -567,20 +580,25 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
 	u32 date = 0;
 	u32 time = 0;
 
-	rtc_tm->tm_year -= SUN6I_YEAR_OFF;
-	rtc_tm->tm_mon += 1;
-
-	date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
-		SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
-		SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
-
-	if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
-		date |= SUN6I_LEAP_SET_VALUE(1);
-
 	time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec)  |
 		SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min)  |
 		SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);
 
+	if (chip->flags & RTC_LINEAR_DAY) {
+		/* The division will cut off the H:M:S part of rtc_tm. */
+		date = div_u64(rtc_tm_to_time64(rtc_tm), SECS_PER_DAY);
+	} else {
+		rtc_tm->tm_year -= SUN6I_YEAR_OFF;
+		rtc_tm->tm_mon += 1;
+
+		date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
+			SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
+			SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
+
+		if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
+			date |= SUN6I_LEAP_SET_VALUE(1);
+	}
+
 	/* Check whether registers are writable */
 	if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL,
 			   SUN6I_LOSC_CTRL_ACC_MASK, 50)) {
@@ -674,6 +692,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, chip);
 
+	chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev);
+
 	chip->irq = platform_get_irq(pdev, 0);
 	if (chip->irq < 0)
 		return chip->irq;
@@ -720,7 +740,10 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 		return PTR_ERR(chip->rtc);
 
 	chip->rtc->ops = &sun6i_rtc_ops;
-	chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
+	if (chip->flags & RTC_LINEAR_DAY)
+		chip->rtc->range_max = (65536 * SECS_PER_DAY) - 1;
+	else
+		chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
 
 	ret = devm_rtc_register_device(chip->rtc);
 	if (ret)
-- 
2.30.2


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

* [PATCH 02/17] rtc: sun6i: Add support for linear day storage
@ 2021-08-02  6:21   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

From: Andre Przywara <andre.przywara@arm.com>

Newer versions of the Allwinner RTC, as for instance found in the H616
SoC, no longer store a broken-down day/month/year representation in the
RTC_DAY_REG, but just a linear day number.
The user manual does not give any indication about the expected epoch
time of this day count, but the BSP kernel uses the UNIX epoch, which
allows easy support due to existing conversion functions in the kernel.

Allow tagging a compatible string with a flag, and use that to mark
those new RTCs. Then convert between a UNIX day number (converted into
seconds) and the broken-down day representation using mktime64() and
time64_to_tm() in the set_time/get_time functions.

That enables support for the RTC in those new chips.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/rtc/rtc-sun6i.c | 69 +++++++++++++++++++++++++++--------------
 1 file changed, 46 insertions(+), 23 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index c551ebf0ac00..a980d4e7408d 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -110,6 +110,8 @@
 #define SUN6I_YEAR_MIN				1970
 #define SUN6I_YEAR_OFF				(SUN6I_YEAR_MIN - 1900)
 
+#define SECS_PER_DAY				(24 * 3600ULL)
+
 /*
  * There are other differences between models, including:
  *
@@ -133,12 +135,15 @@ struct sun6i_rtc_clk_data {
 	unsigned int has_auto_swt : 1;
 };
 
+#define RTC_LINEAR_DAY	BIT(0)
+
 struct sun6i_rtc_dev {
 	struct rtc_device *rtc;
 	const struct sun6i_rtc_clk_data *data;
 	void __iomem *base;
 	int irq;
 	time64_t alarm;
+	unsigned long flags;
 
 	struct clk_hw hw;
 	struct clk_hw *int_osc;
@@ -467,22 +472,30 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 	} while ((date != readl(chip->base + SUN6I_RTC_YMD)) ||
 		 (time != readl(chip->base + SUN6I_RTC_HMS)));
 
+	if (chip->flags & RTC_LINEAR_DAY) {
+		/*
+		 * Newer chips store a linear day number, the manual
+		 * does not mandate any epoch base. The BSP driver uses
+		 * the UNIX epoch, let's just copy that, as it's the
+		 * easiest anyway.
+		 */
+		rtc_time64_to_tm((date & 0xffff) * SECS_PER_DAY, rtc_tm);
+	} else {
+		rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
+		rtc_tm->tm_mon  = SUN6I_DATE_GET_MON_VALUE(date) - 1;
+		rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
+
+		/*
+		 * switch from (data_year->min)-relative offset to
+		 * a (1900)-relative one
+		 */
+		rtc_tm->tm_year += SUN6I_YEAR_OFF;
+	}
+
 	rtc_tm->tm_sec  = SUN6I_TIME_GET_SEC_VALUE(time);
 	rtc_tm->tm_min  = SUN6I_TIME_GET_MIN_VALUE(time);
 	rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time);
 
-	rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
-	rtc_tm->tm_mon  = SUN6I_DATE_GET_MON_VALUE(date);
-	rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
-
-	rtc_tm->tm_mon  -= 1;
-
-	/*
-	 * switch from (data_year->min)-relative offset to
-	 * a (1900)-relative one
-	 */
-	rtc_tm->tm_year += SUN6I_YEAR_OFF;
-
 	return 0;
 }
 
@@ -567,20 +580,25 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
 	u32 date = 0;
 	u32 time = 0;
 
-	rtc_tm->tm_year -= SUN6I_YEAR_OFF;
-	rtc_tm->tm_mon += 1;
-
-	date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
-		SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
-		SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
-
-	if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
-		date |= SUN6I_LEAP_SET_VALUE(1);
-
 	time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec)  |
 		SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min)  |
 		SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);
 
+	if (chip->flags & RTC_LINEAR_DAY) {
+		/* The division will cut off the H:M:S part of rtc_tm. */
+		date = div_u64(rtc_tm_to_time64(rtc_tm), SECS_PER_DAY);
+	} else {
+		rtc_tm->tm_year -= SUN6I_YEAR_OFF;
+		rtc_tm->tm_mon += 1;
+
+		date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
+			SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
+			SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
+
+		if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
+			date |= SUN6I_LEAP_SET_VALUE(1);
+	}
+
 	/* Check whether registers are writable */
 	if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL,
 			   SUN6I_LOSC_CTRL_ACC_MASK, 50)) {
@@ -674,6 +692,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, chip);
 
+	chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev);
+
 	chip->irq = platform_get_irq(pdev, 0);
 	if (chip->irq < 0)
 		return chip->irq;
@@ -720,7 +740,10 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 		return PTR_ERR(chip->rtc);
 
 	chip->rtc->ops = &sun6i_rtc_ops;
-	chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
+	if (chip->flags & RTC_LINEAR_DAY)
+		chip->rtc->range_max = (65536 * SECS_PER_DAY) - 1;
+	else
+		chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
 
 	ret = devm_rtc_register_device(chip->rtc);
 	if (ret)
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 03/17] rtc: sun6i: Add support for broken-down alarm registers
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:21   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

From: Andre Przywara <andre.przywara@arm.com>

Newer versions of the Allwinner RTC, for instance as found in the H616
SoC, not only store the current day as a linear number, but also change
the way the alarm is handled: There are now two registers, that
explicitly store the wakeup time, in the same format as the current
time.

Add support for that variant by writing the requested wakeup time
directly into the registers, instead of programming the seconds left, as
the old SoCs required.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/rtc/rtc-sun6i.c | 57 +++++++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index a980d4e7408d..752bea949050 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -48,7 +48,8 @@
 
 /* Alarm 0 (counter) */
 #define SUN6I_ALRM_COUNTER			0x0020
-#define SUN6I_ALRM_CUR_VAL			0x0024
+/* This holds the remaining alarm seconds on older SoCs (current value) */
+#define SUN6I_ALRM_COUNTER_HMS			0x0024
 #define SUN6I_ALRM_EN				0x0028
 #define SUN6I_ALRM_EN_CNT_EN			BIT(0)
 #define SUN6I_ALRM_IRQ_EN			0x002c
@@ -523,32 +524,54 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
 	struct rtc_time *alrm_tm = &wkalrm->time;
 	struct rtc_time tm_now;
-	time64_t time_now, time_set;
+	time64_t time_set;
+	u32 counter_val, counter_val_hms;
 	int ret;
 
-	ret = sun6i_rtc_gettime(dev, &tm_now);
-	if (ret < 0) {
-		dev_err(dev, "Error in getting time\n");
-		return -EINVAL;
-	}
-
 	time_set = rtc_tm_to_time64(alrm_tm);
-	time_now = rtc_tm_to_time64(&tm_now);
-	if (time_set <= time_now) {
-		dev_err(dev, "Date to set in the past\n");
-		return -EINVAL;
-	}
 
-	if ((time_set - time_now) > U32_MAX) {
-		dev_err(dev, "Date too far in the future\n");
-		return -EINVAL;
+	if (chip->flags & RTC_LINEAR_DAY) {
+		/*
+		 * The alarm registers hold the actual alarm time, encoded
+		 * in the same way (linear day + HMS) as the current time.
+		 */
+		counter_val_hms = SUN6I_TIME_SET_SEC_VALUE(alrm_tm->tm_sec)  |
+				  SUN6I_TIME_SET_MIN_VALUE(alrm_tm->tm_min)  |
+				  SUN6I_TIME_SET_HOUR_VALUE(alrm_tm->tm_hour);
+		/* The division will cut off the H:M:S part of alrm_tm. */
+		counter_val = div_u64(rtc_tm_to_time64(alrm_tm), SECS_PER_DAY);
+	} else {
+		/* The alarm register holds the number of seconds left. */
+		time64_t time_now;
+
+		ret = sun6i_rtc_gettime(dev, &tm_now);
+		if (ret < 0) {
+			dev_err(dev, "Error in getting time\n");
+			return -EINVAL;
+		}
+
+		time_now = rtc_tm_to_time64(&tm_now);
+		if (time_set <= time_now) {
+			dev_err(dev, "Date to set in the past\n");
+			return -EINVAL;
+		}
+		if ((time_set - time_now) > U32_MAX) {
+			dev_err(dev, "Date too far in the future\n");
+			return -EINVAL;
+		}
+
+		counter_val = time_set - time_now;
 	}
 
 	sun6i_rtc_setaie(0, chip);
 	writel(0, chip->base + SUN6I_ALRM_COUNTER);
+	if (chip->flags & RTC_LINEAR_DAY)
+		writel(0, chip->base + SUN6I_ALRM_COUNTER_HMS);
 	usleep_range(100, 300);
 
-	writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
+	writel(counter_val, chip->base + SUN6I_ALRM_COUNTER);
+	if (chip->flags & RTC_LINEAR_DAY)
+		writel(counter_val_hms, chip->base + SUN6I_ALRM_COUNTER_HMS);
 	chip->alarm = time_set;
 
 	sun6i_rtc_setaie(wkalrm->enabled, chip);
-- 
2.30.2


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

* [PATCH 03/17] rtc: sun6i: Add support for broken-down alarm registers
@ 2021-08-02  6:21   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

From: Andre Przywara <andre.przywara@arm.com>

Newer versions of the Allwinner RTC, for instance as found in the H616
SoC, not only store the current day as a linear number, but also change
the way the alarm is handled: There are now two registers, that
explicitly store the wakeup time, in the same format as the current
time.

Add support for that variant by writing the requested wakeup time
directly into the registers, instead of programming the seconds left, as
the old SoCs required.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/rtc/rtc-sun6i.c | 57 +++++++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index a980d4e7408d..752bea949050 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -48,7 +48,8 @@
 
 /* Alarm 0 (counter) */
 #define SUN6I_ALRM_COUNTER			0x0020
-#define SUN6I_ALRM_CUR_VAL			0x0024
+/* This holds the remaining alarm seconds on older SoCs (current value) */
+#define SUN6I_ALRM_COUNTER_HMS			0x0024
 #define SUN6I_ALRM_EN				0x0028
 #define SUN6I_ALRM_EN_CNT_EN			BIT(0)
 #define SUN6I_ALRM_IRQ_EN			0x002c
@@ -523,32 +524,54 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
 	struct rtc_time *alrm_tm = &wkalrm->time;
 	struct rtc_time tm_now;
-	time64_t time_now, time_set;
+	time64_t time_set;
+	u32 counter_val, counter_val_hms;
 	int ret;
 
-	ret = sun6i_rtc_gettime(dev, &tm_now);
-	if (ret < 0) {
-		dev_err(dev, "Error in getting time\n");
-		return -EINVAL;
-	}
-
 	time_set = rtc_tm_to_time64(alrm_tm);
-	time_now = rtc_tm_to_time64(&tm_now);
-	if (time_set <= time_now) {
-		dev_err(dev, "Date to set in the past\n");
-		return -EINVAL;
-	}
 
-	if ((time_set - time_now) > U32_MAX) {
-		dev_err(dev, "Date too far in the future\n");
-		return -EINVAL;
+	if (chip->flags & RTC_LINEAR_DAY) {
+		/*
+		 * The alarm registers hold the actual alarm time, encoded
+		 * in the same way (linear day + HMS) as the current time.
+		 */
+		counter_val_hms = SUN6I_TIME_SET_SEC_VALUE(alrm_tm->tm_sec)  |
+				  SUN6I_TIME_SET_MIN_VALUE(alrm_tm->tm_min)  |
+				  SUN6I_TIME_SET_HOUR_VALUE(alrm_tm->tm_hour);
+		/* The division will cut off the H:M:S part of alrm_tm. */
+		counter_val = div_u64(rtc_tm_to_time64(alrm_tm), SECS_PER_DAY);
+	} else {
+		/* The alarm register holds the number of seconds left. */
+		time64_t time_now;
+
+		ret = sun6i_rtc_gettime(dev, &tm_now);
+		if (ret < 0) {
+			dev_err(dev, "Error in getting time\n");
+			return -EINVAL;
+		}
+
+		time_now = rtc_tm_to_time64(&tm_now);
+		if (time_set <= time_now) {
+			dev_err(dev, "Date to set in the past\n");
+			return -EINVAL;
+		}
+		if ((time_set - time_now) > U32_MAX) {
+			dev_err(dev, "Date too far in the future\n");
+			return -EINVAL;
+		}
+
+		counter_val = time_set - time_now;
 	}
 
 	sun6i_rtc_setaie(0, chip);
 	writel(0, chip->base + SUN6I_ALRM_COUNTER);
+	if (chip->flags & RTC_LINEAR_DAY)
+		writel(0, chip->base + SUN6I_ALRM_COUNTER_HMS);
 	usleep_range(100, 300);
 
-	writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
+	writel(counter_val, chip->base + SUN6I_ALRM_COUNTER);
+	if (chip->flags & RTC_LINEAR_DAY)
+		writel(counter_val_hms, chip->base + SUN6I_ALRM_COUNTER_HMS);
 	chip->alarm = time_set;
 
 	sun6i_rtc_setaie(wkalrm->enabled, chip);
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 04/17] dt-bindings: rtc: sun6i: add compatible string for R329 RTC
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:21   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 has a RTC similar to previous ones, capable of
controlling LOSC and IOSC and with only one alarm.

Add a compatible string for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml    | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index beeb90e55727..7fd1ad46496b 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -26,6 +26,7 @@ properties:
           - const: allwinner,sun50i-a64-rtc
           - const: allwinner,sun8i-h3-rtc
       - const: allwinner,sun50i-h6-rtc
+      - const: allwinner,sun50i-r329-rtc
 
   reg:
     maxItems: 1
@@ -85,6 +86,7 @@ allOf:
             enum:
               - allwinner,sun8i-h3-rtc
               - allwinner,sun50i-h5-rtc
+              - allwinner,sun50i-r329-rtc
 
     then:
       properties:
@@ -108,7 +110,9 @@ allOf:
       properties:
         compatible:
           contains:
-            const: allwinner,sun8i-r40-rtc
+            enum:
+              - allwinner,sun8i-r40-rtc
+              - allwinner,sun50i-r329-rtc
 
     then:
       properties:
-- 
2.30.2


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

* [PATCH 04/17] dt-bindings: rtc: sun6i: add compatible string for R329 RTC
@ 2021-08-02  6:21   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:21 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 has a RTC similar to previous ones, capable of
controlling LOSC and IOSC and with only one alarm.

Add a compatible string for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml    | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index beeb90e55727..7fd1ad46496b 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -26,6 +26,7 @@ properties:
           - const: allwinner,sun50i-a64-rtc
           - const: allwinner,sun8i-h3-rtc
       - const: allwinner,sun50i-h6-rtc
+      - const: allwinner,sun50i-r329-rtc
 
   reg:
     maxItems: 1
@@ -85,6 +86,7 @@ allOf:
             enum:
               - allwinner,sun8i-h3-rtc
               - allwinner,sun50i-h5-rtc
+              - allwinner,sun50i-r329-rtc
 
     then:
       properties:
@@ -108,7 +110,9 @@ allOf:
       properties:
         compatible:
           contains:
-            const: allwinner,sun8i-r40-rtc
+            enum:
+              - allwinner,sun8i-r40-rtc
+              - allwinner,sun50i-r329-rtc
 
     then:
       properties:
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 05/17] rtc: sun6i: add support for R329 RTC
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 SoC has a RTC with similar clock control capability to
H6, but its day storage changed to be linear, similar to the one in H616
RTC.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/rtc/rtc-sun6i.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 752bea949050..06eca57e5215 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -386,6 +386,24 @@ static void __init sun50i_h6_rtc_clk_init(struct device_node *node)
 CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
 		      sun50i_h6_rtc_clk_init);
 
+static const struct sun6i_rtc_clk_data sun50i_r329_rtc_data = {
+	.rc_osc_rate = 16000000,
+	.fixed_prescaler = 32,
+	.has_prescaler = 1,
+	.has_out_clk = 1,
+	.export_iosc = 1,
+	.has_losc_en = 1,
+	.has_auto_swt = 1,
+};
+
+static void __init sun50i_r329_rtc_clk_init(struct device_node *node)
+{
+	sun6i_rtc_clk_init(node, &sun50i_r329_rtc_data);
+}
+
+CLK_OF_DECLARE_DRIVER(sun50i_r329_rtc_clk, "allwinner,sun50i-r329-rtc",
+		      sun50i_r329_rtc_clk_init);
+
 /*
  * The R40 user manual is self-conflicting on whether the prescaler is
  * fixed or configurable. The clock diagram shows it as fixed, but there
@@ -791,6 +809,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
 	{ .compatible = "allwinner,sun8i-v3-rtc" },
 	{ .compatible = "allwinner,sun50i-h5-rtc" },
 	{ .compatible = "allwinner,sun50i-h6-rtc" },
+	{ .compatible = "allwinner,sun50i-r329-rtc",
+		.data = (void *)RTC_LINEAR_DAY },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
-- 
2.30.2


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

* [PATCH 05/17] rtc: sun6i: add support for R329 RTC
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 SoC has a RTC with similar clock control capability to
H6, but its day storage changed to be linear, similar to the one in H616
RTC.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/rtc/rtc-sun6i.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 752bea949050..06eca57e5215 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -386,6 +386,24 @@ static void __init sun50i_h6_rtc_clk_init(struct device_node *node)
 CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
 		      sun50i_h6_rtc_clk_init);
 
+static const struct sun6i_rtc_clk_data sun50i_r329_rtc_data = {
+	.rc_osc_rate = 16000000,
+	.fixed_prescaler = 32,
+	.has_prescaler = 1,
+	.has_out_clk = 1,
+	.export_iosc = 1,
+	.has_losc_en = 1,
+	.has_auto_swt = 1,
+};
+
+static void __init sun50i_r329_rtc_clk_init(struct device_node *node)
+{
+	sun6i_rtc_clk_init(node, &sun50i_r329_rtc_data);
+}
+
+CLK_OF_DECLARE_DRIVER(sun50i_r329_rtc_clk, "allwinner,sun50i-r329-rtc",
+		      sun50i_r329_rtc_clk_init);
+
 /*
  * The R40 user manual is self-conflicting on whether the prescaler is
  * fixed or configurable. The clock diagram shows it as fixed, but there
@@ -791,6 +809,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
 	{ .compatible = "allwinner,sun8i-v3-rtc" },
 	{ .compatible = "allwinner,sun50i-h5-rtc" },
 	{ .compatible = "allwinner,sun50i-h6-rtc" },
+	{ .compatible = "allwinner,sun50i-r329-rtc",
+		.data = (void *)RTC_LINEAR_DAY },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 have two pin controllers similar to previous Allwinner
SoCs, PIO and R-PIO.

Add compatible strings for them.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
index cce63c3cc463..802fba3fa34d 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
@@ -55,6 +55,8 @@ properties:
       - allwinner,sun50i-h6-r-pinctrl
       - allwinner,sun50i-h616-pinctrl
       - allwinner,sun50i-h616-r-pinctrl
+      - allwinner,sun50i-r329-pinctrl
+      - allwinner,sun50i-r329-r-pinctrl
       - allwinner,suniv-f1c100s-pinctrl
       - nextthing,gr8-pinctrl
 
@@ -189,6 +191,7 @@ allOf:
             - allwinner,sun6i-a31-pinctrl
             - allwinner,sun6i-a31s-pinctrl
             - allwinner,sun50i-h6-pinctrl
+            - allwinner,sun50i-r329-pinctrl
 
     then:
       properties:
@@ -204,6 +207,7 @@ allOf:
             - allwinner,sun8i-a83t-pinctrl
             - allwinner,sun50i-a64-pinctrl
             - allwinner,sun50i-h5-pinctrl
+            - allwinner,sun50i-r329-r-pinctrl
             - allwinner,suniv-f1c100s-pinctrl
 
     then:
-- 
2.30.2


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

* [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 have two pin controllers similar to previous Allwinner
SoCs, PIO and R-PIO.

Add compatible strings for them.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
index cce63c3cc463..802fba3fa34d 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
@@ -55,6 +55,8 @@ properties:
       - allwinner,sun50i-h6-r-pinctrl
       - allwinner,sun50i-h616-pinctrl
       - allwinner,sun50i-h616-r-pinctrl
+      - allwinner,sun50i-r329-pinctrl
+      - allwinner,sun50i-r329-r-pinctrl
       - allwinner,suniv-f1c100s-pinctrl
       - nextthing,gr8-pinctrl
 
@@ -189,6 +191,7 @@ allOf:
             - allwinner,sun6i-a31-pinctrl
             - allwinner,sun6i-a31s-pinctrl
             - allwinner,sun50i-h6-pinctrl
+            - allwinner,sun50i-r329-pinctrl
 
     then:
       properties:
@@ -204,6 +207,7 @@ allOf:
             - allwinner,sun8i-a83t-pinctrl
             - allwinner,sun50i-a64-pinctrl
             - allwinner,sun50i-h5-pinctrl
+            - allwinner,sun50i-r329-r-pinctrl
             - allwinner,suniv-f1c100s-pinctrl
 
     then:
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 SoC has two pin controllers similar to ones on previous
SoCs, one in CPUX power domain and another in CPUS.

This patch adds support for the CPUX domain pin controller.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/pinctrl/sunxi/Kconfig               |   5 +
 drivers/pinctrl/sunxi/Makefile              |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c | 410 ++++++++++++++++++++
 3 files changed, 416 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 33751a6a0757..c662e8b1b351 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -129,4 +129,9 @@ config PINCTRL_SUN50I_H616_R
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN50I_R329
+	bool "Support for the Allwinner R329 PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index d3440c42b9d6..e33f7c5f1ff9 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -25,5 +25,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
+obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
new file mode 100644
index 000000000000..742f437ec0b6
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner R329 SoC pinctrl driver.
+ *
+ * Copyright (C) 2021 Sipeed
+ * based on the H616 pinctrl driver
+ *   Copyright (C) 2020 Arm Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin r329_pins[] = {
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM0 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
+		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PB_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM1 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
+		  SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PB_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM2 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
+		  SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PB_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM3 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
+		  SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PB_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart0"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM4 */
+		  SUNXI_FUNCTION(0x4, "i2s0_dout0"),
+		  SUNXI_FUNCTION(0x5, "i2s0_din1"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PB_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart0"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM5 */
+		  SUNXI_FUNCTION(0x4, "i2s0_dout1"),
+		  SUNXI_FUNCTION(0x5, "i2s0_din0"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PB_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "ir"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM6 */
+		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT2 */
+		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PB_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "ir"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM7 */
+		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT3 */
+		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PB_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "ir_tx"),
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM8 */
+		  SUNXI_FUNCTION(0x4, "ir_rx"),
+		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PB_EINT8 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RB0 */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CLK */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* CS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CMD */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* MISO */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE0 */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D2 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* WP */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CLE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D1 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* MOSI */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* ALE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D0 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* WE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D3 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* HOLD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ0 */
+		  SUNXI_FUNCTION(0x3, "mmc0")),		/* RST */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ1 */
+		  SUNXI_FUNCTION(0x5, "boot_sel")),
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ7 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPEN */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PF_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ6 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPPP */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PF_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ5 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* PWREN */
+		  SUNXI_FUNCTION(0x4, "uart"),		/* TX */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PF_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ4 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* CLK */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CMD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PF_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQS */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* DATA */
+		  SUNXI_FUNCTION(0x4, "uart"),		/* RX */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PF_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ2 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* RST */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PF_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ1 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* DET */
+		  SUNXI_FUNCTION(0x4, "spdif_in"),
+		  SUNXI_FUNCTION(0x5, "spdif_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PF_EINT6 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_clk"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d2"),
+		  /* 0x4 is also mmc1_d2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PG_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_cmd"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d3"),
+		  SUNXI_FUNCTION(0x4, "mmc1_clk"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PG_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d0"),
+		  SUNXI_FUNCTION(0x3, "mmc1_cmd"),
+		  SUNXI_FUNCTION(0x4, "mmc1_d3"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PG_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d1"),
+		  SUNXI_FUNCTION(0x3, "mmc1_clk"),
+		  /* 0x4 is also mmc1_d1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PG_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d2"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d0"),
+		  /* 0x4 is also mmc1_d0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PG_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d3"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d1"),
+		  SUNXI_FUNCTION(0x4, "mmc1_cmd"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PG_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PG_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PG_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PG_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* WP/DBI-TE */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PG_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
+		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PG_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* LRCK */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* CS/DBI-CSX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PG_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* CLK/DBI-SCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PG_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "i2s1_dout0"),
+		  SUNXI_FUNCTION(0x4, "i2s1_din1"),
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI/DBI-SDO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PG_EINT13 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "i2s1_dout1"),
+		  SUNXI_FUNCTION(0x4, "i2s1_din0"),
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PG_EINT14 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* CS/DBI-CSX */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 0)),	/* PH_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* CLK/DBI-SCLK */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 1)),	/* PH_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI/DBI-SDO */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 2)),	/* PH_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 3)),	/* PH_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "spi1_cs"),	/* CS/DBI-CSX */
+		  SUNXI_FUNCTION(0x4, "spi1_hold"),	/* HOLD/DBI-DCX/DBI-WRX */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 4)),	/* PH_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "spi1_clk"),	/* CLK/DBI-SCLK */
+		  SUNXI_FUNCTION(0x4, "spi1_wp"),	/* WP/DBI-TE */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 5)),	/* PH_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* MOSI/SPI-DBO */
+		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM4 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)),	/* PH_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
+		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM5 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)),	/* PH_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* WP/DBI-TE */
+		  SUNXI_FUNCTION(0x4, "ledc"),		/* DO */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)),	/* PH_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
+		  SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)),	/* PH_EINT9 */
+};
+static const unsigned int r329_irq_bank_map[] = { 1, 5, 6, 7 };
+
+static const struct sunxi_pinctrl_desc r329_pinctrl_data = {
+	.pins = r329_pins,
+	.npins = ARRAY_SIZE(r329_pins),
+	.irq_banks = ARRAY_SIZE(r329_irq_bank_map),
+	.irq_bank_map = r329_irq_bank_map,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int r329_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_init(pdev, &r329_pinctrl_data);
+}
+
+static const struct of_device_id r329_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun50i-r329-pinctrl", },
+	{}
+};
+
+static struct platform_driver r329_pinctrl_driver = {
+	.probe	= r329_pinctrl_probe,
+	.driver	= {
+		.name		= "sun50i-r329-pinctrl",
+		.of_match_table	= r329_pinctrl_match,
+	},
+};
+builtin_platform_driver(r329_pinctrl_driver);
-- 
2.30.2


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

* [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 SoC has two pin controllers similar to ones on previous
SoCs, one in CPUX power domain and another in CPUS.

This patch adds support for the CPUX domain pin controller.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/pinctrl/sunxi/Kconfig               |   5 +
 drivers/pinctrl/sunxi/Makefile              |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c | 410 ++++++++++++++++++++
 3 files changed, 416 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 33751a6a0757..c662e8b1b351 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -129,4 +129,9 @@ config PINCTRL_SUN50I_H616_R
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN50I_R329
+	bool "Support for the Allwinner R329 PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index d3440c42b9d6..e33f7c5f1ff9 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -25,5 +25,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
+obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
new file mode 100644
index 000000000000..742f437ec0b6
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner R329 SoC pinctrl driver.
+ *
+ * Copyright (C) 2021 Sipeed
+ * based on the H616 pinctrl driver
+ *   Copyright (C) 2020 Arm Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin r329_pins[] = {
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM0 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
+		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PB_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM1 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
+		  SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PB_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM2 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
+		  SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PB_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM3 */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
+		  SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PB_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart0"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM4 */
+		  SUNXI_FUNCTION(0x4, "i2s0_dout0"),
+		  SUNXI_FUNCTION(0x5, "i2s0_din1"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PB_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart0"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM5 */
+		  SUNXI_FUNCTION(0x4, "i2s0_dout1"),
+		  SUNXI_FUNCTION(0x5, "i2s0_din0"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PB_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "ir"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM6 */
+		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT2 */
+		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PB_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "ir"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM7 */
+		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT3 */
+		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PB_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "ir_tx"),
+		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM8 */
+		  SUNXI_FUNCTION(0x4, "ir_rx"),
+		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PB_EINT8 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RB0 */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CLK */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* CS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CMD */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* MISO */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE0 */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D2 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* WP */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CLE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D1 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* MOSI */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* ALE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D0 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* WE */
+		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D3 */
+		  SUNXI_FUNCTION(0x4, "spi0")),		/* HOLD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ0 */
+		  SUNXI_FUNCTION(0x3, "mmc0")),		/* RST */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ1 */
+		  SUNXI_FUNCTION(0x5, "boot_sel")),
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ7 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPEN */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PF_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ6 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPPP */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PF_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ5 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* PWREN */
+		  SUNXI_FUNCTION(0x4, "uart"),		/* TX */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PF_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ4 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* CLK */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CMD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PF_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQS */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* DATA */
+		  SUNXI_FUNCTION(0x4, "uart"),		/* RX */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PF_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ2 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* RST */
+		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
+		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PF_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ1 */
+		  SUNXI_FUNCTION(0x3, "sim0"),		/* DET */
+		  SUNXI_FUNCTION(0x4, "spdif_in"),
+		  SUNXI_FUNCTION(0x5, "spdif_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PF_EINT6 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_clk"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d2"),
+		  /* 0x4 is also mmc1_d2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PG_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_cmd"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d3"),
+		  SUNXI_FUNCTION(0x4, "mmc1_clk"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PG_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d0"),
+		  SUNXI_FUNCTION(0x3, "mmc1_cmd"),
+		  SUNXI_FUNCTION(0x4, "mmc1_d3"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PG_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d1"),
+		  SUNXI_FUNCTION(0x3, "mmc1_clk"),
+		  /* 0x4 is also mmc1_d1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PG_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d2"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d0"),
+		  /* 0x4 is also mmc1_d0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PG_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1_d3"),
+		  SUNXI_FUNCTION(0x3, "mmc1_d1"),
+		  SUNXI_FUNCTION(0x4, "mmc1_cmd"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PG_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PG_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PG_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PG_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* WP/DBI-TE */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PG_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
+		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PG_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* LRCK */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* CS/DBI-CSX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PG_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* CLK/DBI-SCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PG_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "i2s1_dout0"),
+		  SUNXI_FUNCTION(0x4, "i2s1_din1"),
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI/DBI-SDO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PG_EINT13 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "i2s1_dout1"),
+		  SUNXI_FUNCTION(0x4, "i2s1_din0"),
+		  SUNXI_FUNCTION(0x5, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PG_EINT14 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* CS/DBI-CSX */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 0)),	/* PH_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* CLK/DBI-SCLK */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 1)),	/* PH_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI/DBI-SDO */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 2)),	/* PH_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
+		  SUNXI_FUNCTION(0x4, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 3)),	/* PH_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
+		  SUNXI_FUNCTION(0x3, "spi1_cs"),	/* CS/DBI-CSX */
+		  SUNXI_FUNCTION(0x4, "spi1_hold"),	/* HOLD/DBI-DCX/DBI-WRX */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 4)),	/* PH_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "spi1_clk"),	/* CLK/DBI-SCLK */
+		  SUNXI_FUNCTION(0x4, "spi1_wp"),	/* WP/DBI-TE */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 5)),	/* PH_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* MOSI/SPI-DBO */
+		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM4 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)),	/* PH_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
+		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM5 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)),	/* PH_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* WP/DBI-TE */
+		  SUNXI_FUNCTION(0x4, "ledc"),		/* DO */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)),	/* PH_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
+		  SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
+		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)),	/* PH_EINT9 */
+};
+static const unsigned int r329_irq_bank_map[] = { 1, 5, 6, 7 };
+
+static const struct sunxi_pinctrl_desc r329_pinctrl_data = {
+	.pins = r329_pins,
+	.npins = ARRAY_SIZE(r329_pins),
+	.irq_banks = ARRAY_SIZE(r329_irq_bank_map),
+	.irq_bank_map = r329_irq_bank_map,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int r329_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_init(pdev, &r329_pinctrl_data);
+}
+
+static const struct of_device_id r329_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun50i-r329-pinctrl", },
+	{}
+};
+
+static struct platform_driver r329_pinctrl_driver = {
+	.probe	= r329_pinctrl_probe,
+	.driver	= {
+		.name		= "sun50i-r329-pinctrl",
+		.of_match_table	= r329_pinctrl_match,
+	},
+};
+builtin_platform_driver(r329_pinctrl_driver);
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 08/17] pinctrl: sunxi: add support for R329 R-PIO pin controller
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R320 SoC has a pin controller in the CPUS power domain.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/pinctrl/sunxi/Kconfig                 |   5 +
 drivers/pinctrl/sunxi/Makefile                |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c | 292 ++++++++++++++++++
 3 files changed, 298 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index c662e8b1b351..abd60ff8daec 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -134,4 +134,9 @@ config PINCTRL_SUN50I_R329
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN50I_R329_R
+	bool "Support for the Allwinner R329 R-PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index e33f7c5f1ff9..245840a7959e 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -26,5 +26,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
+obj-$(CONFIG_PINCTRL_SUN50I_R329_R)	+= pinctrl-sun50i-r329-r.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
new file mode 100644
index 000000000000..dc4792c685ba
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner H616 R_PIO pin controller driver
+ *
+ * Copyright (C) 2020 Arm Ltd.
+ * Based on former work, which is:
+ *   Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/reset.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun50i_r329_r_pins[] = {
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* LRCK */
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA3 */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PL_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* BCLK */
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA2 */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PL_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s_dout0"),
+		  SUNXI_FUNCTION(0x3, "s_i2s_din1"),
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA1 */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PL_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s_dout1"),
+		  SUNXI_FUNCTION(0x3, "s_i2s_din0"),
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA0 */
+		  SUNXI_FUNCTION(0x5, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PL_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* MCLK */
+		  SUNXI_FUNCTION(0x3, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* CLK */
+		  SUNXI_FUNCTION(0x5, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PL_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PL_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM4 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PL_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM5 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PL_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* TX */
+		  SUNXI_FUNCTION(0x3, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x4, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PL_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* RX */
+		  SUNXI_FUNCTION(0x3, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION(0x4, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)),	/* PL_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)),	/* PL_EINT10 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* TX */
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* MS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PM_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* RX */
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* CK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PM_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* DO */
+		  SUNXI_FUNCTION(0x4, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PM_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PM_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PM_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* DI */
+		  SUNXI_FUNCTION(0x4, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PM_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nmi"),
+		  SUNXI_FUNCTION(0x3, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PM_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)),	/* PM_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)),	/* PM_EINT8 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PN_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PN_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PN_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PN_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PN_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PN_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PN_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PN_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXERR */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PN_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXCTL/TXEN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PN_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PN_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PN_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXCTL/CRS_DV */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PN_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PN_EINT13 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PN_EINT14 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 15)),	/* PN_EINT15 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* EPHY-25M */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 16)),	/* PN_EINT16 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* CLKIN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 17)),	/* PN_EINT17 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 18),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 18)),	/* PN_EINT18 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 19),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 19)),	/* PN_EINT19 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 20),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 20)),	/* PN_EINT20 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 21),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 21)),	/* PN_EINT21 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 22),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 22)),	/* PN_EINT22 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 23),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 23)),	/* PN_EINT23 */
+};
+
+static const struct sunxi_pinctrl_desc sun50i_r329_r_pinctrl_data = {
+	.pins = sun50i_r329_r_pins,
+	.npins = ARRAY_SIZE(sun50i_r329_r_pins),
+	.pin_base = PL_BASE,
+	.irq_banks = 3,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int sun50i_r329_r_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_init(pdev,
+				  &sun50i_r329_r_pinctrl_data);
+}
+
+static const struct of_device_id sun50i_r329_r_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun50i-r329-r-pinctrl", },
+	{}
+};
+
+static struct platform_driver sun50i_r329_r_pinctrl_driver = {
+	.probe	= sun50i_r329_r_pinctrl_probe,
+	.driver	= {
+		.name		= "sun50i-r329-r-pinctrl",
+		.of_match_table	= sun50i_r329_r_pinctrl_match,
+	},
+};
+builtin_platform_driver(sun50i_r329_r_pinctrl_driver);
-- 
2.30.2


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

* [PATCH 08/17] pinctrl: sunxi: add support for R329 R-PIO pin controller
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R320 SoC has a pin controller in the CPUS power domain.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/pinctrl/sunxi/Kconfig                 |   5 +
 drivers/pinctrl/sunxi/Makefile                |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c | 292 ++++++++++++++++++
 3 files changed, 298 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index c662e8b1b351..abd60ff8daec 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -134,4 +134,9 @@ config PINCTRL_SUN50I_R329
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN50I_R329_R
+	bool "Support for the Allwinner R329 R-PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index e33f7c5f1ff9..245840a7959e 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -26,5 +26,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
+obj-$(CONFIG_PINCTRL_SUN50I_R329_R)	+= pinctrl-sun50i-r329-r.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
new file mode 100644
index 000000000000..dc4792c685ba
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner H616 R_PIO pin controller driver
+ *
+ * Copyright (C) 2020 Arm Ltd.
+ * Based on former work, which is:
+ *   Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/reset.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun50i_r329_r_pins[] = {
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* LRCK */
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA3 */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PL_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* BCLK */
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA2 */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PL_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s_dout0"),
+		  SUNXI_FUNCTION(0x3, "s_i2s_din1"),
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA1 */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PL_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s_dout1"),
+		  SUNXI_FUNCTION(0x3, "s_i2s_din0"),
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* DATA0 */
+		  SUNXI_FUNCTION(0x5, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PL_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* MCLK */
+		  SUNXI_FUNCTION(0x3, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "s_dmic"),	/* CLK */
+		  SUNXI_FUNCTION(0x5, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PL_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PL_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM4 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PL_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION(0x5, "s_pwm"),		/* PWM5 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PL_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* TX */
+		  SUNXI_FUNCTION(0x3, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x4, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PL_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* RX */
+		  SUNXI_FUNCTION(0x3, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION(0x4, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)),	/* PL_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)),	/* PL_EINT10 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* TX */
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* MS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PM_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* RX */
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* CK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PM_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* DO */
+		  SUNXI_FUNCTION(0x4, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x5, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PM_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PM_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PM_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* DI */
+		  SUNXI_FUNCTION(0x4, "s_i2c"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PM_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nmi"),
+		  SUNXI_FUNCTION(0x3, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x4, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PM_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_ir"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "clock"),		/* X32KFOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)),	/* PM_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)),	/* PM_EINT8 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PN_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PN_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PN_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PN_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PN_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PN_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PN_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PN_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXERR */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PN_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXCTL/TXEN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PN_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PN_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXD1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PN_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* RXCTL/CRS_DV */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PN_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PN_EINT13 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PN_EINT14 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 15)),	/* PN_EINT15 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* EPHY-25M */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 16)),	/* PN_EINT16 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "emac"),		/* CLKIN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 17)),	/* PN_EINT17 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 18),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 18)),	/* PN_EINT18 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 19),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 19)),	/* PN_EINT19 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 20),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 20)),	/* PN_EINT20 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 21),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 21)),	/* PN_EINT21 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 22),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 22)),	/* PN_EINT22 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 23),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 23)),	/* PN_EINT23 */
+};
+
+static const struct sunxi_pinctrl_desc sun50i_r329_r_pinctrl_data = {
+	.pins = sun50i_r329_r_pins,
+	.npins = ARRAY_SIZE(sun50i_r329_r_pins),
+	.pin_base = PL_BASE,
+	.irq_banks = 3,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int sun50i_r329_r_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_init(pdev,
+				  &sun50i_r329_r_pinctrl_data);
+}
+
+static const struct of_device_id sun50i_r329_r_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun50i-r329-r-pinctrl", },
+	{}
+};
+
+static struct platform_driver sun50i_r329_r_pinctrl_driver = {
+	.probe	= sun50i_r329_r_pinctrl_probe,
+	.driver	= {
+		.name		= "sun50i-r329-r-pinctrl",
+		.of_match_table	= sun50i_r329_r_pinctrl_match,
+	},
+};
+builtin_platform_driver(sun50i_r329_r_pinctrl_driver);
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 09/17] dt-bindings: clock: sunxi-ng: add compatibles for R329 CCUs
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

R329 has a CPUX CCU and a R-CCU.

Add compatible strings for them.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml    | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index c4b7243ddcf2..4c9a50f263c8 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -43,6 +43,8 @@ properties:
       - allwinner,sun50i-h6-r-ccu
       - allwinner,sun50i-h616-ccu
       - allwinner,sun50i-h616-r-ccu
+      - allwinner,sun50i-r329-ccu
+      - allwinner,sun50i-r329-r-ccu
       - allwinner,suniv-f1c100s-ccu
       - nextthing,gr8-ccu
 
@@ -102,6 +104,8 @@ else:
           - allwinner,sun50i-a100-ccu
           - allwinner,sun50i-h6-ccu
           - allwinner,sun50i-h616-ccu
+          - allwinner,sun50i-r329-ccu
+          - allwinner,sun50i-r329-r-ccu
 
   then:
     properties:
-- 
2.30.2


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

* [PATCH 09/17] dt-bindings: clock: sunxi-ng: add compatibles for R329 CCUs
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

R329 has a CPUX CCU and a R-CCU.

Add compatible strings for them.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml    | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index c4b7243ddcf2..4c9a50f263c8 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -43,6 +43,8 @@ properties:
       - allwinner,sun50i-h6-r-ccu
       - allwinner,sun50i-h616-ccu
       - allwinner,sun50i-h616-r-ccu
+      - allwinner,sun50i-r329-ccu
+      - allwinner,sun50i-r329-r-ccu
       - allwinner,suniv-f1c100s-ccu
       - nextthing,gr8-ccu
 
@@ -102,6 +104,8 @@ else:
           - allwinner,sun50i-a100-ccu
           - allwinner,sun50i-h6-ccu
           - allwinner,sun50i-h616-ccu
+          - allwinner,sun50i-r329-ccu
+          - allwinner,sun50i-r329-r-ccu
 
   then:
     properties:
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 has clock controls in PRCM, like other new Allwinner
SoCs.

Add support for them.

This driver is added before the main CCU because PLLs are controlled by
R-CCU on R329.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/clk/sunxi-ng/Kconfig                  |   5 +
 drivers/clk/sunxi-ng/Makefile                 |   1 +
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
 include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
 include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
 6 files changed, 470 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index cd46d8853876..e49b2c2fa5b7 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
 	default ARM64 && ARCH_SUNXI
 	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
+config SUN50I_R329_R_CCU
+	bool "Support for the Allwinner R329 PRCM CCU"
+	default ARM64 && ARCH_SUNXI
+	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	bool "Support for the Allwinner A10/A20 CCU"
 	default MACH_SUN4I
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 96c324306d97..db338a2188fd 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
 obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
+obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
 obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
new file mode 100644
index 000000000000..5413a701cb57
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Sipeed
+ * Based on the H616 CCU driver, which is:
+ *   Copyright (c) 2020 Arm Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.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-sun50i-r329-r.h"
+
+/*
+ * The M factor is present in the register's description, but not in the
+ * frequency formula, and it's documented as "The bit is only for
+ * testing", so it's not modelled and then force to 0.
+ */
+#define SUN50I_R329_PLL_CPUX_REG	0x1000
+static struct ccu_mult pll_cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.mult		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.common		= {
+		.reg		= 0x1000,
+		.hw.init	= CLK_HW_INIT("pll-cpux", "osc24M",
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+#define SUN50I_R329_PLL_PERIPH_REG	0x1010
+static struct ccu_nm pll_periph_base_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x1010,
+		.hw.init	= CLK_HW_INIT("pll-periph-base", "osc24M",
+					      &ccu_nm_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-base",
+		   0x1010, 16, 3, 0);
+static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-periph-base",
+		   0x1010, 20, 3, 0);
+static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
+			   &pll_periph_2x_clk.common.hw, 2, 1, 0);
+
+#define SUN50I_R329_PLL_AUDIO0_REG	0x1020
+static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
+	{ .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64 },
+};
+
+static struct ccu_nm pll_audio0_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(1, 1),
+	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table,
+					 BIT(24), 0x1120, BIT(31)),
+	.common		= {
+		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
+		.reg		= 0x1020,
+		.hw.init	= CLK_HW_INIT("pll-audio0", "osc24M",
+					      &ccu_nm_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-audio0",
+		   0x1020, 16, 3, 0);
+static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-audio0",
+		   0x1020, 20, 3, 0);
+
+/*
+ * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
+ * BSP driver always has M0 = 1 and M1 = 2 (this is also the
+ * reset value in the register).
+ *
+ * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
+ */
+#define SUN50I_R329_PLL_AUDIO1_REG	0x1030
+static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
+	{ .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22 },
+	{ .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24 },
+	{ .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
+	{ .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
+};
+static struct ccu_nm pll_audio1_4x_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(16, 6),
+	.fixed_post_div	= 2,
+	.sdm		= _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
+					 BIT(24), 0x1130, BIT(31)),
+	.common		= {
+		.features	= CCU_FEATURE_FIXED_POSTDIV |
+				  CCU_FEATURE_SIGMA_DELTA_MOD,
+		.reg		= 0x1030,
+		.hw.init	= CLK_HW_INIT("pll-audio1-4x", "osc24M",
+					      &ccu_nm_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
+			   &pll_audio1_4x_clk.common.hw, 2, 1,
+			   CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
+			   &pll_audio1_4x_clk.common.hw, 4, 1,
+			   CLK_SET_RATE_PARENT);
+
+static const char * const r_bus_parents[] = { "osc24M", "osc32k", "iosc",
+					      "pll-periph-2x",
+					      "pll-audio0-div2" };
+static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents, 0x000,
+			     0, 5,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents, 0x00c,
+			     0, 5,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents, 0x010,
+			     0, 5,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
+		      0x0ec, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c, BIT(0), 0);
+
+static const char * const r_pwm_parents[] = { "osc24M", "osc32k", "iosc" };
+static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents, 0x130,
+			       24, 3,	/* mux */
+			       BIT(31),	/* gate */
+			       0);
+
+static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c, BIT(0), 0);
+
+static const char * const r_audio_parents[] = { "pll-audio0-div5", "pll-audio0-div2",
+						"pll-audio1-1x", "pll-audio1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc", r_audio_parents, 0x140,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac", r_audio_parents, 0x144,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
+		      0x14c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic", r_audio_parents, 0x150,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
+		      0x16c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s", r_audio_parents, 0x170,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
+				  r_audio_parents, 0x174,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c, BIT(0), 0);
+
+static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents, 0x1c0,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
+		      0x1dc, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-apb1",
+		      0x1ec, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
+		      0x20c, BIT(0), CLK_IS_CRITICAL);
+
+static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
+	&pll_cpux_clk.common,
+	&pll_periph_base_clk.common,
+	&pll_periph_2x_clk.common,
+	&pll_periph_800m_clk.common,
+	&pll_audio0_clk.common,
+	&pll_audio0_div2_clk.common,
+	&pll_audio0_div5_clk.common,
+	&pll_audio1_4x_clk.common,
+	&r_ahb_clk.common,
+	&r_apb1_clk.common,
+	&r_apb2_clk.common,
+	&r_bus_gpadc_clk.common,
+	&r_bus_ths_clk.common,
+	&r_bus_dma_clk.common,
+	&r_pwm_clk.common,
+	&r_bus_pwm_clk.common,
+	&r_codec_adc_clk.common,
+	&r_codec_dac_clk.common,
+	&r_bus_codec_clk.common,
+	&r_dmic_clk.common,
+	&r_bus_dmic_clk.common,
+	&r_bus_lradc_clk.common,
+	&r_i2s_clk.common,
+	&r_i2s_asrc_clk.common,
+	&r_bus_i2s_clk.common,
+	&r_bus_uart_clk.common,
+	&r_bus_i2c_clk.common,
+	&r_ir_clk.common,
+	&r_bus_ir_clk.common,
+	&r_bus_msgbox_clk.common,
+	&r_bus_spinlock_clk.common,
+	&r_bus_rtc_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
+	.hws	= {
+		[CLK_PLL_CPUX]		= &pll_cpux_clk.common.hw,
+		[CLK_PLL_PERIPH_BASE]	= &pll_periph_base_clk.common.hw,
+		[CLK_PLL_PERIPH_2X]	= &pll_periph_2x_clk.common.hw,
+		[CLK_PLL_PERIPH_800M]	= &pll_periph_800m_clk.common.hw,
+		[CLK_PLL_PERIPH]	= &pll_periph_clk.hw,
+		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.common.hw,
+		[CLK_PLL_AUDIO0_DIV2]	= &pll_audio0_div2_clk.common.hw,
+		[CLK_PLL_AUDIO0_DIV5]	= &pll_audio0_div5_clk.common.hw,
+		[CLK_PLL_AUDIO1_4X]	= &pll_audio1_4x_clk.common.hw,
+		[CLK_PLL_AUDIO1_2X]	= &pll_audio1_2x_clk.hw,
+		[CLK_PLL_AUDIO1]	= &pll_audio1_clk.hw,
+		[CLK_R_AHB]		= &r_ahb_clk.common.hw,
+		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
+		[CLK_R_APB2]		= &r_apb2_clk.common.hw,
+		[CLK_R_BUS_GPADC]	= &r_bus_gpadc_clk.common.hw,
+		[CLK_R_BUS_THS]		= &r_bus_ths_clk.common.hw,
+		[CLK_R_BUS_DMA]		= &r_bus_dma_clk.common.hw,
+		[CLK_R_PWM]		= &r_pwm_clk.common.hw,
+		[CLK_R_BUS_PWM]		= &r_bus_pwm_clk.common.hw,
+		[CLK_R_CODEC_ADC]	= &r_codec_adc_clk.common.hw,
+		[CLK_R_CODEC_DAC]	= &r_codec_dac_clk.common.hw,
+		[CLK_R_BUS_CODEC]	= &r_bus_codec_clk.common.hw,
+		[CLK_R_DMIC]		= &r_dmic_clk.common.hw,
+		[CLK_R_BUS_DMIC]	= &r_bus_dmic_clk.common.hw,
+		[CLK_R_BUS_LRADC]	= &r_bus_lradc_clk.common.hw,
+		[CLK_R_I2S]		= &r_i2s_clk.common.hw,
+		[CLK_R_I2S_ASRC]	= &r_i2s_asrc_clk.common.hw,
+		[CLK_R_BUS_I2S]		= &r_bus_i2s_clk.common.hw,
+		[CLK_R_BUS_UART]	= &r_bus_uart_clk.common.hw,
+		[CLK_R_BUS_I2C]		= &r_bus_i2c_clk.common.hw,
+		[CLK_R_IR]		= &r_ir_clk.common.hw,
+		[CLK_R_BUS_IR]		= &r_bus_ir_clk.common.hw,
+		[CLK_R_BUS_MSGBOX]	= &r_bus_msgbox_clk.common.hw,
+		[CLK_R_BUS_SPINLOCK]	= &r_bus_spinlock_clk.common.hw,
+		[CLK_R_BUS_RTC]		= &r_bus_rtc_clk.common.hw,
+	},
+	.num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
+	[RST_R_BUS_GPADC]	= { 0x0ec, BIT(16) },
+	[RST_R_BUS_THS]		= { 0x0fc, BIT(16) },
+	[RST_R_BUS_DMA]		= { 0x10c, BIT(16) },
+	[RST_R_BUS_PWM]		= { 0x13c, BIT(16) },
+	[RST_R_BUS_CODEC]	= { 0x14c, BIT(16) },
+	[RST_R_BUS_DMIC]	= { 0x15c, BIT(16) },
+	[RST_R_BUS_LRADC]	= { 0x16c, BIT(16) },
+	[RST_R_BUS_I2S]		= { 0x17c, BIT(16) },
+	[RST_R_BUS_UART]	= { 0x18c, BIT(16) },
+	[RST_R_BUS_I2C]		= { 0x19c, BIT(16) },
+	[RST_R_BUS_IR]		= { 0x1cc, BIT(16) },
+	[RST_R_BUS_MSGBOX]	= { 0x1dc, BIT(16) },
+	[RST_R_BUS_SPINLOCK]	= { 0x1ec, BIT(16) },
+	[RST_R_BUS_RTC]		= { 0x20c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
+	.ccu_clks	= sun50i_r329_r_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_r_ccu_clks),
+
+	.hw_clks	= &sun50i_r329_r_hw_clks,
+
+	.resets		= sun50i_r329_r_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_r329_r_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+	SUN50I_R329_PLL_CPUX_REG,
+	SUN50I_R329_PLL_PERIPH_REG,
+	SUN50I_R329_PLL_AUDIO0_REG,
+	SUN50I_R329_PLL_AUDIO1_REG,
+};
+
+static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
+{
+	void __iomem *reg;
+	u32 val;
+	int i;
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		pr_err("%pOF: Could not map clock registers\n", node);
+		return;
+	}
+
+	/* Enable the lock bits and the output enable bits on all PLLs */
+	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+		val = readl(reg + pll_regs[i]);
+		val |= BIT(29) | BIT(27);
+		writel(val, reg + pll_regs[i]);
+	}
+
+	/*
+	 * Force the I/O dividers of PLL-AUDIO1 to reset default value
+	 *
+	 * See the comment before pll-audio1 definition for the reason.
+	 */
+
+	val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
+	val &= ~BIT(1);
+	val |= BIT(0);
+	writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
+
+	i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
+	if (i)
+		pr_err("%pOF: probing clocks fails: %d\n", node, i);
+}
+
+CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
+	       sun50i_r329_r_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
new file mode 100644
index 000000000000..62cf65322116
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _CCU_SUN50I_R329_R_H
+#define _CCU_SUN50I_R329_R_H
+
+#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
+
+#define CLK_PLL_CPUX		0
+#define CLK_PLL_PERIPH_BASE	1
+#define CLK_PLL_PERIPH_2X	2
+#define CLK_PLL_PERIPH_800M	3
+#define CLK_PLL_PERIPH		4
+#define CLK_PLL_AUDIO0		5
+#define CLK_PLL_AUDIO0_DIV2	6
+#define CLK_PLL_AUDIO0_DIV5	7
+#define CLK_PLL_AUDIO1_4X	8
+#define CLK_PLL_AUDIO1_2X	9
+#define CLK_PLL_AUDIO1		10
+#define CLK_R_AHB		11
+
+/* R_APB1 exported for PIO */
+
+#define CLK_R_APB2		13
+
+/* All module / bus gate clocks exported */
+
+#define CLK_NUMBER	(CLK_R_BUS_RTC + 1)
+
+#endif /* _CCU_SUN50I_R329_R_H */
diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
new file mode 100644
index 000000000000..df9bc58de5c4
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
+
+#define CLK_R_APB1		12
+
+#define CLK_R_BUS_GPADC		14
+#define CLK_R_BUS_THS		15
+#define CLK_R_BUS_DMA		16
+#define CLK_R_PWM		17
+#define CLK_R_BUS_PWM		18
+#define CLK_R_CODEC_ADC		19
+#define CLK_R_CODEC_DAC		20
+#define CLK_R_BUS_CODEC		21
+#define CLK_R_DMIC		22
+#define CLK_R_BUS_DMIC		23
+#define CLK_R_BUS_LRADC		24
+#define CLK_R_I2S		25
+#define CLK_R_I2S_ASRC		26
+#define CLK_R_BUS_I2S		27
+#define CLK_R_BUS_UART		28
+#define CLK_R_BUS_I2C		29
+#define CLK_R_IR		30
+#define CLK_R_BUS_IR		31
+#define CLK_R_BUS_MSGBOX	32
+#define CLK_R_BUS_SPINLOCK	33
+#define CLK_R_BUS_RTC		34
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
new file mode 100644
index 000000000000..40644f2f21c6
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
+
+#define RST_R_BUS_GPADC		0
+#define RST_R_BUS_THS		1
+#define RST_R_BUS_DMA		2
+#define RST_R_BUS_PWM		3
+#define RST_R_BUS_CODEC		4
+#define RST_R_BUS_DMIC		5
+#define RST_R_BUS_LRADC		6
+#define RST_R_BUS_I2S		7
+#define RST_R_BUS_UART		8
+#define RST_R_BUS_I2C		9
+#define RST_R_BUS_IR		10
+#define RST_R_BUS_MSGBOX	11
+#define RST_R_BUS_SPINLOCK	12
+#define RST_R_BUS_RTC		13
+
+#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */
-- 
2.30.2


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

* [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 has clock controls in PRCM, like other new Allwinner
SoCs.

Add support for them.

This driver is added before the main CCU because PLLs are controlled by
R-CCU on R329.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/clk/sunxi-ng/Kconfig                  |   5 +
 drivers/clk/sunxi-ng/Makefile                 |   1 +
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
 include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
 include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
 6 files changed, 470 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index cd46d8853876..e49b2c2fa5b7 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
 	default ARM64 && ARCH_SUNXI
 	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
+config SUN50I_R329_R_CCU
+	bool "Support for the Allwinner R329 PRCM CCU"
+	default ARM64 && ARCH_SUNXI
+	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	bool "Support for the Allwinner A10/A20 CCU"
 	default MACH_SUN4I
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 96c324306d97..db338a2188fd 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
 obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
+obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
 obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
new file mode 100644
index 000000000000..5413a701cb57
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Sipeed
+ * Based on the H616 CCU driver, which is:
+ *   Copyright (c) 2020 Arm Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.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-sun50i-r329-r.h"
+
+/*
+ * The M factor is present in the register's description, but not in the
+ * frequency formula, and it's documented as "The bit is only for
+ * testing", so it's not modelled and then force to 0.
+ */
+#define SUN50I_R329_PLL_CPUX_REG	0x1000
+static struct ccu_mult pll_cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.mult		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.common		= {
+		.reg		= 0x1000,
+		.hw.init	= CLK_HW_INIT("pll-cpux", "osc24M",
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+#define SUN50I_R329_PLL_PERIPH_REG	0x1010
+static struct ccu_nm pll_periph_base_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x1010,
+		.hw.init	= CLK_HW_INIT("pll-periph-base", "osc24M",
+					      &ccu_nm_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-base",
+		   0x1010, 16, 3, 0);
+static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-periph-base",
+		   0x1010, 20, 3, 0);
+static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
+			   &pll_periph_2x_clk.common.hw, 2, 1, 0);
+
+#define SUN50I_R329_PLL_AUDIO0_REG	0x1020
+static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
+	{ .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64 },
+};
+
+static struct ccu_nm pll_audio0_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(1, 1),
+	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table,
+					 BIT(24), 0x1120, BIT(31)),
+	.common		= {
+		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
+		.reg		= 0x1020,
+		.hw.init	= CLK_HW_INIT("pll-audio0", "osc24M",
+					      &ccu_nm_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-audio0",
+		   0x1020, 16, 3, 0);
+static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-audio0",
+		   0x1020, 20, 3, 0);
+
+/*
+ * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
+ * BSP driver always has M0 = 1 and M1 = 2 (this is also the
+ * reset value in the register).
+ *
+ * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
+ */
+#define SUN50I_R329_PLL_AUDIO1_REG	0x1030
+static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
+	{ .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22 },
+	{ .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24 },
+	{ .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
+	{ .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
+};
+static struct ccu_nm pll_audio1_4x_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(16, 6),
+	.fixed_post_div	= 2,
+	.sdm		= _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
+					 BIT(24), 0x1130, BIT(31)),
+	.common		= {
+		.features	= CCU_FEATURE_FIXED_POSTDIV |
+				  CCU_FEATURE_SIGMA_DELTA_MOD,
+		.reg		= 0x1030,
+		.hw.init	= CLK_HW_INIT("pll-audio1-4x", "osc24M",
+					      &ccu_nm_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
+			   &pll_audio1_4x_clk.common.hw, 2, 1,
+			   CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
+			   &pll_audio1_4x_clk.common.hw, 4, 1,
+			   CLK_SET_RATE_PARENT);
+
+static const char * const r_bus_parents[] = { "osc24M", "osc32k", "iosc",
+					      "pll-periph-2x",
+					      "pll-audio0-div2" };
+static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents, 0x000,
+			     0, 5,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents, 0x00c,
+			     0, 5,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents, 0x010,
+			     0, 5,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
+		      0x0ec, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c, BIT(0), 0);
+
+static const char * const r_pwm_parents[] = { "osc24M", "osc32k", "iosc" };
+static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents, 0x130,
+			       24, 3,	/* mux */
+			       BIT(31),	/* gate */
+			       0);
+
+static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c, BIT(0), 0);
+
+static const char * const r_audio_parents[] = { "pll-audio0-div5", "pll-audio0-div2",
+						"pll-audio1-1x", "pll-audio1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc", r_audio_parents, 0x140,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac", r_audio_parents, 0x144,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
+		      0x14c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic", r_audio_parents, 0x150,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
+		      0x16c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s", r_audio_parents, 0x170,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
+				  r_audio_parents, 0x174,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c, BIT(0), 0);
+
+static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents, 0x1c0,
+				  0, 5,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
+		      0x1dc, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-apb1",
+		      0x1ec, BIT(0), 0);
+static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
+		      0x20c, BIT(0), CLK_IS_CRITICAL);
+
+static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
+	&pll_cpux_clk.common,
+	&pll_periph_base_clk.common,
+	&pll_periph_2x_clk.common,
+	&pll_periph_800m_clk.common,
+	&pll_audio0_clk.common,
+	&pll_audio0_div2_clk.common,
+	&pll_audio0_div5_clk.common,
+	&pll_audio1_4x_clk.common,
+	&r_ahb_clk.common,
+	&r_apb1_clk.common,
+	&r_apb2_clk.common,
+	&r_bus_gpadc_clk.common,
+	&r_bus_ths_clk.common,
+	&r_bus_dma_clk.common,
+	&r_pwm_clk.common,
+	&r_bus_pwm_clk.common,
+	&r_codec_adc_clk.common,
+	&r_codec_dac_clk.common,
+	&r_bus_codec_clk.common,
+	&r_dmic_clk.common,
+	&r_bus_dmic_clk.common,
+	&r_bus_lradc_clk.common,
+	&r_i2s_clk.common,
+	&r_i2s_asrc_clk.common,
+	&r_bus_i2s_clk.common,
+	&r_bus_uart_clk.common,
+	&r_bus_i2c_clk.common,
+	&r_ir_clk.common,
+	&r_bus_ir_clk.common,
+	&r_bus_msgbox_clk.common,
+	&r_bus_spinlock_clk.common,
+	&r_bus_rtc_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
+	.hws	= {
+		[CLK_PLL_CPUX]		= &pll_cpux_clk.common.hw,
+		[CLK_PLL_PERIPH_BASE]	= &pll_periph_base_clk.common.hw,
+		[CLK_PLL_PERIPH_2X]	= &pll_periph_2x_clk.common.hw,
+		[CLK_PLL_PERIPH_800M]	= &pll_periph_800m_clk.common.hw,
+		[CLK_PLL_PERIPH]	= &pll_periph_clk.hw,
+		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.common.hw,
+		[CLK_PLL_AUDIO0_DIV2]	= &pll_audio0_div2_clk.common.hw,
+		[CLK_PLL_AUDIO0_DIV5]	= &pll_audio0_div5_clk.common.hw,
+		[CLK_PLL_AUDIO1_4X]	= &pll_audio1_4x_clk.common.hw,
+		[CLK_PLL_AUDIO1_2X]	= &pll_audio1_2x_clk.hw,
+		[CLK_PLL_AUDIO1]	= &pll_audio1_clk.hw,
+		[CLK_R_AHB]		= &r_ahb_clk.common.hw,
+		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
+		[CLK_R_APB2]		= &r_apb2_clk.common.hw,
+		[CLK_R_BUS_GPADC]	= &r_bus_gpadc_clk.common.hw,
+		[CLK_R_BUS_THS]		= &r_bus_ths_clk.common.hw,
+		[CLK_R_BUS_DMA]		= &r_bus_dma_clk.common.hw,
+		[CLK_R_PWM]		= &r_pwm_clk.common.hw,
+		[CLK_R_BUS_PWM]		= &r_bus_pwm_clk.common.hw,
+		[CLK_R_CODEC_ADC]	= &r_codec_adc_clk.common.hw,
+		[CLK_R_CODEC_DAC]	= &r_codec_dac_clk.common.hw,
+		[CLK_R_BUS_CODEC]	= &r_bus_codec_clk.common.hw,
+		[CLK_R_DMIC]		= &r_dmic_clk.common.hw,
+		[CLK_R_BUS_DMIC]	= &r_bus_dmic_clk.common.hw,
+		[CLK_R_BUS_LRADC]	= &r_bus_lradc_clk.common.hw,
+		[CLK_R_I2S]		= &r_i2s_clk.common.hw,
+		[CLK_R_I2S_ASRC]	= &r_i2s_asrc_clk.common.hw,
+		[CLK_R_BUS_I2S]		= &r_bus_i2s_clk.common.hw,
+		[CLK_R_BUS_UART]	= &r_bus_uart_clk.common.hw,
+		[CLK_R_BUS_I2C]		= &r_bus_i2c_clk.common.hw,
+		[CLK_R_IR]		= &r_ir_clk.common.hw,
+		[CLK_R_BUS_IR]		= &r_bus_ir_clk.common.hw,
+		[CLK_R_BUS_MSGBOX]	= &r_bus_msgbox_clk.common.hw,
+		[CLK_R_BUS_SPINLOCK]	= &r_bus_spinlock_clk.common.hw,
+		[CLK_R_BUS_RTC]		= &r_bus_rtc_clk.common.hw,
+	},
+	.num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
+	[RST_R_BUS_GPADC]	= { 0x0ec, BIT(16) },
+	[RST_R_BUS_THS]		= { 0x0fc, BIT(16) },
+	[RST_R_BUS_DMA]		= { 0x10c, BIT(16) },
+	[RST_R_BUS_PWM]		= { 0x13c, BIT(16) },
+	[RST_R_BUS_CODEC]	= { 0x14c, BIT(16) },
+	[RST_R_BUS_DMIC]	= { 0x15c, BIT(16) },
+	[RST_R_BUS_LRADC]	= { 0x16c, BIT(16) },
+	[RST_R_BUS_I2S]		= { 0x17c, BIT(16) },
+	[RST_R_BUS_UART]	= { 0x18c, BIT(16) },
+	[RST_R_BUS_I2C]		= { 0x19c, BIT(16) },
+	[RST_R_BUS_IR]		= { 0x1cc, BIT(16) },
+	[RST_R_BUS_MSGBOX]	= { 0x1dc, BIT(16) },
+	[RST_R_BUS_SPINLOCK]	= { 0x1ec, BIT(16) },
+	[RST_R_BUS_RTC]		= { 0x20c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
+	.ccu_clks	= sun50i_r329_r_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_r_ccu_clks),
+
+	.hw_clks	= &sun50i_r329_r_hw_clks,
+
+	.resets		= sun50i_r329_r_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_r329_r_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+	SUN50I_R329_PLL_CPUX_REG,
+	SUN50I_R329_PLL_PERIPH_REG,
+	SUN50I_R329_PLL_AUDIO0_REG,
+	SUN50I_R329_PLL_AUDIO1_REG,
+};
+
+static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
+{
+	void __iomem *reg;
+	u32 val;
+	int i;
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		pr_err("%pOF: Could not map clock registers\n", node);
+		return;
+	}
+
+	/* Enable the lock bits and the output enable bits on all PLLs */
+	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+		val = readl(reg + pll_regs[i]);
+		val |= BIT(29) | BIT(27);
+		writel(val, reg + pll_regs[i]);
+	}
+
+	/*
+	 * Force the I/O dividers of PLL-AUDIO1 to reset default value
+	 *
+	 * See the comment before pll-audio1 definition for the reason.
+	 */
+
+	val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
+	val &= ~BIT(1);
+	val |= BIT(0);
+	writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
+
+	i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
+	if (i)
+		pr_err("%pOF: probing clocks fails: %d\n", node, i);
+}
+
+CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
+	       sun50i_r329_r_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
new file mode 100644
index 000000000000..62cf65322116
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _CCU_SUN50I_R329_R_H
+#define _CCU_SUN50I_R329_R_H
+
+#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
+
+#define CLK_PLL_CPUX		0
+#define CLK_PLL_PERIPH_BASE	1
+#define CLK_PLL_PERIPH_2X	2
+#define CLK_PLL_PERIPH_800M	3
+#define CLK_PLL_PERIPH		4
+#define CLK_PLL_AUDIO0		5
+#define CLK_PLL_AUDIO0_DIV2	6
+#define CLK_PLL_AUDIO0_DIV5	7
+#define CLK_PLL_AUDIO1_4X	8
+#define CLK_PLL_AUDIO1_2X	9
+#define CLK_PLL_AUDIO1		10
+#define CLK_R_AHB		11
+
+/* R_APB1 exported for PIO */
+
+#define CLK_R_APB2		13
+
+/* All module / bus gate clocks exported */
+
+#define CLK_NUMBER	(CLK_R_BUS_RTC + 1)
+
+#endif /* _CCU_SUN50I_R329_R_H */
diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
new file mode 100644
index 000000000000..df9bc58de5c4
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
+
+#define CLK_R_APB1		12
+
+#define CLK_R_BUS_GPADC		14
+#define CLK_R_BUS_THS		15
+#define CLK_R_BUS_DMA		16
+#define CLK_R_PWM		17
+#define CLK_R_BUS_PWM		18
+#define CLK_R_CODEC_ADC		19
+#define CLK_R_CODEC_DAC		20
+#define CLK_R_BUS_CODEC		21
+#define CLK_R_DMIC		22
+#define CLK_R_BUS_DMIC		23
+#define CLK_R_BUS_LRADC		24
+#define CLK_R_I2S		25
+#define CLK_R_I2S_ASRC		26
+#define CLK_R_BUS_I2S		27
+#define CLK_R_BUS_UART		28
+#define CLK_R_BUS_I2C		29
+#define CLK_R_IR		30
+#define CLK_R_BUS_IR		31
+#define CLK_R_BUS_MSGBOX	32
+#define CLK_R_BUS_SPINLOCK	33
+#define CLK_R_BUS_RTC		34
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
new file mode 100644
index 000000000000..40644f2f21c6
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
+
+#define RST_R_BUS_GPADC		0
+#define RST_R_BUS_THS		1
+#define RST_R_BUS_DMA		2
+#define RST_R_BUS_PWM		3
+#define RST_R_BUS_CODEC		4
+#define RST_R_BUS_DMIC		5
+#define RST_R_BUS_LRADC		6
+#define RST_R_BUS_I2S		7
+#define RST_R_BUS_UART		8
+#define RST_R_BUS_I2C		9
+#define RST_R_BUS_IR		10
+#define RST_R_BUS_MSGBOX	11
+#define RST_R_BUS_SPINLOCK	12
+#define RST_R_BUS_RTC		13
+
+#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 has a CCU that is similar to the H616 one, but it's cut
down and have PLLs moved out.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/clk/sunxi-ng/Kconfig                |   5 +
 drivers/clk/sunxi-ng/Makefile               |   1 +
 drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526 ++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
 include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
 include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++
 6 files changed, 682 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index e49b2c2fa5b7..4b32d5f81ea8 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
 	default ARM64 && ARCH_SUNXI
 	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
+config SUN50I_R329_CCU
+	bool "Support for the Allwinner R329 CCU"
+	default ARM64 && ARCH_SUNXI
+	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
 config SUN50I_R329_R_CCU
 	bool "Support for the Allwinner R329 PRCM CCU"
 	default ARM64 && ARCH_SUNXI
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index db338a2188fd..62f3c5bf331c 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
 obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
+obj-$(CONFIG_SUN50I_R329_CCU)	+= ccu-sun50i-r329.o
 obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
 obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
new file mode 100644
index 000000000000..a0b4cfd6e1db
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
@@ -0,0 +1,526 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Based on the H616 CCU driver, which is:
+ *   Copyright (c) 2020 Arm Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.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-sun50i-r329.h"
+
+/*
+ * An external divider of PLL-CPUX is controlled here. As it's similar to
+ * the external divider of PLL-CPUX on previous SoCs (only usable under
+ * 288MHz}, ignore it.
+ */
+static const char * const cpux_parents[] = { "osc24M", "osc32k", "iosc",
+					     "pll-cpux", "pll-periph",
+					     "pll-periph-2x",
+					     "pll=periph-800m" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+		     0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
+
+static const char * const ahb_parents[] = { "osc24M", "osc32k",
+					    "iosc", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX(ahb_clk, "ahb",
+			     ahb_parents, 0x510,
+			     0, 2,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static const char * const apb_parents[] = { "osc24M", "osc32k",
+					    "ahb", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb_parents, 0x520,
+			     0, 2,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb_parents, 0x524,
+			     0, 2,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static const char * const ce_parents[] = { "osc24M", "pll-periph-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 1,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb",
+		      0x68c, BIT(0), 0);
+
+static const char * const aipu_parents[] = { "pll-periph-2x", "pll-periph-800m",
+					     "pll-audio0-div2", "pll-audio0-div5",
+					     "pll-cpux" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(aipu_clk, "aipu", aipu_parents, 0x6f0,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_aipu_clk, "bus-aipu", "ahb",
+		      0x6fc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
+		      0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb",
+		      0x71c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb",
+		      0x72c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb",
+		      0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb",
+		      0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
+
+static const char * const dram_parents[] = { "pll-periph-2x",
+					     "pll-periph-800m",
+					     "pll-audio0-div2",
+					     "pll-audio0-div5" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
+				  0, 2,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  CLK_IS_CRITICAL);
+
+
+static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "dram",
+		      0x804, BIT(0), 0);
+static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "dram",
+		      0x804, BIT(2), 0);
+static SUNXI_CCU_GATE(mbus_r_dma_clk, "mbus-r-dma", "dram",
+		      0x804, BIT(3), 0);
+static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "dram",
+		      0x804, BIT(5), 0);
+static SUNXI_CCU_GATE(mbus_aipu_clk, "mbus-aipu", "dram",
+		      0x804, BIT(16), 0);
+
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
+		      0x80c, BIT(0), CLK_IS_CRITICAL);
+
+static const char * const nand_parents[] = { "osc24M", "pll-periph",
+					     "pll-audio-div2",
+					     "pll-periph-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_parents, 0x810,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_parents, 0x814,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb", 0x82c, BIT(0), 0);
+
+static const char * const mmc_parents[] = { "osc24M", "pll-periph",
+					    "pll-periph-2x",
+					    "pll-audio0-div2" };
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
+					  0, 4,		/* M */
+					  8, 2,		/* P */
+					  24, 2,	/* mux */
+					  BIT(31),	/* gate */
+					  2,		/* post-div */
+					  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
+					  0, 4,		/* M */
+					  8, 2,		/* P */
+					  24, 2,	/* mux */
+					  BIT(31),	/* gate */
+					  2,		/* post-div */
+					  0);
+
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 0x84c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 0x93c, BIT(0), 0);
+
+static const char * const spi_parents[] = { "osc24M", "pll-periph",
+					    "pll-periph-2x",
+					    "pll-audio0-div2",
+					    "pll-audio0-div5" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 0x96c, BIT(1), 0);
+
+static CLK_FIXED_FACTOR(emac_25m_div_clk, "emac-25m-div", "pll-periph",
+			2, 1, 0);
+static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "emac-25m-div", 0x970,
+		      BIT(31) | BIT(30), 0);
+
+static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb", 0x97c, BIT(0), 0);
+
+static const char * const ir_parents[] = { "osc32k", "iosc",
+					   "pll-periph", "pll-audio0-div2" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "apb1", 0x99c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
+
+static const char * const audio_parents[] = { "pll-audio1",
+					      "pll-audio1-4x",
+					      "pll-audio0-div2",
+					      "pll-audio0-div5" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_clk, "spdif", audio_parents, 0xa20,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
+ * We will force them to 0 (12M divided from 48M).
+ */
+#define SUN50I_R329_USB0_CLK_REG		0xa70
+#define SUN50I_R329_USB1_CLK_REG		0xa74
+
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb", 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb", 0xa8c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb", 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 0xa8c, BIT(8), 0);
+
+static const char * const ledc_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents, 0xbf0,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 1,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "apb1", 0xbfc, BIT(0), 0);
+
+/* Fixed factor clocks */
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+
+static struct ccu_common *sun50i_r329_ccu_clks[] = {
+	&cpux_clk.common,
+	&axi_clk.common,
+	&cpux_apb_clk.common,
+	&ahb_clk.common,
+	&apb1_clk.common,
+	&apb2_clk.common,
+	&ce_clk.common,
+	&bus_ce_clk.common,
+	&aipu_clk.common,
+	&bus_aipu_clk.common,
+	&bus_dma_clk.common,
+	&bus_msgbox_clk.common,
+	&bus_spinlock_clk.common,
+	&bus_hstimer_clk.common,
+	&avs_clk.common,
+	&bus_dbg_clk.common,
+	&bus_pwm_clk.common,
+	&dram_clk.common,
+	&mbus_dma_clk.common,
+	&mbus_ce_clk.common,
+	&mbus_r_dma_clk.common,
+	&mbus_nand_clk.common,
+	&mbus_aipu_clk.common,
+	&bus_dram_clk.common,
+	&nand0_clk.common,
+	&nand1_clk.common,
+	&bus_nand_clk.common,
+	&mmc0_clk.common,
+	&mmc1_clk.common,
+	&bus_mmc0_clk.common,
+	&bus_mmc1_clk.common,
+	&bus_uart0_clk.common,
+	&bus_uart1_clk.common,
+	&bus_uart2_clk.common,
+	&bus_uart3_clk.common,
+	&bus_i2c0_clk.common,
+	&bus_i2c1_clk.common,
+	&bus_scr_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&bus_spi0_clk.common,
+	&bus_spi1_clk.common,
+	&emac_25m_clk.common,
+	&bus_emac_clk.common,
+	&ir_rx_clk.common,
+	&bus_ir_rx_clk.common,
+	&ir_tx_clk.common,
+	&bus_ir_tx_clk.common,
+	&i2s0_clk.common,
+	&i2s1_clk.common,
+	&bus_i2s0_clk.common,
+	&bus_i2s1_clk.common,
+	&spdif_clk.common,
+	&bus_spdif_clk.common,
+	&usb_ohci0_clk.common,
+	&usb_phy0_clk.common,
+	&usb_ohci1_clk.common,
+	&usb_phy1_clk.common,
+	&bus_ohci0_clk.common,
+	&bus_ohci1_clk.common,
+	&bus_ehci0_clk.common,
+	&bus_otg_clk.common,
+	&ledc_clk.common,
+	&bus_ledc_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_r329_hw_clks = {
+	.hws	= {
+		[CLK_OSC12M]		= &osc12M_clk.hw,
+		[CLK_CPUX]		= &cpux_clk.common.hw,
+		[CLK_AXI]		= &axi_clk.common.hw,
+		[CLK_CPUX_APB]		= &cpux_apb_clk.common.hw,
+		[CLK_AHB]		= &ahb_clk.common.hw,
+		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_APB2]		= &apb2_clk.common.hw,
+		[CLK_CE]		= &ce_clk.common.hw,
+		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
+		[CLK_AIPU]		= &aipu_clk.common.hw,
+		[CLK_BUS_AIPU]		= &bus_aipu_clk.common.hw,
+		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
+		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
+		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
+		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
+		[CLK_AVS]		= &avs_clk.common.hw,
+		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
+		[CLK_BUS_PWM]		= &bus_pwm_clk.common.hw,
+		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
+		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
+		[CLK_MBUS_R_DMA]	= &mbus_r_dma_clk.common.hw,
+		[CLK_MBUS_NAND]		= &mbus_nand_clk.common.hw,
+		[CLK_MBUS_AIPU]		= &mbus_aipu_clk.common.hw,
+		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
+		[CLK_NAND0]		= &nand0_clk.common.hw,
+		[CLK_NAND1]		= &nand1_clk.common.hw,
+		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
+		[CLK_MMC0]		= &mmc0_clk.common.hw,
+		[CLK_MMC1]		= &mmc1_clk.common.hw,
+		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
+		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
+		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
+		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
+		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
+		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
+		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
+		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
+		[CLK_BUS_SCR]		= &bus_scr_clk.common.hw,
+		[CLK_SPI0]		= &spi0_clk.common.hw,
+		[CLK_SPI1]		= &spi1_clk.common.hw,
+		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
+		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
+		[CLK_EMAC_25M_DIV]	= &emac_25m_div_clk.hw,
+		[CLK_EMAC_25M]		= &emac_25m_clk.common.hw,
+		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
+		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
+		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
+		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
+		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
+		[CLK_I2S0]		= &i2s0_clk.common.hw,
+		[CLK_I2S1]		= &i2s1_clk.common.hw,
+		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
+		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
+		[CLK_SPDIF]		= &spdif_clk.common.hw,
+		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
+		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
+		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
+		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
+		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
+		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
+		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
+		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
+		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
+		[CLK_LEDC]		= &ledc_clk.common.hw,
+		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
+	},
+	.num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_r329_ccu_resets[] = {
+	[RST_MBUS]		= { 0x540, BIT(30) },
+
+	[RST_BUS_CE]		= { 0x68c, BIT(16) },
+	[RST_BUS_AIPU]		= { 0x6fc, BIT(16) },
+	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
+	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
+	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
+	[RST_BUS_HSTIMER]	= { 0x73c, BIT(16) },
+	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
+	[RST_BUS_PWM]		= { 0x7ac, BIT(16) },
+	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
+	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
+	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
+	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
+	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
+	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
+	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
+	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
+	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
+	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
+	[RST_BUS_SCR]		= { 0x93c, BIT(16) },
+	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
+	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
+	[RST_BUS_EMAC]		= { 0x97c, BIT(16) },
+	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
+	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
+	[RST_BUS_I2S0]		= { 0xa1c, BIT(16) },
+	[RST_BUS_I2S1]		= { 0xa1c, BIT(17) },
+	[RST_BUS_SPDIF]		= { 0xa2c, BIT(16) },
+
+	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
+	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
+
+	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
+	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
+	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
+	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
+
+	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_r329_ccu_desc = {
+	.ccu_clks	= sun50i_r329_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_ccu_clks),
+
+	.hw_clks	= &sun50i_r329_hw_clks,
+
+	.resets		= sun50i_r329_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_r329_ccu_resets),
+};
+
+static const u32 sun50i_r329_usb_clk_regs[] = {
+	SUN50I_R329_USB0_CLK_REG,
+	SUN50I_R329_USB1_CLK_REG,
+};
+
+static int sun50i_r329_ccu_probe(struct platform_device *pdev)
+{
+	void __iomem *reg;
+	u32 val;
+	int i;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/*
+	 * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
+	 *
+	 * This clock mux is still mysterious, and the code just enforces
+	 * it to have a valid clock parent.
+	 */
+	for (i = 0; i < ARRAY_SIZE(sun50i_r329_usb_clk_regs); i++) {
+		val = readl(reg + sun50i_r329_usb_clk_regs[i]);
+		val &= ~GENMASK(25, 24);
+		writel(val, reg + sun50i_r329_usb_clk_regs[i]);
+	}
+
+	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_r329_ccu_desc);
+}
+
+static const struct of_device_id sun50i_r329_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-r329-ccu" },
+	{ }
+};
+
+static struct platform_driver sun50i_r329_ccu_driver = {
+	.probe	= sun50i_r329_ccu_probe,
+	.driver	= {
+		.name	= "sun50i-r329-ccu",
+		.of_match_table	= sun50i_r329_ccu_ids,
+	},
+};
+module_platform_driver(sun50i_r329_ccu_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
new file mode 100644
index 000000000000..144ac9954ef3
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _CCU_SUN50I_R329_H_
+#define _CCU_SUN50I_R329_H_
+
+#include <dt-bindings/clock/sun50i-r329-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-ccu.h>
+
+#define CLK_OSC12M		0
+
+/* CPUX exported for DVFS */
+
+#define CLK_AXI			2
+#define CLK_CPUX_APB		3
+#define CLK_AHB			4
+
+/* APB1 exported for PIO */
+
+#define CLK_APB2		6
+
+/* Peripheral module and gate clock exported except for DRAM ones */
+
+#define CLK_DRAM		18
+
+#define CLK_BUS_DRAM		24
+
+#define CLK_NUMBER		(CLK_BUS_LEDC + 1)
+
+#endif /* _CCU_SUN50I_R329_H_ */
diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h b/include/dt-bindings/clock/sun50i-r329-ccu.h
new file mode 100644
index 000000000000..116f8d13a9b3
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
+
+#define CLK_CPUX		1
+
+#define CLK_APB1		5
+
+#define CLK_CE			7
+#define CLK_BUS_CE		8
+#define CLK_AIPU		9
+#define CLK_BUS_AIPU		10
+#define CLK_BUS_DMA		11
+#define CLK_BUS_MSGBOX		12
+#define CLK_BUS_SPINLOCK	13
+#define CLK_BUS_HSTIMER		14
+#define CLK_AVS			15
+#define CLK_BUS_DBG		16
+#define CLK_BUS_PWM		17
+
+#define CLK_MBUS_DMA		19
+#define CLK_MBUS_CE		20
+#define CLK_MBUS_R_DMA		21
+#define CLK_MBUS_NAND		22
+#define CLK_MBUS_AIPU		23
+
+#define CLK_NAND0		25
+#define CLK_NAND1		26
+#define CLK_BUS_NAND		27
+#define CLK_MMC0		28
+#define CLK_MMC1		29
+#define CLK_BUS_MMC0		30
+#define CLK_BUS_MMC1		31
+#define CLK_BUS_UART0		32
+#define CLK_BUS_UART1		33
+#define CLK_BUS_UART2		34
+#define CLK_BUS_UART3		35
+#define CLK_BUS_I2C0		36
+#define CLK_BUS_I2C1		37
+#define CLK_BUS_SCR		38
+#define CLK_SPI0		39
+#define CLK_SPI1		40
+#define CLK_BUS_SPI0		41
+#define CLK_BUS_SPI1		42
+#define CLK_EMAC_25M_DIV	43
+#define CLK_EMAC_25M		44
+#define CLK_BUS_EMAC		45
+#define CLK_IR_RX		46
+#define CLK_BUS_IR_RX		47
+#define CLK_IR_TX		48
+#define CLK_BUS_IR_TX		49
+#define CLK_I2S0		50
+#define CLK_I2S1		51
+#define CLK_BUS_I2S0		52
+#define CLK_BUS_I2S1		53
+#define CLK_SPDIF		54
+#define CLK_BUS_SPDIF		55
+#define CLK_USB_OHCI0		56
+#define CLK_USB_PHY0		57
+#define CLK_USB_OHCI1		58
+#define CLK_USB_PHY1		59
+#define CLK_BUS_OHCI0		60
+#define CLK_BUS_OHCI1		61
+#define CLK_BUS_EHCI0		62
+#define CLK_BUS_OTG		63
+#define CLK_LEDC		64
+#define CLK_BUS_LEDC		65
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h b/include/dt-bindings/reset/sun50i-r329-ccu.h
new file mode 100644
index 000000000000..bb704a82443f
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
+
+#define RST_MBUS		0
+#define RST_BUS_CE		1
+#define RST_BUS_AIPU		2
+#define RST_BUS_DMA		3
+#define RST_BUS_MSGBOX		4
+#define RST_BUS_SPINLOCK	5
+#define RST_BUS_HSTIMER		6
+#define RST_BUS_DBG		7
+#define RST_BUS_PWM		8
+#define RST_BUS_DRAM		9
+#define RST_BUS_NAND		10
+#define RST_BUS_MMC0		11
+#define RST_BUS_MMC1		12
+#define RST_BUS_UART0		13
+#define RST_BUS_UART1		14
+#define RST_BUS_UART2		15
+#define RST_BUS_UART3		16
+#define RST_BUS_I2C0		17
+#define RST_BUS_I2C1		18
+#define RST_BUS_SCR		19
+#define RST_BUS_SPI0		20
+#define RST_BUS_SPI1		21
+#define RST_BUS_EMAC		22
+#define RST_BUS_IR_RX		23
+#define RST_BUS_IR_TX		24
+#define RST_BUS_I2S0		25
+#define RST_BUS_I2S1		26
+#define RST_BUS_SPDIF		27
+#define RST_USB_PHY0		28
+#define RST_USB_PHY1		29
+#define RST_BUS_OHCI0		30
+#define RST_BUS_OHCI1		31
+#define RST_BUS_EHCI0		32
+#define RST_BUS_OTG		33
+#define RST_BUS_LEDC		34
+
+#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
-- 
2.30.2


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

* [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 has a CCU that is similar to the H616 one, but it's cut
down and have PLLs moved out.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/clk/sunxi-ng/Kconfig                |   5 +
 drivers/clk/sunxi-ng/Makefile               |   1 +
 drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526 ++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
 include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
 include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++
 6 files changed, 682 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index e49b2c2fa5b7..4b32d5f81ea8 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
 	default ARM64 && ARCH_SUNXI
 	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
+config SUN50I_R329_CCU
+	bool "Support for the Allwinner R329 CCU"
+	default ARM64 && ARCH_SUNXI
+	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
 config SUN50I_R329_R_CCU
 	bool "Support for the Allwinner R329 PRCM CCU"
 	default ARM64 && ARCH_SUNXI
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index db338a2188fd..62f3c5bf331c 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
 obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
+obj-$(CONFIG_SUN50I_R329_CCU)	+= ccu-sun50i-r329.o
 obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
 obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
new file mode 100644
index 000000000000..a0b4cfd6e1db
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
@@ -0,0 +1,526 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Based on the H616 CCU driver, which is:
+ *   Copyright (c) 2020 Arm Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.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-sun50i-r329.h"
+
+/*
+ * An external divider of PLL-CPUX is controlled here. As it's similar to
+ * the external divider of PLL-CPUX on previous SoCs (only usable under
+ * 288MHz}, ignore it.
+ */
+static const char * const cpux_parents[] = { "osc24M", "osc32k", "iosc",
+					     "pll-cpux", "pll-periph",
+					     "pll-periph-2x",
+					     "pll=periph-800m" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+		     0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
+
+static const char * const ahb_parents[] = { "osc24M", "osc32k",
+					    "iosc", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX(ahb_clk, "ahb",
+			     ahb_parents, 0x510,
+			     0, 2,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static const char * const apb_parents[] = { "osc24M", "osc32k",
+					    "ahb", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb_parents, 0x520,
+			     0, 2,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb_parents, 0x524,
+			     0, 2,	/* M */
+			     8, 2,	/* P */
+			     24, 3,	/* mux */
+			     0);
+
+static const char * const ce_parents[] = { "osc24M", "pll-periph-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 1,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb",
+		      0x68c, BIT(0), 0);
+
+static const char * const aipu_parents[] = { "pll-periph-2x", "pll-periph-800m",
+					     "pll-audio0-div2", "pll-audio0-div5",
+					     "pll-cpux" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(aipu_clk, "aipu", aipu_parents, 0x6f0,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_aipu_clk, "bus-aipu", "ahb",
+		      0x6fc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
+		      0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb",
+		      0x71c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb",
+		      0x72c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb",
+		      0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb",
+		      0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
+
+static const char * const dram_parents[] = { "pll-periph-2x",
+					     "pll-periph-800m",
+					     "pll-audio0-div2",
+					     "pll-audio0-div5" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
+				  0, 2,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  CLK_IS_CRITICAL);
+
+
+static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "dram",
+		      0x804, BIT(0), 0);
+static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "dram",
+		      0x804, BIT(2), 0);
+static SUNXI_CCU_GATE(mbus_r_dma_clk, "mbus-r-dma", "dram",
+		      0x804, BIT(3), 0);
+static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "dram",
+		      0x804, BIT(5), 0);
+static SUNXI_CCU_GATE(mbus_aipu_clk, "mbus-aipu", "dram",
+		      0x804, BIT(16), 0);
+
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
+		      0x80c, BIT(0), CLK_IS_CRITICAL);
+
+static const char * const nand_parents[] = { "osc24M", "pll-periph",
+					     "pll-audio-div2",
+					     "pll-periph-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_parents, 0x810,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_parents, 0x814,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb", 0x82c, BIT(0), 0);
+
+static const char * const mmc_parents[] = { "osc24M", "pll-periph",
+					    "pll-periph-2x",
+					    "pll-audio0-div2" };
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
+					  0, 4,		/* M */
+					  8, 2,		/* P */
+					  24, 2,	/* mux */
+					  BIT(31),	/* gate */
+					  2,		/* post-div */
+					  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
+					  0, 4,		/* M */
+					  8, 2,		/* P */
+					  24, 2,	/* mux */
+					  BIT(31),	/* gate */
+					  2,		/* post-div */
+					  0);
+
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 0x84c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 0x93c, BIT(0), 0);
+
+static const char * const spi_parents[] = { "osc24M", "pll-periph",
+					    "pll-periph-2x",
+					    "pll-audio0-div2",
+					    "pll-audio0-div5" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 0x96c, BIT(1), 0);
+
+static CLK_FIXED_FACTOR(emac_25m_div_clk, "emac-25m-div", "pll-periph",
+			2, 1, 0);
+static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "emac-25m-div", 0x970,
+		      BIT(31) | BIT(30), 0);
+
+static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb", 0x97c, BIT(0), 0);
+
+static const char * const ir_parents[] = { "osc32k", "iosc",
+					   "pll-periph", "pll-audio0-div2" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "apb1", 0x99c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
+
+static const char * const audio_parents[] = { "pll-audio1",
+					      "pll-audio1-4x",
+					      "pll-audio0-div2",
+					      "pll-audio0-div5" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_clk, "spdif", audio_parents, 0xa20,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
+ * We will force them to 0 (12M divided from 48M).
+ */
+#define SUN50I_R329_USB0_CLK_REG		0xa70
+#define SUN50I_R329_USB1_CLK_REG		0xa74
+
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb", 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb", 0xa8c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb", 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 0xa8c, BIT(8), 0);
+
+static const char * const ledc_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents, 0xbf0,
+				  0, 4,		/* M */
+				  8, 2,		/* P */
+				  24, 1,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "apb1", 0xbfc, BIT(0), 0);
+
+/* Fixed factor clocks */
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+
+static struct ccu_common *sun50i_r329_ccu_clks[] = {
+	&cpux_clk.common,
+	&axi_clk.common,
+	&cpux_apb_clk.common,
+	&ahb_clk.common,
+	&apb1_clk.common,
+	&apb2_clk.common,
+	&ce_clk.common,
+	&bus_ce_clk.common,
+	&aipu_clk.common,
+	&bus_aipu_clk.common,
+	&bus_dma_clk.common,
+	&bus_msgbox_clk.common,
+	&bus_spinlock_clk.common,
+	&bus_hstimer_clk.common,
+	&avs_clk.common,
+	&bus_dbg_clk.common,
+	&bus_pwm_clk.common,
+	&dram_clk.common,
+	&mbus_dma_clk.common,
+	&mbus_ce_clk.common,
+	&mbus_r_dma_clk.common,
+	&mbus_nand_clk.common,
+	&mbus_aipu_clk.common,
+	&bus_dram_clk.common,
+	&nand0_clk.common,
+	&nand1_clk.common,
+	&bus_nand_clk.common,
+	&mmc0_clk.common,
+	&mmc1_clk.common,
+	&bus_mmc0_clk.common,
+	&bus_mmc1_clk.common,
+	&bus_uart0_clk.common,
+	&bus_uart1_clk.common,
+	&bus_uart2_clk.common,
+	&bus_uart3_clk.common,
+	&bus_i2c0_clk.common,
+	&bus_i2c1_clk.common,
+	&bus_scr_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&bus_spi0_clk.common,
+	&bus_spi1_clk.common,
+	&emac_25m_clk.common,
+	&bus_emac_clk.common,
+	&ir_rx_clk.common,
+	&bus_ir_rx_clk.common,
+	&ir_tx_clk.common,
+	&bus_ir_tx_clk.common,
+	&i2s0_clk.common,
+	&i2s1_clk.common,
+	&bus_i2s0_clk.common,
+	&bus_i2s1_clk.common,
+	&spdif_clk.common,
+	&bus_spdif_clk.common,
+	&usb_ohci0_clk.common,
+	&usb_phy0_clk.common,
+	&usb_ohci1_clk.common,
+	&usb_phy1_clk.common,
+	&bus_ohci0_clk.common,
+	&bus_ohci1_clk.common,
+	&bus_ehci0_clk.common,
+	&bus_otg_clk.common,
+	&ledc_clk.common,
+	&bus_ledc_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_r329_hw_clks = {
+	.hws	= {
+		[CLK_OSC12M]		= &osc12M_clk.hw,
+		[CLK_CPUX]		= &cpux_clk.common.hw,
+		[CLK_AXI]		= &axi_clk.common.hw,
+		[CLK_CPUX_APB]		= &cpux_apb_clk.common.hw,
+		[CLK_AHB]		= &ahb_clk.common.hw,
+		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_APB2]		= &apb2_clk.common.hw,
+		[CLK_CE]		= &ce_clk.common.hw,
+		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
+		[CLK_AIPU]		= &aipu_clk.common.hw,
+		[CLK_BUS_AIPU]		= &bus_aipu_clk.common.hw,
+		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
+		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
+		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
+		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
+		[CLK_AVS]		= &avs_clk.common.hw,
+		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
+		[CLK_BUS_PWM]		= &bus_pwm_clk.common.hw,
+		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
+		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
+		[CLK_MBUS_R_DMA]	= &mbus_r_dma_clk.common.hw,
+		[CLK_MBUS_NAND]		= &mbus_nand_clk.common.hw,
+		[CLK_MBUS_AIPU]		= &mbus_aipu_clk.common.hw,
+		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
+		[CLK_NAND0]		= &nand0_clk.common.hw,
+		[CLK_NAND1]		= &nand1_clk.common.hw,
+		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
+		[CLK_MMC0]		= &mmc0_clk.common.hw,
+		[CLK_MMC1]		= &mmc1_clk.common.hw,
+		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
+		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
+		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
+		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
+		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
+		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
+		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
+		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
+		[CLK_BUS_SCR]		= &bus_scr_clk.common.hw,
+		[CLK_SPI0]		= &spi0_clk.common.hw,
+		[CLK_SPI1]		= &spi1_clk.common.hw,
+		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
+		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
+		[CLK_EMAC_25M_DIV]	= &emac_25m_div_clk.hw,
+		[CLK_EMAC_25M]		= &emac_25m_clk.common.hw,
+		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
+		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
+		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
+		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
+		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
+		[CLK_I2S0]		= &i2s0_clk.common.hw,
+		[CLK_I2S1]		= &i2s1_clk.common.hw,
+		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
+		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
+		[CLK_SPDIF]		= &spdif_clk.common.hw,
+		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
+		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
+		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
+		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
+		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
+		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
+		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
+		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
+		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
+		[CLK_LEDC]		= &ledc_clk.common.hw,
+		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
+	},
+	.num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_r329_ccu_resets[] = {
+	[RST_MBUS]		= { 0x540, BIT(30) },
+
+	[RST_BUS_CE]		= { 0x68c, BIT(16) },
+	[RST_BUS_AIPU]		= { 0x6fc, BIT(16) },
+	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
+	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
+	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
+	[RST_BUS_HSTIMER]	= { 0x73c, BIT(16) },
+	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
+	[RST_BUS_PWM]		= { 0x7ac, BIT(16) },
+	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
+	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
+	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
+	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
+	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
+	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
+	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
+	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
+	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
+	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
+	[RST_BUS_SCR]		= { 0x93c, BIT(16) },
+	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
+	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
+	[RST_BUS_EMAC]		= { 0x97c, BIT(16) },
+	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
+	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
+	[RST_BUS_I2S0]		= { 0xa1c, BIT(16) },
+	[RST_BUS_I2S1]		= { 0xa1c, BIT(17) },
+	[RST_BUS_SPDIF]		= { 0xa2c, BIT(16) },
+
+	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
+	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
+
+	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
+	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
+	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
+	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
+
+	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_r329_ccu_desc = {
+	.ccu_clks	= sun50i_r329_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_ccu_clks),
+
+	.hw_clks	= &sun50i_r329_hw_clks,
+
+	.resets		= sun50i_r329_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_r329_ccu_resets),
+};
+
+static const u32 sun50i_r329_usb_clk_regs[] = {
+	SUN50I_R329_USB0_CLK_REG,
+	SUN50I_R329_USB1_CLK_REG,
+};
+
+static int sun50i_r329_ccu_probe(struct platform_device *pdev)
+{
+	void __iomem *reg;
+	u32 val;
+	int i;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/*
+	 * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
+	 *
+	 * This clock mux is still mysterious, and the code just enforces
+	 * it to have a valid clock parent.
+	 */
+	for (i = 0; i < ARRAY_SIZE(sun50i_r329_usb_clk_regs); i++) {
+		val = readl(reg + sun50i_r329_usb_clk_regs[i]);
+		val &= ~GENMASK(25, 24);
+		writel(val, reg + sun50i_r329_usb_clk_regs[i]);
+	}
+
+	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_r329_ccu_desc);
+}
+
+static const struct of_device_id sun50i_r329_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-r329-ccu" },
+	{ }
+};
+
+static struct platform_driver sun50i_r329_ccu_driver = {
+	.probe	= sun50i_r329_ccu_probe,
+	.driver	= {
+		.name	= "sun50i-r329-ccu",
+		.of_match_table	= sun50i_r329_ccu_ids,
+	},
+};
+module_platform_driver(sun50i_r329_ccu_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
new file mode 100644
index 000000000000..144ac9954ef3
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _CCU_SUN50I_R329_H_
+#define _CCU_SUN50I_R329_H_
+
+#include <dt-bindings/clock/sun50i-r329-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-ccu.h>
+
+#define CLK_OSC12M		0
+
+/* CPUX exported for DVFS */
+
+#define CLK_AXI			2
+#define CLK_CPUX_APB		3
+#define CLK_AHB			4
+
+/* APB1 exported for PIO */
+
+#define CLK_APB2		6
+
+/* Peripheral module and gate clock exported except for DRAM ones */
+
+#define CLK_DRAM		18
+
+#define CLK_BUS_DRAM		24
+
+#define CLK_NUMBER		(CLK_BUS_LEDC + 1)
+
+#endif /* _CCU_SUN50I_R329_H_ */
diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h b/include/dt-bindings/clock/sun50i-r329-ccu.h
new file mode 100644
index 000000000000..116f8d13a9b3
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
+
+#define CLK_CPUX		1
+
+#define CLK_APB1		5
+
+#define CLK_CE			7
+#define CLK_BUS_CE		8
+#define CLK_AIPU		9
+#define CLK_BUS_AIPU		10
+#define CLK_BUS_DMA		11
+#define CLK_BUS_MSGBOX		12
+#define CLK_BUS_SPINLOCK	13
+#define CLK_BUS_HSTIMER		14
+#define CLK_AVS			15
+#define CLK_BUS_DBG		16
+#define CLK_BUS_PWM		17
+
+#define CLK_MBUS_DMA		19
+#define CLK_MBUS_CE		20
+#define CLK_MBUS_R_DMA		21
+#define CLK_MBUS_NAND		22
+#define CLK_MBUS_AIPU		23
+
+#define CLK_NAND0		25
+#define CLK_NAND1		26
+#define CLK_BUS_NAND		27
+#define CLK_MMC0		28
+#define CLK_MMC1		29
+#define CLK_BUS_MMC0		30
+#define CLK_BUS_MMC1		31
+#define CLK_BUS_UART0		32
+#define CLK_BUS_UART1		33
+#define CLK_BUS_UART2		34
+#define CLK_BUS_UART3		35
+#define CLK_BUS_I2C0		36
+#define CLK_BUS_I2C1		37
+#define CLK_BUS_SCR		38
+#define CLK_SPI0		39
+#define CLK_SPI1		40
+#define CLK_BUS_SPI0		41
+#define CLK_BUS_SPI1		42
+#define CLK_EMAC_25M_DIV	43
+#define CLK_EMAC_25M		44
+#define CLK_BUS_EMAC		45
+#define CLK_IR_RX		46
+#define CLK_BUS_IR_RX		47
+#define CLK_IR_TX		48
+#define CLK_BUS_IR_TX		49
+#define CLK_I2S0		50
+#define CLK_I2S1		51
+#define CLK_BUS_I2S0		52
+#define CLK_BUS_I2S1		53
+#define CLK_SPDIF		54
+#define CLK_BUS_SPDIF		55
+#define CLK_USB_OHCI0		56
+#define CLK_USB_PHY0		57
+#define CLK_USB_OHCI1		58
+#define CLK_USB_PHY1		59
+#define CLK_BUS_OHCI0		60
+#define CLK_BUS_OHCI1		61
+#define CLK_BUS_EHCI0		62
+#define CLK_BUS_OTG		63
+#define CLK_LEDC		64
+#define CLK_BUS_LEDC		65
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h b/include/dt-bindings/reset/sun50i-r329-ccu.h
new file mode 100644
index 000000000000..bb704a82443f
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
+
+#define RST_MBUS		0
+#define RST_BUS_CE		1
+#define RST_BUS_AIPU		2
+#define RST_BUS_DMA		3
+#define RST_BUS_MSGBOX		4
+#define RST_BUS_SPINLOCK	5
+#define RST_BUS_HSTIMER		6
+#define RST_BUS_DBG		7
+#define RST_BUS_PWM		8
+#define RST_BUS_DRAM		9
+#define RST_BUS_NAND		10
+#define RST_BUS_MMC0		11
+#define RST_BUS_MMC1		12
+#define RST_BUS_UART0		13
+#define RST_BUS_UART1		14
+#define RST_BUS_UART2		15
+#define RST_BUS_UART3		16
+#define RST_BUS_I2C0		17
+#define RST_BUS_I2C1		18
+#define RST_BUS_SCR		19
+#define RST_BUS_SPI0		20
+#define RST_BUS_SPI1		21
+#define RST_BUS_EMAC		22
+#define RST_BUS_IR_RX		23
+#define RST_BUS_IR_TX		24
+#define RST_BUS_I2S0		25
+#define RST_BUS_I2S1		26
+#define RST_BUS_SPDIF		27
+#define RST_USB_PHY0		28
+#define RST_USB_PHY1		29
+#define RST_BUS_OHCI0		30
+#define RST_BUS_OHCI1		31
+#define RST_BUS_EHCI0		32
+#define RST_BUS_OTG		33
+#define RST_BUS_LEDC		34
+
+#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 12/17] dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

R329 SoC has two MMC controllers similar to ones in the previous
Allwinner SoCs. However, as R329 has no eMMC controller, the two MMC
controllers look like a mixture of previous SoCs' ordinary MMC
controller and eMMC controller.

Add a compatible string for R329 MMC controllers.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index 4f62ad6ce50c..3e8c3c747a9b 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -28,6 +28,7 @@ properties:
       - const: allwinner,sun50i-a64-mmc
       - const: allwinner,sun50i-a100-emmc
       - const: allwinner,sun50i-a100-mmc
+      - const: allwinner,sun50i-r329-mmc
       - items:
           - const: allwinner,sun8i-a83t-mmc
           - const: allwinner,sun7i-a20-mmc
-- 
2.30.2


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

* [PATCH 12/17] dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

R329 SoC has two MMC controllers similar to ones in the previous
Allwinner SoCs. However, as R329 has no eMMC controller, the two MMC
controllers look like a mixture of previous SoCs' ordinary MMC
controller and eMMC controller.

Add a compatible string for R329 MMC controllers.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index 4f62ad6ce50c..3e8c3c747a9b 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -28,6 +28,7 @@ properties:
       - const: allwinner,sun50i-a64-mmc
       - const: allwinner,sun50i-a100-emmc
       - const: allwinner,sun50i-a100-mmc
+      - const: allwinner,sun50i-r329-mmc
       - items:
           - const: allwinner,sun8i-a83t-mmc
           - const: allwinner,sun7i-a20-mmc
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 13/17] mmc: sunxi: add support for R329 MMC controllers
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

The two MMC controllers in Allwinner R329 have a mixed feature set
comparing to the previous SoCs' ordinary MMC and eMMC controllers.

Add support for them.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/mmc/host/sunxi-mmc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 2702736a1c57..0c9f66785286 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1199,6 +1199,15 @@ static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = {
 	.needs_new_timings = true,
 };
 
+static const struct sunxi_mmc_cfg sun50i_r329_cfg = {
+	.idma_des_size_bits = 13,
+	.idma_des_shift = 2,
+	.clk_delays = NULL,
+	.can_calibrate = true,
+	.mask_data0 = true,
+	.needs_new_timings = true,
+};
+
 static const struct of_device_id sunxi_mmc_of_match[] = {
 	{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
 	{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
@@ -1209,6 +1218,7 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
 	{ .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
 	{ .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
 	{ .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
+	{ .compatible = "allwinner,sun50i-r329-mmc", .data = &sun50i_r329_cfg },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
-- 
2.30.2


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

* [PATCH 13/17] mmc: sunxi: add support for R329 MMC controllers
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

The two MMC controllers in Allwinner R329 have a mixed feature set
comparing to the previous SoCs' ordinary MMC and eMMC controllers.

Add support for them.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/mmc/host/sunxi-mmc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 2702736a1c57..0c9f66785286 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1199,6 +1199,15 @@ static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = {
 	.needs_new_timings = true,
 };
 
+static const struct sunxi_mmc_cfg sun50i_r329_cfg = {
+	.idma_des_size_bits = 13,
+	.idma_des_shift = 2,
+	.clk_delays = NULL,
+	.can_calibrate = true,
+	.mask_data0 = true,
+	.needs_new_timings = true,
+};
+
 static const struct of_device_id sunxi_mmc_of_match[] = {
 	{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
 	{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
@@ -1209,6 +1218,7 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
 	{ .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
 	{ .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
 	{ .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
+	{ .compatible = "allwinner,sun50i-r329-mmc", .data = &sun50i_r329_cfg },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 14/17] dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Sipeed MaixSense is an Allwinner R329 development kit based on Maix IIA
SoM.

Add compatible strings for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 889128acf49a..bce306908eff 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -444,6 +444,12 @@ properties:
           - const: haoyu,a10-marsboard
           - const: allwinner,sun4i-a10
 
+      - description: Sipeed MaixSense
+        items:
+          - const: sipeed,maixsense
+          - const: sipeed,maix-iia
+          - const: allwinner,sun50i-r329
+
       - description: MapleBoard MP130
         items:
           - const: mapleboard,mp130
-- 
2.30.2


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

* [PATCH 14/17] dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Sipeed MaixSense is an Allwinner R329 development kit based on Maix IIA
SoM.

Add compatible strings for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 889128acf49a..bce306908eff 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -444,6 +444,12 @@ properties:
           - const: haoyu,a10-marsboard
           - const: allwinner,sun4i-a10
 
+      - description: Sipeed MaixSense
+        items:
+          - const: sipeed,maixsense
+          - const: sipeed,maix-iia
+          - const: allwinner,sun50i-r329
+
       - description: MapleBoard MP130
         items:
           - const: mapleboard,mp130
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 is a new SoC focused on smart audio devices.

Add a DTSI file for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
 1 file changed, 244 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
new file mode 100644
index 000000000000..bfefa2b734b0
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-r329-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-ccu.h>
+#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <1>;
+			enable-method = "psci";
+		};
+	};
+
+	osc24M: osc24M_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		arm,no-tick-in-suspend;
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pio: pinctrl@2000400 {
+			compatible = "allwinner,sun50i-r329-pinctrl";
+			reg = <0x02000400 0x400>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			uart0_pb_pins: uart0-pb-pins {
+				pins = "PB4", "PB5";
+				function = "uart0";
+			};
+
+			mmc0_pf_pins: mmc0-pf-pins {
+				pins = "PF0", "PF1", "PF2",
+				       "PF3", "PF4", "PF5";
+				function = "mmc0";
+			};
+
+			mmc1_clk_pg0: mmc1-clk-pg0 {
+				pins = "PG0";
+				function = "mmc1_clk";
+			};
+
+			mmc1_cmd_pg1: mmc1-clk-pg1 {
+				pins = "PG1";
+				function = "mmc1_cmd";
+			};
+
+			mmc1_d0_pg2: mmc1-clk-pg2 {
+				pins = "PG2";
+				function = "mmc1_d0";
+			};
+
+			mmc1_d1_pg3: mmc1-clk-pg3 {
+				pins = "PG3";
+				function = "mmc1_d1";
+			};
+
+			mmc1_d2_pg4: mmc1-clk-pg4 {
+				pins = "PG4";
+				function = "mmc1_d2";
+			};
+
+			mmc1_d3_pg5: mmc1-clk-pg5 {
+				pins = "PG5";
+				function = "mmc1_d3";
+			};
+		};
+
+		ccu: clock@2001000 {
+			compatible = "allwinner,sun50i-r329-ccu";
+			reg = <0x02001000 0x1000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		uart0: serial@2500000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500000 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+			status = "disabled";
+		};
+
+		uart1: serial@2500400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500400 0x400>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
+			status = "disabled";
+		};
+
+		uart2: serial@2500800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500800 0x400>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
+			status = "disabled";
+		};
+
+		uart3: serial@2500c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500c00 0x400>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller@3021000 {
+			compatible = "arm,gic-400";
+			reg = <0x03021000 0x1000>,
+			      <0x03022000 0x2000>,
+			      <0x03024000 0x2000>,
+			      <0x03026000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		mmc0: mmc@4020000 {
+			compatible = "allwinner,sun50i-r329-mmc";
+			reg = <0x04020000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc@4021000 {
+			compatible = "allwinner,sun50i-r329-mmc";
+			reg = <0x04021000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		r_ccu: clock@7010000 {
+			compatible = "allwinner,sun50i-r329-r-ccu";
+			reg = <0x07010000 0x10000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		r_pio: pinctrl@7022000 {
+			compatible = "allwinner,sun50i-r329-r-pinctrl";
+			reg = <0x07022000 0x400>;
+			interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		rtc: rtc@7090000 {
+			compatible = "allwinner,sun50i-r329-rtc";
+			reg = <0x07090000 0x400>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			clock-output-names = "osc32k", "osc32k-out", "iosc";
+			#clock-cells = <1>;
+		};
+	};
+};
-- 
2.30.2


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

* [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Allwinner R329 is a new SoC focused on smart audio devices.

Add a DTSI file for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
 1 file changed, 244 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
new file mode 100644
index 000000000000..bfefa2b734b0
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-r329-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-ccu.h>
+#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <1>;
+			enable-method = "psci";
+		};
+	};
+
+	osc24M: osc24M_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		arm,no-tick-in-suspend;
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pio: pinctrl@2000400 {
+			compatible = "allwinner,sun50i-r329-pinctrl";
+			reg = <0x02000400 0x400>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			uart0_pb_pins: uart0-pb-pins {
+				pins = "PB4", "PB5";
+				function = "uart0";
+			};
+
+			mmc0_pf_pins: mmc0-pf-pins {
+				pins = "PF0", "PF1", "PF2",
+				       "PF3", "PF4", "PF5";
+				function = "mmc0";
+			};
+
+			mmc1_clk_pg0: mmc1-clk-pg0 {
+				pins = "PG0";
+				function = "mmc1_clk";
+			};
+
+			mmc1_cmd_pg1: mmc1-clk-pg1 {
+				pins = "PG1";
+				function = "mmc1_cmd";
+			};
+
+			mmc1_d0_pg2: mmc1-clk-pg2 {
+				pins = "PG2";
+				function = "mmc1_d0";
+			};
+
+			mmc1_d1_pg3: mmc1-clk-pg3 {
+				pins = "PG3";
+				function = "mmc1_d1";
+			};
+
+			mmc1_d2_pg4: mmc1-clk-pg4 {
+				pins = "PG4";
+				function = "mmc1_d2";
+			};
+
+			mmc1_d3_pg5: mmc1-clk-pg5 {
+				pins = "PG5";
+				function = "mmc1_d3";
+			};
+		};
+
+		ccu: clock@2001000 {
+			compatible = "allwinner,sun50i-r329-ccu";
+			reg = <0x02001000 0x1000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		uart0: serial@2500000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500000 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+			status = "disabled";
+		};
+
+		uart1: serial@2500400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500400 0x400>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
+			status = "disabled";
+		};
+
+		uart2: serial@2500800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500800 0x400>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
+			status = "disabled";
+		};
+
+		uart3: serial@2500c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500c00 0x400>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller@3021000 {
+			compatible = "arm,gic-400";
+			reg = <0x03021000 0x1000>,
+			      <0x03022000 0x2000>,
+			      <0x03024000 0x2000>,
+			      <0x03026000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		mmc0: mmc@4020000 {
+			compatible = "allwinner,sun50i-r329-mmc";
+			reg = <0x04020000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc@4021000 {
+			compatible = "allwinner,sun50i-r329-mmc";
+			reg = <0x04021000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		r_ccu: clock@7010000 {
+			compatible = "allwinner,sun50i-r329-r-ccu";
+			reg = <0x07010000 0x10000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		r_pio: pinctrl@7022000 {
+			compatible = "allwinner,sun50i-r329-r-pinctrl";
+			reg = <0x07022000 0x400>;
+			interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		rtc: rtc@7090000 {
+			compatible = "allwinner,sun50i-r329-rtc";
+			reg = <0x07090000 0x400>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			clock-output-names = "osc32k", "osc32k-out", "iosc";
+			#clock-cells = <1>;
+		};
+	};
+};
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 16/17] arm64: allwinner: dts: r329: add DTSI file for Sipeed Maix IIA
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Sipeed Maix IIA is a R329-N4 (AIPU available and 256MiB DRAM) based SoM,
with a Realtek SDIO Wi-Fi module on it.

Add a DTSI file for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../dts/allwinner/sun50i-r329-maix-iia.dtsi   | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi
new file mode 100644
index 000000000000..15774f8a5445
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+#include "sun50i-r329.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	reg_vcc3v3: vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 1 0 GPIO_ACTIVE_LOW>; /* PM0 */
+		post-power-on-delay-ms = <200>;
+	};
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_clk_pg0>, <&mmc1_cmd_pg1>, <&mmc1_d0_pg2>,
+		    <&mmc1_d1_pg3>, <&mmc1_d2_pg4>, <&mmc1_d3_pg5>;
+
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
-- 
2.30.2


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

* [PATCH 16/17] arm64: allwinner: dts: r329: add DTSI file for Sipeed Maix IIA
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Sipeed Maix IIA is a R329-N4 (AIPU available and 256MiB DRAM) based SoM,
with a Realtek SDIO Wi-Fi module on it.

Add a DTSI file for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 .../dts/allwinner/sun50i-r329-maix-iia.dtsi   | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi
new file mode 100644
index 000000000000..15774f8a5445
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-r329-maix-iia.dtsi
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+#include "sun50i-r329.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	reg_vcc3v3: vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 1 0 GPIO_ACTIVE_LOW>; /* PM0 */
+		post-power-on-delay-ms = <200>;
+	};
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_clk_pg0>, <&mmc1_cmd_pg1>, <&mmc1_d0_pg2>,
+		    <&mmc1_d1_pg3>, <&mmc1_d2_pg4>, <&mmc1_d3_pg5>;
+
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 17/17] arm64: allwinner: dts: r329: add support for Sipeed MaixSense
  2021-08-02  6:21 ` Icenowy Zheng
@ 2021-08-02  6:22   ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Sipeed MaixSense is a R329 devkit based on Maix IIA SoM.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |  1 +
 .../dts/allwinner/sun50i-r329-maixsense.dts   | 37 +++++++++++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index a96d9d2d8dd8..80a336d480ac 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -37,3 +37,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-r329-maixsense.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts b/arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts
new file mode 100644
index 000000000000..1876b9d0b080
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+/dts-v1/;
+
+#include "sun50i-r329-maix-iia.dtsi"
+
+/ {
+	model = "Sipeed MaixSense";
+	compatible = "sipeed,maixsense", "sipeed,maix-iia",
+		     "allwinner,sun50i-r329";
+
+	aliases {
+		serial0 = &uart0;
+		mmc0 = &mmc0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pf_pins>;
+
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
-- 
2.30.2


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

* [PATCH 17/17] arm64: allwinner: dts: r329: add support for Sipeed MaixSense
@ 2021-08-02  6:22   ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  6:22 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel, Icenowy Zheng

Sipeed MaixSense is a R329 devkit based on Maix IIA SoM.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |  1 +
 .../dts/allwinner/sun50i-r329-maixsense.dts   | 37 +++++++++++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index a96d9d2d8dd8..80a336d480ac 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -37,3 +37,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-r329-maixsense.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts b/arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts
new file mode 100644
index 000000000000..1876b9d0b080
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-r329-maixsense.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+/dts-v1/;
+
+#include "sun50i-r329-maix-iia.dtsi"
+
+/ {
+	model = "Sipeed MaixSense";
+	compatible = "sipeed,maixsense", "sipeed,maix-iia",
+		     "allwinner,sun50i-r329";
+
+	aliases {
+		serial0 = &uart0;
+		mmc0 = &mmc0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pf_pins>;
+
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-02  9:03     ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  9:03 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

在 2021-08-02星期一的 14:22 +0800,Icenowy Zheng写道:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled
> by
> R-CCU on R329.

Well, I forgot to mention that the R_DMA bus clock gates/resets are not
documented on the user manual, and the info here is get by experiment.

There seems to be another hidden bus clock gate/reset according to a
register dump of R_CCU done on BSP kernel, but I have no idea what it
is.

> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374
> ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> ng/Kconfig
> index cd46d8853876..e49b2c2fa5b7 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>         default ARM64 && ARCH_SUNXI
>         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_R_CCU
> +       bool "Support for the Allwinner R329 PRCM CCU"
> +       default ARM64 && ARCH_SUNXI
> +       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN4I_A10_CCU
>         bool "Support for the Allwinner A10/A20 CCU"
>         default MACH_SUN4I
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-
> ng/Makefile
> index 96c324306d97..db338a2188fd 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)       += ccu-
> sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)  += ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)  += ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_R_CCU)        += ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..5413a701cb57
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Sipeed
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329-r.h"
> +
> +/*
> + * The M factor is present in the register's description, but not in
> the
> + * frequency formula, and it's documented as "The bit is only for
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_R329_PLL_CPUX_REG       0x1000
> +static struct ccu_mult pll_cpux_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .mult           = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .common         = {
> +               .reg            = 0x1000,
> +               .hw.init        = CLK_HW_INIT("pll-cpux", "osc24M",
> +                                             &ccu_mult_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +#define SUN50I_R329_PLL_PERIPH_REG     0x1010
> +static struct ccu_nm pll_periph_base_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
> +       .common         = {
> +               .reg            = 0x1010,
> +               .hw.init        = CLK_HW_INIT("pll-periph-base",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-
> base",
> +                  0x1010, 16, 3, 0);
> +static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-
> periph-base",
> +                  0x1010, 20, 3, 0);
> +static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
> +                          &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +#define SUN50I_R329_PLL_AUDIO0_REG     0x1020
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> +       { .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64
> },
> +};
> +
> +static struct ccu_nm pll_audio0_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1),
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio0_sdm_table,
> +                                        BIT(24), 0x1120, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1020,
> +               .hw.init        = CLK_HW_INIT("pll-audio0", "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-
> audio0",
> +                  0x1020, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-
> audio0",
> +                  0x1020, 20, 3, 0);
> +
> +/*
> + * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
> + * BSP driver always has M0 = 1 and M1 = 2 (this is also the
> + * reset value in the register).
> + *
> + * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
> + */
> +#define SUN50I_R329_PLL_AUDIO1_REG     0x1030
> +static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
> +       { .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22
> },
> +       { .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24
> },
> +       { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +       { .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
> +};
> +static struct ccu_nm pll_audio1_4x_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(16, 6),
> +       .fixed_post_div = 2,
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
> +                                        BIT(24), 0x1130, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_FIXED_POSTDIV |
> +                                 CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1030,
> +               .hw.init        = CLK_HW_INIT("pll-audio1-4x",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
> +                          &pll_audio1_4x_clk.common.hw, 2, 1,
> +                          CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
> +                          &pll_audio1_4x_clk.common.hw, 4, 1,
> +                          CLK_SET_RATE_PARENT);
> +
> +static const char * const r_bus_parents[] = { "osc24M", "osc32k",
> "iosc",
> +                                             "pll-periph-2x",
> +                                             "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents,
> 0x000,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents,
> 0x00c,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents,
> 0x010,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
> +                     0x0ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc,
> BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c,
> BIT(0), 0);
> +
> +static const char * const r_pwm_parents[] = { "osc24M", "osc32k",
> "iosc" };
> +static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents,
> 0x130,
> +                              24, 3,   /* mux */
> +                              BIT(31), /* gate */
> +                              0);
> +
> +static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c,
> BIT(0), 0);
> +
> +static const char * const r_audio_parents[] = { "pll-audio0-div5",
> "pll-audio0-div2",
> +                                               "pll-audio1-1x",
> "pll-audio1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc",
> r_audio_parents, 0x140,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac",
> r_audio_parents, 0x144,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
> +                     0x14c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic",
> r_audio_parents, 0x150,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
> +                     0x16c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s",
> r_audio_parents, 0x170,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
> +                                 r_audio_parents, 0x174,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c,
> BIT(0), 0);
> +
> +static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents,
> 0x1c0,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
> +                     0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-
> apb1",
> +                     0x1ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
> +                     0x20c, BIT(0), CLK_IS_CRITICAL);
> +
> +static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
> +       &pll_cpux_clk.common,
> +       &pll_periph_base_clk.common,
> +       &pll_periph_2x_clk.common,
> +       &pll_periph_800m_clk.common,
> +       &pll_audio0_clk.common,
> +       &pll_audio0_div2_clk.common,
> +       &pll_audio0_div5_clk.common,
> +       &pll_audio1_4x_clk.common,
> +       &r_ahb_clk.common,
> +       &r_apb1_clk.common,
> +       &r_apb2_clk.common,
> +       &r_bus_gpadc_clk.common,
> +       &r_bus_ths_clk.common,
> +       &r_bus_dma_clk.common,
> +       &r_pwm_clk.common,
> +       &r_bus_pwm_clk.common,
> +       &r_codec_adc_clk.common,
> +       &r_codec_dac_clk.common,
> +       &r_bus_codec_clk.common,
> +       &r_dmic_clk.common,
> +       &r_bus_dmic_clk.common,
> +       &r_bus_lradc_clk.common,
> +       &r_i2s_clk.common,
> +       &r_i2s_asrc_clk.common,
> +       &r_bus_i2s_clk.common,
> +       &r_bus_uart_clk.common,
> +       &r_bus_i2c_clk.common,
> +       &r_ir_clk.common,
> +       &r_bus_ir_clk.common,
> +       &r_bus_msgbox_clk.common,
> +       &r_bus_spinlock_clk.common,
> +       &r_bus_rtc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
> +       .hws    = {
> +               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
> +               [CLK_PLL_PERIPH_BASE]   =
> &pll_periph_base_clk.common.hw,
> +               [CLK_PLL_PERIPH_2X]     =
> &pll_periph_2x_clk.common.hw,
> +               [CLK_PLL_PERIPH_800M]   =
> &pll_periph_800m_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.hw,
> +               [CLK_PLL_AUDIO0]        = &pll_audio0_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV2]   =
> &pll_audio0_div2_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV5]   =
> &pll_audio0_div5_clk.common.hw,
> +               [CLK_PLL_AUDIO1_4X]     =
> &pll_audio1_4x_clk.common.hw,
> +               [CLK_PLL_AUDIO1_2X]     = &pll_audio1_2x_clk.hw,
> +               [CLK_PLL_AUDIO1]        = &pll_audio1_clk.hw,
> +               [CLK_R_AHB]             = &r_ahb_clk.common.hw,
> +               [CLK_R_APB1]            = &r_apb1_clk.common.hw,
> +               [CLK_R_APB2]            = &r_apb2_clk.common.hw,
> +               [CLK_R_BUS_GPADC]       = &r_bus_gpadc_clk.common.hw,
> +               [CLK_R_BUS_THS]         = &r_bus_ths_clk.common.hw,
> +               [CLK_R_BUS_DMA]         = &r_bus_dma_clk.common.hw,
> +               [CLK_R_PWM]             = &r_pwm_clk.common.hw,
> +               [CLK_R_BUS_PWM]         = &r_bus_pwm_clk.common.hw,
> +               [CLK_R_CODEC_ADC]       = &r_codec_adc_clk.common.hw,
> +               [CLK_R_CODEC_DAC]       = &r_codec_dac_clk.common.hw,
> +               [CLK_R_BUS_CODEC]       = &r_bus_codec_clk.common.hw,
> +               [CLK_R_DMIC]            = &r_dmic_clk.common.hw,
> +               [CLK_R_BUS_DMIC]        = &r_bus_dmic_clk.common.hw,
> +               [CLK_R_BUS_LRADC]       = &r_bus_lradc_clk.common.hw,
> +               [CLK_R_I2S]             = &r_i2s_clk.common.hw,
> +               [CLK_R_I2S_ASRC]        = &r_i2s_asrc_clk.common.hw,
> +               [CLK_R_BUS_I2S]         = &r_bus_i2s_clk.common.hw,
> +               [CLK_R_BUS_UART]        = &r_bus_uart_clk.common.hw,
> +               [CLK_R_BUS_I2C]         = &r_bus_i2c_clk.common.hw,
> +               [CLK_R_IR]              = &r_ir_clk.common.hw,
> +               [CLK_R_BUS_IR]          = &r_bus_ir_clk.common.hw,
> +               [CLK_R_BUS_MSGBOX]      =
> &r_bus_msgbox_clk.common.hw,
> +               [CLK_R_BUS_SPINLOCK]    =
> &r_bus_spinlock_clk.common.hw,
> +               [CLK_R_BUS_RTC]         = &r_bus_rtc_clk.common.hw,
> +       },
> +       .num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
> +       [RST_R_BUS_GPADC]       = { 0x0ec, BIT(16) },
> +       [RST_R_BUS_THS]         = { 0x0fc, BIT(16) },
> +       [RST_R_BUS_DMA]         = { 0x10c, BIT(16) },
> +       [RST_R_BUS_PWM]         = { 0x13c, BIT(16) },
> +       [RST_R_BUS_CODEC]       = { 0x14c, BIT(16) },
> +       [RST_R_BUS_DMIC]        = { 0x15c, BIT(16) },
> +       [RST_R_BUS_LRADC]       = { 0x16c, BIT(16) },
> +       [RST_R_BUS_I2S]         = { 0x17c, BIT(16) },
> +       [RST_R_BUS_UART]        = { 0x18c, BIT(16) },
> +       [RST_R_BUS_I2C]         = { 0x19c, BIT(16) },
> +       [RST_R_BUS_IR]          = { 0x1cc, BIT(16) },
> +       [RST_R_BUS_MSGBOX]      = { 0x1dc, BIT(16) },
> +       [RST_R_BUS_SPINLOCK]    = { 0x1ec, BIT(16) },
> +       [RST_R_BUS_RTC]         = { 0x20c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
> +       .ccu_clks       = sun50i_r329_r_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun50i_r329_r_ccu_clks),
> +
> +       .hw_clks        = &sun50i_r329_r_hw_clks,
> +
> +       .resets         = sun50i_r329_r_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun50i_r329_r_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> +       SUN50I_R329_PLL_CPUX_REG,
> +       SUN50I_R329_PLL_PERIPH_REG,
> +       SUN50I_R329_PLL_AUDIO0_REG,
> +       SUN50I_R329_PLL_AUDIO1_REG,
> +};
> +
> +static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
> +{
> +       void __iomem *reg;
> +       u32 val;
> +       int i;
> +
> +       reg = of_io_request_and_map(node, 0,
> of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%pOF: Could not map clock registers\n",
> node);
> +               return;
> +       }
> +
> +       /* Enable the lock bits and the output enable bits on all
> PLLs */
> +       for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +               val = readl(reg + pll_regs[i]);
> +               val |= BIT(29) | BIT(27);
> +               writel(val, reg + pll_regs[i]);
> +       }
> +
> +       /*
> +        * Force the I/O dividers of PLL-AUDIO1 to reset default
> value
> +        *
> +        * See the comment before pll-audio1 definition for the
> reason.
> +        */
> +
> +       val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
> +       val &= ~BIT(1);
> +       val |= BIT(0);
> +       writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
> +
> +       i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
> +       if (i)
> +               pr_err("%pOF: probing clocks fails: %d\n", node, i);
> +}
> +
> +CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
> +              sun50i_r329_r_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> new file mode 100644
> index 000000000000..62cf65322116
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_R_H
> +#define _CCU_SUN50I_R329_R_H
> +
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +#define CLK_PLL_CPUX           0
> +#define CLK_PLL_PERIPH_BASE    1
> +#define CLK_PLL_PERIPH_2X      2
> +#define CLK_PLL_PERIPH_800M    3
> +#define CLK_PLL_PERIPH         4
> +#define CLK_PLL_AUDIO0         5
> +#define CLK_PLL_AUDIO0_DIV2    6
> +#define CLK_PLL_AUDIO0_DIV5    7
> +#define CLK_PLL_AUDIO1_4X      8
> +#define CLK_PLL_AUDIO1_2X      9
> +#define CLK_PLL_AUDIO1         10
> +#define CLK_R_AHB              11
> +
> +/* R_APB1 exported for PIO */
> +
> +#define CLK_R_APB2             13
> +
> +/* All module / bus gate clocks exported */
> +
> +#define CLK_NUMBER     (CLK_R_BUS_RTC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_R_H */
> diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..df9bc58de5c4
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +
> +#define CLK_R_APB1             12
> +
> +#define CLK_R_BUS_GPADC                14
> +#define CLK_R_BUS_THS          15
> +#define CLK_R_BUS_DMA          16
> +#define CLK_R_PWM              17
> +#define CLK_R_BUS_PWM          18
> +#define CLK_R_CODEC_ADC                19
> +#define CLK_R_CODEC_DAC                20
> +#define CLK_R_BUS_CODEC                21
> +#define CLK_R_DMIC             22
> +#define CLK_R_BUS_DMIC         23
> +#define CLK_R_BUS_LRADC                24
> +#define CLK_R_I2S              25
> +#define CLK_R_I2S_ASRC         26
> +#define CLK_R_BUS_I2S          27
> +#define CLK_R_BUS_UART         28
> +#define CLK_R_BUS_I2C          29
> +#define CLK_R_IR               30
> +#define CLK_R_BUS_IR           31
> +#define CLK_R_BUS_MSGBOX       32
> +#define CLK_R_BUS_SPINLOCK     33
> +#define CLK_R_BUS_RTC          34
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..40644f2f21c6
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +
> +#define RST_R_BUS_GPADC                0
> +#define RST_R_BUS_THS          1
> +#define RST_R_BUS_DMA          2
> +#define RST_R_BUS_PWM          3
> +#define RST_R_BUS_CODEC                4
> +#define RST_R_BUS_DMIC         5
> +#define RST_R_BUS_LRADC                6
> +#define RST_R_BUS_I2S          7
> +#define RST_R_BUS_UART         8
> +#define RST_R_BUS_I2C          9
> +#define RST_R_BUS_IR           10
> +#define RST_R_BUS_MSGBOX       11
> +#define RST_R_BUS_SPINLOCK     12
> +#define RST_R_BUS_RTC          13
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */



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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
@ 2021-08-02  9:03     ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  9:03 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

在 2021-08-02星期一的 14:22 +0800,Icenowy Zheng写道:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled
> by
> R-CCU on R329.

Well, I forgot to mention that the R_DMA bus clock gates/resets are not
documented on the user manual, and the info here is get by experiment.

There seems to be another hidden bus clock gate/reset according to a
register dump of R_CCU done on BSP kernel, but I have no idea what it
is.

> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374
> ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> ng/Kconfig
> index cd46d8853876..e49b2c2fa5b7 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>         default ARM64 && ARCH_SUNXI
>         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_R_CCU
> +       bool "Support for the Allwinner R329 PRCM CCU"
> +       default ARM64 && ARCH_SUNXI
> +       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN4I_A10_CCU
>         bool "Support for the Allwinner A10/A20 CCU"
>         default MACH_SUN4I
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-
> ng/Makefile
> index 96c324306d97..db338a2188fd 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)       += ccu-
> sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)  += ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)  += ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_R_CCU)        += ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..5413a701cb57
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Sipeed
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329-r.h"
> +
> +/*
> + * The M factor is present in the register's description, but not in
> the
> + * frequency formula, and it's documented as "The bit is only for
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_R329_PLL_CPUX_REG       0x1000
> +static struct ccu_mult pll_cpux_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .mult           = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .common         = {
> +               .reg            = 0x1000,
> +               .hw.init        = CLK_HW_INIT("pll-cpux", "osc24M",
> +                                             &ccu_mult_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +#define SUN50I_R329_PLL_PERIPH_REG     0x1010
> +static struct ccu_nm pll_periph_base_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
> +       .common         = {
> +               .reg            = 0x1010,
> +               .hw.init        = CLK_HW_INIT("pll-periph-base",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-
> base",
> +                  0x1010, 16, 3, 0);
> +static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-
> periph-base",
> +                  0x1010, 20, 3, 0);
> +static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
> +                          &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +#define SUN50I_R329_PLL_AUDIO0_REG     0x1020
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> +       { .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64
> },
> +};
> +
> +static struct ccu_nm pll_audio0_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1),
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio0_sdm_table,
> +                                        BIT(24), 0x1120, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1020,
> +               .hw.init        = CLK_HW_INIT("pll-audio0", "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-
> audio0",
> +                  0x1020, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-
> audio0",
> +                  0x1020, 20, 3, 0);
> +
> +/*
> + * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
> + * BSP driver always has M0 = 1 and M1 = 2 (this is also the
> + * reset value in the register).
> + *
> + * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
> + */
> +#define SUN50I_R329_PLL_AUDIO1_REG     0x1030
> +static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
> +       { .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22
> },
> +       { .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24
> },
> +       { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +       { .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
> +};
> +static struct ccu_nm pll_audio1_4x_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(16, 6),
> +       .fixed_post_div = 2,
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
> +                                        BIT(24), 0x1130, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_FIXED_POSTDIV |
> +                                 CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1030,
> +               .hw.init        = CLK_HW_INIT("pll-audio1-4x",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
> +                          &pll_audio1_4x_clk.common.hw, 2, 1,
> +                          CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
> +                          &pll_audio1_4x_clk.common.hw, 4, 1,
> +                          CLK_SET_RATE_PARENT);
> +
> +static const char * const r_bus_parents[] = { "osc24M", "osc32k",
> "iosc",
> +                                             "pll-periph-2x",
> +                                             "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents,
> 0x000,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents,
> 0x00c,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents,
> 0x010,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
> +                     0x0ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc,
> BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c,
> BIT(0), 0);
> +
> +static const char * const r_pwm_parents[] = { "osc24M", "osc32k",
> "iosc" };
> +static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents,
> 0x130,
> +                              24, 3,   /* mux */
> +                              BIT(31), /* gate */
> +                              0);
> +
> +static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c,
> BIT(0), 0);
> +
> +static const char * const r_audio_parents[] = { "pll-audio0-div5",
> "pll-audio0-div2",
> +                                               "pll-audio1-1x",
> "pll-audio1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc",
> r_audio_parents, 0x140,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac",
> r_audio_parents, 0x144,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
> +                     0x14c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic",
> r_audio_parents, 0x150,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
> +                     0x16c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s",
> r_audio_parents, 0x170,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
> +                                 r_audio_parents, 0x174,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c,
> BIT(0), 0);
> +
> +static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents,
> 0x1c0,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
> +                     0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-
> apb1",
> +                     0x1ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
> +                     0x20c, BIT(0), CLK_IS_CRITICAL);
> +
> +static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
> +       &pll_cpux_clk.common,
> +       &pll_periph_base_clk.common,
> +       &pll_periph_2x_clk.common,
> +       &pll_periph_800m_clk.common,
> +       &pll_audio0_clk.common,
> +       &pll_audio0_div2_clk.common,
> +       &pll_audio0_div5_clk.common,
> +       &pll_audio1_4x_clk.common,
> +       &r_ahb_clk.common,
> +       &r_apb1_clk.common,
> +       &r_apb2_clk.common,
> +       &r_bus_gpadc_clk.common,
> +       &r_bus_ths_clk.common,
> +       &r_bus_dma_clk.common,
> +       &r_pwm_clk.common,
> +       &r_bus_pwm_clk.common,
> +       &r_codec_adc_clk.common,
> +       &r_codec_dac_clk.common,
> +       &r_bus_codec_clk.common,
> +       &r_dmic_clk.common,
> +       &r_bus_dmic_clk.common,
> +       &r_bus_lradc_clk.common,
> +       &r_i2s_clk.common,
> +       &r_i2s_asrc_clk.common,
> +       &r_bus_i2s_clk.common,
> +       &r_bus_uart_clk.common,
> +       &r_bus_i2c_clk.common,
> +       &r_ir_clk.common,
> +       &r_bus_ir_clk.common,
> +       &r_bus_msgbox_clk.common,
> +       &r_bus_spinlock_clk.common,
> +       &r_bus_rtc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
> +       .hws    = {
> +               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
> +               [CLK_PLL_PERIPH_BASE]   =
> &pll_periph_base_clk.common.hw,
> +               [CLK_PLL_PERIPH_2X]     =
> &pll_periph_2x_clk.common.hw,
> +               [CLK_PLL_PERIPH_800M]   =
> &pll_periph_800m_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.hw,
> +               [CLK_PLL_AUDIO0]        = &pll_audio0_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV2]   =
> &pll_audio0_div2_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV5]   =
> &pll_audio0_div5_clk.common.hw,
> +               [CLK_PLL_AUDIO1_4X]     =
> &pll_audio1_4x_clk.common.hw,
> +               [CLK_PLL_AUDIO1_2X]     = &pll_audio1_2x_clk.hw,
> +               [CLK_PLL_AUDIO1]        = &pll_audio1_clk.hw,
> +               [CLK_R_AHB]             = &r_ahb_clk.common.hw,
> +               [CLK_R_APB1]            = &r_apb1_clk.common.hw,
> +               [CLK_R_APB2]            = &r_apb2_clk.common.hw,
> +               [CLK_R_BUS_GPADC]       = &r_bus_gpadc_clk.common.hw,
> +               [CLK_R_BUS_THS]         = &r_bus_ths_clk.common.hw,
> +               [CLK_R_BUS_DMA]         = &r_bus_dma_clk.common.hw,
> +               [CLK_R_PWM]             = &r_pwm_clk.common.hw,
> +               [CLK_R_BUS_PWM]         = &r_bus_pwm_clk.common.hw,
> +               [CLK_R_CODEC_ADC]       = &r_codec_adc_clk.common.hw,
> +               [CLK_R_CODEC_DAC]       = &r_codec_dac_clk.common.hw,
> +               [CLK_R_BUS_CODEC]       = &r_bus_codec_clk.common.hw,
> +               [CLK_R_DMIC]            = &r_dmic_clk.common.hw,
> +               [CLK_R_BUS_DMIC]        = &r_bus_dmic_clk.common.hw,
> +               [CLK_R_BUS_LRADC]       = &r_bus_lradc_clk.common.hw,
> +               [CLK_R_I2S]             = &r_i2s_clk.common.hw,
> +               [CLK_R_I2S_ASRC]        = &r_i2s_asrc_clk.common.hw,
> +               [CLK_R_BUS_I2S]         = &r_bus_i2s_clk.common.hw,
> +               [CLK_R_BUS_UART]        = &r_bus_uart_clk.common.hw,
> +               [CLK_R_BUS_I2C]         = &r_bus_i2c_clk.common.hw,
> +               [CLK_R_IR]              = &r_ir_clk.common.hw,
> +               [CLK_R_BUS_IR]          = &r_bus_ir_clk.common.hw,
> +               [CLK_R_BUS_MSGBOX]      =
> &r_bus_msgbox_clk.common.hw,
> +               [CLK_R_BUS_SPINLOCK]    =
> &r_bus_spinlock_clk.common.hw,
> +               [CLK_R_BUS_RTC]         = &r_bus_rtc_clk.common.hw,
> +       },
> +       .num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
> +       [RST_R_BUS_GPADC]       = { 0x0ec, BIT(16) },
> +       [RST_R_BUS_THS]         = { 0x0fc, BIT(16) },
> +       [RST_R_BUS_DMA]         = { 0x10c, BIT(16) },
> +       [RST_R_BUS_PWM]         = { 0x13c, BIT(16) },
> +       [RST_R_BUS_CODEC]       = { 0x14c, BIT(16) },
> +       [RST_R_BUS_DMIC]        = { 0x15c, BIT(16) },
> +       [RST_R_BUS_LRADC]       = { 0x16c, BIT(16) },
> +       [RST_R_BUS_I2S]         = { 0x17c, BIT(16) },
> +       [RST_R_BUS_UART]        = { 0x18c, BIT(16) },
> +       [RST_R_BUS_I2C]         = { 0x19c, BIT(16) },
> +       [RST_R_BUS_IR]          = { 0x1cc, BIT(16) },
> +       [RST_R_BUS_MSGBOX]      = { 0x1dc, BIT(16) },
> +       [RST_R_BUS_SPINLOCK]    = { 0x1ec, BIT(16) },
> +       [RST_R_BUS_RTC]         = { 0x20c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
> +       .ccu_clks       = sun50i_r329_r_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun50i_r329_r_ccu_clks),
> +
> +       .hw_clks        = &sun50i_r329_r_hw_clks,
> +
> +       .resets         = sun50i_r329_r_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun50i_r329_r_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> +       SUN50I_R329_PLL_CPUX_REG,
> +       SUN50I_R329_PLL_PERIPH_REG,
> +       SUN50I_R329_PLL_AUDIO0_REG,
> +       SUN50I_R329_PLL_AUDIO1_REG,
> +};
> +
> +static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
> +{
> +       void __iomem *reg;
> +       u32 val;
> +       int i;
> +
> +       reg = of_io_request_and_map(node, 0,
> of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%pOF: Could not map clock registers\n",
> node);
> +               return;
> +       }
> +
> +       /* Enable the lock bits and the output enable bits on all
> PLLs */
> +       for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +               val = readl(reg + pll_regs[i]);
> +               val |= BIT(29) | BIT(27);
> +               writel(val, reg + pll_regs[i]);
> +       }
> +
> +       /*
> +        * Force the I/O dividers of PLL-AUDIO1 to reset default
> value
> +        *
> +        * See the comment before pll-audio1 definition for the
> reason.
> +        */
> +
> +       val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
> +       val &= ~BIT(1);
> +       val |= BIT(0);
> +       writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
> +
> +       i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
> +       if (i)
> +               pr_err("%pOF: probing clocks fails: %d\n", node, i);
> +}
> +
> +CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
> +              sun50i_r329_r_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> new file mode 100644
> index 000000000000..62cf65322116
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_R_H
> +#define _CCU_SUN50I_R329_R_H
> +
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +#define CLK_PLL_CPUX           0
> +#define CLK_PLL_PERIPH_BASE    1
> +#define CLK_PLL_PERIPH_2X      2
> +#define CLK_PLL_PERIPH_800M    3
> +#define CLK_PLL_PERIPH         4
> +#define CLK_PLL_AUDIO0         5
> +#define CLK_PLL_AUDIO0_DIV2    6
> +#define CLK_PLL_AUDIO0_DIV5    7
> +#define CLK_PLL_AUDIO1_4X      8
> +#define CLK_PLL_AUDIO1_2X      9
> +#define CLK_PLL_AUDIO1         10
> +#define CLK_R_AHB              11
> +
> +/* R_APB1 exported for PIO */
> +
> +#define CLK_R_APB2             13
> +
> +/* All module / bus gate clocks exported */
> +
> +#define CLK_NUMBER     (CLK_R_BUS_RTC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_R_H */
> diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..df9bc58de5c4
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +
> +#define CLK_R_APB1             12
> +
> +#define CLK_R_BUS_GPADC                14
> +#define CLK_R_BUS_THS          15
> +#define CLK_R_BUS_DMA          16
> +#define CLK_R_PWM              17
> +#define CLK_R_BUS_PWM          18
> +#define CLK_R_CODEC_ADC                19
> +#define CLK_R_CODEC_DAC                20
> +#define CLK_R_BUS_CODEC                21
> +#define CLK_R_DMIC             22
> +#define CLK_R_BUS_DMIC         23
> +#define CLK_R_BUS_LRADC                24
> +#define CLK_R_I2S              25
> +#define CLK_R_I2S_ASRC         26
> +#define CLK_R_BUS_I2S          27
> +#define CLK_R_BUS_UART         28
> +#define CLK_R_BUS_I2C          29
> +#define CLK_R_IR               30
> +#define CLK_R_BUS_IR           31
> +#define CLK_R_BUS_MSGBOX       32
> +#define CLK_R_BUS_SPINLOCK     33
> +#define CLK_R_BUS_RTC          34
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..40644f2f21c6
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +
> +#define RST_R_BUS_GPADC                0
> +#define RST_R_BUS_THS          1
> +#define RST_R_BUS_DMA          2
> +#define RST_R_BUS_PWM          3
> +#define RST_R_BUS_CODEC                4
> +#define RST_R_BUS_DMIC         5
> +#define RST_R_BUS_LRADC                6
> +#define RST_R_BUS_I2S          7
> +#define RST_R_BUS_UART         8
> +#define RST_R_BUS_I2C          9
> +#define RST_R_BUS_IR           10
> +#define RST_R_BUS_MSGBOX       11
> +#define RST_R_BUS_SPINLOCK     12
> +#define RST_R_BUS_RTC          13
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-02  9:52     ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  9:52 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

在 2021-08-02星期一的 14:22 +0800,Icenowy Zheng写道:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled
> by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374
> ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> ng/Kconfig
> index cd46d8853876..e49b2c2fa5b7 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>         default ARM64 && ARCH_SUNXI
>         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_R_CCU
> +       bool "Support for the Allwinner R329 PRCM CCU"
> +       default ARM64 && ARCH_SUNXI
> +       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN4I_A10_CCU
>         bool "Support for the Allwinner A10/A20 CCU"
>         default MACH_SUN4I
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-
> ng/Makefile
> index 96c324306d97..db338a2188fd 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)       += ccu-
> sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)  += ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)  += ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_R_CCU)        += ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..5413a701cb57
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Sipeed
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329-r.h"
> +
> +/*
> + * The M factor is present in the register's description, but not in
> the
> + * frequency formula, and it's documented as "The bit is only for
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_R329_PLL_CPUX_REG       0x1000
> +static struct ccu_mult pll_cpux_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .mult           = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .common         = {
> +               .reg            = 0x1000,
> +               .hw.init        = CLK_HW_INIT("pll-cpux", "osc24M",
> +                                             &ccu_mult_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +#define SUN50I_R329_PLL_PERIPH_REG     0x1010
> +static struct ccu_nm pll_periph_base_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
> +       .common         = {
> +               .reg            = 0x1010,
> +               .hw.init        = CLK_HW_INIT("pll-periph-base",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-
> base",
> +                  0x1010, 16, 3, 0);
> +static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-
> periph-base",
> +                  0x1010, 20, 3, 0);
> +static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
> +                          &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +#define SUN50I_R329_PLL_AUDIO0_REG     0x1020
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> +       { .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64
> },
> +};
> +
> +static struct ccu_nm pll_audio0_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1),
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio0_sdm_table,
> +                                        BIT(24), 0x1120, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1020,
> +               .hw.init        = CLK_HW_INIT("pll-audio0", "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-
> audio0",
> +                  0x1020, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-
> audio0",
> +                  0x1020, 20, 3, 0);
> +
> +/*
> + * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
> + * BSP driver always has M0 = 1 and M1 = 2 (this is also the
> + * reset value in the register).
> + *
> + * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
> + */
> +#define SUN50I_R329_PLL_AUDIO1_REG     0x1030
> +static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
> +       { .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22
> },
> +       { .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24
> },
> +       { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +       { .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
> +};

Sorry, the SDM table here is wrong -- all rate here should be *2
(because I wrongly assumed how postdiv works with sdm).

> +static struct ccu_nm pll_audio1_4x_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(16, 6),
> +       .fixed_post_div = 2,
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
> +                                        BIT(24), 0x1130, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_FIXED_POSTDIV |
> +                                 CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1030,
> +               .hw.init        = CLK_HW_INIT("pll-audio1-4x",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
> +                          &pll_audio1_4x_clk.common.hw, 2, 1,
> +                          CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
> +                          &pll_audio1_4x_clk.common.hw, 4, 1,
> +                          CLK_SET_RATE_PARENT);
> +
> +static const char * const r_bus_parents[] = { "osc24M", "osc32k",
> "iosc",
> +                                             "pll-periph-2x",
> +                                             "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents,
> 0x000,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents,
> 0x00c,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents,
> 0x010,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
> +                     0x0ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc,
> BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c,
> BIT(0), 0);
> +
> +static const char * const r_pwm_parents[] = { "osc24M", "osc32k",
> "iosc" };
> +static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents,
> 0x130,
> +                              24, 3,   /* mux */
> +                              BIT(31), /* gate */
> +                              0);
> +
> +static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c,
> BIT(0), 0);
> +
> +static const char * const r_audio_parents[] = { "pll-audio0-div5",
> "pll-audio0-div2",
> +                                               "pll-audio1-1x",
> "pll-audio1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc",
> r_audio_parents, 0x140,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac",
> r_audio_parents, 0x144,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
> +                     0x14c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic",
> r_audio_parents, 0x150,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
> +                     0x16c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s",
> r_audio_parents, 0x170,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
> +                                 r_audio_parents, 0x174,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c,
> BIT(0), 0);
> +
> +static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents,
> 0x1c0,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
> +                     0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-
> apb1",
> +                     0x1ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
> +                     0x20c, BIT(0), CLK_IS_CRITICAL);
> +
> +static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
> +       &pll_cpux_clk.common,
> +       &pll_periph_base_clk.common,
> +       &pll_periph_2x_clk.common,
> +       &pll_periph_800m_clk.common,
> +       &pll_audio0_clk.common,
> +       &pll_audio0_div2_clk.common,
> +       &pll_audio0_div5_clk.common,
> +       &pll_audio1_4x_clk.common,
> +       &r_ahb_clk.common,
> +       &r_apb1_clk.common,
> +       &r_apb2_clk.common,
> +       &r_bus_gpadc_clk.common,
> +       &r_bus_ths_clk.common,
> +       &r_bus_dma_clk.common,
> +       &r_pwm_clk.common,
> +       &r_bus_pwm_clk.common,
> +       &r_codec_adc_clk.common,
> +       &r_codec_dac_clk.common,
> +       &r_bus_codec_clk.common,
> +       &r_dmic_clk.common,
> +       &r_bus_dmic_clk.common,
> +       &r_bus_lradc_clk.common,
> +       &r_i2s_clk.common,
> +       &r_i2s_asrc_clk.common,
> +       &r_bus_i2s_clk.common,
> +       &r_bus_uart_clk.common,
> +       &r_bus_i2c_clk.common,
> +       &r_ir_clk.common,
> +       &r_bus_ir_clk.common,
> +       &r_bus_msgbox_clk.common,
> +       &r_bus_spinlock_clk.common,
> +       &r_bus_rtc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
> +       .hws    = {
> +               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
> +               [CLK_PLL_PERIPH_BASE]   =
> &pll_periph_base_clk.common.hw,
> +               [CLK_PLL_PERIPH_2X]     =
> &pll_periph_2x_clk.common.hw,
> +               [CLK_PLL_PERIPH_800M]   =
> &pll_periph_800m_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.hw,
> +               [CLK_PLL_AUDIO0]        = &pll_audio0_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV2]   =
> &pll_audio0_div2_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV5]   =
> &pll_audio0_div5_clk.common.hw,
> +               [CLK_PLL_AUDIO1_4X]     =
> &pll_audio1_4x_clk.common.hw,
> +               [CLK_PLL_AUDIO1_2X]     = &pll_audio1_2x_clk.hw,
> +               [CLK_PLL_AUDIO1]        = &pll_audio1_clk.hw,
> +               [CLK_R_AHB]             = &r_ahb_clk.common.hw,
> +               [CLK_R_APB1]            = &r_apb1_clk.common.hw,
> +               [CLK_R_APB2]            = &r_apb2_clk.common.hw,
> +               [CLK_R_BUS_GPADC]       = &r_bus_gpadc_clk.common.hw,
> +               [CLK_R_BUS_THS]         = &r_bus_ths_clk.common.hw,
> +               [CLK_R_BUS_DMA]         = &r_bus_dma_clk.common.hw,
> +               [CLK_R_PWM]             = &r_pwm_clk.common.hw,
> +               [CLK_R_BUS_PWM]         = &r_bus_pwm_clk.common.hw,
> +               [CLK_R_CODEC_ADC]       = &r_codec_adc_clk.common.hw,
> +               [CLK_R_CODEC_DAC]       = &r_codec_dac_clk.common.hw,
> +               [CLK_R_BUS_CODEC]       = &r_bus_codec_clk.common.hw,
> +               [CLK_R_DMIC]            = &r_dmic_clk.common.hw,
> +               [CLK_R_BUS_DMIC]        = &r_bus_dmic_clk.common.hw,
> +               [CLK_R_BUS_LRADC]       = &r_bus_lradc_clk.common.hw,
> +               [CLK_R_I2S]             = &r_i2s_clk.common.hw,
> +               [CLK_R_I2S_ASRC]        = &r_i2s_asrc_clk.common.hw,
> +               [CLK_R_BUS_I2S]         = &r_bus_i2s_clk.common.hw,
> +               [CLK_R_BUS_UART]        = &r_bus_uart_clk.common.hw,
> +               [CLK_R_BUS_I2C]         = &r_bus_i2c_clk.common.hw,
> +               [CLK_R_IR]              = &r_ir_clk.common.hw,
> +               [CLK_R_BUS_IR]          = &r_bus_ir_clk.common.hw,
> +               [CLK_R_BUS_MSGBOX]      =
> &r_bus_msgbox_clk.common.hw,
> +               [CLK_R_BUS_SPINLOCK]    =
> &r_bus_spinlock_clk.common.hw,
> +               [CLK_R_BUS_RTC]         = &r_bus_rtc_clk.common.hw,
> +       },
> +       .num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
> +       [RST_R_BUS_GPADC]       = { 0x0ec, BIT(16) },
> +       [RST_R_BUS_THS]         = { 0x0fc, BIT(16) },
> +       [RST_R_BUS_DMA]         = { 0x10c, BIT(16) },
> +       [RST_R_BUS_PWM]         = { 0x13c, BIT(16) },
> +       [RST_R_BUS_CODEC]       = { 0x14c, BIT(16) },
> +       [RST_R_BUS_DMIC]        = { 0x15c, BIT(16) },
> +       [RST_R_BUS_LRADC]       = { 0x16c, BIT(16) },
> +       [RST_R_BUS_I2S]         = { 0x17c, BIT(16) },
> +       [RST_R_BUS_UART]        = { 0x18c, BIT(16) },
> +       [RST_R_BUS_I2C]         = { 0x19c, BIT(16) },
> +       [RST_R_BUS_IR]          = { 0x1cc, BIT(16) },
> +       [RST_R_BUS_MSGBOX]      = { 0x1dc, BIT(16) },
> +       [RST_R_BUS_SPINLOCK]    = { 0x1ec, BIT(16) },
> +       [RST_R_BUS_RTC]         = { 0x20c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
> +       .ccu_clks       = sun50i_r329_r_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun50i_r329_r_ccu_clks),
> +
> +       .hw_clks        = &sun50i_r329_r_hw_clks,
> +
> +       .resets         = sun50i_r329_r_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun50i_r329_r_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> +       SUN50I_R329_PLL_CPUX_REG,
> +       SUN50I_R329_PLL_PERIPH_REG,
> +       SUN50I_R329_PLL_AUDIO0_REG,
> +       SUN50I_R329_PLL_AUDIO1_REG,
> +};
> +
> +static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
> +{
> +       void __iomem *reg;
> +       u32 val;
> +       int i;
> +
> +       reg = of_io_request_and_map(node, 0,
> of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%pOF: Could not map clock registers\n",
> node);
> +               return;
> +       }
> +
> +       /* Enable the lock bits and the output enable bits on all
> PLLs */
> +       for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +               val = readl(reg + pll_regs[i]);
> +               val |= BIT(29) | BIT(27);
> +               writel(val, reg + pll_regs[i]);
> +       }
> +
> +       /*
> +        * Force the I/O dividers of PLL-AUDIO1 to reset default
> value
> +        *
> +        * See the comment before pll-audio1 definition for the
> reason.
> +        */
> +
> +       val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
> +       val &= ~BIT(1);
> +       val |= BIT(0);
> +       writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
> +
> +       i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
> +       if (i)
> +               pr_err("%pOF: probing clocks fails: %d\n", node, i);
> +}
> +
> +CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
> +              sun50i_r329_r_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> new file mode 100644
> index 000000000000..62cf65322116
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_R_H
> +#define _CCU_SUN50I_R329_R_H
> +
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +#define CLK_PLL_CPUX           0
> +#define CLK_PLL_PERIPH_BASE    1
> +#define CLK_PLL_PERIPH_2X      2
> +#define CLK_PLL_PERIPH_800M    3
> +#define CLK_PLL_PERIPH         4
> +#define CLK_PLL_AUDIO0         5
> +#define CLK_PLL_AUDIO0_DIV2    6
> +#define CLK_PLL_AUDIO0_DIV5    7
> +#define CLK_PLL_AUDIO1_4X      8
> +#define CLK_PLL_AUDIO1_2X      9
> +#define CLK_PLL_AUDIO1         10
> +#define CLK_R_AHB              11
> +
> +/* R_APB1 exported for PIO */
> +
> +#define CLK_R_APB2             13
> +
> +/* All module / bus gate clocks exported */
> +
> +#define CLK_NUMBER     (CLK_R_BUS_RTC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_R_H */
> diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..df9bc58de5c4
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +
> +#define CLK_R_APB1             12
> +
> +#define CLK_R_BUS_GPADC                14
> +#define CLK_R_BUS_THS          15
> +#define CLK_R_BUS_DMA          16
> +#define CLK_R_PWM              17
> +#define CLK_R_BUS_PWM          18
> +#define CLK_R_CODEC_ADC                19
> +#define CLK_R_CODEC_DAC                20
> +#define CLK_R_BUS_CODEC                21
> +#define CLK_R_DMIC             22
> +#define CLK_R_BUS_DMIC         23
> +#define CLK_R_BUS_LRADC                24
> +#define CLK_R_I2S              25
> +#define CLK_R_I2S_ASRC         26
> +#define CLK_R_BUS_I2S          27
> +#define CLK_R_BUS_UART         28
> +#define CLK_R_BUS_I2C          29
> +#define CLK_R_IR               30
> +#define CLK_R_BUS_IR           31
> +#define CLK_R_BUS_MSGBOX       32
> +#define CLK_R_BUS_SPINLOCK     33
> +#define CLK_R_BUS_RTC          34
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..40644f2f21c6
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +
> +#define RST_R_BUS_GPADC                0
> +#define RST_R_BUS_THS          1
> +#define RST_R_BUS_DMA          2
> +#define RST_R_BUS_PWM          3
> +#define RST_R_BUS_CODEC                4
> +#define RST_R_BUS_DMIC         5
> +#define RST_R_BUS_LRADC                6
> +#define RST_R_BUS_I2S          7
> +#define RST_R_BUS_UART         8
> +#define RST_R_BUS_I2C          9
> +#define RST_R_BUS_IR           10
> +#define RST_R_BUS_MSGBOX       11
> +#define RST_R_BUS_SPINLOCK     12
> +#define RST_R_BUS_RTC          13
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */



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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
@ 2021-08-02  9:52     ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-02  9:52 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

在 2021-08-02星期一的 14:22 +0800,Icenowy Zheng写道:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled
> by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374
> ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> ng/Kconfig
> index cd46d8853876..e49b2c2fa5b7 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>         default ARM64 && ARCH_SUNXI
>         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_R_CCU
> +       bool "Support for the Allwinner R329 PRCM CCU"
> +       default ARM64 && ARCH_SUNXI
> +       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN4I_A10_CCU
>         bool "Support for the Allwinner A10/A20 CCU"
>         default MACH_SUN4I
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-
> ng/Makefile
> index 96c324306d97..db338a2188fd 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)       += ccu-
> sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)  += ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)  += ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_R_CCU)        += ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..5413a701cb57
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Sipeed
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329-r.h"
> +
> +/*
> + * The M factor is present in the register's description, but not in
> the
> + * frequency formula, and it's documented as "The bit is only for
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_R329_PLL_CPUX_REG       0x1000
> +static struct ccu_mult pll_cpux_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .mult           = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .common         = {
> +               .reg            = 0x1000,
> +               .hw.init        = CLK_HW_INIT("pll-cpux", "osc24M",
> +                                             &ccu_mult_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +#define SUN50I_R329_PLL_PERIPH_REG     0x1010
> +static struct ccu_nm pll_periph_base_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
> +       .common         = {
> +               .reg            = 0x1010,
> +               .hw.init        = CLK_HW_INIT("pll-periph-base",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-
> base",
> +                  0x1010, 16, 3, 0);
> +static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-
> periph-base",
> +                  0x1010, 20, 3, 0);
> +static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
> +                          &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +#define SUN50I_R329_PLL_AUDIO0_REG     0x1020
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> +       { .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64
> },
> +};
> +
> +static struct ccu_nm pll_audio0_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(1, 1),
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio0_sdm_table,
> +                                        BIT(24), 0x1120, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1020,
> +               .hw.init        = CLK_HW_INIT("pll-audio0", "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-
> audio0",
> +                  0x1020, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-
> audio0",
> +                  0x1020, 20, 3, 0);
> +
> +/*
> + * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
> + * BSP driver always has M0 = 1 and M1 = 2 (this is also the
> + * reset value in the register).
> + *
> + * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
> + */
> +#define SUN50I_R329_PLL_AUDIO1_REG     0x1030
> +static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
> +       { .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22
> },
> +       { .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24
> },
> +       { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +       { .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
> +};

Sorry, the SDM table here is wrong -- all rate here should be *2
(because I wrongly assumed how postdiv works with sdm).

> +static struct ccu_nm pll_audio1_4x_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +       .m              = _SUNXI_CCU_DIV(16, 6),
> +       .fixed_post_div = 2,
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
> +                                        BIT(24), 0x1130, BIT(31)),
> +       .common         = {
> +               .features       = CCU_FEATURE_FIXED_POSTDIV |
> +                                 CCU_FEATURE_SIGMA_DELTA_MOD,
> +               .reg            = 0x1030,
> +               .hw.init        = CLK_HW_INIT("pll-audio1-4x",
> "osc24M",
> +                                             &ccu_nm_ops,
> +                                             CLK_SET_RATE_UNGATE),
> +       },
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
> +                          &pll_audio1_4x_clk.common.hw, 2, 1,
> +                          CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
> +                          &pll_audio1_4x_clk.common.hw, 4, 1,
> +                          CLK_SET_RATE_PARENT);
> +
> +static const char * const r_bus_parents[] = { "osc24M", "osc32k",
> "iosc",
> +                                             "pll-periph-2x",
> +                                             "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents,
> 0x000,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents,
> 0x00c,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents,
> 0x010,
> +                            0, 5,      /* M */
> +                            8, 2,      /* P */
> +                            24, 3,     /* mux */
> +                            0);
> +
> +static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
> +                     0x0ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc,
> BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c,
> BIT(0), 0);
> +
> +static const char * const r_pwm_parents[] = { "osc24M", "osc32k",
> "iosc" };
> +static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents,
> 0x130,
> +                              24, 3,   /* mux */
> +                              BIT(31), /* gate */
> +                              0);
> +
> +static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c,
> BIT(0), 0);
> +
> +static const char * const r_audio_parents[] = { "pll-audio0-div5",
> "pll-audio0-div2",
> +                                               "pll-audio1-1x",
> "pll-audio1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc",
> r_audio_parents, 0x140,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac",
> r_audio_parents, 0x144,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
> +                     0x14c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic",
> r_audio_parents, 0x150,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
> +                     0x16c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s",
> r_audio_parents, 0x170,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
> +                                 r_audio_parents, 0x174,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c,
> BIT(0), 0);
> +
> +static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents,
> 0x1c0,
> +                                 0, 5,         /* M */
> +                                 8, 2,         /* P */
> +                                 24, 3,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc,
> BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
> +                     0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-
> apb1",
> +                     0x1ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
> +                     0x20c, BIT(0), CLK_IS_CRITICAL);
> +
> +static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
> +       &pll_cpux_clk.common,
> +       &pll_periph_base_clk.common,
> +       &pll_periph_2x_clk.common,
> +       &pll_periph_800m_clk.common,
> +       &pll_audio0_clk.common,
> +       &pll_audio0_div2_clk.common,
> +       &pll_audio0_div5_clk.common,
> +       &pll_audio1_4x_clk.common,
> +       &r_ahb_clk.common,
> +       &r_apb1_clk.common,
> +       &r_apb2_clk.common,
> +       &r_bus_gpadc_clk.common,
> +       &r_bus_ths_clk.common,
> +       &r_bus_dma_clk.common,
> +       &r_pwm_clk.common,
> +       &r_bus_pwm_clk.common,
> +       &r_codec_adc_clk.common,
> +       &r_codec_dac_clk.common,
> +       &r_bus_codec_clk.common,
> +       &r_dmic_clk.common,
> +       &r_bus_dmic_clk.common,
> +       &r_bus_lradc_clk.common,
> +       &r_i2s_clk.common,
> +       &r_i2s_asrc_clk.common,
> +       &r_bus_i2s_clk.common,
> +       &r_bus_uart_clk.common,
> +       &r_bus_i2c_clk.common,
> +       &r_ir_clk.common,
> +       &r_bus_ir_clk.common,
> +       &r_bus_msgbox_clk.common,
> +       &r_bus_spinlock_clk.common,
> +       &r_bus_rtc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
> +       .hws    = {
> +               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
> +               [CLK_PLL_PERIPH_BASE]   =
> &pll_periph_base_clk.common.hw,
> +               [CLK_PLL_PERIPH_2X]     =
> &pll_periph_2x_clk.common.hw,
> +               [CLK_PLL_PERIPH_800M]   =
> &pll_periph_800m_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.hw,
> +               [CLK_PLL_AUDIO0]        = &pll_audio0_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV2]   =
> &pll_audio0_div2_clk.common.hw,
> +               [CLK_PLL_AUDIO0_DIV5]   =
> &pll_audio0_div5_clk.common.hw,
> +               [CLK_PLL_AUDIO1_4X]     =
> &pll_audio1_4x_clk.common.hw,
> +               [CLK_PLL_AUDIO1_2X]     = &pll_audio1_2x_clk.hw,
> +               [CLK_PLL_AUDIO1]        = &pll_audio1_clk.hw,
> +               [CLK_R_AHB]             = &r_ahb_clk.common.hw,
> +               [CLK_R_APB1]            = &r_apb1_clk.common.hw,
> +               [CLK_R_APB2]            = &r_apb2_clk.common.hw,
> +               [CLK_R_BUS_GPADC]       = &r_bus_gpadc_clk.common.hw,
> +               [CLK_R_BUS_THS]         = &r_bus_ths_clk.common.hw,
> +               [CLK_R_BUS_DMA]         = &r_bus_dma_clk.common.hw,
> +               [CLK_R_PWM]             = &r_pwm_clk.common.hw,
> +               [CLK_R_BUS_PWM]         = &r_bus_pwm_clk.common.hw,
> +               [CLK_R_CODEC_ADC]       = &r_codec_adc_clk.common.hw,
> +               [CLK_R_CODEC_DAC]       = &r_codec_dac_clk.common.hw,
> +               [CLK_R_BUS_CODEC]       = &r_bus_codec_clk.common.hw,
> +               [CLK_R_DMIC]            = &r_dmic_clk.common.hw,
> +               [CLK_R_BUS_DMIC]        = &r_bus_dmic_clk.common.hw,
> +               [CLK_R_BUS_LRADC]       = &r_bus_lradc_clk.common.hw,
> +               [CLK_R_I2S]             = &r_i2s_clk.common.hw,
> +               [CLK_R_I2S_ASRC]        = &r_i2s_asrc_clk.common.hw,
> +               [CLK_R_BUS_I2S]         = &r_bus_i2s_clk.common.hw,
> +               [CLK_R_BUS_UART]        = &r_bus_uart_clk.common.hw,
> +               [CLK_R_BUS_I2C]         = &r_bus_i2c_clk.common.hw,
> +               [CLK_R_IR]              = &r_ir_clk.common.hw,
> +               [CLK_R_BUS_IR]          = &r_bus_ir_clk.common.hw,
> +               [CLK_R_BUS_MSGBOX]      =
> &r_bus_msgbox_clk.common.hw,
> +               [CLK_R_BUS_SPINLOCK]    =
> &r_bus_spinlock_clk.common.hw,
> +               [CLK_R_BUS_RTC]         = &r_bus_rtc_clk.common.hw,
> +       },
> +       .num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
> +       [RST_R_BUS_GPADC]       = { 0x0ec, BIT(16) },
> +       [RST_R_BUS_THS]         = { 0x0fc, BIT(16) },
> +       [RST_R_BUS_DMA]         = { 0x10c, BIT(16) },
> +       [RST_R_BUS_PWM]         = { 0x13c, BIT(16) },
> +       [RST_R_BUS_CODEC]       = { 0x14c, BIT(16) },
> +       [RST_R_BUS_DMIC]        = { 0x15c, BIT(16) },
> +       [RST_R_BUS_LRADC]       = { 0x16c, BIT(16) },
> +       [RST_R_BUS_I2S]         = { 0x17c, BIT(16) },
> +       [RST_R_BUS_UART]        = { 0x18c, BIT(16) },
> +       [RST_R_BUS_I2C]         = { 0x19c, BIT(16) },
> +       [RST_R_BUS_IR]          = { 0x1cc, BIT(16) },
> +       [RST_R_BUS_MSGBOX]      = { 0x1dc, BIT(16) },
> +       [RST_R_BUS_SPINLOCK]    = { 0x1ec, BIT(16) },
> +       [RST_R_BUS_RTC]         = { 0x20c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
> +       .ccu_clks       = sun50i_r329_r_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun50i_r329_r_ccu_clks),
> +
> +       .hw_clks        = &sun50i_r329_r_hw_clks,
> +
> +       .resets         = sun50i_r329_r_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun50i_r329_r_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> +       SUN50I_R329_PLL_CPUX_REG,
> +       SUN50I_R329_PLL_PERIPH_REG,
> +       SUN50I_R329_PLL_AUDIO0_REG,
> +       SUN50I_R329_PLL_AUDIO1_REG,
> +};
> +
> +static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
> +{
> +       void __iomem *reg;
> +       u32 val;
> +       int i;
> +
> +       reg = of_io_request_and_map(node, 0,
> of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%pOF: Could not map clock registers\n",
> node);
> +               return;
> +       }
> +
> +       /* Enable the lock bits and the output enable bits on all
> PLLs */
> +       for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +               val = readl(reg + pll_regs[i]);
> +               val |= BIT(29) | BIT(27);
> +               writel(val, reg + pll_regs[i]);
> +       }
> +
> +       /*
> +        * Force the I/O dividers of PLL-AUDIO1 to reset default
> value
> +        *
> +        * See the comment before pll-audio1 definition for the
> reason.
> +        */
> +
> +       val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
> +       val &= ~BIT(1);
> +       val |= BIT(0);
> +       writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
> +
> +       i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
> +       if (i)
> +               pr_err("%pOF: probing clocks fails: %d\n", node, i);
> +}
> +
> +CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
> +              sun50i_r329_r_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> new file mode 100644
> index 000000000000..62cf65322116
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_R_H
> +#define _CCU_SUN50I_R329_R_H
> +
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +#define CLK_PLL_CPUX           0
> +#define CLK_PLL_PERIPH_BASE    1
> +#define CLK_PLL_PERIPH_2X      2
> +#define CLK_PLL_PERIPH_800M    3
> +#define CLK_PLL_PERIPH         4
> +#define CLK_PLL_AUDIO0         5
> +#define CLK_PLL_AUDIO0_DIV2    6
> +#define CLK_PLL_AUDIO0_DIV5    7
> +#define CLK_PLL_AUDIO1_4X      8
> +#define CLK_PLL_AUDIO1_2X      9
> +#define CLK_PLL_AUDIO1         10
> +#define CLK_R_AHB              11
> +
> +/* R_APB1 exported for PIO */
> +
> +#define CLK_R_APB2             13
> +
> +/* All module / bus gate clocks exported */
> +
> +#define CLK_NUMBER     (CLK_R_BUS_RTC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_R_H */
> diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..df9bc58de5c4
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +
> +#define CLK_R_APB1             12
> +
> +#define CLK_R_BUS_GPADC                14
> +#define CLK_R_BUS_THS          15
> +#define CLK_R_BUS_DMA          16
> +#define CLK_R_PWM              17
> +#define CLK_R_BUS_PWM          18
> +#define CLK_R_CODEC_ADC                19
> +#define CLK_R_CODEC_DAC                20
> +#define CLK_R_BUS_CODEC                21
> +#define CLK_R_DMIC             22
> +#define CLK_R_BUS_DMIC         23
> +#define CLK_R_BUS_LRADC                24
> +#define CLK_R_I2S              25
> +#define CLK_R_I2S_ASRC         26
> +#define CLK_R_BUS_I2S          27
> +#define CLK_R_BUS_UART         28
> +#define CLK_R_BUS_I2C          29
> +#define CLK_R_IR               30
> +#define CLK_R_BUS_IR           31
> +#define CLK_R_BUS_MSGBOX       32
> +#define CLK_R_BUS_SPINLOCK     33
> +#define CLK_R_BUS_RTC          34
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..40644f2f21c6
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +
> +#define RST_R_BUS_GPADC                0
> +#define RST_R_BUS_THS          1
> +#define RST_R_BUS_DMA          2
> +#define RST_R_BUS_PWM          3
> +#define RST_R_BUS_CODEC                4
> +#define RST_R_BUS_DMIC         5
> +#define RST_R_BUS_LRADC                6
> +#define RST_R_BUS_I2S          7
> +#define RST_R_BUS_UART         8
> +#define RST_R_BUS_I2C          9
> +#define RST_R_BUS_IR           10
> +#define RST_R_BUS_MSGBOX       11
> +#define RST_R_BUS_SPINLOCK     12
> +#define RST_R_BUS_RTC          13
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17] dt-bindings: rtc: sun6i: add compatible string for R329 RTC
  2021-08-02  6:21   ` Icenowy Zheng
@ 2021-08-06 21:39     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:39 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Alexandre Belloni, Ulf Hansson, Linus Walleij,
	Maxime Ripard, Samuel Holland, Chen-Yu Tsai, linux-sunxi,
	Jernej Skrabec, Rob Herring, Andre Przywara, linux-kernel,
	linux-arm-kernel

On Mon, 02 Aug 2021 14:21:59 +0800, Icenowy Zheng wrote:
> Allwinner R329 has a RTC similar to previous ones, capable of
> controlling LOSC and IOSC and with only one alarm.
> 
> Add a compatible string for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml    | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 04/17] dt-bindings: rtc: sun6i: add compatible string for R329 RTC
@ 2021-08-06 21:39     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:39 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Alexandre Belloni, Ulf Hansson, Linus Walleij,
	Maxime Ripard, Samuel Holland, Chen-Yu Tsai, linux-sunxi,
	Jernej Skrabec, Rob Herring, Andre Przywara, linux-kernel,
	linux-arm-kernel

On Mon, 02 Aug 2021 14:21:59 +0800, Icenowy Zheng wrote:
> Allwinner R329 has a RTC similar to previous ones, capable of
> controlling LOSC and IOSC and with only one alarm.
> 
> Add a compatible string for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml    | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-06 21:40     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:40 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Chen-Yu Tsai, Maxime Ripard, Samuel Holland, devicetree,
	Alexandre Belloni, Jernej Skrabec, linux-sunxi, Ulf Hansson,
	linux-kernel, linux-arm-kernel, Andre Przywara, Rob Herring,
	Linus Walleij

On Mon, 02 Aug 2021 14:22:01 +0800, Icenowy Zheng wrote:
> Allwinner R329 have two pin controllers similar to previous Allwinner
> SoCs, PIO and R-PIO.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml         | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
@ 2021-08-06 21:40     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:40 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Chen-Yu Tsai, Maxime Ripard, Samuel Holland, devicetree,
	Alexandre Belloni, Jernej Skrabec, linux-sunxi, Ulf Hansson,
	linux-kernel, linux-arm-kernel, Andre Przywara, Rob Herring,
	Linus Walleij

On Mon, 02 Aug 2021 14:22:01 +0800, Icenowy Zheng wrote:
> Allwinner R329 have two pin controllers similar to previous Allwinner
> SoCs, PIO and R-PIO.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml         | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 09/17] dt-bindings: clock: sunxi-ng: add compatibles for R329 CCUs
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-06 21:41     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:41 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Ulf Hansson, linux-kernel, devicetree, Andre Przywara,
	Jernej Skrabec, Linus Walleij, Alexandre Belloni, Samuel Holland,
	linux-arm-kernel, Maxime Ripard, Chen-Yu Tsai, Rob Herring,
	linux-sunxi

On Mon, 02 Aug 2021 14:22:04 +0800, Icenowy Zheng wrote:
> R329 has a CPUX CCU and a R-CCU.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml    | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 09/17] dt-bindings: clock: sunxi-ng: add compatibles for R329 CCUs
@ 2021-08-06 21:41     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:41 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Ulf Hansson, linux-kernel, devicetree, Andre Przywara,
	Jernej Skrabec, Linus Walleij, Alexandre Belloni, Samuel Holland,
	linux-arm-kernel, Maxime Ripard, Chen-Yu Tsai, Rob Herring,
	linux-sunxi

On Mon, 02 Aug 2021 14:22:04 +0800, Icenowy Zheng wrote:
> R329 has a CPUX CCU and a R-CCU.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml    | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-06 21:42     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:42 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On Mon, Aug 02, 2021 at 02:22:05PM +0800, Icenowy Zheng wrote:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++

These 2 belong in the binding patch.

>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
@ 2021-08-06 21:42     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:42 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On Mon, Aug 02, 2021 at 02:22:05PM +0800, Icenowy Zheng wrote:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++

These 2 belong in the binding patch.

>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-06 21:42     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:42 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On Mon, Aug 02, 2021 at 02:22:06PM +0800, Icenowy Zheng wrote:
> Allwinner R329 has a CCU that is similar to the H616 one, but it's cut
> down and have PLLs moved out.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                |   5 +
>  drivers/clk/sunxi-ng/Makefile               |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526 ++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
>  include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
>  include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++

Same here.

>  6 files changed, 682 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h

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

* Re: [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
@ 2021-08-06 21:42     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:42 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On Mon, Aug 02, 2021 at 02:22:06PM +0800, Icenowy Zheng wrote:
> Allwinner R329 has a CCU that is similar to the H616 one, but it's cut
> down and have PLLs moved out.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                |   5 +
>  drivers/clk/sunxi-ng/Makefile               |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526 ++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
>  include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
>  include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++

Same here.

>  6 files changed, 682 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 12/17] dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-06 21:42     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:42 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Ulf Hansson, devicetree, Linus Walleij, linux-sunxi,
	Alexandre Belloni, linux-arm-kernel, Jernej Skrabec,
	Andre Przywara, linux-kernel, Maxime Ripard, Rob Herring,
	Samuel Holland, Chen-Yu Tsai

On Mon, 02 Aug 2021 14:22:07 +0800, Icenowy Zheng wrote:
> R329 SoC has two MMC controllers similar to ones in the previous
> Allwinner SoCs. However, as R329 has no eMMC controller, the two MMC
> controllers look like a mixture of previous SoCs' ordinary MMC
> controller and eMMC controller.
> 
> Add a compatible string for R329 MMC controllers.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml         | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 12/17] dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
@ 2021-08-06 21:42     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:42 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Ulf Hansson, devicetree, Linus Walleij, linux-sunxi,
	Alexandre Belloni, linux-arm-kernel, Jernej Skrabec,
	Andre Przywara, linux-kernel, Maxime Ripard, Rob Herring,
	Samuel Holland, Chen-Yu Tsai

On Mon, 02 Aug 2021 14:22:07 +0800, Icenowy Zheng wrote:
> R329 SoC has two MMC controllers similar to ones in the previous
> Allwinner SoCs. However, as R329 has no eMMC controller, the two MMC
> controllers look like a mixture of previous SoCs' ordinary MMC
> controller and eMMC controller.
> 
> Add a compatible string for R329 MMC controllers.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml         | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 14/17] dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-06 21:43     ` Rob Herring
  -1 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:43 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: linux-arm-kernel, linux-kernel, linux-sunxi, Chen-Yu Tsai,
	Samuel Holland, Linus Walleij, Jernej Skrabec, devicetree,
	Rob Herring, Alexandre Belloni, Ulf Hansson, Maxime Ripard,
	Andre Przywara

On Mon, 02 Aug 2021 14:22:09 +0800, Icenowy Zheng wrote:
> Sipeed MaixSense is an Allwinner R329 development kit based on Maix IIA
> SoM.
> 
> Add compatible strings for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 14/17] dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
@ 2021-08-06 21:43     ` Rob Herring
  0 siblings, 0 replies; 112+ messages in thread
From: Rob Herring @ 2021-08-06 21:43 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: linux-arm-kernel, linux-kernel, linux-sunxi, Chen-Yu Tsai,
	Samuel Holland, Linus Walleij, Jernej Skrabec, devicetree,
	Rob Herring, Alexandre Belloni, Ulf Hansson, Maxime Ripard,
	Andre Przywara

On Mon, 02 Aug 2021 14:22:09 +0800, Icenowy Zheng wrote:
> Sipeed MaixSense is an Allwinner R329 development kit based on Maix IIA
> SoM.
> 
> Add compatible strings for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 00/17] Basical Allwinner R329 support
  2021-08-02  6:21 ` Icenowy Zheng
  (?)
@ 2021-08-10 11:04   ` Ulf Hansson
  -1 siblings, 0 replies; 112+ messages in thread
From: Ulf Hansson @ 2021-08-10 11:04 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	DTML, Linux ARM, linux-sunxi, Linux Kernel Mailing List

On Mon, 2 Aug 2021 at 08:24, Icenowy Zheng <icenowy@sipeed.com> wrote:
>
> This patchset tries to add basical support for Allwinner R329 SoC to the
> Linux kernel, including clock/pintrl driver and MMC support.
>
> Three patches from the H616 patchset, which are used to support the RTC
> with linear day, are attached into this patchset. Other RTC-related
> patches of that patchset is not included, because the binding of the
> clock part there is still under discussion.
>
> Then I added RTC binding and support (which is now only a struct
> addition). I added RTC into this patchset, with the same reason that
> H616 patchset contains RTC, which is to make the clock tree correct at
> the first inclusion.
>
> After RTC, main basical SoC-specific part, pinctrl and CCU, come. The
> R329 CCU is something special because PLLs are in R-CCU, no main CCU.
>
> MMC support is added here because it's also a simple struct addition
> work, no main driver code change needed.

It sounds like the MMC updates can be posted separately to linux-mmc.
Please do so I can pick them up.

[...]

Kind regards
Uffe

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

* Re: [PATCH 00/17] Basical Allwinner R329 support
@ 2021-08-10 11:04   ` Ulf Hansson
  0 siblings, 0 replies; 112+ messages in thread
From: Ulf Hansson @ 2021-08-10 11:04 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	DTML, Linux ARM, linux-sunxi, Linux Kernel Mailing List

On Mon, 2 Aug 2021 at 08:24, Icenowy Zheng <icenowy@sipeed.com> wrote:
>
> This patchset tries to add basical support for Allwinner R329 SoC to the
> Linux kernel, including clock/pintrl driver and MMC support.
>
> Three patches from the H616 patchset, which are used to support the RTC
> with linear day, are attached into this patchset. Other RTC-related
> patches of that patchset is not included, because the binding of the
> clock part there is still under discussion.
>
> Then I added RTC binding and support (which is now only a struct
> addition). I added RTC into this patchset, with the same reason that
> H616 patchset contains RTC, which is to make the clock tree correct at
> the first inclusion.
>
> After RTC, main basical SoC-specific part, pinctrl and CCU, come. The
> R329 CCU is something special because PLLs are in R-CCU, no main CCU.
>
> MMC support is added here because it's also a simple struct addition
> work, no main driver code change needed.

It sounds like the MMC updates can be posted separately to linux-mmc.
Please do so I can pick them up.

[...]

Kind regards
Uffe

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

* Re: [PATCH 00/17] Basical Allwinner R329 support
@ 2021-08-10 11:04   ` Ulf Hansson
  0 siblings, 0 replies; 112+ messages in thread
From: Ulf Hansson @ 2021-08-10 11:04 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	DTML, Linux ARM, linux-sunxi, Linux Kernel Mailing List

On Mon, 2 Aug 2021 at 08:24, Icenowy Zheng <icenowy@sipeed.com> wrote:
>
> This patchset tries to add basical support for Allwinner R329 SoC to the
> Linux kernel, including clock/pintrl driver and MMC support.
>
> Three patches from the H616 patchset, which are used to support the RTC
> with linear day, are attached into this patchset. Other RTC-related
> patches of that patchset is not included, because the binding of the
> clock part there is still under discussion.
>
> Then I added RTC binding and support (which is now only a struct
> addition). I added RTC into this patchset, with the same reason that
> H616 patchset contains RTC, which is to make the clock tree correct at
> the first inclusion.
>
> After RTC, main basical SoC-specific part, pinctrl and CCU, come. The
> R329 CCU is something special because PLLs are in R-CCU, no main CCU.
>
> MMC support is added here because it's also a simple struct addition
> work, no main driver code change needed.

It sounds like the MMC updates can be posted separately to linux-mmc.
Please do so I can pick them up.

[...]

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
  2021-08-02  6:22   ` Icenowy Zheng
  (?)
@ 2021-08-11  9:23     ` Linus Walleij
  -1 siblings, 0 replies; 112+ messages in thread
From: Linus Walleij @ 2021-08-11  9:23 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Alexandre Belloni, Andre Przywara, Samuel Holland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux ARM, linux-sunxi, linux-kernel

On Mon, Aug 2, 2021 at 8:23 AM Icenowy Zheng <icenowy@sipeed.com> wrote:

> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
>
> This patch adds support for the CPUX domain pin controller.
>
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Can you send the pin control changes separately?
Also the bindings.

Then they can be reviewed and merged separately so I
don't have to pick out the stuff I can apply.

Yours,
Linus Walleij

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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
@ 2021-08-11  9:23     ` Linus Walleij
  0 siblings, 0 replies; 112+ messages in thread
From: Linus Walleij @ 2021-08-11  9:23 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Alexandre Belloni, Andre Przywara, Samuel Holland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux ARM, linux-sunxi, linux-kernel

On Mon, Aug 2, 2021 at 8:23 AM Icenowy Zheng <icenowy@sipeed.com> wrote:

> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
>
> This patch adds support for the CPUX domain pin controller.
>
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Can you send the pin control changes separately?
Also the bindings.

Then they can be reviewed and merged separately so I
don't have to pick out the stuff I can apply.

Yours,
Linus Walleij

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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
@ 2021-08-11  9:23     ` Linus Walleij
  0 siblings, 0 replies; 112+ messages in thread
From: Linus Walleij @ 2021-08-11  9:23 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Ulf Hansson, Alexandre Belloni, Andre Przywara, Samuel Holland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux ARM, linux-sunxi, linux-kernel

On Mon, Aug 2, 2021 at 8:23 AM Icenowy Zheng <icenowy@sipeed.com> wrote:

> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
>
> This patch adds support for the CPUX domain pin controller.
>
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Can you send the pin control changes separately?
Also the bindings.

Then they can be reviewed and merged separately so I
don't have to pick out the stuff I can apply.

Yours,
Linus Walleij

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 12/17] dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  8:47     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:47 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 476 bytes --]

On Mon, Aug 02, 2021 at 02:22:07PM +0800, Icenowy Zheng wrote:
> R329 SoC has two MMC controllers similar to ones in the previous
> Allwinner SoCs. However, as R329 has no eMMC controller, the two MMC
> controllers look like a mixture of previous SoCs' ordinary MMC
> controller and eMMC controller.
> 
> Add a compatible string for R329 MMC controllers.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 12/17] dt-bindings: mmc: sunxi-mmc: add R329 MMC compatible string
@ 2021-08-18  8:47     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:47 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 476 bytes --]

On Mon, Aug 02, 2021 at 02:22:07PM +0800, Icenowy Zheng wrote:
> R329 SoC has two MMC controllers similar to ones in the previous
> Allwinner SoCs. However, as R329 has no eMMC controller, the two MMC
> controllers look like a mixture of previous SoCs' ordinary MMC
> controller and eMMC controller.
> 
> Add a compatible string for R329 MMC controllers.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 13/17] mmc: sunxi: add support for R329 MMC controllers
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  8:47     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:47 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 347 bytes --]

On Mon, Aug 02, 2021 at 02:22:08PM +0800, Icenowy Zheng wrote:
> The two MMC controllers in Allwinner R329 have a mixed feature set
> comparing to the previous SoCs' ordinary MMC and eMMC controllers.
> 
> Add support for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 13/17] mmc: sunxi: add support for R329 MMC controllers
@ 2021-08-18  8:47     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:47 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 347 bytes --]

On Mon, Aug 02, 2021 at 02:22:08PM +0800, Icenowy Zheng wrote:
> The two MMC controllers in Allwinner R329 have a mixed feature set
> comparing to the previous SoCs' ordinary MMC and eMMC controllers.
> 
> Add support for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  8:48     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:48 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 315 bytes --]

On Mon, Aug 02, 2021 at 02:22:01PM +0800, Icenowy Zheng wrote:
> Allwinner R329 have two pin controllers similar to previous Allwinner
> SoCs, PIO and R-PIO.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
@ 2021-08-18  8:48     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:48 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 315 bytes --]

On Mon, Aug 02, 2021 at 02:22:01PM +0800, Icenowy Zheng wrote:
> Allwinner R329 have two pin controllers similar to previous Allwinner
> SoCs, PIO and R-PIO.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  8:48     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:48 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 374 bytes --]

On Mon, Aug 02, 2021 at 02:22:02PM +0800, Icenowy Zheng wrote:
> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
> 
> This patch adds support for the CPUX domain pin controller.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
@ 2021-08-18  8:48     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:48 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 374 bytes --]

On Mon, Aug 02, 2021 at 02:22:02PM +0800, Icenowy Zheng wrote:
> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
> 
> This patch adds support for the CPUX domain pin controller.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  8:50     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:50 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 414 bytes --]

On Mon, Aug 02, 2021 at 02:22:05PM +0800, Icenowy Zheng wrote:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

The driver looks good, the title has a typo though (sunxi=ng vs sunxi-ng)

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
@ 2021-08-18  8:50     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:50 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 414 bytes --]

On Mon, Aug 02, 2021 at 02:22:05PM +0800, Icenowy Zheng wrote:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

The driver looks good, the title has a typo though (sunxi=ng vs sunxi-ng)

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 08/17] pinctrl: sunxi: add support for R329 R-PIO pin controller
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  8:52     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:52 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 274 bytes --]

On Mon, Aug 02, 2021 at 02:22:03PM +0800, Icenowy Zheng wrote:
> Allwinner R320 SoC has a pin controller in the CPUS power domain.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 08/17] pinctrl: sunxi: add support for R329 R-PIO pin controller
@ 2021-08-18  8:52     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  8:52 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 274 bytes --]

On Mon, Aug 02, 2021 at 02:22:03PM +0800, Icenowy Zheng wrote:
> Allwinner R320 SoC has a pin controller in the CPUS power domain.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  9:01     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  9:01 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4202 bytes --]

On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
> Allwinner R329 is a new SoC focused on smart audio devices.
> 
> Add a DTSI file for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
>  1 file changed, 244 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> 
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> new file mode 100644
> index 000000000000..bfefa2b734b0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +// Copyright (c) 2021 Sipeed
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +/ {
> +	interrupt-parent = <&gic>;
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@0 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <0>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu1: cpu@1 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <1>;
> +			enable-method = "psci";
> +		};
> +	};
> +
> +	osc24M: osc24M_clk {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "osc24M";
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		arm,no-tick-in-suspend;
> +		interrupts = <GIC_PPI 13
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 14
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 11
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 10
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
> +	};
> +
> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +		pio: pinctrl@2000400 {
> +			compatible = "allwinner,sun50i-r329-pinctrl";
> +			reg = <0x02000400 0x400>;
> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
> +			clock-names = "apb", "hosc", "losc";
> +			gpio-controller;
> +			#gpio-cells = <3>;
> +			interrupt-controller;
> +			#interrupt-cells = <3>;
> +
> +			uart0_pb_pins: uart0-pb-pins {
> +				pins = "PB4", "PB5";
> +				function = "uart0";
> +			};
> +
> +			mmc0_pf_pins: mmc0-pf-pins {
> +				pins = "PF0", "PF1", "PF2",
> +				       "PF3", "PF4", "PF5";
> +				function = "mmc0";
> +			};
> +
> +			mmc1_clk_pg0: mmc1-clk-pg0 {
> +				pins = "PG0";
> +				function = "mmc1_clk";
> +			};

Argh, of course it was bound to happen :)

Make sure your DT pass validation though, all your mmc1 node names will report errors.

> +
> +			mmc1_cmd_pg1: mmc1-clk-pg1 {

s/clk/cmd/ ?

> +				pins = "PG1";
> +				function = "mmc1_cmd";
> +			};
> +
> +			mmc1_d0_pg2: mmc1-clk-pg2 {

s/clk/d0/

> +				pins = "PG2";
> +				function = "mmc1_d0";
> +			};
> +
> +			mmc1_d1_pg3: mmc1-clk-pg3 {

s/clk/d1/

> +				pins = "PG3";
> +				function = "mmc1_d1";
> +			};
> +
> +			mmc1_d2_pg4: mmc1-clk-pg4 {

s/clk/d2/

> +				pins = "PG4";
> +				function = "mmc1_d2";
> +			};
> +
> +			mmc1_d3_pg5: mmc1-clk-pg5 {

s/clk/d3/

> +				pins = "PG5";
> +				function = "mmc1_d3";
> +			};
> +		};
> +
> +		ccu: clock@2001000 {
> +			compatible = "allwinner,sun50i-r329-ccu";
> +			reg = <0x02001000 0x1000>;
> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
> +			clock-names = "hosc", "losc", "iosc";

Do we have a clock tree for the RTC? Is it the same than the H616?

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
@ 2021-08-18  9:01     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  9:01 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 4202 bytes --]

On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
> Allwinner R329 is a new SoC focused on smart audio devices.
> 
> Add a DTSI file for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
>  1 file changed, 244 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> 
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> new file mode 100644
> index 000000000000..bfefa2b734b0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +// Copyright (c) 2021 Sipeed
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +/ {
> +	interrupt-parent = <&gic>;
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@0 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <0>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu1: cpu@1 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <1>;
> +			enable-method = "psci";
> +		};
> +	};
> +
> +	osc24M: osc24M_clk {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "osc24M";
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		arm,no-tick-in-suspend;
> +		interrupts = <GIC_PPI 13
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 14
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 11
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 10
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
> +	};
> +
> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +		pio: pinctrl@2000400 {
> +			compatible = "allwinner,sun50i-r329-pinctrl";
> +			reg = <0x02000400 0x400>;
> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
> +			clock-names = "apb", "hosc", "losc";
> +			gpio-controller;
> +			#gpio-cells = <3>;
> +			interrupt-controller;
> +			#interrupt-cells = <3>;
> +
> +			uart0_pb_pins: uart0-pb-pins {
> +				pins = "PB4", "PB5";
> +				function = "uart0";
> +			};
> +
> +			mmc0_pf_pins: mmc0-pf-pins {
> +				pins = "PF0", "PF1", "PF2",
> +				       "PF3", "PF4", "PF5";
> +				function = "mmc0";
> +			};
> +
> +			mmc1_clk_pg0: mmc1-clk-pg0 {
> +				pins = "PG0";
> +				function = "mmc1_clk";
> +			};

Argh, of course it was bound to happen :)

Make sure your DT pass validation though, all your mmc1 node names will report errors.

> +
> +			mmc1_cmd_pg1: mmc1-clk-pg1 {

s/clk/cmd/ ?

> +				pins = "PG1";
> +				function = "mmc1_cmd";
> +			};
> +
> +			mmc1_d0_pg2: mmc1-clk-pg2 {

s/clk/d0/

> +				pins = "PG2";
> +				function = "mmc1_d0";
> +			};
> +
> +			mmc1_d1_pg3: mmc1-clk-pg3 {

s/clk/d1/

> +				pins = "PG3";
> +				function = "mmc1_d1";
> +			};
> +
> +			mmc1_d2_pg4: mmc1-clk-pg4 {

s/clk/d2/

> +				pins = "PG4";
> +				function = "mmc1_d2";
> +			};
> +
> +			mmc1_d3_pg5: mmc1-clk-pg5 {

s/clk/d3/

> +				pins = "PG5";
> +				function = "mmc1_d3";
> +			};
> +		};
> +
> +		ccu: clock@2001000 {
> +			compatible = "allwinner,sun50i-r329-ccu";
> +			reg = <0x02001000 0x1000>;
> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
> +			clock-names = "hosc", "losc", "iosc";

Do we have a clock tree for the RTC? Is it the same than the H616?

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 14/17] dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-18  9:03     ` Maxime Ripard
  -1 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  9:03 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 981 bytes --]

On Mon, Aug 02, 2021 at 02:22:09PM +0800, Icenowy Zheng wrote:
> Sipeed MaixSense is an Allwinner R329 development kit based on Maix IIA
> SoM.
> 
> Add compatible strings for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
> index 889128acf49a..bce306908eff 100644
> --- a/Documentation/devicetree/bindings/arm/sunxi.yaml
> +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
> @@ -444,6 +444,12 @@ properties:
>            - const: haoyu,a10-marsboard
>            - const: allwinner,sun4i-a10
>  
> +      - description: Sipeed MaixSense
> +        items:
> +          - const: sipeed,maixsense
> +          - const: sipeed,maix-iia
> +          - const: allwinner,sun50i-r329
> +

This should be ordered

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 14/17] dt-bindings: arm: sunxi: add compatible strings for Sipeed MaixSense
@ 2021-08-18  9:03     ` Maxime Ripard
  0 siblings, 0 replies; 112+ messages in thread
From: Maxime Ripard @ 2021-08-18  9:03 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 981 bytes --]

On Mon, Aug 02, 2021 at 02:22:09PM +0800, Icenowy Zheng wrote:
> Sipeed MaixSense is an Allwinner R329 development kit based on Maix IIA
> SoM.
> 
> Add compatible strings for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
> index 889128acf49a..bce306908eff 100644
> --- a/Documentation/devicetree/bindings/arm/sunxi.yaml
> +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
> @@ -444,6 +444,12 @@ properties:
>            - const: haoyu,a10-marsboard
>            - const: allwinner,sun4i-a10
>  
> +      - description: Sipeed MaixSense
> +        items:
> +          - const: sipeed,maixsense
> +          - const: sipeed,maix-iia
> +          - const: allwinner,sun50i-r329
> +

This should be ordered

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
  2021-08-18  9:01     ` Maxime Ripard
@ 2021-08-18  9:15       ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-18  9:15 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel



于 2021年8月18日 GMT+08:00 下午5:01:39, Maxime Ripard <maxime@cerno.tech> 写到:
>On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
>> Allwinner R329 is a new SoC focused on smart audio devices.
>> 
>> Add a DTSI file for it.
>> 
>> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
>> ---
>>  .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
>>  1 file changed, 244 insertions(+)
>>  create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
>> 
>> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
>> new file mode 100644
>> index 000000000000..bfefa2b734b0
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
>> @@ -0,0 +1,244 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +// Copyright (c) 2021 Sipeed
>> +
>> +#include <dt-bindings/interrupt-controller/arm-gic.h>
>> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
>> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
>> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
>> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
>> +
>> +/ {
>> +	interrupt-parent = <&gic>;
>> +	#address-cells = <1>;
>> +	#size-cells = <1>;
>> +
>> +	cpus {
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		cpu0: cpu@0 {
>> +			compatible = "arm,cortex-a53";
>> +			device_type = "cpu";
>> +			reg = <0>;
>> +			enable-method = "psci";
>> +		};
>> +
>> +		cpu1: cpu@1 {
>> +			compatible = "arm,cortex-a53";
>> +			device_type = "cpu";
>> +			reg = <1>;
>> +			enable-method = "psci";
>> +		};
>> +	};
>> +
>> +	osc24M: osc24M_clk {
>> +		#clock-cells = <0>;
>> +		compatible = "fixed-clock";
>> +		clock-frequency = <24000000>;
>> +		clock-output-names = "osc24M";
>> +	};
>> +
>> +	psci {
>> +		compatible = "arm,psci-0.2";
>> +		method = "smc";
>> +	};
>> +
>> +	timer {
>> +		compatible = "arm,armv8-timer";
>> +		arm,no-tick-in-suspend;
>> +		interrupts = <GIC_PPI 13
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
>> +			     <GIC_PPI 14
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
>> +			     <GIC_PPI 11
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
>> +			     <GIC_PPI 10
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
>> +	};
>> +
>> +	soc {
>> +		compatible = "simple-bus";
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		ranges;
>> +
>> +		pio: pinctrl@2000400 {
>> +			compatible = "allwinner,sun50i-r329-pinctrl";
>> +			reg = <0x02000400 0x400>;
>> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
>> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
>> +				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
>> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
>> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
>> +			clock-names = "apb", "hosc", "losc";
>> +			gpio-controller;
>> +			#gpio-cells = <3>;
>> +			interrupt-controller;
>> +			#interrupt-cells = <3>;
>> +
>> +			uart0_pb_pins: uart0-pb-pins {
>> +				pins = "PB4", "PB5";
>> +				function = "uart0";
>> +			};
>> +
>> +			mmc0_pf_pins: mmc0-pf-pins {
>> +				pins = "PF0", "PF1", "PF2",
>> +				       "PF3", "PF4", "PF5";
>> +				function = "mmc0";
>> +			};
>> +
>> +			mmc1_clk_pg0: mmc1-clk-pg0 {
>> +				pins = "PG0";
>> +				function = "mmc1_clk";
>> +			};
>
>Argh, of course it was bound to happen :)
>
>Make sure your DT pass validation though, all your mmc1 node names will report errors.
>
>> +
>> +			mmc1_cmd_pg1: mmc1-clk-pg1 {
>
>s/clk/cmd/ ?
>
>> +				pins = "PG1";
>> +				function = "mmc1_cmd";
>> +			};
>> +
>> +			mmc1_d0_pg2: mmc1-clk-pg2 {
>
>s/clk/d0/
>
>> +				pins = "PG2";
>> +				function = "mmc1_d0";
>> +			};
>> +
>> +			mmc1_d1_pg3: mmc1-clk-pg3 {
>
>s/clk/d1/
>
>> +				pins = "PG3";
>> +				function = "mmc1_d1";
>> +			};
>> +
>> +			mmc1_d2_pg4: mmc1-clk-pg4 {
>
>s/clk/d2/
>
>> +				pins = "PG4";
>> +				function = "mmc1_d2";
>> +			};
>> +
>> +			mmc1_d3_pg5: mmc1-clk-pg5 {
>
>s/clk/d3/
>
>> +				pins = "PG5";
>> +				function = "mmc1_d3";
>> +			};
>> +		};
>> +
>> +		ccu: clock@2001000 {
>> +			compatible = "allwinner,sun50i-r329-ccu";
>> +			reg = <0x02001000 0x1000>;
>> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
>> +			clock-names = "hosc", "losc", "iosc";
>
>Do we have a clock tree for the RTC? Is it the same than the H616?

Nope, it's the same with H6 because of external LOSC crystal is
possible. (Although production M2A SoMs has it NC for cost control.)

What's the same between H616 and R329 is linear day storage of the timekeeping
part, not the clock part.

>
>Maxime

-- 
使用 K-9 Mail 发送自我的Android设备。

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
@ 2021-08-18  9:15       ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-18  9:15 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, Samuel Holland,
	devicetree, linux-arm-kernel, linux-sunxi, linux-kernel



于 2021年8月18日 GMT+08:00 下午5:01:39, Maxime Ripard <maxime@cerno.tech> 写到:
>On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
>> Allwinner R329 is a new SoC focused on smart audio devices.
>> 
>> Add a DTSI file for it.
>> 
>> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
>> ---
>>  .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
>>  1 file changed, 244 insertions(+)
>>  create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
>> 
>> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
>> new file mode 100644
>> index 000000000000..bfefa2b734b0
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
>> @@ -0,0 +1,244 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +// Copyright (c) 2021 Sipeed
>> +
>> +#include <dt-bindings/interrupt-controller/arm-gic.h>
>> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
>> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
>> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
>> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
>> +
>> +/ {
>> +	interrupt-parent = <&gic>;
>> +	#address-cells = <1>;
>> +	#size-cells = <1>;
>> +
>> +	cpus {
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		cpu0: cpu@0 {
>> +			compatible = "arm,cortex-a53";
>> +			device_type = "cpu";
>> +			reg = <0>;
>> +			enable-method = "psci";
>> +		};
>> +
>> +		cpu1: cpu@1 {
>> +			compatible = "arm,cortex-a53";
>> +			device_type = "cpu";
>> +			reg = <1>;
>> +			enable-method = "psci";
>> +		};
>> +	};
>> +
>> +	osc24M: osc24M_clk {
>> +		#clock-cells = <0>;
>> +		compatible = "fixed-clock";
>> +		clock-frequency = <24000000>;
>> +		clock-output-names = "osc24M";
>> +	};
>> +
>> +	psci {
>> +		compatible = "arm,psci-0.2";
>> +		method = "smc";
>> +	};
>> +
>> +	timer {
>> +		compatible = "arm,armv8-timer";
>> +		arm,no-tick-in-suspend;
>> +		interrupts = <GIC_PPI 13
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
>> +			     <GIC_PPI 14
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
>> +			     <GIC_PPI 11
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
>> +			     <GIC_PPI 10
>> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
>> +	};
>> +
>> +	soc {
>> +		compatible = "simple-bus";
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		ranges;
>> +
>> +		pio: pinctrl@2000400 {
>> +			compatible = "allwinner,sun50i-r329-pinctrl";
>> +			reg = <0x02000400 0x400>;
>> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
>> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
>> +				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
>> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
>> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
>> +			clock-names = "apb", "hosc", "losc";
>> +			gpio-controller;
>> +			#gpio-cells = <3>;
>> +			interrupt-controller;
>> +			#interrupt-cells = <3>;
>> +
>> +			uart0_pb_pins: uart0-pb-pins {
>> +				pins = "PB4", "PB5";
>> +				function = "uart0";
>> +			};
>> +
>> +			mmc0_pf_pins: mmc0-pf-pins {
>> +				pins = "PF0", "PF1", "PF2",
>> +				       "PF3", "PF4", "PF5";
>> +				function = "mmc0";
>> +			};
>> +
>> +			mmc1_clk_pg0: mmc1-clk-pg0 {
>> +				pins = "PG0";
>> +				function = "mmc1_clk";
>> +			};
>
>Argh, of course it was bound to happen :)
>
>Make sure your DT pass validation though, all your mmc1 node names will report errors.
>
>> +
>> +			mmc1_cmd_pg1: mmc1-clk-pg1 {
>
>s/clk/cmd/ ?
>
>> +				pins = "PG1";
>> +				function = "mmc1_cmd";
>> +			};
>> +
>> +			mmc1_d0_pg2: mmc1-clk-pg2 {
>
>s/clk/d0/
>
>> +				pins = "PG2";
>> +				function = "mmc1_d0";
>> +			};
>> +
>> +			mmc1_d1_pg3: mmc1-clk-pg3 {
>
>s/clk/d1/
>
>> +				pins = "PG3";
>> +				function = "mmc1_d1";
>> +			};
>> +
>> +			mmc1_d2_pg4: mmc1-clk-pg4 {
>
>s/clk/d2/
>
>> +				pins = "PG4";
>> +				function = "mmc1_d2";
>> +			};
>> +
>> +			mmc1_d3_pg5: mmc1-clk-pg5 {
>
>s/clk/d3/
>
>> +				pins = "PG5";
>> +				function = "mmc1_d3";
>> +			};
>> +		};
>> +
>> +		ccu: clock@2001000 {
>> +			compatible = "allwinner,sun50i-r329-ccu";
>> +			reg = <0x02001000 0x1000>;
>> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
>> +			clock-names = "hosc", "losc", "iosc";
>
>Do we have a clock tree for the RTC? Is it the same than the H616?

Nope, it's the same with H6 because of external LOSC crystal is
possible. (Although production M2A SoMs has it NC for cost control.)

What's the same between H616 and R329 is linear day storage of the timekeeping
part, not the clock part.

>
>Maxime

-- 
使用 K-9 Mail 发送自我的Android设备。

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
  2021-08-18  9:15       ` Icenowy Zheng
@ 2021-08-19  2:32         ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  2:32 UTC (permalink / raw)
  To: Icenowy Zheng, Maxime Ripard
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel

On 8/18/21 4:15 AM, Icenowy Zheng wrote:
> 于 2021年8月18日 GMT+08:00 下午5:01:39, Maxime Ripard <maxime@cerno.tech> 写到:
>> On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
>>> +		ccu: clock@2001000 {
>>> +			compatible = "allwinner,sun50i-r329-ccu";
>>> +			reg = <0x02001000 0x1000>;
>>> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
>>> +			clock-names = "hosc", "losc", "iosc";
>>
>> Do we have a clock tree for the RTC? Is it the same than the H616?
> 
> Nope, it's the same with H6 because of external LOSC crystal is
> possible. (Although production M2A SoMs has it NC for cost control.)

It is not the same as the H6, either. The clock tree _is_ identical to the D1,
which has three diagrams on pages 363-364 of its user manual here:

https://dl.linux-sunxi.org/D1/D1_User_Manual_V0.1_Draft_Version.pdf

Compared to the H6, the R329/D1:
 - Loses the LOSC calibration circuit
 - Gains a third mux input for LOSC (not external 32k) to fanout
 - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
 - Gains an SPI bus clock input divided from the PRCM AHB

Compared to the H616, the R329/D1:
 - Has an external 32k crystal input
   - Gains the IOSC vs. external 32k crystal mux for LOSC
   - Switches fanout mux input #1 from pll_periph0/N to external 32k
 - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
 - Gains an SPI bus clock input divided from the PRCM AHB

So the R329/D1 RTC has three inputs:
 - SPI clock from PRCM
 - 24 MHz DCXO crystal
 - 32 kHz external crystal (optional)

and four outputs:
 - 16 MHz "IOSC" RC oscillator
 - 32 kHz "LOSC"
 - ~1 kHz for RTC timekeeping
 - 32 kHz fanout

(Arguably, since the 24 MHz DCXO can be turned on/off from the RTC registers, it
should be an "output" and not an "input".)

Regards,
Samuel

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
@ 2021-08-19  2:32         ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  2:32 UTC (permalink / raw)
  To: Icenowy Zheng, Maxime Ripard
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel

On 8/18/21 4:15 AM, Icenowy Zheng wrote:
> 于 2021年8月18日 GMT+08:00 下午5:01:39, Maxime Ripard <maxime@cerno.tech> 写到:
>> On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
>>> +		ccu: clock@2001000 {
>>> +			compatible = "allwinner,sun50i-r329-ccu";
>>> +			reg = <0x02001000 0x1000>;
>>> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
>>> +			clock-names = "hosc", "losc", "iosc";
>>
>> Do we have a clock tree for the RTC? Is it the same than the H616?
> 
> Nope, it's the same with H6 because of external LOSC crystal is
> possible. (Although production M2A SoMs has it NC for cost control.)

It is not the same as the H6, either. The clock tree _is_ identical to the D1,
which has three diagrams on pages 363-364 of its user manual here:

https://dl.linux-sunxi.org/D1/D1_User_Manual_V0.1_Draft_Version.pdf

Compared to the H6, the R329/D1:
 - Loses the LOSC calibration circuit
 - Gains a third mux input for LOSC (not external 32k) to fanout
 - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
 - Gains an SPI bus clock input divided from the PRCM AHB

Compared to the H616, the R329/D1:
 - Has an external 32k crystal input
   - Gains the IOSC vs. external 32k crystal mux for LOSC
   - Switches fanout mux input #1 from pll_periph0/N to external 32k
 - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
 - Gains an SPI bus clock input divided from the PRCM AHB

So the R329/D1 RTC has three inputs:
 - SPI clock from PRCM
 - 24 MHz DCXO crystal
 - 32 kHz external crystal (optional)

and four outputs:
 - 16 MHz "IOSC" RC oscillator
 - 32 kHz "LOSC"
 - ~1 kHz for RTC timekeeping
 - 32 kHz fanout

(Arguably, since the 24 MHz DCXO can be turned on/off from the RTC registers, it
should be an "output" and not an "input".)

Regards,
Samuel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-19  2:40     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  2:40 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 have two pin controllers similar to previous Allwinner
> SoCs, PIO and R-PIO.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml         | 4 ++++
>  1 file changed, 4 insertions(+)

Reviewed-by: Samuel Holland <samuel@sholland.org>

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

* Re: [PATCH 06/17] dt-bindings: pinctrl: document Allwinner R329 PIO and R-PIO
@ 2021-08-19  2:40     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  2:40 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 have two pin controllers similar to previous Allwinner
> SoCs, PIO and R-PIO.
> 
> Add compatible strings for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml         | 4 ++++
>  1 file changed, 4 insertions(+)

Reviewed-by: Samuel Holland <samuel@sholland.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-19  3:09     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  3:09 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
> 
> This patch adds support for the CPUX domain pin controller.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/pinctrl/sunxi/Kconfig               |   5 +
>  drivers/pinctrl/sunxi/Makefile              |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c | 410 ++++++++++++++++++++
>  3 files changed, 416 insertions(+)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index 33751a6a0757..c662e8b1b351 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -129,4 +129,9 @@ config PINCTRL_SUN50I_H616_R
>  	default ARM64 && ARCH_SUNXI
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN50I_R329
> +	bool "Support for the Allwinner R329 PIO"
> +	default ARM64 && ARCH_SUNXI
> +	select PINCTRL_SUNXI
> +
>  endif
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index d3440c42b9d6..e33f7c5f1ff9 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -25,5 +25,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
> +obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
> new file mode 100644
> index 000000000000..742f437ec0b6
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
> @@ -0,0 +1,410 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner R329 SoC pinctrl driver.
> + *
> + * Copyright (C) 2021 Sipeed
> + * based on the H616 pinctrl driver
> + *   Copyright (C) 2020 Arm Ltd.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +static const struct sunxi_desc_pin r329_pins[] = {
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM0 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
> +		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PB_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM1 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
> +		  SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PB_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM2 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
> +		  SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PB_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM3 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
> +		  SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PB_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart0"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM4 */
> +		  SUNXI_FUNCTION(0x4, "i2s0_dout0"),
> +		  SUNXI_FUNCTION(0x5, "i2s0_din1"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PB_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart0"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM5 */
> +		  SUNXI_FUNCTION(0x4, "i2s0_dout1"),
> +		  SUNXI_FUNCTION(0x5, "i2s0_din0"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PB_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "ir"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM6 */
> +		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT2 */
> +		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PB_EINT6 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "ir"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM7 */
> +		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT3 */
> +		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PB_EINT7 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "ir_tx"),
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM8 */
> +		  SUNXI_FUNCTION(0x4, "ir_rx"),
> +		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PB_EINT8 */
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* RB0 */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CLK */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* CS */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* RE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CMD */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* MISO */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE0 */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D2 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* WP */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* CLE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D1 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* MOSI */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* ALE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D0 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* CLK */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* WE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D3 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* HOLD */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ0 */
> +		  SUNXI_FUNCTION(0x3, "mmc0")),		/* RST */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ1 */
> +		  SUNXI_FUNCTION(0x5, "boot_sel")),
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ7 */

Please be consistent between "nand" and "nand0". "nand0" looks like it is much
more common.

> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPEN */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D1 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PF_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ6 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPPP */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D0 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PF_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ5 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* PWREN */
> +		  SUNXI_FUNCTION(0x4, "uart"),		/* TX */

Should be "uart0".

> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PF_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ4 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* CLK */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CMD */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PF_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQS */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* DATA */
> +		  SUNXI_FUNCTION(0x4, "uart"),		/* RX */

"uart0" here as well.

> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D3 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PF_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ2 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* RST */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D2 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PF_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ1 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* DET */
> +		  SUNXI_FUNCTION(0x4, "spdif_in"),
> +		  SUNXI_FUNCTION(0x5, "spdif_out"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PF_EINT6 */
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_clk"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d2"),
> +		  /* 0x4 is also mmc1_d2 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PG_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_cmd"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d3"),
> +		  SUNXI_FUNCTION(0x4, "mmc1_clk"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PG_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d0"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_cmd"),
> +		  SUNXI_FUNCTION(0x4, "mmc1_d3"),

Missing function 5 "pll".

> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PG_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d1"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_clk"),
> +		  /* 0x4 is also mmc1_d1 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PG_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d2"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d0"),
> +		  /* 0x4 is also mmc1_d0 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PG_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d3"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d1"),
> +		  SUNXI_FUNCTION(0x4, "mmc1_cmd"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PG_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PG_EINT6 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PG_EINT7 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PG_EINT8 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* WP/DBI-TE */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PG_EINT9 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
> +		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */

Should be function 4.

> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PG_EINT10 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "i2s1"),		/* LRCK */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* CS/DBI-CSX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PG_EINT11 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* CLK/DBI-SCLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PG_EINT12 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "i2s1_dout0"),
> +		  SUNXI_FUNCTION(0x4, "i2s1_din1"),
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI/DBI-SDO */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PG_EINT13 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "i2s1_dout1"),
> +		  SUNXI_FUNCTION(0x4, "i2s1_din0"),
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PG_EINT14 */
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* CS/DBI-CSX */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM0 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 0)),	/* PH_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* CLK/DBI-SCLK */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM1 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 1)),	/* PH_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
> +		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI/DBI-SDO */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 2)),	/* PH_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
> +		  SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 3)),	/* PH_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "spi1_cs"),	/* CS/DBI-CSX */
> +		  SUNXI_FUNCTION(0x4, "spi1_hold"),	/* HOLD/DBI-DCX/DBI-WRX */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM2 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 4)),	/* PH_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "spi1_clk"),	/* CLK/DBI-SCLK */
> +		  SUNXI_FUNCTION(0x4, "spi1_wp"),	/* WP/DBI-TE */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM3 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 5)),	/* PH_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* MOSI/SPI-DBO */
> +		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM4 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)),	/* PH_EINT6 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
> +		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM5 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)),	/* PH_EINT7 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* WP/DBI-TE */
> +		  SUNXI_FUNCTION(0x4, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */

You have PH8 and PH9 functions 2 through 5 swapped.

And I won't be surprised if I missed something too :)

Regards,
Samuel

> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)),	/* PH_EINT8 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
> +		  SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)),	/* PH_EINT9 */
> +};
> +static const unsigned int r329_irq_bank_map[] = { 1, 5, 6, 7 };
> +
> +static const struct sunxi_pinctrl_desc r329_pinctrl_data = {
> +	.pins = r329_pins,
> +	.npins = ARRAY_SIZE(r329_pins),
> +	.irq_banks = ARRAY_SIZE(r329_irq_bank_map),
> +	.irq_bank_map = r329_irq_bank_map,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +};
> +
> +static int r329_pinctrl_probe(struct platform_device *pdev)
> +{
> +	return sunxi_pinctrl_init(pdev, &r329_pinctrl_data);
> +}
> +
> +static const struct of_device_id r329_pinctrl_match[] = {
> +	{ .compatible = "allwinner,sun50i-r329-pinctrl", },
> +	{}
> +};
> +
> +static struct platform_driver r329_pinctrl_driver = {
> +	.probe	= r329_pinctrl_probe,
> +	.driver	= {
> +		.name		= "sun50i-r329-pinctrl",
> +		.of_match_table	= r329_pinctrl_match,
> +	},
> +};
> +builtin_platform_driver(r329_pinctrl_driver);
> 


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

* Re: [PATCH 07/17] pinctrl: sunxi: add support for R329 CPUX pin controller
@ 2021-08-19  3:09     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  3:09 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 SoC has two pin controllers similar to ones on previous
> SoCs, one in CPUX power domain and another in CPUS.
> 
> This patch adds support for the CPUX domain pin controller.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/pinctrl/sunxi/Kconfig               |   5 +
>  drivers/pinctrl/sunxi/Makefile              |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c | 410 ++++++++++++++++++++
>  3 files changed, 416 insertions(+)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index 33751a6a0757..c662e8b1b351 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -129,4 +129,9 @@ config PINCTRL_SUN50I_H616_R
>  	default ARM64 && ARCH_SUNXI
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN50I_R329
> +	bool "Support for the Allwinner R329 PIO"
> +	default ARM64 && ARCH_SUNXI
> +	select PINCTRL_SUNXI
> +
>  endif
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index d3440c42b9d6..e33f7c5f1ff9 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -25,5 +25,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
> +obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
> new file mode 100644
> index 000000000000..742f437ec0b6
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329.c
> @@ -0,0 +1,410 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner R329 SoC pinctrl driver.
> + *
> + * Copyright (C) 2021 Sipeed
> + * based on the H616 pinctrl driver
> + *   Copyright (C) 2020 Arm Ltd.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +static const struct sunxi_desc_pin r329_pins[] = {
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM0 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
> +		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PB_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM1 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
> +		  SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PB_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM2 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
> +		  SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PB_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM3 */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
> +		  SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PB_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart0"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM4 */
> +		  SUNXI_FUNCTION(0x4, "i2s0_dout0"),
> +		  SUNXI_FUNCTION(0x5, "i2s0_din1"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PB_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart0"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM5 */
> +		  SUNXI_FUNCTION(0x4, "i2s0_dout1"),
> +		  SUNXI_FUNCTION(0x5, "i2s0_din0"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PB_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "ir"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM6 */
> +		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT2 */
> +		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PB_EINT6 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "ir"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM7 */
> +		  SUNXI_FUNCTION(0x4, "i2s0"),		/* DOUT3 */
> +		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PB_EINT7 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "ir_tx"),
> +		  SUNXI_FUNCTION(0x3, "pwm"),		/* PWM8 */
> +		  SUNXI_FUNCTION(0x4, "ir_rx"),
> +		  SUNXI_FUNCTION(0x5, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PB_EINT8 */
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* RB0 */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CLK */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* CS */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* RE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* CMD */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* MISO */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE0 */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D2 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* WP */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* CLE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D1 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* MOSI */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* ALE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D0 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* CLK */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* WE */
> +		  SUNXI_FUNCTION(0x3, "mmc0"),		/* D3 */
> +		  SUNXI_FUNCTION(0x4, "spi0")),		/* HOLD */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ0 */
> +		  SUNXI_FUNCTION(0x3, "mmc0")),		/* RST */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ1 */
> +		  SUNXI_FUNCTION(0x5, "boot_sel")),
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ7 */

Please be consistent between "nand" and "nand0". "nand0" looks like it is much
more common.

> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPEN */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* MS */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D1 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PF_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ6 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* VPPPP */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DI */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D0 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PF_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ5 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* PWREN */
> +		  SUNXI_FUNCTION(0x4, "uart"),		/* TX */

Should be "uart0".

> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PF_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ4 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* CLK */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* DO */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* CMD */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PF_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQS */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* DATA */
> +		  SUNXI_FUNCTION(0x4, "uart"),		/* RX */

"uart0" here as well.

> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D3 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PF_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ2 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* RST */
> +		  SUNXI_FUNCTION(0x4, "jtag"),		/* CK */
> +		  SUNXI_FUNCTION(0x5, "mmc0"),		/* D2 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PF_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ1 */
> +		  SUNXI_FUNCTION(0x3, "sim0"),		/* DET */
> +		  SUNXI_FUNCTION(0x4, "spdif_in"),
> +		  SUNXI_FUNCTION(0x5, "spdif_out"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PF_EINT6 */
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_clk"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d2"),
> +		  /* 0x4 is also mmc1_d2 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PG_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_cmd"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d3"),
> +		  SUNXI_FUNCTION(0x4, "mmc1_clk"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PG_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d0"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_cmd"),
> +		  SUNXI_FUNCTION(0x4, "mmc1_d3"),

Missing function 5 "pll".

> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PG_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d1"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_clk"),
> +		  /* 0x4 is also mmc1_d1 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PG_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d2"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d0"),
> +		  /* 0x4 is also mmc1_d0 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PG_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "mmc1_d3"),
> +		  SUNXI_FUNCTION(0x3, "mmc1_d1"),
> +		  SUNXI_FUNCTION(0x4, "mmc1_cmd"),
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PG_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PG_EINT6 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PG_EINT7 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PG_EINT8 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* WP/DBI-TE */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PG_EINT9 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
> +		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */

Should be function 4.

> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PG_EINT10 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "i2s1"),		/* LRCK */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* CS/DBI-CSX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PG_EINT11 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* CLK/DBI-SCLK */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PG_EINT12 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "i2s1_dout0"),
> +		  SUNXI_FUNCTION(0x4, "i2s1_din1"),
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI/DBI-SDO */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PG_EINT13 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "i2s1_dout1"),
> +		  SUNXI_FUNCTION(0x4, "i2s1_din0"),
> +		  SUNXI_FUNCTION(0x5, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PG_EINT14 */
> +	/* Hole */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* CS/DBI-CSX */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM0 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 0)),	/* PH_EINT0 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* CLK/DBI-SCLK */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM1 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 1)),	/* PH_EINT1 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
> +		  SUNXI_FUNCTION(0x3, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI/DBI-SDO */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 2)),	/* PH_EINT2 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
> +		  SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
> +		  SUNXI_FUNCTION(0x4, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 3)),	/* PH_EINT3 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* TX */
> +		  SUNXI_FUNCTION(0x3, "spi1_cs"),	/* CS/DBI-CSX */
> +		  SUNXI_FUNCTION(0x4, "spi1_hold"),	/* HOLD/DBI-DCX/DBI-WRX */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM2 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 4)),	/* PH_EINT4 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RX */
> +		  SUNXI_FUNCTION(0x3, "spi1_clk"),	/* CLK/DBI-SCLK */
> +		  SUNXI_FUNCTION(0x4, "spi1_wp"),	/* WP/DBI-TE */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM3 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 5)),	/* PH_EINT5 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* RTS */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* MOSI/SPI-DBO */
> +		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM4 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)),	/* PH_EINT6 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "uart3"),		/* CTS */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* MISO/DBI-SDI/DBI-TE/DBI-DCX */
> +		  SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		  SUNXI_FUNCTION(0x5, "pwm"),		/* PWM5 */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)),	/* PH_EINT7 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* WP/DBI-TE */
> +		  SUNXI_FUNCTION(0x4, "ledc"),		/* DO */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* TX */

You have PH8 and PH9 functions 2 through 5 swapped.

And I won't be surprised if I missed something too :)

Regards,
Samuel

> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)),	/* PH_EINT8 */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
> +		  SUNXI_FUNCTION(0x3, "spi1"),		/* HOLD/DBI-DCX/DBI-WRX */
> +		  SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
> +		  SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)),	/* PH_EINT9 */
> +};
> +static const unsigned int r329_irq_bank_map[] = { 1, 5, 6, 7 };
> +
> +static const struct sunxi_pinctrl_desc r329_pinctrl_data = {
> +	.pins = r329_pins,
> +	.npins = ARRAY_SIZE(r329_pins),
> +	.irq_banks = ARRAY_SIZE(r329_irq_bank_map),
> +	.irq_bank_map = r329_irq_bank_map,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +};
> +
> +static int r329_pinctrl_probe(struct platform_device *pdev)
> +{
> +	return sunxi_pinctrl_init(pdev, &r329_pinctrl_data);
> +}
> +
> +static const struct of_device_id r329_pinctrl_match[] = {
> +	{ .compatible = "allwinner,sun50i-r329-pinctrl", },
> +	{}
> +};
> +
> +static struct platform_driver r329_pinctrl_driver = {
> +	.probe	= r329_pinctrl_probe,
> +	.driver	= {
> +		.name		= "sun50i-r329-pinctrl",
> +		.of_match_table	= r329_pinctrl_match,
> +	},
> +};
> +builtin_platform_driver(r329_pinctrl_driver);
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 08/17] pinctrl: sunxi: add support for R329 R-PIO pin controller
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-19  3:22     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  3:22 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R320 SoC has a pin controller in the CPUS power domain.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/pinctrl/sunxi/Kconfig                 |   5 +
>  drivers/pinctrl/sunxi/Makefile                |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c | 292 ++++++++++++++++++
>  3 files changed, 298 insertions(+)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index c662e8b1b351..abd60ff8daec 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -134,4 +134,9 @@ config PINCTRL_SUN50I_R329
>  	default ARM64 && ARCH_SUNXI
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN50I_R329_R
> +	bool "Support for the Allwinner R329 R-PIO"
> +	default ARM64 && ARCH_SUNXI
> +	select PINCTRL_SUNXI
> +
>  endif
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index e33f7c5f1ff9..245840a7959e 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -26,5 +26,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
>  obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
> +obj-$(CONFIG_PINCTRL_SUN50I_R329_R)	+= pinctrl-sun50i-r329-r.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..dc4792c685ba
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner H616 R_PIO pin controller driver

This needs to be updated.

> + *
> + * Copyright (C) 2020 Arm Ltd.
> + * Based on former work, which is:
> + *   Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/reset.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +static const struct sunxi_desc_pin sun50i_r329_r_pins[] = {
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* LRCK */

"s_i2s0" for these would match existing drivers (and the manual).

Everything else matches the manual.

Regards,
Samuel

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

* Re: [PATCH 08/17] pinctrl: sunxi: add support for R329 R-PIO pin controller
@ 2021-08-19  3:22     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-19  3:22 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R320 SoC has a pin controller in the CPUS power domain.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/pinctrl/sunxi/Kconfig                 |   5 +
>  drivers/pinctrl/sunxi/Makefile                |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c | 292 ++++++++++++++++++
>  3 files changed, 298 insertions(+)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index c662e8b1b351..abd60ff8daec 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -134,4 +134,9 @@ config PINCTRL_SUN50I_R329
>  	default ARM64 && ARCH_SUNXI
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN50I_R329_R
> +	bool "Support for the Allwinner R329 R-PIO"
> +	default ARM64 && ARCH_SUNXI
> +	select PINCTRL_SUNXI
> +
>  endif
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index e33f7c5f1ff9..245840a7959e 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -26,5 +26,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
>  obj-$(CONFIG_PINCTRL_SUN50I_R329)	+= pinctrl-sun50i-r329.o
> +obj-$(CONFIG_PINCTRL_SUN50I_R329_R)	+= pinctrl-sun50i-r329-r.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..dc4792c685ba
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-r329-r.c
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner H616 R_PIO pin controller driver

This needs to be updated.

> + *
> + * Copyright (C) 2020 Arm Ltd.
> + * Based on former work, which is:
> + *   Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/reset.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +static const struct sunxi_desc_pin sun50i_r329_r_pins[] = {
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
> +		  SUNXI_FUNCTION(0x0, "gpio_in"),
> +		  SUNXI_FUNCTION(0x1, "gpio_out"),
> +		  SUNXI_FUNCTION(0x2, "s_i2s"),		/* LRCK */

"s_i2s0" for these would match existing drivers (and the manual).

Everything else matches the manual.

Regards,
Samuel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-20  0:55     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  0:55 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index cd46d8853876..e49b2c2fa5b7 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>  	default ARM64 && ARCH_SUNXI
>  	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_R_CCU
> +	bool "Support for the Allwinner R329 PRCM CCU"
> +	default ARM64 && ARCH_SUNXI
> +	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN4I_A10_CCU
>  	bool "Support for the Allwinner A10/A20 CCU"
>  	default MACH_SUN4I
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 96c324306d97..db338a2188fd 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)	+= ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..5413a701cb57
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Sipeed
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329-r.h"
> +
> +/*
> + * The M factor is present in the register's description, but not in the
> + * frequency formula, and it's documented as "The bit is only for
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_R329_PLL_CPUX_REG	0x1000
> +static struct ccu_mult pll_cpux_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.mult		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.common		= {
> +		.reg		= 0x1000,
> +		.hw.init	= CLK_HW_INIT("pll-cpux", "osc24M",
> +					      &ccu_mult_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +#define SUN50I_R329_PLL_PERIPH_REG	0x1010
> +static struct ccu_nm pll_periph_base_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
> +	.common		= {
> +		.reg		= 0x1010,
> +		.hw.init	= CLK_HW_INIT("pll-periph-base", "osc24M",
> +					      &ccu_nm_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-base",
> +		   0x1010, 16, 3, 0);
> +static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-periph-base",
> +		   0x1010, 20, 3, 0);

M as abbreviation for "mega" should be capitalized.

> +static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
> +			   &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +#define SUN50I_R329_PLL_AUDIO0_REG	0x1020
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> +	{ .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64 },
> +};
> +
> +static struct ccu_nm pll_audio0_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.m		= _SUNXI_CCU_DIV(1, 1),
> +	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table,
> +					 BIT(24), 0x1120, BIT(31)),
> +	.common		= {
> +		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
> +		.reg		= 0x1020,
> +		.hw.init	= CLK_HW_INIT("pll-audio0", "osc24M",
> +					      &ccu_nm_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-audio0",
> +		   0x1020, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-audio0",
> +		   0x1020, 20, 3, 0);
> +
> +/*
> + * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
> + * BSP driver always has M0 = 1 and M1 = 2 (this is also the
> + * reset value in the register).
> + *
> + * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
> + */
> +#define SUN50I_R329_PLL_AUDIO1_REG	0x1030
> +static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
> +	{ .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22 },
> +	{ .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24 },
> +	{ .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +	{ .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
> +};
> +static struct ccu_nm pll_audio1_4x_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.m		= _SUNXI_CCU_DIV(16, 6),
> +	.fixed_post_div	= 2,
> +	.sdm		= _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
> +					 BIT(24), 0x1130, BIT(31)),
> +	.common		= {
> +		.features	= CCU_FEATURE_FIXED_POSTDIV |
> +				  CCU_FEATURE_SIGMA_DELTA_MOD,
> +		.reg		= 0x1030,
> +		.hw.init	= CLK_HW_INIT("pll-audio1-4x", "osc24M",
> +					      &ccu_nm_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
> +			   &pll_audio1_4x_clk.common.hw, 2, 1,
> +			   CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
> +			   &pll_audio1_4x_clk.common.hw, 4, 1,
> +			   CLK_SET_RATE_PARENT);
> +
> +static const char * const r_bus_parents[] = { "osc24M", "osc32k", "iosc",
> +					      "pll-periph-2x",
> +					      "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents, 0x000,
> +			     0, 5,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents, 0x00c,
> +			     0, 5,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents, 0x010,
> +			     0, 5,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);

These are numbered 0 and 1 in the manual and in the BSP. Why number them
differently here?

> +
> +static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
> +		      0x0ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c, BIT(0), 0);

BSP has R_TIMER at 0x11c and R_TWD at 0x12c.

> +
> +static const char * const r_pwm_parents[] = { "osc24M", "osc32k", "iosc" };
> +static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents, 0x130,
> +			       24, 3,	/* mux */
> +			       BIT(31),	/* gate */
> +			       0);
> +
> +static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c, BIT(0), 0);
> +
> +static const char * const r_audio_parents[] = { "pll-audio0-div5", "pll-audio0-div2",
> +						"pll-audio1-1x", "pll-audio1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc", r_audio_parents, 0x140,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */

I don't think it matters much, but the audio and IR muxes are documented as
being two bits wide.

> +				  BIT(31),	/* gate */
> +				  0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac", r_audio_parents, 0x144,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
> +		      0x14c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic", r_audio_parents, 0x150,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
> +		      0x16c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s", r_audio_parents, 0x170,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
> +				  r_audio_parents, 0x174,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);

The BSP claims there is an R_I2S1 module clock at 0x178. Can you check if that
exists? And the corresponding gate/reset bits in 0x17c?

> +static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c, BIT(0), 0);

R_PPU is at 0x1ac, and R_DSP is at 0x1bc.

> +
> +static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents, 0x1c0,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
> +		      0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-apb1",
> +		      0x1ec, BIT(0), 0);

R_DSP_SRAM is at 0x1fc.

> +static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
> +		      0x20c, BIT(0), CLK_IS_CRITICAL);

Is this a workaround for the clock consumer missing from the RTC driver?

Also, there is a "PSARM" clock at 0x210 and its gate at 0x21c. I think this may
refer to the NPU from ARM China?

Finally, there is a CPUCFG gate at 0x22c. I'm not sure which CPUCFG this refers to.

> +
> +static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
> +	&pll_cpux_clk.common,
> +	&pll_periph_base_clk.common,
> +	&pll_periph_2x_clk.common,
> +	&pll_periph_800m_clk.common,
> +	&pll_audio0_clk.common,
> +	&pll_audio0_div2_clk.common,
> +	&pll_audio0_div5_clk.common,
> +	&pll_audio1_4x_clk.common,
> +	&r_ahb_clk.common,
> +	&r_apb1_clk.common,
> +	&r_apb2_clk.common,
> +	&r_bus_gpadc_clk.common,
> +	&r_bus_ths_clk.common,
> +	&r_bus_dma_clk.common,
> +	&r_pwm_clk.common,
> +	&r_bus_pwm_clk.common,
> +	&r_codec_adc_clk.common,
> +	&r_codec_dac_clk.common,
> +	&r_bus_codec_clk.common,
> +	&r_dmic_clk.common,
> +	&r_bus_dmic_clk.common,
> +	&r_bus_lradc_clk.common,
> +	&r_i2s_clk.common,
> +	&r_i2s_asrc_clk.common,
> +	&r_bus_i2s_clk.common,
> +	&r_bus_uart_clk.common,
> +	&r_bus_i2c_clk.common,
> +	&r_ir_clk.common,
> +	&r_bus_ir_clk.common,
> +	&r_bus_msgbox_clk.common,
> +	&r_bus_spinlock_clk.common,
> +	&r_bus_rtc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
> +	.hws	= {
> +		[CLK_PLL_CPUX]		= &pll_cpux_clk.common.hw,
> +		[CLK_PLL_PERIPH_BASE]	= &pll_periph_base_clk.common.hw,
> +		[CLK_PLL_PERIPH_2X]	= &pll_periph_2x_clk.common.hw,
> +		[CLK_PLL_PERIPH_800M]	= &pll_periph_800m_clk.common.hw,
> +		[CLK_PLL_PERIPH]	= &pll_periph_clk.hw,
> +		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.common.hw,
> +		[CLK_PLL_AUDIO0_DIV2]	= &pll_audio0_div2_clk.common.hw,
> +		[CLK_PLL_AUDIO0_DIV5]	= &pll_audio0_div5_clk.common.hw,
> +		[CLK_PLL_AUDIO1_4X]	= &pll_audio1_4x_clk.common.hw,
> +		[CLK_PLL_AUDIO1_2X]	= &pll_audio1_2x_clk.hw,
> +		[CLK_PLL_AUDIO1]	= &pll_audio1_clk.hw,
> +		[CLK_R_AHB]		= &r_ahb_clk.common.hw,
> +		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
> +		[CLK_R_APB2]		= &r_apb2_clk.common.hw,
> +		[CLK_R_BUS_GPADC]	= &r_bus_gpadc_clk.common.hw,
> +		[CLK_R_BUS_THS]		= &r_bus_ths_clk.common.hw,
> +		[CLK_R_BUS_DMA]		= &r_bus_dma_clk.common.hw,
> +		[CLK_R_PWM]		= &r_pwm_clk.common.hw,
> +		[CLK_R_BUS_PWM]		= &r_bus_pwm_clk.common.hw,
> +		[CLK_R_CODEC_ADC]	= &r_codec_adc_clk.common.hw,
> +		[CLK_R_CODEC_DAC]	= &r_codec_dac_clk.common.hw,
> +		[CLK_R_BUS_CODEC]	= &r_bus_codec_clk.common.hw,
> +		[CLK_R_DMIC]		= &r_dmic_clk.common.hw,
> +		[CLK_R_BUS_DMIC]	= &r_bus_dmic_clk.common.hw,
> +		[CLK_R_BUS_LRADC]	= &r_bus_lradc_clk.common.hw,
> +		[CLK_R_I2S]		= &r_i2s_clk.common.hw,
> +		[CLK_R_I2S_ASRC]	= &r_i2s_asrc_clk.common.hw,
> +		[CLK_R_BUS_I2S]		= &r_bus_i2s_clk.common.hw,
> +		[CLK_R_BUS_UART]	= &r_bus_uart_clk.common.hw,
> +		[CLK_R_BUS_I2C]		= &r_bus_i2c_clk.common.hw,
> +		[CLK_R_IR]		= &r_ir_clk.common.hw,
> +		[CLK_R_BUS_IR]		= &r_bus_ir_clk.common.hw,
> +		[CLK_R_BUS_MSGBOX]	= &r_bus_msgbox_clk.common.hw,
> +		[CLK_R_BUS_SPINLOCK]	= &r_bus_spinlock_clk.common.hw,
> +		[CLK_R_BUS_RTC]		= &r_bus_rtc_clk.common.hw,
> +	},
> +	.num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
> +	[RST_R_BUS_GPADC]	= { 0x0ec, BIT(16) },
> +	[RST_R_BUS_THS]		= { 0x0fc, BIT(16) },
> +	[RST_R_BUS_DMA]		= { 0x10c, BIT(16) },
> +	[RST_R_BUS_PWM]		= { 0x13c, BIT(16) },
> +	[RST_R_BUS_CODEC]	= { 0x14c, BIT(16) },
> +	[RST_R_BUS_DMIC]	= { 0x15c, BIT(16) },
> +	[RST_R_BUS_LRADC]	= { 0x16c, BIT(16) },
> +	[RST_R_BUS_I2S]		= { 0x17c, BIT(16) },
> +	[RST_R_BUS_UART]	= { 0x18c, BIT(16) },
> +	[RST_R_BUS_I2C]		= { 0x19c, BIT(16) },
> +	[RST_R_BUS_IR]		= { 0x1cc, BIT(16) },
> +	[RST_R_BUS_MSGBOX]	= { 0x1dc, BIT(16) },
> +	[RST_R_BUS_SPINLOCK]	= { 0x1ec, BIT(16) },
> +	[RST_R_BUS_RTC]		= { 0x20c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
> +	.ccu_clks	= sun50i_r329_r_ccu_clks,
> +	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_r_ccu_clks),
> +
> +	.hw_clks	= &sun50i_r329_r_hw_clks,
> +
> +	.resets		= sun50i_r329_r_ccu_resets,
> +	.num_resets	= ARRAY_SIZE(sun50i_r329_r_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> +	SUN50I_R329_PLL_CPUX_REG,
> +	SUN50I_R329_PLL_PERIPH_REG,
> +	SUN50I_R329_PLL_AUDIO0_REG,
> +	SUN50I_R329_PLL_AUDIO1_REG,
> +};
> +
> +static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
> +{
> +	void __iomem *reg;
> +	u32 val;
> +	int i;
> +
> +	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> +	if (IS_ERR(reg)) {
> +		pr_err("%pOF: Could not map clock registers\n", node);
> +		return;
> +	}
> +
> +	/* Enable the lock bits and the output enable bits on all PLLs */
> +	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +		val = readl(reg + pll_regs[i]);
> +		val |= BIT(29) | BIT(27);
> +		writel(val, reg + pll_regs[i]);
> +	}
> +
> +	/*
> +	 * Force the I/O dividers of PLL-AUDIO1 to reset default value
> +	 *
> +	 * See the comment before pll-audio1 definition for the reason.
> +	 */
> +
> +	val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
> +	val &= ~BIT(1);
> +	val |= BIT(0);
> +	writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
> +
> +	i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
> +	if (i)
> +		pr_err("%pOF: probing clocks fails: %d\n", node, i);
> +}
> +
> +CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
> +	       sun50i_r329_r_ccu_setup);

Please make this a platform driver. There is no particular reason why it needs
to be an early OF clock provider.

Regards,
Samuel

> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> new file mode 100644
> index 000000000000..62cf65322116
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_R_H
> +#define _CCU_SUN50I_R329_R_H
> +
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +#define CLK_PLL_CPUX		0
> +#define CLK_PLL_PERIPH_BASE	1
> +#define CLK_PLL_PERIPH_2X	2
> +#define CLK_PLL_PERIPH_800M	3
> +#define CLK_PLL_PERIPH		4
> +#define CLK_PLL_AUDIO0		5
> +#define CLK_PLL_AUDIO0_DIV2	6
> +#define CLK_PLL_AUDIO0_DIV5	7
> +#define CLK_PLL_AUDIO1_4X	8
> +#define CLK_PLL_AUDIO1_2X	9
> +#define CLK_PLL_AUDIO1		10
> +#define CLK_R_AHB		11
> +
> +/* R_APB1 exported for PIO */
> +
> +#define CLK_R_APB2		13
> +
> +/* All module / bus gate clocks exported */
> +
> +#define CLK_NUMBER	(CLK_R_BUS_RTC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_R_H */
> diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..df9bc58de5c4
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +
> +#define CLK_R_APB1		12
> +
> +#define CLK_R_BUS_GPADC		14
> +#define CLK_R_BUS_THS		15
> +#define CLK_R_BUS_DMA		16
> +#define CLK_R_PWM		17
> +#define CLK_R_BUS_PWM		18
> +#define CLK_R_CODEC_ADC		19
> +#define CLK_R_CODEC_DAC		20
> +#define CLK_R_BUS_CODEC		21
> +#define CLK_R_DMIC		22
> +#define CLK_R_BUS_DMIC		23
> +#define CLK_R_BUS_LRADC		24
> +#define CLK_R_I2S		25
> +#define CLK_R_I2S_ASRC		26
> +#define CLK_R_BUS_I2S		27
> +#define CLK_R_BUS_UART		28
> +#define CLK_R_BUS_I2C		29
> +#define CLK_R_IR		30
> +#define CLK_R_BUS_IR		31
> +#define CLK_R_BUS_MSGBOX	32
> +#define CLK_R_BUS_SPINLOCK	33
> +#define CLK_R_BUS_RTC		34
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..40644f2f21c6
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +
> +#define RST_R_BUS_GPADC		0
> +#define RST_R_BUS_THS		1
> +#define RST_R_BUS_DMA		2
> +#define RST_R_BUS_PWM		3
> +#define RST_R_BUS_CODEC		4
> +#define RST_R_BUS_DMIC		5
> +#define RST_R_BUS_LRADC		6
> +#define RST_R_BUS_I2S		7
> +#define RST_R_BUS_UART		8
> +#define RST_R_BUS_I2C		9
> +#define RST_R_BUS_IR		10
> +#define RST_R_BUS_MSGBOX	11
> +#define RST_R_BUS_SPINLOCK	12
> +#define RST_R_BUS_RTC		13
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */
> 


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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
@ 2021-08-20  0:55     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  0:55 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 has clock controls in PRCM, like other new Allwinner
> SoCs.
> 
> Add support for them.
> 
> This driver is added before the main CCU because PLLs are controlled by
> R-CCU on R329.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   5 +
>  drivers/clk/sunxi-ng/Makefile                 |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
>  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
>  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
>  6 files changed, 470 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index cd46d8853876..e49b2c2fa5b7 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>  	default ARM64 && ARCH_SUNXI
>  	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_R_CCU
> +	bool "Support for the Allwinner R329 PRCM CCU"
> +	default ARM64 && ARCH_SUNXI
> +	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN4I_A10_CCU
>  	bool "Support for the Allwinner A10/A20 CCU"
>  	default MACH_SUN4I
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 96c324306d97..db338a2188fd 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)	+= ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> new file mode 100644
> index 000000000000..5413a701cb57
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Sipeed
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329-r.h"
> +
> +/*
> + * The M factor is present in the register's description, but not in the
> + * frequency formula, and it's documented as "The bit is only for
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_R329_PLL_CPUX_REG	0x1000
> +static struct ccu_mult pll_cpux_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.mult		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.common		= {
> +		.reg		= 0x1000,
> +		.hw.init	= CLK_HW_INIT("pll-cpux", "osc24M",
> +					      &ccu_mult_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +#define SUN50I_R329_PLL_PERIPH_REG	0x1010
> +static struct ccu_nm pll_periph_base_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
> +	.common		= {
> +		.reg		= 0x1010,
> +		.hw.init	= CLK_HW_INIT("pll-periph-base", "osc24M",
> +					      &ccu_nm_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-base",
> +		   0x1010, 16, 3, 0);
> +static SUNXI_CCU_M(pll_periph_800m_clk, "pll-periph-800m", "pll-periph-base",
> +		   0x1010, 20, 3, 0);

M as abbreviation for "mega" should be capitalized.

> +static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
> +			   &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +#define SUN50I_R329_PLL_AUDIO0_REG	0x1020
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> +	{ .rate = 1548288000, .pattern = 0xc0070624, .m = 1, .n = 64 },
> +};
> +
> +static struct ccu_nm pll_audio0_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.m		= _SUNXI_CCU_DIV(1, 1),
> +	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table,
> +					 BIT(24), 0x1120, BIT(31)),
> +	.common		= {
> +		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
> +		.reg		= 0x1020,
> +		.hw.init	= CLK_HW_INIT("pll-audio0", "osc24M",
> +					      &ccu_nm_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +static SUNXI_CCU_M(pll_audio0_div2_clk, "pll-audio0-div2", "pll-audio0",
> +		   0x1020, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio0_div5_clk, "pll-audio0-div5", "pll-audio0",
> +		   0x1020, 20, 3, 0);
> +
> +/*
> + * PLL-AUDIO1 has 3 dividers defined in the datasheet, however the
> + * BSP driver always has M0 = 1 and M1 = 2 (this is also the
> + * reset value in the register).
> + *
> + * Here just module it as NM clock, and force M0 = 1 and M1 = 2.
> + */
> +#define SUN50I_R329_PLL_AUDIO1_REG	0x1030
> +static struct ccu_sdm_setting pll_audio1_4x_sdm_table[] = {
> +	{ .rate = 22579200, .pattern = 0xc001288d, .m = 12, .n = 22 },
> +	{ .rate = 24576000, .pattern = 0xc00126e9, .m = 12, .n = 24 },
> +	{ .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +	{ .rate = 98304000, .pattern = 0xc00126e9, .m = 3, .n = 24 },
> +};
> +static struct ccu_nm pll_audio1_4x_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> +	.m		= _SUNXI_CCU_DIV(16, 6),
> +	.fixed_post_div	= 2,
> +	.sdm		= _SUNXI_CCU_SDM(pll_audio1_4x_sdm_table,
> +					 BIT(24), 0x1130, BIT(31)),
> +	.common		= {
> +		.features	= CCU_FEATURE_FIXED_POSTDIV |
> +				  CCU_FEATURE_SIGMA_DELTA_MOD,
> +		.reg		= 0x1030,
> +		.hw.init	= CLK_HW_INIT("pll-audio1-4x", "osc24M",
> +					      &ccu_nm_ops,
> +					      CLK_SET_RATE_UNGATE),
> +	},
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio1_2x_clk, "pll-audio1-2x",
> +			   &pll_audio1_4x_clk.common.hw, 2, 1,
> +			   CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HW(pll_audio1_clk, "pll-audio1",
> +			   &pll_audio1_4x_clk.common.hw, 4, 1,
> +			   CLK_SET_RATE_PARENT);
> +
> +static const char * const r_bus_parents[] = { "osc24M", "osc32k", "iosc",
> +					      "pll-periph-2x",
> +					      "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", r_bus_parents, 0x000,
> +			     0, 5,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb1_clk, "r-apb1", r_bus_parents, 0x00c,
> +			     0, 5,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(r_apb2_clk, "r-apb2", r_bus_parents, 0x010,
> +			     0, 5,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);

These are numbered 0 and 1 in the manual and in the BSP. Why number them
differently here?

> +
> +static SUNXI_CCU_GATE(r_bus_gpadc_clk, "r-bus-gpadc", "r-apb1",
> +		      0x0ec, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_ths_clk, "r-bus-ths", "r-apb1", 0x0fc, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(r_bus_dma_clk, "r-bus-dma", "r-apb1", 0x10c, BIT(0), 0);

BSP has R_TIMER at 0x11c and R_TWD at 0x12c.

> +
> +static const char * const r_pwm_parents[] = { "osc24M", "osc32k", "iosc" };
> +static SUNXI_CCU_MUX_WITH_GATE(r_pwm_clk, "r-pwm", r_pwm_parents, 0x130,
> +			       24, 3,	/* mux */
> +			       BIT(31),	/* gate */
> +			       0);
> +
> +static SUNXI_CCU_GATE(r_bus_pwm_clk, "r-bus-pwm", "r-apb1", 0x13c, BIT(0), 0);
> +
> +static const char * const r_audio_parents[] = { "pll-audio0-div5", "pll-audio0-div2",
> +						"pll-audio1-1x", "pll-audio1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_adc_clk, "r-codec-adc", r_audio_parents, 0x140,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */

I don't think it matters much, but the audio and IR muxes are documented as
being two bits wide.

> +				  BIT(31),	/* gate */
> +				  0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_codec_dac_clk, "r-codec-dac", r_audio_parents, 0x144,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(r_bus_codec_clk, "r-bus-codec", "r-apb1",
> +		      0x14c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_dmic_clk, "r-dmic", r_audio_parents, 0x150,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(r_bus_dmic_clk, "r-bus-dmic", "r-apb1", 0x15c, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_lradc_clk, "r-bus-lradc", "r-apb1",
> +		      0x16c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_clk, "r-i2s", r_audio_parents, 0x170,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_i2s_asrc_clk, "r-i2s-asrc",
> +				  r_audio_parents, 0x174,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);

The BSP claims there is an R_I2S1 module clock at 0x178. Can you check if that
exists? And the corresponding gate/reset bits in 0x17c?

> +static SUNXI_CCU_GATE(r_bus_i2s_clk, "r-bus-i2s", "r-apb1", 0x17c, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_uart_clk, "r-bus-uart", "r-apb2", 0x18c, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_i2c_clk, "r-bus-i2c", "r-apb2", 0x19c, BIT(0), 0);

R_PPU is at 0x1ac, and R_DSP is at 0x1bc.

> +
> +static const char * const r_ir_parents[] = { "osc32k", "osc24M" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_clk, "r-ir", r_ir_parents, 0x1c0,
> +				  0, 5,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(r_bus_ir_clk, "r-bus-ir", "r-apb1", 0x1cc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_msgbox_clk, "r-bus-msgbox", "r-apb1",
> +		      0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_bus_spinlock_clk, "r-bus-spinlock", "r-apb1",
> +		      0x1ec, BIT(0), 0);

R_DSP_SRAM is at 0x1fc.

> +static SUNXI_CCU_GATE(r_bus_rtc_clk, "r-bus-rtc", "r-ahb",
> +		      0x20c, BIT(0), CLK_IS_CRITICAL);

Is this a workaround for the clock consumer missing from the RTC driver?

Also, there is a "PSARM" clock at 0x210 and its gate at 0x21c. I think this may
refer to the NPU from ARM China?

Finally, there is a CPUCFG gate at 0x22c. I'm not sure which CPUCFG this refers to.

> +
> +static struct ccu_common *sun50i_r329_r_ccu_clks[] = {
> +	&pll_cpux_clk.common,
> +	&pll_periph_base_clk.common,
> +	&pll_periph_2x_clk.common,
> +	&pll_periph_800m_clk.common,
> +	&pll_audio0_clk.common,
> +	&pll_audio0_div2_clk.common,
> +	&pll_audio0_div5_clk.common,
> +	&pll_audio1_4x_clk.common,
> +	&r_ahb_clk.common,
> +	&r_apb1_clk.common,
> +	&r_apb2_clk.common,
> +	&r_bus_gpadc_clk.common,
> +	&r_bus_ths_clk.common,
> +	&r_bus_dma_clk.common,
> +	&r_pwm_clk.common,
> +	&r_bus_pwm_clk.common,
> +	&r_codec_adc_clk.common,
> +	&r_codec_dac_clk.common,
> +	&r_bus_codec_clk.common,
> +	&r_dmic_clk.common,
> +	&r_bus_dmic_clk.common,
> +	&r_bus_lradc_clk.common,
> +	&r_i2s_clk.common,
> +	&r_i2s_asrc_clk.common,
> +	&r_bus_i2s_clk.common,
> +	&r_bus_uart_clk.common,
> +	&r_bus_i2c_clk.common,
> +	&r_ir_clk.common,
> +	&r_bus_ir_clk.common,
> +	&r_bus_msgbox_clk.common,
> +	&r_bus_spinlock_clk.common,
> +	&r_bus_rtc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_r_hw_clks = {
> +	.hws	= {
> +		[CLK_PLL_CPUX]		= &pll_cpux_clk.common.hw,
> +		[CLK_PLL_PERIPH_BASE]	= &pll_periph_base_clk.common.hw,
> +		[CLK_PLL_PERIPH_2X]	= &pll_periph_2x_clk.common.hw,
> +		[CLK_PLL_PERIPH_800M]	= &pll_periph_800m_clk.common.hw,
> +		[CLK_PLL_PERIPH]	= &pll_periph_clk.hw,
> +		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.common.hw,
> +		[CLK_PLL_AUDIO0_DIV2]	= &pll_audio0_div2_clk.common.hw,
> +		[CLK_PLL_AUDIO0_DIV5]	= &pll_audio0_div5_clk.common.hw,
> +		[CLK_PLL_AUDIO1_4X]	= &pll_audio1_4x_clk.common.hw,
> +		[CLK_PLL_AUDIO1_2X]	= &pll_audio1_2x_clk.hw,
> +		[CLK_PLL_AUDIO1]	= &pll_audio1_clk.hw,
> +		[CLK_R_AHB]		= &r_ahb_clk.common.hw,
> +		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
> +		[CLK_R_APB2]		= &r_apb2_clk.common.hw,
> +		[CLK_R_BUS_GPADC]	= &r_bus_gpadc_clk.common.hw,
> +		[CLK_R_BUS_THS]		= &r_bus_ths_clk.common.hw,
> +		[CLK_R_BUS_DMA]		= &r_bus_dma_clk.common.hw,
> +		[CLK_R_PWM]		= &r_pwm_clk.common.hw,
> +		[CLK_R_BUS_PWM]		= &r_bus_pwm_clk.common.hw,
> +		[CLK_R_CODEC_ADC]	= &r_codec_adc_clk.common.hw,
> +		[CLK_R_CODEC_DAC]	= &r_codec_dac_clk.common.hw,
> +		[CLK_R_BUS_CODEC]	= &r_bus_codec_clk.common.hw,
> +		[CLK_R_DMIC]		= &r_dmic_clk.common.hw,
> +		[CLK_R_BUS_DMIC]	= &r_bus_dmic_clk.common.hw,
> +		[CLK_R_BUS_LRADC]	= &r_bus_lradc_clk.common.hw,
> +		[CLK_R_I2S]		= &r_i2s_clk.common.hw,
> +		[CLK_R_I2S_ASRC]	= &r_i2s_asrc_clk.common.hw,
> +		[CLK_R_BUS_I2S]		= &r_bus_i2s_clk.common.hw,
> +		[CLK_R_BUS_UART]	= &r_bus_uart_clk.common.hw,
> +		[CLK_R_BUS_I2C]		= &r_bus_i2c_clk.common.hw,
> +		[CLK_R_IR]		= &r_ir_clk.common.hw,
> +		[CLK_R_BUS_IR]		= &r_bus_ir_clk.common.hw,
> +		[CLK_R_BUS_MSGBOX]	= &r_bus_msgbox_clk.common.hw,
> +		[CLK_R_BUS_SPINLOCK]	= &r_bus_spinlock_clk.common.hw,
> +		[CLK_R_BUS_RTC]		= &r_bus_rtc_clk.common.hw,
> +	},
> +	.num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_r_ccu_resets[] = {
> +	[RST_R_BUS_GPADC]	= { 0x0ec, BIT(16) },
> +	[RST_R_BUS_THS]		= { 0x0fc, BIT(16) },
> +	[RST_R_BUS_DMA]		= { 0x10c, BIT(16) },
> +	[RST_R_BUS_PWM]		= { 0x13c, BIT(16) },
> +	[RST_R_BUS_CODEC]	= { 0x14c, BIT(16) },
> +	[RST_R_BUS_DMIC]	= { 0x15c, BIT(16) },
> +	[RST_R_BUS_LRADC]	= { 0x16c, BIT(16) },
> +	[RST_R_BUS_I2S]		= { 0x17c, BIT(16) },
> +	[RST_R_BUS_UART]	= { 0x18c, BIT(16) },
> +	[RST_R_BUS_I2C]		= { 0x19c, BIT(16) },
> +	[RST_R_BUS_IR]		= { 0x1cc, BIT(16) },
> +	[RST_R_BUS_MSGBOX]	= { 0x1dc, BIT(16) },
> +	[RST_R_BUS_SPINLOCK]	= { 0x1ec, BIT(16) },
> +	[RST_R_BUS_RTC]		= { 0x20c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_r_ccu_desc = {
> +	.ccu_clks	= sun50i_r329_r_ccu_clks,
> +	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_r_ccu_clks),
> +
> +	.hw_clks	= &sun50i_r329_r_hw_clks,
> +
> +	.resets		= sun50i_r329_r_ccu_resets,
> +	.num_resets	= ARRAY_SIZE(sun50i_r329_r_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> +	SUN50I_R329_PLL_CPUX_REG,
> +	SUN50I_R329_PLL_PERIPH_REG,
> +	SUN50I_R329_PLL_AUDIO0_REG,
> +	SUN50I_R329_PLL_AUDIO1_REG,
> +};
> +
> +static void __init sun50i_r329_r_ccu_setup(struct device_node *node)
> +{
> +	void __iomem *reg;
> +	u32 val;
> +	int i;
> +
> +	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> +	if (IS_ERR(reg)) {
> +		pr_err("%pOF: Could not map clock registers\n", node);
> +		return;
> +	}
> +
> +	/* Enable the lock bits and the output enable bits on all PLLs */
> +	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +		val = readl(reg + pll_regs[i]);
> +		val |= BIT(29) | BIT(27);
> +		writel(val, reg + pll_regs[i]);
> +	}
> +
> +	/*
> +	 * Force the I/O dividers of PLL-AUDIO1 to reset default value
> +	 *
> +	 * See the comment before pll-audio1 definition for the reason.
> +	 */
> +
> +	val = readl(reg + SUN50I_R329_PLL_AUDIO1_REG);
> +	val &= ~BIT(1);
> +	val |= BIT(0);
> +	writel(val, reg + SUN50I_R329_PLL_AUDIO1_REG);
> +
> +	i = sunxi_ccu_probe(node, reg, &sun50i_r329_r_ccu_desc);
> +	if (i)
> +		pr_err("%pOF: probing clocks fails: %d\n", node, i);
> +}
> +
> +CLK_OF_DECLARE(sun50i_r329_r_ccu, "allwinner,sun50i-r329-r-ccu",
> +	       sun50i_r329_r_ccu_setup);

Please make this a platform driver. There is no particular reason why it needs
to be an early OF clock provider.

Regards,
Samuel

> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> new file mode 100644
> index 000000000000..62cf65322116
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_R_H
> +#define _CCU_SUN50I_R329_R_H
> +
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +#define CLK_PLL_CPUX		0
> +#define CLK_PLL_PERIPH_BASE	1
> +#define CLK_PLL_PERIPH_2X	2
> +#define CLK_PLL_PERIPH_800M	3
> +#define CLK_PLL_PERIPH		4
> +#define CLK_PLL_AUDIO0		5
> +#define CLK_PLL_AUDIO0_DIV2	6
> +#define CLK_PLL_AUDIO0_DIV5	7
> +#define CLK_PLL_AUDIO1_4X	8
> +#define CLK_PLL_AUDIO1_2X	9
> +#define CLK_PLL_AUDIO1		10
> +#define CLK_R_AHB		11
> +
> +/* R_APB1 exported for PIO */
> +
> +#define CLK_R_APB2		13
> +
> +/* All module / bus gate clocks exported */
> +
> +#define CLK_NUMBER	(CLK_R_BUS_RTC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_R_H */
> diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..df9bc58de5c4
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
> +
> +#define CLK_R_APB1		12
> +
> +#define CLK_R_BUS_GPADC		14
> +#define CLK_R_BUS_THS		15
> +#define CLK_R_BUS_DMA		16
> +#define CLK_R_PWM		17
> +#define CLK_R_BUS_PWM		18
> +#define CLK_R_CODEC_ADC		19
> +#define CLK_R_CODEC_DAC		20
> +#define CLK_R_BUS_CODEC		21
> +#define CLK_R_DMIC		22
> +#define CLK_R_BUS_DMIC		23
> +#define CLK_R_BUS_LRADC		24
> +#define CLK_R_I2S		25
> +#define CLK_R_I2S_ASRC		26
> +#define CLK_R_BUS_I2S		27
> +#define CLK_R_BUS_UART		28
> +#define CLK_R_BUS_I2C		29
> +#define CLK_R_IR		30
> +#define CLK_R_BUS_IR		31
> +#define CLK_R_BUS_MSGBOX	32
> +#define CLK_R_BUS_SPINLOCK	33
> +#define CLK_R_BUS_RTC		34
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> new file mode 100644
> index 000000000000..40644f2f21c6
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
> +
> +#define RST_R_BUS_GPADC		0
> +#define RST_R_BUS_THS		1
> +#define RST_R_BUS_DMA		2
> +#define RST_R_BUS_PWM		3
> +#define RST_R_BUS_CODEC		4
> +#define RST_R_BUS_DMIC		5
> +#define RST_R_BUS_LRADC		6
> +#define RST_R_BUS_I2S		7
> +#define RST_R_BUS_UART		8
> +#define RST_R_BUS_I2C		9
> +#define RST_R_BUS_IR		10
> +#define RST_R_BUS_MSGBOX	11
> +#define RST_R_BUS_SPINLOCK	12
> +#define RST_R_BUS_RTC		13
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-20  2:41     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  2:41 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 has a CCU that is similar to the H616 one, but it's cut
> down and have PLLs moved out.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                |   5 +
>  drivers/clk/sunxi-ng/Makefile               |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526 ++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
>  include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
>  include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++
>  6 files changed, 682 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index e49b2c2fa5b7..4b32d5f81ea8 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>  	default ARM64 && ARCH_SUNXI
>  	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_CCU
> +	bool "Support for the Allwinner R329 CCU"
> +	default ARM64 && ARCH_SUNXI
> +	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN50I_R329_R_CCU
>  	bool "Support for the Allwinner R329 PRCM CCU"
>  	default ARM64 && ARCH_SUNXI
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index db338a2188fd..62f3c5bf331c 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_CCU)	+= ccu-sun50i-r329.o
>  obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> new file mode 100644
> index 000000000000..a0b4cfd6e1db
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> @@ -0,0 +1,526 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329.h"
> +
> +/*
> + * An external divider of PLL-CPUX is controlled here. As it's similar to
> + * the external divider of PLL-CPUX on previous SoCs (only usable under
> + * 288MHz}, ignore it.

Mismatched (braces} here

> + */
> +static const char * const cpux_parents[] = { "osc24M", "osc32k", "iosc",
> +					     "pll-cpux", "pll-periph",
> +					     "pll-periph-2x",
> +					     "pll=periph-800m" };

= should be a -.

Now that these PLLs are in a different device, how is this supposed to affect
the DT binding? Do we put all of them in the clocks property?

If so, we can use .fw_name at some point. If not, why bother with the clocks
property at all? This is another part of the "let's get the clock tree right
from the start" discussion.

> +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
> +		     0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
> +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
> +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
> +
> +static const char * const ahb_parents[] = { "osc24M", "osc32k",
> +					    "iosc", "pll-periph" };
> +static SUNXI_CCU_MP_WITH_MUX(ahb_clk, "ahb",
> +			     ahb_parents, 0x510,
> +			     0, 2,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static const char * const apb_parents[] = { "osc24M", "osc32k",
> +					    "ahb", "pll-periph" };
> +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb_parents, 0x520,
> +			     0, 2,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb_parents, 0x524,
> +			     0, 2,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);

Hmm, so Allwinner is inconsistent with these. The manual has APB0/APB1, but the
BSP has APB1/APB2.

> +
> +static const char * const ce_parents[] = { "osc24M", "pll-periph-2x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 1,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb",
> +		      0x68c, BIT(0), 0);
> +
> +static const char * const aipu_parents[] = { "pll-periph-2x", "pll-periph-800m",
> +					     "pll-audio0-div2", "pll-audio0-div5",
> +					     "pll-cpux" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(aipu_clk, "aipu", aipu_parents, 0x6f0,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_aipu_clk, "bus-aipu", "ahb",
> +		      0x6fc, BIT(0), 0);

The manual has separate gates for an AIPU AHB master at bit 1, and an AHB slave
at bit 0.

> +
> +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
> +		      0x70c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb",
> +		      0x71c, BIT(0), 0);

There are two message boxes (bits 0 and 1).

> +
> +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb",
> +		      0x72c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb",
> +		      0x73c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb",
> +		      0x78c, BIT(0), 0);

There is a gate for the PSI clock (the parent for the AHB clocks) at 0x79c.

> +
> +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
> +
> +static const char * const dram_parents[] = { "pll-periph-2x",
> +					     "pll-periph-800m",
> +					     "pll-audio0-div2",
> +					     "pll-audio0-div5" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> +				  0, 2,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  CLK_IS_CRITICAL);
> +
> +
> +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "dram",
> +		      0x804, BIT(0), 0);
> +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "dram",
> +		      0x804, BIT(2), 0);
> +static SUNXI_CCU_GATE(mbus_r_dma_clk, "mbus-r-dma", "dram",
> +		      0x804, BIT(3), 0);
> +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "dram",
> +		      0x804, BIT(5), 0);
> +static SUNXI_CCU_GATE(mbus_aipu_clk, "mbus-aipu", "dram",
> +		      0x804, BIT(16), 0);
> +
> +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
> +		      0x80c, BIT(0), CLK_IS_CRITICAL);

The DRAM bus clock is not critical. It only needs to be enabled for register
access (PMU, DVFS).

> +
> +static const char * const nand_parents[] = { "osc24M", "pll-periph",
> +					     "pll-audio-div2",
> +					     "pll-periph-2x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_parents, 0x810,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_parents, 0x814,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb", 0x82c, BIT(0), 0);
> +
> +static const char * const mmc_parents[] = { "osc24M", "pll-periph",
> +					    "pll-periph-2x",
> +					    "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
> +					  0, 4,		/* M */
> +					  8, 2,		/* P */
> +					  24, 2,	/* mux */
> +					  BIT(31),	/* gate */
> +					  2,		/* post-div */
> +					  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
> +					  0, 4,		/* M */
> +					  8, 2,		/* P */
> +					  24, 2,	/* mux */
> +					  BIT(31),	/* gate */
> +					  2,		/* post-div */

Where does the post-divider come from?

> +					  0);
> +
> +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 0x84c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 0x84c, BIT(1), 0);
> +
> +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
> +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
> +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
> +
> +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
> +
> +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 0x93c, BIT(0), 0);
> +
> +static const char * const spi_parents[] = { "osc24M", "pll-periph",
> +					    "pll-periph-2x",
> +					    "pll-audio0-div2",
> +					    "pll-audio0-div5" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 0x96c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 0x96c, BIT(1), 0);
> +
> +static CLK_FIXED_FACTOR(emac_25m_div_clk, "emac-25m-div", "pll-periph",
> +			2, 1, 0);
> +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "emac-25m-div", 0x970,
> +		      BIT(31) | BIT(30), 0);

The divider should be 24, not 2. And you can use CCU_FEATURE_ALL_PREDIV on the
gate to remove the separate divider clock.

> +
> +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb", 0x97c, BIT(0), 0);
> +
> +static const char * const ir_parents[] = { "osc32k", "iosc",

Both the manual and the BSP have the second parent as osc24M, not iosc.

> +					   "pll-periph", "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "apb1", 0x99c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
> +
> +static const char * const audio_parents[] = { "pll-audio1",
> +					      "pll-audio1-4x",
> +					      "pll-audio0-div2",
> +					      "pll-audio0-div5" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
> +				  0, 4,		/* M */

All of the audio modules have 5-bit M dividers.

> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_clk, "spdif", audio_parents, 0xa20,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
> +
> +/*
> + * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
> + * We will force them to 0 (12M divided from 48M).
> + */
> +#define SUN50I_R329_USB0_CLK_REG		0xa70
> +#define SUN50I_R329_USB1_CLK_REG		0xa74

This "48M" clock is divided/synchronized from pll-periph, as shown in the
"Module Clock Generation" diagram and USB "PHY Connection Diagram" in the
manual. So I recommend the following structure:

static CLK_FIXED_FACTOR(usb_48M_clk, "usb-48M",
                        "pll-periph", 25, 2, 0);

static CLK_FIXED_FACTOR_HW(usb_12M_clk, "usb-12M",
                           &usb_48M_clk.hw, 4, 1, 0);

static const char *const usb_ohci_parents[] = { "usb-12M", "osc12M",
                                                "osc32k" };
static SUNXI_CCU_MUX_WITH_GATE(usb_ohci0_clk, "usb-ohci0",
                               usb_ohci_parents, 0xa70,
                               24, 2,           /* mux */
                               BIT(31),         /* gate */
                               0);

static SUNXI_CCU_MUX_WITH_GATE(usb_ohci1_clk, "usb-ohci1",
                               usb_ohci_parents, 0xa74,
                               24, 2,           /* mux */
                               BIT(31),         /* gate */
                               0);

For anyone following along without R329 documents, this is all the same as the
D1, though the labels in the diagrams are slightly different. Hooray for finally
documenting this so it is no longer "mysterious"!

Regards,
Samuel

> +
> +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
> +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
> +
> +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
> +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
> +
> +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb", 0xa8c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb", 0xa8c, BIT(1), 0);
> +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb", 0xa8c, BIT(4), 0);
> +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 0xa8c, BIT(8), 0);
> +
> +static const char * const ledc_parents[] = { "osc24M", "pll-periph" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents, 0xbf0,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 1,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "apb1", 0xbfc, BIT(0), 0);
> +
> +/* Fixed factor clocks */
> +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
> +
> +static struct ccu_common *sun50i_r329_ccu_clks[] = {
> +	&cpux_clk.common,
> +	&axi_clk.common,
> +	&cpux_apb_clk.common,
> +	&ahb_clk.common,
> +	&apb1_clk.common,
> +	&apb2_clk.common,
> +	&ce_clk.common,
> +	&bus_ce_clk.common,
> +	&aipu_clk.common,
> +	&bus_aipu_clk.common,
> +	&bus_dma_clk.common,
> +	&bus_msgbox_clk.common,
> +	&bus_spinlock_clk.common,
> +	&bus_hstimer_clk.common,
> +	&avs_clk.common,
> +	&bus_dbg_clk.common,
> +	&bus_pwm_clk.common,
> +	&dram_clk.common,
> +	&mbus_dma_clk.common,
> +	&mbus_ce_clk.common,
> +	&mbus_r_dma_clk.common,
> +	&mbus_nand_clk.common,
> +	&mbus_aipu_clk.common,
> +	&bus_dram_clk.common,
> +	&nand0_clk.common,
> +	&nand1_clk.common,
> +	&bus_nand_clk.common,
> +	&mmc0_clk.common,
> +	&mmc1_clk.common,
> +	&bus_mmc0_clk.common,
> +	&bus_mmc1_clk.common,
> +	&bus_uart0_clk.common,
> +	&bus_uart1_clk.common,
> +	&bus_uart2_clk.common,
> +	&bus_uart3_clk.common,
> +	&bus_i2c0_clk.common,
> +	&bus_i2c1_clk.common,
> +	&bus_scr_clk.common,
> +	&spi0_clk.common,
> +	&spi1_clk.common,
> +	&bus_spi0_clk.common,
> +	&bus_spi1_clk.common,
> +	&emac_25m_clk.common,
> +	&bus_emac_clk.common,
> +	&ir_rx_clk.common,
> +	&bus_ir_rx_clk.common,
> +	&ir_tx_clk.common,
> +	&bus_ir_tx_clk.common,
> +	&i2s0_clk.common,
> +	&i2s1_clk.common,
> +	&bus_i2s0_clk.common,
> +	&bus_i2s1_clk.common,
> +	&spdif_clk.common,
> +	&bus_spdif_clk.common,
> +	&usb_ohci0_clk.common,
> +	&usb_phy0_clk.common,
> +	&usb_ohci1_clk.common,
> +	&usb_phy1_clk.common,
> +	&bus_ohci0_clk.common,
> +	&bus_ohci1_clk.common,
> +	&bus_ehci0_clk.common,
> +	&bus_otg_clk.common,
> +	&ledc_clk.common,
> +	&bus_ledc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_hw_clks = {
> +	.hws	= {
> +		[CLK_OSC12M]		= &osc12M_clk.hw,
> +		[CLK_CPUX]		= &cpux_clk.common.hw,
> +		[CLK_AXI]		= &axi_clk.common.hw,
> +		[CLK_CPUX_APB]		= &cpux_apb_clk.common.hw,
> +		[CLK_AHB]		= &ahb_clk.common.hw,
> +		[CLK_APB1]		= &apb1_clk.common.hw,
> +		[CLK_APB2]		= &apb2_clk.common.hw,
> +		[CLK_CE]		= &ce_clk.common.hw,
> +		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
> +		[CLK_AIPU]		= &aipu_clk.common.hw,
> +		[CLK_BUS_AIPU]		= &bus_aipu_clk.common.hw,
> +		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
> +		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
> +		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
> +		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
> +		[CLK_AVS]		= &avs_clk.common.hw,
> +		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
> +		[CLK_BUS_PWM]		= &bus_pwm_clk.common.hw,
> +		[CLK_DRAM]		= &dram_clk.common.hw,
> +		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
> +		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
> +		[CLK_MBUS_R_DMA]	= &mbus_r_dma_clk.common.hw,
> +		[CLK_MBUS_NAND]		= &mbus_nand_clk.common.hw,
> +		[CLK_MBUS_AIPU]		= &mbus_aipu_clk.common.hw,
> +		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
> +		[CLK_NAND0]		= &nand0_clk.common.hw,
> +		[CLK_NAND1]		= &nand1_clk.common.hw,
> +		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
> +		[CLK_MMC0]		= &mmc0_clk.common.hw,
> +		[CLK_MMC1]		= &mmc1_clk.common.hw,
> +		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
> +		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
> +		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
> +		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
> +		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
> +		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
> +		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
> +		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
> +		[CLK_BUS_SCR]		= &bus_scr_clk.common.hw,
> +		[CLK_SPI0]		= &spi0_clk.common.hw,
> +		[CLK_SPI1]		= &spi1_clk.common.hw,
> +		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
> +		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
> +		[CLK_EMAC_25M_DIV]	= &emac_25m_div_clk.hw,
> +		[CLK_EMAC_25M]		= &emac_25m_clk.common.hw,
> +		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
> +		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
> +		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
> +		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
> +		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
> +		[CLK_I2S0]		= &i2s0_clk.common.hw,
> +		[CLK_I2S1]		= &i2s1_clk.common.hw,
> +		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
> +		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
> +		[CLK_SPDIF]		= &spdif_clk.common.hw,
> +		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
> +		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
> +		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
> +		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
> +		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
> +		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
> +		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
> +		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
> +		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
> +		[CLK_LEDC]		= &ledc_clk.common.hw,
> +		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
> +	},
> +	.num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_ccu_resets[] = {
> +	[RST_MBUS]		= { 0x540, BIT(30) },
> +
> +	[RST_BUS_CE]		= { 0x68c, BIT(16) },
> +	[RST_BUS_AIPU]		= { 0x6fc, BIT(16) },
> +	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
> +	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
> +	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
> +	[RST_BUS_HSTIMER]	= { 0x73c, BIT(16) },
> +	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
> +	[RST_BUS_PWM]		= { 0x7ac, BIT(16) },
> +	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
> +	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
> +	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
> +	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
> +	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
> +	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
> +	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
> +	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
> +	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
> +	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
> +	[RST_BUS_SCR]		= { 0x93c, BIT(16) },
> +	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
> +	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
> +	[RST_BUS_EMAC]		= { 0x97c, BIT(16) },
> +	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
> +	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
> +	[RST_BUS_I2S0]		= { 0xa1c, BIT(16) },
> +	[RST_BUS_I2S1]		= { 0xa1c, BIT(17) },
> +	[RST_BUS_SPDIF]		= { 0xa2c, BIT(16) },
> +
> +	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
> +	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
> +
> +	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
> +	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
> +	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
> +	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
> +
> +	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_ccu_desc = {
> +	.ccu_clks	= sun50i_r329_ccu_clks,
> +	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_ccu_clks),
> +
> +	.hw_clks	= &sun50i_r329_hw_clks,
> +
> +	.resets		= sun50i_r329_ccu_resets,
> +	.num_resets	= ARRAY_SIZE(sun50i_r329_ccu_resets),
> +};
> +
> +static const u32 sun50i_r329_usb_clk_regs[] = {
> +	SUN50I_R329_USB0_CLK_REG,
> +	SUN50I_R329_USB1_CLK_REG,
> +};
> +
> +static int sun50i_r329_ccu_probe(struct platform_device *pdev)
> +{
> +	void __iomem *reg;
> +	u32 val;
> +	int i;
> +
> +	reg = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(reg))
> +		return PTR_ERR(reg);
> +
> +	/*
> +	 * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
> +	 *
> +	 * This clock mux is still mysterious, and the code just enforces
> +	 * it to have a valid clock parent.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(sun50i_r329_usb_clk_regs); i++) {
> +		val = readl(reg + sun50i_r329_usb_clk_regs[i]);
> +		val &= ~GENMASK(25, 24);
> +		writel(val, reg + sun50i_r329_usb_clk_regs[i]);
> +	}
> +
> +	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_r329_ccu_desc);
> +}
> +
> +static const struct of_device_id sun50i_r329_ccu_ids[] = {
> +	{ .compatible = "allwinner,sun50i-r329-ccu" },
> +	{ }
> +};
> +
> +static struct platform_driver sun50i_r329_ccu_driver = {
> +	.probe	= sun50i_r329_ccu_probe,
> +	.driver	= {
> +		.name	= "sun50i-r329-ccu",
> +		.of_match_table	= sun50i_r329_ccu_ids,
> +	},
> +};
> +module_platform_driver(sun50i_r329_ccu_driver);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> new file mode 100644
> index 000000000000..144ac9954ef3
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_H_
> +#define _CCU_SUN50I_R329_H_
> +
> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> +
> +#define CLK_OSC12M		0
> +
> +/* CPUX exported for DVFS */
> +
> +#define CLK_AXI			2
> +#define CLK_CPUX_APB		3
> +#define CLK_AHB			4
> +
> +/* APB1 exported for PIO */
> +
> +#define CLK_APB2		6
> +
> +/* Peripheral module and gate clock exported except for DRAM ones */
> +
> +#define CLK_DRAM		18
> +
> +#define CLK_BUS_DRAM		24
> +
> +#define CLK_NUMBER		(CLK_BUS_LEDC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_H_ */
> diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h b/include/dt-bindings/clock/sun50i-r329-ccu.h
> new file mode 100644
> index 000000000000..116f8d13a9b3
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> +
> +#define CLK_CPUX		1
> +
> +#define CLK_APB1		5
> +
> +#define CLK_CE			7
> +#define CLK_BUS_CE		8
> +#define CLK_AIPU		9
> +#define CLK_BUS_AIPU		10
> +#define CLK_BUS_DMA		11
> +#define CLK_BUS_MSGBOX		12
> +#define CLK_BUS_SPINLOCK	13
> +#define CLK_BUS_HSTIMER		14
> +#define CLK_AVS			15
> +#define CLK_BUS_DBG		16
> +#define CLK_BUS_PWM		17
> +
> +#define CLK_MBUS_DMA		19
> +#define CLK_MBUS_CE		20
> +#define CLK_MBUS_R_DMA		21
> +#define CLK_MBUS_NAND		22
> +#define CLK_MBUS_AIPU		23
> +
> +#define CLK_NAND0		25
> +#define CLK_NAND1		26
> +#define CLK_BUS_NAND		27
> +#define CLK_MMC0		28
> +#define CLK_MMC1		29
> +#define CLK_BUS_MMC0		30
> +#define CLK_BUS_MMC1		31
> +#define CLK_BUS_UART0		32
> +#define CLK_BUS_UART1		33
> +#define CLK_BUS_UART2		34
> +#define CLK_BUS_UART3		35
> +#define CLK_BUS_I2C0		36
> +#define CLK_BUS_I2C1		37
> +#define CLK_BUS_SCR		38
> +#define CLK_SPI0		39
> +#define CLK_SPI1		40
> +#define CLK_BUS_SPI0		41
> +#define CLK_BUS_SPI1		42
> +#define CLK_EMAC_25M_DIV	43
> +#define CLK_EMAC_25M		44
> +#define CLK_BUS_EMAC		45
> +#define CLK_IR_RX		46
> +#define CLK_BUS_IR_RX		47
> +#define CLK_IR_TX		48
> +#define CLK_BUS_IR_TX		49
> +#define CLK_I2S0		50
> +#define CLK_I2S1		51
> +#define CLK_BUS_I2S0		52
> +#define CLK_BUS_I2S1		53
> +#define CLK_SPDIF		54
> +#define CLK_BUS_SPDIF		55
> +#define CLK_USB_OHCI0		56
> +#define CLK_USB_PHY0		57
> +#define CLK_USB_OHCI1		58
> +#define CLK_USB_PHY1		59
> +#define CLK_BUS_OHCI0		60
> +#define CLK_BUS_OHCI1		61
> +#define CLK_BUS_EHCI0		62
> +#define CLK_BUS_OTG		63
> +#define CLK_LEDC		64
> +#define CLK_BUS_LEDC		65
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h b/include/dt-bindings/reset/sun50i-r329-ccu.h
> new file mode 100644
> index 000000000000..bb704a82443f
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
> @@ -0,0 +1,45 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> +
> +#define RST_MBUS		0
> +#define RST_BUS_CE		1
> +#define RST_BUS_AIPU		2
> +#define RST_BUS_DMA		3
> +#define RST_BUS_MSGBOX		4
> +#define RST_BUS_SPINLOCK	5
> +#define RST_BUS_HSTIMER		6
> +#define RST_BUS_DBG		7
> +#define RST_BUS_PWM		8
> +#define RST_BUS_DRAM		9
> +#define RST_BUS_NAND		10
> +#define RST_BUS_MMC0		11
> +#define RST_BUS_MMC1		12
> +#define RST_BUS_UART0		13
> +#define RST_BUS_UART1		14
> +#define RST_BUS_UART2		15
> +#define RST_BUS_UART3		16
> +#define RST_BUS_I2C0		17
> +#define RST_BUS_I2C1		18
> +#define RST_BUS_SCR		19
> +#define RST_BUS_SPI0		20
> +#define RST_BUS_SPI1		21
> +#define RST_BUS_EMAC		22
> +#define RST_BUS_IR_RX		23
> +#define RST_BUS_IR_TX		24
> +#define RST_BUS_I2S0		25
> +#define RST_BUS_I2S1		26
> +#define RST_BUS_SPDIF		27
> +#define RST_USB_PHY0		28
> +#define RST_USB_PHY1		29
> +#define RST_BUS_OHCI0		30
> +#define RST_BUS_OHCI1		31
> +#define RST_BUS_EHCI0		32
> +#define RST_BUS_OTG		33
> +#define RST_BUS_LEDC		34
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
> 


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

* Re: [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
@ 2021-08-20  2:41     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  2:41 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 has a CCU that is similar to the H616 one, but it's cut
> down and have PLLs moved out.
> 
> Add support for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/clk/sunxi-ng/Kconfig                |   5 +
>  drivers/clk/sunxi-ng/Makefile               |   1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526 ++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
>  include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
>  include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++
>  6 files changed, 682 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
>  create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index e49b2c2fa5b7..4b32d5f81ea8 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
>  	default ARM64 && ARCH_SUNXI
>  	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_R329_CCU
> +	bool "Support for the Allwinner R329 CCU"
> +	default ARM64 && ARCH_SUNXI
> +	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN50I_R329_R_CCU
>  	bool "Support for the Allwinner R329 PRCM CCU"
>  	default ARM64 && ARCH_SUNXI
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index db338a2188fd..62f3c5bf331c 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= ccu-sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)	+= ccu-sun50i-h6.o
>  obj-$(CONFIG_SUN50I_H616_CCU)	+= ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)	+= ccu-sun50i-h6-r.o
> +obj-$(CONFIG_SUN50I_R329_CCU)	+= ccu-sun50i-r329.o
>  obj-$(CONFIG_SUN50I_R329_R_CCU)	+= ccu-sun50i-r329-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)	+= ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.c b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> new file mode 100644
> index 000000000000..a0b4cfd6e1db
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> @@ -0,0 +1,526 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Based on the H616 CCU driver, which is:
> + *   Copyright (c) 2020 Arm Ltd.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.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-sun50i-r329.h"
> +
> +/*
> + * An external divider of PLL-CPUX is controlled here. As it's similar to
> + * the external divider of PLL-CPUX on previous SoCs (only usable under
> + * 288MHz}, ignore it.

Mismatched (braces} here

> + */
> +static const char * const cpux_parents[] = { "osc24M", "osc32k", "iosc",
> +					     "pll-cpux", "pll-periph",
> +					     "pll-periph-2x",
> +					     "pll=periph-800m" };

= should be a -.

Now that these PLLs are in a different device, how is this supposed to affect
the DT binding? Do we put all of them in the clocks property?

If so, we can use .fw_name at some point. If not, why bother with the clocks
property at all? This is another part of the "let's get the clock tree right
from the start" discussion.

> +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
> +		     0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
> +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
> +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
> +
> +static const char * const ahb_parents[] = { "osc24M", "osc32k",
> +					    "iosc", "pll-periph" };
> +static SUNXI_CCU_MP_WITH_MUX(ahb_clk, "ahb",
> +			     ahb_parents, 0x510,
> +			     0, 2,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static const char * const apb_parents[] = { "osc24M", "osc32k",
> +					    "ahb", "pll-periph" };
> +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb_parents, 0x520,
> +			     0, 2,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);
> +
> +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb_parents, 0x524,
> +			     0, 2,	/* M */
> +			     8, 2,	/* P */
> +			     24, 3,	/* mux */
> +			     0);

Hmm, so Allwinner is inconsistent with these. The manual has APB0/APB1, but the
BSP has APB1/APB2.

> +
> +static const char * const ce_parents[] = { "osc24M", "pll-periph-2x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 1,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb",
> +		      0x68c, BIT(0), 0);
> +
> +static const char * const aipu_parents[] = { "pll-periph-2x", "pll-periph-800m",
> +					     "pll-audio0-div2", "pll-audio0-div5",
> +					     "pll-cpux" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(aipu_clk, "aipu", aipu_parents, 0x6f0,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_aipu_clk, "bus-aipu", "ahb",
> +		      0x6fc, BIT(0), 0);

The manual has separate gates for an AIPU AHB master at bit 1, and an AHB slave
at bit 0.

> +
> +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
> +		      0x70c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb",
> +		      0x71c, BIT(0), 0);

There are two message boxes (bits 0 and 1).

> +
> +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb",
> +		      0x72c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb",
> +		      0x73c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb",
> +		      0x78c, BIT(0), 0);

There is a gate for the PSI clock (the parent for the AHB clocks) at 0x79c.

> +
> +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
> +
> +static const char * const dram_parents[] = { "pll-periph-2x",
> +					     "pll-periph-800m",
> +					     "pll-audio0-div2",
> +					     "pll-audio0-div5" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> +				  0, 2,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  CLK_IS_CRITICAL);
> +
> +
> +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "dram",
> +		      0x804, BIT(0), 0);
> +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "dram",
> +		      0x804, BIT(2), 0);
> +static SUNXI_CCU_GATE(mbus_r_dma_clk, "mbus-r-dma", "dram",
> +		      0x804, BIT(3), 0);
> +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "dram",
> +		      0x804, BIT(5), 0);
> +static SUNXI_CCU_GATE(mbus_aipu_clk, "mbus-aipu", "dram",
> +		      0x804, BIT(16), 0);
> +
> +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
> +		      0x80c, BIT(0), CLK_IS_CRITICAL);

The DRAM bus clock is not critical. It only needs to be enabled for register
access (PMU, DVFS).

> +
> +static const char * const nand_parents[] = { "osc24M", "pll-periph",
> +					     "pll-audio-div2",
> +					     "pll-periph-2x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_parents, 0x810,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_parents, 0x814,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb", 0x82c, BIT(0), 0);
> +
> +static const char * const mmc_parents[] = { "osc24M", "pll-periph",
> +					    "pll-periph-2x",
> +					    "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
> +					  0, 4,		/* M */
> +					  8, 2,		/* P */
> +					  24, 2,	/* mux */
> +					  BIT(31),	/* gate */
> +					  2,		/* post-div */
> +					  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
> +					  0, 4,		/* M */
> +					  8, 2,		/* P */
> +					  24, 2,	/* mux */
> +					  BIT(31),	/* gate */
> +					  2,		/* post-div */

Where does the post-divider come from?

> +					  0);
> +
> +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 0x84c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 0x84c, BIT(1), 0);
> +
> +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
> +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
> +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
> +
> +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
> +
> +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 0x93c, BIT(0), 0);
> +
> +static const char * const spi_parents[] = { "osc24M", "pll-periph",
> +					    "pll-periph-2x",
> +					    "pll-audio0-div2",
> +					    "pll-audio0-div5" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 3,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 0x96c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 0x96c, BIT(1), 0);
> +
> +static CLK_FIXED_FACTOR(emac_25m_div_clk, "emac-25m-div", "pll-periph",
> +			2, 1, 0);
> +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "emac-25m-div", 0x970,
> +		      BIT(31) | BIT(30), 0);

The divider should be 24, not 2. And you can use CCU_FEATURE_ALL_PREDIV on the
gate to remove the separate divider clock.

> +
> +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb", 0x97c, BIT(0), 0);
> +
> +static const char * const ir_parents[] = { "osc32k", "iosc",

Both the manual and the BSP have the second parent as osc24M, not iosc.

> +					   "pll-periph", "pll-audio0-div2" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "apb1", 0x99c, BIT(0), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
> +
> +static const char * const audio_parents[] = { "pll-audio1",
> +					      "pll-audio1-4x",
> +					      "pll-audio0-div2",
> +					      "pll-audio0-div5" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
> +				  0, 4,		/* M */

All of the audio modules have 5-bit M dividers.

> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_clk, "spdif", audio_parents, 0xa20,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
> +
> +/*
> + * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
> + * We will force them to 0 (12M divided from 48M).
> + */
> +#define SUN50I_R329_USB0_CLK_REG		0xa70
> +#define SUN50I_R329_USB1_CLK_REG		0xa74

This "48M" clock is divided/synchronized from pll-periph, as shown in the
"Module Clock Generation" diagram and USB "PHY Connection Diagram" in the
manual. So I recommend the following structure:

static CLK_FIXED_FACTOR(usb_48M_clk, "usb-48M",
                        "pll-periph", 25, 2, 0);

static CLK_FIXED_FACTOR_HW(usb_12M_clk, "usb-12M",
                           &usb_48M_clk.hw, 4, 1, 0);

static const char *const usb_ohci_parents[] = { "usb-12M", "osc12M",
                                                "osc32k" };
static SUNXI_CCU_MUX_WITH_GATE(usb_ohci0_clk, "usb-ohci0",
                               usb_ohci_parents, 0xa70,
                               24, 2,           /* mux */
                               BIT(31),         /* gate */
                               0);

static SUNXI_CCU_MUX_WITH_GATE(usb_ohci1_clk, "usb-ohci1",
                               usb_ohci_parents, 0xa74,
                               24, 2,           /* mux */
                               BIT(31),         /* gate */
                               0);

For anyone following along without R329 documents, this is all the same as the
D1, though the labels in the diagrams are slightly different. Hooray for finally
documenting this so it is no longer "mysterious"!

Regards,
Samuel

> +
> +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
> +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
> +
> +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
> +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
> +
> +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb", 0xa8c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb", 0xa8c, BIT(1), 0);
> +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb", 0xa8c, BIT(4), 0);
> +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 0xa8c, BIT(8), 0);
> +
> +static const char * const ledc_parents[] = { "osc24M", "pll-periph" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents, 0xbf0,
> +				  0, 4,		/* M */
> +				  8, 2,		/* P */
> +				  24, 1,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "apb1", 0xbfc, BIT(0), 0);
> +
> +/* Fixed factor clocks */
> +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
> +
> +static struct ccu_common *sun50i_r329_ccu_clks[] = {
> +	&cpux_clk.common,
> +	&axi_clk.common,
> +	&cpux_apb_clk.common,
> +	&ahb_clk.common,
> +	&apb1_clk.common,
> +	&apb2_clk.common,
> +	&ce_clk.common,
> +	&bus_ce_clk.common,
> +	&aipu_clk.common,
> +	&bus_aipu_clk.common,
> +	&bus_dma_clk.common,
> +	&bus_msgbox_clk.common,
> +	&bus_spinlock_clk.common,
> +	&bus_hstimer_clk.common,
> +	&avs_clk.common,
> +	&bus_dbg_clk.common,
> +	&bus_pwm_clk.common,
> +	&dram_clk.common,
> +	&mbus_dma_clk.common,
> +	&mbus_ce_clk.common,
> +	&mbus_r_dma_clk.common,
> +	&mbus_nand_clk.common,
> +	&mbus_aipu_clk.common,
> +	&bus_dram_clk.common,
> +	&nand0_clk.common,
> +	&nand1_clk.common,
> +	&bus_nand_clk.common,
> +	&mmc0_clk.common,
> +	&mmc1_clk.common,
> +	&bus_mmc0_clk.common,
> +	&bus_mmc1_clk.common,
> +	&bus_uart0_clk.common,
> +	&bus_uart1_clk.common,
> +	&bus_uart2_clk.common,
> +	&bus_uart3_clk.common,
> +	&bus_i2c0_clk.common,
> +	&bus_i2c1_clk.common,
> +	&bus_scr_clk.common,
> +	&spi0_clk.common,
> +	&spi1_clk.common,
> +	&bus_spi0_clk.common,
> +	&bus_spi1_clk.common,
> +	&emac_25m_clk.common,
> +	&bus_emac_clk.common,
> +	&ir_rx_clk.common,
> +	&bus_ir_rx_clk.common,
> +	&ir_tx_clk.common,
> +	&bus_ir_tx_clk.common,
> +	&i2s0_clk.common,
> +	&i2s1_clk.common,
> +	&bus_i2s0_clk.common,
> +	&bus_i2s1_clk.common,
> +	&spdif_clk.common,
> +	&bus_spdif_clk.common,
> +	&usb_ohci0_clk.common,
> +	&usb_phy0_clk.common,
> +	&usb_ohci1_clk.common,
> +	&usb_phy1_clk.common,
> +	&bus_ohci0_clk.common,
> +	&bus_ohci1_clk.common,
> +	&bus_ehci0_clk.common,
> +	&bus_otg_clk.common,
> +	&ledc_clk.common,
> +	&bus_ledc_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_r329_hw_clks = {
> +	.hws	= {
> +		[CLK_OSC12M]		= &osc12M_clk.hw,
> +		[CLK_CPUX]		= &cpux_clk.common.hw,
> +		[CLK_AXI]		= &axi_clk.common.hw,
> +		[CLK_CPUX_APB]		= &cpux_apb_clk.common.hw,
> +		[CLK_AHB]		= &ahb_clk.common.hw,
> +		[CLK_APB1]		= &apb1_clk.common.hw,
> +		[CLK_APB2]		= &apb2_clk.common.hw,
> +		[CLK_CE]		= &ce_clk.common.hw,
> +		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
> +		[CLK_AIPU]		= &aipu_clk.common.hw,
> +		[CLK_BUS_AIPU]		= &bus_aipu_clk.common.hw,
> +		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
> +		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
> +		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
> +		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
> +		[CLK_AVS]		= &avs_clk.common.hw,
> +		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
> +		[CLK_BUS_PWM]		= &bus_pwm_clk.common.hw,
> +		[CLK_DRAM]		= &dram_clk.common.hw,
> +		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
> +		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
> +		[CLK_MBUS_R_DMA]	= &mbus_r_dma_clk.common.hw,
> +		[CLK_MBUS_NAND]		= &mbus_nand_clk.common.hw,
> +		[CLK_MBUS_AIPU]		= &mbus_aipu_clk.common.hw,
> +		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
> +		[CLK_NAND0]		= &nand0_clk.common.hw,
> +		[CLK_NAND1]		= &nand1_clk.common.hw,
> +		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
> +		[CLK_MMC0]		= &mmc0_clk.common.hw,
> +		[CLK_MMC1]		= &mmc1_clk.common.hw,
> +		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
> +		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
> +		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
> +		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
> +		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
> +		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
> +		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
> +		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
> +		[CLK_BUS_SCR]		= &bus_scr_clk.common.hw,
> +		[CLK_SPI0]		= &spi0_clk.common.hw,
> +		[CLK_SPI1]		= &spi1_clk.common.hw,
> +		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
> +		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
> +		[CLK_EMAC_25M_DIV]	= &emac_25m_div_clk.hw,
> +		[CLK_EMAC_25M]		= &emac_25m_clk.common.hw,
> +		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
> +		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
> +		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
> +		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
> +		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
> +		[CLK_I2S0]		= &i2s0_clk.common.hw,
> +		[CLK_I2S1]		= &i2s1_clk.common.hw,
> +		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
> +		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
> +		[CLK_SPDIF]		= &spdif_clk.common.hw,
> +		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
> +		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
> +		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
> +		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
> +		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
> +		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
> +		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
> +		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
> +		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
> +		[CLK_LEDC]		= &ledc_clk.common.hw,
> +		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
> +	},
> +	.num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun50i_r329_ccu_resets[] = {
> +	[RST_MBUS]		= { 0x540, BIT(30) },
> +
> +	[RST_BUS_CE]		= { 0x68c, BIT(16) },
> +	[RST_BUS_AIPU]		= { 0x6fc, BIT(16) },
> +	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
> +	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
> +	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
> +	[RST_BUS_HSTIMER]	= { 0x73c, BIT(16) },
> +	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
> +	[RST_BUS_PWM]		= { 0x7ac, BIT(16) },
> +	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
> +	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
> +	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
> +	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
> +	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
> +	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
> +	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
> +	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
> +	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
> +	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
> +	[RST_BUS_SCR]		= { 0x93c, BIT(16) },
> +	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
> +	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
> +	[RST_BUS_EMAC]		= { 0x97c, BIT(16) },
> +	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
> +	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
> +	[RST_BUS_I2S0]		= { 0xa1c, BIT(16) },
> +	[RST_BUS_I2S1]		= { 0xa1c, BIT(17) },
> +	[RST_BUS_SPDIF]		= { 0xa2c, BIT(16) },
> +
> +	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
> +	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
> +
> +	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
> +	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
> +	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
> +	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
> +
> +	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_r329_ccu_desc = {
> +	.ccu_clks	= sun50i_r329_ccu_clks,
> +	.num_ccu_clks	= ARRAY_SIZE(sun50i_r329_ccu_clks),
> +
> +	.hw_clks	= &sun50i_r329_hw_clks,
> +
> +	.resets		= sun50i_r329_ccu_resets,
> +	.num_resets	= ARRAY_SIZE(sun50i_r329_ccu_resets),
> +};
> +
> +static const u32 sun50i_r329_usb_clk_regs[] = {
> +	SUN50I_R329_USB0_CLK_REG,
> +	SUN50I_R329_USB1_CLK_REG,
> +};
> +
> +static int sun50i_r329_ccu_probe(struct platform_device *pdev)
> +{
> +	void __iomem *reg;
> +	u32 val;
> +	int i;
> +
> +	reg = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(reg))
> +		return PTR_ERR(reg);
> +
> +	/*
> +	 * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
> +	 *
> +	 * This clock mux is still mysterious, and the code just enforces
> +	 * it to have a valid clock parent.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(sun50i_r329_usb_clk_regs); i++) {
> +		val = readl(reg + sun50i_r329_usb_clk_regs[i]);
> +		val &= ~GENMASK(25, 24);
> +		writel(val, reg + sun50i_r329_usb_clk_regs[i]);
> +	}
> +
> +	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_r329_ccu_desc);
> +}
> +
> +static const struct of_device_id sun50i_r329_ccu_ids[] = {
> +	{ .compatible = "allwinner,sun50i-r329-ccu" },
> +	{ }
> +};
> +
> +static struct platform_driver sun50i_r329_ccu_driver = {
> +	.probe	= sun50i_r329_ccu_probe,
> +	.driver	= {
> +		.name	= "sun50i-r329-ccu",
> +		.of_match_table	= sun50i_r329_ccu_ids,
> +	},
> +};
> +module_platform_driver(sun50i_r329_ccu_driver);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.h b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> new file mode 100644
> index 000000000000..144ac9954ef3
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _CCU_SUN50I_R329_H_
> +#define _CCU_SUN50I_R329_H_
> +
> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> +
> +#define CLK_OSC12M		0
> +
> +/* CPUX exported for DVFS */
> +
> +#define CLK_AXI			2
> +#define CLK_CPUX_APB		3
> +#define CLK_AHB			4
> +
> +/* APB1 exported for PIO */
> +
> +#define CLK_APB2		6
> +
> +/* Peripheral module and gate clock exported except for DRAM ones */
> +
> +#define CLK_DRAM		18
> +
> +#define CLK_BUS_DRAM		24
> +
> +#define CLK_NUMBER		(CLK_BUS_LEDC + 1)
> +
> +#endif /* _CCU_SUN50I_R329_H_ */
> diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h b/include/dt-bindings/clock/sun50i-r329-ccu.h
> new file mode 100644
> index 000000000000..116f8d13a9b3
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> +
> +#define CLK_CPUX		1
> +
> +#define CLK_APB1		5
> +
> +#define CLK_CE			7
> +#define CLK_BUS_CE		8
> +#define CLK_AIPU		9
> +#define CLK_BUS_AIPU		10
> +#define CLK_BUS_DMA		11
> +#define CLK_BUS_MSGBOX		12
> +#define CLK_BUS_SPINLOCK	13
> +#define CLK_BUS_HSTIMER		14
> +#define CLK_AVS			15
> +#define CLK_BUS_DBG		16
> +#define CLK_BUS_PWM		17
> +
> +#define CLK_MBUS_DMA		19
> +#define CLK_MBUS_CE		20
> +#define CLK_MBUS_R_DMA		21
> +#define CLK_MBUS_NAND		22
> +#define CLK_MBUS_AIPU		23
> +
> +#define CLK_NAND0		25
> +#define CLK_NAND1		26
> +#define CLK_BUS_NAND		27
> +#define CLK_MMC0		28
> +#define CLK_MMC1		29
> +#define CLK_BUS_MMC0		30
> +#define CLK_BUS_MMC1		31
> +#define CLK_BUS_UART0		32
> +#define CLK_BUS_UART1		33
> +#define CLK_BUS_UART2		34
> +#define CLK_BUS_UART3		35
> +#define CLK_BUS_I2C0		36
> +#define CLK_BUS_I2C1		37
> +#define CLK_BUS_SCR		38
> +#define CLK_SPI0		39
> +#define CLK_SPI1		40
> +#define CLK_BUS_SPI0		41
> +#define CLK_BUS_SPI1		42
> +#define CLK_EMAC_25M_DIV	43
> +#define CLK_EMAC_25M		44
> +#define CLK_BUS_EMAC		45
> +#define CLK_IR_RX		46
> +#define CLK_BUS_IR_RX		47
> +#define CLK_IR_TX		48
> +#define CLK_BUS_IR_TX		49
> +#define CLK_I2S0		50
> +#define CLK_I2S1		51
> +#define CLK_BUS_I2S0		52
> +#define CLK_BUS_I2S1		53
> +#define CLK_SPDIF		54
> +#define CLK_BUS_SPDIF		55
> +#define CLK_USB_OHCI0		56
> +#define CLK_USB_PHY0		57
> +#define CLK_USB_OHCI1		58
> +#define CLK_USB_PHY1		59
> +#define CLK_BUS_OHCI0		60
> +#define CLK_BUS_OHCI1		61
> +#define CLK_BUS_EHCI0		62
> +#define CLK_BUS_OTG		63
> +#define CLK_LEDC		64
> +#define CLK_BUS_LEDC		65
> +
> +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h b/include/dt-bindings/reset/sun50i-r329-ccu.h
> new file mode 100644
> index 000000000000..bb704a82443f
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
> @@ -0,0 +1,45 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> +/*
> + * Copyright (c) 2021 Sipeed
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> +#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> +
> +#define RST_MBUS		0
> +#define RST_BUS_CE		1
> +#define RST_BUS_AIPU		2
> +#define RST_BUS_DMA		3
> +#define RST_BUS_MSGBOX		4
> +#define RST_BUS_SPINLOCK	5
> +#define RST_BUS_HSTIMER		6
> +#define RST_BUS_DBG		7
> +#define RST_BUS_PWM		8
> +#define RST_BUS_DRAM		9
> +#define RST_BUS_NAND		10
> +#define RST_BUS_MMC0		11
> +#define RST_BUS_MMC1		12
> +#define RST_BUS_UART0		13
> +#define RST_BUS_UART1		14
> +#define RST_BUS_UART2		15
> +#define RST_BUS_UART3		16
> +#define RST_BUS_I2C0		17
> +#define RST_BUS_I2C1		18
> +#define RST_BUS_SCR		19
> +#define RST_BUS_SPI0		20
> +#define RST_BUS_SPI1		21
> +#define RST_BUS_EMAC		22
> +#define RST_BUS_IR_RX		23
> +#define RST_BUS_IR_TX		24
> +#define RST_BUS_I2S0		25
> +#define RST_BUS_I2S1		26
> +#define RST_BUS_SPDIF		27
> +#define RST_USB_PHY0		28
> +#define RST_USB_PHY1		29
> +#define RST_BUS_OHCI0		30
> +#define RST_BUS_OHCI1		31
> +#define RST_BUS_EHCI0		32
> +#define RST_BUS_OTG		33
> +#define RST_BUS_LEDC		34
> +
> +#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 13/17] mmc: sunxi: add support for R329 MMC controllers
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-20  2:43     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  2:43 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> The two MMC controllers in Allwinner R329 have a mixed feature set
> comparing to the previous SoCs' ordinary MMC and eMMC controllers.
> 
> Add support for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/mmc/host/sunxi-mmc.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)

Reviewed-by: Samuel Holland <samuel@sholland.org>

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

* Re: [PATCH 13/17] mmc: sunxi: add support for R329 MMC controllers
@ 2021-08-20  2:43     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  2:43 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> The two MMC controllers in Allwinner R329 have a mixed feature set
> comparing to the previous SoCs' ordinary MMC and eMMC controllers.
> 
> Add support for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  drivers/mmc/host/sunxi-mmc.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)

Reviewed-by: Samuel Holland <samuel@sholland.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
  2021-08-02  6:22   ` Icenowy Zheng
@ 2021-08-20  2:59     ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  2:59 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 is a new SoC focused on smart audio devices.
> 
> Add a DTSI file for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
>  1 file changed, 244 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi

One comment below.

All of my other concerns are about the CCU and RTC bindings, which I have
commented on elsewhere.

Regards,
Samuel

> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> new file mode 100644
> index 000000000000..bfefa2b734b0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +// Copyright (c) 2021 Sipeed
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +/ {
> +	interrupt-parent = <&gic>;
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@0 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <0>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu1: cpu@1 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <1>;
> +			enable-method = "psci";
> +		};
> +	};
> +
> +	osc24M: osc24M_clk {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "osc24M";
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		arm,no-tick-in-suspend;
> +		interrupts = <GIC_PPI 13
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 14
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 11
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 10
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
> +	};
> +
> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +		pio: pinctrl@2000400 {
> +			compatible = "allwinner,sun50i-r329-pinctrl";
> +			reg = <0x02000400 0x400>;
> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,

There is an IRQ documented for port C (at SPI 70). Do those pins possibly have
interrupt capability?

> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
> +			clock-names = "apb", "hosc", "losc";
> +			gpio-controller;
> +			#gpio-cells = <3>;
> +			interrupt-controller;
> +			#interrupt-cells = <3>;

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
@ 2021-08-20  2:59     ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  2:59 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> Allwinner R329 is a new SoC focused on smart audio devices.
> 
> Add a DTSI file for it.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> ---
>  .../arm64/boot/dts/allwinner/sun50i-r329.dtsi | 244 ++++++++++++++++++
>  1 file changed, 244 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi

One comment below.

All of my other concerns are about the CCU and RTC bindings, which I have
commented on elsewhere.

Regards,
Samuel

> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> new file mode 100644
> index 000000000000..bfefa2b734b0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-r329.dtsi
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +// Copyright (c) 2021 Sipeed
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> +#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
> +#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
> +
> +/ {
> +	interrupt-parent = <&gic>;
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@0 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <0>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu1: cpu@1 {
> +			compatible = "arm,cortex-a53";
> +			device_type = "cpu";
> +			reg = <1>;
> +			enable-method = "psci";
> +		};
> +	};
> +
> +	osc24M: osc24M_clk {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "osc24M";
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		arm,no-tick-in-suspend;
> +		interrupts = <GIC_PPI 13
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 14
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 11
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 10
> +			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
> +	};
> +
> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +		pio: pinctrl@2000400 {
> +			compatible = "allwinner,sun50i-r329-pinctrl";
> +			reg = <0x02000400 0x400>;
> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,

There is an IRQ documented for port C (at SPI 70). Do those pins possibly have
interrupt capability?

> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
> +			clock-names = "apb", "hosc", "losc";
> +			gpio-controller;
> +			#gpio-cells = <3>;
> +			interrupt-controller;
> +			#interrupt-cells = <3>;

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
  2021-08-19  2:32         ` Samuel Holland
@ 2021-08-20  3:06           ` Samuel Holland
  -1 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  3:06 UTC (permalink / raw)
  To: Icenowy Zheng, Maxime Ripard
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel

On 8/18/21 9:32 PM, Samuel Holland wrote:
> On 8/18/21 4:15 AM, Icenowy Zheng wrote:
>> 于 2021年8月18日 GMT+08:00 下午5:01:39, Maxime Ripard <maxime@cerno.tech> 写到:
>>> On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
>>>> +		ccu: clock@2001000 {
>>>> +			compatible = "allwinner,sun50i-r329-ccu";
>>>> +			reg = <0x02001000 0x1000>;
>>>> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
>>>> +			clock-names = "hosc", "losc", "iosc";
>>>
>>> Do we have a clock tree for the RTC? Is it the same than the H616?
>>
>> Nope, it's the same with H6 because of external LOSC crystal is
>> possible. (Although production M2A SoMs has it NC for cost control.)
> 
> It is not the same as the H6, either. The clock tree _is_ identical to the D1,
> which has three diagrams on pages 363-364 of its user manual here:
> 
> https://dl.linux-sunxi.org/D1/D1_User_Manual_V0.1_Draft_Version.pdf
> 
> Compared to the H6, the R329/D1:
>  - Loses the LOSC calibration circuit
>  - Gains a third mux input for LOSC (not external 32k) to fanout
>  - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
>  - Gains an SPI bus clock input divided from the PRCM AHB
> 
> Compared to the H616, the R329/D1:
>  - Has an external 32k crystal input
>    - Gains the IOSC vs. external 32k crystal mux for LOSC
>    - Switches fanout mux input #1 from pll_periph0/N to external 32k
>  - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
>  - Gains an SPI bus clock input divided from the PRCM AHB
> 
> So the R329/D1 RTC has three^Wfour inputs:
>  - SPI clock from PRCM
>  - 24 MHz DCXO crystal
>  - 32 kHz external crystal (optional)

Whoops, I missed one here:
 - Bus clock from PRCM

The SPI clock is new for R329, but the bus clock has been around since H6.

> and four outputs:
>  - 16 MHz "IOSC" RC oscillator
>  - 32 kHz "LOSC"
>  - ~1 kHz for RTC timekeeping

Even though this is internal to the RTC, it is still useful to model, as it can
be used to correct for known RTC drift. (For example, HOSC/750 is 32000 Hz
instead of 32768 Hz, so 2.34375% slow. But that is better than IOSC, which has
unknown error.)

>  - 32 kHz fanout
> 
> (Arguably, since the 24 MHz DCXO can be turned on/off from the RTC registers, it
> should be an "output" and not an "input".)
> 
> Regards,
> Samuel
> 


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

* Re: [PATCH 15/17] arm64: allwinner: dts: add DTSI file for R329 SoC
@ 2021-08-20  3:06           ` Samuel Holland
  0 siblings, 0 replies; 112+ messages in thread
From: Samuel Holland @ 2021-08-20  3:06 UTC (permalink / raw)
  To: Icenowy Zheng, Maxime Ripard
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, Ulf Hansson,
	Linus Walleij, Alexandre Belloni, Andre Przywara, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel

On 8/18/21 9:32 PM, Samuel Holland wrote:
> On 8/18/21 4:15 AM, Icenowy Zheng wrote:
>> 于 2021年8月18日 GMT+08:00 下午5:01:39, Maxime Ripard <maxime@cerno.tech> 写到:
>>> On Mon, Aug 02, 2021 at 02:22:10PM +0800, Icenowy Zheng wrote:
>>>> +		ccu: clock@2001000 {
>>>> +			compatible = "allwinner,sun50i-r329-ccu";
>>>> +			reg = <0x02001000 0x1000>;
>>>> +			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
>>>> +			clock-names = "hosc", "losc", "iosc";
>>>
>>> Do we have a clock tree for the RTC? Is it the same than the H616?
>>
>> Nope, it's the same with H6 because of external LOSC crystal is
>> possible. (Although production M2A SoMs has it NC for cost control.)
> 
> It is not the same as the H6, either. The clock tree _is_ identical to the D1,
> which has three diagrams on pages 363-364 of its user manual here:
> 
> https://dl.linux-sunxi.org/D1/D1_User_Manual_V0.1_Draft_Version.pdf
> 
> Compared to the H6, the R329/D1:
>  - Loses the LOSC calibration circuit
>  - Gains a third mux input for LOSC (not external 32k) to fanout
>  - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
>  - Gains an SPI bus clock input divided from the PRCM AHB
> 
> Compared to the H616, the R329/D1:
>  - Has an external 32k crystal input
>    - Gains the IOSC vs. external 32k crystal mux for LOSC
>    - Switches fanout mux input #1 from pll_periph0/N to external 32k
>  - Gains a mux to choose between LOSC and HOSC/750 for the RTC clock
>  - Gains an SPI bus clock input divided from the PRCM AHB
> 
> So the R329/D1 RTC has three^Wfour inputs:
>  - SPI clock from PRCM
>  - 24 MHz DCXO crystal
>  - 32 kHz external crystal (optional)

Whoops, I missed one here:
 - Bus clock from PRCM

The SPI clock is new for R329, but the bus clock has been around since H6.

> and four outputs:
>  - 16 MHz "IOSC" RC oscillator
>  - 32 kHz "LOSC"
>  - ~1 kHz for RTC timekeeping

Even though this is internal to the RTC, it is still useful to model, as it can
be used to correct for known RTC drift. (For example, HOSC/750 is 32000 Hz
instead of 32768 Hz, so 2.34375% slow. But that is better than IOSC, which has
unknown error.)

>  - 32 kHz fanout
> 
> (Arguably, since the 24 MHz DCXO can be turned on/off from the RTC registers, it
> should be an "output" and not an "input".)
> 
> Regards,
> Samuel
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
  2021-08-20  2:41     ` Samuel Holland
@ 2021-08-20  3:52       ` Icenowy Zheng
  -1 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-20  3:52 UTC (permalink / raw)
  To: Samuel Holland, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

在 2021-08-19星期四的 21:41 -0500,Samuel Holland写道:
> On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> > Allwinner R329 has a CCU that is similar to the H616 one, but it's
> > cut
> > down and have PLLs moved out.
> > 
> > Add support for it.
> > 
> > Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> > ---
> >  drivers/clk/sunxi-ng/Kconfig                |   5 +
> >  drivers/clk/sunxi-ng/Makefile               |   1 +
> >  drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526
> > ++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
> >  include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
> >  include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++
> >  6 files changed, 682 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> >  create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
> >  create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> > ng/Kconfig
> > index e49b2c2fa5b7..4b32d5f81ea8 100644
> > --- a/drivers/clk/sunxi-ng/Kconfig
> > +++ b/drivers/clk/sunxi-ng/Kconfig
> > @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
> >         default ARM64 && ARCH_SUNXI
> >         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> >  
> > +config SUN50I_R329_CCU
> > +       bool "Support for the Allwinner R329 CCU"
> > +       default ARM64 && ARCH_SUNXI
> > +       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> > +
> >  config SUN50I_R329_R_CCU
> >         bool "Support for the Allwinner R329 PRCM CCU"
> >         default ARM64 && ARCH_SUNXI
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-
> > ng/Makefile
> > index db338a2188fd..62f3c5bf331c 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)       += ccu-
> > sun50i-a100-r.o
> >  obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
> >  obj-$(CONFIG_SUN50I_H616_CCU)  += ccu-sun50i-h616.o
> >  obj-$(CONFIG_SUN50I_H6_R_CCU)  += ccu-sun50i-h6-r.o
> > +obj-$(CONFIG_SUN50I_R329_CCU)  += ccu-sun50i-r329.o
> >  obj-$(CONFIG_SUN50I_R329_R_CCU)        += ccu-sun50i-r329-r.o
> >  obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
> >  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> > b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> > new file mode 100644
> > index 000000000000..a0b4cfd6e1db
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> > @@ -0,0 +1,526 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Based on the H616 CCU driver, which is:
> > + *   Copyright (c) 2020 Arm Ltd.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.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-sun50i-r329.h"
> > +
> > +/*
> > + * An external divider of PLL-CPUX is controlled here. As it's
> > similar to
> > + * the external divider of PLL-CPUX on previous SoCs (only usable
> > under
> > + * 288MHz}, ignore it.
> 
> Mismatched (braces} here
> 
> > + */
> > +static const char * const cpux_parents[] = { "osc24M", "osc32k",
> > "iosc",
> > +                                            "pll-cpux", "pll-
> > periph",
> > +                                            "pll-periph-2x",
> > +                                            "pll=periph-800m" };
> 
> = should be a -.
> 
> Now that these PLLs are in a different device, how is this supposed
> to affect
> the DT binding? Do we put all of them in the clocks property?
> 
> If so, we can use .fw_name at some point. If not, why bother with the
> clocks
> property at all? This is another part of the "let's get the clock
> tree right
> from the start" discussion.

Well we don't now, because I think it's too dirty to put all PLLs into
the device tree, but I must admit that this should be correct.

> 
> > +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
> > +                    0x500, 24, 3, CLK_SET_RATE_PARENT |
> > CLK_IS_CRITICAL);
> > +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
> > +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2,
> > 0);
> > +
> > +static const char * const ahb_parents[] = { "osc24M", "osc32k",
> > +                                           "iosc", "pll-periph" };
> > +static SUNXI_CCU_MP_WITH_MUX(ahb_clk, "ahb",
> > +                            ahb_parents, 0x510,
> > +                            0, 2,      /* M */
> > +                            8, 2,      /* P */
> > +                            24, 3,     /* mux */
> > +                            0);
> > +
> > +static const char * const apb_parents[] = { "osc24M", "osc32k",
> > +                                           "ahb", "pll-periph" };
> > +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb_parents, 0x520,
> > +                            0, 2,      /* M */
> > +                            8, 2,      /* P */
> > +                            24, 3,     /* mux */
> > +                            0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb_parents, 0x524,
> > +                            0, 2,      /* M */
> > +                            8, 2,      /* P */
> > +                            24, 3,     /* mux */
> > +                            0);
> 
> Hmm, so Allwinner is inconsistent with these. The manual has
> APB0/APB1, but the
> BSP has APB1/APB2.
> 
> > +
> > +static const char * const ce_parents[] = { "osc24M", "pll-periph-
> > 2x" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 1,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb",
> > +                     0x68c, BIT(0), 0);
> > +
> > +static const char * const aipu_parents[] = { "pll-periph-2x",
> > "pll-periph-800m",
> > +                                            "pll-audio0-div2",
> > "pll-audio0-div5",
> > +                                            "pll-cpux" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(aipu_clk, "aipu", aipu_parents,
> > 0x6f0,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_aipu_clk, "bus-aipu", "ahb",
> > +                     0x6fc, BIT(0), 0);
> 
> The manual has separate gates for an AIPU AHB master at bit 1, and an
> AHB slave
> at bit 0.
> 
> > +
> > +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
> > +                     0x70c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb",
> > +                     0x71c, BIT(0), 0);
> 
> There are two message boxes (bits 0 and 1).
> 
> > +
> > +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb",
> > +                     0x72c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb",
> > +                     0x73c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31),
> > 0);
> > +
> > +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb",
> > +                     0x78c, BIT(0), 0);
> 
> There is a gate for the PSI clock (the parent for the AHB clocks) at
> 0x79c.
> 
> > +
> > +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac,
> > BIT(0), 0);
> > +
> > +static const char * const dram_parents[] = { "pll-periph-2x",
> > +                                            "pll-periph-800m",
> > +                                            "pll-audio0-div2",
> > +                                            "pll-audio0-div5" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents,
> > 0x800,
> > +                                 0, 2,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 CLK_IS_CRITICAL);
> > +
> > +
> > +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "dram",
> > +                     0x804, BIT(0), 0);
> > +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "dram",
> > +                     0x804, BIT(2), 0);
> > +static SUNXI_CCU_GATE(mbus_r_dma_clk, "mbus-r-dma", "dram",
> > +                     0x804, BIT(3), 0);
> > +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "dram",
> > +                     0x804, BIT(5), 0);
> > +static SUNXI_CCU_GATE(mbus_aipu_clk, "mbus-aipu", "dram",
> > +                     0x804, BIT(16), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
> > +                     0x80c, BIT(0), CLK_IS_CRITICAL);
> 
> The DRAM bus clock is not critical. It only needs to be enabled for
> register
> access (PMU, DVFS).
> 
> > +
> > +static const char * const nand_parents[] = { "osc24M", "pll-
> > periph",
> > +                                            "pll-audio-div2",
> > +                                            "pll-periph-2x" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0",
> > nand_parents, 0x810,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1",
> > nand_parents, 0x814,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb", 0x82c,
> > BIT(0), 0);
> > +
> > +static const char * const mmc_parents[] = { "osc24M", "pll-
> > periph",
> > +                                           "pll-periph-2x",
> > +                                           "pll-audio0-div2" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0",
> > mmc_parents, 0x830,
> > +                                         0, 4,         /* M */
> > +                                         8, 2,         /* P */
> > +                                         24, 2,        /* mux */
> > +                                         BIT(31),      /* gate */
> > +                                         2,            /* post-div
> > */
> > +                                         0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1",
> > mmc_parents, 0x834,
> > +                                         0, 4,         /* M */
> > +                                         8, 2,         /* P */
> > +                                         24, 2,        /* mux */
> > +                                         BIT(31),      /* gate */
> > +                                         2,            /* post-div
> > */
> 
> Where does the post-divider come from?
> 
> > +                                         0);
> > +
> > +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 0x84c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 0x84c,
> > BIT(1), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c,
> > BIT(1), 0);
> > +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c,
> > BIT(2), 0);
> > +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c,
> > BIT(3), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c,
> > BIT(1), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 0x93c,
> > BIT(0), 0);
> > +
> > +static const char * const spi_parents[] = { "osc24M", "pll-
> > periph",
> > +                                           "pll-periph-2x",
> > +                                           "pll-audio0-div2",
> > +                                           "pll-audio0-div5" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents,
> > 0x940,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents,
> > 0x944,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 0x96c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 0x96c,
> > BIT(1), 0);
> > +
> > +static CLK_FIXED_FACTOR(emac_25m_div_clk, "emac-25m-div", "pll-
> > periph",
> > +                       2, 1, 0);
> > +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "emac-25m-div",
> > 0x970,
> > +                     BIT(31) | BIT(30), 0);
> 
> The divider should be 24, not 2. And you can use
> CCU_FEATURE_ALL_PREDIV on the
> gate to remove the separate divider clock.
> 
> > +
> > +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb", 0x97c,
> > BIT(0), 0);
> > +
> > +static const char * const ir_parents[] = { "osc32k", "iosc",
> 
> Both the manual and the BSP have the second parent as osc24M, not
> iosc.
> 
> > +                                          "pll-periph", "pll-
> > audio0-div2" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents,
> > 0x990,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "apb1", 0x99c,
> > BIT(0), 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents,
> > 0x9c0,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc,
> > BIT(0), 0);
> > +
> > +static const char * const audio_parents[] = { "pll-audio1",
> > +                                             "pll-audio1-4x",
> > +                                             "pll-audio0-div2",
> > +                                             "pll-audio0-div5" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents,
> > 0xa10,
> > +                                 0, 4,         /* M */
> 
> All of the audio modules have 5-bit M dividers.
> 
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents,
> > 0xa14,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20,
> > BIT(1), 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_clk, "spdif",
> > audio_parents, 0xa20,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c,
> > BIT(0), 0);
> > +
> > +/*
> > + * There are OHCI 12M clock source selection bits for 2 USB 2.0
> > ports.
> > + * We will force them to 0 (12M divided from 48M).
> > + */
> > +#define SUN50I_R329_USB0_CLK_REG               0xa70
> > +#define SUN50I_R329_USB1_CLK_REG               0xa74
> 
> This "48M" clock is divided/synchronized from pll-periph, as shown in
> the
> "Module Clock Generation" diagram and USB "PHY Connection Diagram" in
> the
> manual. So I recommend the following structure:
> 
> static CLK_FIXED_FACTOR(usb_48M_clk, "usb-48M",
>                         "pll-periph", 25, 2, 0);
> 
> static CLK_FIXED_FACTOR_HW(usb_12M_clk, "usb-12M",
>                            &usb_48M_clk.hw, 4, 1, 0);
> 
> static const char *const usb_ohci_parents[] = { "usb-12M", "osc12M",
>                                                 "osc32k" };
> static SUNXI_CCU_MUX_WITH_GATE(usb_ohci0_clk, "usb-ohci0",
>                                usb_ohci_parents, 0xa70,
>                                24, 2,           /* mux */
>                                BIT(31),         /* gate */
>                                0);
> 
> static SUNXI_CCU_MUX_WITH_GATE(usb_ohci1_clk, "usb-ohci1",
>                                usb_ohci_parents, 0xa74,
>                                24, 2,           /* mux */
>                                BIT(31),         /* gate */
>                                0);
> 
> For anyone following along without R329 documents, this is all the
> same as the
> D1, though the labels in the diagrams are slightly different. Hooray
> for finally
> documenting this so it is no longer "mysterious"!
> 
> Regards,
> Samuel
> 
> > +
> > +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70,
> > BIT(31), 0);
> > +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70,
> > BIT(29), 0);
> > +
> > +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74,
> > BIT(31), 0);
> > +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74,
> > BIT(29), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb", 0xa8c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb", 0xa8c,
> > BIT(1), 0);
> > +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb", 0xa8c,
> > BIT(4), 0);
> > +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 0xa8c,
> > BIT(8), 0);
> > +
> > +static const char * const ledc_parents[] = { "osc24M", "pll-
> > periph" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents,
> > 0xbf0,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 1,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "apb1", 0xbfc,
> > BIT(0), 0);
> > +
> > +/* Fixed factor clocks */
> > +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2,
> > 1, 0);
> > +
> > +static struct ccu_common *sun50i_r329_ccu_clks[] = {
> > +       &cpux_clk.common,
> > +       &axi_clk.common,
> > +       &cpux_apb_clk.common,
> > +       &ahb_clk.common,
> > +       &apb1_clk.common,
> > +       &apb2_clk.common,
> > +       &ce_clk.common,
> > +       &bus_ce_clk.common,
> > +       &aipu_clk.common,
> > +       &bus_aipu_clk.common,
> > +       &bus_dma_clk.common,
> > +       &bus_msgbox_clk.common,
> > +       &bus_spinlock_clk.common,
> > +       &bus_hstimer_clk.common,
> > +       &avs_clk.common,
> > +       &bus_dbg_clk.common,
> > +       &bus_pwm_clk.common,
> > +       &dram_clk.common,
> > +       &mbus_dma_clk.common,
> > +       &mbus_ce_clk.common,
> > +       &mbus_r_dma_clk.common,
> > +       &mbus_nand_clk.common,
> > +       &mbus_aipu_clk.common,
> > +       &bus_dram_clk.common,
> > +       &nand0_clk.common,
> > +       &nand1_clk.common,
> > +       &bus_nand_clk.common,
> > +       &mmc0_clk.common,
> > +       &mmc1_clk.common,
> > +       &bus_mmc0_clk.common,
> > +       &bus_mmc1_clk.common,
> > +       &bus_uart0_clk.common,
> > +       &bus_uart1_clk.common,
> > +       &bus_uart2_clk.common,
> > +       &bus_uart3_clk.common,
> > +       &bus_i2c0_clk.common,
> > +       &bus_i2c1_clk.common,
> > +       &bus_scr_clk.common,
> > +       &spi0_clk.common,
> > +       &spi1_clk.common,
> > +       &bus_spi0_clk.common,
> > +       &bus_spi1_clk.common,
> > +       &emac_25m_clk.common,
> > +       &bus_emac_clk.common,
> > +       &ir_rx_clk.common,
> > +       &bus_ir_rx_clk.common,
> > +       &ir_tx_clk.common,
> > +       &bus_ir_tx_clk.common,
> > +       &i2s0_clk.common,
> > +       &i2s1_clk.common,
> > +       &bus_i2s0_clk.common,
> > +       &bus_i2s1_clk.common,
> > +       &spdif_clk.common,
> > +       &bus_spdif_clk.common,
> > +       &usb_ohci0_clk.common,
> > +       &usb_phy0_clk.common,
> > +       &usb_ohci1_clk.common,
> > +       &usb_phy1_clk.common,
> > +       &bus_ohci0_clk.common,
> > +       &bus_ohci1_clk.common,
> > +       &bus_ehci0_clk.common,
> > +       &bus_otg_clk.common,
> > +       &ledc_clk.common,
> > +       &bus_ledc_clk.common,
> > +};
> > +
> > +static struct clk_hw_onecell_data sun50i_r329_hw_clks = {
> > +       .hws    = {
> > +               [CLK_OSC12M]            = &osc12M_clk.hw,
> > +               [CLK_CPUX]              = &cpux_clk.common.hw,
> > +               [CLK_AXI]               = &axi_clk.common.hw,
> > +               [CLK_CPUX_APB]          = &cpux_apb_clk.common.hw,
> > +               [CLK_AHB]               = &ahb_clk.common.hw,
> > +               [CLK_APB1]              = &apb1_clk.common.hw,
> > +               [CLK_APB2]              = &apb2_clk.common.hw,
> > +               [CLK_CE]                = &ce_clk.common.hw,
> > +               [CLK_BUS_CE]            = &bus_ce_clk.common.hw,
> > +               [CLK_AIPU]              = &aipu_clk.common.hw,
> > +               [CLK_BUS_AIPU]          = &bus_aipu_clk.common.hw,
> > +               [CLK_BUS_DMA]           = &bus_dma_clk.common.hw,
> > +               [CLK_BUS_MSGBOX]        =
> > &bus_msgbox_clk.common.hw,
> > +               [CLK_BUS_SPINLOCK]      =
> > &bus_spinlock_clk.common.hw,
> > +               [CLK_BUS_HSTIMER]       =
> > &bus_hstimer_clk.common.hw,
> > +               [CLK_AVS]               = &avs_clk.common.hw,
> > +               [CLK_BUS_DBG]           = &bus_dbg_clk.common.hw,
> > +               [CLK_BUS_PWM]           = &bus_pwm_clk.common.hw,
> > +               [CLK_DRAM]              = &dram_clk.common.hw,
> > +               [CLK_MBUS_DMA]          = &mbus_dma_clk.common.hw,
> > +               [CLK_MBUS_CE]           = &mbus_ce_clk.common.hw,
> > +               [CLK_MBUS_R_DMA]        =
> > &mbus_r_dma_clk.common.hw,
> > +               [CLK_MBUS_NAND]         = &mbus_nand_clk.common.hw,
> > +               [CLK_MBUS_AIPU]         = &mbus_aipu_clk.common.hw,
> > +               [CLK_BUS_DRAM]          = &bus_dram_clk.common.hw,
> > +               [CLK_NAND0]             = &nand0_clk.common.hw,
> > +               [CLK_NAND1]             = &nand1_clk.common.hw,
> > +               [CLK_BUS_NAND]          = &bus_nand_clk.common.hw,
> > +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> > +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> > +               [CLK_BUS_MMC0]          = &bus_mmc0_clk.common.hw,
> > +               [CLK_BUS_MMC1]          = &bus_mmc1_clk.common.hw,
> > +               [CLK_BUS_UART0]         = &bus_uart0_clk.common.hw,
> > +               [CLK_BUS_UART1]         = &bus_uart1_clk.common.hw,
> > +               [CLK_BUS_UART2]         = &bus_uart2_clk.common.hw,
> > +               [CLK_BUS_UART3]         = &bus_uart3_clk.common.hw,
> > +               [CLK_BUS_I2C0]          = &bus_i2c0_clk.common.hw,
> > +               [CLK_BUS_I2C1]          = &bus_i2c1_clk.common.hw,
> > +               [CLK_BUS_SCR]           = &bus_scr_clk.common.hw,
> > +               [CLK_SPI0]              = &spi0_clk.common.hw,
> > +               [CLK_SPI1]              = &spi1_clk.common.hw,
> > +               [CLK_BUS_SPI0]          = &bus_spi0_clk.common.hw,
> > +               [CLK_BUS_SPI1]          = &bus_spi1_clk.common.hw,
> > +               [CLK_EMAC_25M_DIV]      = &emac_25m_div_clk.hw,
> > +               [CLK_EMAC_25M]          = &emac_25m_clk.common.hw,
> > +               [CLK_BUS_EMAC]          = &bus_emac_clk.common.hw,
> > +               [CLK_IR_RX]             = &ir_rx_clk.common.hw,
> > +               [CLK_BUS_IR_RX]         = &bus_ir_rx_clk.common.hw,
> > +               [CLK_IR_TX]             = &ir_tx_clk.common.hw,
> > +               [CLK_BUS_IR_TX]         = &bus_ir_tx_clk.common.hw,
> > +               [CLK_I2S0]              = &i2s0_clk.common.hw,
> > +               [CLK_I2S1]              = &i2s1_clk.common.hw,
> > +               [CLK_BUS_I2S0]          = &bus_i2s0_clk.common.hw,
> > +               [CLK_BUS_I2S1]          = &bus_i2s1_clk.common.hw,
> > +               [CLK_SPDIF]             = &spdif_clk.common.hw,
> > +               [CLK_BUS_SPDIF]         = &bus_spdif_clk.common.hw,
> > +               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
> > +               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
> > +               [CLK_USB_OHCI1]         = &usb_ohci1_clk.common.hw,
> > +               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
> > +               [CLK_BUS_OHCI0]         = &bus_ohci0_clk.common.hw,
> > +               [CLK_BUS_OHCI1]         = &bus_ohci1_clk.common.hw,
> > +               [CLK_BUS_EHCI0]         = &bus_ehci0_clk.common.hw,
> > +               [CLK_BUS_OTG]           = &bus_otg_clk.common.hw,
> > +               [CLK_LEDC]              = &ledc_clk.common.hw,
> > +               [CLK_BUS_LEDC]          = &bus_ledc_clk.common.hw,
> > +       },
> > +       .num = CLK_NUMBER,
> > +};
> > +
> > +static struct ccu_reset_map sun50i_r329_ccu_resets[] = {
> > +       [RST_MBUS]              = { 0x540, BIT(30) },
> > +
> > +       [RST_BUS_CE]            = { 0x68c, BIT(16) },
> > +       [RST_BUS_AIPU]          = { 0x6fc, BIT(16) },
> > +       [RST_BUS_DMA]           = { 0x70c, BIT(16) },
> > +       [RST_BUS_MSGBOX]        = { 0x71c, BIT(16) },
> > +       [RST_BUS_SPINLOCK]      = { 0x72c, BIT(16) },
> > +       [RST_BUS_HSTIMER]       = { 0x73c, BIT(16) },
> > +       [RST_BUS_DBG]           = { 0x78c, BIT(16) },
> > +       [RST_BUS_PWM]           = { 0x7ac, BIT(16) },
> > +       [RST_BUS_DRAM]          = { 0x80c, BIT(16) },
> > +       [RST_BUS_NAND]          = { 0x82c, BIT(16) },
> > +       [RST_BUS_MMC0]          = { 0x84c, BIT(16) },
> > +       [RST_BUS_MMC1]          = { 0x84c, BIT(17) },
> > +       [RST_BUS_UART0]         = { 0x90c, BIT(16) },
> > +       [RST_BUS_UART1]         = { 0x90c, BIT(17) },
> > +       [RST_BUS_UART2]         = { 0x90c, BIT(18) },
> > +       [RST_BUS_UART3]         = { 0x90c, BIT(19) },
> > +       [RST_BUS_I2C0]          = { 0x91c, BIT(16) },
> > +       [RST_BUS_I2C1]          = { 0x91c, BIT(17) },
> > +       [RST_BUS_SCR]           = { 0x93c, BIT(16) },
> > +       [RST_BUS_SPI0]          = { 0x96c, BIT(16) },
> > +       [RST_BUS_SPI1]          = { 0x96c, BIT(17) },
> > +       [RST_BUS_EMAC]          = { 0x97c, BIT(16) },
> > +       [RST_BUS_IR_RX]         = { 0x99c, BIT(16) },
> > +       [RST_BUS_IR_TX]         = { 0x9cc, BIT(16) },
> > +       [RST_BUS_I2S0]          = { 0xa1c, BIT(16) },
> > +       [RST_BUS_I2S1]          = { 0xa1c, BIT(17) },
> > +       [RST_BUS_SPDIF]         = { 0xa2c, BIT(16) },
> > +
> > +       [RST_USB_PHY0]          = { 0xa70, BIT(30) },
> > +       [RST_USB_PHY1]          = { 0xa74, BIT(30) },
> > +
> > +       [RST_BUS_OHCI0]         = { 0xa8c, BIT(16) },
> > +       [RST_BUS_OHCI1]         = { 0xa8c, BIT(17) },
> > +       [RST_BUS_EHCI0]         = { 0xa8c, BIT(20) },
> > +       [RST_BUS_OTG]           = { 0xa8c, BIT(24) },
> > +
> > +       [RST_BUS_LEDC]          = { 0xbfc, BIT(16) },
> > +};
> > +
> > +static const struct sunxi_ccu_desc sun50i_r329_ccu_desc = {
> > +       .ccu_clks       = sun50i_r329_ccu_clks,
> > +       .num_ccu_clks   = ARRAY_SIZE(sun50i_r329_ccu_clks),
> > +
> > +       .hw_clks        = &sun50i_r329_hw_clks,
> > +
> > +       .resets         = sun50i_r329_ccu_resets,
> > +       .num_resets     = ARRAY_SIZE(sun50i_r329_ccu_resets),
> > +};
> > +
> > +static const u32 sun50i_r329_usb_clk_regs[] = {
> > +       SUN50I_R329_USB0_CLK_REG,
> > +       SUN50I_R329_USB1_CLK_REG,
> > +};
> > +
> > +static int sun50i_r329_ccu_probe(struct platform_device *pdev)
> > +{
> > +       void __iomem *reg;
> > +       u32 val;
> > +       int i;
> > +
> > +       reg = devm_platform_ioremap_resource(pdev, 0);
> > +       if (IS_ERR(reg))
> > +               return PTR_ERR(reg);
> > +
> > +       /*
> > +        * Force OHCI 12M clock sources to 00 (12MHz divided from
> > 48MHz)
> > +        *
> > +        * This clock mux is still mysterious, and the code just
> > enforces
> > +        * it to have a valid clock parent.
> > +        */
> > +       for (i = 0; i < ARRAY_SIZE(sun50i_r329_usb_clk_regs); i++)
> > {
> > +               val = readl(reg + sun50i_r329_usb_clk_regs[i]);
> > +               val &= ~GENMASK(25, 24);
> > +               writel(val, reg + sun50i_r329_usb_clk_regs[i]);
> > +       }
> > +
> > +       return sunxi_ccu_probe(pdev->dev.of_node, reg,
> > &sun50i_r329_ccu_desc);
> > +}
> > +
> > +static const struct of_device_id sun50i_r329_ccu_ids[] = {
> > +       { .compatible = "allwinner,sun50i-r329-ccu" },
> > +       { }
> > +};
> > +
> > +static struct platform_driver sun50i_r329_ccu_driver = {
> > +       .probe  = sun50i_r329_ccu_probe,
> > +       .driver = {
> > +               .name   = "sun50i-r329-ccu",
> > +               .of_match_table = sun50i_r329_ccu_ids,
> > +       },
> > +};
> > +module_platform_driver(sun50i_r329_ccu_driver);
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> > b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> > new file mode 100644
> > index 000000000000..144ac9954ef3
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> > @@ -0,0 +1,32 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2021 Sipeed
> > + */
> > +
> > +#ifndef _CCU_SUN50I_R329_H_
> > +#define _CCU_SUN50I_R329_H_
> > +
> > +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> > +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> > +
> > +#define CLK_OSC12M             0
> > +
> > +/* CPUX exported for DVFS */
> > +
> > +#define CLK_AXI                        2
> > +#define CLK_CPUX_APB           3
> > +#define CLK_AHB                        4
> > +
> > +/* APB1 exported for PIO */
> > +
> > +#define CLK_APB2               6
> > +
> > +/* Peripheral module and gate clock exported except for DRAM ones
> > */
> > +
> > +#define CLK_DRAM               18
> > +
> > +#define CLK_BUS_DRAM           24
> > +
> > +#define CLK_NUMBER             (CLK_BUS_LEDC + 1)
> > +
> > +#endif /* _CCU_SUN50I_R329_H_ */
> > diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h
> > b/include/dt-bindings/clock/sun50i-r329-ccu.h
> > new file mode 100644
> > index 000000000000..116f8d13a9b3
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
> > @@ -0,0 +1,73 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2021 Sipeed
> > + */
> > +
> > +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> > +#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> > +
> > +#define CLK_CPUX               1
> > +
> > +#define CLK_APB1               5
> > +
> > +#define CLK_CE                 7
> > +#define CLK_BUS_CE             8
> > +#define CLK_AIPU               9
> > +#define CLK_BUS_AIPU           10
> > +#define CLK_BUS_DMA            11
> > +#define CLK_BUS_MSGBOX         12
> > +#define CLK_BUS_SPINLOCK       13
> > +#define CLK_BUS_HSTIMER                14
> > +#define CLK_AVS                        15
> > +#define CLK_BUS_DBG            16
> > +#define CLK_BUS_PWM            17
> > +
> > +#define CLK_MBUS_DMA           19
> > +#define CLK_MBUS_CE            20
> > +#define CLK_MBUS_R_DMA         21
> > +#define CLK_MBUS_NAND          22
> > +#define CLK_MBUS_AIPU          23
> > +
> > +#define CLK_NAND0              25
> > +#define CLK_NAND1              26
> > +#define CLK_BUS_NAND           27
> > +#define CLK_MMC0               28
> > +#define CLK_MMC1               29
> > +#define CLK_BUS_MMC0           30
> > +#define CLK_BUS_MMC1           31
> > +#define CLK_BUS_UART0          32
> > +#define CLK_BUS_UART1          33
> > +#define CLK_BUS_UART2          34
> > +#define CLK_BUS_UART3          35
> > +#define CLK_BUS_I2C0           36
> > +#define CLK_BUS_I2C1           37
> > +#define CLK_BUS_SCR            38
> > +#define CLK_SPI0               39
> > +#define CLK_SPI1               40
> > +#define CLK_BUS_SPI0           41
> > +#define CLK_BUS_SPI1           42
> > +#define CLK_EMAC_25M_DIV       43
> > +#define CLK_EMAC_25M           44
> > +#define CLK_BUS_EMAC           45
> > +#define CLK_IR_RX              46
> > +#define CLK_BUS_IR_RX          47
> > +#define CLK_IR_TX              48
> > +#define CLK_BUS_IR_TX          49
> > +#define CLK_I2S0               50
> > +#define CLK_I2S1               51
> > +#define CLK_BUS_I2S0           52
> > +#define CLK_BUS_I2S1           53
> > +#define CLK_SPDIF              54
> > +#define CLK_BUS_SPDIF          55
> > +#define CLK_USB_OHCI0          56
> > +#define CLK_USB_PHY0           57
> > +#define CLK_USB_OHCI1          58
> > +#define CLK_USB_PHY1           59
> > +#define CLK_BUS_OHCI0          60
> > +#define CLK_BUS_OHCI1          61
> > +#define CLK_BUS_EHCI0          62
> > +#define CLK_BUS_OTG            63
> > +#define CLK_LEDC               64
> > +#define CLK_BUS_LEDC           65
> > +
> > +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
> > diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h
> > b/include/dt-bindings/reset/sun50i-r329-ccu.h
> > new file mode 100644
> > index 000000000000..bb704a82443f
> > --- /dev/null
> > +++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
> > @@ -0,0 +1,45 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> > +/*
> > + * Copyright (c) 2021 Sipeed
> > + */
> > +
> > +#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> > +#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> > +
> > +#define RST_MBUS               0
> > +#define RST_BUS_CE             1
> > +#define RST_BUS_AIPU           2
> > +#define RST_BUS_DMA            3
> > +#define RST_BUS_MSGBOX         4
> > +#define RST_BUS_SPINLOCK       5
> > +#define RST_BUS_HSTIMER                6
> > +#define RST_BUS_DBG            7
> > +#define RST_BUS_PWM            8
> > +#define RST_BUS_DRAM           9
> > +#define RST_BUS_NAND           10
> > +#define RST_BUS_MMC0           11
> > +#define RST_BUS_MMC1           12
> > +#define RST_BUS_UART0          13
> > +#define RST_BUS_UART1          14
> > +#define RST_BUS_UART2          15
> > +#define RST_BUS_UART3          16
> > +#define RST_BUS_I2C0           17
> > +#define RST_BUS_I2C1           18
> > +#define RST_BUS_SCR            19
> > +#define RST_BUS_SPI0           20
> > +#define RST_BUS_SPI1           21
> > +#define RST_BUS_EMAC           22
> > +#define RST_BUS_IR_RX          23
> > +#define RST_BUS_IR_TX          24
> > +#define RST_BUS_I2S0           25
> > +#define RST_BUS_I2S1           26
> > +#define RST_BUS_SPDIF          27
> > +#define RST_USB_PHY0           28
> > +#define RST_USB_PHY1           29
> > +#define RST_BUS_OHCI0          30
> > +#define RST_BUS_OHCI1          31
> > +#define RST_BUS_EHCI0          32
> > +#define RST_BUS_OTG            33
> > +#define RST_BUS_LEDC           34
> > +
> > +#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
> > 
> 
> 



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

* Re: [PATCH 11/17] clk: sunxi-ng: add support for Allwinner R329 CCU
@ 2021-08-20  3:52       ` Icenowy Zheng
  0 siblings, 0 replies; 112+ messages in thread
From: Icenowy Zheng @ 2021-08-20  3:52 UTC (permalink / raw)
  To: Samuel Holland, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, Ulf Hansson, Linus Walleij, Alexandre Belloni,
	Andre Przywara
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

在 2021-08-19星期四的 21:41 -0500,Samuel Holland写道:
> On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> > Allwinner R329 has a CCU that is similar to the H616 one, but it's
> > cut
> > down and have PLLs moved out.
> > 
> > Add support for it.
> > 
> > Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> > ---
> >  drivers/clk/sunxi-ng/Kconfig                |   5 +
> >  drivers/clk/sunxi-ng/Makefile               |   1 +
> >  drivers/clk/sunxi-ng/ccu-sun50i-r329.c      | 526
> > ++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu-sun50i-r329.h      |  32 ++
> >  include/dt-bindings/clock/sun50i-r329-ccu.h |  73 +++
> >  include/dt-bindings/reset/sun50i-r329-ccu.h |  45 ++
> >  6 files changed, 682 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> >  create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
> >  create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> > ng/Kconfig
> > index e49b2c2fa5b7..4b32d5f81ea8 100644
> > --- a/drivers/clk/sunxi-ng/Kconfig
> > +++ b/drivers/clk/sunxi-ng/Kconfig
> > @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
> >         default ARM64 && ARCH_SUNXI
> >         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> >  
> > +config SUN50I_R329_CCU
> > +       bool "Support for the Allwinner R329 CCU"
> > +       default ARM64 && ARCH_SUNXI
> > +       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> > +
> >  config SUN50I_R329_R_CCU
> >         bool "Support for the Allwinner R329 PRCM CCU"
> >         default ARM64 && ARCH_SUNXI
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-
> > ng/Makefile
> > index db338a2188fd..62f3c5bf331c 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)       += ccu-
> > sun50i-a100-r.o
> >  obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
> >  obj-$(CONFIG_SUN50I_H616_CCU)  += ccu-sun50i-h616.o
> >  obj-$(CONFIG_SUN50I_H6_R_CCU)  += ccu-sun50i-h6-r.o
> > +obj-$(CONFIG_SUN50I_R329_CCU)  += ccu-sun50i-r329.o
> >  obj-$(CONFIG_SUN50I_R329_R_CCU)        += ccu-sun50i-r329-r.o
> >  obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
> >  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> > b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> > new file mode 100644
> > index 000000000000..a0b4cfd6e1db
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.c
> > @@ -0,0 +1,526 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Based on the H616 CCU driver, which is:
> > + *   Copyright (c) 2020 Arm Ltd.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.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-sun50i-r329.h"
> > +
> > +/*
> > + * An external divider of PLL-CPUX is controlled here. As it's
> > similar to
> > + * the external divider of PLL-CPUX on previous SoCs (only usable
> > under
> > + * 288MHz}, ignore it.
> 
> Mismatched (braces} here
> 
> > + */
> > +static const char * const cpux_parents[] = { "osc24M", "osc32k",
> > "iosc",
> > +                                            "pll-cpux", "pll-
> > periph",
> > +                                            "pll-periph-2x",
> > +                                            "pll=periph-800m" };
> 
> = should be a -.
> 
> Now that these PLLs are in a different device, how is this supposed
> to affect
> the DT binding? Do we put all of them in the clocks property?
> 
> If so, we can use .fw_name at some point. If not, why bother with the
> clocks
> property at all? This is another part of the "let's get the clock
> tree right
> from the start" discussion.

Well we don't now, because I think it's too dirty to put all PLLs into
the device tree, but I must admit that this should be correct.

> 
> > +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
> > +                    0x500, 24, 3, CLK_SET_RATE_PARENT |
> > CLK_IS_CRITICAL);
> > +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
> > +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2,
> > 0);
> > +
> > +static const char * const ahb_parents[] = { "osc24M", "osc32k",
> > +                                           "iosc", "pll-periph" };
> > +static SUNXI_CCU_MP_WITH_MUX(ahb_clk, "ahb",
> > +                            ahb_parents, 0x510,
> > +                            0, 2,      /* M */
> > +                            8, 2,      /* P */
> > +                            24, 3,     /* mux */
> > +                            0);
> > +
> > +static const char * const apb_parents[] = { "osc24M", "osc32k",
> > +                                           "ahb", "pll-periph" };
> > +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb_parents, 0x520,
> > +                            0, 2,      /* M */
> > +                            8, 2,      /* P */
> > +                            24, 3,     /* mux */
> > +                            0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb_parents, 0x524,
> > +                            0, 2,      /* M */
> > +                            8, 2,      /* P */
> > +                            24, 3,     /* mux */
> > +                            0);
> 
> Hmm, so Allwinner is inconsistent with these. The manual has
> APB0/APB1, but the
> BSP has APB1/APB2.
> 
> > +
> > +static const char * const ce_parents[] = { "osc24M", "pll-periph-
> > 2x" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 1,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb",
> > +                     0x68c, BIT(0), 0);
> > +
> > +static const char * const aipu_parents[] = { "pll-periph-2x",
> > "pll-periph-800m",
> > +                                            "pll-audio0-div2",
> > "pll-audio0-div5",
> > +                                            "pll-cpux" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(aipu_clk, "aipu", aipu_parents,
> > 0x6f0,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_aipu_clk, "bus-aipu", "ahb",
> > +                     0x6fc, BIT(0), 0);
> 
> The manual has separate gates for an AIPU AHB master at bit 1, and an
> AHB slave
> at bit 0.
> 
> > +
> > +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
> > +                     0x70c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb",
> > +                     0x71c, BIT(0), 0);
> 
> There are two message boxes (bits 0 and 1).
> 
> > +
> > +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb",
> > +                     0x72c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb",
> > +                     0x73c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31),
> > 0);
> > +
> > +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb",
> > +                     0x78c, BIT(0), 0);
> 
> There is a gate for the PSI clock (the parent for the AHB clocks) at
> 0x79c.
> 
> > +
> > +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac,
> > BIT(0), 0);
> > +
> > +static const char * const dram_parents[] = { "pll-periph-2x",
> > +                                            "pll-periph-800m",
> > +                                            "pll-audio0-div2",
> > +                                            "pll-audio0-div5" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents,
> > 0x800,
> > +                                 0, 2,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 CLK_IS_CRITICAL);
> > +
> > +
> > +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "dram",
> > +                     0x804, BIT(0), 0);
> > +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "dram",
> > +                     0x804, BIT(2), 0);
> > +static SUNXI_CCU_GATE(mbus_r_dma_clk, "mbus-r-dma", "dram",
> > +                     0x804, BIT(3), 0);
> > +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "dram",
> > +                     0x804, BIT(5), 0);
> > +static SUNXI_CCU_GATE(mbus_aipu_clk, "mbus-aipu", "dram",
> > +                     0x804, BIT(16), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
> > +                     0x80c, BIT(0), CLK_IS_CRITICAL);
> 
> The DRAM bus clock is not critical. It only needs to be enabled for
> register
> access (PMU, DVFS).
> 
> > +
> > +static const char * const nand_parents[] = { "osc24M", "pll-
> > periph",
> > +                                            "pll-audio-div2",
> > +                                            "pll-periph-2x" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0",
> > nand_parents, 0x810,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1",
> > nand_parents, 0x814,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb", 0x82c,
> > BIT(0), 0);
> > +
> > +static const char * const mmc_parents[] = { "osc24M", "pll-
> > periph",
> > +                                           "pll-periph-2x",
> > +                                           "pll-audio0-div2" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0",
> > mmc_parents, 0x830,
> > +                                         0, 4,         /* M */
> > +                                         8, 2,         /* P */
> > +                                         24, 2,        /* mux */
> > +                                         BIT(31),      /* gate */
> > +                                         2,            /* post-div
> > */
> > +                                         0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1",
> > mmc_parents, 0x834,
> > +                                         0, 4,         /* M */
> > +                                         8, 2,         /* P */
> > +                                         24, 2,        /* mux */
> > +                                         BIT(31),      /* gate */
> > +                                         2,            /* post-div
> > */
> 
> Where does the post-divider come from?
> 
> > +                                         0);
> > +
> > +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 0x84c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 0x84c,
> > BIT(1), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c,
> > BIT(1), 0);
> > +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c,
> > BIT(2), 0);
> > +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c,
> > BIT(3), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c,
> > BIT(1), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 0x93c,
> > BIT(0), 0);
> > +
> > +static const char * const spi_parents[] = { "osc24M", "pll-
> > periph",
> > +                                           "pll-periph-2x",
> > +                                           "pll-audio0-div2",
> > +                                           "pll-audio0-div5" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents,
> > 0x940,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents,
> > 0x944,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 3,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 0x96c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 0x96c,
> > BIT(1), 0);
> > +
> > +static CLK_FIXED_FACTOR(emac_25m_div_clk, "emac-25m-div", "pll-
> > periph",
> > +                       2, 1, 0);
> > +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "emac-25m-div",
> > 0x970,
> > +                     BIT(31) | BIT(30), 0);
> 
> The divider should be 24, not 2. And you can use
> CCU_FEATURE_ALL_PREDIV on the
> gate to remove the separate divider clock.
> 
> > +
> > +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb", 0x97c,
> > BIT(0), 0);
> > +
> > +static const char * const ir_parents[] = { "osc32k", "iosc",
> 
> Both the manual and the BSP have the second parent as osc24M, not
> iosc.
> 
> > +                                          "pll-periph", "pll-
> > audio0-div2" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents,
> > 0x990,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "apb1", 0x99c,
> > BIT(0), 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents,
> > 0x9c0,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc,
> > BIT(0), 0);
> > +
> > +static const char * const audio_parents[] = { "pll-audio1",
> > +                                             "pll-audio1-4x",
> > +                                             "pll-audio0-div2",
> > +                                             "pll-audio0-div5" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents,
> > 0xa10,
> > +                                 0, 4,         /* M */
> 
> All of the audio modules have 5-bit M dividers.
> 
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents,
> > 0xa14,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20,
> > BIT(1), 0);
> > +
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_clk, "spdif",
> > audio_parents, 0xa20,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 2,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c,
> > BIT(0), 0);
> > +
> > +/*
> > + * There are OHCI 12M clock source selection bits for 2 USB 2.0
> > ports.
> > + * We will force them to 0 (12M divided from 48M).
> > + */
> > +#define SUN50I_R329_USB0_CLK_REG               0xa70
> > +#define SUN50I_R329_USB1_CLK_REG               0xa74
> 
> This "48M" clock is divided/synchronized from pll-periph, as shown in
> the
> "Module Clock Generation" diagram and USB "PHY Connection Diagram" in
> the
> manual. So I recommend the following structure:
> 
> static CLK_FIXED_FACTOR(usb_48M_clk, "usb-48M",
>                         "pll-periph", 25, 2, 0);
> 
> static CLK_FIXED_FACTOR_HW(usb_12M_clk, "usb-12M",
>                            &usb_48M_clk.hw, 4, 1, 0);
> 
> static const char *const usb_ohci_parents[] = { "usb-12M", "osc12M",
>                                                 "osc32k" };
> static SUNXI_CCU_MUX_WITH_GATE(usb_ohci0_clk, "usb-ohci0",
>                                usb_ohci_parents, 0xa70,
>                                24, 2,           /* mux */
>                                BIT(31),         /* gate */
>                                0);
> 
> static SUNXI_CCU_MUX_WITH_GATE(usb_ohci1_clk, "usb-ohci1",
>                                usb_ohci_parents, 0xa74,
>                                24, 2,           /* mux */
>                                BIT(31),         /* gate */
>                                0);
> 
> For anyone following along without R329 documents, this is all the
> same as the
> D1, though the labels in the diagrams are slightly different. Hooray
> for finally
> documenting this so it is no longer "mysterious"!
> 
> Regards,
> Samuel
> 
> > +
> > +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70,
> > BIT(31), 0);
> > +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70,
> > BIT(29), 0);
> > +
> > +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74,
> > BIT(31), 0);
> > +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74,
> > BIT(29), 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb", 0xa8c,
> > BIT(0), 0);
> > +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb", 0xa8c,
> > BIT(1), 0);
> > +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb", 0xa8c,
> > BIT(4), 0);
> > +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 0xa8c,
> > BIT(8), 0);
> > +
> > +static const char * const ledc_parents[] = { "osc24M", "pll-
> > periph" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents,
> > 0xbf0,
> > +                                 0, 4,         /* M */
> > +                                 8, 2,         /* P */
> > +                                 24, 1,        /* mux */
> > +                                 BIT(31),      /* gate */
> > +                                 0);
> > +
> > +static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "apb1", 0xbfc,
> > BIT(0), 0);
> > +
> > +/* Fixed factor clocks */
> > +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2,
> > 1, 0);
> > +
> > +static struct ccu_common *sun50i_r329_ccu_clks[] = {
> > +       &cpux_clk.common,
> > +       &axi_clk.common,
> > +       &cpux_apb_clk.common,
> > +       &ahb_clk.common,
> > +       &apb1_clk.common,
> > +       &apb2_clk.common,
> > +       &ce_clk.common,
> > +       &bus_ce_clk.common,
> > +       &aipu_clk.common,
> > +       &bus_aipu_clk.common,
> > +       &bus_dma_clk.common,
> > +       &bus_msgbox_clk.common,
> > +       &bus_spinlock_clk.common,
> > +       &bus_hstimer_clk.common,
> > +       &avs_clk.common,
> > +       &bus_dbg_clk.common,
> > +       &bus_pwm_clk.common,
> > +       &dram_clk.common,
> > +       &mbus_dma_clk.common,
> > +       &mbus_ce_clk.common,
> > +       &mbus_r_dma_clk.common,
> > +       &mbus_nand_clk.common,
> > +       &mbus_aipu_clk.common,
> > +       &bus_dram_clk.common,
> > +       &nand0_clk.common,
> > +       &nand1_clk.common,
> > +       &bus_nand_clk.common,
> > +       &mmc0_clk.common,
> > +       &mmc1_clk.common,
> > +       &bus_mmc0_clk.common,
> > +       &bus_mmc1_clk.common,
> > +       &bus_uart0_clk.common,
> > +       &bus_uart1_clk.common,
> > +       &bus_uart2_clk.common,
> > +       &bus_uart3_clk.common,
> > +       &bus_i2c0_clk.common,
> > +       &bus_i2c1_clk.common,
> > +       &bus_scr_clk.common,
> > +       &spi0_clk.common,
> > +       &spi1_clk.common,
> > +       &bus_spi0_clk.common,
> > +       &bus_spi1_clk.common,
> > +       &emac_25m_clk.common,
> > +       &bus_emac_clk.common,
> > +       &ir_rx_clk.common,
> > +       &bus_ir_rx_clk.common,
> > +       &ir_tx_clk.common,
> > +       &bus_ir_tx_clk.common,
> > +       &i2s0_clk.common,
> > +       &i2s1_clk.common,
> > +       &bus_i2s0_clk.common,
> > +       &bus_i2s1_clk.common,
> > +       &spdif_clk.common,
> > +       &bus_spdif_clk.common,
> > +       &usb_ohci0_clk.common,
> > +       &usb_phy0_clk.common,
> > +       &usb_ohci1_clk.common,
> > +       &usb_phy1_clk.common,
> > +       &bus_ohci0_clk.common,
> > +       &bus_ohci1_clk.common,
> > +       &bus_ehci0_clk.common,
> > +       &bus_otg_clk.common,
> > +       &ledc_clk.common,
> > +       &bus_ledc_clk.common,
> > +};
> > +
> > +static struct clk_hw_onecell_data sun50i_r329_hw_clks = {
> > +       .hws    = {
> > +               [CLK_OSC12M]            = &osc12M_clk.hw,
> > +               [CLK_CPUX]              = &cpux_clk.common.hw,
> > +               [CLK_AXI]               = &axi_clk.common.hw,
> > +               [CLK_CPUX_APB]          = &cpux_apb_clk.common.hw,
> > +               [CLK_AHB]               = &ahb_clk.common.hw,
> > +               [CLK_APB1]              = &apb1_clk.common.hw,
> > +               [CLK_APB2]              = &apb2_clk.common.hw,
> > +               [CLK_CE]                = &ce_clk.common.hw,
> > +               [CLK_BUS_CE]            = &bus_ce_clk.common.hw,
> > +               [CLK_AIPU]              = &aipu_clk.common.hw,
> > +               [CLK_BUS_AIPU]          = &bus_aipu_clk.common.hw,
> > +               [CLK_BUS_DMA]           = &bus_dma_clk.common.hw,
> > +               [CLK_BUS_MSGBOX]        =
> > &bus_msgbox_clk.common.hw,
> > +               [CLK_BUS_SPINLOCK]      =
> > &bus_spinlock_clk.common.hw,
> > +               [CLK_BUS_HSTIMER]       =
> > &bus_hstimer_clk.common.hw,
> > +               [CLK_AVS]               = &avs_clk.common.hw,
> > +               [CLK_BUS_DBG]           = &bus_dbg_clk.common.hw,
> > +               [CLK_BUS_PWM]           = &bus_pwm_clk.common.hw,
> > +               [CLK_DRAM]              = &dram_clk.common.hw,
> > +               [CLK_MBUS_DMA]          = &mbus_dma_clk.common.hw,
> > +               [CLK_MBUS_CE]           = &mbus_ce_clk.common.hw,
> > +               [CLK_MBUS_R_DMA]        =
> > &mbus_r_dma_clk.common.hw,
> > +               [CLK_MBUS_NAND]         = &mbus_nand_clk.common.hw,
> > +               [CLK_MBUS_AIPU]         = &mbus_aipu_clk.common.hw,
> > +               [CLK_BUS_DRAM]          = &bus_dram_clk.common.hw,
> > +               [CLK_NAND0]             = &nand0_clk.common.hw,
> > +               [CLK_NAND1]             = &nand1_clk.common.hw,
> > +               [CLK_BUS_NAND]          = &bus_nand_clk.common.hw,
> > +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> > +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> > +               [CLK_BUS_MMC0]          = &bus_mmc0_clk.common.hw,
> > +               [CLK_BUS_MMC1]          = &bus_mmc1_clk.common.hw,
> > +               [CLK_BUS_UART0]         = &bus_uart0_clk.common.hw,
> > +               [CLK_BUS_UART1]         = &bus_uart1_clk.common.hw,
> > +               [CLK_BUS_UART2]         = &bus_uart2_clk.common.hw,
> > +               [CLK_BUS_UART3]         = &bus_uart3_clk.common.hw,
> > +               [CLK_BUS_I2C0]          = &bus_i2c0_clk.common.hw,
> > +               [CLK_BUS_I2C1]          = &bus_i2c1_clk.common.hw,
> > +               [CLK_BUS_SCR]           = &bus_scr_clk.common.hw,
> > +               [CLK_SPI0]              = &spi0_clk.common.hw,
> > +               [CLK_SPI1]              = &spi1_clk.common.hw,
> > +               [CLK_BUS_SPI0]          = &bus_spi0_clk.common.hw,
> > +               [CLK_BUS_SPI1]          = &bus_spi1_clk.common.hw,
> > +               [CLK_EMAC_25M_DIV]      = &emac_25m_div_clk.hw,
> > +               [CLK_EMAC_25M]          = &emac_25m_clk.common.hw,
> > +               [CLK_BUS_EMAC]          = &bus_emac_clk.common.hw,
> > +               [CLK_IR_RX]             = &ir_rx_clk.common.hw,
> > +               [CLK_BUS_IR_RX]         = &bus_ir_rx_clk.common.hw,
> > +               [CLK_IR_TX]             = &ir_tx_clk.common.hw,
> > +               [CLK_BUS_IR_TX]         = &bus_ir_tx_clk.common.hw,
> > +               [CLK_I2S0]              = &i2s0_clk.common.hw,
> > +               [CLK_I2S1]              = &i2s1_clk.common.hw,
> > +               [CLK_BUS_I2S0]          = &bus_i2s0_clk.common.hw,
> > +               [CLK_BUS_I2S1]          = &bus_i2s1_clk.common.hw,
> > +               [CLK_SPDIF]             = &spdif_clk.common.hw,
> > +               [CLK_BUS_SPDIF]         = &bus_spdif_clk.common.hw,
> > +               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
> > +               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
> > +               [CLK_USB_OHCI1]         = &usb_ohci1_clk.common.hw,
> > +               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
> > +               [CLK_BUS_OHCI0]         = &bus_ohci0_clk.common.hw,
> > +               [CLK_BUS_OHCI1]         = &bus_ohci1_clk.common.hw,
> > +               [CLK_BUS_EHCI0]         = &bus_ehci0_clk.common.hw,
> > +               [CLK_BUS_OTG]           = &bus_otg_clk.common.hw,
> > +               [CLK_LEDC]              = &ledc_clk.common.hw,
> > +               [CLK_BUS_LEDC]          = &bus_ledc_clk.common.hw,
> > +       },
> > +       .num = CLK_NUMBER,
> > +};
> > +
> > +static struct ccu_reset_map sun50i_r329_ccu_resets[] = {
> > +       [RST_MBUS]              = { 0x540, BIT(30) },
> > +
> > +       [RST_BUS_CE]            = { 0x68c, BIT(16) },
> > +       [RST_BUS_AIPU]          = { 0x6fc, BIT(16) },
> > +       [RST_BUS_DMA]           = { 0x70c, BIT(16) },
> > +       [RST_BUS_MSGBOX]        = { 0x71c, BIT(16) },
> > +       [RST_BUS_SPINLOCK]      = { 0x72c, BIT(16) },
> > +       [RST_BUS_HSTIMER]       = { 0x73c, BIT(16) },
> > +       [RST_BUS_DBG]           = { 0x78c, BIT(16) },
> > +       [RST_BUS_PWM]           = { 0x7ac, BIT(16) },
> > +       [RST_BUS_DRAM]          = { 0x80c, BIT(16) },
> > +       [RST_BUS_NAND]          = { 0x82c, BIT(16) },
> > +       [RST_BUS_MMC0]          = { 0x84c, BIT(16) },
> > +       [RST_BUS_MMC1]          = { 0x84c, BIT(17) },
> > +       [RST_BUS_UART0]         = { 0x90c, BIT(16) },
> > +       [RST_BUS_UART1]         = { 0x90c, BIT(17) },
> > +       [RST_BUS_UART2]         = { 0x90c, BIT(18) },
> > +       [RST_BUS_UART3]         = { 0x90c, BIT(19) },
> > +       [RST_BUS_I2C0]          = { 0x91c, BIT(16) },
> > +       [RST_BUS_I2C1]          = { 0x91c, BIT(17) },
> > +       [RST_BUS_SCR]           = { 0x93c, BIT(16) },
> > +       [RST_BUS_SPI0]          = { 0x96c, BIT(16) },
> > +       [RST_BUS_SPI1]          = { 0x96c, BIT(17) },
> > +       [RST_BUS_EMAC]          = { 0x97c, BIT(16) },
> > +       [RST_BUS_IR_RX]         = { 0x99c, BIT(16) },
> > +       [RST_BUS_IR_TX]         = { 0x9cc, BIT(16) },
> > +       [RST_BUS_I2S0]          = { 0xa1c, BIT(16) },
> > +       [RST_BUS_I2S1]          = { 0xa1c, BIT(17) },
> > +       [RST_BUS_SPDIF]         = { 0xa2c, BIT(16) },
> > +
> > +       [RST_USB_PHY0]          = { 0xa70, BIT(30) },
> > +       [RST_USB_PHY1]          = { 0xa74, BIT(30) },
> > +
> > +       [RST_BUS_OHCI0]         = { 0xa8c, BIT(16) },
> > +       [RST_BUS_OHCI1]         = { 0xa8c, BIT(17) },
> > +       [RST_BUS_EHCI0]         = { 0xa8c, BIT(20) },
> > +       [RST_BUS_OTG]           = { 0xa8c, BIT(24) },
> > +
> > +       [RST_BUS_LEDC]          = { 0xbfc, BIT(16) },
> > +};
> > +
> > +static const struct sunxi_ccu_desc sun50i_r329_ccu_desc = {
> > +       .ccu_clks       = sun50i_r329_ccu_clks,
> > +       .num_ccu_clks   = ARRAY_SIZE(sun50i_r329_ccu_clks),
> > +
> > +       .hw_clks        = &sun50i_r329_hw_clks,
> > +
> > +       .resets         = sun50i_r329_ccu_resets,
> > +       .num_resets     = ARRAY_SIZE(sun50i_r329_ccu_resets),
> > +};
> > +
> > +static const u32 sun50i_r329_usb_clk_regs[] = {
> > +       SUN50I_R329_USB0_CLK_REG,
> > +       SUN50I_R329_USB1_CLK_REG,
> > +};
> > +
> > +static int sun50i_r329_ccu_probe(struct platform_device *pdev)
> > +{
> > +       void __iomem *reg;
> > +       u32 val;
> > +       int i;
> > +
> > +       reg = devm_platform_ioremap_resource(pdev, 0);
> > +       if (IS_ERR(reg))
> > +               return PTR_ERR(reg);
> > +
> > +       /*
> > +        * Force OHCI 12M clock sources to 00 (12MHz divided from
> > 48MHz)
> > +        *
> > +        * This clock mux is still mysterious, and the code just
> > enforces
> > +        * it to have a valid clock parent.
> > +        */
> > +       for (i = 0; i < ARRAY_SIZE(sun50i_r329_usb_clk_regs); i++)
> > {
> > +               val = readl(reg + sun50i_r329_usb_clk_regs[i]);
> > +               val &= ~GENMASK(25, 24);
> > +               writel(val, reg + sun50i_r329_usb_clk_regs[i]);
> > +       }
> > +
> > +       return sunxi_ccu_probe(pdev->dev.of_node, reg,
> > &sun50i_r329_ccu_desc);
> > +}
> > +
> > +static const struct of_device_id sun50i_r329_ccu_ids[] = {
> > +       { .compatible = "allwinner,sun50i-r329-ccu" },
> > +       { }
> > +};
> > +
> > +static struct platform_driver sun50i_r329_ccu_driver = {
> > +       .probe  = sun50i_r329_ccu_probe,
> > +       .driver = {
> > +               .name   = "sun50i-r329-ccu",
> > +               .of_match_table = sun50i_r329_ccu_ids,
> > +       },
> > +};
> > +module_platform_driver(sun50i_r329_ccu_driver);
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> > b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> > new file mode 100644
> > index 000000000000..144ac9954ef3
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-r329.h
> > @@ -0,0 +1,32 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2021 Sipeed
> > + */
> > +
> > +#ifndef _CCU_SUN50I_R329_H_
> > +#define _CCU_SUN50I_R329_H_
> > +
> > +#include <dt-bindings/clock/sun50i-r329-ccu.h>
> > +#include <dt-bindings/reset/sun50i-r329-ccu.h>
> > +
> > +#define CLK_OSC12M             0
> > +
> > +/* CPUX exported for DVFS */
> > +
> > +#define CLK_AXI                        2
> > +#define CLK_CPUX_APB           3
> > +#define CLK_AHB                        4
> > +
> > +/* APB1 exported for PIO */
> > +
> > +#define CLK_APB2               6
> > +
> > +/* Peripheral module and gate clock exported except for DRAM ones
> > */
> > +
> > +#define CLK_DRAM               18
> > +
> > +#define CLK_BUS_DRAM           24
> > +
> > +#define CLK_NUMBER             (CLK_BUS_LEDC + 1)
> > +
> > +#endif /* _CCU_SUN50I_R329_H_ */
> > diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h
> > b/include/dt-bindings/clock/sun50i-r329-ccu.h
> > new file mode 100644
> > index 000000000000..116f8d13a9b3
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
> > @@ -0,0 +1,73 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2021 Sipeed
> > + */
> > +
> > +#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> > +#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
> > +
> > +#define CLK_CPUX               1
> > +
> > +#define CLK_APB1               5
> > +
> > +#define CLK_CE                 7
> > +#define CLK_BUS_CE             8
> > +#define CLK_AIPU               9
> > +#define CLK_BUS_AIPU           10
> > +#define CLK_BUS_DMA            11
> > +#define CLK_BUS_MSGBOX         12
> > +#define CLK_BUS_SPINLOCK       13
> > +#define CLK_BUS_HSTIMER                14
> > +#define CLK_AVS                        15
> > +#define CLK_BUS_DBG            16
> > +#define CLK_BUS_PWM            17
> > +
> > +#define CLK_MBUS_DMA           19
> > +#define CLK_MBUS_CE            20
> > +#define CLK_MBUS_R_DMA         21
> > +#define CLK_MBUS_NAND          22
> > +#define CLK_MBUS_AIPU          23
> > +
> > +#define CLK_NAND0              25
> > +#define CLK_NAND1              26
> > +#define CLK_BUS_NAND           27
> > +#define CLK_MMC0               28
> > +#define CLK_MMC1               29
> > +#define CLK_BUS_MMC0           30
> > +#define CLK_BUS_MMC1           31
> > +#define CLK_BUS_UART0          32
> > +#define CLK_BUS_UART1          33
> > +#define CLK_BUS_UART2          34
> > +#define CLK_BUS_UART3          35
> > +#define CLK_BUS_I2C0           36
> > +#define CLK_BUS_I2C1           37
> > +#define CLK_BUS_SCR            38
> > +#define CLK_SPI0               39
> > +#define CLK_SPI1               40
> > +#define CLK_BUS_SPI0           41
> > +#define CLK_BUS_SPI1           42
> > +#define CLK_EMAC_25M_DIV       43
> > +#define CLK_EMAC_25M           44
> > +#define CLK_BUS_EMAC           45
> > +#define CLK_IR_RX              46
> > +#define CLK_BUS_IR_RX          47
> > +#define CLK_IR_TX              48
> > +#define CLK_BUS_IR_TX          49
> > +#define CLK_I2S0               50
> > +#define CLK_I2S1               51
> > +#define CLK_BUS_I2S0           52
> > +#define CLK_BUS_I2S1           53
> > +#define CLK_SPDIF              54
> > +#define CLK_BUS_SPDIF          55
> > +#define CLK_USB_OHCI0          56
> > +#define CLK_USB_PHY0           57
> > +#define CLK_USB_OHCI1          58
> > +#define CLK_USB_PHY1           59
> > +#define CLK_BUS_OHCI0          60
> > +#define CLK_BUS_OHCI1          61
> > +#define CLK_BUS_EHCI0          62
> > +#define CLK_BUS_OTG            63
> > +#define CLK_LEDC               64
> > +#define CLK_BUS_LEDC           65
> > +
> > +#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
> > diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h
> > b/include/dt-bindings/reset/sun50i-r329-ccu.h
> > new file mode 100644
> > index 000000000000..bb704a82443f
> > --- /dev/null
> > +++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
> > @@ -0,0 +1,45 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
> > +/*
> > + * Copyright (c) 2021 Sipeed
> > + */
> > +
> > +#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> > +#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
> > +
> > +#define RST_MBUS               0
> > +#define RST_BUS_CE             1
> > +#define RST_BUS_AIPU           2
> > +#define RST_BUS_DMA            3
> > +#define RST_BUS_MSGBOX         4
> > +#define RST_BUS_SPINLOCK       5
> > +#define RST_BUS_HSTIMER                6
> > +#define RST_BUS_DBG            7
> > +#define RST_BUS_PWM            8
> > +#define RST_BUS_DRAM           9
> > +#define RST_BUS_NAND           10
> > +#define RST_BUS_MMC0           11
> > +#define RST_BUS_MMC1           12
> > +#define RST_BUS_UART0          13
> > +#define RST_BUS_UART1          14
> > +#define RST_BUS_UART2          15
> > +#define RST_BUS_UART3          16
> > +#define RST_BUS_I2C0           17
> > +#define RST_BUS_I2C1           18
> > +#define RST_BUS_SCR            19
> > +#define RST_BUS_SPI0           20
> > +#define RST_BUS_SPI1           21
> > +#define RST_BUS_EMAC           22
> > +#define RST_BUS_IR_RX          23
> > +#define RST_BUS_IR_TX          24
> > +#define RST_BUS_I2S0           25
> > +#define RST_BUS_I2S1           26
> > +#define RST_BUS_SPDIF          27
> > +#define RST_USB_PHY0           28
> > +#define RST_USB_PHY1           29
> > +#define RST_BUS_OHCI0          30
> > +#define RST_BUS_OHCI1          31
> > +#define RST_BUS_EHCI0          32
> > +#define RST_BUS_OTG            33
> > +#define RST_BUS_LEDC           34
> > +
> > +#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
> > 
> 
> 



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 10/17] clk: sunxi=ng: add support for R329 R-CCU
  2021-08-20  0:55     ` Samuel Holland
@ 2021-08-20  4:34       ` Jernej Škrabec
  -1 siblings, 0 replies; 112+ messages in thread
From: Jernej Škrabec @ 2021-08-20  4:34 UTC (permalink / raw)
  To: Icenowy Zheng, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Ulf Hansson, Linus Walleij, Alexandre Belloni, Andre Przywara,
	Samuel Holland
  Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel

Hi Samuel!

Dne petek, 20. avgust 2021 ob 02:55:10 CEST je Samuel Holland napisal(a):
> On 8/2/21 1:22 AM, Icenowy Zheng wrote:
> > Allwinner R329 has clock controls in PRCM, like other new Allwinner
> > SoCs.
> > 
> > Add support for them.
> > 
> > This driver is added before the main CCU because PLLs are controlled by
> > R-CCU on R329.
> > 
> > Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
> > ---
> > 
> >  drivers/clk/sunxi-ng/Kconfig                  |   5 +
> >  drivers/clk/sunxi-ng/Makefile                 |   1 +
> >  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c      | 374 ++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h      |  33 ++
> >  include/dt-bindings/clock/sun50i-r329-r-ccu.h |  33 ++
> >  include/dt-bindings/reset/sun50i-r329-r-ccu.h |  24 ++
> >  6 files changed, 470 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-r329-r.h
> >  create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
> >  create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> > index cd46d8853876..e49b2c2fa5b7 100644
> > --- a/drivers/clk/sunxi-ng/Kconfig
> > +++ b/drivers/clk/sunxi-ng/Kconfig
> > @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU
> > 
> >  	default ARM64 && ARCH_SUNXI
> >  	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> > 
> > +config SUN50I_R329_R_CCU
> > +	bool "Support for the Allwinner R329 PRCM CCU"
> > +	default ARM64 && ARCH_SUNXI
> > +	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> > +
> > 
> >  config SUN4I_A10_CCU
> >  
> >  	bool "Suppor