From: Andre Przywara <andre.przywara@arm.com>
To: "Jernej Škrabec" <jernej.skrabec@gmail.com>
Cc: Tom Rini <trini@konsulko.com>, Simon Glass <sjg@chromium.org>,
Mikhail Kalashnikov <iuncuim@gmail.com>,
u-boot@lists.denx.de, linux-sunxi@lists.linux.dev
Subject: Re: [PATCH 01/34] sunxi: clock: H6: drop usage of struct sunxi_ccm_reg
Date: Sun, 23 Mar 2025 23:50:27 +0000 [thread overview]
Message-ID: <20250323235027.5d0f34d3@minigeek.lan> (raw)
In-Reply-To: <4995090.31r3eYUQgx@jernej-laptop>
On Sun, 23 Mar 2025 12:56:55 +0100
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi Jernej,
thanks for having a look!
> Dne nedelja, 23. marec 2025 ob 12:35:11 Srednjeevropski standardni čas je Andre Przywara napisal(a):
> > U-Boot drivers often revert to using C structures for modelling hardware
> > register frames. This creates some problems:
> > - A "struct" is a C language construct to group several variables
> > together. The details of the layout of this struct are partly subject
> > to the compiler's discretion (padding and alignment).
> > - The "packed" attribute would force a certain layout, but we are not
> > using it.
> > - The actual source of information from the data sheet is the register
> > offset. Here we create an artificial struct, carefully tuning the
> > layout (with a lot of reserved members) to match that offset. To help
> > with correctness, we put the desired information as a *comment*,
> > though this is purely for the human reader, and has no effect on the
> > generated layout. This sounds all very backwards.
> > - Using a struct suggests we can assign a pointer and then access the
> > register content via the members. But this is not the case, instead
> > every MMIO register access must go through specific accessor functions,
> > to meet the ordering and access size guarantees the hardware requires.
> > - We share those structs in code shared across multiple SoC families,
> > though most SoCs define their own version of the struct. Members must
> > match in their name, across every SoC, otherwise compilation will fail.
> > We work around this with even more #ifdefs in the shared code.
> > - Some SoCs have an *almost* identical layout, but differ in a few
> > registers. This requires hard to maintain #ifdef's in the struct
> > definition.
> > - Some of the register frames are huge: the H6 CCU device defines 127
> > registers. We use 15 of them. Still the whole frame would need to be
> > described, which is very tedious, but for no reason.
> > - Adding a new SoC often forces people to decide whether to share an
> > existing struct, or to create a new copy. For some cases (say like 80%
> > similarity) this works out badly either way.
> >
> > The Linux kernel heavily frowns upon those register structs, and instead
> > uses a much simpler solution: #define REG_NAME <offset>
> > This easily maps to the actual information from the data sheet, and can
> > much simpler be shared across multiple SoCs, as it allows to have all
> > SoC versions visible, so we can use C "if" statements instead of #ifdef's.
> > Also it requires to just define the registers we need, and we can use
> > alternative locations for some registers much more easily.
> >
> > Drop the usage of "struct sunxi_ccm_reg" in the H6 SPL clock code, by
> > defining the respective register names and their offsets, then adding
> > them to the base pointer.
> > We cannot drop the struct definition quite yet, as it's also used in
> > other drivers, still.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > .../include/asm/arch-sunxi/clock_sun50i_h6.h | 12 +++++
> > arch/arm/mach-sunxi/clock_sun50i_h6.c | 52 +++++++++----------
> > 2 files changed, 36 insertions(+), 28 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
> > index 76dd33c9477..a485e00f1f3 100644
> > --- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
> > +++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
> > @@ -13,6 +13,18 @@
> > #include <linux/bitops.h>
> > #endif
> >
> > +#define CCU_H6_PLL1_CFG 0x000
> > +#define CCU_H6_PLL5_CFG 0x010
> > +#define CCU_H6_PLL6_CFG 0x020
> > +#define CCU_H6_CPU_AXI_CFG 0x500
> > +#define CCU_H6_PSI_AHB1_AHB2_CFG 0x510
> > +#define CCU_H6_AHB3_CFG 0x51c
> > +#define CCU_H6_APB1_CFG 0x520
> > +#define CCU_H6_APB2_CFG 0x524
> > +#define CCU_H6_MBUS_CFG 0x540
> > +#define CCU_H6_UART_GATE_RESET 0x90c
> > +#define CCU_H6_I2C_GATE_RESET 0x91c
>
> I appreciate this work very much and thanks for doing it!
Ah, great, I was hoping for this kind of feedback. I voiced my concern
about this many years ago, but this was met with some reservations back
then.
> However, I
> have just one more request - PLL1, PLL5, PLL6 and similar names are
> relics of very old Allwinner SoC drivers. IMO it would be better to follow
> names from user manual. This would lower confusion what are they to
> uninitiated people.
I agree, and that's literally patch 37/34 of that branch I took this
series from ;-), so stay tuned for that. The reason this is not in here
or before is that it affects all SoCs, and I wanted to keep that
separate and not blocking the A523 series.
Cheers,
Andre
>
> Best regards.
> Jernej
>
> > +
> > struct sunxi_ccm_reg {
> > u32 pll1_cfg; /* 0x000 pll1 (cpux) control */
> > u8 reserved_0x004[12];
> > diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
> > index b424a7893ea..482d9e0c695 100644
> > --- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
> > +++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
> > @@ -6,8 +6,7 @@
> > #ifdef CONFIG_XPL_BUILD
> > void clock_init_safe(void)
> > {
> > - struct sunxi_ccm_reg *const ccm =
> > - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> > + void *const ccm = (void *)SUNXI_CCM_BASE;
> > struct sunxi_prcm_reg *const prcm =
> > (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
> >
> > @@ -32,60 +31,59 @@ void clock_init_safe(void)
> >
> > clock_set_pll1(408000000);
> >
> > - writel(CCM_PLL6_DEFAULT, &ccm->pll6_cfg);
> > - while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_LOCK))
> > + writel(CCM_PLL6_DEFAULT, ccm + CCU_H6_PLL6_CFG);
> > + while (!(readl(ccm + CCU_H6_PLL6_CFG) & CCM_PLL6_LOCK))
> > ;
> >
> > - clrsetbits_le32(&ccm->cpu_axi_cfg, CCM_CPU_AXI_APB_MASK | CCM_CPU_AXI_AXI_MASK,
> > + clrsetbits_le32(ccm + CCU_H6_CPU_AXI_CFG,
> > + CCM_CPU_AXI_APB_MASK | CCM_CPU_AXI_AXI_MASK,
> > CCM_CPU_AXI_DEFAULT_FACTORS);
> >
> > - writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
> > + writel(CCM_PSI_AHB1_AHB2_DEFAULT, ccm + CCU_H6_PSI_AHB1_AHB2_CFG);
> > #ifdef CCM_AHB3_DEFAULT
> > - writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
> > + writel(CCM_AHB3_DEFAULT, ccm + CCU_H6_AHB3_CFG);
> > #endif
> > - writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
> > + writel(CCM_APB1_DEFAULT, ccm + CCU_H6_APB1_CFG);
> >
> > /*
> > * The mux and factor are set, but the clock will be enabled in
> > * DRAM initialization code.
> > */
> > - writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), &ccm->mbus_cfg);
> > + writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), ccm + CCU_H6_MBUS_CFG);
> > }
> >
> > void clock_init_uart(void)
> > {
> > - struct sunxi_ccm_reg *const ccm =
> > - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> > + void *const ccm = (void *)SUNXI_CCM_BASE;
> >
> > /* uart clock source is apb2 */
> > writel(APB2_CLK_SRC_OSC24M|
> > APB2_CLK_RATE_N_1|
> > APB2_CLK_RATE_M(1),
> > - &ccm->apb2_cfg);
> > + ccm + CCU_H6_APB2_CFG);
> >
> > /* open the clock for uart */
> > - setbits_le32(&ccm->uart_gate_reset,
> > + setbits_le32(ccm + CCU_H6_UART_GATE_RESET,
> > 1 << (CONFIG_CONS_INDEX - 1));
> >
> > /* deassert uart reset */
> > - setbits_le32(&ccm->uart_gate_reset,
> > + setbits_le32(ccm + CCU_H6_UART_GATE_RESET,
> > 1 << (RESET_SHIFT + CONFIG_CONS_INDEX - 1));
> > }
> >
> > void clock_set_pll1(unsigned int clk)
> > {
> > - struct sunxi_ccm_reg * const ccm =
> > - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> > + void *const ccm = (void *)SUNXI_CCM_BASE;
> > u32 val;
> >
> > /* Do not support clocks < 288MHz as they need factor P */
> > if (clk < 288000000) clk = 288000000;
> >
> > /* Switch to 24MHz clock while changing PLL1 */
> > - val = readl(&ccm->cpu_axi_cfg);
> > + val = readl(ccm + CCU_H6_CPU_AXI_CFG);
> > val &= ~CCM_CPU_AXI_MUX_MASK;
> > val |= CCM_CPU_AXI_MUX_OSC24M;
> > - writel(val, &ccm->cpu_axi_cfg);
> > + writel(val, ccm + CCU_H6_CPU_AXI_CFG);
> >
> > /* clk = 24*n/p, p is ignored if clock is >288MHz */
> > val = CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2;
> > @@ -94,20 +92,19 @@ void clock_set_pll1(unsigned int clk)
> > val |= CCM_PLL1_OUT_EN;
> > if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> > val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
> > - writel(val, &ccm->pll1_cfg);
> > - while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
> > + writel(val, ccm + CCU_H6_PLL1_CFG);
> > + while (!(readl(ccm + CCU_H6_PLL1_CFG) & CCM_PLL1_LOCK)) {}
> >
> > /* Switch CPU to PLL1 */
> > - val = readl(&ccm->cpu_axi_cfg);
> > + val = readl(ccm + CCU_H6_CPU_AXI_CFG);
> > val &= ~CCM_CPU_AXI_MUX_MASK;
> > val |= CCM_CPU_AXI_MUX_PLL_CPUX;
> > - writel(val, &ccm->cpu_axi_cfg);
> > + writel(val, ccm + CCU_H6_CPU_AXI_CFG);
> > }
> >
> > int clock_twi_onoff(int port, int state)
> > {
> > - struct sunxi_ccm_reg *const ccm =
> > - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> > + void *const ccm = (void *)SUNXI_CCM_BASE;
> > struct sunxi_prcm_reg *const prcm =
> > (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
> > u32 value, *ptr;
> > @@ -120,7 +117,7 @@ int clock_twi_onoff(int port, int state)
> > ptr = &prcm->twi_gate_reset;
> > } else {
> > shift = port;
> > - ptr = &ccm->twi_gate_reset;
> > + ptr = ccm + CCU_H6_I2C_GATE_RESET;
> > }
> >
> > /* set the apb clock gate and reset for twi */
> > @@ -136,9 +133,8 @@ int clock_twi_onoff(int port, int state)
> > /* PLL_PERIPH0 clock, used by the MMC driver */
> > unsigned int clock_get_pll6(void)
> > {
> > - struct sunxi_ccm_reg *const ccm =
> > - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> > - uint32_t rval = readl(&ccm->pll6_cfg);
> > + void *const ccm = (void *)SUNXI_CCM_BASE;
> > + uint32_t rval = readl(ccm + CCU_H6_PLL6_CFG);
> > int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
> > int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
> > CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
> >
>
>
>
>
>
next prev parent reply other threads:[~2025-03-23 23:51 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-23 11:35 [PATCH 00/34] sunxi: clock refactoring and Allwinner A523 support Andre Przywara
2025-03-23 11:35 ` [PATCH 01/34] sunxi: clock: H6: drop usage of struct sunxi_ccm_reg Andre Przywara
2025-03-23 11:56 ` Jernej Škrabec
2025-03-23 23:50 ` Andre Przywara [this message]
2025-03-23 11:35 ` [PATCH 02/34] sunxi: mmc: remove " Andre Przywara
2025-03-23 12:04 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 03/34] sunxi: H616: dram: " Andre Przywara
2025-03-23 11:35 ` [PATCH 04/34] sunxi: H6: " Andre Przywara
2025-03-23 11:35 ` [PATCH 05/34] sunxi: clock: H6: remove " Andre Przywara
2025-03-23 11:35 ` [PATCH 06/34] sunxi: clock: H6: drop usage of struct sunxi_prcm_reg Andre Przywara
2025-03-23 11:35 ` [PATCH 07/34] sunxi: H6/H616: dram: remove " Andre Przywara
2025-03-23 11:35 ` [PATCH 08/34] sunxi: clock: H6: remove " Andre Przywara
2025-03-23 11:35 ` [PATCH 09/34] sunxi: clock: H6: unify PLL control bit definitions Andre Przywara
2025-03-23 11:35 ` [PATCH 10/34] sunxi: clock: H6: factor out clock_set_pll() Andre Przywara
2025-03-23 11:35 ` [PATCH 11/34] sunxi: clock: H6: factor out H6/H616 CPU clock setup Andre Przywara
2025-03-23 11:35 ` [PATCH 12/34] sunxi: clock: H6: add A523 CPU PLL support Andre Przywara
2025-03-23 11:35 ` [PATCH 13/34] sunxi: spl: add support for Allwinner A523 watchdog Andre Przywara
2025-03-23 12:15 ` Jernej Škrabec
2025-03-23 23:57 ` Andre Przywara
2025-03-23 11:35 ` [PATCH 14/34] dt-bindings: add Allwinner A523 CCU bindings Andre Przywara
2025-03-23 11:35 ` [PATCH 15/34] clk: sunxi: Add support for the A523 CCU Andre Przywara
2025-03-23 11:35 ` [PATCH 16/34] clk: sunxi: Add support for the A523 -R CCU Andre Przywara
2025-03-23 12:18 ` Jernej Škrabec
2025-03-24 0:37 ` Andre Przywara
2025-03-23 11:35 ` [PATCH 17/34] pinctrl: sunxi: add Allwinner A523 pinctrl description Andre Przywara
2025-03-23 11:35 ` [PATCH 18/34] sunxi: mmc: add support for Allwinner A523 MMC mod clock Andre Przywara
2025-03-23 11:35 ` [PATCH 19/34] watchdog: sunxi: add A523 support Andre Przywara
2025-03-24 8:38 ` Stefan Roese
2025-03-23 11:35 ` [PATCH 20/34] power: regulator: add AXP323 support Andre Przywara
2025-03-23 11:35 ` [PATCH 21/34] sunxi: update cpu_sunxi_ncat2.h Andre Przywara
2025-03-23 11:35 ` [PATCH 22/34] sunxi: Kconfig: consolidate SYS_CLK_FREQ selection Andre Przywara
2025-03-23 12:21 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 23/34] spl: reorder SPL_MAX_SIZE defaults for sunxi Andre Przywara
2025-03-23 12:22 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 24/34] sunxi: armv8: fel: move fel_stash variable to the front Andre Przywara
2025-03-23 12:23 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 25/34] sunxi: arm64: boot0.h: move fel_stash_addr " Andre Przywara
2025-03-23 12:23 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 26/34] sunxi: update rmr_switch.S source code Andre Przywara
2025-03-23 12:24 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 27/34] sunxi: armv8: FEL: save and restore GICv3 registers Andre Przywara
2025-03-23 12:25 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 28/34] sunxi: armv8: FEL: save and restore SP_IRQ Andre Przywara
2025-03-23 12:26 ` Jernej Škrabec
2025-03-23 23:52 ` Andre Przywara
2025-03-23 11:35 ` [PATCH 29/34] sunxi: sun50i_h6: add A523 SPL clock setup code Andre Przywara
2025-03-23 12:36 ` Jernej Škrabec
2025-03-23 11:35 ` [PATCH 30/34] sunxi: A523: add DRAM initialisation routine Andre Przywara
2025-03-23 13:15 ` Jernej Škrabec
2025-04-05 22:01 ` Yixun Lan
2025-04-07 9:26 ` Andre Przywara
2025-03-23 11:35 ` [PATCH 31/34] sunxi: A523: add DDR3 DRAM support Andre Przywara
2025-03-23 11:35 ` [PATCH 32/34] sunxi: add basic A523 support Andre Przywara
2025-03-23 11:35 ` [PATCH 33/34] sunxi: A523: add DT files from Linux v3 branch Andre Przywara
2025-04-09 14:28 ` Yixun Lan
2025-03-23 11:35 ` [PATCH 34/34] sunxi: A523: add defconfigs for three boards Andre Przywara
2025-04-05 2:44 ` [PATCH 00/34] sunxi: clock refactoring and Allwinner A523 support Yixun Lan
2025-04-05 12:32 ` Andre Przywara
2025-04-05 13:04 ` Yixun Lan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250323235027.5d0f34d3@minigeek.lan \
--to=andre.przywara@arm.com \
--cc=iuncuim@gmail.com \
--cc=jernej.skrabec@gmail.com \
--cc=linux-sunxi@lists.linux.dev \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox