* [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support
@ 2025-02-14 12:53 Andre Przywara
2025-02-14 12:53 ` [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper Andre Przywara
` (14 more replies)
0 siblings, 15 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Hi,
this is the second drop of the series introducing basic clock support for
the Allwinner A523 family of SoCs, comprising A523, A527, T527, H728. [1]
Since the posting of v1, a T527 user manual surfaced, so we could add
an extra clock, and confirm and clarify on some existing (guessed) ones.
This also contains some fixes to some clock definitions, which were
found either during testing or while checking for new clocks.
One big change in this series is the split of the main CCU driver into 9
patches, purely to help review. For a more detailed changelog, see below.
*************
Please note that the clock numbers changed compared to v1, so DTs from
that era cannot be used anymore with this driver: you have to update
the DTB. Just copying the binding header and recompiling the DTB should do
the trick, since the symbols stayed mostly the same, at least as far they
are used in the basic DTs we use today.
*************
The SoCs contain *four* CCU components, aside from the usual main clock
device and the PRCM clock (in the always-on-domain), there is an MCU
clock and a DSP clock. This series just adds support for the first two,
the other two don't seem to be required for the basic functionality.
The clock tree of each SoC has always been individual, even though the
main clock *types* mostly remain the same. This time we see two slight
variations: There is an MP clock without the P (shift) part, and there
is one with two dividers instead of one divider and one shift field.
The first three patches add support for these new clock types.
Patch 04/15 add the DT binding description for the main CCU, along with
all the clock numbers already defined in the binding headers.
Since the main CCU is massive, and contains a lot of detail, I decided
to split this driver up into 9 patches, simply to help review. I tried
to group them somewhat logically, although this is rather arbitrary, and
just to make each individual patch smaller. I am happy to squash them
all back into one patch once they have been reviewed, for the final
merge. The PRCM CCU is comparably small, so I kept this in one patch.
Interestingly the Allwinner BSP has switched to using the existing sunxi
CCU framework for modelling the clocks (they had their own way before), so
we could theoretically use their code. However when I started working on
this more than a year ago, their files had a GPL-3.0-only license header,
which, according to my research, makes them incompatible for mainline
inclusion. I thus started from "scratch" (adjusting the D1 driver, really).
Meanwhile they seem to have changed the license, and a quick comparison
turned up some differences, some of which seem to be bugs on their, some
on my side, probably. I hope having such a "reference" helps the mainline
code quality, as people can help the review by comparing code.
Given the level of detail required in CCU drivers, I am certain there are
many bugs in there, also many things that can be improved. But after
starring and editing this for weeks, I feel like it's time for the
community to have a look, so please help with the review, and also test.
Based on v6.14-rc1.
Cheers,
Andre
[1] https://linux-sunxi.org/A523#Family_of_sun55iw3
Changelog v1 .. v2:
- rebase onto v6.14-rc1
- split main CCU definition patch into 9 smaller patches
- rename RST_BUS_VO1_TCONLCD0 to RST_BUS_TCON_LCD2
- insert CLK_PLL_VIDEO3_xx clocks
- add clock for 2nd EMAC
- add R_SPI name (though clock definiton is still missing)
- fix ISP clock definition
- remove BSP comments from clocks now documented in the T527 manual
- add Conor's binding ACKs (with thanks!)
Andre Przywara (15):
clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper
clk: sunxi-ng: mp: introduce dual-divider clock
clk: sunxi-ng: mp: provide wrapper for setting feature flags
dt-bindings: clk: sunxi-ng: add compatible for the A523 CCU
clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
clk: sunxi-ng: a523: Add support for bus clocks
clk: sunxi-ng: a523: add video mod clocks
clk: sunxi-ng: a523: add system mod clocks
clk: sunxi-ng: a523: add interface mod clocks
clk: sunxi-ng: a523: add USB mod clocks
clk: sunxi-ng: a523: remaining mod clocks
clk: sunxi-ng: a523: add bus clock gates
clk: sunxi-ng: a523: add reset lines
dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU
clk: sunxi-ng: add support for the A523/T527 PRCM CCU
.../clock/allwinner,sun4i-a10-ccu.yaml | 76 +-
drivers/clk/sunxi-ng/Kconfig | 10 +
drivers/clk/sunxi-ng/Makefile | 4 +
drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c | 245 +++
drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h | 14 +
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 1641 +++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun55i-a523.h | 14 +
drivers/clk/sunxi-ng/ccu_common.h | 1 +
drivers/clk/sunxi-ng/ccu_mp.c | 51 +-
drivers/clk/sunxi-ng/ccu_mp.h | 39 +-
include/dt-bindings/clock/sun55i-a523-ccu.h | 190 ++
include/dt-bindings/clock/sun55i-a523-r-ccu.h | 37 +
include/dt-bindings/reset/sun55i-a523-ccu.h | 87 +
include/dt-bindings/reset/sun55i-a523-r-ccu.h | 25 +
14 files changed, 2394 insertions(+), 40 deletions(-)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h
create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h
--
2.46.3
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-16 8:39 ` Chen-Yu Tsai
2025-02-14 12:53 ` [PATCH v2 02/15] clk: sunxi-ng: mp: introduce dual-divider clock Andre Przywara
` (13 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
The PRCM CCU in the A523 SoC contains some clocks that only feature a
P (shift) factor, but no M divider.
Treat this as a special case of an MP clock: by forcing the M mask to be
0 bits wide, this always result in the M divider value to be 1.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu_mp.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index 6e50f3728fb5f..e235fdfde2d36 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -71,6 +71,24 @@ struct ccu_mp {
} \
}
+#define SUNXI_CCU_P_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
+ _pshift, _pwidth, \
+ _muxshift, _muxwidth, \
+ _gate, _flags) \
+ struct ccu_mp _struct = { \
+ .enable = _gate, \
+ .m = _SUNXI_CCU_DIV(0, 0), \
+ .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
+ .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
+ .common = { \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
+ _parents, \
+ &ccu_mp_ops,\
+ _flags), \
+ } \
+ }
+
#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 02/15] clk: sunxi-ng: mp: introduce dual-divider clock
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
2025-02-14 12:53 ` [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-16 8:39 ` Chen-Yu Tsai
2025-02-14 12:53 ` [PATCH v2 03/15] clk: sunxi-ng: mp: provide wrapper for setting feature flags Andre Przywara
` (12 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
The Allwinner A523 SoC introduces some new MP-style mod clock, where the
second "P" divider is an actual numerical divider value, and not the
numbers of bits to shift (1..32 instead of 1,2,4,8).
The rest of the clock is the same as the existing MP clock, so enhance the
existing code to accommodate for this.
Introduce the new CCU feature bit CCU_FEATURE_DUAL_DIV to mark an MP
clock as having two dividers, and change the dividing and encoding code
to differentiate the two cases.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu_common.h | 1 +
drivers/clk/sunxi-ng/ccu_mp.c | 51 +++++++++++++++++++++++++------
2 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index dd330426a6e5f..50fd268329671 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -19,6 +19,7 @@
#define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7)
#define CCU_FEATURE_KEY_FIELD BIT(8)
#define CCU_FEATURE_CLOSEST_RATE BIT(9)
+#define CCU_FEATURE_DUAL_DIV BIT(10)
/* MMC timing mode switch bit */
#define CCU_MMC_NEW_TIMING_MODE BIT(30)
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index 2bb8987ddcc20..354c981943b6f 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -10,15 +10,23 @@
#include "ccu_gate.h"
#include "ccu_mp.h"
+static unsigned int next_div(unsigned int div, bool shift)
+{
+ if (shift)
+ return div << 1;
+ return div + 1;
+}
+
static unsigned long ccu_mp_find_best(unsigned long parent, unsigned long rate,
unsigned int max_m, unsigned int max_p,
+ bool shift,
unsigned int *m, unsigned int *p)
{
unsigned long best_rate = 0;
unsigned int best_m = 0, best_p = 0;
unsigned int _m, _p;
- for (_p = 1; _p <= max_p; _p <<= 1) {
+ for (_p = 1; _p <= max_p; _p = next_div(_p, shift)) {
for (_m = 1; _m <= max_m; _m++) {
unsigned long tmp_rate = parent / _p / _m;
@@ -43,7 +51,8 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
unsigned long *parent,
unsigned long rate,
unsigned int max_m,
- unsigned int max_p)
+ unsigned int max_p,
+ bool shift)
{
unsigned long parent_rate_saved;
unsigned long parent_rate, now;
@@ -60,7 +69,7 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
maxdiv = max_m * max_p;
maxdiv = min(ULONG_MAX / rate, maxdiv);
- for (_p = 1; _p <= max_p; _p <<= 1) {
+ for (_p = 1; _p <= max_p; _p = next_div(_p, shift)) {
for (_m = 1; _m <= max_m; _m++) {
div = _m * _p;
@@ -103,18 +112,26 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
struct ccu_mp *cmp = data;
unsigned int max_m, max_p;
unsigned int m, p;
+ bool shift = true;
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= cmp->fixed_post_div;
+ if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+ shift = false;
+
max_m = cmp->m.max ?: 1 << cmp->m.width;
- max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+ if (shift)
+ max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+ else
+ max_p = cmp->p.max ?: 1 << cmp->p.width;
if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) {
- rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
+ rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, shift,
+ &m, &p);
} else {
rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate,
- max_m, max_p);
+ max_m, max_p, shift);
}
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
@@ -167,7 +184,11 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
p = reg >> cmp->p.shift;
p &= (1 << cmp->p.width) - 1;
- rate = (parent_rate >> p) / m;
+ if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+ rate = (parent_rate / p) / m;
+ else
+ rate = (parent_rate >> p) / m;
+
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate /= cmp->fixed_post_div;
@@ -190,20 +211,27 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
unsigned int max_m, max_p;
unsigned int m, p;
+ bool shift = true;
u32 reg;
+ if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+ shift = false;
+
/* Adjust parent_rate according to pre-dividers */
parent_rate = ccu_mux_helper_apply_prediv(&cmp->common, &cmp->mux, -1,
parent_rate);
max_m = cmp->m.max ?: 1 << cmp->m.width;
- max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+ if (shift)
+ max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+ else
+ max_p = cmp->p.max ?: 1 << cmp->p.width;
/* Adjust target rate according to post-dividers */
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate = rate * cmp->fixed_post_div;
- ccu_mp_find_best(parent_rate, rate, max_m, max_p, &m, &p);
+ ccu_mp_find_best(parent_rate, rate, max_m, max_p, shift, &m, &p);
spin_lock_irqsave(cmp->common.lock, flags);
@@ -211,7 +239,10 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
reg |= (m - cmp->m.offset) << cmp->m.shift;
- reg |= ilog2(p) << cmp->p.shift;
+ if (shift)
+ reg |= ilog2(p) << cmp->p.shift;
+ else
+ reg |= (p - cmp->p.offset) << cmp->p.shift;
writel(reg, cmp->common.base + cmp->common.reg);
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 03/15] clk: sunxi-ng: mp: provide wrapper for setting feature flags
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
2025-02-14 12:53 ` [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper Andre Przywara
2025-02-14 12:53 ` [PATCH v2 02/15] clk: sunxi-ng: mp: introduce dual-divider clock Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-16 8:41 ` Chen-Yu Tsai
2025-02-14 12:53 ` [PATCH v2 04/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 CCU Andre Przywara
` (11 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
So far our sunxi clock instantiation macros set the required flags
depending on the clock type, but the new "dual divider MP clock"
requires us to pass that piece of information in by the user.
Add a new wrapper macro that allows to specify a "features" field, to
allow marking those dual-divider clocks accordingly.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu_mp.h | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index e235fdfde2d36..687bd2ec798e2 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -100,11 +100,12 @@ struct ccu_mp {
_muxshift, _muxwidth, \
0, _flags)
-#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
+#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
- _gate, _flags) \
+ _gate, _flags, \
+ _features) \
struct ccu_mp _struct = { \
.enable = _gate, \
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
@@ -112,13 +113,25 @@ struct ccu_mp {
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
.common = { \
.reg = _reg, \
+ .features = _features, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
_parents, \
- &ccu_mp_ops, \
+ &ccu_mp_ops,\
_flags), \
} \
}
+#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
+ _mshift, _mwidth, \
+ _pshift, _pwidth, \
+ _muxshift, _muxwidth, \
+ _gate, _flags) \
+ SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, \
+ _reg, _mshift, _mwidth, \
+ _pshift, _pwidth, \
+ _muxshift, _muxwidth, \
+ _gate, _flags, 0)
+
#define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 04/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 CCU
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (2 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 03/15] clk: sunxi-ng: mp: provide wrapper for setting feature flags Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs Andre Przywara
` (10 subsequent siblings)
14 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
the main CCU.
Add the new compatible string, along with the required input clock
lists.
Also add the DT binding headers, listing all the clocks with their ID
numbers.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../clock/allwinner,sun4i-a10-ccu.yaml | 2 +
include/dt-bindings/clock/sun55i-a523-ccu.h | 190 ++++++++++++++++++
include/dt-bindings/reset/sun55i-a523-ccu.h | 87 ++++++++
3 files changed, 279 insertions(+)
create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index 1690b9d99c3d4..451a18de1b6c1 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -45,6 +45,7 @@ properties:
- allwinner,sun50i-h6-r-ccu
- allwinner,sun50i-h616-ccu
- allwinner,sun50i-h616-r-ccu
+ - allwinner,sun55i-a523-ccu
- allwinner,suniv-f1c100s-ccu
- nextthing,gr8-ccu
@@ -106,6 +107,7 @@ else:
- allwinner,sun50i-a100-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h616-ccu
+ - allwinner,sun55i-a523-ccu
then:
properties:
diff --git a/include/dt-bindings/clock/sun55i-a523-ccu.h b/include/dt-bindings/clock/sun55i-a523-ccu.h
new file mode 100644
index 0000000000000..89bc114f7a31f
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-ccu.h
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_
+
+#define CLK_PLL_DDR0 0
+#define CLK_PLL_PERIPH0_4X 1
+#define CLK_PLL_PERIPH0_2X 2
+#define CLK_PLL_PERIPH0_800M 3
+#define CLK_PLL_PERIPH0_480M 4
+#define CLK_PLL_PERIPH0_600M 5
+#define CLK_PLL_PERIPH0_400M 6
+#define CLK_PLL_PERIPH0_300M 7
+#define CLK_PLL_PERIPH0_200M 8
+#define CLK_PLL_PERIPH0_160M 9
+#define CLK_PLL_PERIPH0_150M 10
+#define CLK_PLL_PERIPH1_4X 11
+#define CLK_PLL_PERIPH1_2X 12
+#define CLK_PLL_PERIPH1_800M 13
+#define CLK_PLL_PERIPH1_480M 14
+#define CLK_PLL_PERIPH1_600M 15
+#define CLK_PLL_PERIPH1_400M 16
+#define CLK_PLL_PERIPH1_300M 17
+#define CLK_PLL_PERIPH1_200M 18
+#define CLK_PLL_PERIPH1_160M 19
+#define CLK_PLL_PERIPH1_150M 20
+#define CLK_PLL_GPU 21
+#define CLK_PLL_VIDEO0_8X 22
+#define CLK_PLL_VIDEO0_4X 23
+#define CLK_PLL_VIDEO0_3X 24
+#define CLK_PLL_VIDEO1_8X 25
+#define CLK_PLL_VIDEO1_4X 26
+#define CLK_PLL_VIDEO1_3X 27
+#define CLK_PLL_VIDEO2_8X 28
+#define CLK_PLL_VIDEO2_4X 29
+#define CLK_PLL_VIDEO2_3X 30
+#define CLK_PLL_VIDEO3_8X 31
+#define CLK_PLL_VIDEO3_4X 32
+#define CLK_PLL_VIDEO3_3X 33
+#define CLK_PLL_VE 34
+#define CLK_PLL_AUDIO0_4X 35
+#define CLK_PLL_AUDIO0_2X 36
+#define CLK_PLL_AUDIO0 37
+#define CLK_PLL_AUDIO1 38
+#define CLK_PLL_AUDIO1_DIV2 39
+#define CLK_PLL_AUDIO1_DIV5 40
+#define CLK_PLL_NPU_4X 41
+#define CLK_PLL_NPU_2X 42
+#define CLK_PLL_NPU 43
+#define CLK_AHB 44
+#define CLK_APB0 45
+#define CLK_APB1 46
+#define CLK_MBUS 47
+#define CLK_DE 48
+#define CLK_BUS_DE 49
+#define CLK_DI 50
+#define CLK_BUS_DI 51
+#define CLK_G2D 52
+#define CLK_BUS_G2D 53
+#define CLK_GPU 54
+#define CLK_BUS_GPU 55
+#define CLK_CE 56
+#define CLK_BUS_CE 57
+#define CLK_BUS_CE_SYS 58
+#define CLK_VE 59
+#define CLK_BUS_VE 60
+#define CLK_BUS_DMA 61
+#define CLK_BUS_MSGBOX 62
+#define CLK_BUS_SPINLOCK 63
+#define CLK_HSTIMER0 64
+#define CLK_HSTIMER1 65
+#define CLK_HSTIMER2 66
+#define CLK_HSTIMER3 67
+#define CLK_HSTIMER4 68
+#define CLK_HSTIMER5 69
+#define CLK_BUS_HSTIMER 70
+#define CLK_BUS_DBG 71
+#define CLK_BUS_PWM0 72
+#define CLK_BUS_PWM1 73
+#define CLK_IOMMU 74
+#define CLK_BUS_IOMMU 75
+#define CLK_DRAM 76
+#define CLK_MBUS_DMA 77
+#define CLK_MBUS_VE 78
+#define CLK_MBUS_CE 79
+#define CLK_MBUS_TVIN 80
+#define CLK_MBUS_CSI 81
+#define CLK_BUS_DRAM 82
+#define CLK_NAND0 83
+#define CLK_NAND1 84
+#define CLK_BUS_NAND 85
+#define CLK_MMC0 86
+#define CLK_MMC1 87
+#define CLK_MMC2 88
+#define CLK_BUS_SYSDAP 89
+#define CLK_BUS_MMC0 90
+#define CLK_BUS_MMC1 91
+#define CLK_BUS_MMC2 92
+#define CLK_BUS_UART0 93
+#define CLK_BUS_UART1 94
+#define CLK_BUS_UART2 95
+#define CLK_BUS_UART3 96
+#define CLK_BUS_UART4 97
+#define CLK_BUS_UART5 98
+#define CLK_BUS_UART6 99
+#define CLK_BUS_UART7 100
+#define CLK_BUS_I2C0 101
+#define CLK_BUS_I2C1 102
+#define CLK_BUS_I2C2 103
+#define CLK_BUS_I2C3 104
+#define CLK_BUS_I2C4 105
+#define CLK_BUS_I2C5 106
+#define CLK_BUS_CAN 107
+#define CLK_SPI0 108
+#define CLK_SPI1 109
+#define CLK_SPI2 110
+#define CLK_SPIFC 111
+#define CLK_BUS_SPI0 112
+#define CLK_BUS_SPI1 113
+#define CLK_BUS_SPI2 114
+#define CLK_BUS_SPIFC 115
+#define CLK_EMAC0_25M 116
+#define CLK_EMAC1_25M 117
+#define CLK_BUS_EMAC0 118
+#define CLK_BUS_EMAC1 119
+#define CLK_IR_RX 120
+#define CLK_BUS_IR_RX 121
+#define CLK_IR_TX 122
+#define CLK_BUS_IR_TX 123
+#define CLK_GPADC0 124
+#define CLK_GPADC1 125
+#define CLK_BUS_GPADC0 126
+#define CLK_BUS_GPADC1 127
+#define CLK_BUS_THS 128
+#define CLK_USB_OHCI0 129
+#define CLK_USB_OHCI1 130
+#define CLK_BUS_OHCI0 131
+#define CLK_BUS_OHCI1 132
+#define CLK_BUS_EHCI0 133
+#define CLK_BUS_EHCI1 134
+#define CLK_BUS_OTG 135
+#define CLK_BUS_LRADC 136
+#define CLK_PCIE_AUX 137
+#define CLK_BUS_DPSS_TOP 138
+#define CLK_HDMI_24M 139
+#define CLK_HDMI_CEC_32K 140
+#define CLK_HDMI_CEC 141
+#define CLK_BUS_HDMI 142
+#define CLK_MIPI_DSI0 143
+#define CLK_MIPI_DSI1 144
+#define CLK_BUS_MIPI_DSI0 145
+#define CLK_BUS_MIPI_DSI1 146
+#define CLK_TCON_LCD0 147
+#define CLK_TCON_LCD1 148
+#define CLK_COMBOPHY_DSI0 149
+#define CLK_COMBOPHY_DSI1 150
+#define CLK_BUS_TCON_LCD0 151
+#define CLK_BUS_TCON_LCD1 152
+#define CLK_TCON_TV0 153
+#define CLK_TCON_TV1 154
+#define CLK_BUS_TCON_TV0 155
+#define CLK_BUS_TCON_TV1 156
+#define CLK_EDP 157
+#define CLK_BUS_EDP 158
+#define CLK_LEDC 159
+#define CLK_BUS_LEDC 160
+#define CLK_CSI_TOP 161
+#define CLK_CSI_MCLK0 162
+#define CLK_CSI_MCLK1 163
+#define CLK_CSI_MCLK2 164
+#define CLK_CSI_MCLK3 165
+#define CLK_BUS_CSI 166
+#define CLK_ISP 167
+#define CLK_DSP 168
+#define CLK_BUS_DSP_CFG 169
+#define CLK_FANOUT_24M 170
+#define CLK_FANOUT_12M 171
+#define CLK_FANOUT_16M 172
+#define CLK_FANOUT_25M 173
+#define CLK_FANOUT_32K 174
+#define CLK_FANOUT_27M 175
+#define CLK_FANOUT_PCLK 176
+#define CLK_FANOUT0 177
+#define CLK_FANOUT1 178
+#define CLK_FANOUT2 179
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun55i-a523-ccu.h b/include/dt-bindings/reset/sun55i-a523-ccu.h
new file mode 100644
index 0000000000000..f137d03b03fbe
--- /dev/null
+++ b/include/dt-bindings/reset/sun55i-a523-ccu.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN55I_A523_CCU_H_
+#define _DT_BINDINGS_RST_SUN55I_A523_CCU_H_
+
+#define RST_MBUS 0
+#define RST_BUS_NSI 1
+#define RST_BUS_DE 2
+#define RST_BUS_DI 3
+#define RST_BUS_G2D 4
+#define RST_BUS_SYS 5
+#define RST_BUS_GPU 6
+#define RST_BUS_CE 7
+#define RST_BUS_SYS_CE 8
+#define RST_BUS_VE 9
+#define RST_BUS_DMA 10
+#define RST_BUS_MSGBOX 11
+#define RST_BUS_SPINLOCK 12
+#define RST_BUS_CPUXTIMER 13
+#define RST_BUS_DBG 14
+#define RST_BUS_PWM0 15
+#define RST_BUS_PWM1 16
+#define RST_BUS_DRAM 17
+#define RST_BUS_NAND 18
+#define RST_BUS_MMC0 19
+#define RST_BUS_MMC1 20
+#define RST_BUS_MMC2 21
+#define RST_BUS_SYSDAP 22
+#define RST_BUS_UART0 23
+#define RST_BUS_UART1 24
+#define RST_BUS_UART2 25
+#define RST_BUS_UART3 26
+#define RST_BUS_UART4 27
+#define RST_BUS_UART5 28
+#define RST_BUS_UART6 29
+#define RST_BUS_UART7 30
+#define RST_BUS_I2C0 31
+#define RST_BUS_I2C1 32
+#define RST_BUS_I2C2 33
+#define RST_BUS_I2C3 34
+#define RST_BUS_I2C4 35
+#define RST_BUS_I2C5 36
+#define RST_BUS_CAN 37
+#define RST_BUS_SPI0 38
+#define RST_BUS_SPI1 39
+#define RST_BUS_SPI2 40
+#define RST_BUS_SPIFC 41
+#define RST_BUS_EMAC0 42
+#define RST_BUS_EMAC1 43
+#define RST_BUS_IR_RX 44
+#define RST_BUS_IR_TX 45
+#define RST_BUS_GPADC0 46
+#define RST_BUS_GPADC1 47
+#define RST_BUS_THS 48
+#define RST_USB_PHY0 49
+#define RST_USB_PHY1 50
+#define RST_BUS_OHCI0 51
+#define RST_BUS_OHCI1 52
+#define RST_BUS_EHCI0 53
+#define RST_BUS_EHCI1 54
+#define RST_BUS_OTG 55
+#define RST_BUS_3 56
+#define RST_BUS_LRADC 57
+#define RST_BUS_PCIE_USB3 58
+#define RST_BUS_DPSS_TOP 59
+#define RST_BUS_HDMI_MAIN 60
+#define RST_BUS_HDMI_SUB 61
+#define RST_BUS_MIPI_DSI0 62
+#define RST_BUS_MIPI_DSI1 63
+#define RST_BUS_TCON_LCD0 64
+#define RST_BUS_TCON_LCD1 65
+#define RST_BUS_TCON_LCD2 66
+#define RST_BUS_TCON_TV0 67
+#define RST_BUS_TCON_TV1 68
+#define RST_BUS_LVDS0 69
+#define RST_BUS_LVDS1 70
+#define RST_BUS_EDP 71
+#define RST_BUS_VIDEO_OUT0 72
+#define RST_BUS_VIDEO_OUT1 73
+#define RST_BUS_LEDC 74
+#define RST_BUS_CSI 75
+#define RST_BUS_ISP 76
+
+#endif /* _DT_BINDINGS_RST_SUN55I_A523_CCU_H_ */
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (3 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 04/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 CCU Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:03 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 06/15] clk: sunxi-ng: a523: Add support for bus clocks Andre Przywara
` (9 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the PLL clocks of the main CCU of the Allwinner A523 and T527 SoCs.
The clocks were modelled after the A523 and T527 manual, and double
checked by writing all 1's into the respective register, to spot all
implemented bits.
The PLL and mod clocks for the two CPU clusters and the DSU are part of
a separate CCU, also most audio clocks are collected in a DSP CCU, so
both of these clock groups are missing from this driver.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 2 +
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 481 +++++++++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun55i-a523.h | 14 +
drivers/clk/sunxi-ng/ccu_mp.h | 14 +-
5 files changed, 510 insertions(+), 6 deletions(-)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index b547198a2c654..04efbda847cf9 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -52,6 +52,11 @@ config SUN50I_H6_R_CCU
default y
depends on ARM64 || COMPILE_TEST
+config SUN55I_A523_CCU
+ tristate "Support for the Allwinner A523/T527 CCU"
+ default y
+ depends on ARM64 || COMPILE_TEST
+
config SUN4I_A10_CCU
tristate "Support for the Allwinner A10/A20 CCU"
default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6b3ae2b620db6..01a887f7824bb 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
+obj-$(CONFIG_SUN55I_A523_CCU) += sun55i-a523-ccu.o
obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
@@ -58,6 +59,7 @@ sun50i-a100-r-ccu-y += ccu-sun50i-a100-r.o
sun50i-h6-ccu-y += ccu-sun50i-h6.o
sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
sun50i-h616-ccu-y += ccu-sun50i-h616.o
+sun55i-a523-ccu-y += ccu-sun55i-a523.o
sun4i-a10-ccu-y += ccu-sun4i-a10.o
sun5i-ccu-y += ccu-sun5i.o
sun6i-a31-ccu-y += ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
new file mode 100644
index 0000000000000..8374e841e9d82
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023-2024 Arm Ltd.
+ * Based on the D1 CCU driver:
+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "../clk.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-sun55i-a523.h"
+
+/*
+ * The 24 MHz oscillator, the root of most of the clock tree.
+ * .fw_name is the string used in the DT "clock-names" property, used to
+ * identify the corresponding clock in the "clocks" property.
+ */
+static const struct clk_parent_data osc24M[] = {
+ { .fw_name = "hosc" }
+};
+
+/**************************************************************************
+ * PLLs *
+ **************************************************************************/
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN55I_A523_PLL_DDR0_REG 0x010
+static struct ccu_nkmp pll_ddr0_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x010,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M,
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_GATE |
+ CLK_IS_CRITICAL),
+ },
+};
+
+/*
+ * There is no actual clock output with that frequency (2.4 GHz), instead it
+ * has multiple outputs with adjustable dividers from that base frequency.
+ * Model them separately as divider clocks based on that parent here.
+ */
+#define SUN55I_A523_PLL_PERIPH0_REG 0x020
+static struct ccu_nm pll_periph0_4x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x020,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+/*
+ * Most clock-defining macros expect an *array* of parent clocks, even if
+ * they do not contain a muxer to select between different parents.
+ * The macros ending in just _HW take a simple clock pointer, but then create
+ * a single-entry array out of that. The macros using _HWS take such an
+ * array (even when it is a single entry one), this avoids having those
+ * helper arrays created inside *every* clock definition.
+ * This means for every clock that is referenced more than once it is
+ * useful to create such a dummy array and use _HWS.
+ */
+static const struct clk_hw *pll_periph0_4x_hws[] = {
+ &pll_periph0_4x_clk.common.hw
+};
+
+static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
+ pll_periph0_4x_hws, 0x020, 16, 3, 0);
+static const struct clk_hw *pll_periph0_2x_hws[] = {
+ &pll_periph0_2x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M",
+ pll_periph0_4x_hws, 0x020, 20, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph0_480M_clk, "pll-periph0-480M",
+ pll_periph0_4x_hws, 0x020, 2, 3, 0);
+static const struct clk_hw *pll_periph0_480M_hws[] = {
+ &pll_periph0_480M_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph0_600M_clk, "pll-periph0-600M",
+ pll_periph0_2x_hws, 2, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_400M_clk, "pll-periph0-400M",
+ pll_periph0_2x_hws, 3, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_300M_clk, "pll-periph0-300M",
+ pll_periph0_2x_hws, 4, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_200M_clk, "pll-periph0-200M",
+ pll_periph0_2x_hws, 6, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
+ pll_periph0_2x_hws, 8, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
+ pll_periph0_480M_hws, 3, 1, 0);
+
+#define SUN55I_A523_PLL_PERIPH1_REG 0x028
+static struct ccu_nm pll_periph1_4x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x028,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph1-4x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+static const struct clk_hw *pll_periph1_4x_hws[] = {
+ &pll_periph1_4x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
+ pll_periph1_4x_hws, 0x028, 16, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph1_800M_clk, "pll-periph1-800M",
+ pll_periph1_4x_hws, 0x028, 20, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph1_480M_clk, "pll-periph1-480M",
+ pll_periph1_4x_hws, 0x028, 2, 3, 0);
+
+static const struct clk_hw *pll_periph1_2x_hws[] = {
+ &pll_periph1_2x_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph1_600M_clk, "pll-periph1-600M",
+ pll_periph1_2x_hws, 2, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_400M_clk, "pll-periph1-400M",
+ pll_periph1_2x_hws, 3, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_300M_clk, "pll-periph1-300M",
+ pll_periph1_2x_hws, 4, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_200M_clk, "pll-periph1-200M",
+ pll_periph1_2x_hws, 6, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_150M_clk, "pll-periph1-150M",
+ pll_periph1_2x_hws, 8, 1, 0);
+static const struct clk_hw *pll_periph1_480M_hws[] = {
+ &pll_periph1_480M_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph1_160M_clk, "pll-periph1-160M",
+ pll_periph1_480M_hws, 3, 1, 0);
+
+#define SUN55I_A523_PLL_GPU_REG 0x030
+static struct ccu_nkmp pll_gpu_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x030,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-gpu", osc24M,
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+#define SUN55I_A523_PLL_VIDEO0_REG 0x040
+static struct ccu_nm pll_video0_8x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x040,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video0-8x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+static const struct clk_hw *pll_video0_8x_hws[] = {
+ &pll_video0_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video0_4x_clk, "pll-video0-4x",
+ pll_video0_8x_hws, 0x040, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video0_3x_clk, "pll-video0-3x",
+ pll_video0_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VIDEO1_REG 0x048
+static struct ccu_nm pll_video1_8x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x048,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video1-8x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+static const struct clk_hw *pll_video1_8x_hws[] = {
+ &pll_video1_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video1_4x_clk, "pll-video1-4x",
+ pll_video1_8x_hws, 0x048, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video1_3x_clk, "pll-video1-3x",
+ pll_video1_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VIDEO2_REG 0x050
+static struct ccu_nm pll_video2_8x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x050,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video2-8x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+static const struct clk_hw *pll_video2_8x_hws[] = {
+ &pll_video2_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video2_4x_clk, "pll-video2-4x",
+ pll_video2_8x_hws, 0x050, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video2_3x_clk, "pll-video2-3x",
+ pll_video2_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VE_REG 0x058
+static struct ccu_nkmp pll_ve_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x058,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M,
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+#define SUN55I_A523_PLL_VIDEO3_REG 0x068
+static struct ccu_nm pll_video3_8x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x068,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video3-8x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+static const struct clk_hw *pll_video3_8x_hws[] = {
+ &pll_video3_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video3_4x_clk, "pll-video3-4x",
+ pll_video3_8x_hws, 0x068, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video3_3x_clk, "pll-video3-3x",
+ pll_video3_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+/*
+ * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors.
+ * Since we only need some fixed frequency from this PLL (22.5792MHz x 4 and
+ * 24.576MHz x 4), ignore those dividers and force both of them to 1 (encoded
+ * as 0), in the probe function below.
+ * The M factor must be an even number to produce a 50% duty cycle output.
+ */
+#define SUN55I_A523_PLL_AUDIO0_REG 0x078
+static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
+ { .rate = 90316800, .pattern = 0xc000872b, .m = 20, .n = 75 },
+ { .rate = 98304000, .pattern = 0xc0004dd3, .m = 12, .n = 49 },
+
+};
+
+static struct ccu_nm pll_audio0_4x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(16, 6),
+ .sdm = _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24),
+ 0x178, BIT(31)),
+ .min_rate = 180000000U,
+ .max_rate = 3000000000U,
+ .common = {
+ .reg = 0x078,
+ .features = CCU_FEATURE_SIGMA_DELTA_MOD,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+
+static CLK_FIXED_FACTOR_HW(pll_audio0_2x_clk, "pll-audio0-2x",
+ &pll_audio0_4x_clk.common.hw, 2, 1, 0);
+static CLK_FIXED_FACTOR_HW(pll_audio0_clk, "pll-audio0",
+ &pll_audio0_4x_clk.common.hw, 4, 1, 0);
+
+#define SUN55I_A523_PLL_NPU_REG 0x080
+static struct ccu_nm pll_npu_4x_clk = {
+ .enable = BIT(27),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x0080,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x",
+ osc24M, &ccu_nm_ops,
+ CLK_SET_RATE_GATE),
+ },
+};
+static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
+ &pll_npu_4x_clk.common.hw, 2, 1, CLK_SET_RATE_PARENT);
+
+static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
+ &pll_npu_4x_clk.common.hw, 4, 1, 0);
+
+/*
+ * Contains all clocks that are controlled by a hardware register. They
+ * have a (sunxi) .common member, which needs to be initialised by the common
+ * sunxi CCU code, to be filled with the MMIO base address and the shared lock.
+ */
+static struct ccu_common *sun55i_a523_ccu_clks[] = {
+ &pll_ddr0_clk.common,
+ &pll_periph0_4x_clk.common,
+ &pll_periph0_2x_clk.common,
+ &pll_periph0_800M_clk.common,
+ &pll_periph0_480M_clk.common,
+ &pll_periph1_4x_clk.common,
+ &pll_periph1_2x_clk.common,
+ &pll_periph1_800M_clk.common,
+ &pll_periph1_480M_clk.common,
+ &pll_gpu_clk.common,
+ &pll_video0_8x_clk.common,
+ &pll_video0_4x_clk.common,
+ &pll_video1_8x_clk.common,
+ &pll_video1_4x_clk.common,
+ &pll_video2_8x_clk.common,
+ &pll_video2_4x_clk.common,
+ &pll_video3_8x_clk.common,
+ &pll_video3_4x_clk.common,
+ &pll_ve_clk.common,
+ &pll_audio0_4x_clk.common,
+ &pll_npu_4x_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
+ .num = CLK_NUMBER,
+ .hws = {
+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
+ [CLK_PLL_PERIPH0_4X] = &pll_periph0_4x_clk.common.hw,
+ [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.common.hw,
+ [CLK_PLL_PERIPH0_800M] = &pll_periph0_800M_clk.common.hw,
+ [CLK_PLL_PERIPH0_480M] = &pll_periph0_480M_clk.common.hw,
+ [CLK_PLL_PERIPH0_600M] = &pll_periph0_600M_clk.hw,
+ [CLK_PLL_PERIPH0_400M] = &pll_periph0_400M_clk.hw,
+ [CLK_PLL_PERIPH0_300M] = &pll_periph0_300M_clk.hw,
+ [CLK_PLL_PERIPH0_200M] = &pll_periph0_200M_clk.hw,
+ [CLK_PLL_PERIPH0_160M] = &pll_periph0_160M_clk.hw,
+ [CLK_PLL_PERIPH0_150M] = &pll_periph0_150M_clk.hw,
+ [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_clk.common.hw,
+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.common.hw,
+ [CLK_PLL_PERIPH1_800M] = &pll_periph1_800M_clk.common.hw,
+ [CLK_PLL_PERIPH1_480M] = &pll_periph1_480M_clk.common.hw,
+ [CLK_PLL_PERIPH1_600M] = &pll_periph1_600M_clk.hw,
+ [CLK_PLL_PERIPH1_400M] = &pll_periph1_400M_clk.hw,
+ [CLK_PLL_PERIPH1_300M] = &pll_periph1_300M_clk.hw,
+ [CLK_PLL_PERIPH1_200M] = &pll_periph1_200M_clk.hw,
+ [CLK_PLL_PERIPH1_160M] = &pll_periph1_160M_clk.hw,
+ [CLK_PLL_PERIPH1_150M] = &pll_periph1_150M_clk.hw,
+ [CLK_PLL_VIDEO0_8X] = &pll_video0_8x_clk.common.hw,
+ [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.common.hw,
+ [CLK_PLL_VIDEO0_3X] = &pll_video0_3x_clk.hw,
+ [CLK_PLL_VIDEO1_8X] = &pll_video1_8x_clk.common.hw,
+ [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.common.hw,
+ [CLK_PLL_VIDEO1_3X] = &pll_video1_3x_clk.hw,
+ [CLK_PLL_VIDEO2_8X] = &pll_video2_8x_clk.common.hw,
+ [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.common.hw,
+ [CLK_PLL_VIDEO2_3X] = &pll_video2_3x_clk.hw,
+ [CLK_PLL_VIDEO3_8X] = &pll_video3_8x_clk.common.hw,
+ [CLK_PLL_VIDEO3_4X] = &pll_video3_4x_clk.common.hw,
+ [CLK_PLL_VIDEO3_3X] = &pll_video3_3x_clk.hw,
+ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
+ [CLK_PLL_AUDIO0_4X] = &pll_audio0_4x_clk.common.hw,
+ [CLK_PLL_AUDIO0_2X] = &pll_audio0_2x_clk.hw,
+ [CLK_PLL_AUDIO0] = &pll_audio0_clk.hw,
+ [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
+ [CLK_PLL_NPU_2X] = &pll_npu_2x_clk.hw,
+ [CLK_PLL_NPU] = &pll_npu_1x_clk.hw,
+ },
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
+ .ccu_clks = sun55i_a523_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun55i_a523_ccu_clks),
+
+ .hw_clks = &sun55i_a523_hw_clks,
+};
+
+static const u32 pll_regs[] = {
+ SUN55I_A523_PLL_DDR0_REG,
+ SUN55I_A523_PLL_PERIPH0_REG,
+ SUN55I_A523_PLL_PERIPH1_REG,
+ SUN55I_A523_PLL_GPU_REG,
+ SUN55I_A523_PLL_VIDEO0_REG,
+ SUN55I_A523_PLL_VIDEO1_REG,
+ SUN55I_A523_PLL_VIDEO2_REG,
+ SUN55I_A523_PLL_VE_REG,
+ SUN55I_A523_PLL_VIDEO3_REG,
+ SUN55I_A523_PLL_AUDIO0_REG,
+ SUN55I_A523_PLL_NPU_REG,
+};
+
+static int sun55i_a523_ccu_probe(struct platform_device *pdev)
+{
+ void __iomem *reg;
+ u32 val;
+ int i, ret;
+
+ reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ /*
+ * The PLL clock code does not model all bits, for instance it does
+ * not support a separate enable and gate bit. We present the
+ * gate bit(27) as the enable bit, but then have to set the
+ * PLL Enable, LDO Enable, and Lock Enable bits on all PLLs here.
+ */
+ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+ val = readl(reg + pll_regs[i]);
+ val |= BIT(31) | BIT(30) | BIT(29);
+ writel(val, reg + pll_regs[i]);
+ }
+
+ /* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
+ val = readl(reg + SUN55I_A523_PLL_AUDIO0_REG);
+ val &= ~(BIT(1) | BIT(0));
+ writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
+
+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id sun55i_a523_ccu_ids[] = {
+ { .compatible = "allwinner,sun55i-a523-ccu" },
+ { }
+};
+
+static struct platform_driver sun55i_a523_ccu_driver = {
+ .probe = sun55i_a523_ccu_probe,
+ .driver = {
+ .name = "sun55i-a523-ccu",
+ .suppress_bind_attrs = true,
+ .of_match_table = sun55i_a523_ccu_ids,
+ },
+};
+module_platform_driver(sun55i_a523_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_DESCRIPTION("Support for the Allwinner A523 CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
new file mode 100644
index 0000000000000..fc8dd42f1b47b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_H
+#define _CCU_SUN55I_A523_H
+
+#include <dt-bindings/clock/sun55i-a523-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-ccu.h>
+
+#define CLK_NUMBER (CLK_FANOUT2 + 1)
+
+#endif /* _CCU_SUN55I_A523_H */
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index 687bd2ec798e2..5311835a4db60 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -100,20 +100,22 @@ struct ccu_mp {
_muxshift, _muxwidth, \
0, _flags)
-#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
+#define SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
- _gate, _flags, \
- _features) \
+ _gate, _postdiv, \
+ _flags, _features) \
struct ccu_mp _struct = { \
.enable = _gate, \
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
+ .fixed_post_div = _postdiv, \
.common = { \
.reg = _reg, \
- .features = _features, \
+ .features = CCU_FEATURE_FIXED_POSTDIV | \
+ _features, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
_parents, \
&ccu_mp_ops,\
@@ -126,11 +128,11 @@ struct ccu_mp {
_pshift, _pwidth, \
_muxshift, _muxwidth, \
_gate, _flags) \
- SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, \
+ SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(_struct, _name, _parents, \
_reg, _mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
- _gate, _flags, 0)
+ _gate, 1, _flags, 0)
#define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 06/15] clk: sunxi-ng: a523: Add support for bus clocks
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (4 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:06 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks Andre Przywara
` (8 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the basic bus clocks for the Allwinner A523 and T527 SoCs.
This covers the AHB, APB0 and APB1 clocks. Linux is not supposed to
change those clocks, but they are needed as parents for many other mod
clocks.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 39 ++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 8374e841e9d82..59f45e7c0904b 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -331,6 +331,39 @@ static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
&pll_npu_4x_clk.common.hw, 4, 1, 0);
+
+/**************************************************************************
+ * bus clocks *
+ **************************************************************************/
+
+static const struct clk_parent_data ahb_apb0_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .hw = &pll_periph0_600M_clk.hw },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
+ 0, 5, /* M */
+ 24, 2, /* mux */
+ 0);
+static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
+ 0, 5, /* M */
+ 24, 2, /* mux */
+ 0);
+
+static const struct clk_parent_data apb1_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .hw = &pll_periph0_600M_clk.hw },
+ { .hw = &pll_periph0_480M_clk.common.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ 0);
+
/*
* Contains all clocks that are controlled by a hardware register. They
* have a (sunxi) .common member, which needs to be initialised by the common
@@ -358,6 +391,9 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&pll_ve_clk.common,
&pll_audio0_4x_clk.common,
&pll_npu_4x_clk.common,
+ &ahb_clk.common,
+ &apb0_clk.common,
+ &apb1_clk.common,
};
static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -403,6 +439,9 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
[CLK_PLL_NPU_2X] = &pll_npu_2x_clk.hw,
[CLK_PLL_NPU] = &pll_npu_1x_clk.hw,
+ [CLK_AHB] = &ahb_clk.common.hw,
+ [CLK_APB0] = &apb0_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
},
};
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (5 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 06/15] clk: sunxi-ng: a523: Add support for bus clocks Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:26 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 08/15] clk: sunxi-ng: a523: add system " Andre Przywara
` (7 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the clocks driving the various video subsystems of the SoC: the "DE"
display engine, the "DI" deinterlacer, the "G2D" 2D graphics system, the
Mali "GPU", the "VE" video engine, its associated IOMMU, as well as the
clocks for the various video output drivers (HDMI, DP, LCDs).
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 219 +++++++++++++++++++++++++
1 file changed, 219 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 59f45e7c0904b..0ef1fd71a1ca5 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -364,6 +364,192 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
24, 3, /* mux */
0);
+
+/**************************************************************************
+ * mod clocks *
+ **************************************************************************/
+
+static const struct clk_hw *de_parents[] = {
+ &pll_periph0_300M_clk.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_video3_4x_clk.common.hw,
+ &pll_video3_3x_clk.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *di_parents[] = {
+ &pll_periph0_300M_clk.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_video0_4x_clk.common.hw,
+ &pll_video1_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *g2d_parents[] = {
+ &pll_periph0_400M_clk.hw,
+ &pll_periph0_300M_clk.hw,
+ &pll_video0_4x_clk.common.hw,
+ &pll_video1_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_hw *gpu_parents[] = {
+ &pll_gpu_clk.common.hw,
+ &pll_periph0_800M_clk.common.hw,
+ &pll_periph0_600M_clk.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_periph0_300M_clk.hw,
+ &pll_periph0_200M_clk.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_hw *ve_parents[] = {
+ &pll_ve_clk.common.hw,
+ &pll_periph0_480M_clk.common.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_periph0_300M_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data iommu_parents[] = {
+ { .hw = &pll_periph0_600M_clk.hw },
+ { .hw = &pll_ddr0_clk.common.hw },
+ { .hw = &pll_periph0_480M_clk.common.hw },
+ { .hw = &pll_periph0_400M_clk.hw },
+ { .hw = &pll_periph0_150M_clk.hw },
+ { .fw_name = "hosc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
+
+/* TODO: add mux between 32kOSC and PERIPH0/18750 */
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
+ pll_periph0_2x_hws,
+ 0xb10, BIT(30), 36621, 0);
+
+static const struct clk_parent_data hdmi_cec_parents[] = {
+ { .fw_name = "losc" },
+ { .hw = &hdmi_cec_32k_clk.common.hw },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
+ 0xb10,
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_parent_data mipi_dsi_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph0_200M_clk.hw },
+ { .hw = &pll_periph0_150M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi0_clk, "mipi-dsi0",
+ mipi_dsi_parents, 0xb24,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
+ mipi_dsi_parents, 0xb28,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *tcon_parents[] = {
+ &pll_video0_4x_clk.common.hw,
+ &pll_video1_4x_clk.common.hw,
+ &pll_video2_4x_clk.common.hw,
+ &pll_video3_4x_clk.common.hw,
+ &pll_periph0_2x_clk.common.hw,
+ &pll_video0_3x_clk.hw,
+ &pll_video1_3x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
+ 0xb60,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
+ 0xb64,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi0_clk, "combophy-dsi0",
+ tcon_parents, 0xb6c,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
+ tcon_parents, 0xb70,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
+ 0xb80,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
+ 0xb84,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *edp_parents[] = {
+ &pll_video0_4x_clk.common.hw,
+ &pll_video1_4x_clk.common.hw,
+ &pll_video2_4x_clk.common.hw,
+ &pll_video3_4x_clk.common.hw,
+ &pll_periph0_2x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
/*
* Contains all clocks that are controlled by a hardware register. They
* have a (sunxi) .common member, which needs to be initialised by the common
@@ -394,6 +580,22 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&ahb_clk.common,
&apb0_clk.common,
&apb1_clk.common,
+ &de_clk.common,
+ &di_clk.common,
+ &g2d_clk.common,
+ &gpu_clk.common,
+ &ve_clk.common,
+ &iommu_clk.common,
+ &hdmi_24M_clk.common,
+ &hdmi_cec_32k_clk.common,
+ &hdmi_cec_clk.common,
+ &mipi_dsi0_clk.common,
+ &mipi_dsi1_clk.common,
+ &tcon_lcd0_clk.common,
+ &tcon_lcd1_clk.common,
+ &tcon_tv0_clk.common,
+ &tcon_tv1_clk.common,
+ &edp_clk.common,
};
static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -442,6 +644,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_AHB] = &ahb_clk.common.hw,
[CLK_APB0] = &apb0_clk.common.hw,
[CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_DI] = &di_clk.common.hw,
+ [CLK_G2D] = &g2d_clk.common.hw,
+ [CLK_GPU] = &gpu_clk.common.hw,
+ [CLK_VE] = &ve_clk.common.hw,
+ [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
+ [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
+ [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
+ [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
+ [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
+ [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
+ [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
+ [CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
+ [CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
+ [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
+ [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
+ [CLK_EDP] = &edp_clk.common.hw,
},
};
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 08/15] clk: sunxi-ng: a523: add system mod clocks
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (6 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:34 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 09/15] clk: sunxi-ng: a523: add interface " Andre Przywara
` (6 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the clocks driving some core system related subsystems of the SoC:
the "CE" crypto engine, the high speed timers, the DRAM and the associated
MBUS clock, and the PCIe clock.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 119 +++++++++++++++++++++++++
1 file changed, 119 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 0ef1fd71a1ca5..b68c44bce825f 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -423,6 +423,18 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
BIT(31), /* gate */
0);
+static const struct clk_parent_data ce_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph0_480M_clk.common.hw },
+ { .hw = &pll_periph0_400M_clk.hw },
+ { .hw = &pll_periph0_300M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
static const struct clk_hw *ve_parents[] = {
&pll_ve_clk.common.hw,
&pll_periph0_480M_clk.common.hw,
@@ -435,6 +447,65 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static const struct clk_parent_data hstimer_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "iosc" },
+ { .fw_name = "losc" },
+ { .hw = &pll_periph0_200M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
+ hstimer_parents, 0x730,
+ 0, 0, /* M */
+ 0, 3, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
+ hstimer_parents,
+ 0x734,
+ 0, 0, /* M */
+ 0, 3, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
+ hstimer_parents,
+ 0x738,
+ 0, 0, /* M */
+ 0, 3, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
+ hstimer_parents,
+ 0x73c,
+ 0, 0, /* M */
+ 0, 3, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
+ hstimer_parents,
+ 0x740,
+ 0, 0, /* M */
+ 0, 3, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
+ hstimer_parents,
+ 0x744,
+ 0, 0, /* M */
+ 0, 3, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
static const struct clk_parent_data iommu_parents[] = {
{ .hw = &pll_periph0_600M_clk.hw },
{ .hw = &pll_ddr0_clk.common.hw },
@@ -450,6 +521,34 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static const struct clk_hw *dram_parents[] = {
+ &pll_ddr0_clk.common.hw,
+ &pll_periph0_600M_clk.hw,
+ &pll_periph0_480M_clk.common.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_periph0_150M_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_IS_CRITICAL);
+
+static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
+ &dram_clk.common.hw, 4, 1, 0);
+
+static const struct clk_parent_data losc_hosc_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
+ losc_hosc_parents, 0xaa0,
+ 0, 5, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
/* TODO: add mux between 32kOSC and PERIPH0/18750 */
@@ -584,8 +683,17 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&di_clk.common,
&g2d_clk.common,
&gpu_clk.common,
+ &ce_clk.common,
&ve_clk.common,
+ &hstimer0_clk.common,
+ &hstimer1_clk.common,
+ &hstimer2_clk.common,
+ &hstimer3_clk.common,
+ &hstimer4_clk.common,
+ &hstimer5_clk.common,
&iommu_clk.common,
+ &dram_clk.common,
+ &pcie_aux_clk.common,
&hdmi_24M_clk.common,
&hdmi_cec_32k_clk.common,
&hdmi_cec_clk.common,
@@ -644,11 +752,22 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_AHB] = &ahb_clk.common.hw,
[CLK_APB0] = &apb0_clk.common.hw,
[CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.hw,
[CLK_DE] = &de_clk.common.hw,
[CLK_DI] = &di_clk.common.hw,
[CLK_G2D] = &g2d_clk.common.hw,
[CLK_GPU] = &gpu_clk.common.hw,
+ [CLK_CE] = &ce_clk.common.hw,
[CLK_VE] = &ve_clk.common.hw,
+ [CLK_HSTIMER0] = &hstimer0_clk.common.hw,
+ [CLK_HSTIMER1] = &hstimer1_clk.common.hw,
+ [CLK_HSTIMER2] = &hstimer2_clk.common.hw,
+ [CLK_HSTIMER3] = &hstimer3_clk.common.hw,
+ [CLK_HSTIMER4] = &hstimer4_clk.common.hw,
+ [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
+ [CLK_IOMMU] = &iommu_clk.common.hw,
+ [CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
[CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
[CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
[CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 09/15] clk: sunxi-ng: a523: add interface mod clocks
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (7 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 08/15] clk: sunxi-ng: a523: add system " Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:42 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 10/15] clk: sunxi-ng: a523: add USB " Andre Przywara
` (5 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the clocks driving what the user manual summarises under "interface"
devices: raw NAND flash, MMC, SPI, EMAC, "IR" infrared, and the "GPADC"
general purpose analogue/digital converter.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 160 +++++++++++++++++++++++++
1 file changed, 160 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index b68c44bce825f..14d13fb16dfbb 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -113,6 +113,9 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
pll_periph0_2x_hws, 8, 1, 0);
static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
pll_periph0_480M_hws, 3, 1, 0);
+static const struct clk_hw *pll_periph0_150M_hws[] = {
+ &pll_periph0_150M_clk.hw
+};
#define SUN55I_A523_PLL_PERIPH1_REG 0x028
static struct ccu_nm pll_periph1_4x_clk = {
@@ -537,6 +540,133 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
&dram_clk.common.hw, 4, 1, 0);
+static const struct clk_parent_data nand_mmc_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph0_400M_clk.hw },
+ { .hw = &pll_periph0_300M_clk.hw },
+ { .hw = &pll_periph1_400M_clk.hw },
+ { .hw = &pll_periph1_300M_clk.hw },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand0_clk, "nand0", nand_mmc_parents,
+ 0x810,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
+ 0x814,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
+ 0x830,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 2, /* post div */
+ 0, CCU_FEATURE_DUAL_DIV);
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc1_clk, "mmc1", nand_mmc_parents,
+ 0x834,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 2, /* post div */
+ 0, CCU_FEATURE_DUAL_DIV);
+
+static const struct clk_parent_data mmc2_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph0_800M_clk.common.hw },
+ { .hw = &pll_periph0_600M_clk.hw },
+ { .hw = &pll_periph1_800M_clk.common.hw },
+ { .hw = &pll_periph1_600M_clk.hw },
+};
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
+ 0x838,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 2, /* post div */
+ 0, CCU_FEATURE_DUAL_DIV);
+
+static const struct clk_parent_data spi_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph0_300M_clk.hw },
+ { .hw = &pll_periph0_200M_clk.hw },
+ { .hw = &pll_periph1_300M_clk.hw },
+ { .hw = &pll_periph1_200M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
+ 0x950,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
+ pll_periph0_150M_hws,
+ 0x970, BIT(31) | BIT(30), 6, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
+ pll_periph0_150M_hws,
+ 0x974, BIT(31) | BIT(30), 6, 0);
+
+static const struct clk_parent_data ir_rx_parents[] = {
+ { .fw_name = "losc" },
+ { .fw_name = "hosc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
+ 0, 5, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+static const struct clk_parent_data ir_tx_ledc_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph1_600M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
+ 0x9c0,
+ 0, 5, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
+ 0, 5, /* M */
+ BIT(31), /* gate */
+ 0);
+static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
+ 0, 5, /* M */
+ BIT(31), /* gate */
+ 0);
+
static const struct clk_parent_data losc_hosc_parents[] = {
{ .fw_name = "hosc" },
{ .fw_name = "losc" },
@@ -693,6 +823,21 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&hstimer5_clk.common,
&iommu_clk.common,
&dram_clk.common,
+ &nand0_clk.common,
+ &nand1_clk.common,
+ &mmc0_clk.common,
+ &mmc1_clk.common,
+ &mmc2_clk.common,
+ &spi0_clk.common,
+ &spi1_clk.common,
+ &spi2_clk.common,
+ &spifc_clk.common,
+ &emac0_25M_clk.common,
+ &emac1_25M_clk.common,
+ &ir_rx_clk.common,
+ &ir_tx_clk.common,
+ &gpadc0_clk.common,
+ &gpadc1_clk.common,
&pcie_aux_clk.common,
&hdmi_24M_clk.common,
&hdmi_cec_32k_clk.common,
@@ -767,6 +912,21 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_HSTIMER5] = &hstimer5_clk.common.hw,
[CLK_IOMMU] = &iommu_clk.common.hw,
[CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_NAND0] = &nand0_clk.common.hw,
+ [CLK_NAND1] = &nand1_clk.common.hw,
+ [CLK_MMC0] = &mmc0_clk.common.hw,
+ [CLK_MMC1] = &mmc1_clk.common.hw,
+ [CLK_MMC2] = &mmc2_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_SPI1] = &spi1_clk.common.hw,
+ [CLK_SPI2] = &spi2_clk.common.hw,
+ [CLK_SPIFC] = &spifc_clk.common.hw,
+ [CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
+ [CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
+ [CLK_IR_RX] = &ir_rx_clk.common.hw,
+ [CLK_IR_TX] = &ir_tx_clk.common.hw,
+ [CLK_GPADC0] = &gpadc0_clk.common.hw,
+ [CLK_GPADC1] = &gpadc1_clk.common.hw,
[CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
[CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
[CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 10/15] clk: sunxi-ng: a523: add USB mod clocks
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (8 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 09/15] clk: sunxi-ng: a523: add interface " Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:46 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 11/15] clk: sunxi-ng: a523: remaining " Andre Przywara
` (4 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the clocks driving the USB subsystem: this just covers the two
clocks creating the 12 MHz rate for the OHCI (USB 1.x) device. The rest
of the USB clocks are either gate clocks (added later) or created
internal to the USB IP.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 57 ++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 14d13fb16dfbb..59cc31f89ae77 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -667,6 +667,59 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
BIT(31), /* gate */
0);
+/*
+ * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
+ * a 2x multiplier from osc24M synchronized by pll-periph0, and is also used by
+ * the OHCI module.
+ */
+static const struct clk_parent_data usb_ohci_parents[] = {
+ { .hw = &pll_periph0_4x_clk.common.hw },
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+};
+static const struct ccu_mux_fixed_prediv usb_ohci_predivs[] = {
+ { .index = 0, .div = 50 },
+ { .index = 1, .div = 2 },
+};
+
+static struct ccu_mux usb_ohci0_clk = {
+ .enable = BIT(31),
+ .mux = {
+ .shift = 24,
+ .width = 2,
+ .fixed_predivs = usb_ohci_predivs,
+ .n_predivs = ARRAY_SIZE(usb_ohci_predivs),
+ },
+ .common = {
+ .reg = 0xa70,
+ .features = CCU_FEATURE_FIXED_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("usb-ohci0",
+ usb_ohci_parents,
+ &ccu_mux_ops,
+ 0),
+ },
+};
+
+static struct ccu_mux usb_ohci1_clk = {
+ .enable = BIT(31),
+ .mux = {
+ .shift = 24,
+ .width = 2,
+ .fixed_predivs = usb_ohci_predivs,
+ .n_predivs = ARRAY_SIZE(usb_ohci_predivs),
+ },
+ .common = {
+ .reg = 0xa74,
+ .features = CCU_FEATURE_FIXED_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("usb-ohci1",
+ usb_ohci_parents,
+ &ccu_mux_ops,
+ 0),
+ },
+};
+
+
static const struct clk_parent_data losc_hosc_parents[] = {
{ .fw_name = "hosc" },
{ .fw_name = "losc" },
@@ -838,6 +891,8 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&ir_tx_clk.common,
&gpadc0_clk.common,
&gpadc1_clk.common,
+ &usb_ohci0_clk.common,
+ &usb_ohci1_clk.common,
&pcie_aux_clk.common,
&hdmi_24M_clk.common,
&hdmi_cec_32k_clk.common,
@@ -927,6 +982,8 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_IR_TX] = &ir_tx_clk.common.hw,
[CLK_GPADC0] = &gpadc0_clk.common.hw,
[CLK_GPADC1] = &gpadc1_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
[CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
[CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
[CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 11/15] clk: sunxi-ng: a523: remaining mod clocks
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (9 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 10/15] clk: sunxi-ng: a523: add USB " Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 19:55 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates Andre Przywara
` (3 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the remaining mod clocks, driving various parts of the SoC: the "LEDC"
LED controller, the "CSI" camera interface, the "ISP" image processor,
the DSP clock, and the "fanout" clocks, which allow to put clock signals
on external pins.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 190 +++++++++++++++++++++++++
1 file changed, 190 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 59cc31f89ae77..6a4340f1fd041 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -354,6 +354,7 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
0, 5, /* M */
24, 2, /* mux */
0);
+static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
static const struct clk_parent_data apb1_parents[] = {
{ .fw_name = "hosc" },
@@ -832,6 +833,153 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
BIT(31), /* gate */
0);
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
+ 0xbf0,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_hw *csi_top_parents[] = {
+ &pll_periph0_300M_clk.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_periph0_480M_clk.common.hw,
+ &pll_video3_4x_clk.common.hw,
+ &pll_video3_3x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents,
+ 0xc04,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_parent_data csi_mclk_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_video3_4x_clk.common.hw },
+ { .hw = &pll_video0_4x_clk.common.hw },
+ { .hw = &pll_video1_4x_clk.common.hw },
+ { .hw = &pll_video2_4x_clk.common.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0",
+ csi_mclk_parents, 0xc08,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1",
+ csi_mclk_parents, 0xc0c,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2",
+ csi_mclk_parents, 0xc10,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
+ csi_mclk_parents, 0xc14,
+ 0, 5, /* M */
+ 8, 5, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_hw *isp_parents[] = {
+ &pll_periph0_300M_clk.hw,
+ &pll_periph0_400M_clk.hw,
+ &pll_video2_4x_clk.common.hw,
+ &pll_video3_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(isp_clk, "isp", isp_parents, 0xc20,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_parent_data dsp_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .hw = &pll_periph0_2x_clk.common.hw },
+ { .hw = &pll_periph0_400M_clk.hw, },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
+ 0xf30, BIT(0), 0);
+static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
+ 0xf30, BIT(1), 2, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M",
+ pll_periph0_480M_hws,
+ 0xf30, BIT(2), 30, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M",
+ pll_periph0_2x_hws,
+ 0xf30, BIT(3), 48, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_50M_clk, "fanout-50M",
+ pll_periph0_2x_hws,
+ 0xf30, BIT(4), 24, 0);
+
+/* These clocks have a second divider that is not modelled and forced to 0. */
+#define SUN55I_A523_FANOUT_27M_REG 0xf34
+static const struct clk_hw *fanout_27M_parents[] = {
+ &pll_video0_4x_clk.common.hw,
+ &pll_video1_4x_clk.common.hw,
+ &pll_video2_4x_clk.common.hw,
+ &pll_video3_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M",
+ fanout_27M_parents, 0xf34,
+ 0, 5, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+#define SUN55I_A523_FANOUT_PCLK_REG 0xf38
+static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws,
+ 0xf38,
+ 0, 5, /* M */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_parent_data fanout_parents[] = {
+ { .fw_name = "osc32k-out" },
+ { .hw = &fanout_12M_clk.common.hw, },
+ { .hw = &fanout_16M_clk.common.hw, },
+ { .hw = &fanout_24M_clk.common.hw, },
+ { .hw = &fanout_25M_clk.common.hw, },
+ { .hw = &fanout_27M_clk.common.hw, },
+ { .hw = &fanout_pclk_clk.common.hw, },
+ { .hw = &fanout_50M_clk.common.hw, },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents,
+ 0xf3c,
+ 0, 3, /* mux */
+ BIT(21), /* gate */
+ 0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents,
+ 0xf3c,
+ 3, 3, /* mux */
+ BIT(22), /* gate */
+ 0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents,
+ 0xf3c,
+ 6, 3, /* mux */
+ BIT(23), /* gate */
+ 0);
+
/*
* Contains all clocks that are controlled by a hardware register. They
* have a (sunxi) .common member, which needs to be initialised by the common
@@ -904,6 +1052,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&tcon_tv0_clk.common,
&tcon_tv1_clk.common,
&edp_clk.common,
+ &ledc_clk.common,
+ &csi_top_clk.common,
+ &csi_mclk0_clk.common,
+ &csi_mclk1_clk.common,
+ &csi_mclk2_clk.common,
+ &csi_mclk3_clk.common,
+ &isp_clk.common,
+ &dsp_clk.common,
+ &fanout_24M_clk.common,
+ &fanout_12M_clk.common,
+ &fanout_16M_clk.common,
+ &fanout_25M_clk.common,
+ &fanout_27M_clk.common,
+ &fanout_pclk_clk.common,
+ &fanout0_clk.common,
+ &fanout1_clk.common,
+ &fanout2_clk.common,
};
static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -997,6 +1162,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
[CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
[CLK_EDP] = &edp_clk.common.hw,
+ [CLK_LEDC] = &ledc_clk.common.hw,
+ [CLK_CSI_TOP] = &csi_top_clk.common.hw,
+ [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
+ [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
+ [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
+ [CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
+ [CLK_ISP] = &isp_clk.common.hw,
+ [CLK_DSP] = &dsp_clk.common.hw,
+ [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
+ [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
+ [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
+ [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
+ [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
+ [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
+ [CLK_FANOUT0] = &fanout0_clk.common.hw,
+ [CLK_FANOUT1] = &fanout1_clk.common.hw,
+ [CLK_FANOUT2] = &fanout2_clk.common.hw,
},
};
@@ -1048,6 +1230,14 @@ static int sun55i_a523_ccu_probe(struct platform_device *pdev)
val &= ~(BIT(1) | BIT(0));
writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
+ /* Force fanout factors N to 0. */
+ val = readl(reg + SUN55I_A523_FANOUT_27M_REG);
+ val &= ~GENMASK(12, 8);
+ writel(val, reg + SUN55I_A523_FANOUT_27M_REG);
+ val = readl(reg + SUN55I_A523_FANOUT_PCLK_REG);
+ val &= ~GENMASK(9, 5);
+ writel(val, reg + SUN55I_A523_FANOUT_PCLK_REG);
+
ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
if (ret)
return ret;
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (10 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 11/15] clk: sunxi-ng: a523: remaining " Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 20:12 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines Andre Przywara
` (2 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Add the various bus clock gates that control access to the devices'
register interface.
These clocks are each just one bit, typically the lower bits in some "BGR"
(Bus Gate / Reset) registers, for each device group: one for all UARTs,
one for all SPI interfaces, and so on.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 295 ++++++++++++++++++++++++-
1 file changed, 294 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 6a4340f1fd041..fbed9b2b3b2f9 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -350,6 +350,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
0, 5, /* M */
24, 2, /* mux */
0);
+static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
+
static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
0, 5, /* M */
24, 2, /* mux */
@@ -367,10 +369,11 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
0, 5, /* M */
24, 3, /* mux */
0);
+static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
/**************************************************************************
- * mod clocks *
+ * mod clocks with gates *
**************************************************************************/
static const struct clk_hw *de_parents[] = {
@@ -386,6 +389,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
+
static const struct clk_hw *di_parents[] = {
&pll_periph0_300M_clk.hw,
&pll_periph0_400M_clk.hw,
@@ -399,6 +404,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
+
static const struct clk_hw *g2d_parents[] = {
&pll_periph0_400M_clk.hw,
&pll_periph0_300M_clk.hw,
@@ -412,6 +419,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
+
static const struct clk_hw *gpu_parents[] = {
&pll_gpu_clk.common.hw,
&pll_periph0_800M_clk.common.hw,
@@ -427,6 +436,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
+
static const struct clk_parent_data ce_parents[] = {
{ .fw_name = "hosc" },
{ .hw = &pll_periph0_480M_clk.common.hw },
@@ -439,6 +450,10 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
+ BIT(1), 0);
+
static const struct clk_hw *ve_parents[] = {
&pll_ve_clk.common.hw,
&pll_periph0_480M_clk.common.hw,
@@ -451,6 +466,16 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
+ BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
+ BIT(0), 0);
+
static const struct clk_parent_data hstimer_parents[] = {
{ .fw_name = "hosc" },
{ .fw_name = "iosc" },
@@ -510,6 +535,15 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
+ BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
+ BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
+
static const struct clk_parent_data iommu_parents[] = {
{ .hw = &pll_periph0_600M_clk.hw },
{ .hw = &pll_ddr0_clk.common.hw },
@@ -525,6 +559,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
+ BIT(0), 0);
+
static const struct clk_hw *dram_parents[] = {
&pll_ddr0_clk.common.hw,
&pll_periph0_600M_clk.hw,
@@ -541,6 +578,22 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
&dram_clk.common.hw, 4, 1, 0);
+static SUNXI_CCU_GATE_HW(mbus_dma_clk, "mbus-dma", &mbus_clk.hw,
+ 0x804, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(mbus_ve_clk, "mbus-ve", &mbus_clk.hw,
+ 0x804, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(mbus_ce_clk, "mbus-ce", &mbus_clk.hw,
+ 0x804, BIT(2), 0);
+static SUNXI_CCU_GATE_HW(mbus_nand_clk, "mbus-nand", &mbus_clk.hw,
+ 0x804, BIT(5), 0);
+static SUNXI_CCU_GATE_HW(mbus_usb3_clk, "mbus-usb3", &mbus_clk.hw,
+ 0x804, BIT(6), 0);
+static SUNXI_CCU_GATE_HW(mbus_csi_clk, "mbus-csi", &mbus_clk.hw,
+ 0x804, BIT(8), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
+ BIT(0), CLK_IS_CRITICAL);
+
static const struct clk_parent_data nand_mmc_parents[] = {
{ .fw_name = "hosc" },
{ .hw = &pll_periph0_400M_clk.hw },
@@ -563,6 +616,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
+ BIT(0), 0);
+
static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
0x830,
0, 5, /* M */
@@ -598,6 +654,39 @@ static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
2, /* post div */
0, CCU_FEATURE_DUAL_DIV);
+static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
+ BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
+ BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
+ BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
+ BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
+ BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
+ BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
+ BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
+ BIT(6), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
+ BIT(7), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
+
static const struct clk_parent_data spi_parents[] = {
{ .fw_name = "hosc" },
{ .hw = &pll_periph0_300M_clk.hw },
@@ -630,6 +719,11 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
24, 3, /* mux */
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
+ BIT(3), 0);
static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
pll_periph0_150M_hws,
@@ -637,6 +731,10 @@ static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
pll_periph0_150M_hws,
0x974, BIT(31) | BIT(30), 6, 0);
+static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
+ BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
+ BIT(0), 0);
static const struct clk_parent_data ir_rx_parents[] = {
{ .fw_name = "losc" },
@@ -648,6 +746,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
24, 1, /* mux */
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
+ BIT(0), 0);
+
static const struct clk_parent_data ir_tx_ledc_parents[] = {
{ .fw_name = "hosc" },
{ .hw = &pll_periph1_600M_clk.hw },
@@ -658,6 +759,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
24, 1, /* mux */
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
+ BIT(0), 0);
static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
0, 5, /* M */
@@ -667,6 +770,12 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
0, 5, /* M */
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
+ BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
+ BIT(1), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
/*
* The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
@@ -720,6 +829,18 @@ static struct ccu_mux usb_ohci1_clk = {
},
};
+static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
+ BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
+ BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
+ BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
+ BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
+ BIT(0), 0);
static const struct clk_parent_data losc_hosc_parents[] = {
{ .fw_name = "hosc" },
@@ -733,6 +854,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws, 0xabc,
+ BIT(0), 0);
+
static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
/* TODO: add mux between 32kOSC and PERIPH0/18750 */
@@ -750,6 +874,8 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
+
static const struct clk_parent_data mipi_dsi_parents[] = {
{ .fw_name = "hosc" },
{ .hw = &pll_periph0_200M_clk.hw },
@@ -769,6 +895,12 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
+ BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
+ BIT(1), 0);
+
static const struct clk_hw *tcon_parents[] = {
&pll_video0_4x_clk.common.hw,
&pll_video1_4x_clk.common.hw,
@@ -806,6 +938,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
+ BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
+ BIT(1), 0);
+
static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
0xb80,
0, 4, /* M */
@@ -820,6 +957,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
BIT(31), /* gate */
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
+ BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
+ BIT(1), 0);
+
static const struct clk_hw *edp_parents[] = {
&pll_video0_4x_clk.common.hw,
&pll_video1_4x_clk.common.hw,
@@ -833,6 +975,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
+
static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
0xbf0,
0, 4, /* M */
@@ -840,6 +984,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
+
static const struct clk_hw *csi_top_parents[] = {
&pll_periph0_300M_clk.hw,
&pll_periph0_400M_clk.hw,
@@ -893,6 +1039,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
+
static const struct clk_hw *isp_parents[] = {
&pll_periph0_300M_clk.hw,
&pll_periph0_400M_clk.hw,
@@ -918,6 +1066,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
BIT(31), /* gate */
0);
+static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk, "bus-dsp-cfg", ahb_hws, 0xc7c,
+ BIT(1), 0);
+
static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
0xf30, BIT(0), 0);
static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
@@ -1011,55 +1162,128 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
&apb0_clk.common,
&apb1_clk.common,
&de_clk.common,
+ &bus_de_clk.common,
&di_clk.common,
+ &bus_di_clk.common,
&g2d_clk.common,
+ &bus_g2d_clk.common,
&gpu_clk.common,
+ &bus_gpu_clk.common,
&ce_clk.common,
+ &bus_ce_clk.common,
+ &bus_ce_sys_clk.common,
&ve_clk.common,
+ &bus_ve_clk.common,
+ &bus_dma_clk.common,
+ &bus_msgbox_clk.common,
+ &bus_spinlock_clk.common,
&hstimer0_clk.common,
&hstimer1_clk.common,
&hstimer2_clk.common,
&hstimer3_clk.common,
&hstimer4_clk.common,
&hstimer5_clk.common,
+ &bus_hstimer_clk.common,
+ &bus_dbg_clk.common,
+ &bus_pwm0_clk.common,
+ &bus_pwm1_clk.common,
&iommu_clk.common,
+ &bus_iommu_clk.common,
&dram_clk.common,
+ &mbus_dma_clk.common,
+ &mbus_ve_clk.common,
+ &mbus_ce_clk.common,
+ &mbus_nand_clk.common,
+ &mbus_usb3_clk.common,
+ &mbus_csi_clk.common,
+ &bus_dram_clk.common,
&nand0_clk.common,
&nand1_clk.common,
+ &bus_nand_clk.common,
&mmc0_clk.common,
&mmc1_clk.common,
&mmc2_clk.common,
+ &bus_sysdap_clk.common,
+ &bus_mmc0_clk.common,
+ &bus_mmc1_clk.common,
+ &bus_mmc2_clk.common,
+ &bus_uart0_clk.common,
+ &bus_uart1_clk.common,
+ &bus_uart2_clk.common,
+ &bus_uart3_clk.common,
+ &bus_uart4_clk.common,
+ &bus_uart5_clk.common,
+ &bus_uart6_clk.common,
+ &bus_uart7_clk.common,
+ &bus_i2c0_clk.common,
+ &bus_i2c1_clk.common,
+ &bus_i2c2_clk.common,
+ &bus_i2c3_clk.common,
+ &bus_i2c4_clk.common,
+ &bus_i2c5_clk.common,
+ &bus_can_clk.common,
&spi0_clk.common,
&spi1_clk.common,
&spi2_clk.common,
&spifc_clk.common,
+ &bus_spi0_clk.common,
+ &bus_spi1_clk.common,
+ &bus_spi2_clk.common,
+ &bus_spifc_clk.common,
&emac0_25M_clk.common,
&emac1_25M_clk.common,
+ &bus_emac0_clk.common,
+ &bus_emac1_clk.common,
&ir_rx_clk.common,
+ &bus_ir_rx_clk.common,
&ir_tx_clk.common,
+ &bus_ir_tx_clk.common,
&gpadc0_clk.common,
&gpadc1_clk.common,
+ &bus_gpadc0_clk.common,
+ &bus_gpadc1_clk.common,
+ &bus_ths_clk.common,
&usb_ohci0_clk.common,
&usb_ohci1_clk.common,
+ &bus_ohci0_clk.common,
+ &bus_ohci1_clk.common,
+ &bus_ehci0_clk.common,
+ &bus_ehci1_clk.common,
+ &bus_otg_clk.common,
+ &bus_lradc_clk.common,
&pcie_aux_clk.common,
+ &bus_dpss_top_clk.common,
&hdmi_24M_clk.common,
&hdmi_cec_32k_clk.common,
&hdmi_cec_clk.common,
+ &bus_hdmi_clk.common,
&mipi_dsi0_clk.common,
&mipi_dsi1_clk.common,
+ &bus_mipi_dsi0_clk.common,
+ &bus_mipi_dsi1_clk.common,
&tcon_lcd0_clk.common,
&tcon_lcd1_clk.common,
+ &combophy_dsi0_clk.common,
+ &combophy_dsi1_clk.common,
+ &bus_tcon_lcd0_clk.common,
+ &bus_tcon_lcd1_clk.common,
&tcon_tv0_clk.common,
&tcon_tv1_clk.common,
+ &bus_tcon_tv0_clk.common,
+ &bus_tcon_tv1_clk.common,
&edp_clk.common,
+ &bus_edp_clk.common,
&ledc_clk.common,
+ &bus_ledc_clk.common,
&csi_top_clk.common,
&csi_mclk0_clk.common,
&csi_mclk1_clk.common,
&csi_mclk2_clk.common,
&csi_mclk3_clk.common,
+ &bus_csi_clk.common,
&isp_clk.common,
&dsp_clk.common,
+ &bus_dsp_cfg_clk.common,
&fanout_24M_clk.common,
&fanout_12M_clk.common,
&fanout_16M_clk.common,
@@ -1119,57 +1343,126 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
[CLK_APB1] = &apb1_clk.common.hw,
[CLK_MBUS] = &mbus_clk.hw,
[CLK_DE] = &de_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
[CLK_DI] = &di_clk.common.hw,
+ [CLK_BUS_DI] = &bus_di_clk.common.hw,
[CLK_G2D] = &g2d_clk.common.hw,
+ [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
[CLK_GPU] = &gpu_clk.common.hw,
+ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
[CLK_CE] = &ce_clk.common.hw,
+ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
+ [CLK_BUS_CE_SYS] = &bus_ce_sys_clk.common.hw,
[CLK_VE] = &ve_clk.common.hw,
+ [CLK_BUS_VE] = &bus_ve_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_HSTIMER0] = &hstimer0_clk.common.hw,
[CLK_HSTIMER1] = &hstimer1_clk.common.hw,
[CLK_HSTIMER2] = &hstimer2_clk.common.hw,
[CLK_HSTIMER3] = &hstimer3_clk.common.hw,
[CLK_HSTIMER4] = &hstimer4_clk.common.hw,
[CLK_HSTIMER5] = &hstimer5_clk.common.hw,
+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
+ [CLK_BUS_PWM0] = &bus_pwm0_clk.common.hw,
+ [CLK_BUS_PWM1] = &bus_pwm1_clk.common.hw,
[CLK_IOMMU] = &iommu_clk.common.hw,
+ [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
[CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
+ [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
+ [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
+ [CLK_MBUS_CSI] = &mbus_csi_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_MMC2] = &mmc2_clk.common.hw,
+ [CLK_BUS_SYSDAP] = &bus_sysdap_clk.common.hw,
+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
+ [CLK_BUS_MMC2] = &bus_mmc2_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_UART4] = &bus_uart4_clk.common.hw,
+ [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
+ [CLK_BUS_UART6] = &bus_uart6_clk.common.hw,
+ [CLK_BUS_UART7] = &bus_uart7_clk.common.hw,
+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
+ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
+ [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
+ [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
+ [CLK_BUS_I2C5] = &bus_i2c5_clk.common.hw,
+ [CLK_BUS_CAN] = &bus_can_clk.common.hw,
[CLK_SPI0] = &spi0_clk.common.hw,
[CLK_SPI1] = &spi1_clk.common.hw,
[CLK_SPI2] = &spi2_clk.common.hw,
[CLK_SPIFC] = &spifc_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
+ [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
+ [CLK_BUS_SPIFC] = &bus_spifc_clk.common.hw,
[CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
[CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
+ [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
+ [CLK_BUS_EMAC1] = &bus_emac1_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_GPADC0] = &gpadc0_clk.common.hw,
[CLK_GPADC1] = &gpadc1_clk.common.hw,
+ [CLK_BUS_GPADC0] = &bus_gpadc0_clk.common.hw,
+ [CLK_BUS_GPADC1] = &bus_gpadc1_clk.common.hw,
+ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
[CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
[CLK_USB_OHCI1] = &usb_ohci1_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_EHCI1] = &bus_ehci1_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw,
[CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
+ [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
[CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
[CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
[CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
+ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
[CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
[CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
+ [CLK_BUS_MIPI_DSI0] = &bus_mipi_dsi0_clk.common.hw,
+ [CLK_BUS_MIPI_DSI1] = &bus_mipi_dsi1_clk.common.hw,
[CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
[CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
[CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
[CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
+ [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw,
+ [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw,
[CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
[CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
+ [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
+ [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
[CLK_EDP] = &edp_clk.common.hw,
+ [CLK_BUS_EDP] = &bus_edp_clk.common.hw,
[CLK_LEDC] = &ledc_clk.common.hw,
+ [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw,
[CLK_CSI_TOP] = &csi_top_clk.common.hw,
[CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
[CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
[CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
[CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
+ [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
[CLK_ISP] = &isp_clk.common.hw,
[CLK_DSP] = &dsp_clk.common.hw,
+ [CLK_BUS_DSP_CFG] = &bus_dsp_cfg_clk.common.hw,
[CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
[CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
[CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (11 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 20:29 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 14/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU Andre Przywara
2025-02-14 12:53 ` [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU Andre Przywara
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Allwinner SoCs do not contain a separate reset controller, instead the
reset lines for the various devices are integrated into the "BGR" (Bus
Gate / Reset) registers, for each device group: one for all UARTs, one
for all SPI interfaces, and so on.
The Allwinner CCU driver also doubles as a reset provider, and since the
reset lines are indeed just single bits in those BGR register, we can
represent them easily in an array of structs, just containing the
register offset and the bit number.
Add the location of the reset bits for all devices in the A523/T527
SoCs, using the existing sunxi CCU infrastructure.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 83 ++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index fbed9b2b3b2f9..d57565f07a112 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -1475,11 +1475,94 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
},
};
+static struct ccu_reset_map sun55i_a523_ccu_resets[] = {
+ [RST_MBUS] = { 0x540, BIT(30) },
+ [RST_BUS_NSI] = { 0x54c, BIT(16) },
+ [RST_BUS_DE] = { 0x60c, BIT(16) },
+ [RST_BUS_DI] = { 0x62c, BIT(16) },
+ [RST_BUS_G2D] = { 0x63c, BIT(16) },
+ [RST_BUS_SYS] = { 0x64c, BIT(16) },
+ [RST_BUS_GPU] = { 0x67c, BIT(16) },
+ [RST_BUS_CE] = { 0x68c, BIT(16) },
+ [RST_BUS_SYS_CE] = { 0x68c, BIT(17) },
+ [RST_BUS_VE] = { 0x69c, BIT(16) },
+ [RST_BUS_DMA] = { 0x70c, BIT(16) },
+ [RST_BUS_MSGBOX] = { 0x71c, BIT(16) },
+ [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
+ [RST_BUS_CPUXTIMER] = { 0x74c, BIT(16) },
+ [RST_BUS_DBG] = { 0x78c, BIT(16) },
+ [RST_BUS_PWM0] = { 0x7ac, BIT(16) },
+ [RST_BUS_PWM1] = { 0x7ac, BIT(17) },
+ [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_MMC2] = { 0x84c, BIT(18) },
+ [RST_BUS_SYSDAP] = { 0x88c, BIT(16) },
+ [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_UART4] = { 0x90c, BIT(20) },
+ [RST_BUS_UART5] = { 0x90c, BIT(21) },
+ [RST_BUS_UART6] = { 0x90c, BIT(22) },
+ [RST_BUS_UART7] = { 0x90c, BIT(23) },
+ [RST_BUS_I2C0] = { 0x91c, BIT(16) },
+ [RST_BUS_I2C1] = { 0x91c, BIT(17) },
+ [RST_BUS_I2C2] = { 0x91c, BIT(18) },
+ [RST_BUS_I2C3] = { 0x91c, BIT(19) },
+ [RST_BUS_I2C4] = { 0x91c, BIT(20) },
+ [RST_BUS_I2C5] = { 0x91c, BIT(21) },
+ [RST_BUS_CAN] = { 0x92c, BIT(16) },
+ [RST_BUS_SPI0] = { 0x96c, BIT(16) },
+ [RST_BUS_SPI1] = { 0x96c, BIT(17) },
+ [RST_BUS_SPI2] = { 0x96c, BIT(18) },
+ [RST_BUS_SPIFC] = { 0x96c, BIT(19) },
+ [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
+ [RST_BUS_EMAC1] = { 0x98c, BIT(16) | BIT(17) }, /* GMAC1-AXI */
+ [RST_BUS_IR_RX] = { 0x99c, BIT(16) },
+ [RST_BUS_IR_TX] = { 0x9cc, BIT(16) },
+ [RST_BUS_GPADC0] = { 0x9ec, BIT(16) },
+ [RST_BUS_GPADC1] = { 0x9ec, BIT(17) },
+ [RST_BUS_THS] = { 0x9fc, 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_EHCI1] = { 0xa8c, BIT(21) },
+ [RST_BUS_OTG] = { 0xa8c, BIT(24) },
+ [RST_BUS_3] = { 0xa8c, BIT(25) }, /* BSP + register */
+ [RST_BUS_LRADC] = { 0xa9c, BIT(16) },
+ [RST_BUS_PCIE_USB3] = { 0xaac, BIT(16) },
+ [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
+ [RST_BUS_HDMI_MAIN] = { 0xb1c, BIT(16) },
+ [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
+ [RST_BUS_MIPI_DSI0] = { 0xb4c, BIT(16) },
+ [RST_BUS_MIPI_DSI1] = { 0xb4c, BIT(17) },
+ [RST_BUS_TCON_LCD0] = { 0xb7c, BIT(16) },
+ [RST_BUS_TCON_LCD1] = { 0xb7c, BIT(17) },
+ [RST_BUS_TCON_LCD2] = { 0xb7c, BIT(18) },
+ [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
+ [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
+ [RST_BUS_LVDS0] = { 0xbac, BIT(16) },
+ [RST_BUS_LVDS1] = { 0xbac, BIT(17) },
+ [RST_BUS_EDP] = { 0xbbc, BIT(16) },
+ [RST_BUS_VIDEO_OUT0] = { 0xbcc, BIT(16) },
+ [RST_BUS_VIDEO_OUT1] = { 0xbcc, BIT(17) },
+ [RST_BUS_LEDC] = { 0xbfc, BIT(16) },
+ [RST_BUS_CSI] = { 0xc1c, BIT(16) },
+ [RST_BUS_ISP] = { 0xc2c, BIT(16) }, /* BSP + register */
+};
+
static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
.ccu_clks = sun55i_a523_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun55i_a523_ccu_clks),
.hw_clks = &sun55i_a523_hw_clks,
+
+ .resets = sun55i_a523_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun55i_a523_ccu_resets),
};
static const u32 pll_regs[] = {
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 14/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (12 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU Andre Przywara
14 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
the PRCM R_CCU.
Add the new compatible string, along with the required input clock
lists. There is now an extra input clock (PLL_AUDIO), so add this to the
list of allowed clocks and required it for the A523 PRCM CCU.
Also add the DT binding headers, listing all the clocks with their ID
numbers.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../clock/allwinner,sun4i-a10-ccu.yaml | 76 ++++++++++++-------
include/dt-bindings/clock/sun55i-a523-r-ccu.h | 37 +++++++++
include/dt-bindings/reset/sun55i-a523-r-ccu.h | 25 ++++++
3 files changed, 110 insertions(+), 28 deletions(-)
create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h
diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index 451a18de1b6c1..791dc333be74d 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -46,6 +46,7 @@ properties:
- allwinner,sun50i-h616-ccu
- allwinner,sun50i-h616-r-ccu
- allwinner,sun55i-a523-ccu
+ - allwinner,sun55i-a523-r-ccu
- allwinner,suniv-f1c100s-ccu
- nextthing,gr8-ccu
@@ -59,6 +60,7 @@ properties:
- description: Low Frequency Oscillator (usually at 32kHz)
- description: Internal Oscillator
- description: Peripherals PLL
+ - description: Audio PLL
clock-names:
minItems: 2
@@ -67,6 +69,7 @@ properties:
- const: losc
- const: iosc
- const: pll-periph
+ - const: pll-audio
required:
- "#clock-cells"
@@ -80,54 +83,71 @@ if:
properties:
compatible:
enum:
- - allwinner,sun8i-a83t-r-ccu
- - allwinner,sun8i-h3-r-ccu
- - allwinner,sun20i-d1-r-ccu
- - allwinner,sun50i-a64-r-ccu
- - allwinner,sun50i-a100-r-ccu
- - allwinner,sun50i-h6-r-ccu
- - allwinner,sun50i-h616-r-ccu
+ - allwinner,sun55i-a523-r-ccu
then:
properties:
clocks:
- minItems: 4
- maxItems: 4
+ minItems: 5
+ maxItems: 5
clock-names:
- minItems: 4
- maxItems: 4
+ minItems: 5
+ maxItems: 5
else:
if:
properties:
compatible:
enum:
- - allwinner,sun20i-d1-ccu
- - allwinner,sun50i-a100-ccu
- - allwinner,sun50i-h6-ccu
- - allwinner,sun50i-h616-ccu
- - allwinner,sun55i-a523-ccu
+ - allwinner,sun8i-a83t-r-ccu
+ - allwinner,sun8i-h3-r-ccu
+ - allwinner,sun20i-d1-r-ccu
+ - allwinner,sun50i-a64-r-ccu
+ - allwinner,sun50i-a100-r-ccu
+ - allwinner,sun50i-h6-r-ccu
+ - allwinner,sun50i-h616-r-ccu
then:
properties:
clocks:
- minItems: 3
- maxItems: 3
+ minItems: 4
+ maxItems: 4
clock-names:
- minItems: 3
- maxItems: 3
+ minItems: 4
+ maxItems: 4
else:
- properties:
- clocks:
- minItems: 2
- maxItems: 2
-
- clock-names:
- minItems: 2
- maxItems: 2
+ if:
+ properties:
+ compatible:
+ enum:
+ - allwinner,sun20i-d1-ccu
+ - allwinner,sun50i-a100-ccu
+ - allwinner,sun50i-h6-ccu
+ - allwinner,sun50i-h616-ccu
+ - allwinner,sun55i-a523-ccu
+
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ maxItems: 3
+
+ clock-names:
+ minItems: 3
+ maxItems: 3
+
+ else:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 2
+
+ clock-names:
+ minItems: 2
+ maxItems: 2
additionalProperties: false
diff --git a/include/dt-bindings/clock/sun55i-a523-r-ccu.h b/include/dt-bindings/clock/sun55i-a523-r-ccu.h
new file mode 100644
index 0000000000000..365647499b9ab
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-r-ccu.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_
+
+#define CLK_R_AHB 0
+#define CLK_R_APB0 1
+#define CLK_R_APB1 2
+#define CLK_R_TIMER0 3
+#define CLK_R_TIMER1 4
+#define CLK_R_TIMER2 5
+#define CLK_BUS_R_TIMER 6
+#define CLK_BUS_R_TWD 7
+#define CLK_R_PWMCTRL 8
+#define CLK_BUS_R_PWMCTRL 9
+#define CLK_R_SPI 10
+#define CLK_BUS_R_SPI 11
+#define CLK_BUS_R_SPINLOCK 12
+#define CLK_BUS_R_MSGBOX 13
+#define CLK_BUS_R_UART0 14
+#define CLK_BUS_R_UART1 15
+#define CLK_BUS_R_I2C0 16
+#define CLK_BUS_R_I2C1 17
+#define CLK_BUS_R_I2C2 18
+#define CLK_BUS_R_PPU0 19
+#define CLK_BUS_R_PPU1 20
+#define CLK_BUS_R_CPU_BIST 21
+#define CLK_R_IR_RX 22
+#define CLK_BUS_R_IR_RX 23
+#define CLK_BUS_R_DMA 24
+#define CLK_BUS_R_RTC 25
+#define CLK_BUS_R_CPUCFG 26
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun55i-a523-r-ccu.h b/include/dt-bindings/reset/sun55i-a523-r-ccu.h
new file mode 100644
index 0000000000000..dd6fbb372e190
--- /dev/null
+++ b/include/dt-bindings/reset/sun55i-a523-r-ccu.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_
+
+#define RST_BUS_R_TIMER 0
+#define RST_BUS_R_TWD 1
+#define RST_BUS_R_PWMCTRL 2
+#define RST_BUS_R_SPI 3
+#define RST_BUS_R_SPINLOCK 4
+#define RST_BUS_R_MSGBOX 5
+#define RST_BUS_R_UART0 6
+#define RST_BUS_R_UART1 7
+#define RST_BUS_R_I2C0 8
+#define RST_BUS_R_I2C1 9
+#define RST_BUS_R_I2C2 10
+#define RST_BUS_R_PPU1 11
+#define RST_BUS_R_IR_RX 12
+#define RST_BUS_R_RTC 13
+#define RST_BUS_R_CPUCFG 14
+
+#endif /* _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_ */
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
` (13 preceding siblings ...)
2025-02-14 12:53 ` [PATCH v2 14/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU Andre Przywara
@ 2025-02-14 12:53 ` Andre Przywara
2025-02-18 20:42 ` Jernej Škrabec
14 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-14 12:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
The A523/T527 SoCs have clock/reset controls in the PRCM part, like many
previous SoCs. For a change, the whole PRCM is documented in the A523
manual, including the system bus tree, so we can describe all those
clocks correctly based on that. There layout seems to be derived from
the H6 and H616 PRCM CCUs, though there are more clocks, and many clocks
have subtly changed.
Describe all the mod and gate clocks, including the three bus clocks
(R_AHB, R_APB0, and R_APB1).
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 2 +
drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c | 245 +++++++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h | 14 ++
4 files changed, 266 insertions(+)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 04efbda847cf9..5830a9d87bf25 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -57,6 +57,11 @@ config SUN55I_A523_CCU
default y
depends on ARM64 || COMPILE_TEST
+config SUN55I_A523_R_CCU
+ tristate "Support for the Allwinner A523/T527 PRCM CCU"
+ default y
+ depends on ARM64 || COMPILE_TEST
+
config SUN4I_A10_CCU
tristate "Support for the Allwinner A10/A20 CCU"
default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 01a887f7824bb..82e471036de69 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
obj-$(CONFIG_SUN55I_A523_CCU) += sun55i-a523-ccu.o
+obj-$(CONFIG_SUN55I_A523_R_CCU) += sun55i-a523-r-ccu.o
obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
@@ -60,6 +61,7 @@ sun50i-h6-ccu-y += ccu-sun50i-h6.o
sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
sun50i-h616-ccu-y += ccu-sun50i-h616.o
sun55i-a523-ccu-y += ccu-sun55i-a523.o
+sun55i-a523-r-ccu-y += ccu-sun55i-a523-r.o
sun4i-a10-ccu-y += ccu-sun4i-a10.o
sun5i-ccu-y += ccu-sun5i.o
sun6i-a31-ccu-y += ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
new file mode 100644
index 0000000000000..0dafc38370f22
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ * Based on the D1 CCU driver:
+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+
+#include "ccu-sun55i-a523-r.h"
+
+static const struct clk_parent_data r_ahb_apb_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .fw_name = "pll-periph" },
+ { .fw_name = "pll-audio" },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(r_ahb_clk, "r-ahb",
+ r_ahb_apb_parents, 0x000,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX(r_apb0_clk, "r-apb0",
+ r_ahb_apb_parents, 0x00c,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX(r_apb1_clk, "r-apb1",
+ r_ahb_apb_parents, 0x010,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ 0);
+
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
+ r_ahb_apb_parents, 0x100,
+ 1, 3, /* P */
+ 4, 3, /* mux */
+ BIT(0),
+ 0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
+ r_ahb_apb_parents, 0x104,
+ 1, 3, /* P */
+ 4, 3, /* mux */
+ BIT(0),
+ 0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
+ r_ahb_apb_parents, 0x108,
+ 1, 3, /* P */
+ 4, 3, /* mux */
+ BIT(0),
+ 0);
+
+static SUNXI_CCU_GATE_HW(bus_r_timer_clk, "bus-r-timer", &r_ahb_clk.common.hw,
+ 0x11c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_twd_clk, "bus-r-twd", &r_apb0_clk.common.hw,
+ 0x12c, BIT(0), 0);
+
+static const struct clk_parent_data r_pwmctrl_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(r_pwmctrl_clk, "r-pwmctrl",
+ r_pwmctrl_parents, 0x130,
+ 24, 1, /* mux */
+ BIT(31),
+ 0);
+static SUNXI_CCU_GATE_HW(bus_r_pwmctrl_clk, "bus-r-pwmctrl",
+ &r_apb0_clk.common.hw, 0x13c, BIT(0), 0);
+
+/* SPI clock is /M/N (same as new MMC?) */
+static SUNXI_CCU_GATE_HW(bus_r_spi_clk, "bus-r-spi",
+ &r_ahb_clk.common.hw, 0x15c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_spinlock_clk, "bus-r-spinlock",
+ &r_ahb_clk.common.hw, 0x16c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_msgbox_clk, "bus-r-msgbox",
+ &r_ahb_clk.common.hw, 0x17c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_uart0_clk, "bus-r-uart0",
+ &r_apb1_clk.common.hw, 0x18c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_uart1_clk, "bus-r-uart1",
+ &r_apb1_clk.common.hw, 0x18c, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c0_clk, "bus-r-i2c0",
+ &r_apb1_clk.common.hw, 0x19c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c1_clk, "bus-r-i2c1",
+ &r_apb1_clk.common.hw, 0x19c, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c2_clk, "bus-r-i2c2",
+ &r_apb1_clk.common.hw, 0x19c, BIT(2), 0);
+static SUNXI_CCU_GATE_HW(bus_r_ppu0_clk, "bus-r-ppu0",
+ &r_apb0_clk.common.hw, 0x1ac, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_ppu1_clk, "bus-r-ppu1",
+ &r_apb0_clk.common.hw, 0x1ac, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_cpu_bist_clk, "bus-r-cpu-bist",
+ &r_apb0_clk.common.hw, 0x1bc, BIT(0), 0);
+
+static const struct clk_parent_data r_ir_rx_parents[] = {
+ { .fw_name = "losc" },
+ { .fw_name = "hosc" },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx",
+ r_ir_rx_parents, 0x1c0,
+ 0, 5, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+static SUNXI_CCU_GATE_HW(bus_r_ir_rx_clk, "bus-r-ir-rx",
+ &r_apb0_clk.common.hw, 0x1cc, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HW(bus_r_dma_clk, "bus-r-dma",
+ &r_apb0_clk.common.hw, 0x1dc, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_rtc_clk, "bus-r-rtc",
+ &r_apb0_clk.common.hw, 0x20c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_cpucfg_clk, "bus-r-cpucfg",
+ &r_apb0_clk.common.hw, 0x22c, BIT(0), 0);
+
+static struct ccu_common *sun55i_a523_r_ccu_clks[] = {
+ &r_ahb_clk.common,
+ &r_apb0_clk.common,
+ &r_apb1_clk.common,
+ &r_cpu_timer0.common,
+ &r_cpu_timer1.common,
+ &r_cpu_timer2.common,
+ &bus_r_timer_clk.common,
+ &bus_r_twd_clk.common,
+ &r_pwmctrl_clk.common,
+ &bus_r_pwmctrl_clk.common,
+ &bus_r_spi_clk.common,
+ &bus_r_spinlock_clk.common,
+ &bus_r_msgbox_clk.common,
+ &bus_r_uart0_clk.common,
+ &bus_r_uart1_clk.common,
+ &bus_r_i2c0_clk.common,
+ &bus_r_i2c1_clk.common,
+ &bus_r_i2c2_clk.common,
+ &bus_r_ppu0_clk.common,
+ &bus_r_ppu1_clk.common,
+ &bus_r_cpu_bist_clk.common,
+ &r_ir_rx_clk.common,
+ &bus_r_ir_rx_clk.common,
+ &bus_r_dma_clk.common,
+ &bus_r_rtc_clk.common,
+ &bus_r_cpucfg_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_r_hw_clks = {
+ .num = CLK_NUMBER,
+ .hws = {
+ [CLK_R_AHB] = &r_ahb_clk.common.hw,
+ [CLK_R_APB0] = &r_apb0_clk.common.hw,
+ [CLK_R_APB1] = &r_apb1_clk.common.hw,
+ [CLK_R_TIMER0] = &r_cpu_timer0.common.hw,
+ [CLK_R_TIMER1] = &r_cpu_timer1.common.hw,
+ [CLK_R_TIMER2] = &r_cpu_timer2.common.hw,
+ [CLK_BUS_R_TIMER] = &bus_r_timer_clk.common.hw,
+ [CLK_BUS_R_TWD] = &bus_r_twd_clk.common.hw,
+ [CLK_R_PWMCTRL] = &r_pwmctrl_clk.common.hw,
+ [CLK_BUS_R_PWMCTRL] = &bus_r_pwmctrl_clk.common.hw,
+ [CLK_BUS_R_SPI] = &bus_r_spi_clk.common.hw,
+ [CLK_BUS_R_SPINLOCK] = &bus_r_spinlock_clk.common.hw,
+ [CLK_BUS_R_MSGBOX] = &bus_r_msgbox_clk.common.hw,
+ [CLK_BUS_R_UART0] = &bus_r_uart0_clk.common.hw,
+ [CLK_BUS_R_UART1] = &bus_r_uart1_clk.common.hw,
+ [CLK_BUS_R_I2C0] = &bus_r_i2c0_clk.common.hw,
+ [CLK_BUS_R_I2C1] = &bus_r_i2c1_clk.common.hw,
+ [CLK_BUS_R_I2C2] = &bus_r_i2c2_clk.common.hw,
+ [CLK_BUS_R_PPU0] = &bus_r_ppu0_clk.common.hw,
+ [CLK_BUS_R_PPU1] = &bus_r_ppu1_clk.common.hw,
+ [CLK_BUS_R_CPU_BIST] = &bus_r_cpu_bist_clk.common.hw,
+ [CLK_R_IR_RX] = &r_ir_rx_clk.common.hw,
+ [CLK_BUS_R_IR_RX] = &bus_r_ir_rx_clk.common.hw,
+ [CLK_BUS_R_DMA] = &bus_r_dma_clk.common.hw,
+ [CLK_BUS_R_RTC] = &bus_r_rtc_clk.common.hw,
+ [CLK_BUS_R_CPUCFG] = &bus_r_cpucfg_clk.common.hw,
+ },
+};
+
+static struct ccu_reset_map sun55i_a523_r_ccu_resets[] = {
+ [RST_BUS_R_TIMER] = { 0x11c, BIT(16) },
+ [RST_BUS_R_TWD] = { 0x12c, BIT(16) },
+ [RST_BUS_R_PWMCTRL] = { 0x13c, BIT(16) },
+ [RST_BUS_R_SPI] = { 0x15c, BIT(16) },
+ [RST_BUS_R_SPINLOCK] = { 0x16c, BIT(16) },
+ [RST_BUS_R_MSGBOX] = { 0x17c, BIT(16) },
+ [RST_BUS_R_UART0] = { 0x18c, BIT(16) },
+ [RST_BUS_R_UART1] = { 0x18c, BIT(17) },
+ [RST_BUS_R_I2C0] = { 0x19c, BIT(16) },
+ [RST_BUS_R_I2C1] = { 0x19c, BIT(17) },
+ [RST_BUS_R_I2C2] = { 0x19c, BIT(18) },
+ [RST_BUS_R_PPU1] = { 0x1ac, BIT(17) },
+ [RST_BUS_R_IR_RX] = { 0x1cc, BIT(16) },
+ [RST_BUS_R_RTC] = { 0x20c, BIT(16) },
+ [RST_BUS_R_CPUCFG] = { 0x22c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_r_ccu_desc = {
+ .ccu_clks = sun55i_a523_r_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun55i_a523_r_ccu_clks),
+
+ .hw_clks = &sun55i_a523_r_hw_clks,
+
+ .resets = sun55i_a523_r_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun55i_a523_r_ccu_resets),
+};
+
+static int sun55i_a523_r_ccu_probe(struct platform_device *pdev)
+{
+ void __iomem *reg;
+
+ reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_r_ccu_desc);
+}
+
+static const struct of_device_id sun55i_a523_r_ccu_ids[] = {
+ { .compatible = "allwinner,sun55i-a523-r-ccu" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sun55i_a523_r_ccu_ids);
+
+static struct platform_driver sun55i_a523_r_ccu_driver = {
+ .probe = sun55i_a523_r_ccu_probe,
+ .driver = {
+ .name = "sun55i-a523-r-ccu",
+ .suppress_bind_attrs = true,
+ .of_match_table = sun55i_a523_r_ccu_ids,
+ },
+};
+module_platform_driver(sun55i_a523_r_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_DESCRIPTION("Support for the Allwinner A523 PRCM CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
new file mode 100644
index 0000000000000..d50f46ac4f3fe
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_R_H
+#define _CCU_SUN55I_A523_R_H
+
+#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
+
+#define CLK_NUMBER (CLK_BUS_R_CPUCFG + 1)
+
+#endif /* _CCU_SUN55I_A523_R_H */
--
2.46.3
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper
2025-02-14 12:53 ` [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper Andre Przywara
@ 2025-02-16 8:39 ` Chen-Yu Tsai
0 siblings, 0 replies; 38+ messages in thread
From: Chen-Yu Tsai @ 2025-02-16 8:39 UTC (permalink / raw)
To: Andre Przywara
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Fri, Feb 14, 2025 at 8:56 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> The PRCM CCU in the A523 SoC contains some clocks that only feature a
> P (shift) factor, but no M divider.
> Treat this as a special case of an MP clock: by forcing the M mask to be
> 0 bits wide, this always result in the M divider value to be 1.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 02/15] clk: sunxi-ng: mp: introduce dual-divider clock
2025-02-14 12:53 ` [PATCH v2 02/15] clk: sunxi-ng: mp: introduce dual-divider clock Andre Przywara
@ 2025-02-16 8:39 ` Chen-Yu Tsai
0 siblings, 0 replies; 38+ messages in thread
From: Chen-Yu Tsai @ 2025-02-16 8:39 UTC (permalink / raw)
To: Andre Przywara
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Fri, Feb 14, 2025 at 8:56 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> The Allwinner A523 SoC introduces some new MP-style mod clock, where the
> second "P" divider is an actual numerical divider value, and not the
> numbers of bits to shift (1..32 instead of 1,2,4,8).
> The rest of the clock is the same as the existing MP clock, so enhance the
> existing code to accommodate for this.
>
> Introduce the new CCU feature bit CCU_FEATURE_DUAL_DIV to mark an MP
> clock as having two dividers, and change the dividing and encoding code
> to differentiate the two cases.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 03/15] clk: sunxi-ng: mp: provide wrapper for setting feature flags
2025-02-14 12:53 ` [PATCH v2 03/15] clk: sunxi-ng: mp: provide wrapper for setting feature flags Andre Przywara
@ 2025-02-16 8:41 ` Chen-Yu Tsai
0 siblings, 0 replies; 38+ messages in thread
From: Chen-Yu Tsai @ 2025-02-16 8:41 UTC (permalink / raw)
To: Andre Przywara
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Fri, Feb 14, 2025 at 8:56 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> So far our sunxi clock instantiation macros set the required flags
> depending on the clock type, but the new "dual divider MP clock"
> requires us to pass that piece of information in by the user.
>
> Add a new wrapper macro that allows to specify a "features" field, to
> allow marking those dual-divider clocks accordingly.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu_mp.h | 19 ++++++++++++++++---
> 1 file changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
> index e235fdfde2d36..687bd2ec798e2 100644
> --- a/drivers/clk/sunxi-ng/ccu_mp.h
> +++ b/drivers/clk/sunxi-ng/ccu_mp.h
> @@ -100,11 +100,12 @@ struct ccu_mp {
> _muxshift, _muxwidth, \
> 0, _flags)
>
> -#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
> +#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
> _mshift, _mwidth, \
> _pshift, _pwidth, \
> _muxshift, _muxwidth, \
> - _gate, _flags) \
> + _gate, _flags, \
> + _features) \
> struct ccu_mp _struct = { \
> .enable = _gate, \
> .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
> @@ -112,13 +113,25 @@ struct ccu_mp {
> .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
> .common = { \
> .reg = _reg, \
> + .features = _features, \
> .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
> _parents, \
> - &ccu_mp_ops, \
> + &ccu_mp_ops,\
Accidental change?
Otherwise,
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> _flags), \
> } \
> }
>
> +#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
> + _mshift, _mwidth, \
> + _pshift, _pwidth, \
> + _muxshift, _muxwidth, \
> + _gate, _flags) \
> + SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, \
> + _reg, _mshift, _mwidth, \
> + _pshift, _pwidth, \
> + _muxshift, _muxwidth, \
> + _gate, _flags, 0)
> +
> #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
> _mshift, _mwidth, \
> _pshift, _pwidth, \
> --
> 2.46.3
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
2025-02-14 12:53 ` [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs Andre Przywara
@ 2025-02-18 19:03 ` Jernej Škrabec
2025-02-28 13:29 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:03 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:49 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the PLL clocks of the main CCU of the Allwinner A523 and T527 SoCs.
> The clocks were modelled after the A523 and T527 manual, and double
> checked by writing all 1's into the respective register, to spot all
> implemented bits.
>
> The PLL and mod clocks for the two CPU clusters and the DSU are part of
> a separate CCU, also most audio clocks are collected in a DSP CCU, so
> both of these clock groups are missing from this driver.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/Kconfig | 5 +
> drivers/clk/sunxi-ng/Makefile | 2 +
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 481 +++++++++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun55i-a523.h | 14 +
> drivers/clk/sunxi-ng/ccu_mp.h | 14 +-
> 5 files changed, 510 insertions(+), 6 deletions(-)
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index b547198a2c654..04efbda847cf9 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -52,6 +52,11 @@ config SUN50I_H6_R_CCU
> default y
> depends on ARM64 || COMPILE_TEST
>
> +config SUN55I_A523_CCU
> + tristate "Support for the Allwinner A523/T527 CCU"
> + default y
> + depends on ARM64 || COMPILE_TEST
> +
> config SUN4I_A10_CCU
> tristate "Support for the Allwinner A10/A20 CCU"
> default y
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 6b3ae2b620db6..01a887f7824bb 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -33,6 +33,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
> obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
> obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
> obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
> +obj-$(CONFIG_SUN55I_A523_CCU) += sun55i-a523-ccu.o
> obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
> obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
> obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
> @@ -58,6 +59,7 @@ sun50i-a100-r-ccu-y += ccu-sun50i-a100-r.o
> sun50i-h6-ccu-y += ccu-sun50i-h6.o
> sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
> sun50i-h616-ccu-y += ccu-sun50i-h616.o
> +sun55i-a523-ccu-y += ccu-sun55i-a523.o
> sun4i-a10-ccu-y += ccu-sun4i-a10.o
> sun5i-ccu-y += ccu-sun5i.o
> sun6i-a31-ccu-y += ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> new file mode 100644
> index 0000000000000..8374e841e9d82
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -0,0 +1,481 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2023-2024 Arm Ltd.
> + * Based on the D1 CCU driver:
> + * Copyright (c) 2020 huangzhenwei@allwinnertech.com
> + * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include "../clk.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-sun55i-a523.h"
> +
> +/*
> + * The 24 MHz oscillator, the root of most of the clock tree.
> + * .fw_name is the string used in the DT "clock-names" property, used to
> + * identify the corresponding clock in the "clocks" property.
> + */
> +static const struct clk_parent_data osc24M[] = {
> + { .fw_name = "hosc" }
> +};
> +
> +/**************************************************************************
> + * PLLs *
> + **************************************************************************/
> +
> +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
> +#define SUN55I_A523_PLL_DDR0_REG 0x010
> +static struct ccu_nkmp pll_ddr0_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
Newer manuals, for example A523 manual v1.4, don't mention input dividers anymore.
Newer BSP driver doesn't have them either. Should we drop them (for all PLLs)?
> + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
> + .common = {
> + .reg = 0x010,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M,
> + &ccu_nkmp_ops,
> + CLK_SET_RATE_GATE |
> + CLK_IS_CRITICAL),
> + },
> +};
> +
> +/*
> + * There is no actual clock output with that frequency (2.4 GHz), instead it
> + * has multiple outputs with adjustable dividers from that base frequency.
> + * Model them separately as divider clocks based on that parent here.
> + */
> +#define SUN55I_A523_PLL_PERIPH0_REG 0x020
> +static struct ccu_nm pll_periph0_4x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x020,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +/*
> + * Most clock-defining macros expect an *array* of parent clocks, even if
> + * they do not contain a muxer to select between different parents.
> + * The macros ending in just _HW take a simple clock pointer, but then create
> + * a single-entry array out of that. The macros using _HWS take such an
> + * array (even when it is a single entry one), this avoids having those
> + * helper arrays created inside *every* clock definition.
> + * This means for every clock that is referenced more than once it is
> + * useful to create such a dummy array and use _HWS.
> + */
> +static const struct clk_hw *pll_periph0_4x_hws[] = {
> + &pll_periph0_4x_clk.common.hw
> +};
> +
> +static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
> + pll_periph0_4x_hws, 0x020, 16, 3, 0);
> +static const struct clk_hw *pll_periph0_2x_hws[] = {
> + &pll_periph0_2x_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M",
> + pll_periph0_4x_hws, 0x020, 20, 3, 0);
> +static SUNXI_CCU_M_HWS(pll_periph0_480M_clk, "pll-periph0-480M",
> + pll_periph0_4x_hws, 0x020, 2, 3, 0);
> +static const struct clk_hw *pll_periph0_480M_hws[] = {
> + &pll_periph0_480M_clk.common.hw
> +};
> +static CLK_FIXED_FACTOR_HWS(pll_periph0_600M_clk, "pll-periph0-600M",
> + pll_periph0_2x_hws, 2, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph0_400M_clk, "pll-periph0-400M",
> + pll_periph0_2x_hws, 3, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph0_300M_clk, "pll-periph0-300M",
> + pll_periph0_2x_hws, 4, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph0_200M_clk, "pll-periph0-200M",
> + pll_periph0_2x_hws, 6, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
> + pll_periph0_2x_hws, 8, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
> + pll_periph0_480M_hws, 3, 1, 0);
> +
> +#define SUN55I_A523_PLL_PERIPH1_REG 0x028
> +static struct ccu_nm pll_periph1_4x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x028,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph1-4x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_periph1_4x_hws[] = {
> + &pll_periph1_4x_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
> + pll_periph1_4x_hws, 0x028, 16, 3, 0);
> +static SUNXI_CCU_M_HWS(pll_periph1_800M_clk, "pll-periph1-800M",
> + pll_periph1_4x_hws, 0x028, 20, 3, 0);
> +static SUNXI_CCU_M_HWS(pll_periph1_480M_clk, "pll-periph1-480M",
> + pll_periph1_4x_hws, 0x028, 2, 3, 0);
> +
> +static const struct clk_hw *pll_periph1_2x_hws[] = {
> + &pll_periph1_2x_clk.common.hw
> +};
> +static CLK_FIXED_FACTOR_HWS(pll_periph1_600M_clk, "pll-periph1-600M",
> + pll_periph1_2x_hws, 2, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph1_400M_clk, "pll-periph1-400M",
> + pll_periph1_2x_hws, 3, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph1_300M_clk, "pll-periph1-300M",
> + pll_periph1_2x_hws, 4, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph1_200M_clk, "pll-periph1-200M",
> + pll_periph1_2x_hws, 6, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_periph1_150M_clk, "pll-periph1-150M",
> + pll_periph1_2x_hws, 8, 1, 0);
> +static const struct clk_hw *pll_periph1_480M_hws[] = {
> + &pll_periph1_480M_clk.common.hw
> +};
> +static CLK_FIXED_FACTOR_HWS(pll_periph1_160M_clk, "pll-periph1-160M",
> + pll_periph1_480M_hws, 3, 1, 0);
> +
> +#define SUN55I_A523_PLL_GPU_REG 0x030
> +static struct ccu_nkmp pll_gpu_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
> + .common = {
> + .reg = 0x030,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-gpu", osc24M,
> + &ccu_nkmp_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +#define SUN55I_A523_PLL_VIDEO0_REG 0x040
> +static struct ccu_nm pll_video0_8x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x040,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video0-8x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video0_8x_hws[] = {
> + &pll_video0_8x_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS(pll_video0_4x_clk, "pll-video0-4x",
> + pll_video0_8x_hws, 0x040, 0, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_video0_3x_clk, "pll-video0-3x",
> + pll_video0_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
> +
> +#define SUN55I_A523_PLL_VIDEO1_REG 0x048
> +static struct ccu_nm pll_video1_8x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x048,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video1-8x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video1_8x_hws[] = {
> + &pll_video1_8x_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS(pll_video1_4x_clk, "pll-video1-4x",
> + pll_video1_8x_hws, 0x048, 0, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_video1_3x_clk, "pll-video1-3x",
> + pll_video1_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
> +
> +#define SUN55I_A523_PLL_VIDEO2_REG 0x050
> +static struct ccu_nm pll_video2_8x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x050,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video2-8x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video2_8x_hws[] = {
> + &pll_video2_8x_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS(pll_video2_4x_clk, "pll-video2-4x",
> + pll_video2_8x_hws, 0x050, 0, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_video2_3x_clk, "pll-video2-3x",
> + pll_video2_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
> +
> +#define SUN55I_A523_PLL_VE_REG 0x058
> +static struct ccu_nkmp pll_ve_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
> + .common = {
> + .reg = 0x058,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M,
> + &ccu_nkmp_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +#define SUN55I_A523_PLL_VIDEO3_REG 0x068
> +static struct ccu_nm pll_video3_8x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x068,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video3-8x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video3_8x_hws[] = {
> + &pll_video3_8x_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS(pll_video3_4x_clk, "pll-video3-4x",
> + pll_video3_8x_hws, 0x068, 0, 1, 0);
> +static CLK_FIXED_FACTOR_HWS(pll_video3_3x_clk, "pll-video3-3x",
> + pll_video3_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
> +
> +/*
> + * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors.
> + * Since we only need some fixed frequency from this PLL (22.5792MHz x 4 and
> + * 24.576MHz x 4), ignore those dividers and force both of them to 1 (encoded
> + * as 0), in the probe function below.
> + * The M factor must be an even number to produce a 50% duty cycle output.
> + */
> +#define SUN55I_A523_PLL_AUDIO0_REG 0x078
> +static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
> + { .rate = 90316800, .pattern = 0xc000872b, .m = 20, .n = 75 },
> + { .rate = 98304000, .pattern = 0xc0004dd3, .m = 12, .n = 49 },
> +
> +};
> +
> +static struct ccu_nm pll_audio0_4x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(16, 6),
> + .sdm = _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24),
> + 0x178, BIT(31)),
> + .min_rate = 180000000U,
> + .max_rate = 3000000000U,
> + .common = {
> + .reg = 0x078,
> + .features = CCU_FEATURE_SIGMA_DELTA_MOD,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_audio0_2x_clk, "pll-audio0-2x",
> + &pll_audio0_4x_clk.common.hw, 2, 1, 0);
> +static CLK_FIXED_FACTOR_HW(pll_audio0_clk, "pll-audio0",
> + &pll_audio0_4x_clk.common.hw, 4, 1, 0);
> +
> +#define SUN55I_A523_PLL_NPU_REG 0x080
> +static struct ccu_nm pll_npu_4x_clk = {
> + .enable = BIT(27),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x0080,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x",
> + osc24M, &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
> + &pll_npu_4x_clk.common.hw, 2, 1, CLK_SET_RATE_PARENT);
> +
> +static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
> + &pll_npu_4x_clk.common.hw, 4, 1, 0);
> +
> +/*
> + * Contains all clocks that are controlled by a hardware register. They
> + * have a (sunxi) .common member, which needs to be initialised by the common
> + * sunxi CCU code, to be filled with the MMIO base address and the shared lock.
> + */
> +static struct ccu_common *sun55i_a523_ccu_clks[] = {
> + &pll_ddr0_clk.common,
> + &pll_periph0_4x_clk.common,
> + &pll_periph0_2x_clk.common,
> + &pll_periph0_800M_clk.common,
> + &pll_periph0_480M_clk.common,
> + &pll_periph1_4x_clk.common,
> + &pll_periph1_2x_clk.common,
> + &pll_periph1_800M_clk.common,
> + &pll_periph1_480M_clk.common,
> + &pll_gpu_clk.common,
> + &pll_video0_8x_clk.common,
> + &pll_video0_4x_clk.common,
> + &pll_video1_8x_clk.common,
> + &pll_video1_4x_clk.common,
> + &pll_video2_8x_clk.common,
> + &pll_video2_4x_clk.common,
> + &pll_video3_8x_clk.common,
> + &pll_video3_4x_clk.common,
> + &pll_ve_clk.common,
> + &pll_audio0_4x_clk.common,
> + &pll_npu_4x_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> + .num = CLK_NUMBER,
> + .hws = {
> + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
> + [CLK_PLL_PERIPH0_4X] = &pll_periph0_4x_clk.common.hw,
> + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.common.hw,
> + [CLK_PLL_PERIPH0_800M] = &pll_periph0_800M_clk.common.hw,
> + [CLK_PLL_PERIPH0_480M] = &pll_periph0_480M_clk.common.hw,
> + [CLK_PLL_PERIPH0_600M] = &pll_periph0_600M_clk.hw,
> + [CLK_PLL_PERIPH0_400M] = &pll_periph0_400M_clk.hw,
> + [CLK_PLL_PERIPH0_300M] = &pll_periph0_300M_clk.hw,
> + [CLK_PLL_PERIPH0_200M] = &pll_periph0_200M_clk.hw,
> + [CLK_PLL_PERIPH0_160M] = &pll_periph0_160M_clk.hw,
> + [CLK_PLL_PERIPH0_150M] = &pll_periph0_150M_clk.hw,
> + [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_clk.common.hw,
> + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.common.hw,
> + [CLK_PLL_PERIPH1_800M] = &pll_periph1_800M_clk.common.hw,
> + [CLK_PLL_PERIPH1_480M] = &pll_periph1_480M_clk.common.hw,
> + [CLK_PLL_PERIPH1_600M] = &pll_periph1_600M_clk.hw,
> + [CLK_PLL_PERIPH1_400M] = &pll_periph1_400M_clk.hw,
> + [CLK_PLL_PERIPH1_300M] = &pll_periph1_300M_clk.hw,
> + [CLK_PLL_PERIPH1_200M] = &pll_periph1_200M_clk.hw,
> + [CLK_PLL_PERIPH1_160M] = &pll_periph1_160M_clk.hw,
> + [CLK_PLL_PERIPH1_150M] = &pll_periph1_150M_clk.hw,
> + [CLK_PLL_VIDEO0_8X] = &pll_video0_8x_clk.common.hw,
> + [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.common.hw,
> + [CLK_PLL_VIDEO0_3X] = &pll_video0_3x_clk.hw,
> + [CLK_PLL_VIDEO1_8X] = &pll_video1_8x_clk.common.hw,
> + [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.common.hw,
> + [CLK_PLL_VIDEO1_3X] = &pll_video1_3x_clk.hw,
> + [CLK_PLL_VIDEO2_8X] = &pll_video2_8x_clk.common.hw,
> + [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.common.hw,
> + [CLK_PLL_VIDEO2_3X] = &pll_video2_3x_clk.hw,
> + [CLK_PLL_VIDEO3_8X] = &pll_video3_8x_clk.common.hw,
> + [CLK_PLL_VIDEO3_4X] = &pll_video3_4x_clk.common.hw,
> + [CLK_PLL_VIDEO3_3X] = &pll_video3_3x_clk.hw,
> + [CLK_PLL_VE] = &pll_ve_clk.common.hw,
> + [CLK_PLL_AUDIO0_4X] = &pll_audio0_4x_clk.common.hw,
> + [CLK_PLL_AUDIO0_2X] = &pll_audio0_2x_clk.hw,
> + [CLK_PLL_AUDIO0] = &pll_audio0_clk.hw,
> + [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
> + [CLK_PLL_NPU_2X] = &pll_npu_2x_clk.hw,
> + [CLK_PLL_NPU] = &pll_npu_1x_clk.hw,
> + },
> +};
> +
> +static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
> + .ccu_clks = sun55i_a523_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun55i_a523_ccu_clks),
> +
> + .hw_clks = &sun55i_a523_hw_clks,
> +};
> +
> +static const u32 pll_regs[] = {
> + SUN55I_A523_PLL_DDR0_REG,
> + SUN55I_A523_PLL_PERIPH0_REG,
> + SUN55I_A523_PLL_PERIPH1_REG,
> + SUN55I_A523_PLL_GPU_REG,
> + SUN55I_A523_PLL_VIDEO0_REG,
> + SUN55I_A523_PLL_VIDEO1_REG,
> + SUN55I_A523_PLL_VIDEO2_REG,
> + SUN55I_A523_PLL_VE_REG,
> + SUN55I_A523_PLL_VIDEO3_REG,
> + SUN55I_A523_PLL_AUDIO0_REG,
> + SUN55I_A523_PLL_NPU_REG,
> +};
> +
> +static int sun55i_a523_ccu_probe(struct platform_device *pdev)
> +{
> + void __iomem *reg;
> + u32 val;
> + int i, ret;
> +
> + reg = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + /*
> + * The PLL clock code does not model all bits, for instance it does
> + * not support a separate enable and gate bit. We present the
> + * gate bit(27) as the enable bit, but then have to set the
> + * PLL Enable, LDO Enable, and Lock Enable bits on all PLLs here.
> + */
> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> + val = readl(reg + pll_regs[i]);
> + val |= BIT(31) | BIT(30) | BIT(29);
> + writel(val, reg + pll_regs[i]);
> + }
> +
> + /* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
> + val = readl(reg + SUN55I_A523_PLL_AUDIO0_REG);
> + val &= ~(BIT(1) | BIT(0));
> + writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
> +
> + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static const struct of_device_id sun55i_a523_ccu_ids[] = {
> + { .compatible = "allwinner,sun55i-a523-ccu" },
> + { }
> +};
> +
> +static struct platform_driver sun55i_a523_ccu_driver = {
> + .probe = sun55i_a523_ccu_probe,
> + .driver = {
> + .name = "sun55i-a523-ccu",
> + .suppress_bind_attrs = true,
> + .of_match_table = sun55i_a523_ccu_ids,
> + },
> +};
> +module_platform_driver(sun55i_a523_ccu_driver);
> +
> +MODULE_IMPORT_NS("SUNXI_CCU");
> +MODULE_DESCRIPTION("Support for the Allwinner A523 CCU");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
> new file mode 100644
> index 0000000000000..fc8dd42f1b47b
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2024 Arm Ltd.
> + */
> +
> +#ifndef _CCU_SUN55I_A523_H
> +#define _CCU_SUN55I_A523_H
> +
> +#include <dt-bindings/clock/sun55i-a523-ccu.h>
> +#include <dt-bindings/reset/sun55i-a523-ccu.h>
> +
> +#define CLK_NUMBER (CLK_FANOUT2 + 1)
> +
> +#endif /* _CCU_SUN55I_A523_H */
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
> index 687bd2ec798e2..5311835a4db60 100644
> --- a/drivers/clk/sunxi-ng/ccu_mp.h
> +++ b/drivers/clk/sunxi-ng/ccu_mp.h
> @@ -100,20 +100,22 @@ struct ccu_mp {
These changes doesn't belong in this commit.
Other than that, this looks like a good start. Thanks!
Best regards,
Jernej
> _muxshift, _muxwidth, \
> 0, _flags)
>
> -#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
> +#define SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(_struct, _name, _parents, _reg, \
> _mshift, _mwidth, \
> _pshift, _pwidth, \
> _muxshift, _muxwidth, \
> - _gate, _flags, \
> - _features) \
> + _gate, _postdiv, \
> + _flags, _features) \
> struct ccu_mp _struct = { \
> .enable = _gate, \
> .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
> .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
> .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
> + .fixed_post_div = _postdiv, \
> .common = { \
> .reg = _reg, \
> - .features = _features, \
> + .features = CCU_FEATURE_FIXED_POSTDIV | \
> + _features, \
> .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
> _parents, \
> &ccu_mp_ops,\
> @@ -126,11 +128,11 @@ struct ccu_mp {
> _pshift, _pwidth, \
> _muxshift, _muxwidth, \
> _gate, _flags) \
> - SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, \
> + SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(_struct, _name, _parents, \
> _reg, _mshift, _mwidth, \
> _pshift, _pwidth, \
> _muxshift, _muxwidth, \
> - _gate, _flags, 0)
> + _gate, 1, _flags, 0)
>
> #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
> _mshift, _mwidth, \
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 06/15] clk: sunxi-ng: a523: Add support for bus clocks
2025-02-14 12:53 ` [PATCH v2 06/15] clk: sunxi-ng: a523: Add support for bus clocks Andre Przywara
@ 2025-02-18 19:06 ` Jernej Škrabec
0 siblings, 0 replies; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:06 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:50 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the basic bus clocks for the Allwinner A523 and T527 SoCs.
> This covers the AHB, APB0 and APB1 clocks. Linux is not supposed to
> change those clocks, but they are needed as parents for many other mod
> clocks.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Best regards,
Jernej
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks
2025-02-14 12:53 ` [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks Andre Przywara
@ 2025-02-18 19:26 ` Jernej Škrabec
2025-02-28 13:42 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:26 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:51 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the clocks driving the various video subsystems of the SoC: the "DE"
> display engine, the "DI" deinterlacer, the "G2D" 2D graphics system, the
> Mali "GPU", the "VE" video engine, its associated IOMMU, as well as the
> clocks for the various video output drivers (HDMI, DP, LCDs).
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 219 +++++++++++++++++++++++++
> 1 file changed, 219 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> index 59f45e7c0904b..0ef1fd71a1ca5 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -364,6 +364,192 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
> 24, 3, /* mux */
> 0);
>
> +
> +/**************************************************************************
> + * mod clocks *
> + **************************************************************************/
> +
> +static const struct clk_hw *de_parents[] = {
> + &pll_periph0_300M_clk.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_video3_4x_clk.common.hw,
> + &pll_video3_3x_clk.hw,
> +};
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static const struct clk_hw *di_parents[] = {
> + &pll_periph0_300M_clk.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_video0_4x_clk.common.hw,
> + &pll_video1_4x_clk.common.hw,
> +};
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static const struct clk_hw *g2d_parents[] = {
> + &pll_periph0_400M_clk.hw,
> + &pll_periph0_300M_clk.hw,
> + &pll_video0_4x_clk.common.hw,
> + &pll_video1_4x_clk.common.hw,
> +};
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_hw *gpu_parents[] = {
> + &pll_gpu_clk.common.hw,
> + &pll_periph0_800M_clk.common.hw,
> + &pll_periph0_600M_clk.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_periph0_300M_clk.hw,
> + &pll_periph0_200M_clk.hw,
> +};
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> + 0, 4, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
GPU clock should have CLK_SET_RATE_FLAG.
> +
> +static const struct clk_hw *ve_parents[] = {
> + &pll_ve_clk.common.hw,
> + &pll_periph0_480M_clk.common.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_periph0_300M_clk.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static const struct clk_parent_data iommu_parents[] = {
> + { .hw = &pll_periph0_600M_clk.hw },
> + { .hw = &pll_ddr0_clk.common.hw },
> + { .hw = &pll_periph0_480M_clk.common.hw },
> + { .hw = &pll_periph0_400M_clk.hw },
> + { .hw = &pll_periph0_150M_clk.hw },
> + { .fw_name = "hosc" },
> +};
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
This won't work. IOMMU clock has also update bit, which must be set to actually
apply the new value, same as DDR clock.
> +
> +static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
> +
> +/* TODO: add mux between 32kOSC and PERIPH0/18750 */
Not sure what this TODO means.
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
> + pll_periph0_2x_hws,
> + 0xb10, BIT(30), 36621, 0);
> +
> +static const struct clk_parent_data hdmi_cec_parents[] = {
> + { .fw_name = "losc" },
> + { .hw = &hdmi_cec_32k_clk.common.hw },
> +};
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
> + 0xb10,
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_parent_data mipi_dsi_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph0_200M_clk.hw },
> + { .hw = &pll_periph0_150M_clk.hw },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi0_clk, "mipi-dsi0",
> + mipi_dsi_parents, 0xb24,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
> + mipi_dsi_parents, 0xb28,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static const struct clk_hw *tcon_parents[] = {
> + &pll_video0_4x_clk.common.hw,
> + &pll_video1_4x_clk.common.hw,
> + &pll_video2_4x_clk.common.hw,
> + &pll_video3_4x_clk.common.hw,
> + &pll_periph0_2x_clk.common.hw,
> + &pll_video0_3x_clk.hw,
> + &pll_video1_3x_clk.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
> + 0xb60,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
> + 0xb64,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
Missing tcon-lcd2 - see T527 manual.
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi0_clk, "combophy-dsi0",
> + tcon_parents, 0xb6c,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
> + tcon_parents, 0xb70,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
> + 0xb80,
> + 0, 4, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
> + 0xb84,
> + 0, 4, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
TCON TV0-1 parents are subset of others, according to T527 manual.
> +
> +static const struct clk_hw *edp_parents[] = {
> + &pll_video0_4x_clk.common.hw,
> + &pll_video1_4x_clk.common.hw,
> + &pll_video2_4x_clk.common.hw,
> + &pll_video3_4x_clk.common.hw,
> + &pll_periph0_2x_clk.common.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> + 0, 4, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
Missing CLK_SET_RATE_PARENT flag.
Best regards,
Jernej
> /*
> * Contains all clocks that are controlled by a hardware register. They
> * have a (sunxi) .common member, which needs to be initialised by the common
> @@ -394,6 +580,22 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> &ahb_clk.common,
> &apb0_clk.common,
> &apb1_clk.common,
> + &de_clk.common,
> + &di_clk.common,
> + &g2d_clk.common,
> + &gpu_clk.common,
> + &ve_clk.common,
> + &iommu_clk.common,
> + &hdmi_24M_clk.common,
> + &hdmi_cec_32k_clk.common,
> + &hdmi_cec_clk.common,
> + &mipi_dsi0_clk.common,
> + &mipi_dsi1_clk.common,
> + &tcon_lcd0_clk.common,
> + &tcon_lcd1_clk.common,
> + &tcon_tv0_clk.common,
> + &tcon_tv1_clk.common,
> + &edp_clk.common,
> };
>
> static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> @@ -442,6 +644,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> [CLK_AHB] = &ahb_clk.common.hw,
> [CLK_APB0] = &apb0_clk.common.hw,
> [CLK_APB1] = &apb1_clk.common.hw,
> + [CLK_DE] = &de_clk.common.hw,
> + [CLK_DI] = &di_clk.common.hw,
> + [CLK_G2D] = &g2d_clk.common.hw,
> + [CLK_GPU] = &gpu_clk.common.hw,
> + [CLK_VE] = &ve_clk.common.hw,
> + [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> + [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> + [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
> + [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
> + [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
> + [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
> + [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
> + [CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
> + [CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
> + [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> + [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> + [CLK_EDP] = &edp_clk.common.hw,
> },
> };
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 08/15] clk: sunxi-ng: a523: add system mod clocks
2025-02-14 12:53 ` [PATCH v2 08/15] clk: sunxi-ng: a523: add system " Andre Przywara
@ 2025-02-18 19:34 ` Jernej Škrabec
2025-02-28 13:43 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:34 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:52 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the clocks driving some core system related subsystems of the SoC:
> the "CE" crypto engine, the high speed timers, the DRAM and the associated
> MBUS clock, and the PCIe clock.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 119 +++++++++++++++++++++++++
> 1 file changed, 119 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> index 0ef1fd71a1ca5..b68c44bce825f 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -423,6 +423,18 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> BIT(31), /* gate */
> 0);
>
> +static const struct clk_parent_data ce_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph0_480M_clk.common.hw },
> + { .hw = &pll_periph0_400M_clk.hw },
> + { .hw = &pll_periph0_300M_clk.hw },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> static const struct clk_hw *ve_parents[] = {
> &pll_ve_clk.common.hw,
> &pll_periph0_480M_clk.common.hw,
> @@ -435,6 +447,65 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static const struct clk_parent_data hstimer_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "iosc" },
> + { .fw_name = "losc" },
> + { .hw = &pll_periph0_200M_clk.hw },
> +};
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
> + hstimer_parents, 0x730,
> + 0, 0, /* M */
> + 0, 3, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
CLK_SET_RATE_PARENT doesn't make much sense for fixed clocks.
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
> + hstimer_parents,
> + 0x734,
> + 0, 0, /* M */
> + 0, 3, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
> + hstimer_parents,
> + 0x738,
> + 0, 0, /* M */
> + 0, 3, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
> + hstimer_parents,
> + 0x73c,
> + 0, 0, /* M */
> + 0, 3, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
> + hstimer_parents,
> + 0x740,
> + 0, 0, /* M */
> + 0, 3, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
> + hstimer_parents,
> + 0x744,
> + 0, 0, /* M */
> + 0, 3, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> static const struct clk_parent_data iommu_parents[] = {
> { .hw = &pll_periph0_600M_clk.hw },
> { .hw = &pll_ddr0_clk.common.hw },
> @@ -450,6 +521,34 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static const struct clk_hw *dram_parents[] = {
> + &pll_ddr0_clk.common.hw,
> + &pll_periph0_600M_clk.hw,
> + &pll_periph0_480M_clk.common.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_periph0_150M_clk.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_IS_CRITICAL);
Same comment as for IOMMU clock. Update bit is needed to actually apply configuration.
Best regards,
Jernej
> +
> +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> + &dram_clk.common.hw, 4, 1, 0);
> +
> +static const struct clk_parent_data losc_hosc_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> +};
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
> + losc_hosc_parents, 0xaa0,
> + 0, 5, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
>
> /* TODO: add mux between 32kOSC and PERIPH0/18750 */
> @@ -584,8 +683,17 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> &di_clk.common,
> &g2d_clk.common,
> &gpu_clk.common,
> + &ce_clk.common,
> &ve_clk.common,
> + &hstimer0_clk.common,
> + &hstimer1_clk.common,
> + &hstimer2_clk.common,
> + &hstimer3_clk.common,
> + &hstimer4_clk.common,
> + &hstimer5_clk.common,
> &iommu_clk.common,
> + &dram_clk.common,
> + &pcie_aux_clk.common,
> &hdmi_24M_clk.common,
> &hdmi_cec_32k_clk.common,
> &hdmi_cec_clk.common,
> @@ -644,11 +752,22 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> [CLK_AHB] = &ahb_clk.common.hw,
> [CLK_APB0] = &apb0_clk.common.hw,
> [CLK_APB1] = &apb1_clk.common.hw,
> + [CLK_MBUS] = &mbus_clk.hw,
> [CLK_DE] = &de_clk.common.hw,
> [CLK_DI] = &di_clk.common.hw,
> [CLK_G2D] = &g2d_clk.common.hw,
> [CLK_GPU] = &gpu_clk.common.hw,
> + [CLK_CE] = &ce_clk.common.hw,
> [CLK_VE] = &ve_clk.common.hw,
> + [CLK_HSTIMER0] = &hstimer0_clk.common.hw,
> + [CLK_HSTIMER1] = &hstimer1_clk.common.hw,
> + [CLK_HSTIMER2] = &hstimer2_clk.common.hw,
> + [CLK_HSTIMER3] = &hstimer3_clk.common.hw,
> + [CLK_HSTIMER4] = &hstimer4_clk.common.hw,
> + [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> + [CLK_IOMMU] = &iommu_clk.common.hw,
> + [CLK_DRAM] = &dram_clk.common.hw,
> + [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 09/15] clk: sunxi-ng: a523: add interface mod clocks
2025-02-14 12:53 ` [PATCH v2 09/15] clk: sunxi-ng: a523: add interface " Andre Przywara
@ 2025-02-18 19:42 ` Jernej Škrabec
2025-02-28 13:46 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:42 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:53 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the clocks driving what the user manual summarises under "interface"
> devices: raw NAND flash, MMC, SPI, EMAC, "IR" infrared, and the "GPADC"
> general purpose analogue/digital converter.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 160 +++++++++++++++++++++++++
> 1 file changed, 160 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> index b68c44bce825f..14d13fb16dfbb 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -113,6 +113,9 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
> pll_periph0_2x_hws, 8, 1, 0);
> static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
> pll_periph0_480M_hws, 3, 1, 0);
> +static const struct clk_hw *pll_periph0_150M_hws[] = {
> + &pll_periph0_150M_clk.hw
> +};
>
> #define SUN55I_A523_PLL_PERIPH1_REG 0x028
> static struct ccu_nm pll_periph1_4x_clk = {
> @@ -537,6 +540,133 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> &dram_clk.common.hw, 4, 1, 0);
>
> +static const struct clk_parent_data nand_mmc_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph0_400M_clk.hw },
> + { .hw = &pll_periph0_300M_clk.hw },
> + { .hw = &pll_periph1_400M_clk.hw },
> + { .hw = &pll_periph1_300M_clk.hw },
> +};
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand0_clk, "nand0", nand_mmc_parents,
> + 0x810,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
> + 0x814,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
> + 0x830,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 2, /* post div */
> + 0, CCU_FEATURE_DUAL_DIV);
> +
> +static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc1_clk, "mmc1", nand_mmc_parents,
> + 0x834,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 2, /* post div */
> + 0, CCU_FEATURE_DUAL_DIV);
> +
> +static const struct clk_parent_data mmc2_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph0_800M_clk.common.hw },
> + { .hw = &pll_periph0_600M_clk.hw },
> + { .hw = &pll_periph1_800M_clk.common.hw },
> + { .hw = &pll_periph1_600M_clk.hw },
> +};
> +
> +static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
> + 0x838,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 2, /* post div */
> + 0, CCU_FEATURE_DUAL_DIV);
> +
> +static const struct clk_parent_data spi_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph0_300M_clk.hw },
> + { .hw = &pll_periph0_200M_clk.hw },
> + { .hw = &pll_periph1_300M_clk.hw },
> + { .hw = &pll_periph1_200M_clk.hw },
> +};
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
> + 0x950,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
Missing CCU_FEATURE_DUAL_DIV flag.
Best regards,
Jernej
> +
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> + pll_periph0_150M_hws,
> + 0x970, BIT(31) | BIT(30), 6, 0);
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
> + pll_periph0_150M_hws,
> + 0x974, BIT(31) | BIT(30), 6, 0);
> +
> +static const struct clk_parent_data ir_rx_parents[] = {
> + { .fw_name = "losc" },
> + { .fw_name = "hosc" },
> +};
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
> + 0, 5, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static const struct clk_parent_data ir_tx_ledc_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph1_600M_clk.hw },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
> + 0x9c0,
> + 0, 5, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
> + 0, 5, /* M */
> + BIT(31), /* gate */
> + 0);
> +static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
> + 0, 5, /* M */
> + BIT(31), /* gate */
> + 0);
> +
> static const struct clk_parent_data losc_hosc_parents[] = {
> { .fw_name = "hosc" },
> { .fw_name = "losc" },
> @@ -693,6 +823,21 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> &hstimer5_clk.common,
> &iommu_clk.common,
> &dram_clk.common,
> + &nand0_clk.common,
> + &nand1_clk.common,
> + &mmc0_clk.common,
> + &mmc1_clk.common,
> + &mmc2_clk.common,
> + &spi0_clk.common,
> + &spi1_clk.common,
> + &spi2_clk.common,
> + &spifc_clk.common,
> + &emac0_25M_clk.common,
> + &emac1_25M_clk.common,
> + &ir_rx_clk.common,
> + &ir_tx_clk.common,
> + &gpadc0_clk.common,
> + &gpadc1_clk.common,
> &pcie_aux_clk.common,
> &hdmi_24M_clk.common,
> &hdmi_cec_32k_clk.common,
> @@ -767,6 +912,21 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> [CLK_IOMMU] = &iommu_clk.common.hw,
> [CLK_DRAM] = &dram_clk.common.hw,
> + [CLK_NAND0] = &nand0_clk.common.hw,
> + [CLK_NAND1] = &nand1_clk.common.hw,
> + [CLK_MMC0] = &mmc0_clk.common.hw,
> + [CLK_MMC1] = &mmc1_clk.common.hw,
> + [CLK_MMC2] = &mmc2_clk.common.hw,
> + [CLK_SPI0] = &spi0_clk.common.hw,
> + [CLK_SPI1] = &spi1_clk.common.hw,
> + [CLK_SPI2] = &spi2_clk.common.hw,
> + [CLK_SPIFC] = &spifc_clk.common.hw,
> + [CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
> + [CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
> + [CLK_IR_RX] = &ir_rx_clk.common.hw,
> + [CLK_IR_TX] = &ir_tx_clk.common.hw,
> + [CLK_GPADC0] = &gpadc0_clk.common.hw,
> + [CLK_GPADC1] = &gpadc1_clk.common.hw,
> [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 10/15] clk: sunxi-ng: a523: add USB mod clocks
2025-02-14 12:53 ` [PATCH v2 10/15] clk: sunxi-ng: a523: add USB " Andre Przywara
@ 2025-02-18 19:46 ` Jernej Škrabec
0 siblings, 0 replies; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:46 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:54 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the clocks driving the USB subsystem: this just covers the two
> clocks creating the 12 MHz rate for the OHCI (USB 1.x) device. The rest
> of the USB clocks are either gate clocks (added later) or created
> internal to the USB IP.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Best regards,
Jernej
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 11/15] clk: sunxi-ng: a523: remaining mod clocks
2025-02-14 12:53 ` [PATCH v2 11/15] clk: sunxi-ng: a523: remaining " Andre Przywara
@ 2025-02-18 19:55 ` Jernej Škrabec
2025-02-28 13:50 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 19:55 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:55 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the remaining mod clocks, driving various parts of the SoC: the "LEDC"
> LED controller, the "CSI" camera interface, the "ISP" image processor,
> the DSP clock, and the "fanout" clocks, which allow to put clock signals
> on external pins.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 190 +++++++++++++++++++++++++
> 1 file changed, 190 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> index 59cc31f89ae77..6a4340f1fd041 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -354,6 +354,7 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
> 0, 5, /* M */
> 24, 2, /* mux */
> 0);
> +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
>
> static const struct clk_parent_data apb1_parents[] = {
> { .fw_name = "hosc" },
> @@ -832,6 +833,153 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> + 0xbf0,
> + 0, 4, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_hw *csi_top_parents[] = {
> + &pll_periph0_300M_clk.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_periph0_480M_clk.common.hw,
> + &pll_video3_4x_clk.common.hw,
> + &pll_video3_3x_clk.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents,
> + 0xc04,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_parent_data csi_mclk_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_video3_4x_clk.common.hw },
> + { .hw = &pll_video0_4x_clk.common.hw },
> + { .hw = &pll_video1_4x_clk.common.hw },
> + { .hw = &pll_video2_4x_clk.common.hw },
> +};
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0",
> + csi_mclk_parents, 0xc08,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
Missing dual div flag for csi-mclk clocks.
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1",
> + csi_mclk_parents, 0xc0c,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2",
> + csi_mclk_parents, 0xc10,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
> + csi_mclk_parents, 0xc14,
> + 0, 5, /* M */
> + 8, 5, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_hw *isp_parents[] = {
> + &pll_periph0_300M_clk.hw,
> + &pll_periph0_400M_clk.hw,
> + &pll_video2_4x_clk.common.hw,
> + &pll_video3_4x_clk.common.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(isp_clk, "isp", isp_parents, 0xc20,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_parent_data dsp_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> + { .fw_name = "iosc" },
> + { .hw = &pll_periph0_2x_clk.common.hw },
> + { .hw = &pll_periph0_400M_clk.hw, },
Last one should be pll_periph0_480M_clk.
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> + 0xf30, BIT(0), 0);
> +static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> + 0xf30, BIT(1), 2, 0);
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M",
> + pll_periph0_480M_hws,
> + 0xf30, BIT(2), 30, 0);
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M",
> + pll_periph0_2x_hws,
> + 0xf30, BIT(3), 48, 0);
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_50M_clk, "fanout-50M",
> + pll_periph0_2x_hws,
> + 0xf30, BIT(4), 24, 0);
> +
> +/* These clocks have a second divider that is not modelled and forced to 0. */
Any specific reason for that?
Best regards,
Jernej
> +#define SUN55I_A523_FANOUT_27M_REG 0xf34
> +static const struct clk_hw *fanout_27M_parents[] = {
> + &pll_video0_4x_clk.common.hw,
> + &pll_video1_4x_clk.common.hw,
> + &pll_video2_4x_clk.common.hw,
> + &pll_video3_4x_clk.common.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M",
> + fanout_27M_parents, 0xf34,
> + 0, 5, /* M */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +#define SUN55I_A523_FANOUT_PCLK_REG 0xf38
> +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws,
> + 0xf38,
> + 0, 5, /* M */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_parent_data fanout_parents[] = {
> + { .fw_name = "osc32k-out" },
> + { .hw = &fanout_12M_clk.common.hw, },
> + { .hw = &fanout_16M_clk.common.hw, },
> + { .hw = &fanout_24M_clk.common.hw, },
> + { .hw = &fanout_25M_clk.common.hw, },
> + { .hw = &fanout_27M_clk.common.hw, },
> + { .hw = &fanout_pclk_clk.common.hw, },
> + { .hw = &fanout_50M_clk.common.hw, },
> +};
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents,
> + 0xf3c,
> + 0, 3, /* mux */
> + BIT(21), /* gate */
> + 0);
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents,
> + 0xf3c,
> + 3, 3, /* mux */
> + BIT(22), /* gate */
> + 0);
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents,
> + 0xf3c,
> + 6, 3, /* mux */
> + BIT(23), /* gate */
> + 0);
> +
> /*
> * Contains all clocks that are controlled by a hardware register. They
> * have a (sunxi) .common member, which needs to be initialised by the common
> @@ -904,6 +1052,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> &tcon_tv0_clk.common,
> &tcon_tv1_clk.common,
> &edp_clk.common,
> + &ledc_clk.common,
> + &csi_top_clk.common,
> + &csi_mclk0_clk.common,
> + &csi_mclk1_clk.common,
> + &csi_mclk2_clk.common,
> + &csi_mclk3_clk.common,
> + &isp_clk.common,
> + &dsp_clk.common,
> + &fanout_24M_clk.common,
> + &fanout_12M_clk.common,
> + &fanout_16M_clk.common,
> + &fanout_25M_clk.common,
> + &fanout_27M_clk.common,
> + &fanout_pclk_clk.common,
> + &fanout0_clk.common,
> + &fanout1_clk.common,
> + &fanout2_clk.common,
> };
>
> static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> @@ -997,6 +1162,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> [CLK_EDP] = &edp_clk.common.hw,
> + [CLK_LEDC] = &ledc_clk.common.hw,
> + [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> + [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> + [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> + [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> + [CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
> + [CLK_ISP] = &isp_clk.common.hw,
> + [CLK_DSP] = &dsp_clk.common.hw,
> + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
> + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
> + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
> + [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
> + [CLK_FANOUT0] = &fanout0_clk.common.hw,
> + [CLK_FANOUT1] = &fanout1_clk.common.hw,
> + [CLK_FANOUT2] = &fanout2_clk.common.hw,
> },
> };
>
> @@ -1048,6 +1230,14 @@ static int sun55i_a523_ccu_probe(struct platform_device *pdev)
> val &= ~(BIT(1) | BIT(0));
> writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
>
> + /* Force fanout factors N to 0. */
> + val = readl(reg + SUN55I_A523_FANOUT_27M_REG);
> + val &= ~GENMASK(12, 8);
> + writel(val, reg + SUN55I_A523_FANOUT_27M_REG);
> + val = readl(reg + SUN55I_A523_FANOUT_PCLK_REG);
> + val &= ~GENMASK(9, 5);
> + writel(val, reg + SUN55I_A523_FANOUT_PCLK_REG);
> +
> ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
> if (ret)
> return ret;
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates
2025-02-14 12:53 ` [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates Andre Przywara
@ 2025-02-18 20:12 ` Jernej Škrabec
2025-02-28 14:04 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 20:12 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:56 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Add the various bus clock gates that control access to the devices'
> register interface.
> These clocks are each just one bit, typically the lower bits in some "BGR"
> (Bus Gate / Reset) registers, for each device group: one for all UARTs,
> one for all SPI interfaces, and so on.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 295 ++++++++++++++++++++++++-
> 1 file changed, 294 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> index 6a4340f1fd041..fbed9b2b3b2f9 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -350,6 +350,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
> 0, 5, /* M */
> 24, 2, /* mux */
> 0);
> +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
> +
> static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
> 0, 5, /* M */
> 24, 2, /* mux */
> @@ -367,10 +369,11 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
> 0, 5, /* M */
> 24, 3, /* mux */
> 0);
> +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
>
>
> /**************************************************************************
> - * mod clocks *
> + * mod clocks with gates *
> **************************************************************************/
>
> static const struct clk_hw *de_parents[] = {
> @@ -386,6 +389,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
> +
> static const struct clk_hw *di_parents[] = {
> &pll_periph0_300M_clk.hw,
> &pll_periph0_400M_clk.hw,
> @@ -399,6 +404,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
> +
> static const struct clk_hw *g2d_parents[] = {
> &pll_periph0_400M_clk.hw,
> &pll_periph0_300M_clk.hw,
> @@ -412,6 +419,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
> +
> static const struct clk_hw *gpu_parents[] = {
> &pll_gpu_clk.common.hw,
> &pll_periph0_800M_clk.common.hw,
> @@ -427,6 +436,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
> +
> static const struct clk_parent_data ce_parents[] = {
> { .fw_name = "hosc" },
> { .hw = &pll_periph0_480M_clk.common.hw },
> @@ -439,6 +450,10 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
> + BIT(1), 0);
> +
> static const struct clk_hw *ve_parents[] = {
> &pll_ve_clk.common.hw,
> &pll_periph0_480M_clk.common.hw,
> @@ -451,6 +466,16 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
> + BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
> + BIT(0), 0);
msgbox and spinlock probably needs to be marked as critical? Crust needs that
for communication with TF-A.
> +
> static const struct clk_parent_data hstimer_parents[] = {
> { .fw_name = "hosc" },
> { .fw_name = "iosc" },
> @@ -510,6 +535,15 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
> + BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
> + BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
> +
> static const struct clk_parent_data iommu_parents[] = {
> { .hw = &pll_periph0_600M_clk.hw },
> { .hw = &pll_ddr0_clk.common.hw },
> @@ -525,6 +559,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
> + BIT(0), 0);
> +
> static const struct clk_hw *dram_parents[] = {
> &pll_ddr0_clk.common.hw,
> &pll_periph0_600M_clk.hw,
> @@ -541,6 +578,22 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> &dram_clk.common.hw, 4, 1, 0);
>
> +static SUNXI_CCU_GATE_HW(mbus_dma_clk, "mbus-dma", &mbus_clk.hw,
> + 0x804, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(mbus_ve_clk, "mbus-ve", &mbus_clk.hw,
> + 0x804, BIT(1), 0);
> +static SUNXI_CCU_GATE_HW(mbus_ce_clk, "mbus-ce", &mbus_clk.hw,
> + 0x804, BIT(2), 0);
> +static SUNXI_CCU_GATE_HW(mbus_nand_clk, "mbus-nand", &mbus_clk.hw,
> + 0x804, BIT(5), 0);
> +static SUNXI_CCU_GATE_HW(mbus_usb3_clk, "mbus-usb3", &mbus_clk.hw,
> + 0x804, BIT(6), 0);
> +static SUNXI_CCU_GATE_HW(mbus_csi_clk, "mbus-csi", &mbus_clk.hw,
> + 0x804, BIT(8), 0);
Missing several MBUS gates. Check T527 manual.
> +
> +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
> + BIT(0), CLK_IS_CRITICAL);
> +
> static const struct clk_parent_data nand_mmc_parents[] = {
> { .fw_name = "hosc" },
> { .hw = &pll_periph0_400M_clk.hw },
> @@ -563,6 +616,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
> + BIT(0), 0);
> +
> static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
> 0x830,
> 0, 5, /* M */
> @@ -598,6 +654,39 @@ static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
> 2, /* post div */
> 0, CCU_FEATURE_DUAL_DIV);
>
> +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
> + BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
> + BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
> + BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
> + BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
> + BIT(3), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
> + BIT(4), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
> + BIT(5), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
> + BIT(6), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
> + BIT(7), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
> +
> static const struct clk_parent_data spi_parents[] = {
> { .fw_name = "hosc" },
> { .hw = &pll_periph0_300M_clk.hw },
> @@ -630,6 +719,11 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
> 24, 3, /* mux */
> BIT(31), /* gate */
> 0);
> +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
> + BIT(3), 0);
>
> static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> pll_periph0_150M_hws,
> @@ -637,6 +731,10 @@ static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
> pll_periph0_150M_hws,
> 0x974, BIT(31) | BIT(30), 6, 0);
> +static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
> + BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
> + BIT(0), 0);
>
> static const struct clk_parent_data ir_rx_parents[] = {
> { .fw_name = "losc" },
> @@ -648,6 +746,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
> 24, 1, /* mux */
> BIT(31), /* gate */
> 0);
> +static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
> + BIT(0), 0);
> +
> static const struct clk_parent_data ir_tx_ledc_parents[] = {
> { .fw_name = "hosc" },
> { .hw = &pll_periph1_600M_clk.hw },
> @@ -658,6 +759,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
> 24, 1, /* mux */
> BIT(31), /* gate */
> 0);
> +static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
> + BIT(0), 0);
>
> static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
> 0, 5, /* M */
> @@ -667,6 +770,12 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
> 0, 5, /* M */
> BIT(31), /* gate */
> 0);
> +static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
> + BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
> + BIT(1), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
>
> /*
> * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
> @@ -720,6 +829,18 @@ static struct ccu_mux usb_ohci1_clk = {
> },
> };
>
> +static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
> + BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
> + BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
> + BIT(4), 0);
> +static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
> + BIT(5), 0);
> +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
> + BIT(0), 0);
>
> static const struct clk_parent_data losc_hosc_parents[] = {
> { .fw_name = "hosc" },
> @@ -733,6 +854,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws, 0xabc,
> + BIT(0), 0);
> +
> static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
>
> /* TODO: add mux between 32kOSC and PERIPH0/18750 */
> @@ -750,6 +874,8 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
> +
> static const struct clk_parent_data mipi_dsi_parents[] = {
> { .fw_name = "hosc" },
> { .hw = &pll_periph0_200M_clk.hw },
> @@ -769,6 +895,12 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
> + BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
> + BIT(1), 0);
> +
> static const struct clk_hw *tcon_parents[] = {
> &pll_video0_4x_clk.common.hw,
> &pll_video1_4x_clk.common.hw,
> @@ -806,6 +938,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
> + BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
> + BIT(1), 0);
Missing gate for bus-tcon-lcd2.
> +
> static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
> 0xb80,
> 0, 4, /* M */
> @@ -820,6 +957,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
> BIT(31), /* gate */
> CLK_SET_RATE_PARENT);
>
> +static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
> + BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
> + BIT(1), 0);
> +
> static const struct clk_hw *edp_parents[] = {
> &pll_video0_4x_clk.common.hw,
> &pll_video1_4x_clk.common.hw,
> @@ -833,6 +975,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
> +
> static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> 0xbf0,
> 0, 4, /* M */
> @@ -840,6 +984,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
> +
> static const struct clk_hw *csi_top_parents[] = {
> &pll_periph0_300M_clk.hw,
> &pll_periph0_400M_clk.hw,
> @@ -893,6 +1039,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
> +
> static const struct clk_hw *isp_parents[] = {
> &pll_periph0_300M_clk.hw,
> &pll_periph0_400M_clk.hw,
> @@ -918,6 +1066,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
> BIT(31), /* gate */
> 0);
>
> +static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk, "bus-dsp-cfg", ahb_hws, 0xc7c,
> + BIT(1), 0);
I don't see 0xc7c register.
Best regards,
Jernej
> +
> static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> 0xf30, BIT(0), 0);
> static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> @@ -1011,55 +1162,128 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> &apb0_clk.common,
> &apb1_clk.common,
> &de_clk.common,
> + &bus_de_clk.common,
> &di_clk.common,
> + &bus_di_clk.common,
> &g2d_clk.common,
> + &bus_g2d_clk.common,
> &gpu_clk.common,
> + &bus_gpu_clk.common,
> &ce_clk.common,
> + &bus_ce_clk.common,
> + &bus_ce_sys_clk.common,
> &ve_clk.common,
> + &bus_ve_clk.common,
> + &bus_dma_clk.common,
> + &bus_msgbox_clk.common,
> + &bus_spinlock_clk.common,
> &hstimer0_clk.common,
> &hstimer1_clk.common,
> &hstimer2_clk.common,
> &hstimer3_clk.common,
> &hstimer4_clk.common,
> &hstimer5_clk.common,
> + &bus_hstimer_clk.common,
> + &bus_dbg_clk.common,
> + &bus_pwm0_clk.common,
> + &bus_pwm1_clk.common,
> &iommu_clk.common,
> + &bus_iommu_clk.common,
> &dram_clk.common,
> + &mbus_dma_clk.common,
> + &mbus_ve_clk.common,
> + &mbus_ce_clk.common,
> + &mbus_nand_clk.common,
> + &mbus_usb3_clk.common,
> + &mbus_csi_clk.common,
> + &bus_dram_clk.common,
> &nand0_clk.common,
> &nand1_clk.common,
> + &bus_nand_clk.common,
> &mmc0_clk.common,
> &mmc1_clk.common,
> &mmc2_clk.common,
> + &bus_sysdap_clk.common,
> + &bus_mmc0_clk.common,
> + &bus_mmc1_clk.common,
> + &bus_mmc2_clk.common,
> + &bus_uart0_clk.common,
> + &bus_uart1_clk.common,
> + &bus_uart2_clk.common,
> + &bus_uart3_clk.common,
> + &bus_uart4_clk.common,
> + &bus_uart5_clk.common,
> + &bus_uart6_clk.common,
> + &bus_uart7_clk.common,
> + &bus_i2c0_clk.common,
> + &bus_i2c1_clk.common,
> + &bus_i2c2_clk.common,
> + &bus_i2c3_clk.common,
> + &bus_i2c4_clk.common,
> + &bus_i2c5_clk.common,
> + &bus_can_clk.common,
> &spi0_clk.common,
> &spi1_clk.common,
> &spi2_clk.common,
> &spifc_clk.common,
> + &bus_spi0_clk.common,
> + &bus_spi1_clk.common,
> + &bus_spi2_clk.common,
> + &bus_spifc_clk.common,
> &emac0_25M_clk.common,
> &emac1_25M_clk.common,
> + &bus_emac0_clk.common,
> + &bus_emac1_clk.common,
> &ir_rx_clk.common,
> + &bus_ir_rx_clk.common,
> &ir_tx_clk.common,
> + &bus_ir_tx_clk.common,
> &gpadc0_clk.common,
> &gpadc1_clk.common,
> + &bus_gpadc0_clk.common,
> + &bus_gpadc1_clk.common,
> + &bus_ths_clk.common,
> &usb_ohci0_clk.common,
> &usb_ohci1_clk.common,
> + &bus_ohci0_clk.common,
> + &bus_ohci1_clk.common,
> + &bus_ehci0_clk.common,
> + &bus_ehci1_clk.common,
> + &bus_otg_clk.common,
> + &bus_lradc_clk.common,
> &pcie_aux_clk.common,
> + &bus_dpss_top_clk.common,
> &hdmi_24M_clk.common,
> &hdmi_cec_32k_clk.common,
> &hdmi_cec_clk.common,
> + &bus_hdmi_clk.common,
> &mipi_dsi0_clk.common,
> &mipi_dsi1_clk.common,
> + &bus_mipi_dsi0_clk.common,
> + &bus_mipi_dsi1_clk.common,
> &tcon_lcd0_clk.common,
> &tcon_lcd1_clk.common,
> + &combophy_dsi0_clk.common,
> + &combophy_dsi1_clk.common,
> + &bus_tcon_lcd0_clk.common,
> + &bus_tcon_lcd1_clk.common,
> &tcon_tv0_clk.common,
> &tcon_tv1_clk.common,
> + &bus_tcon_tv0_clk.common,
> + &bus_tcon_tv1_clk.common,
> &edp_clk.common,
> + &bus_edp_clk.common,
> &ledc_clk.common,
> + &bus_ledc_clk.common,
> &csi_top_clk.common,
> &csi_mclk0_clk.common,
> &csi_mclk1_clk.common,
> &csi_mclk2_clk.common,
> &csi_mclk3_clk.common,
> + &bus_csi_clk.common,
> &isp_clk.common,
> &dsp_clk.common,
> + &bus_dsp_cfg_clk.common,
> &fanout_24M_clk.common,
> &fanout_12M_clk.common,
> &fanout_16M_clk.common,
> @@ -1119,57 +1343,126 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> [CLK_APB1] = &apb1_clk.common.hw,
> [CLK_MBUS] = &mbus_clk.hw,
> [CLK_DE] = &de_clk.common.hw,
> + [CLK_BUS_DE] = &bus_de_clk.common.hw,
> [CLK_DI] = &di_clk.common.hw,
> + [CLK_BUS_DI] = &bus_di_clk.common.hw,
> [CLK_G2D] = &g2d_clk.common.hw,
> + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
> [CLK_GPU] = &gpu_clk.common.hw,
> + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
> [CLK_CE] = &ce_clk.common.hw,
> + [CLK_BUS_CE] = &bus_ce_clk.common.hw,
> + [CLK_BUS_CE_SYS] = &bus_ce_sys_clk.common.hw,
> [CLK_VE] = &ve_clk.common.hw,
> + [CLK_BUS_VE] = &bus_ve_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_HSTIMER0] = &hstimer0_clk.common.hw,
> [CLK_HSTIMER1] = &hstimer1_clk.common.hw,
> [CLK_HSTIMER2] = &hstimer2_clk.common.hw,
> [CLK_HSTIMER3] = &hstimer3_clk.common.hw,
> [CLK_HSTIMER4] = &hstimer4_clk.common.hw,
> [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
> + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
> + [CLK_BUS_PWM0] = &bus_pwm0_clk.common.hw,
> + [CLK_BUS_PWM1] = &bus_pwm1_clk.common.hw,
> [CLK_IOMMU] = &iommu_clk.common.hw,
> + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
> [CLK_DRAM] = &dram_clk.common.hw,
> + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
> + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
> + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
> + [CLK_MBUS_CSI] = &mbus_csi_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_MMC2] = &mmc2_clk.common.hw,
> + [CLK_BUS_SYSDAP] = &bus_sysdap_clk.common.hw,
> + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
> + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
> + [CLK_BUS_MMC2] = &bus_mmc2_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_UART4] = &bus_uart4_clk.common.hw,
> + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
> + [CLK_BUS_UART6] = &bus_uart6_clk.common.hw,
> + [CLK_BUS_UART7] = &bus_uart7_clk.common.hw,
> + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
> + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
> + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
> + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
> + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
> + [CLK_BUS_I2C5] = &bus_i2c5_clk.common.hw,
> + [CLK_BUS_CAN] = &bus_can_clk.common.hw,
> [CLK_SPI0] = &spi0_clk.common.hw,
> [CLK_SPI1] = &spi1_clk.common.hw,
> [CLK_SPI2] = &spi2_clk.common.hw,
> [CLK_SPIFC] = &spifc_clk.common.hw,
> + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
> + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
> + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
> + [CLK_BUS_SPIFC] = &bus_spifc_clk.common.hw,
> [CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
> [CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
> + [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
> + [CLK_BUS_EMAC1] = &bus_emac1_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_GPADC0] = &gpadc0_clk.common.hw,
> [CLK_GPADC1] = &gpadc1_clk.common.hw,
> + [CLK_BUS_GPADC0] = &bus_gpadc0_clk.common.hw,
> + [CLK_BUS_GPADC1] = &bus_gpadc1_clk.common.hw,
> + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
> [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
> [CLK_USB_OHCI1] = &usb_ohci1_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_EHCI1] = &bus_ehci1_clk.common.hw,
> + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
> + [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw,
> [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
> [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
> + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
> [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
> [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
> + [CLK_BUS_MIPI_DSI0] = &bus_mipi_dsi0_clk.common.hw,
> + [CLK_BUS_MIPI_DSI1] = &bus_mipi_dsi1_clk.common.hw,
> [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
> [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
> [CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
> [CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
> + [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw,
> + [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw,
> [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
> + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
> [CLK_EDP] = &edp_clk.common.hw,
> + [CLK_BUS_EDP] = &bus_edp_clk.common.hw,
> [CLK_LEDC] = &ledc_clk.common.hw,
> + [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw,
> [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> [CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
> + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
> [CLK_ISP] = &isp_clk.common.hw,
> [CLK_DSP] = &dsp_clk.common.hw,
> + [CLK_BUS_DSP_CFG] = &bus_dsp_cfg_clk.common.hw,
> [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines
2025-02-14 12:53 ` [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines Andre Przywara
@ 2025-02-18 20:29 ` Jernej Škrabec
2025-02-28 14:21 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 20:29 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:57 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> Allwinner SoCs do not contain a separate reset controller, instead the
> reset lines for the various devices are integrated into the "BGR" (Bus
> Gate / Reset) registers, for each device group: one for all UARTs, one
> for all SPI interfaces, and so on.
> The Allwinner CCU driver also doubles as a reset provider, and since the
> reset lines are indeed just single bits in those BGR register, we can
> represent them easily in an array of structs, just containing the
> register offset and the bit number.
>
> Add the location of the reset bits for all devices in the A523/T527
> SoCs, using the existing sunxi CCU infrastructure.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 83 ++++++++++++++++++++++++++
> 1 file changed, 83 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> index fbed9b2b3b2f9..d57565f07a112 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> @@ -1475,11 +1475,94 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> },
> };
>
> +static struct ccu_reset_map sun55i_a523_ccu_resets[] = {
> + [RST_MBUS] = { 0x540, BIT(30) },
> + [RST_BUS_NSI] = { 0x54c, BIT(16) },
> + [RST_BUS_DE] = { 0x60c, BIT(16) },
> + [RST_BUS_DI] = { 0x62c, BIT(16) },
> + [RST_BUS_G2D] = { 0x63c, BIT(16) },
> + [RST_BUS_SYS] = { 0x64c, BIT(16) },
> + [RST_BUS_GPU] = { 0x67c, BIT(16) },
> + [RST_BUS_CE] = { 0x68c, BIT(16) },
> + [RST_BUS_SYS_CE] = { 0x68c, BIT(17) },
> + [RST_BUS_VE] = { 0x69c, BIT(16) },
> + [RST_BUS_DMA] = { 0x70c, BIT(16) },
> + [RST_BUS_MSGBOX] = { 0x71c, BIT(16) },
> + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
> + [RST_BUS_CPUXTIMER] = { 0x74c, BIT(16) },
> + [RST_BUS_DBG] = { 0x78c, BIT(16) },
> + [RST_BUS_PWM0] = { 0x7ac, BIT(16) },
> + [RST_BUS_PWM1] = { 0x7ac, BIT(17) },
> + [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_MMC2] = { 0x84c, BIT(18) },
> + [RST_BUS_SYSDAP] = { 0x88c, BIT(16) },
> + [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_UART4] = { 0x90c, BIT(20) },
> + [RST_BUS_UART5] = { 0x90c, BIT(21) },
> + [RST_BUS_UART6] = { 0x90c, BIT(22) },
> + [RST_BUS_UART7] = { 0x90c, BIT(23) },
> + [RST_BUS_I2C0] = { 0x91c, BIT(16) },
> + [RST_BUS_I2C1] = { 0x91c, BIT(17) },
> + [RST_BUS_I2C2] = { 0x91c, BIT(18) },
> + [RST_BUS_I2C3] = { 0x91c, BIT(19) },
> + [RST_BUS_I2C4] = { 0x91c, BIT(20) },
> + [RST_BUS_I2C5] = { 0x91c, BIT(21) },
> + [RST_BUS_CAN] = { 0x92c, BIT(16) },
> + [RST_BUS_SPI0] = { 0x96c, BIT(16) },
> + [RST_BUS_SPI1] = { 0x96c, BIT(17) },
> + [RST_BUS_SPI2] = { 0x96c, BIT(18) },
> + [RST_BUS_SPIFC] = { 0x96c, BIT(19) },
> + [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
> + [RST_BUS_EMAC1] = { 0x98c, BIT(16) | BIT(17) }, /* GMAC1-AXI */
GMAC AXI reset should be separate.
> + [RST_BUS_IR_RX] = { 0x99c, BIT(16) },
> + [RST_BUS_IR_TX] = { 0x9cc, BIT(16) },
> + [RST_BUS_GPADC0] = { 0x9ec, BIT(16) },
> + [RST_BUS_GPADC1] = { 0x9ec, BIT(17) },
> + [RST_BUS_THS] = { 0x9fc, 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_EHCI1] = { 0xa8c, BIT(21) },
> + [RST_BUS_OTG] = { 0xa8c, BIT(24) },
> + [RST_BUS_3] = { 0xa8c, BIT(25) }, /* BSP + register */
> + [RST_BUS_LRADC] = { 0xa9c, BIT(16) },
> + [RST_BUS_PCIE_USB3] = { 0xaac, BIT(16) },
> + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
Docs say that there is extra display top reset at 0xacc.
Best regards,
Jernej
> + [RST_BUS_HDMI_MAIN] = { 0xb1c, BIT(16) },
> + [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
> + [RST_BUS_MIPI_DSI0] = { 0xb4c, BIT(16) },
> + [RST_BUS_MIPI_DSI1] = { 0xb4c, BIT(17) },
> + [RST_BUS_TCON_LCD0] = { 0xb7c, BIT(16) },
> + [RST_BUS_TCON_LCD1] = { 0xb7c, BIT(17) },
> + [RST_BUS_TCON_LCD2] = { 0xb7c, BIT(18) },
> + [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
> + [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
> + [RST_BUS_LVDS0] = { 0xbac, BIT(16) },
> + [RST_BUS_LVDS1] = { 0xbac, BIT(17) },
> + [RST_BUS_EDP] = { 0xbbc, BIT(16) },
> + [RST_BUS_VIDEO_OUT0] = { 0xbcc, BIT(16) },
> + [RST_BUS_VIDEO_OUT1] = { 0xbcc, BIT(17) },
> + [RST_BUS_LEDC] = { 0xbfc, BIT(16) },
> + [RST_BUS_CSI] = { 0xc1c, BIT(16) },
> + [RST_BUS_ISP] = { 0xc2c, BIT(16) }, /* BSP + register */
> +};
> +
> static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
> .ccu_clks = sun55i_a523_ccu_clks,
> .num_ccu_clks = ARRAY_SIZE(sun55i_a523_ccu_clks),
>
> .hw_clks = &sun55i_a523_hw_clks,
> +
> + .resets = sun55i_a523_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun55i_a523_ccu_resets),
> };
>
> static const u32 pll_regs[] = {
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
2025-02-14 12:53 ` [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU Andre Przywara
@ 2025-02-18 20:42 ` Jernej Škrabec
2025-02-28 14:33 ` Andre Przywara
0 siblings, 1 reply; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-18 20:42 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Andre Przywara
Cc: Philipp Zabel, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel
Dne petek, 14. februar 2025 ob 13:53:59 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> The A523/T527 SoCs have clock/reset controls in the PRCM part, like many
> previous SoCs. For a change, the whole PRCM is documented in the A523
> manual, including the system bus tree, so we can describe all those
> clocks correctly based on that. There layout seems to be derived from
> the H6 and H616 PRCM CCUs, though there are more clocks, and many clocks
> have subtly changed.
>
> Describe all the mod and gate clocks, including the three bus clocks
> (R_AHB, R_APB0, and R_APB1).
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/Kconfig | 5 +
> drivers/clk/sunxi-ng/Makefile | 2 +
> drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c | 245 +++++++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h | 14 ++
> 4 files changed, 266 insertions(+)
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index 04efbda847cf9..5830a9d87bf25 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -57,6 +57,11 @@ config SUN55I_A523_CCU
> default y
> depends on ARM64 || COMPILE_TEST
>
> +config SUN55I_A523_R_CCU
> + tristate "Support for the Allwinner A523/T527 PRCM CCU"
> + default y
> + depends on ARM64 || COMPILE_TEST
> +
> config SUN4I_A10_CCU
> tristate "Support for the Allwinner A10/A20 CCU"
> default y
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 01a887f7824bb..82e471036de69 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
> obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
> obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
> obj-$(CONFIG_SUN55I_A523_CCU) += sun55i-a523-ccu.o
> +obj-$(CONFIG_SUN55I_A523_R_CCU) += sun55i-a523-r-ccu.o
> obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
> obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
> obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
> @@ -60,6 +61,7 @@ sun50i-h6-ccu-y += ccu-sun50i-h6.o
> sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
> sun50i-h616-ccu-y += ccu-sun50i-h616.o
> sun55i-a523-ccu-y += ccu-sun55i-a523.o
> +sun55i-a523-r-ccu-y += ccu-sun55i-a523-r.o
> sun4i-a10-ccu-y += ccu-sun4i-a10.o
> sun5i-ccu-y += ccu-sun5i.o
> sun6i-a31-ccu-y += ccu-sun6i-a31.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
> new file mode 100644
> index 0000000000000..0dafc38370f22
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
> @@ -0,0 +1,245 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2024 Arm Ltd.
> + * Based on the D1 CCU driver:
> + * Copyright (c) 2020 huangzhenwei@allwinnertech.com
> + * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +
> +#include "ccu-sun55i-a523-r.h"
> +
> +static const struct clk_parent_data r_ahb_apb_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> + { .fw_name = "iosc" },
> + { .fw_name = "pll-periph" },
> + { .fw_name = "pll-audio" },
I believe pll-periph has /3 divider and pll-audio x4 multiplier.
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX(r_ahb_clk, "r-ahb",
> + r_ahb_apb_parents, 0x000,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + 0);
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX(r_apb0_clk, "r-apb0",
> + r_ahb_apb_parents, 0x00c,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + 0);
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX(r_apb1_clk, "r-apb1",
> + r_ahb_apb_parents, 0x010,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + 0);
> +
> +static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
> + r_ahb_apb_parents, 0x100,
> + 1, 3, /* P */
> + 4, 3, /* mux */
> + BIT(0),
> + 0);
> +static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
> + r_ahb_apb_parents, 0x104,
> + 1, 3, /* P */
> + 4, 3, /* mux */
> + BIT(0),
> + 0);
> +static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
> + r_ahb_apb_parents, 0x108,
> + 1, 3, /* P */
> + 4, 3, /* mux */
> + BIT(0),
> + 0);
> +
> +static SUNXI_CCU_GATE_HW(bus_r_timer_clk, "bus-r-timer", &r_ahb_clk.common.hw,
> + 0x11c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_twd_clk, "bus-r-twd", &r_apb0_clk.common.hw,
> + 0x12c, BIT(0), 0);
> +
> +static const struct clk_parent_data r_pwmctrl_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> + { .fw_name = "iosc" },
> +};
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(r_pwmctrl_clk, "r-pwmctrl",
> + r_pwmctrl_parents, 0x130,
> + 24, 1, /* mux */
Mux width is 2.
> + BIT(31),
> + 0);
> +static SUNXI_CCU_GATE_HW(bus_r_pwmctrl_clk, "bus-r-pwmctrl",
> + &r_apb0_clk.common.hw, 0x13c, BIT(0), 0);
> +
> +/* SPI clock is /M/N (same as new MMC?) */
Missing SPI clock (reg 0x150).
Best regards,
Jernej
> +static SUNXI_CCU_GATE_HW(bus_r_spi_clk, "bus-r-spi",
> + &r_ahb_clk.common.hw, 0x15c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_spinlock_clk, "bus-r-spinlock",
> + &r_ahb_clk.common.hw, 0x16c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_msgbox_clk, "bus-r-msgbox",
> + &r_ahb_clk.common.hw, 0x17c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_uart0_clk, "bus-r-uart0",
> + &r_apb1_clk.common.hw, 0x18c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_uart1_clk, "bus-r-uart1",
> + &r_apb1_clk.common.hw, 0x18c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_i2c0_clk, "bus-r-i2c0",
> + &r_apb1_clk.common.hw, 0x19c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_i2c1_clk, "bus-r-i2c1",
> + &r_apb1_clk.common.hw, 0x19c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_i2c2_clk, "bus-r-i2c2",
> + &r_apb1_clk.common.hw, 0x19c, BIT(2), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_ppu0_clk, "bus-r-ppu0",
> + &r_apb0_clk.common.hw, 0x1ac, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_ppu1_clk, "bus-r-ppu1",
> + &r_apb0_clk.common.hw, 0x1ac, BIT(1), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_cpu_bist_clk, "bus-r-cpu-bist",
> + &r_apb0_clk.common.hw, 0x1bc, BIT(0), 0);
> +
> +static const struct clk_parent_data r_ir_rx_parents[] = {
> + { .fw_name = "losc" },
> + { .fw_name = "hosc" },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx",
> + r_ir_rx_parents, 0x1c0,
> + 0, 5, /* M */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static SUNXI_CCU_GATE_HW(bus_r_ir_rx_clk, "bus-r-ir-rx",
> + &r_apb0_clk.common.hw, 0x1cc, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HW(bus_r_dma_clk, "bus-r-dma",
> + &r_apb0_clk.common.hw, 0x1dc, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_rtc_clk, "bus-r-rtc",
> + &r_apb0_clk.common.hw, 0x20c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HW(bus_r_cpucfg_clk, "bus-r-cpucfg",
> + &r_apb0_clk.common.hw, 0x22c, BIT(0), 0);
> +
> +static struct ccu_common *sun55i_a523_r_ccu_clks[] = {
> + &r_ahb_clk.common,
> + &r_apb0_clk.common,
> + &r_apb1_clk.common,
> + &r_cpu_timer0.common,
> + &r_cpu_timer1.common,
> + &r_cpu_timer2.common,
> + &bus_r_timer_clk.common,
> + &bus_r_twd_clk.common,
> + &r_pwmctrl_clk.common,
> + &bus_r_pwmctrl_clk.common,
> + &bus_r_spi_clk.common,
> + &bus_r_spinlock_clk.common,
> + &bus_r_msgbox_clk.common,
> + &bus_r_uart0_clk.common,
> + &bus_r_uart1_clk.common,
> + &bus_r_i2c0_clk.common,
> + &bus_r_i2c1_clk.common,
> + &bus_r_i2c2_clk.common,
> + &bus_r_ppu0_clk.common,
> + &bus_r_ppu1_clk.common,
> + &bus_r_cpu_bist_clk.common,
> + &r_ir_rx_clk.common,
> + &bus_r_ir_rx_clk.common,
> + &bus_r_dma_clk.common,
> + &bus_r_rtc_clk.common,
> + &bus_r_cpucfg_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun55i_a523_r_hw_clks = {
> + .num = CLK_NUMBER,
> + .hws = {
> + [CLK_R_AHB] = &r_ahb_clk.common.hw,
> + [CLK_R_APB0] = &r_apb0_clk.common.hw,
> + [CLK_R_APB1] = &r_apb1_clk.common.hw,
> + [CLK_R_TIMER0] = &r_cpu_timer0.common.hw,
> + [CLK_R_TIMER1] = &r_cpu_timer1.common.hw,
> + [CLK_R_TIMER2] = &r_cpu_timer2.common.hw,
> + [CLK_BUS_R_TIMER] = &bus_r_timer_clk.common.hw,
> + [CLK_BUS_R_TWD] = &bus_r_twd_clk.common.hw,
> + [CLK_R_PWMCTRL] = &r_pwmctrl_clk.common.hw,
> + [CLK_BUS_R_PWMCTRL] = &bus_r_pwmctrl_clk.common.hw,
> + [CLK_BUS_R_SPI] = &bus_r_spi_clk.common.hw,
> + [CLK_BUS_R_SPINLOCK] = &bus_r_spinlock_clk.common.hw,
> + [CLK_BUS_R_MSGBOX] = &bus_r_msgbox_clk.common.hw,
> + [CLK_BUS_R_UART0] = &bus_r_uart0_clk.common.hw,
> + [CLK_BUS_R_UART1] = &bus_r_uart1_clk.common.hw,
> + [CLK_BUS_R_I2C0] = &bus_r_i2c0_clk.common.hw,
> + [CLK_BUS_R_I2C1] = &bus_r_i2c1_clk.common.hw,
> + [CLK_BUS_R_I2C2] = &bus_r_i2c2_clk.common.hw,
> + [CLK_BUS_R_PPU0] = &bus_r_ppu0_clk.common.hw,
> + [CLK_BUS_R_PPU1] = &bus_r_ppu1_clk.common.hw,
> + [CLK_BUS_R_CPU_BIST] = &bus_r_cpu_bist_clk.common.hw,
> + [CLK_R_IR_RX] = &r_ir_rx_clk.common.hw,
> + [CLK_BUS_R_IR_RX] = &bus_r_ir_rx_clk.common.hw,
> + [CLK_BUS_R_DMA] = &bus_r_dma_clk.common.hw,
> + [CLK_BUS_R_RTC] = &bus_r_rtc_clk.common.hw,
> + [CLK_BUS_R_CPUCFG] = &bus_r_cpucfg_clk.common.hw,
> + },
> +};
> +
> +static struct ccu_reset_map sun55i_a523_r_ccu_resets[] = {
> + [RST_BUS_R_TIMER] = { 0x11c, BIT(16) },
> + [RST_BUS_R_TWD] = { 0x12c, BIT(16) },
> + [RST_BUS_R_PWMCTRL] = { 0x13c, BIT(16) },
> + [RST_BUS_R_SPI] = { 0x15c, BIT(16) },
> + [RST_BUS_R_SPINLOCK] = { 0x16c, BIT(16) },
> + [RST_BUS_R_MSGBOX] = { 0x17c, BIT(16) },
> + [RST_BUS_R_UART0] = { 0x18c, BIT(16) },
> + [RST_BUS_R_UART1] = { 0x18c, BIT(17) },
> + [RST_BUS_R_I2C0] = { 0x19c, BIT(16) },
> + [RST_BUS_R_I2C1] = { 0x19c, BIT(17) },
> + [RST_BUS_R_I2C2] = { 0x19c, BIT(18) },
> + [RST_BUS_R_PPU1] = { 0x1ac, BIT(17) },
> + [RST_BUS_R_IR_RX] = { 0x1cc, BIT(16) },
> + [RST_BUS_R_RTC] = { 0x20c, BIT(16) },
> + [RST_BUS_R_CPUCFG] = { 0x22c, BIT(16) },
> +};
> +
> +static const struct sunxi_ccu_desc sun55i_a523_r_ccu_desc = {
> + .ccu_clks = sun55i_a523_r_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun55i_a523_r_ccu_clks),
> +
> + .hw_clks = &sun55i_a523_r_hw_clks,
> +
> + .resets = sun55i_a523_r_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun55i_a523_r_ccu_resets),
> +};
> +
> +static int sun55i_a523_r_ccu_probe(struct platform_device *pdev)
> +{
> + void __iomem *reg;
> +
> + reg = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_r_ccu_desc);
> +}
> +
> +static const struct of_device_id sun55i_a523_r_ccu_ids[] = {
> + { .compatible = "allwinner,sun55i-a523-r-ccu" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, sun55i_a523_r_ccu_ids);
> +
> +static struct platform_driver sun55i_a523_r_ccu_driver = {
> + .probe = sun55i_a523_r_ccu_probe,
> + .driver = {
> + .name = "sun55i-a523-r-ccu",
> + .suppress_bind_attrs = true,
> + .of_match_table = sun55i_a523_r_ccu_ids,
> + },
> +};
> +module_platform_driver(sun55i_a523_r_ccu_driver);
> +
> +MODULE_IMPORT_NS("SUNXI_CCU");
> +MODULE_DESCRIPTION("Support for the Allwinner A523 PRCM CCU");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
> new file mode 100644
> index 0000000000000..d50f46ac4f3fe
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2024 Arm Ltd.
> + */
> +
> +#ifndef _CCU_SUN55I_A523_R_H
> +#define _CCU_SUN55I_A523_R_H
> +
> +#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
> +#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
> +
> +#define CLK_NUMBER (CLK_BUS_R_CPUCFG + 1)
> +
> +#endif /* _CCU_SUN55I_A523_R_H */
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
2025-02-18 19:03 ` Jernej Škrabec
@ 2025-02-28 13:29 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 13:29 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 20:03:38 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi Jernej,
many thanks for having a look!
> Dne petek, 14. februar 2025 ob 13:53:49 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Add the PLL clocks of the main CCU of the Allwinner A523 and T527 SoCs.
> > The clocks were modelled after the A523 and T527 manual, and double
> > checked by writing all 1's into the respective register, to spot all
> > implemented bits.
> >
> > The PLL and mod clocks for the two CPU clusters and the DSU are part of
> > a separate CCU, also most audio clocks are collected in a DSP CCU, so
> > both of these clock groups are missing from this driver.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/Kconfig | 5 +
> > drivers/clk/sunxi-ng/Makefile | 2 +
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 481 +++++++++++++++++++++++++
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.h | 14 +
> > drivers/clk/sunxi-ng/ccu_mp.h | 14 +-
> > 5 files changed, 510 insertions(+), 6 deletions(-)
> > create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h
> >
> > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> > index b547198a2c654..04efbda847cf9 100644
> > --- a/drivers/clk/sunxi-ng/Kconfig
> > +++ b/drivers/clk/sunxi-ng/Kconfig
> > @@ -52,6 +52,11 @@ config SUN50I_H6_R_CCU
> > default y
> > depends on ARM64 || COMPILE_TEST
> >
> > +config SUN55I_A523_CCU
> > + tristate "Support for the Allwinner A523/T527 CCU"
> > + default y
> > + depends on ARM64 || COMPILE_TEST
> > +
> > config SUN4I_A10_CCU
> > tristate "Support for the Allwinner A10/A20 CCU"
> > default y
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index 6b3ae2b620db6..01a887f7824bb 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -33,6 +33,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
> > obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
> > obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
> > obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
> > +obj-$(CONFIG_SUN55I_A523_CCU) += sun55i-a523-ccu.o
> > obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
> > obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
> > obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
> > @@ -58,6 +59,7 @@ sun50i-a100-r-ccu-y += ccu-sun50i-a100-r.o
> > sun50i-h6-ccu-y += ccu-sun50i-h6.o
> > sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
> > sun50i-h616-ccu-y += ccu-sun50i-h616.o
> > +sun55i-a523-ccu-y += ccu-sun55i-a523.o
> > sun4i-a10-ccu-y += ccu-sun4i-a10.o
> > sun5i-ccu-y += ccu-sun5i.o
> > sun6i-a31-ccu-y += ccu-sun6i-a31.o
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > new file mode 100644
> > index 0000000000000..8374e841e9d82
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -0,0 +1,481 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2023-2024 Arm Ltd.
> > + * Based on the D1 CCU driver:
> > + * Copyright (c) 2020 huangzhenwei@allwinnertech.com
> > + * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +
> > +#include "../clk.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-sun55i-a523.h"
> > +
> > +/*
> > + * The 24 MHz oscillator, the root of most of the clock tree.
> > + * .fw_name is the string used in the DT "clock-names" property, used to
> > + * identify the corresponding clock in the "clocks" property.
> > + */
> > +static const struct clk_parent_data osc24M[] = {
> > + { .fw_name = "hosc" }
> > +};
> > +
> > +/**************************************************************************
> > + * PLLs *
> > + **************************************************************************/
> > +
> > +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
> > +#define SUN55I_A523_PLL_DDR0_REG 0x010
> > +static struct ccu_nkmp pll_ddr0_clk = {
> > + .enable = BIT(27),
> > + .lock = BIT(28),
> > + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> > + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>
> Newer manuals, for example A523 manual v1.4, don't mention input dividers anymore.
> Newer BSP driver doesn't have them either. Should we drop them (for all PLLs)?
I don't know, as you figured, I found them in my copy of the manual. For
the PLLs we need today (PLL_PERIPH0) it shouldn't matter anyway: it's
programmed already, and AFAICS Linux actually never reprograms it(?).
In any case, I just left it in for now: the bit is definitely there, I
verified that in U-Boot by only seeing half of the MMC performance with
bit 1 set. We can remove them anytime later, without issue, can't we?
Actually, thinking about that: the manual pretty clearly says that for
instance PLL_PERIPH0 should be set to 1.2GHz and never changed or even
touched. I wonder if we should honour this somehow in the code? It seems
like the CCF doesn't do this anyway at the moment, but it could, I guess?
>
> > + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
> > + .common = {
> > + .reg = 0x010,
> > + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M,
> > + &ccu_nkmp_ops,
> > + CLK_SET_RATE_GATE |
> > + CLK_IS_CRITICAL),
> > + },
> > +};
> > +
....
> > diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
> > index 687bd2ec798e2..5311835a4db60 100644
> > --- a/drivers/clk/sunxi-ng/ccu_mp.h
> > +++ b/drivers/clk/sunxi-ng/ccu_mp.h
> > @@ -100,20 +100,22 @@ struct ccu_mp {
>
> These changes doesn't belong in this commit.
Ah, indeed, I missed that. Moved that out into another patch now.
Cheers,
Andre
> Other than that, this looks like a good start. Thanks!
>
> Best regards,
> Jernej
>
> > _muxshift, _muxwidth, \
> > 0, _flags)
> >
> > -#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
> > +#define SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(_struct, _name, _parents, _reg, \
> > _mshift, _mwidth, \
> > _pshift, _pwidth, \
> > _muxshift, _muxwidth, \
> > - _gate, _flags, \
> > - _features) \
> > + _gate, _postdiv, \
> > + _flags, _features) \
> > struct ccu_mp _struct = { \
> > .enable = _gate, \
> > .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
> > .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
> > .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
> > + .fixed_post_div = _postdiv, \
> > .common = { \
> > .reg = _reg, \
> > - .features = _features, \
> > + .features = CCU_FEATURE_FIXED_POSTDIV | \
> > + _features, \
> > .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
> > _parents, \
> > &ccu_mp_ops,\
> > @@ -126,11 +128,11 @@ struct ccu_mp {
> > _pshift, _pwidth, \
> > _muxshift, _muxwidth, \
> > _gate, _flags) \
> > - SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, \
> > + SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(_struct, _name, _parents, \
> > _reg, _mshift, _mwidth, \
> > _pshift, _pwidth, \
> > _muxshift, _muxwidth, \
> > - _gate, _flags, 0)
> > + _gate, 1, _flags, 0)
> >
> > #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
> > _mshift, _mwidth, \
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks
2025-02-18 19:26 ` Jernej Škrabec
@ 2025-02-28 13:42 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 13:42 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 20:26:31 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
> Dne petek, 14. februar 2025 ob 13:53:51 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Add the clocks driving the various video subsystems of the SoC: the "DE"
> > display engine, the "DI" deinterlacer, the "G2D" 2D graphics system, the
> > Mali "GPU", the "VE" video engine, its associated IOMMU, as well as the
> > clocks for the various video output drivers (HDMI, DP, LCDs).
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 219 +++++++++++++++++++++++++
> > 1 file changed, 219 insertions(+)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > index 59f45e7c0904b..0ef1fd71a1ca5 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -364,6 +364,192 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
> > 24, 3, /* mux */
> > 0);
> >
> > +
> > +/**************************************************************************
> > + * mod clocks *
> > + **************************************************************************/
> > +
> > +static const struct clk_hw *de_parents[] = {
> > + &pll_periph0_300M_clk.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_video3_4x_clk.common.hw,
> > + &pll_video3_3x_clk.hw,
> > +};
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static const struct clk_hw *di_parents[] = {
> > + &pll_periph0_300M_clk.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_video0_4x_clk.common.hw,
> > + &pll_video1_4x_clk.common.hw,
> > +};
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static const struct clk_hw *g2d_parents[] = {
> > + &pll_periph0_400M_clk.hw,
> > + &pll_periph0_300M_clk.hw,
> > + &pll_video0_4x_clk.common.hw,
> > + &pll_video1_4x_clk.common.hw,
> > +};
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_hw *gpu_parents[] = {
> > + &pll_gpu_clk.common.hw,
> > + &pll_periph0_800M_clk.common.hw,
> > + &pll_periph0_600M_clk.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_periph0_300M_clk.hw,
> > + &pll_periph0_200M_clk.hw,
> > +};
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> > + 0, 4, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
>
> GPU clock should have CLK_SET_RATE_FLAG.
Yes indeed, fixed.
> > +
> > +static const struct clk_hw *ve_parents[] = {
> > + &pll_ve_clk.common.hw,
> > + &pll_periph0_480M_clk.common.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_periph0_300M_clk.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static const struct clk_parent_data iommu_parents[] = {
> > + { .hw = &pll_periph0_600M_clk.hw },
> > + { .hw = &pll_ddr0_clk.common.hw },
> > + { .hw = &pll_periph0_480M_clk.common.hw },
> > + { .hw = &pll_periph0_400M_clk.hw },
> > + { .hw = &pll_periph0_150M_clk.hw },
> > + { .fw_name = "hosc" },
> > +};
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
>
> This won't work. IOMMU clock has also update bit, which must be set to actually
> apply the new value, same as DDR clock.
Good point, I actually missed that. I now added a new feature flag in a
new patch to flag those clocks that need bit 27 set whenever we change
something. An update bitmask, defaulting to 0, sounds more elegant, but
gets tricky because we would need that in all those clock routines (gate,
div, mux), so hardcoding bit 27 behind a flag (which is already available
to all those functions) gives a much easier implementation. Feel free to
disagree on that new patch ;-)
> > +
> > +static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
> > +
> > +/* TODO: add mux between 32kOSC and PERIPH0/18750 */
>
> Not sure what this TODO means.
Mhh, I don't remember either, and cannot find 18750 anywhere in the
manuals. Maybe I forgot to remove this comment when implementing the below
clock? Just removed it.
> > +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
> > + pll_periph0_2x_hws,
> > + 0xb10, BIT(30), 36621, 0);
> > +
> > +static const struct clk_parent_data hdmi_cec_parents[] = {
> > + { .fw_name = "losc" },
> > + { .hw = &hdmi_cec_32k_clk.common.hw },
> > +};
> > +static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
> > + 0xb10,
> > + 24, 1, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_parent_data mipi_dsi_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_periph0_200M_clk.hw },
> > + { .hw = &pll_periph0_150M_clk.hw },
> > +};
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi0_clk, "mipi-dsi0",
> > + mipi_dsi_parents, 0xb24,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
> > + mipi_dsi_parents, 0xb28,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static const struct clk_hw *tcon_parents[] = {
> > + &pll_video0_4x_clk.common.hw,
> > + &pll_video1_4x_clk.common.hw,
> > + &pll_video2_4x_clk.common.hw,
> > + &pll_video3_4x_clk.common.hw,
> > + &pll_periph0_2x_clk.common.hw,
> > + &pll_video0_3x_clk.hw,
> > + &pll_video1_3x_clk.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
> > + 0xb60,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
> > + 0xb64,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
>
> Missing tcon-lcd2 - see T527 manual.
Thanks, I added this.
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi0_clk, "combophy-dsi0",
> > + tcon_parents, 0xb6c,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
> > + tcon_parents, 0xb70,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
> > + 0xb80,
> > + 0, 4, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
> > + 0xb84,
> > + 0, 4, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
>
> TCON TV0-1 parents are subset of others, according to T527 manual.
Nice catch, fixed.
> > +
> > +static const struct clk_hw *edp_parents[] = {
> > + &pll_video0_4x_clk.common.hw,
> > + &pll_video1_4x_clk.common.hw,
> > + &pll_video2_4x_clk.common.hw,
> > + &pll_video3_4x_clk.common.hw,
> > + &pll_periph0_2x_clk.common.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> > + 0, 4, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
>
> Missing CLK_SET_RATE_PARENT flag.
Yes, thanks, added.
Cheers,
Andre
>
> Best regards,
> Jernej
>
> > /*
> > * Contains all clocks that are controlled by a hardware register. They
> > * have a (sunxi) .common member, which needs to be initialised by the common
> > @@ -394,6 +580,22 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> > &ahb_clk.common,
> > &apb0_clk.common,
> > &apb1_clk.common,
> > + &de_clk.common,
> > + &di_clk.common,
> > + &g2d_clk.common,
> > + &gpu_clk.common,
> > + &ve_clk.common,
> > + &iommu_clk.common,
> > + &hdmi_24M_clk.common,
> > + &hdmi_cec_32k_clk.common,
> > + &hdmi_cec_clk.common,
> > + &mipi_dsi0_clk.common,
> > + &mipi_dsi1_clk.common,
> > + &tcon_lcd0_clk.common,
> > + &tcon_lcd1_clk.common,
> > + &tcon_tv0_clk.common,
> > + &tcon_tv1_clk.common,
> > + &edp_clk.common,
> > };
> >
> > static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > @@ -442,6 +644,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > [CLK_AHB] = &ahb_clk.common.hw,
> > [CLK_APB0] = &apb0_clk.common.hw,
> > [CLK_APB1] = &apb1_clk.common.hw,
> > + [CLK_DE] = &de_clk.common.hw,
> > + [CLK_DI] = &di_clk.common.hw,
> > + [CLK_G2D] = &g2d_clk.common.hw,
> > + [CLK_GPU] = &gpu_clk.common.hw,
> > + [CLK_VE] = &ve_clk.common.hw,
> > + [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> > + [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> > + [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
> > + [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
> > + [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
> > + [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
> > + [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
> > + [CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
> > + [CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
> > + [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> > + [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> > + [CLK_EDP] = &edp_clk.common.hw,
> > },
> > };
> >
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 08/15] clk: sunxi-ng: a523: add system mod clocks
2025-02-18 19:34 ` Jernej Škrabec
@ 2025-02-28 13:43 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 13:43 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 20:34:27 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
> Dne petek, 14. februar 2025 ob 13:53:52 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Add the clocks driving some core system related subsystems of the SoC:
> > the "CE" crypto engine, the high speed timers, the DRAM and the associated
> > MBUS clock, and the PCIe clock.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 119 +++++++++++++++++++++++++
> > 1 file changed, 119 insertions(+)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > index 0ef1fd71a1ca5..b68c44bce825f 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -423,6 +423,18 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> > BIT(31), /* gate */
> > 0);
> >
> > +static const struct clk_parent_data ce_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_periph0_480M_clk.common.hw },
> > + { .hw = &pll_periph0_400M_clk.hw },
> > + { .hw = &pll_periph0_300M_clk.hw },
> > +};
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > static const struct clk_hw *ve_parents[] = {
> > &pll_ve_clk.common.hw,
> > &pll_periph0_480M_clk.common.hw,
> > @@ -435,6 +447,65 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static const struct clk_parent_data hstimer_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .fw_name = "iosc" },
> > + { .fw_name = "losc" },
> > + { .hw = &pll_periph0_200M_clk.hw },
> > +};
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
> > + hstimer_parents, 0x730,
> > + 0, 0, /* M */
> > + 0, 3, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
>
> CLK_SET_RATE_PARENT doesn't make much sense for fixed clocks.
That's a very good point ;-)
Removed.
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
> > + hstimer_parents,
> > + 0x734,
> > + 0, 0, /* M */
> > + 0, 3, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
> > + hstimer_parents,
> > + 0x738,
> > + 0, 0, /* M */
> > + 0, 3, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
> > + hstimer_parents,
> > + 0x73c,
> > + 0, 0, /* M */
> > + 0, 3, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
> > + hstimer_parents,
> > + 0x740,
> > + 0, 0, /* M */
> > + 0, 3, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
> > + hstimer_parents,
> > + 0x744,
> > + 0, 0, /* M */
> > + 0, 3, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_SET_RATE_PARENT);
> > +
> > static const struct clk_parent_data iommu_parents[] = {
> > { .hw = &pll_periph0_600M_clk.hw },
> > { .hw = &pll_ddr0_clk.common.hw },
> > @@ -450,6 +521,34 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static const struct clk_hw *dram_parents[] = {
> > + &pll_ddr0_clk.common.hw,
> > + &pll_periph0_600M_clk.hw,
> > + &pll_periph0_480M_clk.common.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_periph0_150M_clk.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + CLK_IS_CRITICAL);
>
> Same comment as for IOMMU clock. Update bit is needed to actually apply configuration.
Fixed now.
Thanks!
Andre
>
> Best regards,
> Jernej
>
> > +
> > +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> > + &dram_clk.common.hw, 4, 1, 0);
> > +
> > +static const struct clk_parent_data losc_hosc_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .fw_name = "losc" },
> > +};
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
> > + losc_hosc_parents, 0xaa0,
> > + 0, 5, /* M */
> > + 24, 1, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
> >
> > /* TODO: add mux between 32kOSC and PERIPH0/18750 */
> > @@ -584,8 +683,17 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> > &di_clk.common,
> > &g2d_clk.common,
> > &gpu_clk.common,
> > + &ce_clk.common,
> > &ve_clk.common,
> > + &hstimer0_clk.common,
> > + &hstimer1_clk.common,
> > + &hstimer2_clk.common,
> > + &hstimer3_clk.common,
> > + &hstimer4_clk.common,
> > + &hstimer5_clk.common,
> > &iommu_clk.common,
> > + &dram_clk.common,
> > + &pcie_aux_clk.common,
> > &hdmi_24M_clk.common,
> > &hdmi_cec_32k_clk.common,
> > &hdmi_cec_clk.common,
> > @@ -644,11 +752,22 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > [CLK_AHB] = &ahb_clk.common.hw,
> > [CLK_APB0] = &apb0_clk.common.hw,
> > [CLK_APB1] = &apb1_clk.common.hw,
> > + [CLK_MBUS] = &mbus_clk.hw,
> > [CLK_DE] = &de_clk.common.hw,
> > [CLK_DI] = &di_clk.common.hw,
> > [CLK_G2D] = &g2d_clk.common.hw,
> > [CLK_GPU] = &gpu_clk.common.hw,
> > + [CLK_CE] = &ce_clk.common.hw,
> > [CLK_VE] = &ve_clk.common.hw,
> > + [CLK_HSTIMER0] = &hstimer0_clk.common.hw,
> > + [CLK_HSTIMER1] = &hstimer1_clk.common.hw,
> > + [CLK_HSTIMER2] = &hstimer2_clk.common.hw,
> > + [CLK_HSTIMER3] = &hstimer3_clk.common.hw,
> > + [CLK_HSTIMER4] = &hstimer4_clk.common.hw,
> > + [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> > + [CLK_IOMMU] = &iommu_clk.common.hw,
> > + [CLK_DRAM] = &dram_clk.common.hw,
> > + [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> > [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> > [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> > [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 09/15] clk: sunxi-ng: a523: add interface mod clocks
2025-02-18 19:42 ` Jernej Škrabec
@ 2025-02-28 13:46 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 13:46 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 20:42:48 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
many thanks for staying on this and digging into the details!
> Dne petek, 14. februar 2025 ob 13:53:53 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Add the clocks driving what the user manual summarises under "interface"
> > devices: raw NAND flash, MMC, SPI, EMAC, "IR" infrared, and the "GPADC"
> > general purpose analogue/digital converter.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 160 +++++++++++++++++++++++++
> > 1 file changed, 160 insertions(+)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > index b68c44bce825f..14d13fb16dfbb 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -113,6 +113,9 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
> > pll_periph0_2x_hws, 8, 1, 0);
> > static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
> > pll_periph0_480M_hws, 3, 1, 0);
> > +static const struct clk_hw *pll_periph0_150M_hws[] = {
> > + &pll_periph0_150M_clk.hw
> > +};
> >
> > #define SUN55I_A523_PLL_PERIPH1_REG 0x028
> > static struct ccu_nm pll_periph1_4x_clk = {
> > @@ -537,6 +540,133 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> > static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> > &dram_clk.common.hw, 4, 1, 0);
> >
> > +static const struct clk_parent_data nand_mmc_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_periph0_400M_clk.hw },
> > + { .hw = &pll_periph0_300M_clk.hw },
> > + { .hw = &pll_periph1_400M_clk.hw },
> > + { .hw = &pll_periph1_300M_clk.hw },
> > +};
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand0_clk, "nand0", nand_mmc_parents,
> > + 0x810,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
> > + 0x814,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
> > + 0x830,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 2, /* post div */
> > + 0, CCU_FEATURE_DUAL_DIV);
> > +
> > +static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc1_clk, "mmc1", nand_mmc_parents,
> > + 0x834,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 2, /* post div */
> > + 0, CCU_FEATURE_DUAL_DIV);
> > +
> > +static const struct clk_parent_data mmc2_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_periph0_800M_clk.common.hw },
> > + { .hw = &pll_periph0_600M_clk.hw },
> > + { .hw = &pll_periph1_800M_clk.common.hw },
> > + { .hw = &pll_periph1_600M_clk.hw },
> > +};
> > +
> > +static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
> > + 0x838,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 2, /* post div */
> > + 0, CCU_FEATURE_DUAL_DIV);
> > +
> > +static const struct clk_parent_data spi_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_periph0_300M_clk.hw },
> > + { .hw = &pll_periph0_200M_clk.hw },
> > + { .hw = &pll_periph1_300M_clk.hw },
> > + { .hw = &pll_periph1_200M_clk.hw },
> > +};
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
> > + 0x950,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
>
> Missing CCU_FEATURE_DUAL_DIV flag.
Oh, indeed, for all SPI clocks, nice catch! I introduced a new macro
for this type of clocks now: SUNXI_CCU_DUALDIV_MUX_GATE.
Cheers,
Andre
> Best regards,
> Jernej
>
> > +
> > +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> > + pll_periph0_150M_hws,
> > + 0x970, BIT(31) | BIT(30), 6, 0);
> > +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
> > + pll_periph0_150M_hws,
> > + 0x974, BIT(31) | BIT(30), 6, 0);
> > +
> > +static const struct clk_parent_data ir_rx_parents[] = {
> > + { .fw_name = "losc" },
> > + { .fw_name = "hosc" },
> > +};
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
> > + 0, 5, /* M */
> > + 24, 1, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +static const struct clk_parent_data ir_tx_ledc_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_periph1_600M_clk.hw },
> > +};
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
> > + 0x9c0,
> > + 0, 5, /* M */
> > + 24, 1, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
> > + 0, 5, /* M */
> > + BIT(31), /* gate */
> > + 0);
> > +static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
> > + 0, 5, /* M */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > static const struct clk_parent_data losc_hosc_parents[] = {
> > { .fw_name = "hosc" },
> > { .fw_name = "losc" },
> > @@ -693,6 +823,21 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> > &hstimer5_clk.common,
> > &iommu_clk.common,
> > &dram_clk.common,
> > + &nand0_clk.common,
> > + &nand1_clk.common,
> > + &mmc0_clk.common,
> > + &mmc1_clk.common,
> > + &mmc2_clk.common,
> > + &spi0_clk.common,
> > + &spi1_clk.common,
> > + &spi2_clk.common,
> > + &spifc_clk.common,
> > + &emac0_25M_clk.common,
> > + &emac1_25M_clk.common,
> > + &ir_rx_clk.common,
> > + &ir_tx_clk.common,
> > + &gpadc0_clk.common,
> > + &gpadc1_clk.common,
> > &pcie_aux_clk.common,
> > &hdmi_24M_clk.common,
> > &hdmi_cec_32k_clk.common,
> > @@ -767,6 +912,21 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> > [CLK_IOMMU] = &iommu_clk.common.hw,
> > [CLK_DRAM] = &dram_clk.common.hw,
> > + [CLK_NAND0] = &nand0_clk.common.hw,
> > + [CLK_NAND1] = &nand1_clk.common.hw,
> > + [CLK_MMC0] = &mmc0_clk.common.hw,
> > + [CLK_MMC1] = &mmc1_clk.common.hw,
> > + [CLK_MMC2] = &mmc2_clk.common.hw,
> > + [CLK_SPI0] = &spi0_clk.common.hw,
> > + [CLK_SPI1] = &spi1_clk.common.hw,
> > + [CLK_SPI2] = &spi2_clk.common.hw,
> > + [CLK_SPIFC] = &spifc_clk.common.hw,
> > + [CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
> > + [CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
> > + [CLK_IR_RX] = &ir_rx_clk.common.hw,
> > + [CLK_IR_TX] = &ir_tx_clk.common.hw,
> > + [CLK_GPADC0] = &gpadc0_clk.common.hw,
> > + [CLK_GPADC1] = &gpadc1_clk.common.hw,
> > [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> > [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> > [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 11/15] clk: sunxi-ng: a523: remaining mod clocks
2025-02-18 19:55 ` Jernej Škrabec
@ 2025-02-28 13:50 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 13:50 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 20:55:34 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
> Dne petek, 14. februar 2025 ob 13:53:55 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Add the remaining mod clocks, driving various parts of the SoC: the "LEDC"
> > LED controller, the "CSI" camera interface, the "ISP" image processor,
> > the DSP clock, and the "fanout" clocks, which allow to put clock signals
> > on external pins.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 190 +++++++++++++++++++++++++
> > 1 file changed, 190 insertions(+)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > index 59cc31f89ae77..6a4340f1fd041 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -354,6 +354,7 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
> > 0, 5, /* M */
> > 24, 2, /* mux */
> > 0);
> > +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
> >
> > static const struct clk_parent_data apb1_parents[] = {
> > { .fw_name = "hosc" },
> > @@ -832,6 +833,153 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> > + 0xbf0,
> > + 0, 4, /* M */
> > + 24, 1, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_hw *csi_top_parents[] = {
> > + &pll_periph0_300M_clk.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_periph0_480M_clk.common.hw,
> > + &pll_video3_4x_clk.common.hw,
> > + &pll_video3_3x_clk.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents,
> > + 0xc04,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_parent_data csi_mclk_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .hw = &pll_video3_4x_clk.common.hw },
> > + { .hw = &pll_video0_4x_clk.common.hw },
> > + { .hw = &pll_video1_4x_clk.common.hw },
> > + { .hw = &pll_video2_4x_clk.common.hw },
> > +};
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0",
> > + csi_mclk_parents, 0xc08,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
>
> Missing dual div flag for csi-mclk clocks.
Nice one, another case for the new macro ...
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1",
> > + csi_mclk_parents, 0xc0c,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2",
> > + csi_mclk_parents, 0xc10,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
> > + csi_mclk_parents, 0xc14,
> > + 0, 5, /* M */
> > + 8, 5, /* P */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_hw *isp_parents[] = {
> > + &pll_periph0_300M_clk.hw,
> > + &pll_periph0_400M_clk.hw,
> > + &pll_video2_4x_clk.common.hw,
> > + &pll_video3_4x_clk.common.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(isp_clk, "isp", isp_parents, 0xc20,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_parent_data dsp_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .fw_name = "losc" },
> > + { .fw_name = "iosc" },
> > + { .hw = &pll_periph0_2x_clk.common.hw },
> > + { .hw = &pll_periph0_400M_clk.hw, },
>
> Last one should be pll_periph0_480M_clk.
Right, spotting the difference between an 8 and a 0 earns you some extra
points! Fixed.
>
> > +};
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> > + 0xf30, BIT(0), 0);
> > +static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> > + 0xf30, BIT(1), 2, 0);
> > +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M",
> > + pll_periph0_480M_hws,
> > + 0xf30, BIT(2), 30, 0);
> > +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M",
> > + pll_periph0_2x_hws,
> > + 0xf30, BIT(3), 48, 0);
> > +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_50M_clk, "fanout-50M",
> > + pll_periph0_2x_hws,
> > + 0xf30, BIT(4), 24, 0);
> > +
> > +/* These clocks have a second divider that is not modelled and forced to 0. */
>
> Any specific reason for that?
Laziness? Being annoyed about Allwinner doing those random changes without
good reason? I sighed audibly, then added a new macro that uses the dual
divider feature. This allows us to get rid of the initialisation of those
registers below.
Thanks for poking into this ;-)
Cheers,
Andre
> Best regards,
> Jernej
>
> > +#define SUN55I_A523_FANOUT_27M_REG 0xf34
> > +static const struct clk_hw *fanout_27M_parents[] = {
> > + &pll_video0_4x_clk.common.hw,
> > + &pll_video1_4x_clk.common.hw,
> > + &pll_video2_4x_clk.common.hw,
> > + &pll_video3_4x_clk.common.hw,
> > +};
> > +static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M",
> > + fanout_27M_parents, 0xf34,
> > + 0, 5, /* M */
> > + 24, 2, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +#define SUN55I_A523_FANOUT_PCLK_REG 0xf38
> > +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws,
> > + 0xf38,
> > + 0, 5, /* M */
> > + BIT(31), /* gate */
> > + 0);
> > +
> > +static const struct clk_parent_data fanout_parents[] = {
> > + { .fw_name = "osc32k-out" },
> > + { .hw = &fanout_12M_clk.common.hw, },
> > + { .hw = &fanout_16M_clk.common.hw, },
> > + { .hw = &fanout_24M_clk.common.hw, },
> > + { .hw = &fanout_25M_clk.common.hw, },
> > + { .hw = &fanout_27M_clk.common.hw, },
> > + { .hw = &fanout_pclk_clk.common.hw, },
> > + { .hw = &fanout_50M_clk.common.hw, },
> > +};
> > +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents,
> > + 0xf3c,
> > + 0, 3, /* mux */
> > + BIT(21), /* gate */
> > + 0);
> > +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents,
> > + 0xf3c,
> > + 3, 3, /* mux */
> > + BIT(22), /* gate */
> > + 0);
> > +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents,
> > + 0xf3c,
> > + 6, 3, /* mux */
> > + BIT(23), /* gate */
> > + 0);
> > +
> > /*
> > * Contains all clocks that are controlled by a hardware register. They
> > * have a (sunxi) .common member, which needs to be initialised by the common
> > @@ -904,6 +1052,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> > &tcon_tv0_clk.common,
> > &tcon_tv1_clk.common,
> > &edp_clk.common,
> > + &ledc_clk.common,
> > + &csi_top_clk.common,
> > + &csi_mclk0_clk.common,
> > + &csi_mclk1_clk.common,
> > + &csi_mclk2_clk.common,
> > + &csi_mclk3_clk.common,
> > + &isp_clk.common,
> > + &dsp_clk.common,
> > + &fanout_24M_clk.common,
> > + &fanout_12M_clk.common,
> > + &fanout_16M_clk.common,
> > + &fanout_25M_clk.common,
> > + &fanout_27M_clk.common,
> > + &fanout_pclk_clk.common,
> > + &fanout0_clk.common,
> > + &fanout1_clk.common,
> > + &fanout2_clk.common,
> > };
> >
> > static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > @@ -997,6 +1162,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> > [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> > [CLK_EDP] = &edp_clk.common.hw,
> > + [CLK_LEDC] = &ledc_clk.common.hw,
> > + [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> > + [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> > + [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> > + [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> > + [CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
> > + [CLK_ISP] = &isp_clk.common.hw,
> > + [CLK_DSP] = &dsp_clk.common.hw,
> > + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> > + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> > + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
> > + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
> > + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
> > + [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
> > + [CLK_FANOUT0] = &fanout0_clk.common.hw,
> > + [CLK_FANOUT1] = &fanout1_clk.common.hw,
> > + [CLK_FANOUT2] = &fanout2_clk.common.hw,
> > },
> > };
> >
> > @@ -1048,6 +1230,14 @@ static int sun55i_a523_ccu_probe(struct platform_device *pdev)
> > val &= ~(BIT(1) | BIT(0));
> > writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
> >
> > + /* Force fanout factors N to 0. */
> > + val = readl(reg + SUN55I_A523_FANOUT_27M_REG);
> > + val &= ~GENMASK(12, 8);
> > + writel(val, reg + SUN55I_A523_FANOUT_27M_REG);
> > + val = readl(reg + SUN55I_A523_FANOUT_PCLK_REG);
> > + val &= ~GENMASK(9, 5);
> > + writel(val, reg + SUN55I_A523_FANOUT_PCLK_REG);
> > +
> > ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
> > if (ret)
> > return ret;
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates
2025-02-18 20:12 ` Jernej Škrabec
@ 2025-02-28 14:04 ` Andre Przywara
2025-02-28 14:41 ` Jernej Škrabec
0 siblings, 1 reply; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 14:04 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 21:12:33 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
> Dne petek, 14. februar 2025 ob 13:53:56 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Add the various bus clock gates that control access to the devices'
> > register interface.
> > These clocks are each just one bit, typically the lower bits in some "BGR"
> > (Bus Gate / Reset) registers, for each device group: one for all UARTs,
> > one for all SPI interfaces, and so on.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 295 ++++++++++++++++++++++++-
> > 1 file changed, 294 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > index 6a4340f1fd041..fbed9b2b3b2f9 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -350,6 +350,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
> > 0, 5, /* M */
> > 24, 2, /* mux */
> > 0);
> > +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
> > +
> > static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
> > 0, 5, /* M */
> > 24, 2, /* mux */
> > @@ -367,10 +369,11 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
> > 0, 5, /* M */
> > 24, 3, /* mux */
> > 0);
> > +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
> >
> >
> > /**************************************************************************
> > - * mod clocks *
> > + * mod clocks with gates *
> > **************************************************************************/
> >
> > static const struct clk_hw *de_parents[] = {
> > @@ -386,6 +389,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
> > +
> > static const struct clk_hw *di_parents[] = {
> > &pll_periph0_300M_clk.hw,
> > &pll_periph0_400M_clk.hw,
> > @@ -399,6 +404,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
> > +
> > static const struct clk_hw *g2d_parents[] = {
> > &pll_periph0_400M_clk.hw,
> > &pll_periph0_300M_clk.hw,
> > @@ -412,6 +419,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
> > +
> > static const struct clk_hw *gpu_parents[] = {
> > &pll_gpu_clk.common.hw,
> > &pll_periph0_800M_clk.common.hw,
> > @@ -427,6 +436,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
> > +
> > static const struct clk_parent_data ce_parents[] = {
> > { .fw_name = "hosc" },
> > { .hw = &pll_periph0_480M_clk.common.hw },
> > @@ -439,6 +450,10 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
> > + BIT(1), 0);
> > +
> > static const struct clk_hw *ve_parents[] = {
> > &pll_ve_clk.common.hw,
> > &pll_periph0_480M_clk.common.hw,
> > @@ -451,6 +466,16 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
> > + BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
> > + BIT(0), 0);
>
> msgbox and spinlock probably needs to be marked as critical? Crust needs that
> for communication with TF-A.
Do they? I don't see this being done on any of the other SoCs that use
crust?
I would like to leave it like this for now, we can fix this later (and
backport to stable) if we need so, I think?
>
> > +
> > static const struct clk_parent_data hstimer_parents[] = {
> > { .fw_name = "hosc" },
> > { .fw_name = "iosc" },
> > @@ -510,6 +535,15 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
> > + BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
> > + BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
> > +
> > static const struct clk_parent_data iommu_parents[] = {
> > { .hw = &pll_periph0_600M_clk.hw },
> > { .hw = &pll_ddr0_clk.common.hw },
> > @@ -525,6 +559,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
> > + BIT(0), 0);
> > +
> > static const struct clk_hw *dram_parents[] = {
> > &pll_ddr0_clk.common.hw,
> > &pll_periph0_600M_clk.hw,
> > @@ -541,6 +578,22 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> > static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> > &dram_clk.common.hw, 4, 1, 0);
> >
> > +static SUNXI_CCU_GATE_HW(mbus_dma_clk, "mbus-dma", &mbus_clk.hw,
> > + 0x804, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(mbus_ve_clk, "mbus-ve", &mbus_clk.hw,
> > + 0x804, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HW(mbus_ce_clk, "mbus-ce", &mbus_clk.hw,
> > + 0x804, BIT(2), 0);
> > +static SUNXI_CCU_GATE_HW(mbus_nand_clk, "mbus-nand", &mbus_clk.hw,
> > + 0x804, BIT(5), 0);
> > +static SUNXI_CCU_GATE_HW(mbus_usb3_clk, "mbus-usb3", &mbus_clk.hw,
> > + 0x804, BIT(6), 0);
> > +static SUNXI_CCU_GATE_HW(mbus_csi_clk, "mbus-csi", &mbus_clk.hw,
> > + 0x804, BIT(8), 0);
>
> Missing several MBUS gates. Check T527 manual.
Right, I added isp and gmac1. I did not model the bits in the upper half,
I don't understand what they are for, really, and they are enabled on
reset.
>
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
> > + BIT(0), CLK_IS_CRITICAL);
> > +
> > static const struct clk_parent_data nand_mmc_parents[] = {
> > { .fw_name = "hosc" },
> > { .hw = &pll_periph0_400M_clk.hw },
> > @@ -563,6 +616,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
> > + BIT(0), 0);
> > +
> > static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
> > 0x830,
> > 0, 5, /* M */
> > @@ -598,6 +654,39 @@ static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
> > 2, /* post div */
> > 0, CCU_FEATURE_DUAL_DIV);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
> > + BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
> > + BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
> > + BIT(1), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
> > + BIT(2), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
> > + BIT(3), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
> > + BIT(4), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
> > + BIT(5), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
> > + BIT(6), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
> > + BIT(7), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
> > +
> > static const struct clk_parent_data spi_parents[] = {
> > { .fw_name = "hosc" },
> > { .hw = &pll_periph0_300M_clk.hw },
> > @@ -630,6 +719,11 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
> > 24, 3, /* mux */
> > BIT(31), /* gate */
> > 0);
> > +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
> > + BIT(3), 0);
> >
> > static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> > pll_periph0_150M_hws,
> > @@ -637,6 +731,10 @@ static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> > static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
> > pll_periph0_150M_hws,
> > 0x974, BIT(31) | BIT(30), 6, 0);
> > +static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
> > + BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
> > + BIT(0), 0);
> >
> > static const struct clk_parent_data ir_rx_parents[] = {
> > { .fw_name = "losc" },
> > @@ -648,6 +746,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
> > 24, 1, /* mux */
> > BIT(31), /* gate */
> > 0);
> > +static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
> > + BIT(0), 0);
> > +
> > static const struct clk_parent_data ir_tx_ledc_parents[] = {
> > { .fw_name = "hosc" },
> > { .hw = &pll_periph1_600M_clk.hw },
> > @@ -658,6 +759,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
> > 24, 1, /* mux */
> > BIT(31), /* gate */
> > 0);
> > +static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
> > + BIT(0), 0);
> >
> > static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
> > 0, 5, /* M */
> > @@ -667,6 +770,12 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
> > 0, 5, /* M */
> > BIT(31), /* gate */
> > 0);
> > +static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
> > + BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
> > + BIT(1), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
> >
> > /*
> > * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
> > @@ -720,6 +829,18 @@ static struct ccu_mux usb_ohci1_clk = {
> > },
> > };
> >
> > +static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
> > + BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
> > + BIT(1), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
> > + BIT(4), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
> > + BIT(5), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
> > + BIT(0), 0);
> >
> > static const struct clk_parent_data losc_hosc_parents[] = {
> > { .fw_name = "hosc" },
> > @@ -733,6 +854,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws, 0xabc,
> > + BIT(0), 0);
> > +
> > static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
> >
> > /* TODO: add mux between 32kOSC and PERIPH0/18750 */
> > @@ -750,6 +874,8 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
> > +
> > static const struct clk_parent_data mipi_dsi_parents[] = {
> > { .fw_name = "hosc" },
> > { .hw = &pll_periph0_200M_clk.hw },
> > @@ -769,6 +895,12 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
> > + BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
> > + BIT(1), 0);
> > +
> > static const struct clk_hw *tcon_parents[] = {
> > &pll_video0_4x_clk.common.hw,
> > &pll_video1_4x_clk.common.hw,
> > @@ -806,6 +938,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
> > + BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
> > + BIT(1), 0);
>
> Missing gate for bus-tcon-lcd2.
Right, added now.
>
> > +
> > static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
> > 0xb80,
> > 0, 4, /* M */
> > @@ -820,6 +957,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
> > BIT(31), /* gate */
> > CLK_SET_RATE_PARENT);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
> > + BIT(0), 0);
> > +static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
> > + BIT(1), 0);
> > +
> > static const struct clk_hw *edp_parents[] = {
> > &pll_video0_4x_clk.common.hw,
> > &pll_video1_4x_clk.common.hw,
> > @@ -833,6 +975,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
> > +
> > static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> > 0xbf0,
> > 0, 4, /* M */
> > @@ -840,6 +984,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
> > +
> > static const struct clk_hw *csi_top_parents[] = {
> > &pll_periph0_300M_clk.hw,
> > &pll_periph0_400M_clk.hw,
> > @@ -893,6 +1039,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
> > +
> > static const struct clk_hw *isp_parents[] = {
> > &pll_periph0_300M_clk.hw,
> > &pll_periph0_400M_clk.hw,
> > @@ -918,6 +1066,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
> > BIT(31), /* gate */
> > 0);
> >
> > +static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk, "bus-dsp-cfg", ahb_hws, 0xc7c,
> > + BIT(1), 0);
>
> I don't see 0xc7c register.
Mmh, good point, I thought I saw this in some BSP drop, this "cfg" suffix
hints at this also. But poking it in U-Boot again indeed reveals it's not
implemented, the whole register is WI/RAZ.
Removed that.
Thanks!
Andre
> > +
> > static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> > 0xf30, BIT(0), 0);
> > static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> > @@ -1011,55 +1162,128 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> > &apb0_clk.common,
> > &apb1_clk.common,
> > &de_clk.common,
> > + &bus_de_clk.common,
> > &di_clk.common,
> > + &bus_di_clk.common,
> > &g2d_clk.common,
> > + &bus_g2d_clk.common,
> > &gpu_clk.common,
> > + &bus_gpu_clk.common,
> > &ce_clk.common,
> > + &bus_ce_clk.common,
> > + &bus_ce_sys_clk.common,
> > &ve_clk.common,
> > + &bus_ve_clk.common,
> > + &bus_dma_clk.common,
> > + &bus_msgbox_clk.common,
> > + &bus_spinlock_clk.common,
> > &hstimer0_clk.common,
> > &hstimer1_clk.common,
> > &hstimer2_clk.common,
> > &hstimer3_clk.common,
> > &hstimer4_clk.common,
> > &hstimer5_clk.common,
> > + &bus_hstimer_clk.common,
> > + &bus_dbg_clk.common,
> > + &bus_pwm0_clk.common,
> > + &bus_pwm1_clk.common,
> > &iommu_clk.common,
> > + &bus_iommu_clk.common,
> > &dram_clk.common,
> > + &mbus_dma_clk.common,
> > + &mbus_ve_clk.common,
> > + &mbus_ce_clk.common,
> > + &mbus_nand_clk.common,
> > + &mbus_usb3_clk.common,
> > + &mbus_csi_clk.common,
> > + &bus_dram_clk.common,
> > &nand0_clk.common,
> > &nand1_clk.common,
> > + &bus_nand_clk.common,
> > &mmc0_clk.common,
> > &mmc1_clk.common,
> > &mmc2_clk.common,
> > + &bus_sysdap_clk.common,
> > + &bus_mmc0_clk.common,
> > + &bus_mmc1_clk.common,
> > + &bus_mmc2_clk.common,
> > + &bus_uart0_clk.common,
> > + &bus_uart1_clk.common,
> > + &bus_uart2_clk.common,
> > + &bus_uart3_clk.common,
> > + &bus_uart4_clk.common,
> > + &bus_uart5_clk.common,
> > + &bus_uart6_clk.common,
> > + &bus_uart7_clk.common,
> > + &bus_i2c0_clk.common,
> > + &bus_i2c1_clk.common,
> > + &bus_i2c2_clk.common,
> > + &bus_i2c3_clk.common,
> > + &bus_i2c4_clk.common,
> > + &bus_i2c5_clk.common,
> > + &bus_can_clk.common,
> > &spi0_clk.common,
> > &spi1_clk.common,
> > &spi2_clk.common,
> > &spifc_clk.common,
> > + &bus_spi0_clk.common,
> > + &bus_spi1_clk.common,
> > + &bus_spi2_clk.common,
> > + &bus_spifc_clk.common,
> > &emac0_25M_clk.common,
> > &emac1_25M_clk.common,
> > + &bus_emac0_clk.common,
> > + &bus_emac1_clk.common,
> > &ir_rx_clk.common,
> > + &bus_ir_rx_clk.common,
> > &ir_tx_clk.common,
> > + &bus_ir_tx_clk.common,
> > &gpadc0_clk.common,
> > &gpadc1_clk.common,
> > + &bus_gpadc0_clk.common,
> > + &bus_gpadc1_clk.common,
> > + &bus_ths_clk.common,
> > &usb_ohci0_clk.common,
> > &usb_ohci1_clk.common,
> > + &bus_ohci0_clk.common,
> > + &bus_ohci1_clk.common,
> > + &bus_ehci0_clk.common,
> > + &bus_ehci1_clk.common,
> > + &bus_otg_clk.common,
> > + &bus_lradc_clk.common,
> > &pcie_aux_clk.common,
> > + &bus_dpss_top_clk.common,
> > &hdmi_24M_clk.common,
> > &hdmi_cec_32k_clk.common,
> > &hdmi_cec_clk.common,
> > + &bus_hdmi_clk.common,
> > &mipi_dsi0_clk.common,
> > &mipi_dsi1_clk.common,
> > + &bus_mipi_dsi0_clk.common,
> > + &bus_mipi_dsi1_clk.common,
> > &tcon_lcd0_clk.common,
> > &tcon_lcd1_clk.common,
> > + &combophy_dsi0_clk.common,
> > + &combophy_dsi1_clk.common,
> > + &bus_tcon_lcd0_clk.common,
> > + &bus_tcon_lcd1_clk.common,
> > &tcon_tv0_clk.common,
> > &tcon_tv1_clk.common,
> > + &bus_tcon_tv0_clk.common,
> > + &bus_tcon_tv1_clk.common,
> > &edp_clk.common,
> > + &bus_edp_clk.common,
> > &ledc_clk.common,
> > + &bus_ledc_clk.common,
> > &csi_top_clk.common,
> > &csi_mclk0_clk.common,
> > &csi_mclk1_clk.common,
> > &csi_mclk2_clk.common,
> > &csi_mclk3_clk.common,
> > + &bus_csi_clk.common,
> > &isp_clk.common,
> > &dsp_clk.common,
> > + &bus_dsp_cfg_clk.common,
> > &fanout_24M_clk.common,
> > &fanout_12M_clk.common,
> > &fanout_16M_clk.common,
> > @@ -1119,57 +1343,126 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > [CLK_APB1] = &apb1_clk.common.hw,
> > [CLK_MBUS] = &mbus_clk.hw,
> > [CLK_DE] = &de_clk.common.hw,
> > + [CLK_BUS_DE] = &bus_de_clk.common.hw,
> > [CLK_DI] = &di_clk.common.hw,
> > + [CLK_BUS_DI] = &bus_di_clk.common.hw,
> > [CLK_G2D] = &g2d_clk.common.hw,
> > + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
> > [CLK_GPU] = &gpu_clk.common.hw,
> > + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
> > [CLK_CE] = &ce_clk.common.hw,
> > + [CLK_BUS_CE] = &bus_ce_clk.common.hw,
> > + [CLK_BUS_CE_SYS] = &bus_ce_sys_clk.common.hw,
> > [CLK_VE] = &ve_clk.common.hw,
> > + [CLK_BUS_VE] = &bus_ve_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_HSTIMER0] = &hstimer0_clk.common.hw,
> > [CLK_HSTIMER1] = &hstimer1_clk.common.hw,
> > [CLK_HSTIMER2] = &hstimer2_clk.common.hw,
> > [CLK_HSTIMER3] = &hstimer3_clk.common.hw,
> > [CLK_HSTIMER4] = &hstimer4_clk.common.hw,
> > [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> > + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
> > + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
> > + [CLK_BUS_PWM0] = &bus_pwm0_clk.common.hw,
> > + [CLK_BUS_PWM1] = &bus_pwm1_clk.common.hw,
> > [CLK_IOMMU] = &iommu_clk.common.hw,
> > + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
> > [CLK_DRAM] = &dram_clk.common.hw,
> > + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
> > + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
> > + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
> > + [CLK_MBUS_CSI] = &mbus_csi_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_MMC2] = &mmc2_clk.common.hw,
> > + [CLK_BUS_SYSDAP] = &bus_sysdap_clk.common.hw,
> > + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
> > + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
> > + [CLK_BUS_MMC2] = &bus_mmc2_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_UART4] = &bus_uart4_clk.common.hw,
> > + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
> > + [CLK_BUS_UART6] = &bus_uart6_clk.common.hw,
> > + [CLK_BUS_UART7] = &bus_uart7_clk.common.hw,
> > + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
> > + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
> > + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
> > + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
> > + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
> > + [CLK_BUS_I2C5] = &bus_i2c5_clk.common.hw,
> > + [CLK_BUS_CAN] = &bus_can_clk.common.hw,
> > [CLK_SPI0] = &spi0_clk.common.hw,
> > [CLK_SPI1] = &spi1_clk.common.hw,
> > [CLK_SPI2] = &spi2_clk.common.hw,
> > [CLK_SPIFC] = &spifc_clk.common.hw,
> > + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
> > + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
> > + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
> > + [CLK_BUS_SPIFC] = &bus_spifc_clk.common.hw,
> > [CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
> > [CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
> > + [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
> > + [CLK_BUS_EMAC1] = &bus_emac1_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_GPADC0] = &gpadc0_clk.common.hw,
> > [CLK_GPADC1] = &gpadc1_clk.common.hw,
> > + [CLK_BUS_GPADC0] = &bus_gpadc0_clk.common.hw,
> > + [CLK_BUS_GPADC1] = &bus_gpadc1_clk.common.hw,
> > + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
> > [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
> > [CLK_USB_OHCI1] = &usb_ohci1_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_EHCI1] = &bus_ehci1_clk.common.hw,
> > + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
> > + [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw,
> > [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> > + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
> > [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> > [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> > [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
> > + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
> > [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
> > [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
> > + [CLK_BUS_MIPI_DSI0] = &bus_mipi_dsi0_clk.common.hw,
> > + [CLK_BUS_MIPI_DSI1] = &bus_mipi_dsi1_clk.common.hw,
> > [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
> > [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
> > [CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
> > [CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
> > + [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw,
> > + [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw,
> > [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> > [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> > + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
> > + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
> > [CLK_EDP] = &edp_clk.common.hw,
> > + [CLK_BUS_EDP] = &bus_edp_clk.common.hw,
> > [CLK_LEDC] = &ledc_clk.common.hw,
> > + [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw,
> > [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> > [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> > [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> > [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> > [CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
> > + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
> > [CLK_ISP] = &isp_clk.common.hw,
> > [CLK_DSP] = &dsp_clk.common.hw,
> > + [CLK_BUS_DSP_CFG] = &bus_dsp_cfg_clk.common.hw,
> > [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> > [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> > [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines
2025-02-18 20:29 ` Jernej Škrabec
@ 2025-02-28 14:21 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 14:21 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 21:29:37 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
> Dne petek, 14. februar 2025 ob 13:53:57 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > Allwinner SoCs do not contain a separate reset controller, instead the
> > reset lines for the various devices are integrated into the "BGR" (Bus
> > Gate / Reset) registers, for each device group: one for all UARTs, one
> > for all SPI interfaces, and so on.
> > The Allwinner CCU driver also doubles as a reset provider, and since the
> > reset lines are indeed just single bits in those BGR register, we can
> > represent them easily in an array of structs, just containing the
> > register offset and the bit number.
> >
> > Add the location of the reset bits for all devices in the A523/T527
> > SoCs, using the existing sunxi CCU infrastructure.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 83 ++++++++++++++++++++++++++
> > 1 file changed, 83 insertions(+)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > index fbed9b2b3b2f9..d57565f07a112 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > @@ -1475,11 +1475,94 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > },
> > };
> >
> > +static struct ccu_reset_map sun55i_a523_ccu_resets[] = {
> > + [RST_MBUS] = { 0x540, BIT(30) },
> > + [RST_BUS_NSI] = { 0x54c, BIT(16) },
> > + [RST_BUS_DE] = { 0x60c, BIT(16) },
> > + [RST_BUS_DI] = { 0x62c, BIT(16) },
> > + [RST_BUS_G2D] = { 0x63c, BIT(16) },
> > + [RST_BUS_SYS] = { 0x64c, BIT(16) },
> > + [RST_BUS_GPU] = { 0x67c, BIT(16) },
> > + [RST_BUS_CE] = { 0x68c, BIT(16) },
> > + [RST_BUS_SYS_CE] = { 0x68c, BIT(17) },
> > + [RST_BUS_VE] = { 0x69c, BIT(16) },
> > + [RST_BUS_DMA] = { 0x70c, BIT(16) },
> > + [RST_BUS_MSGBOX] = { 0x71c, BIT(16) },
> > + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
> > + [RST_BUS_CPUXTIMER] = { 0x74c, BIT(16) },
> > + [RST_BUS_DBG] = { 0x78c, BIT(16) },
> > + [RST_BUS_PWM0] = { 0x7ac, BIT(16) },
> > + [RST_BUS_PWM1] = { 0x7ac, BIT(17) },
> > + [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_MMC2] = { 0x84c, BIT(18) },
> > + [RST_BUS_SYSDAP] = { 0x88c, BIT(16) },
> > + [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_UART4] = { 0x90c, BIT(20) },
> > + [RST_BUS_UART5] = { 0x90c, BIT(21) },
> > + [RST_BUS_UART6] = { 0x90c, BIT(22) },
> > + [RST_BUS_UART7] = { 0x90c, BIT(23) },
> > + [RST_BUS_I2C0] = { 0x91c, BIT(16) },
> > + [RST_BUS_I2C1] = { 0x91c, BIT(17) },
> > + [RST_BUS_I2C2] = { 0x91c, BIT(18) },
> > + [RST_BUS_I2C3] = { 0x91c, BIT(19) },
> > + [RST_BUS_I2C4] = { 0x91c, BIT(20) },
> > + [RST_BUS_I2C5] = { 0x91c, BIT(21) },
> > + [RST_BUS_CAN] = { 0x92c, BIT(16) },
> > + [RST_BUS_SPI0] = { 0x96c, BIT(16) },
> > + [RST_BUS_SPI1] = { 0x96c, BIT(17) },
> > + [RST_BUS_SPI2] = { 0x96c, BIT(18) },
> > + [RST_BUS_SPIFC] = { 0x96c, BIT(19) },
> > + [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
> > + [RST_BUS_EMAC1] = { 0x98c, BIT(16) | BIT(17) }, /* GMAC1-AXI */
>
> GMAC AXI reset should be separate.
I see where you are coming from, but what would be the advantage,
really? At the moment the generic STMMAC code and binding only knows
about one reset line, so we would need to add support for a second line
first, potentially even in generic code, but without any real win, I think.
On the other hand the reset struct supports a bit mask already, so
toggling both bits at the same time seems perfectly fine.
So to make things easier, I thought we should take advantage of that,
and having one line covering both bits. There is only one clock gate
bit for GMAC1 as well.
And I know this isn't a good argument, but the BSP does it like this as well ;-)
>
> > + [RST_BUS_IR_RX] = { 0x99c, BIT(16) },
> > + [RST_BUS_IR_TX] = { 0x9cc, BIT(16) },
> > + [RST_BUS_GPADC0] = { 0x9ec, BIT(16) },
> > + [RST_BUS_GPADC1] = { 0x9ec, BIT(17) },
> > + [RST_BUS_THS] = { 0x9fc, 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_EHCI1] = { 0xa8c, BIT(21) },
> > + [RST_BUS_OTG] = { 0xa8c, BIT(24) },
> > + [RST_BUS_3] = { 0xa8c, BIT(25) }, /* BSP + register */
> > + [RST_BUS_LRADC] = { 0xa9c, BIT(16) },
> > + [RST_BUS_PCIE_USB3] = { 0xaac, BIT(16) },
> > + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
>
> Docs say that there is extra display top reset at 0xacc.
Right, also the name is better there: RST_BUS_DISPLAY[01]. Fixed that.
Cheers,
Andre
>
> > + [RST_BUS_HDMI_MAIN] = { 0xb1c, BIT(16) },
> > + [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
> > + [RST_BUS_MIPI_DSI0] = { 0xb4c, BIT(16) },
> > + [RST_BUS_MIPI_DSI1] = { 0xb4c, BIT(17) },
> > + [RST_BUS_TCON_LCD0] = { 0xb7c, BIT(16) },
> > + [RST_BUS_TCON_LCD1] = { 0xb7c, BIT(17) },
> > + [RST_BUS_TCON_LCD2] = { 0xb7c, BIT(18) },
> > + [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
> > + [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
> > + [RST_BUS_LVDS0] = { 0xbac, BIT(16) },
> > + [RST_BUS_LVDS1] = { 0xbac, BIT(17) },
> > + [RST_BUS_EDP] = { 0xbbc, BIT(16) },
> > + [RST_BUS_VIDEO_OUT0] = { 0xbcc, BIT(16) },
> > + [RST_BUS_VIDEO_OUT1] = { 0xbcc, BIT(17) },
> > + [RST_BUS_LEDC] = { 0xbfc, BIT(16) },
> > + [RST_BUS_CSI] = { 0xc1c, BIT(16) },
> > + [RST_BUS_ISP] = { 0xc2c, BIT(16) }, /* BSP + register */
> > +};
> > +
> > static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
> > .ccu_clks = sun55i_a523_ccu_clks,
> > .num_ccu_clks = ARRAY_SIZE(sun55i_a523_ccu_clks),
> >
> > .hw_clks = &sun55i_a523_hw_clks,
> > +
> > + .resets = sun55i_a523_ccu_resets,
> > + .num_resets = ARRAY_SIZE(sun55i_a523_ccu_resets),
> > };
> >
> > static const u32 pll_regs[] = {
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
2025-02-18 20:42 ` Jernej Škrabec
@ 2025-02-28 14:33 ` Andre Przywara
0 siblings, 0 replies; 38+ messages in thread
From: Andre Przywara @ 2025-02-28 14:33 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
On Tue, 18 Feb 2025 21:42:06 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi,
> Dne petek, 14. februar 2025 ob 13:53:59 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > The A523/T527 SoCs have clock/reset controls in the PRCM part, like many
> > previous SoCs. For a change, the whole PRCM is documented in the A523
> > manual, including the system bus tree, so we can describe all those
> > clocks correctly based on that. There layout seems to be derived from
> > the H6 and H616 PRCM CCUs, though there are more clocks, and many clocks
> > have subtly changed.
> >
> > Describe all the mod and gate clocks, including the three bus clocks
> > (R_AHB, R_APB0, and R_APB1).
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/clk/sunxi-ng/Kconfig | 5 +
> > drivers/clk/sunxi-ng/Makefile | 2 +
> > drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c | 245 +++++++++++++++++++++++
> > drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h | 14 ++
> > 4 files changed, 266 insertions(+)
> > create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
> > create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
> >
> > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> > index 04efbda847cf9..5830a9d87bf25 100644
> > --- a/drivers/clk/sunxi-ng/Kconfig
> > +++ b/drivers/clk/sunxi-ng/Kconfig
> > @@ -57,6 +57,11 @@ config SUN55I_A523_CCU
> > default y
> > depends on ARM64 || COMPILE_TEST
> >
> > +config SUN55I_A523_R_CCU
> > + tristate "Support for the Allwinner A523/T527 PRCM CCU"
> > + default y
> > + depends on ARM64 || COMPILE_TEST
> > +
> > config SUN4I_A10_CCU
> > tristate "Support for the Allwinner A10/A20 CCU"
> > default y
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index 01a887f7824bb..82e471036de69 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -34,6 +34,7 @@ obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
> > obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
> > obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
> > obj-$(CONFIG_SUN55I_A523_CCU) += sun55i-a523-ccu.o
> > +obj-$(CONFIG_SUN55I_A523_R_CCU) += sun55i-a523-r-ccu.o
> > obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
> > obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
> > obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
> > @@ -60,6 +61,7 @@ sun50i-h6-ccu-y += ccu-sun50i-h6.o
> > sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
> > sun50i-h616-ccu-y += ccu-sun50i-h616.o
> > sun55i-a523-ccu-y += ccu-sun55i-a523.o
> > +sun55i-a523-r-ccu-y += ccu-sun55i-a523-r.o
> > sun4i-a10-ccu-y += ccu-sun4i-a10.o
> > sun5i-ccu-y += ccu-sun5i.o
> > sun6i-a31-ccu-y += ccu-sun6i-a31.o
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
> > new file mode 100644
> > index 0000000000000..0dafc38370f22
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
> > @@ -0,0 +1,245 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2024 Arm Ltd.
> > + * Based on the D1 CCU driver:
> > + * Copyright (c) 2020 huangzhenwei@allwinnertech.com
> > + * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +
> > +#include "ccu_common.h"
> > +#include "ccu_reset.h"
> > +
> > +#include "ccu_gate.h"
> > +#include "ccu_mp.h"
> > +
> > +#include "ccu-sun55i-a523-r.h"
> > +
> > +static const struct clk_parent_data r_ahb_apb_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .fw_name = "losc" },
> > + { .fw_name = "iosc" },
> > + { .fw_name = "pll-periph" },
> > + { .fw_name = "pll-audio" },
>
> I believe pll-periph has /3 divider and pll-audio x4 multiplier.
Well, it's actually worse, since the audio PLL is the one from the MCU
CCU (PLL_AUDIO1), which we don't support yet.
But those are just the names used in the DT, should they actually reflect
the dividers and multipliers in their string?
> > +};
> > +static SUNXI_CCU_M_DATA_WITH_MUX(r_ahb_clk, "r-ahb",
> > + r_ahb_apb_parents, 0x000,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + 0);
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX(r_apb0_clk, "r-apb0",
> > + r_ahb_apb_parents, 0x00c,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + 0);
> > +
> > +static SUNXI_CCU_M_DATA_WITH_MUX(r_apb1_clk, "r-apb1",
> > + r_ahb_apb_parents, 0x010,
> > + 0, 5, /* M */
> > + 24, 3, /* mux */
> > + 0);
> > +
> > +static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
> > + r_ahb_apb_parents, 0x100,
> > + 1, 3, /* P */
> > + 4, 3, /* mux */
> > + BIT(0),
> > + 0);
> > +static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
> > + r_ahb_apb_parents, 0x104,
> > + 1, 3, /* P */
> > + 4, 3, /* mux */
> > + BIT(0),
> > + 0);
> > +static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
> > + r_ahb_apb_parents, 0x108,
> > + 1, 3, /* P */
> > + 4, 3, /* mux */
> > + BIT(0),
> > + 0);
> > +
> > +static SUNXI_CCU_GATE_HW(bus_r_timer_clk, "bus-r-timer", &r_ahb_clk.common.hw,
> > + 0x11c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_twd_clk, "bus-r-twd", &r_apb0_clk.common.hw,
> > + 0x12c, BIT(0), 0);
> > +
> > +static const struct clk_parent_data r_pwmctrl_parents[] = {
> > + { .fw_name = "hosc" },
> > + { .fw_name = "losc" },
> > + { .fw_name = "iosc" },
> > +};
> > +static SUNXI_CCU_MUX_DATA_WITH_GATE(r_pwmctrl_clk, "r-pwmctrl",
> > + r_pwmctrl_parents, 0x130,
> > + 24, 1, /* mux */
>
> Mux width is 2.
Thanks, fixed.
>
> > + BIT(31),
> > + 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_pwmctrl_clk, "bus-r-pwmctrl",
> > + &r_apb0_clk.common.hw, 0x13c, BIT(0), 0);
> > +
> > +/* SPI clock is /M/N (same as new MMC?) */
>
> Missing SPI clock (reg 0x150).
I deliberately left that out, since its parent list is annoyingly insane,
and includes that PLL_AUDIO1 which we don't support yet. I reserved a
symbol for it, but was wondering if we could add it later?
Cheers,
Andre
>
> > +static SUNXI_CCU_GATE_HW(bus_r_spi_clk, "bus-r-spi",
> > + &r_ahb_clk.common.hw, 0x15c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_spinlock_clk, "bus-r-spinlock",
> > + &r_ahb_clk.common.hw, 0x16c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_msgbox_clk, "bus-r-msgbox",
> > + &r_ahb_clk.common.hw, 0x17c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_uart0_clk, "bus-r-uart0",
> > + &r_apb1_clk.common.hw, 0x18c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_uart1_clk, "bus-r-uart1",
> > + &r_apb1_clk.common.hw, 0x18c, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_i2c0_clk, "bus-r-i2c0",
> > + &r_apb1_clk.common.hw, 0x19c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_i2c1_clk, "bus-r-i2c1",
> > + &r_apb1_clk.common.hw, 0x19c, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_i2c2_clk, "bus-r-i2c2",
> > + &r_apb1_clk.common.hw, 0x19c, BIT(2), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_ppu0_clk, "bus-r-ppu0",
> > + &r_apb0_clk.common.hw, 0x1ac, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_ppu1_clk, "bus-r-ppu1",
> > + &r_apb0_clk.common.hw, 0x1ac, BIT(1), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_cpu_bist_clk, "bus-r-cpu-bist",
> > + &r_apb0_clk.common.hw, 0x1bc, BIT(0), 0);
> > +
> > +static const struct clk_parent_data r_ir_rx_parents[] = {
> > + { .fw_name = "losc" },
> > + { .fw_name = "hosc" },
> > +};
> > +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx",
> > + r_ir_rx_parents, 0x1c0,
> > + 0, 5, /* M */
> > + 24, 2, /* mux */
> > + BIT(31), /* gate */
> > + 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_ir_rx_clk, "bus-r-ir-rx",
> > + &r_apb0_clk.common.hw, 0x1cc, BIT(0), 0);
> > +
> > +static SUNXI_CCU_GATE_HW(bus_r_dma_clk, "bus-r-dma",
> > + &r_apb0_clk.common.hw, 0x1dc, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_rtc_clk, "bus-r-rtc",
> > + &r_apb0_clk.common.hw, 0x20c, BIT(0), 0);
> > +static SUNXI_CCU_GATE_HW(bus_r_cpucfg_clk, "bus-r-cpucfg",
> > + &r_apb0_clk.common.hw, 0x22c, BIT(0), 0);
> > +
> > +static struct ccu_common *sun55i_a523_r_ccu_clks[] = {
> > + &r_ahb_clk.common,
> > + &r_apb0_clk.common,
> > + &r_apb1_clk.common,
> > + &r_cpu_timer0.common,
> > + &r_cpu_timer1.common,
> > + &r_cpu_timer2.common,
> > + &bus_r_timer_clk.common,
> > + &bus_r_twd_clk.common,
> > + &r_pwmctrl_clk.common,
> > + &bus_r_pwmctrl_clk.common,
> > + &bus_r_spi_clk.common,
> > + &bus_r_spinlock_clk.common,
> > + &bus_r_msgbox_clk.common,
> > + &bus_r_uart0_clk.common,
> > + &bus_r_uart1_clk.common,
> > + &bus_r_i2c0_clk.common,
> > + &bus_r_i2c1_clk.common,
> > + &bus_r_i2c2_clk.common,
> > + &bus_r_ppu0_clk.common,
> > + &bus_r_ppu1_clk.common,
> > + &bus_r_cpu_bist_clk.common,
> > + &r_ir_rx_clk.common,
> > + &bus_r_ir_rx_clk.common,
> > + &bus_r_dma_clk.common,
> > + &bus_r_rtc_clk.common,
> > + &bus_r_cpucfg_clk.common,
> > +};
> > +
> > +static struct clk_hw_onecell_data sun55i_a523_r_hw_clks = {
> > + .num = CLK_NUMBER,
> > + .hws = {
> > + [CLK_R_AHB] = &r_ahb_clk.common.hw,
> > + [CLK_R_APB0] = &r_apb0_clk.common.hw,
> > + [CLK_R_APB1] = &r_apb1_clk.common.hw,
> > + [CLK_R_TIMER0] = &r_cpu_timer0.common.hw,
> > + [CLK_R_TIMER1] = &r_cpu_timer1.common.hw,
> > + [CLK_R_TIMER2] = &r_cpu_timer2.common.hw,
> > + [CLK_BUS_R_TIMER] = &bus_r_timer_clk.common.hw,
> > + [CLK_BUS_R_TWD] = &bus_r_twd_clk.common.hw,
> > + [CLK_R_PWMCTRL] = &r_pwmctrl_clk.common.hw,
> > + [CLK_BUS_R_PWMCTRL] = &bus_r_pwmctrl_clk.common.hw,
> > + [CLK_BUS_R_SPI] = &bus_r_spi_clk.common.hw,
> > + [CLK_BUS_R_SPINLOCK] = &bus_r_spinlock_clk.common.hw,
> > + [CLK_BUS_R_MSGBOX] = &bus_r_msgbox_clk.common.hw,
> > + [CLK_BUS_R_UART0] = &bus_r_uart0_clk.common.hw,
> > + [CLK_BUS_R_UART1] = &bus_r_uart1_clk.common.hw,
> > + [CLK_BUS_R_I2C0] = &bus_r_i2c0_clk.common.hw,
> > + [CLK_BUS_R_I2C1] = &bus_r_i2c1_clk.common.hw,
> > + [CLK_BUS_R_I2C2] = &bus_r_i2c2_clk.common.hw,
> > + [CLK_BUS_R_PPU0] = &bus_r_ppu0_clk.common.hw,
> > + [CLK_BUS_R_PPU1] = &bus_r_ppu1_clk.common.hw,
> > + [CLK_BUS_R_CPU_BIST] = &bus_r_cpu_bist_clk.common.hw,
> > + [CLK_R_IR_RX] = &r_ir_rx_clk.common.hw,
> > + [CLK_BUS_R_IR_RX] = &bus_r_ir_rx_clk.common.hw,
> > + [CLK_BUS_R_DMA] = &bus_r_dma_clk.common.hw,
> > + [CLK_BUS_R_RTC] = &bus_r_rtc_clk.common.hw,
> > + [CLK_BUS_R_CPUCFG] = &bus_r_cpucfg_clk.common.hw,
> > + },
> > +};
> > +
> > +static struct ccu_reset_map sun55i_a523_r_ccu_resets[] = {
> > + [RST_BUS_R_TIMER] = { 0x11c, BIT(16) },
> > + [RST_BUS_R_TWD] = { 0x12c, BIT(16) },
> > + [RST_BUS_R_PWMCTRL] = { 0x13c, BIT(16) },
> > + [RST_BUS_R_SPI] = { 0x15c, BIT(16) },
> > + [RST_BUS_R_SPINLOCK] = { 0x16c, BIT(16) },
> > + [RST_BUS_R_MSGBOX] = { 0x17c, BIT(16) },
> > + [RST_BUS_R_UART0] = { 0x18c, BIT(16) },
> > + [RST_BUS_R_UART1] = { 0x18c, BIT(17) },
> > + [RST_BUS_R_I2C0] = { 0x19c, BIT(16) },
> > + [RST_BUS_R_I2C1] = { 0x19c, BIT(17) },
> > + [RST_BUS_R_I2C2] = { 0x19c, BIT(18) },
> > + [RST_BUS_R_PPU1] = { 0x1ac, BIT(17) },
> > + [RST_BUS_R_IR_RX] = { 0x1cc, BIT(16) },
> > + [RST_BUS_R_RTC] = { 0x20c, BIT(16) },
> > + [RST_BUS_R_CPUCFG] = { 0x22c, BIT(16) },
> > +};
> > +
> > +static const struct sunxi_ccu_desc sun55i_a523_r_ccu_desc = {
> > + .ccu_clks = sun55i_a523_r_ccu_clks,
> > + .num_ccu_clks = ARRAY_SIZE(sun55i_a523_r_ccu_clks),
> > +
> > + .hw_clks = &sun55i_a523_r_hw_clks,
> > +
> > + .resets = sun55i_a523_r_ccu_resets,
> > + .num_resets = ARRAY_SIZE(sun55i_a523_r_ccu_resets),
> > +};
> > +
> > +static int sun55i_a523_r_ccu_probe(struct platform_device *pdev)
> > +{
> > + void __iomem *reg;
> > +
> > + reg = devm_platform_ioremap_resource(pdev, 0);
> > + if (IS_ERR(reg))
> > + return PTR_ERR(reg);
> > +
> > + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_r_ccu_desc);
> > +}
> > +
> > +static const struct of_device_id sun55i_a523_r_ccu_ids[] = {
> > + { .compatible = "allwinner,sun55i-a523-r-ccu" },
> > + { }
> > +};
> > +MODULE_DEVICE_TABLE(of, sun55i_a523_r_ccu_ids);
> > +
> > +static struct platform_driver sun55i_a523_r_ccu_driver = {
> > + .probe = sun55i_a523_r_ccu_probe,
> > + .driver = {
> > + .name = "sun55i-a523-r-ccu",
> > + .suppress_bind_attrs = true,
> > + .of_match_table = sun55i_a523_r_ccu_ids,
> > + },
> > +};
> > +module_platform_driver(sun55i_a523_r_ccu_driver);
> > +
> > +MODULE_IMPORT_NS("SUNXI_CCU");
> > +MODULE_DESCRIPTION("Support for the Allwinner A523 PRCM CCU");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
> > new file mode 100644
> > index 0000000000000..d50f46ac4f3fe
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
> > @@ -0,0 +1,14 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright 2024 Arm Ltd.
> > + */
> > +
> > +#ifndef _CCU_SUN55I_A523_R_H
> > +#define _CCU_SUN55I_A523_R_H
> > +
> > +#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
> > +#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
> > +
> > +#define CLK_NUMBER (CLK_BUS_R_CPUCFG + 1)
> > +
> > +#endif /* _CCU_SUN55I_A523_R_H */
> >
>
>
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates
2025-02-28 14:04 ` Andre Przywara
@ 2025-02-28 14:41 ` Jernej Škrabec
0 siblings, 0 replies; 38+ messages in thread
From: Jernej Škrabec @ 2025-02-28 14:41 UTC (permalink / raw)
To: Andre Przywara
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Samuel Holland, Philipp Zabel,
linux-clk, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
Dne petek, 28. februar 2025 ob 15:04:58 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> On Tue, 18 Feb 2025 21:12:33 +0100
> Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
>
> Hi,
>
> > Dne petek, 14. februar 2025 ob 13:53:56 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > > Add the various bus clock gates that control access to the devices'
> > > register interface.
> > > These clocks are each just one bit, typically the lower bits in some "BGR"
> > > (Bus Gate / Reset) registers, for each device group: one for all UARTs,
> > > one for all SPI interfaces, and so on.
> > >
> > > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > > ---
> > > drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 295 ++++++++++++++++++++++++-
> > > 1 file changed, 294 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > > index 6a4340f1fd041..fbed9b2b3b2f9 100644
> > > --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > > +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
> > > @@ -350,6 +350,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
> > > 0, 5, /* M */
> > > 24, 2, /* mux */
> > > 0);
> > > +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
> > > +
> > > static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
> > > 0, 5, /* M */
> > > 24, 2, /* mux */
> > > @@ -367,10 +369,11 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
> > > 0, 5, /* M */
> > > 24, 3, /* mux */
> > > 0);
> > > +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
> > >
> > >
> > > /**************************************************************************
> > > - * mod clocks *
> > > + * mod clocks with gates *
> > > **************************************************************************/
> > >
> > > static const struct clk_hw *de_parents[] = {
> > > @@ -386,6 +389,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
> > > +
> > > static const struct clk_hw *di_parents[] = {
> > > &pll_periph0_300M_clk.hw,
> > > &pll_periph0_400M_clk.hw,
> > > @@ -399,6 +404,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
> > > +
> > > static const struct clk_hw *g2d_parents[] = {
> > > &pll_periph0_400M_clk.hw,
> > > &pll_periph0_300M_clk.hw,
> > > @@ -412,6 +419,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
> > > +
> > > static const struct clk_hw *gpu_parents[] = {
> > > &pll_gpu_clk.common.hw,
> > > &pll_periph0_800M_clk.common.hw,
> > > @@ -427,6 +436,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
> > > +
> > > static const struct clk_parent_data ce_parents[] = {
> > > { .fw_name = "hosc" },
> > > { .hw = &pll_periph0_480M_clk.common.hw },
> > > @@ -439,6 +450,10 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
> > > + BIT(1), 0);
> > > +
> > > static const struct clk_hw *ve_parents[] = {
> > > &pll_ve_clk.common.hw,
> > > &pll_periph0_480M_clk.common.hw,
> > > @@ -451,6 +466,16 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
> > > + BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
> > > + BIT(0), 0);
> >
> > msgbox and spinlock probably needs to be marked as critical? Crust needs that
> > for communication with TF-A.
>
> Do they? I don't see this being done on any of the other SoCs that use
> crust?
> I would like to leave it like this for now, we can fix this later (and
> backport to stable) if we need so, I think?
Sure, it can be changed later.
>
> >
> > > +
> > > static const struct clk_parent_data hstimer_parents[] = {
> > > { .fw_name = "hosc" },
> > > { .fw_name = "iosc" },
> > > @@ -510,6 +535,15 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
> > > + BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
> > > + BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
> > > +
> > > static const struct clk_parent_data iommu_parents[] = {
> > > { .hw = &pll_periph0_600M_clk.hw },
> > > { .hw = &pll_ddr0_clk.common.hw },
> > > @@ -525,6 +559,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(iommu_clk, "iommu", iommu_parents, 0x7b0,
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
> > > + BIT(0), 0);
> > > +
> > > static const struct clk_hw *dram_parents[] = {
> > > &pll_ddr0_clk.common.hw,
> > > &pll_periph0_600M_clk.hw,
> > > @@ -541,6 +578,22 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> > > static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> > > &dram_clk.common.hw, 4, 1, 0);
> > >
> > > +static SUNXI_CCU_GATE_HW(mbus_dma_clk, "mbus-dma", &mbus_clk.hw,
> > > + 0x804, BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HW(mbus_ve_clk, "mbus-ve", &mbus_clk.hw,
> > > + 0x804, BIT(1), 0);
> > > +static SUNXI_CCU_GATE_HW(mbus_ce_clk, "mbus-ce", &mbus_clk.hw,
> > > + 0x804, BIT(2), 0);
> > > +static SUNXI_CCU_GATE_HW(mbus_nand_clk, "mbus-nand", &mbus_clk.hw,
> > > + 0x804, BIT(5), 0);
> > > +static SUNXI_CCU_GATE_HW(mbus_usb3_clk, "mbus-usb3", &mbus_clk.hw,
> > > + 0x804, BIT(6), 0);
> > > +static SUNXI_CCU_GATE_HW(mbus_csi_clk, "mbus-csi", &mbus_clk.hw,
> > > + 0x804, BIT(8), 0);
> >
> > Missing several MBUS gates. Check T527 manual.
>
> Right, I added isp and gmac1. I did not model the bits in the upper half,
> I don't understand what they are for, really, and they are enabled on
> reset.
Ok. BSP actually switches them, but they can be coupled together, if needed.
Best regards,
Jernej
>
> >
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
> > > + BIT(0), CLK_IS_CRITICAL);
> > > +
> > > static const struct clk_parent_data nand_mmc_parents[] = {
> > > { .fw_name = "hosc" },
> > > { .hw = &pll_periph0_400M_clk.hw },
> > > @@ -563,6 +616,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
> > > + BIT(0), 0);
> > > +
> > > static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc0_clk, "mmc0", nand_mmc_parents,
> > > 0x830,
> > > 0, 5, /* M */
> > > @@ -598,6 +654,39 @@ static SUNXI_CCU_MP_MUX_GATE_POSTDIV_FEAT(mmc2_clk, "mmc2", mmc2_parents,
> > > 2, /* post div */
> > > 0, CCU_FEATURE_DUAL_DIV);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
> > > + BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
> > > + BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
> > > + BIT(1), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
> > > + BIT(2), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
> > > + BIT(3), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
> > > + BIT(4), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
> > > + BIT(5), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
> > > + BIT(6), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
> > > + BIT(7), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
> > > +
> > > static const struct clk_parent_data spi_parents[] = {
> > > { .fw_name = "hosc" },
> > > { .hw = &pll_periph0_300M_clk.hw },
> > > @@ -630,6 +719,11 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents,
> > > 24, 3, /* mux */
> > > BIT(31), /* gate */
> > > 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
> > > + BIT(3), 0);
> > >
> > > static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> > > pll_periph0_150M_hws,
> > > @@ -637,6 +731,10 @@ static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
> > > static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
> > > pll_periph0_150M_hws,
> > > 0x974, BIT(31) | BIT(30), 6, 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
> > > + BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
> > > + BIT(0), 0);
> > >
> > > static const struct clk_parent_data ir_rx_parents[] = {
> > > { .fw_name = "losc" },
> > > @@ -648,6 +746,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
> > > 24, 1, /* mux */
> > > BIT(31), /* gate */
> > > 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
> > > + BIT(0), 0);
> > > +
> > > static const struct clk_parent_data ir_tx_ledc_parents[] = {
> > > { .fw_name = "hosc" },
> > > { .hw = &pll_periph1_600M_clk.hw },
> > > @@ -658,6 +759,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
> > > 24, 1, /* mux */
> > > BIT(31), /* gate */
> > > 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
> > > + BIT(0), 0);
> > >
> > > static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
> > > 0, 5, /* M */
> > > @@ -667,6 +770,12 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
> > > 0, 5, /* M */
> > > BIT(31), /* gate */
> > > 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
> > > + BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
> > > + BIT(1), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
> > >
> > > /*
> > > * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
> > > @@ -720,6 +829,18 @@ static struct ccu_mux usb_ohci1_clk = {
> > > },
> > > };
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
> > > + BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
> > > + BIT(1), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
> > > + BIT(4), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
> > > + BIT(5), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
> > > + BIT(0), 0);
> > >
> > > static const struct clk_parent_data losc_hosc_parents[] = {
> > > { .fw_name = "hosc" },
> > > @@ -733,6 +854,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws, 0xabc,
> > > + BIT(0), 0);
> > > +
> > > static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
> > >
> > > /* TODO: add mux between 32kOSC and PERIPH0/18750 */
> > > @@ -750,6 +874,8 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
> > > +
> > > static const struct clk_parent_data mipi_dsi_parents[] = {
> > > { .fw_name = "hosc" },
> > > { .hw = &pll_periph0_200M_clk.hw },
> > > @@ -769,6 +895,12 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
> > > + BIT(0), 0);
> > > +
> > > +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
> > > + BIT(1), 0);
> > > +
> > > static const struct clk_hw *tcon_parents[] = {
> > > &pll_video0_4x_clk.common.hw,
> > > &pll_video1_4x_clk.common.hw,
> > > @@ -806,6 +938,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
> > > + BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
> > > + BIT(1), 0);
> >
> > Missing gate for bus-tcon-lcd2.
>
> Right, added now.
>
> >
> > > +
> > > static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
> > > 0xb80,
> > > 0, 4, /* M */
> > > @@ -820,6 +957,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
> > > BIT(31), /* gate */
> > > CLK_SET_RATE_PARENT);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
> > > + BIT(0), 0);
> > > +static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
> > > + BIT(1), 0);
> > > +
> > > static const struct clk_hw *edp_parents[] = {
> > > &pll_video0_4x_clk.common.hw,
> > > &pll_video1_4x_clk.common.hw,
> > > @@ -833,6 +975,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
> > > +
> > > static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> > > 0xbf0,
> > > 0, 4, /* M */
> > > @@ -840,6 +984,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
> > > +
> > > static const struct clk_hw *csi_top_parents[] = {
> > > &pll_periph0_300M_clk.hw,
> > > &pll_periph0_400M_clk.hw,
> > > @@ -893,6 +1039,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(csi_mclk3_clk, "csi-mclk3",
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
> > > +
> > > static const struct clk_hw *isp_parents[] = {
> > > &pll_periph0_300M_clk.hw,
> > > &pll_periph0_400M_clk.hw,
> > > @@ -918,6 +1066,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
> > > BIT(31), /* gate */
> > > 0);
> > >
> > > +static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk, "bus-dsp-cfg", ahb_hws, 0xc7c,
> > > + BIT(1), 0);
> >
> > I don't see 0xc7c register.
>
> Mmh, good point, I thought I saw this in some BSP drop, this "cfg" suffix
> hints at this also. But poking it in U-Boot again indeed reveals it's not
> implemented, the whole register is WI/RAZ.
> Removed that.
>
> Thanks!
> Andre
>
> > > +
> > > static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> > > 0xf30, BIT(0), 0);
> > > static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> > > @@ -1011,55 +1162,128 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
> > > &apb0_clk.common,
> > > &apb1_clk.common,
> > > &de_clk.common,
> > > + &bus_de_clk.common,
> > > &di_clk.common,
> > > + &bus_di_clk.common,
> > > &g2d_clk.common,
> > > + &bus_g2d_clk.common,
> > > &gpu_clk.common,
> > > + &bus_gpu_clk.common,
> > > &ce_clk.common,
> > > + &bus_ce_clk.common,
> > > + &bus_ce_sys_clk.common,
> > > &ve_clk.common,
> > > + &bus_ve_clk.common,
> > > + &bus_dma_clk.common,
> > > + &bus_msgbox_clk.common,
> > > + &bus_spinlock_clk.common,
> > > &hstimer0_clk.common,
> > > &hstimer1_clk.common,
> > > &hstimer2_clk.common,
> > > &hstimer3_clk.common,
> > > &hstimer4_clk.common,
> > > &hstimer5_clk.common,
> > > + &bus_hstimer_clk.common,
> > > + &bus_dbg_clk.common,
> > > + &bus_pwm0_clk.common,
> > > + &bus_pwm1_clk.common,
> > > &iommu_clk.common,
> > > + &bus_iommu_clk.common,
> > > &dram_clk.common,
> > > + &mbus_dma_clk.common,
> > > + &mbus_ve_clk.common,
> > > + &mbus_ce_clk.common,
> > > + &mbus_nand_clk.common,
> > > + &mbus_usb3_clk.common,
> > > + &mbus_csi_clk.common,
> > > + &bus_dram_clk.common,
> > > &nand0_clk.common,
> > > &nand1_clk.common,
> > > + &bus_nand_clk.common,
> > > &mmc0_clk.common,
> > > &mmc1_clk.common,
> > > &mmc2_clk.common,
> > > + &bus_sysdap_clk.common,
> > > + &bus_mmc0_clk.common,
> > > + &bus_mmc1_clk.common,
> > > + &bus_mmc2_clk.common,
> > > + &bus_uart0_clk.common,
> > > + &bus_uart1_clk.common,
> > > + &bus_uart2_clk.common,
> > > + &bus_uart3_clk.common,
> > > + &bus_uart4_clk.common,
> > > + &bus_uart5_clk.common,
> > > + &bus_uart6_clk.common,
> > > + &bus_uart7_clk.common,
> > > + &bus_i2c0_clk.common,
> > > + &bus_i2c1_clk.common,
> > > + &bus_i2c2_clk.common,
> > > + &bus_i2c3_clk.common,
> > > + &bus_i2c4_clk.common,
> > > + &bus_i2c5_clk.common,
> > > + &bus_can_clk.common,
> > > &spi0_clk.common,
> > > &spi1_clk.common,
> > > &spi2_clk.common,
> > > &spifc_clk.common,
> > > + &bus_spi0_clk.common,
> > > + &bus_spi1_clk.common,
> > > + &bus_spi2_clk.common,
> > > + &bus_spifc_clk.common,
> > > &emac0_25M_clk.common,
> > > &emac1_25M_clk.common,
> > > + &bus_emac0_clk.common,
> > > + &bus_emac1_clk.common,
> > > &ir_rx_clk.common,
> > > + &bus_ir_rx_clk.common,
> > > &ir_tx_clk.common,
> > > + &bus_ir_tx_clk.common,
> > > &gpadc0_clk.common,
> > > &gpadc1_clk.common,
> > > + &bus_gpadc0_clk.common,
> > > + &bus_gpadc1_clk.common,
> > > + &bus_ths_clk.common,
> > > &usb_ohci0_clk.common,
> > > &usb_ohci1_clk.common,
> > > + &bus_ohci0_clk.common,
> > > + &bus_ohci1_clk.common,
> > > + &bus_ehci0_clk.common,
> > > + &bus_ehci1_clk.common,
> > > + &bus_otg_clk.common,
> > > + &bus_lradc_clk.common,
> > > &pcie_aux_clk.common,
> > > + &bus_dpss_top_clk.common,
> > > &hdmi_24M_clk.common,
> > > &hdmi_cec_32k_clk.common,
> > > &hdmi_cec_clk.common,
> > > + &bus_hdmi_clk.common,
> > > &mipi_dsi0_clk.common,
> > > &mipi_dsi1_clk.common,
> > > + &bus_mipi_dsi0_clk.common,
> > > + &bus_mipi_dsi1_clk.common,
> > > &tcon_lcd0_clk.common,
> > > &tcon_lcd1_clk.common,
> > > + &combophy_dsi0_clk.common,
> > > + &combophy_dsi1_clk.common,
> > > + &bus_tcon_lcd0_clk.common,
> > > + &bus_tcon_lcd1_clk.common,
> > > &tcon_tv0_clk.common,
> > > &tcon_tv1_clk.common,
> > > + &bus_tcon_tv0_clk.common,
> > > + &bus_tcon_tv1_clk.common,
> > > &edp_clk.common,
> > > + &bus_edp_clk.common,
> > > &ledc_clk.common,
> > > + &bus_ledc_clk.common,
> > > &csi_top_clk.common,
> > > &csi_mclk0_clk.common,
> > > &csi_mclk1_clk.common,
> > > &csi_mclk2_clk.common,
> > > &csi_mclk3_clk.common,
> > > + &bus_csi_clk.common,
> > > &isp_clk.common,
> > > &dsp_clk.common,
> > > + &bus_dsp_cfg_clk.common,
> > > &fanout_24M_clk.common,
> > > &fanout_12M_clk.common,
> > > &fanout_16M_clk.common,
> > > @@ -1119,57 +1343,126 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
> > > [CLK_APB1] = &apb1_clk.common.hw,
> > > [CLK_MBUS] = &mbus_clk.hw,
> > > [CLK_DE] = &de_clk.common.hw,
> > > + [CLK_BUS_DE] = &bus_de_clk.common.hw,
> > > [CLK_DI] = &di_clk.common.hw,
> > > + [CLK_BUS_DI] = &bus_di_clk.common.hw,
> > > [CLK_G2D] = &g2d_clk.common.hw,
> > > + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
> > > [CLK_GPU] = &gpu_clk.common.hw,
> > > + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
> > > [CLK_CE] = &ce_clk.common.hw,
> > > + [CLK_BUS_CE] = &bus_ce_clk.common.hw,
> > > + [CLK_BUS_CE_SYS] = &bus_ce_sys_clk.common.hw,
> > > [CLK_VE] = &ve_clk.common.hw,
> > > + [CLK_BUS_VE] = &bus_ve_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_HSTIMER0] = &hstimer0_clk.common.hw,
> > > [CLK_HSTIMER1] = &hstimer1_clk.common.hw,
> > > [CLK_HSTIMER2] = &hstimer2_clk.common.hw,
> > > [CLK_HSTIMER3] = &hstimer3_clk.common.hw,
> > > [CLK_HSTIMER4] = &hstimer4_clk.common.hw,
> > > [CLK_HSTIMER5] = &hstimer5_clk.common.hw,
> > > + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
> > > + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
> > > + [CLK_BUS_PWM0] = &bus_pwm0_clk.common.hw,
> > > + [CLK_BUS_PWM1] = &bus_pwm1_clk.common.hw,
> > > [CLK_IOMMU] = &iommu_clk.common.hw,
> > > + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
> > > [CLK_DRAM] = &dram_clk.common.hw,
> > > + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
> > > + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
> > > + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
> > > + [CLK_MBUS_CSI] = &mbus_csi_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_MMC2] = &mmc2_clk.common.hw,
> > > + [CLK_BUS_SYSDAP] = &bus_sysdap_clk.common.hw,
> > > + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
> > > + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
> > > + [CLK_BUS_MMC2] = &bus_mmc2_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_UART4] = &bus_uart4_clk.common.hw,
> > > + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
> > > + [CLK_BUS_UART6] = &bus_uart6_clk.common.hw,
> > > + [CLK_BUS_UART7] = &bus_uart7_clk.common.hw,
> > > + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
> > > + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
> > > + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
> > > + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
> > > + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
> > > + [CLK_BUS_I2C5] = &bus_i2c5_clk.common.hw,
> > > + [CLK_BUS_CAN] = &bus_can_clk.common.hw,
> > > [CLK_SPI0] = &spi0_clk.common.hw,
> > > [CLK_SPI1] = &spi1_clk.common.hw,
> > > [CLK_SPI2] = &spi2_clk.common.hw,
> > > [CLK_SPIFC] = &spifc_clk.common.hw,
> > > + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
> > > + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
> > > + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
> > > + [CLK_BUS_SPIFC] = &bus_spifc_clk.common.hw,
> > > [CLK_EMAC0_25M] = &emac0_25M_clk.common.hw,
> > > [CLK_EMAC1_25M] = &emac1_25M_clk.common.hw,
> > > + [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
> > > + [CLK_BUS_EMAC1] = &bus_emac1_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_GPADC0] = &gpadc0_clk.common.hw,
> > > [CLK_GPADC1] = &gpadc1_clk.common.hw,
> > > + [CLK_BUS_GPADC0] = &bus_gpadc0_clk.common.hw,
> > > + [CLK_BUS_GPADC1] = &bus_gpadc1_clk.common.hw,
> > > + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
> > > [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
> > > [CLK_USB_OHCI1] = &usb_ohci1_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_EHCI1] = &bus_ehci1_clk.common.hw,
> > > + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
> > > + [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw,
> > > [CLK_PCIE_AUX] = &pcie_aux_clk.common.hw,
> > > + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
> > > [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw,
> > > [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw,
> > > [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
> > > + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
> > > [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
> > > [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
> > > + [CLK_BUS_MIPI_DSI0] = &bus_mipi_dsi0_clk.common.hw,
> > > + [CLK_BUS_MIPI_DSI1] = &bus_mipi_dsi1_clk.common.hw,
> > > [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw,
> > > [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw,
> > > [CLK_COMBOPHY_DSI0] = &combophy_dsi0_clk.common.hw,
> > > [CLK_COMBOPHY_DSI1] = &combophy_dsi1_clk.common.hw,
> > > + [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw,
> > > + [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw,
> > > [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
> > > [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
> > > + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
> > > + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
> > > [CLK_EDP] = &edp_clk.common.hw,
> > > + [CLK_BUS_EDP] = &bus_edp_clk.common.hw,
> > > [CLK_LEDC] = &ledc_clk.common.hw,
> > > + [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw,
> > > [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> > > [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> > > [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> > > [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> > > [CLK_CSI_MCLK3] = &csi_mclk3_clk.common.hw,
> > > + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
> > > [CLK_ISP] = &isp_clk.common.hw,
> > > [CLK_DSP] = &dsp_clk.common.hw,
> > > + [CLK_BUS_DSP_CFG] = &bus_dsp_cfg_clk.common.hw,
> > > [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> > > [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> > > [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
> > >
> >
> >
> >
> >
>
>
^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2025-02-28 14:41 UTC | newest]
Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-14 12:53 [PATCH v2 00/15] clk: sunxi-ng: add A523 clock support Andre Przywara
2025-02-14 12:53 ` [PATCH v2 01/15] clk: sunxi-ng: mp: Add SUNXI_CCU_P_DATA_WITH_MUX_GATE wrapper Andre Przywara
2025-02-16 8:39 ` Chen-Yu Tsai
2025-02-14 12:53 ` [PATCH v2 02/15] clk: sunxi-ng: mp: introduce dual-divider clock Andre Przywara
2025-02-16 8:39 ` Chen-Yu Tsai
2025-02-14 12:53 ` [PATCH v2 03/15] clk: sunxi-ng: mp: provide wrapper for setting feature flags Andre Przywara
2025-02-16 8:41 ` Chen-Yu Tsai
2025-02-14 12:53 ` [PATCH v2 04/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 CCU Andre Przywara
2025-02-14 12:53 ` [PATCH v2 05/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs Andre Przywara
2025-02-18 19:03 ` Jernej Škrabec
2025-02-28 13:29 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 06/15] clk: sunxi-ng: a523: Add support for bus clocks Andre Przywara
2025-02-18 19:06 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 07/15] clk: sunxi-ng: a523: add video mod clocks Andre Przywara
2025-02-18 19:26 ` Jernej Škrabec
2025-02-28 13:42 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 08/15] clk: sunxi-ng: a523: add system " Andre Przywara
2025-02-18 19:34 ` Jernej Škrabec
2025-02-28 13:43 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 09/15] clk: sunxi-ng: a523: add interface " Andre Przywara
2025-02-18 19:42 ` Jernej Škrabec
2025-02-28 13:46 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 10/15] clk: sunxi-ng: a523: add USB " Andre Przywara
2025-02-18 19:46 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 11/15] clk: sunxi-ng: a523: remaining " Andre Przywara
2025-02-18 19:55 ` Jernej Škrabec
2025-02-28 13:50 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 12/15] clk: sunxi-ng: a523: add bus clock gates Andre Przywara
2025-02-18 20:12 ` Jernej Škrabec
2025-02-28 14:04 ` Andre Przywara
2025-02-28 14:41 ` Jernej Škrabec
2025-02-14 12:53 ` [PATCH v2 13/15] clk: sunxi-ng: a523: add reset lines Andre Przywara
2025-02-18 20:29 ` Jernej Škrabec
2025-02-28 14:21 ` Andre Przywara
2025-02-14 12:53 ` [PATCH v2 14/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU Andre Przywara
2025-02-14 12:53 ` [PATCH v2 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU Andre Przywara
2025-02-18 20:42 ` Jernej Škrabec
2025-02-28 14:33 ` Andre Przywara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).