clk: Add Allwinner CLK, RESET support
Subsystems (12)
v5 cover clk: Add Allwinner CLK, RESET support
Although the previous version[1] is properly handled the clock gates with enable and disable management, but this series is trying to add some more complex Allwinner CLK architecture by handling parent clock and other CLK attributes.
Allwinner Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management and these can be handled via ccu_clock_gate, which is almost same as previous version changes.
Tree clock has more Allwinner CLK attributes like clock type, fixed clocks, misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be managed via ccu_clock_tree.
On top of initial clock gates supported from previous version, this series is trying to add support for MP, NK, MISC, FIXED clock types with get_rate functionality and that can eventually used by uart driver.
On the summary, this would be an initial infrasture that can fit into remaining clock handle support like set_rate, so the rest of code will add on the requirement basics.
Once this is fine, I will try to add code for other parts especially for MMC since we have migration deadline for BLK, MMC, SCSI.
So, please do let me know if anyone have any inputs.
All these changes available at u-boot-sunxi/clk-next
thanks,
Jagan.
[1] https://patchwork.ozlabs.org/cover/962226/
Jagan Teki (26):
clk: Add Allwinner A64 CLK driver
reset: Add Allwinner RESET driver
clk: sunxi: Add Allwinner H3/H5 CLK driver
clk: sunxi: Add Allwinner A10/A20 CLK driver
clk: sunxi: Add Allwinner A10s/A13 CLK driver
clk: sunxi: Add Allwinner A31 CLK driver
clk: sunxi: Add Allwinner A23/A33 CLK driver
clk: sunxi: Add Allwinner A83T CLK driver
clk: sunxi: Add Allwinner R40 CLK driver
clk: sunxi: Add Allwinner V3S CLK driver
clk: sunxi: Implement UART clocks
clk: sunxi: Implement UART resets
clk: sunxi: Add Allwinner H6 CLK driver
sunxi: A64: Update sun50i-a64-ccu.h
clk: sunxi: Add ccu clock tree support
sunxi: Enable CLK
phy: sun4i-usb: Use CLK and RESET support
reset: Add reset valid
musb-new: sunxi: Use CLK and RESET support
sunxi: usb: Switch to Generic host controllers
usb: host: Drop [e-o]hci-sunxi drivers
clk: sunxi: Implement SPI clocks
spi: sun4i: Add CLK support
clk: sunxi: Implement A64 SPI clocks, resets
spi: Add Allwinner A31 SPI driver
board: sopine: Enable SPI/SPI-FLASH
.../sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 + arch/arm/include/asm/arch-sunxi/ccu.h | 284 +++++++++++++ arch/arm/mach-sunxi/Kconfig | 12 + configs/A10-OLinuXino-Lime_defconfig | 1 + configs/A10s-OLinuXino-M_defconfig | 1 + configs/A13-OLinuXinoM_defconfig | 1 + configs/A13-OLinuXino_defconfig | 1 + configs/A20-OLinuXino-Lime2-eMMC_defconfig | 1 + configs/A20-OLinuXino-Lime2_defconfig | 1 + configs/A20-OLinuXino-Lime_defconfig | 1 + configs/A20-Olimex-SOM204-EVB_defconfig | 1 + configs/Auxtek-T003_defconfig | 1 + configs/Auxtek-T004_defconfig | 1 + configs/Bananapi_defconfig | 1 + configs/Bananapi_m2m_defconfig | 1 + configs/Bananapro_defconfig | 1 + configs/CHIP_defconfig | 1 + configs/CHIP_pro_defconfig | 1 + configs/CSQ_CS908_defconfig | 1 + configs/Colombus_defconfig | 1 + configs/Cubieboard2_defconfig | 1 + configs/Cubieboard_defconfig | 1 + configs/Cubietruck_plus_defconfig | 1 + configs/Hummingbird_A31_defconfig | 1 + configs/Itead_Ibox_A20_defconfig | 1 + configs/Linksprite_pcDuino3_Nano_defconfig | 1 + configs/Linksprite_pcDuino3_defconfig | 1 + configs/Linksprite_pcDuino_defconfig | 1 + configs/MK808C_defconfig | 1 + configs/Marsboard_A10_defconfig | 1 + configs/Mele_A1000G_quad_defconfig | 1 + configs/Mele_A1000_defconfig | 1 + configs/Mele_I7_defconfig | 1 + configs/Mele_M3_defconfig | 1 + configs/Mele_M5_defconfig | 1 + configs/Mele_M9_defconfig | 1 + configs/Mini-X_defconfig | 1 + configs/Orangepi_defconfig | 1 + configs/Orangepi_mini_defconfig | 1 + configs/Sinlinx_SinA31s_defconfig | 1 + configs/Sinlinx_SinA33_defconfig | 1 + configs/Sinovoip_BPI_M2_Plus_defconfig | 1 + configs/Sinovoip_BPI_M2_defconfig | 1 + configs/Sinovoip_BPI_M3_defconfig | 1 + configs/Wexler_TAB7200_defconfig | 1 + configs/Wobo_i5_defconfig | 1 + configs/a64-olinuxino_defconfig | 1 + configs/ba10_tv_box_defconfig | 1 + configs/bananapi_m1_plus_defconfig | 1 + configs/bananapi_m64_defconfig | 1 + configs/ga10h_v1_1_defconfig | 1 + configs/h8_homlet_v2_defconfig | 1 + configs/i12-tvbox_defconfig | 1 + configs/icnova-a20-swac_defconfig | 1 + configs/inet1_defconfig | 1 + configs/inet_q972_defconfig | 1 + configs/jesurun_q5_defconfig | 1 + configs/libretech_all_h3_cc_h2_plus_defconfig | 1 + configs/libretech_all_h3_cc_h3_defconfig | 1 + configs/libretech_all_h3_cc_h5_defconfig | 1 + configs/mixtile_loftq_defconfig | 1 + configs/mk802_a10s_defconfig | 1 + configs/mk802_defconfig | 1 + configs/mk802ii_defconfig | 1 + configs/nanopi_a64_defconfig | 1 + configs/nanopi_m1_defconfig | 1 + configs/nanopi_m1_plus_defconfig | 1 + configs/nanopi_neo2_defconfig | 1 + configs/nanopi_neo_air_defconfig | 1 + configs/nanopi_neo_defconfig | 1 + configs/nanopi_neo_plus2_defconfig | 1 + configs/orangepi_2_defconfig | 1 + configs/orangepi_lite_defconfig | 1 + configs/orangepi_one_defconfig | 1 + configs/orangepi_pc2_defconfig | 1 + configs/orangepi_pc_defconfig | 1 + configs/orangepi_pc_plus_defconfig | 1 + configs/orangepi_plus2e_defconfig | 1 + configs/orangepi_plus_defconfig | 1 + configs/orangepi_prime_defconfig | 1 + configs/orangepi_r1_defconfig | 1 + configs/orangepi_win_defconfig | 1 + configs/orangepi_zero_defconfig | 1 + configs/orangepi_zero_plus2_defconfig | 1 + configs/orangepi_zero_plus_defconfig | 1 + configs/parrot_r16_defconfig | 1 + configs/pine64_plus_defconfig | 1 + configs/r7-tv-dongle_defconfig | 1 + configs/sopine_baseboard_defconfig | 8 + configs/sun8i_a23_evb_defconfig | 1 + configs/sunxi_Gemei_G9_defconfig | 1 + configs/tbs_a711_defconfig | 1 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sunxi/Kconfig | 82 ++++ drivers/clk/sunxi/Makefile | 18 + drivers/clk/sunxi/clk_a10.c | 77 ++++ drivers/clk/sunxi/clk_a10s.c | 68 +++ drivers/clk/sunxi/clk_a23.c | 75 ++++ drivers/clk/sunxi/clk_a31.c | 82 ++++ drivers/clk/sunxi/clk_a64.c | 125 ++++++ drivers/clk/sunxi/clk_a83t.c | 75 ++++ drivers/clk/sunxi/clk_h3.c | 89 ++++ drivers/clk/sunxi/clk_h6.c | 53 +++ drivers/clk/sunxi/clk_r40.c | 88 ++++ drivers/clk/sunxi/clk_sunxi.c | 256 +++++++++++ drivers/clk/sunxi/clk_v3s.c | 59 +++ drivers/phy/allwinner/phy-sun4i-usb.c | 77 +++- drivers/reset/Kconfig | 8 + drivers/reset/Makefile | 1 + drivers/reset/reset-sunxi.c | 125 ++++++ drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/sun4i_spi.c | 46 +- drivers/spi/sun6i_spi.c | 398 ++++++++++++++++++ drivers/usb/host/Kconfig | 2 + drivers/usb/host/Makefile | 2 - drivers/usb/host/ehci-sunxi.c | 204 --------- drivers/usb/host/ohci-sunxi.c | 233 ---------- drivers/usb/musb-new/sunxi.c | 81 ++-- include/configs/sun4i.h | 4 - include/configs/sun50i.h | 5 - include/configs/sun5i.h | 4 - include/configs/sun6i.h | 4 - include/configs/sun7i.h | 4 - include/configs/sun8i.h | 4 - include/configs/sunxi-common.h | 1 - include/dt-bindings/clock/sun50i-a64-ccu.h | 2 + include/reset.h | 11 + scripts/config_whitelist.txt | 2 - 130 files changed, 2248 insertions(+), 534 deletions(-) create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi create mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h create mode 100644 drivers/clk/sunxi/Kconfig create mode 100644 drivers/clk/sunxi/Makefile create mode 100644 drivers/clk/sunxi/clk_a10.c create mode 100644 drivers/clk/sunxi/clk_a10s.c create mode 100644 drivers/clk/sunxi/clk_a23.c create mode 100644 drivers/clk/sunxi/clk_a31.c create mode 100644 drivers/clk/sunxi/clk_a64.c create mode 100644 drivers/clk/sunxi/clk_a83t.c create mode 100644 drivers/clk/sunxi/clk_h3.c create mode 100644 drivers/clk/sunxi/clk_h6.c create mode 100644 drivers/clk/sunxi/clk_r40.c create mode 100644 drivers/clk/sunxi/clk_sunxi.c create mode 100644 drivers/clk/sunxi/clk_v3s.c create mode 100644 drivers/reset/reset-sunxi.c create mode 100644 drivers/spi/sun6i_spi.c delete mode 100644 drivers/usb/host/ehci-sunxi.c delete mode 100644 drivers/usb/host/ohci-sunxi.c
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 1/26 clk: Add Allwinner A64 CLK driver
Add initial clock driver for Allwinner A64.
Implement USB clock enable and disable functions for OHCI, EHCI, OTG and USBPHY gate and clock registers via ccu clk gate table.
--- arch/arm/include/asm/arch-sunxi/ccu.h | 65 +++++++++++++++++++++++ drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sunxi/Kconfig | 18 +++++++ drivers/clk/sunxi/Makefile | 9 ++++ drivers/clk/sunxi/clk_a64.c | 46 +++++++++++++++++ drivers/clk/sunxi/clk_sunxi.c | 74 +++++++++++++++++++++++++++ 7 files changed, 214 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h create mode 100644 drivers/clk/sunxi/Kconfig create mode 100644 drivers/clk/sunxi/Makefile create mode 100644 drivers/clk/sunxi/clk_a64.c create mode 100644 drivers/clk/sunxi/clk_sunxi.c
arch/arm/include/asm/arch-sunxi/ccu.h new file +65 -0
@@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Amarula Solutions. +* Author: Jagan Teki <[email protected]> +*/ + +#ifndef _ASM_ARCH_CCU_H +#define _ASM_ARCH_CCU_H + +/** +* enum ccu_clk_flags - ccu clock flags +* +* @CCU_CLK_F_INIT_DONE: clock gate init done check +*/ +enum ccu_clk_flags { +CCU_CLK_F_INIT_DONE =BIT (0 ), +}; + +/** +* struct ccu_clk_gate - ccu clock gate +* @off: gate offset +* @bit: gate bit +* @flags: clock gate flags +*/ +struct ccu_clk_gate { +u16 off; +u32 bit; +enum ccu_clk_flags flags; +}; + +#define GATE (_off, _bit) { \ + .off = _off, \ + .bit = _bit, \ + .flags = CCU_CLK_F_INIT_DONE, \ +} + +/** +* struct ccu_desc - clock control unit descriptor +* +* @gates: clock gates +*/ +struct ccu_desc { +const struct ccu_clk_gate *gates; +}; + +/** +* struct ccu_priv - sunxi clock control unit +* +* @base: base address +* @desc: ccu descriptor +*/ +struct ccu_priv { +void *base; +const struct ccu_desc *desc; +}; + +/** +* sunxi_clk_probe - common sunxi clock probe +* @dev: clock device +*/ +int sunxi_clk_probe (struct udevice *dev); + +extern struct clk_ops sunxi_clk_ops; + +#endif /* _ASM_ARCH_CCU_H */
drivers/clk/Kconfig +1 -0
@@ -104,6 +104,7 @@ source "drivers/clk/imx/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" source "drivers/clk/renesas/Kconfig" +source "drivers/clk/sunxi/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/uniphier/Kconfig"
drivers/clk/Makefile +1 -0
@@ -22,6 +22,7 @@ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ +obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o obj-$(CONFIG_CLK_STM32MP1) += clk_stm32mp1.o obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
drivers/clk/sunxi/Kconfig new file +18 -0
@@ -0,0 +1,18 @@ +config CLK_SUNXI + bool "Clock support for Allwinner SoCs" + depends on CLK && ARCH_SUNXI + default y + help + This enables support for common clock driver API on Allwinner + SoCs. + +if CLK_SUNXI + +config CLK_SUN50I_A64 + bool "Clock driver for Allwinner A64" + default MACH_SUN50I + help + This enables common clock driver support for platforms based + on Allwinner A64 SoC. + +endif # CLK_SUNXI
drivers/clk/sunxi/Makefile new file +9 -0
@@ -0,0 +1,9 @@ +# +# Copyright (C) 2018 Amarula Solutions. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o + +obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_a64.c new file +46 -0
46 lines not on this page · raw message
drivers/clk/sunxi/clk_sunxi.c new file +74 -0
74 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 2/26 reset: Add Allwinner RESET driver
In reply to Jagan TekiAdd common reset driver for all Allwinner SoC's.
Since CLK and RESET share common DT compatible, it is CLK driver job is to bind the reset driver. So add CLK bind call on respective SoC driver by passing ccu map descriptor so-that reset deassert, deassert operations held based on ccu reset table defined from CLK driver.
Select DM_RESET via CLK_SUNXI, this make hidden section of RESET since CLK and RESET share common DT compatible and code.
--- arch/arm/include/asm/arch-sunxi/ccu.h | 29 ++++++ drivers/clk/sunxi/Kconfig | 1 + drivers/clk/sunxi/clk_a64.c | 20 +++++ drivers/reset/Kconfig | 8 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-sunxi.c | 125 ++++++++++++++++++++++++++ 6 files changed, 184 insertions(+) create mode 100644 drivers/reset/reset-sunxi.c
arch/arm/include/asm/arch-sunxi/ccu.h +29 -0
@@ -34,13 +34,33 @@ struct ccu_clk_gate { .flags = CCU_CLK_F_INIT_DONE, \ } +/** +* struct ccu_reset - ccu reset +* @off: reset offset +* @bit: reset bit +* @flags: reset flags +*/ +struct ccu_reset { +u16 off; +u32 bit; +enum ccu_clk_flags flags; +}; + +#define RESET (_off, _bit) { \ + .off = _off, \ + .bit = _bit, \ + .flags = CCU_CLK_F_INIT_DONE, \ +} +/** * struct ccu_desc - clock control unit descriptor * * @gates: clock gates +* @resets: reset unit */ struct ccu_desc {const struct ccu_clk_gate *gates; +const struct ccu_reset *resets; };/**
@@ -62,4 +82,13 @@ int sunxi_clk_probe(struct udevice *dev);extern struct clk_ops sunxi_clk_ops; +/** +* sunxi_reset_bind() - reset binding +* +* @dev: reset device +* @count: reset count +* @return 0 success, or error value +*/ +int sunxi_reset_bind (struct udevice *dev,ulong count); +#endif /* _ASM_ARCH_CCU_H */
drivers/clk/sunxi/Kconfig +1 -0
@@ -1,6 +1,7 @@ config CLK_SUNXI bool "Clock support for Allwinner SoCs" depends on CLK && ARCH_SUNXI + select DM_RESET default y help This enables support for common clock driver API on Allwinner
drivers/clk/sunxi/clk_a64.c +20 -0
@@ -10,6 +10,7 @@#include <errno.h> #include <asm/arch/ccu.h> #include <dt-bindings/clock/sun50i-a64-ccu.h> +#include <dt-bindings/reset/sun50i-a64-ccu.h> static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )),
@@ -26,10 +27,28 @@ static const struct ccu_clk_gate a64_gates[] = { [CLK_USB_OHCI1] = GATE(0x0cc, BIT(17)), }; +static const struct ccu_reset a64_resets[] = { + [RST_USB_PHY0 ] =RESET (0x0cc ,BIT (0 )), + [RST_USB_PHY1 ] =RESET (0x0cc ,BIT (1 )), + [RST_USB_HSIC ] =RESET (0x0cc ,BIT (2 )), + + [RST_BUS_OTG ] =RESET (0x2c0 ,BIT (23 )), + [RST_BUS_EHCI0 ] =RESET (0x2c0 ,BIT (24 )), + [RST_BUS_EHCI1 ] =RESET (0x2c0 ,BIT (25 )), + [RST_BUS_OHCI0 ] =RESET (0x2c0 ,BIT (28 )), + [RST_BUS_OHCI1 ] =RESET (0x2c0 ,BIT (29 )), +}; +static const struct ccu_desc a64_ccu_desc = { .gates = a64_gates, + .resets = a64_resets, }; +static int a64_clk_bind (struct udevice *dev) +{ +return sunxi_reset_bind (dev,50 ); +} +static const struct udevice_id a64_ccu_ids[] = { { .compatible ="allwinner,sun50i-a64-ccu" , .data = (ulong)&a64_ccu_desc },
@@ -43,4 +62,5 @@ U_BOOT_DRIVER(clk_sun50i_a64) = { .priv_auto_alloc_size = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, + .bind = a64_clk_bind, };
drivers/reset/Kconfig +8 -0
@@ -106,4 +106,12 @@ config RESET_SOCFPGA help Support for reset controller on SoCFPGA platform. +config RESET_SUNXI + bool "RESET support for Allwinner SoCs" + depends on DM_RESET && ARCH_SUNXI + default y + help + This enables support for common reset driver for + Allwinner SoCs. + endmenu
drivers/reset/Makefile +1 -0
@@ -17,3 +17,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o obj-$(CONFIG_RESET_MESON) += reset-meson.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o +obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
drivers/reset/reset-sunxi.c new file +125 -0
125 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 2/26 reset: Add Allwinner RESET driver
Quoted 113 lines · Jagan Teki
Add common reset driver for all Allwinner SoC's.
Since CLK and RESET share common DT compatible, it is CLK driver job is to bind the reset driver. So add CLK bind call on respective SoC driver by passing ccu map descriptor so-that reset deassert, deassert operations held based on ccu reset table defined from CLK driver.
Select
DM_RESETviaCLK_SUNXI, this make hidden section of RESET since CLK and RESET share common DT compatible and code.Signed-off-by Jagan Teki <[email protected]>Acked-by Maxime Ripard <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 29 ++++++ drivers/clk/sunxi/Kconfig | 1 + drivers/clk/sunxi/clk_a64.c | 20 +++++ drivers/reset/Kconfig | 8 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-sunxi.c | 125 ++++++++++++++++++++++++++ 6 files changed, 184 insertions(+) create mode 100644 drivers/reset/reset-sunxi.carch/arm/include/asm/arch-sunxi/ccu.h +29
-0@@ -34,13 +34,33 @@ struct ccu_clk_gate { .flags = CCU_CLK_F_INIT_DONE, \ } +/** +* struct ccu_reset - ccu reset +* @off: reset offset +* @bit: reset bit +* @flags: reset flags +*/ +struct ccu_reset { +u16 off; +u32 bit; +enum ccu_clk_flags flags; +}; + +#define RESET (_off, _bit) { \ + .off = _off, \ + .bit = _bit, \ + .flags = CCU_CLK_F_INIT_DONE, \ +} +/** * struct ccu_desc - clock control unit descriptor * * @gates: clock gates +* @resets: reset unit */ struct ccu_desc {const struct ccu_clk_gate *gates; +const struct ccu_reset *resets; };/** @@ -62,4 +82,13 @@ int sunxi_clk_probe(struct udevice *dev);extern struct clk_ops sunxi_clk_ops; +/** +* sunxi_reset_bind() - reset binding +* +* @dev: reset device +* @count: reset count +* @return 0 success, or error value +*/ +int sunxi_reset_bind (struct udevice *dev,ulong count); +#endif /* _ASM_ARCH_CCU_H */ drivers/clk/sunxi/Kconfig +1
-0@@ -1,6 +1,7 @@ config CLK_SUNXI bool "Clock support for Allwinner SoCs" depends on CLK && ARCH_SUNXI + select DM_RESET default y help This enables support for common clock driver API on Allwinnerdrivers/clk/sunxi/clk_a64.c +11
-0@@ -10,6 +10,7 @@#include <errno.h> #include <asm/arch/ccu.h> #include <dt-bindings/clock/sun50i-a64-ccu.h> +#include <dt-bindings/reset/sun50i-a64-ccu.h> static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )),@@ -26,10 +27,28 @@ static const struct ccu_clk_gate a64_gates[] = { [CLK_USB_OHCI1] = GATE(0x0cc, BIT(17)), }; +static const struct ccu_reset a64_resets[] = { + [RST_USB_PHY0 ] =RESET (0x0cc ,BIT (0 )), + [RST_USB_PHY1 ] =RESET (0x0cc ,BIT (1 )), + [RST_USB_HSIC ] =RESET (0x0cc ,BIT (2 )), + + [RST_BUS_OTG ] =RESET (0x2c0 ,BIT (23 )), + [RST_BUS_EHCI0 ] =RESET (0x2c0 ,BIT (24 )), + [RST_BUS_EHCI1 ] =RESET (0x2c0 ,BIT (25 )), + [RST_BUS_OHCI0 ] =RESET (0x2c0 ,BIT (28 )), + [RST_BUS_OHCI1 ] =RESET (0x2c0 ,BIT (29 )),
drivers/clk/sunxi/clk_a64.c static const struct ccu_clk_gate a64_gates[] = { · line 49
Quoted 10 lines
drivers/clk/sunxi/clk_a64.c +6
-0+}; +static const struct ccu_desc a64_ccu_desc = { .gates = a64_gates, + .resets = a64_resets, }; +static int a64_clk_bind (struct udevice *dev) +{ +return sunxi_reset_bind (dev,50 );
The second parameter is count, so it should be 51. But this is wrong either way, so just use ARRAY_SIZE(a64_reset), as this is what you are after with the check later on.
Same for the other SoCs, of course.
Quoted 67 lines
drivers/clk/sunxi/clk_a64.c +3
-0+} +static const struct udevice_id a64_ccu_ids[] = { { .compatible ="allwinner,sun50i-a64-ccu" , .data = (ulong)&a64_ccu_desc },@@ -43,4 +62,5 @@ U_BOOT_DRIVER(clk_sun50i_a64) = { .priv_auto_alloc_size = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, + .bind = a64_clk_bind, };drivers/reset/Kconfig +8
-0@@ -106,4 +106,12 @@ config RESET_SOCFPGA help Support for reset controller on SoCFPGA platform. +config RESET_SUNXI + bool "RESET support for Allwinner SoCs" + depends on DM_RESET && ARCH_SUNXI + default y + help + This enables support for common reset driver for + Allwinner SoCs. + endmenudrivers/reset/Makefile +1
-0@@ -17,3 +17,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o obj-$(CONFIG_RESET_MESON) += reset-meson.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o +obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.odrivers/reset/reset-sunxi.c new file +24
-0@@ -0,0 +1,125 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* +* Copyright (C) 2018 Amarula Solutions. +* Author: Jagan Teki <[email protected]> +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <reset-uclass.h> +#include <asm/io.h> +#include <dm/lists.h> +#include <linux/log2.h> +#include <asm/arch/ccu.h> + +struct sunxi_reset_priv { +void *base; +ulong count; +const struct ccu_desc *desc; +}; + +static const struct ccu_reset *priv_to_reset (struct sunxi_reset_priv *priv, +unsigned long id) +{
drivers/reset/reset-sunxi.c line 34
Quoted 10 lines
drivers/reset/reset-sunxi.c new file +10
-0+return &priv->desc->resets[id]; +} + +static int sunxi_reset_request (struct reset_ctl *reset_ctl) +{ +struct sunxi_reset_priv *priv =dev_get_priv (reset_ctl->dev); + +debug ("%s: (RST#%ld)\n" , __func__, reset_ctl->id); + +/* check dt-bindings/reset/sun8i-h3-ccu.h for max id */
File name should be generic, but the comment is not correct anyway, since we are limited by the array size, not by the DT. So please just remove this comment.
Cheers,
Andre.
Quoted 92 lines
drivers/reset/reset-sunxi.c new file +91
-0+if (reset_ctl->id >= priv->count) +return -EINVAL ; + +return 0 ; +} + +static int sunxi_reset_free (struct reset_ctl *reset_ctl) +{ +debug ("%s: (RST#%ld)\n" , __func__, reset_ctl->id); + +return 0 ; +} + +static int sunxi_set_reset (struct reset_ctl *reset_ctl,bool on) +{ +struct sunxi_reset_priv *priv =dev_get_priv (reset_ctl->dev); +const struct ccu_reset *reset =priv_to_reset (priv, reset_ctl->id); +u32 reg; + +if (!(reset->flags &CCU_CLK_F_INIT_DONE )) { +printf ("%s: (RST#%ld) unhandled\n" , __func__, reset_ctl->id); +return 0 ; + } + +debug ("%s: (RST#%ld) off#0x%x, BIT(%d)\n" , __func__, + reset_ctl->id, reset->off,ilog2 (reset->bit)); + + reg =readl (priv->base + reset->off); +if (on) + reg |= reset->bit; +else + reg &= ~reset->bit; + +writel (reg, priv->base + reset->off); + +return 0 ; +} + +static int sunxi_reset_assert (struct reset_ctl *reset_ctl) +{ +return sunxi_set_reset (reset_ctl, false); +} + +static int sunxi_reset_deassert (struct reset_ctl *reset_ctl) +{ +return sunxi_set_reset (reset_ctl, true); +} + +struct reset_ops sunxi_reset_ops = { + .request = sunxi_reset_request, + .free = sunxi_reset_free, + .rst_assert = sunxi_reset_assert, + .rst_deassert = sunxi_reset_deassert, +}; + +static int sunxi_reset_probe (struct udevice *dev) +{ +struct sunxi_reset_priv *priv =dev_get_priv (dev); + + priv->base =dev_read_addr_ptr (dev); + +return 0 ; +} + +int sunxi_reset_bind (struct udevice *dev,ulong count) +{ +struct udevice *rst_dev; +struct sunxi_reset_priv *priv; +int ret; + + ret =device_bind_driver_to_node (dev,"sunxi_reset" ,"reset" , +dev_ofnode (dev), &rst_dev); +if (ret) { +debug ("failed to bind sunxi_reset driver (ret=%d)\n" , ret); +return ret; + } + priv =malloc (sizeof (struct sunxi_reset_priv )); + priv->count = count; + priv->desc = (const struct ccu_desc *)dev_get_driver_data (dev); + rst_dev->priv = priv; + +return 0 ; +} + +U_BOOT_DRIVER (sunxi_reset) = { + .name ="sunxi_reset" , + .id =UCLASS_RESET , + .ops = &sunxi_reset_ops, + .probe = sunxi_reset_probe, + .priv_auto_alloc_size =sizeof (struct sunxi_reset_priv ), +};
PATCH v5 3/26 clk: sunxi: Add Allwinner H3/H5 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner H3/H5.
- Implement USB bus and USB clocks via ccu_clk_gate table for H3/H5, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table for H3/H5, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 ++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_h3.c | 79 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 drivers/clk/sunxi/clk_h3.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -9,6 +9,13 @@ config CLK_SUNXI if CLK_SUNXI +config CLK_SUN8I_H3 + bool "Clock driver for Allwinner H3/H5" + default MACH_SUNXI_H3_H5 + help + This enables common clock driver support for platforms based + on Allwinner H3/H5 SoC. + config CLK_SUN50I_A64 bool "Clock driver for Allwinner A64" default MACH_SUN50I
drivers/clk/sunxi/Makefile +1 -0
@@ -6,4 +6,5 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o +obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_h3.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 4/26 clk: sunxi: Add Allwinner A10/A20 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner A10/A20.
- Implement USB ahb and USB clocks via ccu_clk_gate table for A10/A20, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB resets via ccu_reset table for A10/A20, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 +++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_a10.c | 59 +++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 drivers/clk/sunxi/clk_a10.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -9,6 +9,13 @@ config CLK_SUNXI if CLK_SUNXI +config CLK_SUN4I_A10 + bool "Clock driver for Allwinner A10/A20" + default MACH_SUN4I || MACH_SUN7I + help + This enables common clock driver support for platforms based + on Allwinner A10/A20 SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -6,5 +6,6 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o +obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_a10.c new file +59 -0
59 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 5/26 clk: sunxi: Add Allwinner A10s/A13 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner A10s/A13.
- Implement USB ahb and USB clocks via ccu_clk_gate table for A10s/A13, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB resets via ccu_reset table for A10s/A13, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 +++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_a10s.c | 56 ++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 drivers/clk/sunxi/clk_a10s.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -16,6 +16,13 @@ config CLK_SUN4I_A10 This enables common clock driver support for platforms based on Allwinner A10/A20 SoC. +config CLK_SUN5I_A10S + bool "Clock driver for Allwinner A10s/A13" + default MACH_SUN5I + help + This enables common clock driver support for platforms based + on Allwinner A10s/A13 SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -7,5 +7,6 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o +obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_a10s.c new file +56 -0
56 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 6/26 clk: sunxi: Add Allwinner A31 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner A31.
- Implement USB ahb1 and USB clocks via ccu_clk_gate table for A31, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB ahb1 and USB resets via ccu_reset table for A31, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 ++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_a31.c | 68 +++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 drivers/clk/sunxi/clk_a31.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -23,6 +23,13 @@ config CLK_SUN5I_A10S This enables common clock driver support for platforms based on Allwinner A10s/A13 SoC. +config CLK_SUN6I_A31 + bool "Clock driver for Allwinner A31/A31s" + default MACH_SUN6I + help + This enables common clock driver support for platforms based + on Allwinner A31/A31s SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -8,5 +8,6 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o +obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_a31.c new file +68 -0
68 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 7/26 clk: sunxi: Add Allwinner A23/A33 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner A23/A33.
- Implement USB bus and USB clocks via ccu_clk_gate table for A23/A33, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table for A23/A33, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 +++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_a23.c | 63 +++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 drivers/clk/sunxi/clk_a23.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -30,6 +30,13 @@ config CLK_SUN6I_A31 This enables common clock driver support for platforms based on Allwinner A31/A31s SoC. +config CLK_SUN8I_A23 + bool "Clock driver for Allwinner A23/A33" + default MACH_SUN8I_A23 || MACH_SUN8I_A33 + help + This enables common clock driver support for platforms based + on Allwinner A23/A33 SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -9,5 +9,6 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o +obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_a23.c new file +63 -0
63 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 8/26 clk: sunxi: Add Allwinner A83T CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner A83T.
- Implement USB bus and USB clocks via ccu_clk_gate table for A83T, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table for A83T, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 ++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_a83t.c | 63 ++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 drivers/clk/sunxi/clk_a83t.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -37,6 +37,13 @@ config CLK_SUN8I_A23 This enables common clock driver support for platforms based on Allwinner A23/A33 SoC. +config CLK_SUN8I_A83T + bool "Clock driver for Allwinner A83T" + default MACH_SUN8I_A83T + help + This enables common clock driver support for platforms based + on Allwinner A83T SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -10,5 +10,6 @@ obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o +obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_a83t.c new file +63 -0
63 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 9/26 clk: sunxi: Add Allwinner R40 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner R40.
- Implement USB bus and USB clocks via ccu_clk_gate for R40, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table for R40, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 ++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_r40.c | 70 +++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 drivers/clk/sunxi/clk_r40.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -44,6 +44,13 @@ config CLK_SUN8I_A83T This enables common clock driver support for platforms based on Allwinner A83T SoC. +config CLK_SUN8I_R40 + bool "Clock driver for Allwinner R40" + default MACH_SUN8I_R40 + help + This enables common clock driver support for platforms based + on Allwinner R40 SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -11,5 +11,6 @@ obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o +obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_r40.c new file +70 -0
70 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 10/26 clk: sunxi: Add Allwinner V3S CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner V3S.
- Implement USB bus and USB clocks via ccu_clk_gate table for V3S, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table for V3S, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 +++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_v3s.c | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 drivers/clk/sunxi/clk_v3s.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -51,6 +51,13 @@ config CLK_SUN8I_R40 This enables common clock driver support for platforms based on Allwinner R40 SoC. +config CLK_SUN8I_V3S + bool "Clock driver for Allwinner V3S" + default MACH_SUN8I_V3S + help + This enables common clock driver support for platforms based + on Allwinner V3S SoC. + config CLK_SUN8I_H3 bool "Clock driver for Allwinner H3/H5" default MACH_SUNXI_H3_H5
drivers/clk/sunxi/Makefile +1 -0
@@ -12,5 +12,6 @@ obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o +obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_v3s.c new file +51 -0
51 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 11/26 clk: sunxi: Implement UART clocks
In reply to Jagan TekiImplement UART clocks for all Allwinner SoC
clock drivers via ccu clock gate table.
--- drivers/clk/sunxi/clk_a10.c | 9 +++++++++ drivers/clk/sunxi/clk_a10s.c | 5 +++++ drivers/clk/sunxi/clk_a23.c | 6 ++++++ drivers/clk/sunxi/clk_a31.c | 7 +++++++ drivers/clk/sunxi/clk_a64.c | 6 ++++++ drivers/clk/sunxi/clk_a83t.c | 6 ++++++ drivers/clk/sunxi/clk_h3.c | 5 +++++ drivers/clk/sunxi/clk_r40.c | 9 +++++++++ drivers/clk/sunxi/clk_v3s.c | 4 ++++ 9 files changed, 57 insertions(+)
drivers/clk/sunxi/clk_a10.c +9 -0
@@ -19,6 +19,15 @@ static struct ccu_clk_gate a10_gates[] = { [CLK_AHB_EHCI1] = GATE(0x060, BIT(3)), [CLK_AHB_OHCI1] = GATE(0x060, BIT(4)), + [CLK_APB1_UART0] = GATE(0x06c, BIT(16)), + [CLK_APB1_UART1] = GATE(0x06c, BIT(17)), + [CLK_APB1_UART2] = GATE(0x06c, BIT(18)), + [CLK_APB1_UART3] = GATE(0x06c, BIT(19)), + [CLK_APB1_UART4] = GATE(0x06c, BIT(20)), + [CLK_APB1_UART5] = GATE(0x06c, BIT(21)), + [CLK_APB1_UART6] = GATE(0x06c, BIT(22)), + [CLK_APB1_UART7] = GATE(0x06c, BIT(23)), + [CLK_USB_OHCI0] = GATE(0x0cc, BIT(6)), [CLK_USB_OHCI1] = GATE(0x0cc, BIT(7)), [CLK_USB_PHY] = GATE(0x0cc, BIT(8)),
drivers/clk/sunxi/clk_a10s.c +5 -0
@@ -17,6 +17,11 @@ static struct ccu_clk_gate a10s_gates[] = { [CLK_AHB_EHCI] = GATE(0x060, BIT(1)), [CLK_AHB_OHCI] = GATE(0x060, BIT(2)), + [CLK_APB1_UART0] = GATE(0x06c, BIT(16)), + [CLK_APB1_UART1] = GATE(0x06c, BIT(17)), + [CLK_APB1_UART2] = GATE(0x06c, BIT(18)), + [CLK_APB1_UART3] = GATE(0x06c, BIT(19)), + [CLK_USB_OHCI] = GATE(0x0cc, BIT(6)), [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)),
drivers/clk/sunxi/clk_a23.c +6 -0
@@ -17,6 +17,12 @@ static struct ccu_clk_gate a23_gates[] = { [CLK_BUS_EHCI] = GATE(0x060, BIT(26)), [CLK_BUS_OHCI] = GATE(0x060, BIT(29)), + [CLK_BUS_UART0] = GATE(0x06c, BIT(16)), + [CLK_BUS_UART1] = GATE(0x06c, BIT(17)), + [CLK_BUS_UART2] = GATE(0x06c, BIT(18)), + [CLK_BUS_UART3] = GATE(0x06c, BIT(19)), + [CLK_BUS_UART4] = GATE(0x06c, BIT(20)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_HSIC] = GATE(0x0cc, BIT(10)),
drivers/clk/sunxi/clk_a31.c +7 -0
@@ -20,6 +20,13 @@ static struct ccu_clk_gate a31_gates[] = { [CLK_AHB1_OHCI1] = GATE(0x060, BIT(30)), [CLK_AHB1_OHCI2] = GATE(0x060, BIT(31)), + [CLK_APB2_UART0] = GATE(0x06c, BIT(16)), + [CLK_APB2_UART1] = GATE(0x06c, BIT(17)), + [CLK_APB2_UART2] = GATE(0x06c, BIT(18)), + [CLK_APB2_UART3] = GATE(0x06c, BIT(19)), + [CLK_APB2_UART4] = GATE(0x06c, BIT(20)), + [CLK_APB2_UART5] = GATE(0x06c, BIT(21)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_PHY2] = GATE(0x0cc, BIT(10)),
drivers/clk/sunxi/clk_a64.c +6 -0
@@ -19,6 +19,12 @@ static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OHCI0] = GATE(0x060, BIT(28)), [CLK_BUS_OHCI1] = GATE(0x060, BIT(29)), + [CLK_BUS_UART0] = GATE(0x06c, BIT(16)), + [CLK_BUS_UART1] = GATE(0x06c, BIT(17)), + [CLK_BUS_UART2] = GATE(0x06c, BIT(18)), + [CLK_BUS_UART3] = GATE(0x06c, BIT(19)), + [CLK_BUS_UART4] = GATE(0x06c, BIT(20)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_HSIC] = GATE(0x0cc, BIT(10)),
drivers/clk/sunxi/clk_a83t.c +6 -0
@@ -18,6 +18,12 @@ static struct ccu_clk_gate a83t_gates[] = { [CLK_BUS_EHCI1] = GATE(0x060, BIT(27)), [CLK_BUS_OHCI0] = GATE(0x060, BIT(29)), + [CLK_BUS_UART0] = GATE(0x06c, BIT(16)), + [CLK_BUS_UART1] = GATE(0x06c, BIT(17)), + [CLK_BUS_UART2] = GATE(0x06c, BIT(18)), + [CLK_BUS_UART3] = GATE(0x06c, BIT(19)), + [CLK_BUS_UART4] = GATE(0x06c, BIT(20)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_HSIC] = GATE(0x0cc, BIT(10)),
drivers/clk/sunxi/clk_h3.c +5 -0
@@ -23,6 +23,11 @@ static struct ccu_clk_gate h3_gates[] = { [CLK_BUS_OHCI2] = GATE(0x060, BIT(30)), [CLK_BUS_OHCI3] = GATE(0x060, BIT(31)), + [CLK_BUS_UART0] = GATE(0x06c, BIT(16)), + [CLK_BUS_UART1] = GATE(0x06c, BIT(17)), + [CLK_BUS_UART2] = GATE(0x06c, BIT(18)), + [CLK_BUS_UART3] = GATE(0x06c, BIT(19)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_PHY2] = GATE(0x0cc, BIT(10)),
drivers/clk/sunxi/clk_r40.c +9 -0
@@ -21,6 +21,15 @@ static struct ccu_clk_gate r40_gates[] = { [CLK_BUS_OHCI1] = GATE(0x060, BIT(30)), [CLK_BUS_OHCI2] = GATE(0x060, BIT(31)), + [CLK_BUS_UART0] = GATE(0x06c, BIT(16)), + [CLK_BUS_UART1] = GATE(0x06c, BIT(17)), + [CLK_BUS_UART2] = GATE(0x06c, BIT(18)), + [CLK_BUS_UART3] = GATE(0x06c, BIT(19)), + [CLK_BUS_UART4] = GATE(0x06c, BIT(20)), + [CLK_BUS_UART5] = GATE(0x06c, BIT(21)), + [CLK_BUS_UART6] = GATE(0x06c, BIT(22)), + [CLK_BUS_UART7] = GATE(0x06c, BIT(23)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_PHY2] = GATE(0x0cc, BIT(10)),
drivers/clk/sunxi/clk_v3s.c +4 -0
@@ -15,6 +15,10 @@static struct ccu_clk_gate v3s_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (24 )), + [CLK_BUS_UART0 ] =GATE (0x06c ,BIT (16 )), + [CLK_BUS_UART1 ] =GATE (0x06c ,BIT (17 )), + [CLK_BUS_UART2 ] =GATE (0x06c ,BIT (18 )), + [CLK_USB_PHY0 ] =GATE (0x0cc ,BIT (8 )), };
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 12/26 clk: sunxi: Implement UART resets
In reply to Jagan TekiImplement UART resets for all relevant Allwinner SoC clock drivers via ccu reset table.
--- drivers/clk/sunxi/clk_a23.c | 6 ++++++ drivers/clk/sunxi/clk_a31.c | 7 +++++++ drivers/clk/sunxi/clk_a64.c | 6 ++++++ drivers/clk/sunxi/clk_a83t.c | 6 ++++++ drivers/clk/sunxi/clk_h3.c | 5 +++++ drivers/clk/sunxi/clk_r40.c | 9 +++++++++ drivers/clk/sunxi/clk_v3s.c | 4 ++++ 7 files changed, 43 insertions(+)
drivers/clk/sunxi/clk_a23.c +6 -0
@@ -38,6 +38,12 @@ static struct ccu_reset a23_resets[] = { [RST_BUS_OTG] = RESET(0x2c0, BIT(24)), [RST_BUS_EHCI] = RESET(0x2c0, BIT(26)), [RST_BUS_OHCI] = RESET(0x2c0, BIT(29)), + + [RST_BUS_UART0] = RESET(0x2d8, BIT(16)), + [RST_BUS_UART1] = RESET(0x2d8, BIT(17)), + [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), + [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), + [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), };static const struct ccu_desc a23_ccu_desc = {
drivers/clk/sunxi/clk_a31.c +7 -0
@@ -46,6 +46,13 @@ static struct ccu_reset a31_resets[] = { [RST_AHB1_OHCI0] = RESET(0x2c0, BIT(29)), [RST_AHB1_OHCI1] = RESET(0x2c0, BIT(30)), [RST_AHB1_OHCI2] = RESET(0x2c0, BIT(31)), + + [RST_APB2_UART0] = RESET(0x2d8, BIT(16)), + [RST_APB2_UART1] = RESET(0x2d8, BIT(17)), + [RST_APB2_UART2] = RESET(0x2d8, BIT(18)), + [RST_APB2_UART3] = RESET(0x2d8, BIT(19)), + [RST_APB2_UART4] = RESET(0x2d8, BIT(20)), + [RST_APB2_UART5] = RESET(0x2d8, BIT(21)), };static const struct ccu_desc a31_ccu_desc = {
drivers/clk/sunxi/clk_a64.c +6 -0
@@ -43,6 +43,12 @@ static const struct ccu_reset a64_resets[] = { [RST_BUS_EHCI1] = RESET(0x2c0, BIT(25)), [RST_BUS_OHCI0] = RESET(0x2c0, BIT(28)), [RST_BUS_OHCI1] = RESET(0x2c0, BIT(29)), + + [RST_BUS_UART0] = RESET(0x2d8, BIT(16)), + [RST_BUS_UART1] = RESET(0x2d8, BIT(17)), + [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), + [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), + [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), };static const struct ccu_desc a64_ccu_desc = {
drivers/clk/sunxi/clk_a83t.c +6 -0
@@ -40,6 +40,12 @@ static struct ccu_reset a83t_resets[] = { [RST_BUS_EHCI0] = RESET(0x2c0, BIT(26)), [RST_BUS_EHCI1] = RESET(0x2c0, BIT(27)), [RST_BUS_OHCI0] = RESET(0x2c0, BIT(29)), + + [RST_BUS_UART0] = RESET(0x2d8, BIT(16)), + [RST_BUS_UART1] = RESET(0x2d8, BIT(17)), + [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), + [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), + [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), };static const struct ccu_desc a83t_ccu_desc = {
drivers/clk/sunxi/clk_h3.c +5 -0
@@ -53,6 +53,11 @@ static struct ccu_reset h3_resets[] = { [RST_BUS_OHCI1] = RESET(0x2c0, BIT(29)), [RST_BUS_OHCI2] = RESET(0x2c0, BIT(30)), [RST_BUS_OHCI3] = RESET(0x2c0, BIT(31)), + + [RST_BUS_UART0] = RESET(0x2d8, BIT(16)), + [RST_BUS_UART1] = RESET(0x2d8, BIT(17)), + [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), + [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), };static const struct ccu_desc h3_ccu_desc = {
drivers/clk/sunxi/clk_r40.c +9 -0
@@ -50,6 +50,15 @@ static struct ccu_reset r40_resets[] = { [RST_BUS_OHCI0] = RESET(0x2c0, BIT(29)), [RST_BUS_OHCI1] = RESET(0x2c0, BIT(30)), [RST_BUS_OHCI2] = RESET(0x2c0, BIT(31)), + + [RST_BUS_UART0] = RESET(0x2d8, BIT(16)), + [RST_BUS_UART1] = RESET(0x2d8, BIT(17)), + [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), + [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), + [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), + [RST_BUS_UART5] = RESET(0x2d8, BIT(21)), + [RST_BUS_UART6] = RESET(0x2d8, BIT(22)), + [RST_BUS_UART7] = RESET(0x2d8, BIT(23)), };static const struct ccu_desc r40_ccu_desc = {
drivers/clk/sunxi/clk_v3s.c +4 -0
@@ -26,6 +26,10 @@ static struct ccu_reset v3s_resets[] = { [RST_USB_PHY0] = RESET(0x0cc, BIT(0)), [RST_BUS_OTG] = RESET(0x2c0, BIT(24)), + + [RST_BUS_UART0] = RESET(0x2d8, BIT(16)), + [RST_BUS_UART1] = RESET(0x2d8, BIT(17)), + [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), };static const struct ccu_desc v3s_ccu_desc = {
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 13/26 clk: sunxi: Add Allwinner H6 CLK driver
In reply to Jagan TekiAdd initial clock driver for Allwinner H6.
- Implement UART bus clocks via ccu_clk_gate table for H6, so it can accessed in common clk enable and disable functions from clk_sunxi.c
- Implement UART bus resets via ccu_reset table for H6, so it can accessed in common reset deassert and assert functions from reset-sunxi.c
--- drivers/clk/sunxi/Kconfig | 7 +++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_h6.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 drivers/clk/sunxi/clk_h6.c
drivers/clk/sunxi/Kconfig +7 -0
@@ -65,6 +65,13 @@ config CLK_SUN8I_H3 This enables common clock driver support for platforms based on Allwinner H3/H5 SoC. +config CLK_SUN50I_H6 + bool "Clock driver for Allwinner H6" + default MACH_SUN50I_H6 + help + This enables common clock driver support for platforms based + on Allwinner H6 SoC. + config CLK_SUN50I_A64 bool "Clock driver for Allwinner A64" default MACH_SUN50I
drivers/clk/sunxi/Makefile +1 -0
@@ -14,4 +14,5 @@ obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o +obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
drivers/clk/sunxi/clk_h6.c new file +53 -0
53 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 14/26 sunxi: A64: Update sun50i-a64-ccu.h
In reply to Jagan TekiUpdate sun50i-a64-ccu.h from the Linux sunxi/dt64-for-4.20 tree:
commit 679294497be31596e1c9c61507746d72b6b05f26
Author: Rodrigo Exterckötter Tjäder <[email protected]> Date: Wed Sep 26 19:48:24 2018 +0000
arm64: dts: allwinner: a64: a64-olinuxino: set the PHY TX delay
This should be a part of previous sync patch from
commit 1b39a1834ed182bbd8036a5cd74a9ea111fa4691
Author: Andre Przywara <[email protected]> Date: Mon Oct 29 00:56:47 2018 +0000
sunxi: A64: Update .dts/.dtsi files
--- include/dt-bindings/clock/sun50i-a64-ccu.h | 2 ++ 1 file changed, 2 insertions(+)
include/dt-bindings/clock/sun50i-a64-ccu.h +2 -0
@@ -43,6 +43,8 @@#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_#define _DT_BINDINGS_CLK_SUN50I_A64_H_ +#define CLK_PLL_PERIPH0 11 +#define CLK_BUS_MIPI_DSI 28#define CLK_BUS_CE 29#define CLK_BUS_DMA 30
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
In reply to Jagan TekiClock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via ccu_clock_gate.
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via ccu_clock_tree.
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with get_rate functionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.
Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part of ccu_clock_gate.
--- arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c | 40 ++++++ drivers/clk/sunxi/clk_sunxi.c | 182 ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)
arch/arm/include/asm/arch-sunxi/ccu.h +191 -1
@@ -7,15 +7,204 @@#ifndef _ASM_ARCH_CCU_H#define _ASM_ARCH_CCU_H +#define OSC_32K_ULL 32000ULL +#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type +* @CCU_CLK_TYPE_FIXED: fixed clock type +* @CCU_CLK_TYPE_MP: mp clock type +* @CCU_CLK_TYPE_NK: nk clock type +*/ +enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/** * enum ccu_clk_flags - ccu clock flags * -* @CCU_CLK_F_INIT_DONE: clock gate init done check +* @CCU_CLK_F_INIT_DONE: clock tree/gate init done check +* @CCU_CLK_F_POSTDIV: clock post divider */ enum ccu_clk_flags {CCU_CLK_F_INIT_DONE =BIT (0 ), +CCU_CLK_F_POSTDIV =BIT (1 ), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX (_shift, _width, _offset, \ + _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m +* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent; +enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux; +unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE (_parent, _type, _off, \ + _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \ +} + +#define MISC (_parent) \ + TREE(_parent, CCU_CLK_TYPE_MISC, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE) + +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset
@@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };
drivers/clk/sunxi/clk_a64.c +40 -0
@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = { +CLK_OSC_24M , +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),
@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };
drivers/clk/sunxi/clk_sunxi.c +182 -0
194 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
Quoted 6 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.
So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Quoted 2 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.
For a start, can we use more descriptive names than those very specific MP/NK names? DIV_MUX and PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.
Quoted 22 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c | 40 ++++++ drivers/clk/sunxi/clk_sunxi.c | 182 ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)arch/arm/include/asm/arch-sunxi/ccu.h +0
-0
arch/arm/include/asm/arch-sunxi/ccu.h line 10
Quoted 4 lines
arch/arm/include/asm/arch-sunxi/ccu.h +1
-0@@ -7,15 +7,204 @@#ifndef _ASM_ARCH_CCU_H#define _ASM_ARCH_CCU_H +#define OSC_32K_ULL 32000ULL
32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type
What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
arch/arm/include/asm/arch-sunxi/ccu.h line 19
Quoted 3 lines
arch/arm/include/asm/arch-sunxi/ccu.h +3
-0+* @CCU_CLK_TYPE_FIXED: fixed clock type +* @CCU_CLK_TYPE_MP: mp clock type +* @CCU_CLK_TYPE_NK: nk clock type
What is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fields
This gives more speaking names, plus some explanation.
arch/arm/include/asm/arch-sunxi/ccu.h line 31
Quoted 13 lines
arch/arm/include/asm/arch-sunxi/ccu.h +9
-1+*/ +enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/** * enum ccu_clk_flags - ccu clock flags * -* @CCU_CLK_F_INIT_DONE: clock gate init done check +* @CCU_CLK_F_INIT_DONE: clock tree/gate init done check
Is this flag to tell implemented clocks apart from unimplemented ones, which would be reset to all zeroes by the compiler? Then it should be called something with VALID in it.
Quoted 84 lines
arch/arm/include/asm/arch-sunxi/ccu.h +79
-0+* @CCU_CLK_F_POSTDIV: clock post divider */ enum ccu_clk_flags {CCU_CLK_F_INIT_DONE =BIT (0 ), +CCU_CLK_F_POSTDIV =BIT (1 ), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX (_shift, _width, _offset, \ + _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m
arch/arm/include/asm/arch-sunxi/ccu.h line 125
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent;
Shouldn't that be called "parents" instead?
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux;
arch/arm/include/asm/arch-sunxi/ccu.h line 141
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE(_parent, _type, _off, \
Just a nit, but TREE is somewhat confusing here, as this just constructs a single entry in an array. The tree property is realised through the parent array, if I get this correctly.
So should we name this ENTRY or CLK_ENTRY instead?
Quoted 17 lines
arch/arm/include/asm/arch-sunxi/ccu.h +17
-0+ _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \
arch/arm/include/asm/arch-sunxi/ccu.h line 168
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+} + +#define MISC (_parent) \ + TREE(_parent, CCU_CLK_TYPE_MISC, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE)
If MISC is really something like GATE or SIMPLE, would it be possible to construct the single element array here, so that the macro just takes the one parent clock ID here, instead of referring to an extra array?
Quoted 55 lines
arch/arm/include/asm/arch-sunxi/ccu.h +40
-0+ +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset @@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };drivers/clk/sunxi/clk_a64.c +0
-0
drivers/clk/sunxi/clk_a64.c line 19
Quoted 8 lines
drivers/clk/sunxi/clk_a64.c +5
-0@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = {
Why is this long? That's the DT clock index, which is 32 bit wide, right? Just unsigned int or uint32_t should be sufficient. long is quite a treacherous type to use, especially as we share code between 32 and 64-bit architectures.
Quoted 50 lines
drivers/clk/sunxi/clk_a64.c +35
-0+ CLK_OSC_24M, +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };drivers/clk/sunxi/clk_sunxi.c +0
-0
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 22
Quoted 5 lines
drivers/clk/sunxi/clk_sunxi.c +2
-0@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,return &priv->desc->gates[id]; } +static const struct ccu_clk_tree *priv_to_tree (struct ccu_priv *priv, +unsigned long id)
Again, why long here? Especially as it's u32 in the function below.
Quoted 6 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +return &priv->desc->tree[id]; +} + +static int sunxi_get_parent_idx (const struct ccu_clk_tree *tree,void *base) +{
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 38
Quoted 10 lines
drivers/clk/sunxi/clk_sunxi.c +10
-0+u32 reg, idx; + + reg =readl (base + tree->off); + idx = reg >> tree->mux.shift; + idx &= (1 << tree->mux.width) -1 ; + +return idx; +} + +static ulong sunxi_fixed_get_rate (struct clk *clk,unsigned long id)
Same "long" question for both the return type and the id. And for everything below.
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 50
Quoted 12 lines
drivers/clk/sunxi/clk_sunxi.c +12
-0+{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { +printf ("%s: (CLK#%ld) unhandled\n" , __func__, clk->id); +return 0 ; + } + +return tree->fixed_rate; +} +
So why are there all those separate functions? Isn't that all the same
algorithm: adjust the parent rate based on the clock type? I reworked this with recursive calls and it's MUCH less code:
(fill the gaps, using your types for your convenience ;-)
static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong parent_rate) { NK algorithm of sunxi_nk_get_rate }
static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong parent_rate) { MP algorithm of sunxi_mp_get_rate }
static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid) {
....
switch (tree->type) {
case CCU_CLK_TYPE_MISC:
return sunxi_calc_clk_rate(priv, tree->parent[0]);
case CCU_CLK_TYPE_FIXED:
return tree->fixed_rate;
case CCU_CLK_TYPE_NK:
rate = sunxi_calc_clk_rate(priv,
sunxi_get_parent_id(tree, priv->base));
return sunxi_apply_pll(priv, clkid, rate);
(similar for _MP)...
}
static ulong sunxi_clk_get_rate(struct clk *clk)
{
struct ccu_priv *priv = dev_get_priv(clk->dev);
return sunxi_calc_clk_rate(priv, clk->id);
}This removes about 80 lines from that file.
Let me know if I should post my rework.
Cheers,
Andre.
Quoted 163 lines
drivers/clk/sunxi/clk_sunxi.c +152
-0+static ulong sunxi_nk_get_parent_rate (struct clk *clk,unsigned long id) +{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); +ulong rate =0 ; + +switch (tree->type) { +case CCU_CLK_TYPE_FIXED : + rate =sunxi_fixed_get_rate (clk, id); +break ; +default : +printf ("%s: Unknown (TYPE#%d)\n" , __func__, tree->type); +break ; + } + +return rate; +} + +static ulong sunxi_nk_get_rate (struct clk *clk,unsigned long id) +{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); +ulong rate, parent_rate; +unsigned long n, k; +u32 reg; + + parent_rate =sunxi_nk_get_parent_rate (clk, tree->parent[0 ]); + + reg =readl (priv->base + tree->off); + + n = reg >> tree->n.shift; + n &= (1 << tree->n.width) -1 ; + n += tree->n.offset; +if (!n) + n++; + + k = reg >> tree->k.shift; + k &= (1 << tree->k.width) -1 ; + k += tree->k.offset; +if (!k) + k++; + + rate = parent_rate * n * k; +if (tree->flags &CCU_CLK_F_POSTDIV ) + rate /= tree->postdiv; + +return rate; +} + +static ulong sunxi_mp_get_parent_rate (struct clk *clk,unsigned long id) +{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); +ulong rate =0 ; + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { +printf ("%s: (CLK#%ld) unhandled\n" , __func__, clk->id); +return 0 ; + } + +switch (tree->type) { +case CCU_CLK_TYPE_FIXED : + rate =sunxi_fixed_get_rate (clk, id); +break ; +case CCU_CLK_TYPE_NK : + rate =sunxi_nk_get_rate (clk, id); +break ; +default : +printf ("%s: (TYPE#%d) unhandled\n" , __func__, tree->type); +break ; + } + +return rate; +} + +static ulong sunxi_mp_get_rate (struct clk *clk,unsigned long id) +{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); +unsigned int m, p; +ulong parent_rate; +u32 reg, idx; + + idx =sunxi_get_parent_idx (tree, priv->base); +if (idx <0 ) { +printf ("%s: Wrong parent index %d\n" , __func__, idx); +return 0 ; + } + + parent_rate =sunxi_mp_get_parent_rate (clk, tree->parent[idx]); + + reg =readl (priv->base + tree->off); + + m = reg >> tree->m.shift; + m &= (1 << tree->m.width) -1 ; + m += tree->m.offset; +if (!m) + m++; + + p = reg >> tree->p.shift; + p &= (1 << tree->p.width) -1 ; + +return (parent_rate >> p) / m; +} + +static ulong sunxi_misc_get_rate (struct clk *clk,unsigned long id) +{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); +ulong rate =0 ; + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { +printf ("%s: (CLK#%ld) unhandled\n" , __func__, clk->id); +return 0 ; + } + +switch (tree->type) { +case CCU_CLK_TYPE_MP : + rate =sunxi_mp_get_rate (clk, id); +break ; +default : +printf ("%s: (TYPE#%d) unhandled\n" , __func__, tree->type); +break ; + } + +return rate; +} + +static ulong sunxi_clk_get_rate (struct clk *clk) +{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, clk->id); +ulong rate =0 ; + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { +printf ("%s: (CLK#%ld) unhandled\n" , __func__, clk->id); +return 0 ; + } + +switch (tree->type) { +case CCU_CLK_TYPE_MISC : + rate =sunxi_misc_get_rate (clk, tree->parent[0 ]); +break ; +default : +printf ("%s: (TYPE#%d) unhandled\n" , __func__, tree->type); +break ; + } + +return rate; +} +static int sunxi_set_gate (struct clk *clk,bool on) {struct ccu_priv *priv =dev_get_priv (clk->dev);@@ -56,6 +237,7 @@ static int sunxi_clk_disable(struct clk *clk)struct clk_ops sunxi_clk_ops = { .enable = sunxi_clk_enable, .disable = sunxi_clk_disable, + .get_rate = sunxi_clk_get_rate, };int sunxi_clk_probe (struct udevice *dev)
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
Quoted 68 lines · André Przywara
Quoted 6 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Quoted 2 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 22 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c | 40 ++++++ drivers/clk/sunxi/clk_sunxi.c | 182 ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)arch/arm/include/asm/arch-sunxi/ccu.h +0
-0arch/arm/include/asm/arch-sunxi/ccu.h line 10
Quoted 4 lines
arch/arm/include/asm/arch-sunxi/ccu.h +1
-0@@ -7,15 +7,204 @@#ifndef _ASM_ARCH_CCU_H#define _ASM_ARCH_CCU_H +#define OSC_32K_ULL 32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 7 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 19
Quoted 3 lines
arch/arm/include/asm/arch-sunxi/ccu.h +3
-0+* @CCU_CLK_TYPE_FIXED: fixed clock type +* @CCU_CLK_TYPE_MP: mp clock type +* @CCU_CLK_TYPE_NK: nk clock type What is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
We have PLL with 2 multipliers, but also others with other factors sets, so that will end up being confusing. If the MP, NK and so on stuff is confusing, maybe we should just add a comment on top of that structure to explain what those factors are and what it actually means?
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190107/26a42f3f/attachment.sig>
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
On Mon, 7 Jan 2019 14:01:01 +0100
Maxime Ripard <[email protected]> wrote:
Hi,
Quoted 81 lines · André Przywara
Quoted 71 lines · Jagan Teki
Quoted 7 lines
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Quoted 3 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 19 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192+++++++++++++++++++++++++-
drivers/clk/sunxi/clk_a64.c
| 40 ++++++drivers/clk/sunxi/clk_sunxi.c| 182
++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)(quoted diff) +0
-0Quoted 8 lines
b/arch/arm/include/asm/arch-sunxi/ccu.hindex3fdc26978d..61b8c36b3b100644 ---a/arch/arm/include/asm/arch-sunxi/ccu.h+++b/arch/arm/include/asm/arch-sunxi/ccu.h@@ -7,15 +7,204 @@
#ifndef_ASM_ARCH_CCU_H
#define_ASM_ARCH_CCU_H+#define
OSC_32K_ULL32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 8 lines
Quoted 3 lines
+ * @CCU_CLK_TYPE_FIXED: fixed clock type
+ * @CCU_CLK_TYPE_MP: mp clock type
+ * @CCU_CLK_TYPE_NK: nk clock typeWhat is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier
fields
Quoted 5 lines
We have PLL with 2 multipliers, but also others with other factors sets, so that will end up being confusing. If the MP, NK and so on stuff is confusing, maybe we should just add a comment on top of that structure to explain what those factors are and what it actually means?
Fair enough, or we name it CCU_CLK_TYPE_PLL_NK, because this is what this type deals with. Point is that by chance I happened to know about those naming of factors in the manual, but other might be lost by just seeing "mp" or "nk", without any explanation - and the comment doesn't help here at all.
The other part is that the "TYPE_MP" is twice as confusing, as it can perfectly describe the MMC clocks, which use "N" and "M" in the A64 manual, for instance. That's why my suggestion for calling a spade a spade and saying it's a divider clock with a multiplexer. Happy to have the Linux naming in the comments.
Thanks,
Andre.
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
Quoted 19 lines · Andre Przywara
Quoted 13 lines
Quoted 4 lines
What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 8 lines
Quoted 3 lines
+ * @CCU_CLK_TYPE_FIXED: fixed clock type
+ * @CCU_CLK_TYPE_MP: mp clock type
+ * @CCU_CLK_TYPE_NK: nk clock typeWhat is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier
fieldsQuoted 5 lines
We have PLL with 2 multipliers, but also others with other factors sets, so that will end up being confusing. If the MP, NK and so on stuff is confusing, maybe we should just add a comment on top of that structure to explain what those factors are and what it actually means?
Quoted 5 lines
Fair enough, or we name it
CCU_CLK_TYPE_PLL_NK, because this is what this type deals with. Point is that by chance I happened to know about those naming of factors in the manual, but other might be lost by just seeing "mp" or "nk", without any explanation - and the comment doesn't help here at all.
Either way, we should really document this properly.
Quoted 5 lines
The other part is that the "
TYPE_MP" is twice as confusing, as it can perfectly describe the MMC clocks, which use "N" and "M" in the A64 manual, for instance. That's why my suggestion for calling a spade a spade and saying it's a divider clock with a multiplexer. Happy to have the Linux naming in the comments.
NM and MP aren't really the same though. NM is one multiplier and one divider, while MP is one divider and one right shift.
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190107/6e86550c/attachment.sig>
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
In reply to André PrzywaraQuoted 9 lines · André Przywara
Quoted 6 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.
Quoted 7 lines
So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Exactly. Idea is to keep the macro's as simple as possible.
Adding gates clocks separately make easy and reasonable way to enable/disable clock operations. We even operate with single macro with all clock attributes along with gate(either another member or common structure like Linux does), but that seems not simple as per as my experince since there are many IP's like USB's just need enable/disable.
Quoted 42 lines
Quoted 3 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 22 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c | 40 ++++++ drivers/clk/sunxi/clk_sunxi.c | 182 ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)arch/arm/include/asm/arch-sunxi/ccu.h +0
-0arch/arm/include/asm/arch-sunxi/ccu.h line 10
Quoted 4 lines
arch/arm/include/asm/arch-sunxi/ccu.h +1
-0@@ -7,15 +7,204 @@#ifndef _ASM_ARCH_CCU_H#define _ASM_ARCH_CCU_H +#define OSC_32K_ULL 32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Unlike MP type in MMC, UART doesn't need any clock attributes like dividers, mux, etc, just have attached parent. I don't think UART clock is simple one It has parent, that indeed have another parents and so...on, ie reason I named as MISC.
Quoted 21 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 19
Quoted 4 lines
arch/arm/include/asm/arch-sunxi/ccu.h +3
-0+* @CCU_CLK_TYPE_FIXED: fixed clock type +* @CCU_CLK_TYPE_MP: mp clock type +* @CCU_CLK_TYPE_NK: nk clock type What is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fieldsThis gives more speaking names, plus some explanation.
Quoted 9 lines
arch/arm/include/asm/arch-sunxi/ccu.h +8
-0+*/ +enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/**
Quoted 8 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 31
Quoted 4 lines
arch/arm/include/asm/arch-sunxi/ccu.h +1
-1* enum ccu_clk_flags - ccu clock flags * -* @CCU_CLK_F_INIT_DONE: clock gate init done check +* @CCU_CLK_F_INIT_DONE: clock tree/gate init done check Is this flag to tell implemented clocks apart from unimplemented ones, which would be reset to all zeroes by the compiler? Then it should be called something with VALID in it.
Since the flags attached with real numeric initialized by macro itself rather than some other source like complier or any, so marked INIT_DONE seems to meaningful.
and eventually the same verified in code whether the init done or not.
Quoted 335 lines
Quoted 85 lines
arch/arm/include/asm/arch-sunxi/ccu.h +79
-0+* @CCU_CLK_F_POSTDIV: clock post divider */ enum ccu_clk_flags {CCU_CLK_F_INIT_DONE =BIT (0 ), +CCU_CLK_F_POSTDIV =BIT (1 ), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX (_shift, _width, _offset, \ + _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m arch/arm/include/asm/arch-sunxi/ccu.h line 125
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent;Shouldn't that be called "parents" instead?
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux;arch/arm/include/asm/arch-sunxi/ccu.h line 141
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE(_parent, _type, _off, \Just a nit, but TREE is somewhat confusing here, as this just constructs a single entry in an array. The tree property is realised through the parent array, if I get this correctly.
So should we name this ENTRY orCLK_ENTRYinstead?Quoted 17 lines
arch/arm/include/asm/arch-sunxi/ccu.h +17
-0+ _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \arch/arm/include/asm/arch-sunxi/ccu.h line 168
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+} + +#define MISC (_parent) \ + TREE(_parent, CCU_CLK_TYPE_MISC, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE)If MISC is really something like GATE or SIMPLE, would it be possible to construct the single element array here, so that the macro just takes the one parent clock ID here, instead of referring to an extra array?
Quoted 55 lines
arch/arm/include/asm/arch-sunxi/ccu.h +40
-0+ +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset @@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };drivers/clk/sunxi/clk_a64.c +0
-0drivers/clk/sunxi/clk_a64.c line 19
Quoted 8 lines
drivers/clk/sunxi/clk_a64.c +5
-0@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = {Why is this long? That's the DT clock index, which is 32 bit wide, right? Just unsigned int or
uint32_tshould be sufficient. long is quite a treacherous type to use, especially as we share code between 32 and 64-bit architectures.Quoted 50 lines
drivers/clk/sunxi/clk_a64.c +35
-0+ CLK_OSC_24M, +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };drivers/clk/sunxi/clk_sunxi.c +0
-0drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 22
Quoted 5 lines
drivers/clk/sunxi/clk_sunxi.c +2
-0@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,return &priv->desc->gates[id]; } +static const struct ccu_clk_tree *priv_to_tree (struct ccu_priv *priv, +unsigned long id)Again, why long here? Especially as it's u32 in the function below.
Quoted 6 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +return &priv->desc->tree[id]; +} + +static int sunxi_get_parent_idx (const struct ccu_clk_tree *tree,void *base) +{drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 38
Quoted 10 lines
drivers/clk/sunxi/clk_sunxi.c +10
-0+u32 reg, idx; + + reg =readl (base + tree->off); + idx = reg >> tree->mux.shift; + idx &= (1 << tree->mux.width) -1 ; + +return idx; +} + +static ulong sunxi_fixed_get_rate (struct clk *clk,unsigned long id)Same "long" question for both the return type and the id. And for everything below.
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 50
Quoted 12 lines
drivers/clk/sunxi/clk_sunxi.c +12
-0+{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { +printf ("%s: (CLK#%ld) unhandled\n" , __func__, clk->id); +return 0 ; + } + +return tree->fixed_rate; +} +So why are there all those separate functions? Isn't that all the same
algorithm: adjust the parent rate based on the clock type? I reworked this with recursive calls and it's MUCH less code:(fill the gaps, using your types for your convenience ;-)
static ulong
sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong parent_rate){ NK algorithm ofsunxi_nk_get_rate}
static ulongsunxi_apply_div(struct ccu_priv *priv, ulong id, ulong parent_rate){ MP algorithm ofsunxi_mp_get_rate}
static ulongsunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid){
....switch (tree->type) { case CCU_CLK_TYPE_MISC: return sunxi_calc_clk_rate(priv, tree->parent[0]); case CCU_CLK_TYPE_FIXED: return tree->fixed_rate; case CCU_CLK_TYPE_NK: rate = sunxi_calc_clk_rate(priv, sunxi_get_parent_id(tree, priv->base)); return sunxi_apply_pll(priv, clkid, rate); (similar for _MP)
Quoted 2 lines
...
}
Initially I would tried the recursive and yes code can reduce but using recursive can leed more disadvantage in-terms of code tracing during long run. Due to all these factors I used simple function calls.
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
On Tue, 8 Jan 2019 16:27:14 +0530
Jagan Teki <[email protected]> wrote:
Hi,
Quoted 86 lines
Quoted 10 lines · André Przywara
Quoted 7 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.Quoted 8 lines
So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Exactly. Idea is to keep the macro's as simple as possible.
Adding gates clocks separately make easy and reasonable way to enable/disable clock operations. We even operate with single macro with all clock attributes along with gate(either another member or common structure like Linux does), but that seems not simple as per as my experince since there are many IP's like USB's just need enable/disable.
Quoted 44 lines
Quoted 4 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 19 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192+++++++++++++++++++++++++-
drivers/clk/sunxi/clk_a64.c
| 40 ++++++drivers/clk/sunxi/clk_sunxi.c| 182
++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)(quoted diff) +0
-0Quoted 8 lines
b/arch/arm/include/asm/arch-sunxi/ccu.hindex3fdc26978d..61b8c36b3b100644 ---a/arch/arm/include/asm/arch-sunxi/ccu.h+++b/arch/arm/include/asm/arch-sunxi/ccu.h@@ -7,15 +7,204 @@
#ifndef_ASM_ARCH_CCU_H
#define_ASM_ARCH_CCU_H+#define
OSC_32K_ULL32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
Quoted 11 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 4 lines
Unlike MP type in MMC, UART doesn't need any clock attributes like dividers, mux, etc, just have attached parent. I don't think UART clock is simple one It has parent, that indeed have another parents and so...on, ie reason I named as MISC.
Not really, as far as I can see the UART clock is a just a gate clock as many others, with one parent (APB2).
The fact that APB2 in turn can have multiple parents doesn't affect the UART clock itself, as you model this via the clock tree.
In fact we could have similar clocks in the tree structure for the other gate clocks (USB, for instance), it's just that the UART is the only user so far which actually queries the clock rate.
So MISC is way too generic, I would still prefer CCU_CLK_TYPE_GATE.
Quoted 30 lines
Quoted 21 lines
Quoted 3 lines
+ * @CCU_CLK_TYPE_FIXED: fixed clock type
+ * @CCU_CLK_TYPE_MP: mp clock type
+ * @CCU_CLK_TYPE_NK: nk clock typeWhat is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fieldsThis gives more speaking names, plus some explanation.
Quoted 10 lines
+ */
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/** * enum ccu_clk_flags - ccu clock flags Quoted 8 lines
Quoted 4 lines
*
- * @CCU_CLK_F_INIT_DONE: clock gate init done check
+ * @CCU_CLK_F_INIT_DONE: clock tree/gate init done
checkIs this flag to tell implemented clocks apart from unimplemented ones, which would be reset to all zeroes by the compiler? Then it should be called something with VALID in it.
Quoted 3 lines
Since the flags attached with real numeric initialized by macro itself rather than some other source like complier or any, so marked
INIT_DONEseems to meaningful.
When I read INIT_DONE I understand some code has initialised this clock at some point, which isn't true. I don't fight the flag itself, just the name.
Quoted 345 lines
and eventually the same verified in code whether the init done or not.
Quoted 340 lines
Quoted 86 lines
+ * @CCU_CLK_F_POSTDIV: clock post divider
*/
enumccu_clk_flags{
CCU_CLK_F_INIT_DONE= BIT(0),arch/arm/include/asm/arch-sunxi/ccu.h +19
-0+ CCU_CLK_F_POSTDIV = BIT(1), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
_offset, \arch/arm/include/asm/arch-sunxi/ccu.h +59
-0+ _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m arch/arm/include/asm/arch-sunxi/ccu.h line 125
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent;Shouldn't that be called "parents" instead?
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux;arch/arm/include/asm/arch-sunxi/ccu.h line 141
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE(_parent, _type, _off, \Just a nit, but TREE is somewhat confusing here, as this just constructs a single entry in an array. The tree property is realised through the parent array, if I get this correctly. So should we name this ENTRY or
CLK_ENTRYinstead?Quoted 21 lines
arch/arm/include/asm/arch-sunxi/ccu.h +20
-0+ _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \ +} + +#define
MISC(_parent)\arch/arm/include/asm/arch-sunxi/ccu.h line 168
Quoted 7 lines
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+TREE (_parent,CCU_CLK_TYPE_MISC ,0 , \ + {0}, {0}, \ + {0}, \ +0 , \ + {0}, {0}, \ +0 , \ +CCU_CLK_F_INIT_DONE )If MISC is really something like GATE or SIMPLE, would it be possible to construct the single element array here, so that the macro just takes the one parent clock ID here, instead of referring to an extra array?
Quoted 55 lines
arch/arm/include/asm/arch-sunxi/ccu.h +40
-0+ +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset @@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_a64.cindex162ec769d6..1d0cd98183100644drivers/clk/sunxi/clk_a64.c line 19
Quoted 8 lines
drivers/clk/sunxi/clk_a64.c +5
-0@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = {Why is this long? That's the DT clock index, which is 32 bit wide, right? Just unsigned int or
uint32_tshould be sufficient. long is quite a treacherous type to use, especially as we share code between 32 and 64-bit architectures.Quoted 50 lines
drivers/clk/sunxi/clk_a64.c +35
-0+ CLK_OSC_24M, +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_sunxi.cindex345d706c2a..2aebd257d1100644 ---a/drivers/clk/sunxi/clk_sunxi.c
+++b/drivers/clk/sunxi/clk_sunxi.cReview static const struct ccu_clk_gate · line 23
Quoted 6 lines
(quoted diff) +2
-0@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, return &priv->desc->gates[id]; } +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv, + unsigned long id)Again, why long here? Especially as it's u32 in the function below.
Quoted 7 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +return &priv->desc->tree[id]; +} + +static int sunxi_get_parent_idx (const struct ccu_clk_tree *tree, void *base) +{ +u32 reg, idx;drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
Quoted 10 lines
drivers/clk/sunxi/clk_sunxi.c +9
-0+ + reg =readl (base + tree->off); + idx = reg >> tree->mux.shift; + idx &= (1 << tree->mux.width) -1 ; + +return idx; +} + +static ulong sunxi_fixed_get_rate (struct clk *clk,unsigned long id)Same "long" question for both the return type and the id. And for everything below.
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 50
Quoted 13 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { + printf("%s: (CLK#%ld) unhandled\n", __func__,
clk->id);drivers/clk/sunxi/clk_sunxi.c +6
-0+return 0 ; + } + +return tree->fixed_rate; +} +So why are there all those separate functions? Isn't that all the same algorithm: adjust the parent rate based on the clock type? I reworked this with recursive calls and it's MUCH less code:
(fill the gaps, using your types for your convenience ;-)
static ulong
sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong parent_rate){ NK algorithm ofsunxi_nk_get_rate}
static ulongsunxi_apply_div(struct ccu_priv *priv, ulong id, ulong parent_rate){ MP algorithm ofsunxi_mp_get_rate}
static ulongsunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid){
....switch (tree->type) { case CCU_CLK_TYPE_MISC: return sunxi_calc_clk_rate(priv, tree->parent[0]); case CCU_CLK_TYPE_FIXED: return tree->fixed_rate; case CCU_CLK_TYPE_NK: rate = sunxi_calc_clk_rate(priv, sunxi_get_parent_id(tree, priv->base)); return sunxi_apply_pll(priv, clkid, rate); (similar for _MP)Quoted 2 lines
...
}
Quoted 4 lines
Initially I would tried the recursive and yes code can reduce but using recursive can leed more disadvantage in-terms of code tracing during long run. Due to all these factors I used simple function calls.
But I find those extra functions much more confusing, due to the similar names and their very similar functionality. Also it seems that you just implemented what we need so far, so you will probably need to extend those functions, making them even more similar and duplicating more code. Basically you try to roll out the tree structure.
Since the clocks are organised in a tree-like structure, I believe this recursive definition is a much better fit: A clock takes one of possibly multiple input clocks and adjusts this rate. Full stop. The rest is then just connecting them to other clocks.
The code looks much simpler and is much smaller this way:
https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112
Typically the recursion depth is just two or three levels, so I don't buy the argument of code tracing.
Cheers,
Andre.
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
Quoted 102 lines · Andre Przywara
On Tue, 8 Jan 2019 16:27:14 +0530
Jagan Teki <[email protected]> wrote:Hi,
Quoted 86 lines
Quoted 10 lines · André Przywara
Quoted 7 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.Quoted 8 lines
So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Exactly. Idea is to keep the macro's as simple as possible.
Adding gates clocks separately make easy and reasonable way to enable/disable clock operations. We even operate with single macro with all clock attributes along with gate(either another member or common structure like Linux does), but that seems not simple as per as my experince since there are many IP's like USB's just need enable/disable.
Quoted 44 lines
Quoted 4 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 19 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192+++++++++++++++++++++++++-
drivers/clk/sunxi/clk_a64.c
| 40 ++++++drivers/clk/sunxi/clk_sunxi.c| 182
++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)(quoted diff) +0
-0Quoted 8 lines
b/arch/arm/include/asm/arch-sunxi/ccu.hindex3fdc26978d..61b8c36b3b100644 ---a/arch/arm/include/asm/arch-sunxi/ccu.h+++b/arch/arm/include/asm/arch-sunxi/ccu.h@@ -7,15 +7,204 @@
#ifndef_ASM_ARCH_CCU_H
#define_ASM_ARCH_CCU_H+#define
OSC_32K_ULL32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
Quoted 11 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 4 lines
Unlike MP type in MMC, UART doesn't need any clock attributes like dividers, mux, etc, just have attached parent. I don't think UART clock is simple one It has parent, that indeed have another parents and so...on, ie reason I named as MISC.
Not really, as far as I can see the UART clock is a just a gate clock as many others, with one parent (APB2).
The fact that APB2 in turn can have multiple parents doesn't affect the UART clock itself, as you model this via the clock tree.
Quoted 5 lines
In fact we could have similar clocks in the tree structure for the other gate clocks (USB, for instance), it's just that the UART is the only user so far which actually queries the clock rate.
So MISC is way too generic, I would still prefer
CCU_CLK_TYPE_GATE.
TYPE_GATE is more sense. fine for me.
Quoted 31 lines
Quoted 31 lines
Quoted 30 lines
Quoted 4 lines
+ * @CCU_CLK_TYPE_FIXED: fixed clock type
+ * @CCU_CLK_TYPE_MP: mp clock type
+ * @CCU_CLK_TYPE_NK: nk clock typeWhat is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fieldsThis gives more speaking names, plus some explanation.
Quoted 13 lines
+ */
arch/arm/include/asm/arch-sunxi/ccu.h +8
-1+enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/** * enum ccu_clk_flags - ccu clock flags * -* @CCU_CLK_F_INIT_DONE: clock gate init done check +* @CCU_CLK_F_INIT_DONE: clock tree/gate init done Quoted 1 line
check
Is this flag to tell implemented clocks apart from unimplemented ones, which would be reset to all zeroes by the compiler? Then it should be called something with VALID in it.
Quoted 7 lines
Quoted 3 lines
Since the flags attached with real numeric initialized by macro itself rather than some other source like complier or any, so marked
INIT_DONEseems to meaningful.When I read
INIT_DONEI understand some code has initialised this clock at some point, which isn't true. I don't fight the flag itself, just the name.
OK, I have updated INIT_DONE with IS_VALID and sent new version changes based on this.
Quoted 364 lines
Quoted 346 lines
and eventually the same verified in code whether the init done or not.
Quoted 340 lines
Quoted 86 lines
+ * @CCU_CLK_F_POSTDIV: clock post divider
*/
enumccu_clk_flags{
CCU_CLK_F_INIT_DONE= BIT(0),arch/arm/include/asm/arch-sunxi/ccu.h +19
-0+ CCU_CLK_F_POSTDIV = BIT(1), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
_offset, \arch/arm/include/asm/arch-sunxi/ccu.h +59
-0+ _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m arch/arm/include/asm/arch-sunxi/ccu.h line 125
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent;Shouldn't that be called "parents" instead?
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux;arch/arm/include/asm/arch-sunxi/ccu.h line 141
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE(_parent, _type, _off, \Just a nit, but TREE is somewhat confusing here, as this just constructs a single entry in an array. The tree property is realised through the parent array, if I get this correctly. So should we name this ENTRY or
CLK_ENTRYinstead?Quoted 21 lines
arch/arm/include/asm/arch-sunxi/ccu.h +20
-0+ _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \ +} + +#define
MISC(_parent)\arch/arm/include/asm/arch-sunxi/ccu.h line 168
Quoted 7 lines
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+TREE (_parent,CCU_CLK_TYPE_MISC ,0 , \ + {0}, {0}, \ + {0}, \ +0 , \ + {0}, {0}, \ +0 , \ +CCU_CLK_F_INIT_DONE )If MISC is really something like GATE or SIMPLE, would it be possible to construct the single element array here, so that the macro just takes the one parent clock ID here, instead of referring to an extra array?
Quoted 55 lines
arch/arm/include/asm/arch-sunxi/ccu.h +40
-0+ +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset @@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_a64.cindex162ec769d6..1d0cd98183100644drivers/clk/sunxi/clk_a64.c line 19
Quoted 8 lines
drivers/clk/sunxi/clk_a64.c +5
-0@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = {Why is this long? That's the DT clock index, which is 32 bit wide, right? Just unsigned int or
uint32_tshould be sufficient. long is quite a treacherous type to use, especially as we share code between 32 and 64-bit architectures.Quoted 50 lines
drivers/clk/sunxi/clk_a64.c +35
-0+ CLK_OSC_24M, +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_sunxi.cindex345d706c2a..2aebd257d1100644 ---a/drivers/clk/sunxi/clk_sunxi.c
+++b/drivers/clk/sunxi/clk_sunxi.cReview static const struct ccu_clk_gate · line 23
Quoted 6 lines
(quoted diff) +2
-0@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, return &priv->desc->gates[id]; } +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv, + unsigned long id)Again, why long here? Especially as it's u32 in the function below.
Quoted 7 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +return &priv->desc->tree[id]; +} + +static int sunxi_get_parent_idx (const struct ccu_clk_tree *tree, void *base) +{ +u32 reg, idx;drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
Quoted 10 lines
drivers/clk/sunxi/clk_sunxi.c +9
-0+ + reg =readl (base + tree->off); + idx = reg >> tree->mux.shift; + idx &= (1 << tree->mux.width) -1 ; + +return idx; +} + +static ulong sunxi_fixed_get_rate (struct clk *clk,unsigned long id)Same "long" question for both the return type and the id. And for everything below.
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 50
Quoted 13 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { + printf("%s: (CLK#%ld) unhandled\n", __func__,
clk->id);drivers/clk/sunxi/clk_sunxi.c +6
-0+return 0 ; + } + +return tree->fixed_rate; +} +So why are there all those separate functions? Isn't that all the same algorithm: adjust the parent rate based on the clock type? I reworked this with recursive calls and it's MUCH less code:
(fill the gaps, using your types for your convenience ;-)
static ulong
sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong parent_rate){ NK algorithm ofsunxi_nk_get_rate}
static ulongsunxi_apply_div(struct ccu_priv *priv, ulong id, ulong parent_rate){ MP algorithm ofsunxi_mp_get_rate}
static ulongsunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid){
....switch (tree->type) { case CCU_CLK_TYPE_MISC: return sunxi_calc_clk_rate(priv, tree->parent[0]); case CCU_CLK_TYPE_FIXED: return tree->fixed_rate; case CCU_CLK_TYPE_NK: rate = sunxi_calc_clk_rate(priv, sunxi_get_parent_id(tree, priv->base)); return sunxi_apply_pll(priv, clkid, rate); (similar for _MP)Quoted 2 lines
...
}Quoted 4 lines
Initially I would tried the recursive and yes code can reduce but using recursive can leed more disadvantage in-terms of code tracing during long run. Due to all these factors I used simple function calls.
But I find those extra functions much more confusing, due to the similar names and their very similar functionality. Also it seems that you just implemented what we need so far, so you will probably need to extend those functions, making them even more similar and duplicating more code. Basically you try to roll out the tree structure.
Since the clocks are organised in a tree-like structure, I believe this recursive definition is a much better fit: A clock takes one of possibly multiple input clocks and adjusts this rate. Full stop. The rest is then just connecting them to other clocks.
The code looks much simpler and is much smaller this way:
https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112
Quoted 2 lines
Typically the recursion depth is just two or three levels, so I don't buy the argument of code tracing.
OK. agreed thanks.
I shall take this recursive and try to mark separate patch on behalf of you if possible, will that be fine?
He is my next version TODO.
- Fixing clock types with meaning full values
- Adopt recursive function calls
- Try to add full MMC blot.
Let me know if you have any comments or question so-that we can collaborate smooth to get CLK in as soon as possible.
Jagan.
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
Quoted 146 lines · Jagan Teki
Quoted 102 lines · Andre Przywara
On Tue, 8 Jan 2019 16:27:14 +0530
Jagan Teki <[email protected]> wrote:Hi,
Quoted 86 lines
Quoted 10 lines · André Przywara
Quoted 7 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.Quoted 8 lines
So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Exactly. Idea is to keep the macro's as simple as possible.
Adding gates clocks separately make easy and reasonable way to enable/disable clock operations. We even operate with single macro with all clock attributes along with gate(either another member or common structure like Linux does), but that seems not simple as per as my experince since there are many IP's like USB's just need enable/disable.
Quoted 44 lines
Quoted 4 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 19 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192+++++++++++++++++++++++++-
drivers/clk/sunxi/clk_a64.c
| 40 ++++++drivers/clk/sunxi/clk_sunxi.c| 182
++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)(quoted diff) +0
-0Quoted 8 lines
b/arch/arm/include/asm/arch-sunxi/ccu.hindex3fdc26978d..61b8c36b3b100644 ---a/arch/arm/include/asm/arch-sunxi/ccu.h+++b/arch/arm/include/asm/arch-sunxi/ccu.h@@ -7,15 +7,204 @@
#ifndef_ASM_ARCH_CCU_H
#define_ASM_ARCH_CCU_H+#define
OSC_32K_ULL32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
Quoted 11 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 4 lines
Unlike MP type in MMC, UART doesn't need any clock attributes like dividers, mux, etc, just have attached parent. I don't think UART clock is simple one It has parent, that indeed have another parents and so...on, ie reason I named as MISC.
Not really, as far as I can see the UART clock is a just a gate clock as many others, with one parent (APB2).
The fact that APB2 in turn can have multiple parents doesn't affect the UART clock itself, as you model this via the clock tree.Quoted 5 lines
In fact we could have similar clocks in the tree structure for the other gate clocks (USB, for instance), it's just that the UART is the only user so far which actually queries the clock rate.
So MISC is way too generic, I would still prefer
CCU_CLK_TYPE_GATE.
TYPE_GATEis more sense. fine for me.Quoted 35 lines
Quoted 34 lines
Quoted 22 lines
Quoted 4 lines
+ * @CCU_CLK_TYPE_FIXED: fixed clock type
+ * @CCU_CLK_TYPE_MP: mp clock type
+ * @CCU_CLK_TYPE_NK: nk clock typeWhat is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fieldsThis gives more speaking names, plus some explanation.
Quoted 10 lines
+ */
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/** * enum ccu_clk_flags - ccu clock flags Quoted 8 lines
Quoted 4 lines
*
- * @CCU_CLK_F_INIT_DONE: clock gate init done check
+ * @CCU_CLK_F_INIT_DONE: clock tree/gate init done
checkIs this flag to tell implemented clocks apart from unimplemented ones, which would be reset to all zeroes by the compiler? Then it should be called something with VALID in it.
Since the flags attached with real numeric initialized by macro itself rather than some other source like complier or any, so marked
INIT_DONEseems to meaningful.
Quoted 6 lines
Quoted 3 lines
When I read
INIT_DONEI understand some code has initialised this clock at some point, which isn't true. I don't fight the flag itself, just the name.OK, I have updated
INIT_DONEwithIS_VALIDand sent new version changes based on this.
Great, thanks!
Quoted 363 lines
Quoted 363 lines
Quoted 345 lines
and eventually the same verified in code whether the init done or not.
Quoted 340 lines
Quoted 86 lines
+ * @CCU_CLK_F_POSTDIV: clock post divider
*/
enumccu_clk_flags{
CCU_CLK_F_INIT_DONE= BIT(0),arch/arm/include/asm/arch-sunxi/ccu.h +19
-0+ CCU_CLK_F_POSTDIV = BIT(1), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
_offset, \arch/arm/include/asm/arch-sunxi/ccu.h +59
-0+ _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m arch/arm/include/asm/arch-sunxi/ccu.h line 125
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent;Shouldn't that be called "parents" instead?
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux;arch/arm/include/asm/arch-sunxi/ccu.h line 141
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE(_parent, _type, _off, \Just a nit, but TREE is somewhat confusing here, as this just constructs a single entry in an array. The tree property is realised through the parent array, if I get this correctly. So should we name this ENTRY or
CLK_ENTRYinstead?Quoted 21 lines
arch/arm/include/asm/arch-sunxi/ccu.h +20
-0+ _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \ +} + +#define
MISC(_parent)\arch/arm/include/asm/arch-sunxi/ccu.h line 168
Quoted 7 lines
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+TREE (_parent,CCU_CLK_TYPE_MISC ,0 , \ + {0}, {0}, \ + {0}, \ +0 , \ + {0}, {0}, \ +0 , \ +CCU_CLK_F_INIT_DONE )If MISC is really something like GATE or SIMPLE, would it be possible to construct the single element array here, so that the macro just takes the one parent clock ID here, instead of referring to an extra array?
Quoted 55 lines
arch/arm/include/asm/arch-sunxi/ccu.h +40
-0+ +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset @@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_a64.cindex162ec769d6..1d0cd98183100644drivers/clk/sunxi/clk_a64.c line 19
Quoted 8 lines
drivers/clk/sunxi/clk_a64.c +5
-0@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = {Why is this long? That's the DT clock index, which is 32 bit wide, right? Just unsigned int or
uint32_tshould be sufficient. long is quite a treacherous type to use, especially as we share code between 32 and 64-bit architectures.Quoted 50 lines
drivers/clk/sunxi/clk_a64.c +35
-0+ CLK_OSC_24M, +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_sunxi.cindex345d706c2a..2aebd257d1100644 ---a/drivers/clk/sunxi/clk_sunxi.c
+++b/drivers/clk/sunxi/clk_sunxi.cReview static const struct ccu_clk_gate · line 23
Quoted 6 lines
(quoted diff) +2
-0@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, return &priv->desc->gates[id]; } +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv, + unsigned long id)Again, why long here? Especially as it's u32 in the function below.
Quoted 7 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +return &priv->desc->tree[id]; +} + +static int sunxi_get_parent_idx (const struct ccu_clk_tree *tree, void *base) +{ +u32 reg, idx;drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
Quoted 10 lines
drivers/clk/sunxi/clk_sunxi.c +9
-0+ + reg =readl (base + tree->off); + idx = reg >> tree->mux.shift; + idx &= (1 << tree->mux.width) -1 ; + +return idx; +} + +static ulong sunxi_fixed_get_rate (struct clk *clk,unsigned long id)Same "long" question for both the return type and the id. And for everything below.
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 50
Quoted 13 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { + printf("%s: (CLK#%ld) unhandled\n", __func__,
clk->id);drivers/clk/sunxi/clk_sunxi.c +6
-0+return 0 ; + } + +return tree->fixed_rate; +} +So why are there all those separate functions? Isn't that all the same algorithm: adjust the parent rate based on the clock type? I reworked this with recursive calls and it's MUCH less code:
(fill the gaps, using your types for your convenience ;-)
static ulong
sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong parent_rate){ NK algorithm ofsunxi_nk_get_rate}
static ulongsunxi_apply_div(struct ccu_priv *priv, ulong id, ulong parent_rate){ MP algorithm ofsunxi_mp_get_rate}
static ulongsunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid){
....switch (tree->type) { case CCU_CLK_TYPE_MISC: return sunxi_calc_clk_rate(priv, tree->parent[0]); case CCU_CLK_TYPE_FIXED: return tree->fixed_rate; case CCU_CLK_TYPE_NK: rate = sunxi_calc_clk_rate(priv, sunxi_get_parent_id(tree, priv->base)); return sunxi_apply_pll(priv, clkid, rate); (similar for _MP)Quoted 2 lines
...
}Quoted 4 lines
Initially I would tried the recursive and yes code can reduce but using recursive can leed more disadvantage in-terms of code tracing during long run. Due to all these factors I used simple function calls.
But I find those extra functions much more confusing, due to the similar names and their very similar functionality. Also it seems that you just implemented what we need so far, so you will probably need to extend those functions, making them even more similar and duplicating more code. Basically you try to roll out the tree structure.
Since the clocks are organised in a tree-like structure, I believe this recursive definition is a much better fit: A clock takes one of possibly multiple input clocks and adjusts this rate. Full stop. The rest is then just connecting them to other clocks.
The code looks much simpler and is much smaller this way:
https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112
Quoted 7 lines
Quoted 2 lines
Typically the recursion depth is just two or three levels, so I don't buy the argument of code tracing.
OK. agreed thanks.
I shall take this recursive and try to mark separate patch on behalf of you if possible, will that be fine?
No need, just rework this into this patch and keep your authorship. You did the bulk of the work anyway. If someone complains about the code, send them to me ;-)
Quoted 7 lines
He is my next version TODO.
- Fixing clock types with meaning full values
- Adopt recursive function calls
- Try to add full MMC blot.Let me know if you have any comments or question so-that we can collaborate smooth to get CLK in as soon as possible.
Sure, lets nail this in the upcoming merge window.
Btw. I still get the warning for DM_USB, shouldn't this be fixed already by this series?
Cheers,
Andre.
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
Quoted 537 lines · André Przywara
Quoted 146 lines · Jagan Teki
Quoted 102 lines · Andre Przywara
On Tue, 8 Jan 2019 16:27:14 +0530
Jagan Teki <[email protected]> wrote:Hi,
Quoted 86 lines
Quoted 10 lines · André Przywara
Quoted 7 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.Quoted 8 lines
So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Exactly. Idea is to keep the macro's as simple as possible.
Adding gates clocks separately make easy and reasonable way to enable/disable clock operations. We even operate with single macro with all clock attributes along with gate(either another member or common structure like Linux does), but that seems not simple as per as my experince since there are many IP's like USB's just need enable/disable.
Quoted 44 lines
Quoted 4 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 19 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192+++++++++++++++++++++++++-
drivers/clk/sunxi/clk_a64.c
| 40 ++++++drivers/clk/sunxi/clk_sunxi.c| 182
++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)(quoted diff) +0
-0Quoted 8 lines
b/arch/arm/include/asm/arch-sunxi/ccu.hindex3fdc26978d..61b8c36b3b100644 ---a/arch/arm/include/asm/arch-sunxi/ccu.h+++b/arch/arm/include/asm/arch-sunxi/ccu.h@@ -7,15 +7,204 @@
#ifndef_ASM_ARCH_CCU_H
#define_ASM_ARCH_CCU_H+#define
OSC_32K_ULL32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
Quoted 11 lines
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
Quoted 4 lines
Unlike MP type in MMC, UART doesn't need any clock attributes like dividers, mux, etc, just have attached parent. I don't think UART clock is simple one It has parent, that indeed have another parents and so...on, ie reason I named as MISC.
Not really, as far as I can see the UART clock is a just a gate clock as many others, with one parent (APB2).
The fact that APB2 in turn can have multiple parents doesn't affect the UART clock itself, as you model this via the clock tree.Quoted 5 lines
In fact we could have similar clocks in the tree structure for the other gate clocks (USB, for instance), it's just that the UART is the only user so far which actually queries the clock rate.
So MISC is way too generic, I would still prefer
CCU_CLK_TYPE_GATE.
TYPE_GATEis more sense. fine for me.Quoted 35 lines
Quoted 34 lines
Quoted 22 lines
Quoted 4 lines
+ * @CCU_CLK_TYPE_FIXED: fixed clock type
+ * @CCU_CLK_TYPE_MP: mp clock type
+ * @CCU_CLK_TYPE_NK: nk clock typeWhat is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fieldsThis gives more speaking names, plus some explanation.
Quoted 10 lines
+ */
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+enum ccu_clk_type { +CCU_CLK_TYPE_MISC =0 , +CCU_CLK_TYPE_FIXED =1 , +CCU_CLK_TYPE_MP =2 , +CCU_CLK_TYPE_NK =3 , +}; +/** * enum ccu_clk_flags - ccu clock flags Quoted 8 lines
Quoted 4 lines
*
- * @CCU_CLK_F_INIT_DONE: clock gate init done check
+ * @CCU_CLK_F_INIT_DONE: clock tree/gate init done
checkIs this flag to tell implemented clocks apart from unimplemented ones, which would be reset to all zeroes by the compiler? Then it should be called something with VALID in it.
Since the flags attached with real numeric initialized by macro itself rather than some other source like complier or any, so marked
INIT_DONEseems to meaningful.Quoted 6 lines
Quoted 3 lines
When I read
INIT_DONEI understand some code has initialised this clock at some point, which isn't true. I don't fight the flag itself, just the name.OK, I have updated
INIT_DONEwithIS_VALIDand sent new version changes based on this.Great, thanks!
Quoted 363 lines
Quoted 363 lines
Quoted 345 lines
and eventually the same verified in code whether the init done or not.
Quoted 340 lines
Quoted 86 lines
+ * @CCU_CLK_F_POSTDIV: clock post divider
*/
enumccu_clk_flags{
CCU_CLK_F_INIT_DONE= BIT(0),arch/arm/include/asm/arch-sunxi/ccu.h +19
-0+ CCU_CLK_F_POSTDIV = BIT(1), }; +/** +* struct ccu_mult - ccu clock multiplier +* +* @shift: multiplier shift value +* @width: multiplier width value +* @offset: multiplier offset +* @min: minimum multiplier +* @max: maximum multiplier +*/ +struct ccu_mult { +u8 shift; +u8 width; +u8 offset; +u8 min; +u8 max; +}; + +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
_offset, \arch/arm/include/asm/arch-sunxi/ccu.h +59
-0+ _min, _max) { \ + .shift = _shift, \ + .width = _width, \ + .offset = _offset, \ + .min = _min, \ + .max = _max, \ +} + +#define _CCU_MULT_MIN (_shift, _width, _min) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0) + +#define _CCU_MULT (_shift, _width) \ + _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0) + +/** +* struct ccu_mux - ccu clock multiplexer +* +* @shift: multiplexer shift value +* @width: multiplexer width value +*/ +struct ccu_mux { +u8 shift; +u8 width; +}; + +#define _CCU_MUX (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ +} + +/** +* struct ccu_div - ccu clock divider +* +* @shift: divider shift value +* @width: divider width value +* @offset: divider offset +* @max: maximum divider value +*/ +struct ccu_div { +u8 shift; +u8 width; +u32 offset; +u32 max; +}; + +#define _CCU_DIV (_shift, _width) { \ + .shift = _shift, \ + .width = _width, \ + .offset = 1, \ + .max = 0, \ +} + +/** +* struct ccu_clk_tree - ccu clock tree +* +* @parent: parent clock tree +* @type: clock type +* @off: clock tree offset +* @m: divider m arch/arm/include/asm/arch-sunxi/ccu.h line 125
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+* @p: divider p +* @mux: multiplexer mux +* @post: post divider value +* @n: multiplier n +* @k: multiplier k +* @fixed_rate: fixed rate +* @flags: clock tree flags +*/ +struct ccu_clk_tree { +const unsigned long *parent;Shouldn't that be called "parents" instead?
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+enum ccu_clk_type type; +u16 off; + +struct ccu_div m; +struct ccu_div p; +struct ccu_mux mux;arch/arm/include/asm/arch-sunxi/ccu.h line 141
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/ccu.h +10
-0+unsigned int postdiv; + +struct ccu_mult n; +struct ccu_mult k; + +ulong fixed_rate; +enum ccu_clk_flags flags; +}; + +#define TREE(_parent, _type, _off, \Just a nit, but TREE is somewhat confusing here, as this just constructs a single entry in an array. The tree property is realised through the parent array, if I get this correctly. So should we name this ENTRY or
CLK_ENTRYinstead?Quoted 21 lines
arch/arm/include/asm/arch-sunxi/ccu.h +20
-0+ _m, _p, \ + _mux, \ + _postdiv, \ + _n, _k, \ + _fixed_rate, \ + _flags) { \ + .parent = _parent, \ + .type = _type, \ + .off = _off, \ + .m = _m, \ + .p = _p, \ + .mux = _mux, \ + .postdiv = _postdiv, \ + .n = _n, \ + .k = _k, \ + .fixed_rate = _fixed_rate, \ + .flags = _flags, \ +} + +#define
MISC(_parent)\arch/arm/include/asm/arch-sunxi/ccu.h line 168
Quoted 7 lines
arch/arm/include/asm/arch-sunxi/ccu.h +7
-0+TREE (_parent,CCU_CLK_TYPE_MISC ,0 , \ + {0}, {0}, \ + {0}, \ +0 , \ + {0}, {0}, \ +0 , \ +CCU_CLK_F_INIT_DONE )If MISC is really something like GATE or SIMPLE, would it be possible to construct the single element array here, so that the macro just takes the one parent clock ID here, instead of referring to an extra array?
Quoted 55 lines
arch/arm/include/asm/arch-sunxi/ccu.h +40
-0+ +#define FIXED (_fixed_rate) \ + TREE(NULL, CCU_CLK_TYPE_FIXED, 0, \ + {0}, {0}, \ + {0}, \ + 0, \ + {0}, {0}, \ + _fixed_rate, \ + CCU_CLK_F_INIT_DONE) + +#define NK (_parent, _off, \ + _nshift, _nwidth, \ + _kshift, _kwidth, _kmin, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_NK, _off, \ + {0}, {0}, \ + {0}, \ + _postdiv, \ + _CCU_MULT(_nshift, _nwidth), \ + _CCU_MULT_MIN(_kshift, _kwidth, _kmin), \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) + +#define MP (_parent, _off, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _postdiv, \ + _flags) \ + TREE(_parent, CCU_CLK_TYPE_MP, _off, \ + _CCU_DIV(_mshift, _mwidth), \ + _CCU_DIV(_pshift, _pwidth), \ + _CCU_MUX(_muxshift, _muxwidth), \ + _postdiv, \ + {0}, {0}, \ + 0, \ + CCU_CLK_F_INIT_DONE | _flags) +/** * struct ccu_clk_gate - ccu clock gate * @off: gate offset @@ -59,6 +248,7 @@ struct ccu_reset {* @resets: reset unit */ struct ccu_desc { +const struct ccu_clk_tree *tree;const struct ccu_clk_gate *gates;const struct ccu_reset *resets; };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_a64.cindex162ec769d6..1d0cd98183100644drivers/clk/sunxi/clk_a64.c line 19
Quoted 8 lines
drivers/clk/sunxi/clk_a64.c +5
-0@@ -12,6 +12,45 @@#include <dt-bindings/clock/sun50i-a64-ccu.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#define CLK_APB2 26 +#define CLK_OSC_32K (CLK_GPU + 1) +#define CLK_OSC_24M (CLK_OSC_32K + 1) + +static const unsigned long periph0_parents[] = {Why is this long? That's the DT clock index, which is 32 bit wide, right? Just unsigned int or
uint32_tshould be sufficient. long is quite a treacherous type to use, especially as we share code between 32 and 64-bit architectures.Quoted 50 lines
drivers/clk/sunxi/clk_a64.c +35
-0+ CLK_OSC_24M, +}; + +static const unsigned long apb2_parents[] = { +CLK_OSC_32K , +CLK_OSC_24M , +CLK_PLL_PERIPH0 , +CLK_PLL_PERIPH0 , +}; + +static const unsigned long uart_parents[] = { +CLK_APB2 , +}; + +static const struct ccu_clk_tree a64_tree[] = { + [CLK_OSC_32K ] =FIXED (OSC_32K_ULL ), + [CLK_OSC_24M ] =FIXED (OSC_24M_ULL ), + + [CLK_PLL_PERIPH0 ] =NK (periph0_parents,0x028 , +8 ,5 ,/* N */ +4 ,2 ,2 ,/* K */ +2 ,/* post-div */ +CCU_CLK_F_POSTDIV ), + + [CLK_APB2 ] =MP (apb2_parents,0x058 , +0 ,5 ,/* M */ +16 ,2 ,/* P */ +24 ,2 ,/* mux */ +0 , +0 ), + + [CLK_BUS_UART0 ] =MISC (uart_parents), +}; +static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )),@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = { };static const struct ccu_desc a64_ccu_desc = { + .tree = a64_tree, .gates = a64_gates, .resets = a64_resets, };(quoted diff) +0
-0
b/drivers/clk/sunxi/clk_sunxi.cindex345d706c2a..2aebd257d1100644 ---a/drivers/clk/sunxi/clk_sunxi.c
+++b/drivers/clk/sunxi/clk_sunxi.cReview static const struct ccu_clk_gate · line 23
Quoted 6 lines
(quoted diff) +2
-0@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, return &priv->desc->gates[id]; } +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv, + unsigned long id)Again, why long here? Especially as it's u32 in the function below.
Quoted 7 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +return &priv->desc->tree[id]; +} + +static int sunxi_get_parent_idx (const struct ccu_clk_tree *tree, void *base) +{ +u32 reg, idx;drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
Quoted 10 lines
drivers/clk/sunxi/clk_sunxi.c +9
-0+ + reg =readl (base + tree->off); + idx = reg >> tree->mux.shift; + idx &= (1 << tree->mux.width) -1 ; + +return idx; +} + +static ulong sunxi_fixed_get_rate (struct clk *clk,unsigned long id)Same "long" question for both the return type and the id. And for everything below.
drivers/clk/sunxi/clk_sunxi.c static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, · line 50
Quoted 13 lines
drivers/clk/sunxi/clk_sunxi.c +6
-0+{ +struct ccu_priv *priv =dev_get_priv (clk->dev); +const struct ccu_clk_tree *tree =priv_to_tree (priv, id); + +if (!(tree->flags &CCU_CLK_F_INIT_DONE )) { + printf("%s: (CLK#%ld) unhandled\n", __func__,
clk->id);drivers/clk/sunxi/clk_sunxi.c +6
-0+return 0 ; + } + +return tree->fixed_rate; +} +So why are there all those separate functions? Isn't that all the same algorithm: adjust the parent rate based on the clock type? I reworked this with recursive calls and it's MUCH less code:
(fill the gaps, using your types for your convenience ;-)
static ulong
sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong parent_rate){ NK algorithm ofsunxi_nk_get_rate}
static ulongsunxi_apply_div(struct ccu_priv *priv, ulong id, ulong parent_rate){ MP algorithm ofsunxi_mp_get_rate}
static ulongsunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid){
....switch (tree->type) { case CCU_CLK_TYPE_MISC: return sunxi_calc_clk_rate(priv, tree->parent[0]); case CCU_CLK_TYPE_FIXED: return tree->fixed_rate; case CCU_CLK_TYPE_NK: rate = sunxi_calc_clk_rate(priv, sunxi_get_parent_id(tree, priv->base)); return sunxi_apply_pll(priv, clkid, rate); (similar for _MP)Quoted 2 lines
...
}Quoted 4 lines
Initially I would tried the recursive and yes code can reduce but using recursive can leed more disadvantage in-terms of code tracing during long run. Due to all these factors I used simple function calls.
But I find those extra functions much more confusing, due to the similar names and their very similar functionality. Also it seems that you just implemented what we need so far, so you will probably need to extend those functions, making them even more similar and duplicating more code. Basically you try to roll out the tree structure.
Since the clocks are organised in a tree-like structure, I believe this recursive definition is a much better fit: A clock takes one of possibly multiple input clocks and adjusts this rate. Full stop. The rest is then just connecting them to other clocks.
The code looks much simpler and is much smaller this way:
https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112Quoted 7 lines
Quoted 2 lines
Typically the recursion depth is just two or three levels, so I don't buy the argument of code tracing.
OK. agreed thanks.
I shall take this recursive and try to mark separate patch on behalf of you if possible, will that be fine?
No need, just rework this into this patch and keep your authorship. You did the bulk of the work anyway. If someone complains about the code, send them to me ;-)
Quoted 5 lines
He is my next version TODO.
- Fixing clock types with meaning full values
- Adopt recursive function calls
- Try to add full MMC blot.
Quoted 7 lines
Quoted 2 lines
Let me know if you have any comments or question so-that we can collaborate smooth to get CLK in as soon as possible.
Sure, lets nail this in the upcoming merge window.
Btw. I still get the warning for
DM_USB, shouldn't this be fixed already by this series?
We already have DM_USB enabled, since the check will also look for BLK it's still showing the warning. Once we move DM_MMC it will gone.
PATCH v5 15/26 clk: sunxi: Add ccu clock tree support
In reply to André PrzywaraQuoted 73 lines · André Przywara
Quoted 6 lines · Jagan Teki
Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management which can be handle via
ccu_clock_gate.So if I understand this correctly, you implement the gate functionality separately from the complex clock code, even if they are the same clock from the DT point of view? So if one wants to enable the MMC0 clock, which is a mux/divider clock, one needs to specify an extra entry in the gate array to describe the enable bit in this special clock register? Sounds a bit surprising, but is probably a neat trick to keep things simple. There should be a comment in the code to this regard then.
Quoted 2 lines
Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp, pre/post div, flags etc. which were managed via
ccu_clock_tree.For a start, can we use more descriptive names than those very specific MP/NK names?
DIV_MUXand PLL sound more descriptive to me. I understand that Linux uses those terms, but it would be great if uninitiated people have a chance to understand this as well.Quoted 22 lines
This patch add support for MP, NK, MISC, FIXED clock types as part of ccu clock tree with
get_ratefunctionality this eventually used by uart driver. and rest of the infrastructure will try to add while CLK is being used on respective peripherals.Note that few of the tree type clock would require to enable gates on their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value should add as part ofccu_clock_gate.Signed-off-by Jagan Teki <[email protected]>--- arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c | 40 ++++++ drivers/clk/sunxi/clk_sunxi.c | 182 ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-)arch/arm/include/asm/arch-sunxi/ccu.h +0
-0arch/arm/include/asm/arch-sunxi/ccu.h line 10
Quoted 4 lines
arch/arm/include/asm/arch-sunxi/ccu.h +1
-0@@ -7,15 +7,204 @@#ifndef _ASM_ARCH_CCU_H#define _ASM_ARCH_CCU_H +#define OSC_32K_ULL 32000ULL32768
And why ULL? The whole Allwinner clock system works with 32-bit values, so just U would be totally sufficient. This avoid blowing this up to 64 bit unnecessarily, which sounds painful for those poor ARMv7 parts.
arch/arm/include/asm/arch-sunxi/ccu.h line 16
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/ccu.h +6
-0+#define OSC_24M_ULL 24000000ULL + +/** +* enum ccu_clk_type - ccu clock types +* +* @CCU_CLK_TYPE_MISC: misc clock type What is MISC, exactly? Seems like an artefact clock to me, some placeholder you need because gate clocks are handled separately in the gates struct. Should this be called something with SIMPLE instead, or GATE?
arch/arm/include/asm/arch-sunxi/ccu.h line 19
Quoted 3 lines
arch/arm/include/asm/arch-sunxi/ccu.h +3
-0+* @CCU_CLK_TYPE_FIXED: fixed clock type +* @CCU_CLK_TYPE_MP: mp clock type +* @CCU_CLK_TYPE_NK: nk clock type
Quoted 6 lines
What is the point of those comments, as you are basically repeating the enum name? What about:
* @CCU_CLK_TYPE_PLL: PLL clock with two multiplier fields
* @CCU_CLK_TYPE_MUX_DIV: multiple parents, two divider fieldsThis gives more speaking names, plus some explanation.
My idea is to give generic name for a given clock type for example MP clock has different varients like MP clock, MP with DIV, MP with Postdiv, MP can be MMC etc. same like NK clock type as NK with postdiv, NK can be PLL.
With this we can expose the base name to outside and keep fill the require variants during macro initialization. This can avoid to many names on the same clock based on the different variants. Yes we can add proper full detailed comments on the given type.
PATCH v5 16/26 sunxi: Enable CLK
In reply to Jagan TekiCLK and DM_RESET drivers are now available for most of the Allwinner platforms, so enable in mach-sunxi/Kconfig
Enabling CLK will select DM_RESET by default.
--- arch/arm/mach-sunxi/Kconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/arm/mach-sunxi/Kconfig +12 -0
@@ -132,6 +132,7 @@ endif config MACH_SUNXI_H3_H5 bool + select CLK select DM_I2C select PHY_SUN4I_USB select SUNXI_DE2
@@ -154,6 +155,7 @@ config MACH_SUN4I bool "sun4i (Allwinner A10)" select CPU_V7A select ARM_CORTEX_CPU_IS_UP + select CLK select DM_MMC if MMC select DM_SCSI if SCSI select PHY_SUN4I_USB
@@ -165,6 +167,7 @@ config MACH_SUN5I bool "sun5i (Allwinner A13)" select CPU_V7A select ARM_CORTEX_CPU_IS_UP + select CLK select DRAM_SUN4I select PHY_SUN4I_USB select SUNXI_GEN_SUN4I
@@ -177,6 +180,7 @@ config MACH_SUN6I select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI + select CLK select DRAM_SUN6I select PHY_SUN4I_USB select SUN6I_P2WI
@@ -191,6 +195,7 @@ config MACH_SUN7I select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI + select CLK select DRAM_SUN4I select PHY_SUN4I_USB select SUNXI_GEN_SUN4I
@@ -203,6 +208,7 @@ config MACH_SUN8I_A23 select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI + select CLK select DRAM_SUN8I_A23 select PHY_SUN4I_USB select SUNXI_GEN_SUN6I
@@ -216,6 +222,7 @@ config MACH_SUN8I_A33 select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI + select CLK select DRAM_SUN8I_A33 select PHY_SUN4I_USB select SUNXI_GEN_SUN6I
@@ -226,6 +233,7 @@ config MACH_SUN8I_A33 config MACH_SUN8I_A83T bool "sun8i (Allwinner A83T)" select CPU_V7A + select CLK select DRAM_SUN8I_A83T select PHY_SUN4I_USB select SUNXI_GEN_SUN6I
@@ -248,6 +256,7 @@ config MACH_SUN8I_R40 select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI + select CLK select SUNXI_GEN_SUN6I select SUPPORT_SPL select SUNXI_DRAM_DW
@@ -259,6 +268,7 @@ config MACH_SUN8I_V3S select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI + select CLK select SUNXI_GEN_SUN6I select SUNXI_DRAM_DW select SUNXI_DRAM_DW_16BIT
@@ -277,6 +287,7 @@ config MACH_SUN9I config MACH_SUN50I bool "sun50i (Allwinner A64)" select ARM64 + select CLK select DM_I2C select PHY_SUN4I_USB select SUN6I_PRCM
@@ -300,6 +311,7 @@ config MACH_SUN50I_H5 config MACH_SUN50I_H6 bool "sun50i (Allwinner H6)" select ARM64 + select CLK select SUPPORT_SPL select FIT select SPL_LOAD_FIT
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 17/26 phy: sun4i-usb: Use CLK and RESET support
In reply to Jagan TekiNow clock and reset drivers are available for respective SoC's so use clk and reset ops on phy driver.
--- drivers/phy/allwinner/phy-sun4i-usb.c | 77 ++++++++++++++++++++------- 1 file changed, 57 insertions(+), 20 deletions(-)
drivers/phy/allwinner/phy-sun4i-usb.c +57 -20
@@ -11,10 +11,12 @@*/ #include <common.h> +#include <clk.h> #include <dm.h> #include <dm/device.h> #include <generic-phy.h> #include <phy-sun4i-usb.h> +#include <reset.h> #include <asm/gpio.h> #include <asm/io.h> #include <asm/arch/clock.h>
@@ -80,6 +82,7 @@ struct sun4i_usb_phy_cfg {enum sun4i_usb_phy_type type;u32 disc_thresh;u8 phyctl_offset; +bool dedicated_clocks;bool enable_pmu_unk1;bool phy0_dual_route; };
@@ -88,30 +91,21 @@ struct sun4i_usb_phy_info {const char *gpio_vbus;const char *gpio_vbus_det;const char *gpio_id_det; -int rst_mask; } phy_info[] = { { .gpio_vbus = CONFIG_USB0_VBUS_PIN, .gpio_vbus_det = CONFIG_USB0_VBUS_DET, .gpio_id_det = CONFIG_USB0_ID_DET, - .rst_mask = (CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK), }, { .gpio_vbus = CONFIG_USB1_VBUS_PIN, .gpio_vbus_det = NULL, .gpio_id_det = NULL, - .rst_mask = (CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK), }, { .gpio_vbus = CONFIG_USB2_VBUS_PIN, .gpio_vbus_det = NULL, .gpio_id_det = NULL, -#ifdef CONFIG_MACH_SUN8I_A83T - .rst_mask = (CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK | - CCM_USB_CTRL_12M_CLK), -#else - .rst_mask = (CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK), -#endif }, { .gpio_vbus = CONFIG_USB3_VBUS_PIN,
@@ -126,13 +120,13 @@ struct sun4i_usb_phy_plat {int gpio_vbus;int gpio_vbus_det;int gpio_id_det; -int rst_mask; +struct clk clocks; +struct reset_ctl resets;int id; };struct sun4i_usb_phy_data {void __iomem *base; -struct sunxi_ccm_reg *ccm;const struct sun4i_usb_phy_cfg *cfg;struct sun4i_usb_phy_plat *usb_phy; };
@@ -266,8 +260,19 @@ static int sun4i_usb_phy_init(struct phy *phy)struct sun4i_usb_phy_data *data =dev_get_priv (phy->dev);struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];u32 val; +int ret; -setbits_le32 (&data->ccm->usb_clk_cfg, usb_phy->rst_mask); + ret =clk_enable (&usb_phy->clocks); +if (ret) { +dev_err (dev,"failed to enable usb_%ldphy clock\n" , phy->id); +return ret; + } + + ret =reset_deassert (&usb_phy->resets); +if (ret) { +dev_err (dev,"failed to deassert usb_%ldreset reset\n" , phy->id); +return ret; + }if (data->cfg->type == sun8i_a83t_phy) {if (phy->id ==0 ) {
@@ -308,6 +313,7 @@ static int sun4i_usb_phy_exit(struct phy *phy) {struct sun4i_usb_phy_data *data =dev_get_priv (phy->dev);struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; +int ret;if (phy->id ==0 ) {if (data->cfg->type == sun8i_a83t_phy) {
@@ -320,7 +326,17 @@ static int sun4i_usb_phy_exit(struct phy *phy)sun4i_usb_phy_passby (phy, false); -clrbits_le32 (&data->ccm->usb_clk_cfg, usb_phy->rst_mask); + ret =clk_disable (&usb_phy->clocks); +if (ret) { +dev_err (dev,"failed to disable usb_%ldphy clock\n" , phy->id); +return ret; + } + + ret =reset_assert (&usb_phy->resets); +if (ret) { +dev_err (dev,"failed to assert usb_%ldreset reset\n" , phy->id); +return ret; + }return 0 ; }
@@ -407,10 +423,6 @@ static int sun4i_usb_phy_probe(struct udevice *dev)if (IS_ERR (data->base))return PTR_ERR (data->base); - data->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ; -if (IS_ERR (data->ccm)) -return PTR_ERR (data->ccm); - data->usb_phy = plat;for (i =0 ; i < data->cfg->num_phys; i++) {struct sun4i_usb_phy_plat *phy = &plat[i];
@@ -448,6 +460,24 @@ static int sun4i_usb_phy_probe(struct udevice *dev)sunxi_gpio_set_pull (phy->gpio_id_det,SUNXI_GPIO_PULL_UP ); } +if (data->cfg->dedicated_clocks) +snprintf (name,sizeof (name),"usb%d_phy" , i); +else +strlcpy (name,"usb_phy" ,sizeof (name)); + + ret =clk_get_by_name (dev, name, &phy->clocks); +if (ret) { +dev_err (dev,"failed to get usb%d_phy clock phandle\n" , i); +return ret; + } + +snprintf (name,sizeof (name),"usb%d_reset" , i); + ret =reset_get_by_name (dev, name, &phy->resets); +if (ret) { +dev_err (dev,"failed to get usb%d_reset reset phandle\n" , i); +return ret; + } +if (i || data->cfg->phy0_dual_route) {snprintf (name,sizeof (name),"pmu%d" , i); phy->pmu = (void __iomem *)devfdt_get_addr_name (dev, name);
@@ -456,9 +486,6 @@ static int sun4i_usb_phy_probe(struct udevice *dev) } phy->id = i; - phy->rst_mask = info->rst_mask; -if ((data->cfg->type == sun8i_h3_phy) && (phy->id ==3 )) - phy->rst_mask = (BIT (3 ) |BIT (11 )); };debug ("Allwinner Sun4I USB PHY driver loaded\n" );
@@ -470,6 +497,7 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { .type = sun4i_a10_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = false, .enable_pmu_unk1 = false, };
@@ -478,6 +506,7 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { .type = sun4i_a10_phy, .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = false, .enable_pmu_unk1 = false, };
@@ -486,6 +515,7 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { .type = sun6i_a31_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = true, .enable_pmu_unk1 = false, };
@@ -494,6 +524,7 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .type = sun4i_a10_phy, .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = false, .enable_pmu_unk1 = false, };
@@ -502,6 +533,7 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { .type = sun4i_a10_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = true, .enable_pmu_unk1 = false, };
@@ -510,6 +542,7 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { .type = sun8i_a33_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, .enable_pmu_unk1 = false, };
@@ -517,6 +550,7 @@ static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { .num_phys = 3, .type = sun8i_a83t_phy, .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, };static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
@@ -524,6 +558,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .type = sun8i_h3_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, .enable_pmu_unk1 = true, .phy0_dual_route = true, };
@@ -533,6 +568,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { .type = sun8i_v3s_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, .enable_pmu_unk1 = true, .phy0_dual_route = true, };
@@ -542,6 +578,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .type = sun50i_a64_phy, .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, .enable_pmu_unk1 = true, .phy0_dual_route = true, };
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 17/26 phy: sun4i-usb: Use CLK and RESET support
Quoted 6 lines · Jagan Teki
Now clock and reset drivers are available for respective SoC's so use clk and reset ops on phy driver.
Cc Marek Vasut <[email protected]>Signed-off-by Jagan Teki <[email protected]>Acked-by Maxime Ripard <[email protected]>
btw I hope this is planned for _after_ 2019.01 release ?
[...]
Signature · 2 lines
Best regards, Marek Vasut
PATCH v5 17/26 phy: sun4i-usb: Use CLK and RESET support
Quoted 5 lines · Marek Vasut
Quoted 3 lines · Jagan Teki
Now clock and reset drivers are available for respective SoC's so use clk and reset ops on phy driver.
Quoted 7 lines
Quoted 3 lines
Cc Marek Vasut <[email protected]>Signed-off-by Jagan Teki <[email protected]>Acked-by Maxime Ripard <[email protected]>Reviewed-by Marek Vasut <[email protected]>btw I hope this is planned for _after_ 2019.01 release ?
Yes.
PATCH v5 18/26 reset: Add reset valid
In reply to Jagan TekiAdd reset_valid to check whether given reset is valid or not.
--- include/reset.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
include/reset.h +11 -0
@@ -306,4 +306,15 @@ static inline int reset_release_bulk(struct reset_ctl_bulk *bulk) }#endif +/** +* reset_valid() - check if reset is valid +* +* @reset_ctl: the reset to check +* @return TRUE if valid, or FALSE +*/ +static inline bool reset_valid (struct reset_ctl *reset_ctl) +{ +return !!reset_ctl->dev; +} +#endif
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 19/26 musb-new: sunxi: Use CLK and RESET support
In reply to Jagan TekiNow clock and reset drivers are available for respective SoC's so use clk and reset ops on musb driver.
--- drivers/usb/musb-new/sunxi.c | 81 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 41 deletions(-)
drivers/usb/musb-new/sunxi.c +40 -41
@@ -16,9 +16,11 @@* This file is part of the Inventra Controller Driver for Linux. */ #include <common.h> +#include <clk.h> #include <dm.h> #include <generic-phy.h> #include <phy-sun4i-usb.h> +#include <reset.h> #include <asm/arch/cpu.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h>
@@ -80,16 +82,12 @@struct sunxi_musb_config {struct musb_hdrc_config *config; -bool has_reset; -u8 rst_bit; -u8 clkgate_bit; -u32 off_reset0; };struct sunxi_glue {struct musb_host_data mdata; -struct sunxi_ccm_reg *ccm; -u32 *reg_reset0; +struct clk clk; +struct reset_ctl rst;struct sunxi_musb_config *cfg;struct device dev;struct phy phy;
@@ -296,24 +294,27 @@ static int sunxi_musb_init(struct musb *musb)pr_debug ("%s():\n" , __func__); - ret =generic_phy_init (&glue->phy); + ret =clk_enable (&glue->clk);if (ret) { -pr_err ("failed to init USB PHY\n" ); +pr_err ("failed to enable clock\n" );return ret; } - musb->isr = sunxi_musb_interrupt; - -setbits_le32 (&glue->ccm->ahb_gate0,BIT (AHB_GATE_OFFSET_USB0 )); -if (glue->cfg->clkgate_bit) -setbits_le32 (&glue->ccm->ahb_gate0, -BIT (glue->cfg->clkgate_bit)); +if (reset_valid (&glue->rst)) { + ret =reset_deassert (&glue->rst); +if (ret) { +pr_err ("failed to deassert reset\n" ); + goto err_clk; + } + } -if (glue->cfg->has_reset) -setbits_le32 (glue->reg_reset0,BIT (AHB_GATE_OFFSET_USB0 )); + ret =generic_phy_init (&glue->phy); +if (ret) { +pr_err ("failed to init USB PHY\n" ); + goto err_rst; + } -if (glue->cfg->rst_bit) -setbits_le32 (glue->reg_reset0,BIT (glue->cfg->rst_bit)); + musb->isr = sunxi_musb_interrupt;USBC_ConfigFIFO_Base ();USBC_EnableDpDmPullUp (musb->mregs);
@@ -329,6 +330,13 @@ static int sunxi_musb_init(struct musb *musb)USBC_ForceVbusValidToHigh (musb->mregs);return 0 ; + +err_rst: +if (reset_valid (&glue->rst)) +reset_assert (&glue->rst); +err_clk: +clk_disable (&glue->clk); +return ret; }static int sunxi_musb_exit (struct musb *musb)
@@ -339,21 +347,14 @@ static int sunxi_musb_exit(struct musb *musb)if (generic_phy_valid (&glue->phy)) { ret =generic_phy_exit (&glue->phy);if (ret) { -dev_err (dev,"failed to power off usb phy\n" ); +pr_err ("failed to power off usb phy\n" );return ret; } } -if (glue->cfg->has_reset) -clrbits_le32 (glue->reg_reset0,BIT (AHB_GATE_OFFSET_USB0 )); - -if (glue->cfg->rst_bit) -clrbits_le32 (glue->reg_reset0,BIT (glue->cfg->rst_bit)); - -clrbits_le32 (&glue->ccm->ahb_gate0,BIT (AHB_GATE_OFFSET_USB0 )); -if (glue->cfg->clkgate_bit) -clrbits_le32 (&glue->ccm->ahb_gate0, -BIT (glue->cfg->clkgate_bit)); +if (reset_valid (&glue->rst)) +reset_assert (&glue->rst); +clk_disable (&glue->clk);return 0 ; }
@@ -450,11 +451,17 @@ static int musb_usb_probe(struct udevice *dev)if (!glue->cfg)return -EINVAL ; - glue->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ; -if (IS_ERR (glue->ccm)) -return PTR_ERR (glue->ccm); + ret =clk_get_by_index (dev,0 , &glue->clk); +if (ret) { +pr_err ("failed to get clock\n" ); +return ret; + } - glue->reg_reset0 = (void *)glue->ccm + glue->cfg->off_reset0; + ret =reset_get_by_index (dev,0 , &glue->rst); +if (ret && ret != -ENOENT ) { +pr_err ("failed to get reset\n" ); +return ret; + } ret =generic_phy_get_by_name (dev,"usb" , &glue->phy);if (ret) {
@@ -462,7 +469,6 @@ static int musb_usb_probe(struct udevice *dev)return ret; } -memset (&pdata,0 ,sizeof (pdata)); pdata.power =250 ; pdata.platform_ops = &sunxi_musb_ops;
@@ -505,21 +511,14 @@ static int musb_usb_remove(struct udevice *dev)static const struct sunxi_musb_config sun4i_a10_cfg = { .config = &musb_config, - .has_reset = false, };static const struct sunxi_musb_config sun6i_a31_cfg = { .config = &musb_config, - .has_reset = true, - .off_reset0 =OFF_SUN6I_AHB_RESET0 , };static const struct sunxi_musb_config sun8i_h3_cfg = { .config = &musb_config_h3, - .has_reset = true, - .rst_bit =23 , - .clkgate_bit =23 , - .off_reset0 =OFF_SUN6I_AHB_RESET0 , };static const struct udevice_id sunxi_musb_ids[] = {
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 19/26 musb-new: sunxi: Use CLK and RESET support
Quoted 57 lines · Jagan Teki
Now clock and reset drivers are available for respective SoC's so use clk and reset ops on musb driver.
Cc Marek Vasut <[email protected]>Signed-off-by Jagan Teki <[email protected]>Acked-by Maxime Ripard <[email protected]>--- drivers/usb/musb-new/sunxi.c | 81 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 41 deletions(-)drivers/usb/musb-new/sunxi.c +6
-8@@ -16,9 +16,11 @@* This file is part of the Inventra Controller Driver for Linux. */ #include <common.h> +#include <clk.h> #include <dm.h> #include <generic-phy.h> #include <phy-sun4i-usb.h> +#include <reset.h> #include <asm/arch/cpu.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> @@ -80,16 +82,12 @@struct sunxi_musb_config {struct musb_hdrc_config *config; -bool has_reset; -u8 rst_bit; -u8 clkgate_bit; -u32 off_reset0; };struct sunxi_glue {struct musb_host_data mdata; -struct sunxi_ccm_reg *ccm; -u32 *reg_reset0; +struct clk clk; +struct reset_ctl rst;struct sunxi_musb_config *cfg;struct device dev;struct phy phy;@@ -296,24 +294,27 @@ static int sunxi_musb_init(struct musb *musb)pr_debug ("%s():\n" , __func__); - ret =generic_phy_init (&glue->phy); + ret =clk_enable (&glue->clk);if (ret) { -pr_err ("failed to init USB PHY\n" ); +pr_err ("failed to enable clock\n" );return ret; }
drivers/usb/musb-new/sunxi.c static int sunxi_musb_init(struct musb *musb) · line 306
Quoted 10 lines
drivers/usb/musb-new/sunxi.c +4
-6- musb->isr = sunxi_musb_interrupt; - -setbits_le32 (&glue->ccm->ahb_gate0,BIT (AHB_GATE_OFFSET_USB0 )); -if (glue->cfg->clkgate_bit) -setbits_le32 (&glue->ccm->ahb_gate0, -BIT (glue->cfg->clkgate_bit)); +if (reset_valid (&glue->rst)) { + ret =reset_deassert (&glue->rst); +if (ret) { +pr_err ("failed to deassert reset\n" );
dev_err(dev, ...), fix globally
[...]
Signature · 2 lines
Best regards, Marek Vasut
PATCH v5 20/26 sunxi: usb: Switch to Generic host controllers
In reply to Jagan TekiOnce of key blocker for using USB Generic host controller drivers in Allwinner are CLK and RESET drivers, now these available for USB usage.
So switch sunxi USB use EHCI and OHCI Generic controllers.
Enabling USB is wisely a board choise, So Enable USB_OHCI_HCD where it already have USB_EHCI_HCD
--- configs/A10-OLinuXino-Lime_defconfig | 1 + configs/A10s-OLinuXino-M_defconfig | 1 + configs/A13-OLinuXinoM_defconfig | 1 + configs/A13-OLinuXino_defconfig | 1 + configs/A20-OLinuXino-Lime2-eMMC_defconfig | 1 + configs/A20-OLinuXino-Lime2_defconfig | 1 + configs/A20-OLinuXino-Lime_defconfig | 1 + configs/A20-Olimex-SOM204-EVB_defconfig | 1 + configs/Auxtek-T003_defconfig | 1 + configs/Auxtek-T004_defconfig | 1 + configs/Bananapi_defconfig | 1 + configs/Bananapi_m2m_defconfig | 1 + configs/Bananapro_defconfig | 1 + configs/CHIP_defconfig | 1 + configs/CHIP_pro_defconfig | 1 + configs/CSQ_CS908_defconfig | 1 + configs/Colombus_defconfig | 1 + configs/Cubieboard2_defconfig | 1 + configs/Cubieboard_defconfig | 1 + configs/Cubietruck_plus_defconfig | 1 + configs/Hummingbird_A31_defconfig | 1 + configs/Itead_Ibox_A20_defconfig | 1 + configs/Linksprite_pcDuino3_Nano_defconfig | 1 + configs/Linksprite_pcDuino3_defconfig | 1 + configs/Linksprite_pcDuino_defconfig | 1 + configs/MK808C_defconfig | 1 + configs/Marsboard_A10_defconfig | 1 + configs/Mele_A1000G_quad_defconfig | 1 + configs/Mele_A1000_defconfig | 1 + configs/Mele_I7_defconfig | 1 + configs/Mele_M3_defconfig | 1 + configs/Mele_M5_defconfig | 1 + configs/Mele_M9_defconfig | 1 + configs/Mini-X_defconfig | 1 + configs/Orangepi_defconfig | 1 + configs/Orangepi_mini_defconfig | 1 + configs/Sinlinx_SinA31s_defconfig | 1 + configs/Sinlinx_SinA33_defconfig | 1 + configs/Sinovoip_BPI_M2_Plus_defconfig | 1 + configs/Sinovoip_BPI_M2_defconfig | 1 + configs/Sinovoip_BPI_M3_defconfig | 1 + configs/Wexler_TAB7200_defconfig | 1 + configs/Wobo_i5_defconfig | 1 + configs/a64-olinuxino_defconfig | 1 + configs/ba10_tv_box_defconfig | 1 + configs/bananapi_m1_plus_defconfig | 1 + configs/bananapi_m64_defconfig | 1 + configs/ga10h_v1_1_defconfig | 1 + configs/h8_homlet_v2_defconfig | 1 + configs/i12-tvbox_defconfig | 1 + configs/icnova-a20-swac_defconfig | 1 + configs/inet1_defconfig | 1 + configs/inet_q972_defconfig | 1 + configs/jesurun_q5_defconfig | 1 + configs/libretech_all_h3_cc_h2_plus_defconfig | 1 + configs/libretech_all_h3_cc_h3_defconfig | 1 + configs/libretech_all_h3_cc_h5_defconfig | 1 + configs/mixtile_loftq_defconfig | 1 + configs/mk802_a10s_defconfig | 1 + configs/mk802_defconfig | 1 + configs/mk802ii_defconfig | 1 + configs/nanopi_a64_defconfig | 1 + configs/nanopi_m1_defconfig | 1 + configs/nanopi_m1_plus_defconfig | 1 + configs/nanopi_neo2_defconfig | 1 + configs/nanopi_neo_air_defconfig | 1 + configs/nanopi_neo_defconfig | 1 + configs/nanopi_neo_plus2_defconfig | 1 + configs/orangepi_2_defconfig | 1 + configs/orangepi_lite_defconfig | 1 + configs/orangepi_one_defconfig | 1 + configs/orangepi_pc2_defconfig | 1 + configs/orangepi_pc_defconfig | 1 + configs/orangepi_pc_plus_defconfig | 1 + configs/orangepi_plus2e_defconfig | 1 + configs/orangepi_plus_defconfig | 1 + configs/orangepi_prime_defconfig | 1 + configs/orangepi_r1_defconfig | 1 + configs/orangepi_win_defconfig | 1 + configs/orangepi_zero_defconfig | 1 + configs/orangepi_zero_plus2_defconfig | 1 + configs/orangepi_zero_plus_defconfig | 1 + configs/parrot_r16_defconfig | 1 + configs/pine64_plus_defconfig | 1 + configs/r7-tv-dongle_defconfig | 1 + configs/sopine_baseboard_defconfig | 1 + configs/sun8i_a23_evb_defconfig | 1 + configs/sunxi_Gemei_G9_defconfig | 1 + configs/tbs_a711_defconfig | 1 + drivers/usb/host/Kconfig | 2 ++ include/configs/sun4i.h | 4 ---- include/configs/sun50i.h | 5 ----- include/configs/sun5i.h | 4 ---- include/configs/sun6i.h | 4 ---- include/configs/sun7i.h | 4 ---- include/configs/sun8i.h | 4 ---- include/configs/sunxi-common.h | 1 - 97 files changed, 91 insertions(+), 26 deletions(-)
configs/A10-OLinuXino-Lime_defconfig +1 -0
@@ -22,5 +22,6 @@ CONFIG_SUN4I_EMAC=y CONFIG_AXP_ALDO3_VOLT=2800 CONFIG_AXP_ALDO4_VOLT=2800 CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A10s-OLinuXino-M_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_MII=y CONFIG_SUN4I_EMAC=y CONFIG_AXP152_POWER=y CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A13-OLinuXinoM_defconfig +1 -0
@@ -19,5 +19,6 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_DEFAULT_DEVICE_TREE="sun5i-a13-olinuxino-micro" CONFIG_SUNXI_NO_PMIC=y CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A13-OLinuXino_defconfig +1 -0
@@ -26,6 +26,7 @@ CONFIG_DFU_RAM=y CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_AXP_ALDO3_VOLT=3300 CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A20-OLinuXino-Lime2-eMMC_defconfig +1 -0
@@ -31,6 +31,7 @@ CONFIG_AXP_ALDO3_VOLT=2800 CONFIG_AXP_ALDO3_VOLT_SLOPE_08=y CONFIG_AXP_ALDO4_VOLT=2800 CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A20-OLinuXino-Lime2_defconfig +1 -0
@@ -30,6 +30,7 @@ CONFIG_AXP_ALDO3_VOLT=2800 CONFIG_AXP_ALDO3_VOLT_SLOPE_08=y CONFIG_AXP_ALDO4_VOLT=2800 CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A20-OLinuXino-Lime_defconfig +1 -0
@@ -21,5 +21,6 @@ CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO3_VOLT=2800 CONFIG_AXP_ALDO4_VOLT=2800 CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/A20-Olimex-SOM204-EVB_defconfig +1 -0
@@ -29,6 +29,7 @@ CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO3_VOLT=2800 CONFIG_AXP_ALDO4_VOLT=2800 CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Auxtek-T003_defconfig +1 -0
@@ -15,5 +15,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-auxtek-t003" CONFIG_AXP152_POWER=y CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Auxtek-T004_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-auxtek-t004" CONFIG_AXP152_POWER=y CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Bananapi_defconfig +1 -0
@@ -21,5 +21,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Bananapi_m2m_defconfig +1 -0
@@ -15,6 +15,7 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_PARTITION_UUIDS is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-r16-bananapi-m2m" CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_FUNCTION_MASS_STORAGE=y
configs/Bananapro_defconfig +1 -0
@@ -24,5 +24,6 @@ CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO4_VOLT=2500 CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/CHIP_defconfig +1 -0
@@ -17,6 +17,7 @@ CONFIG_DFU_RAM=y CONFIG_AXP_ALDO3_VOLT=3300 CONFIG_AXP_ALDO4_VOLT=3300 CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/CHIP_pro_defconfig +1 -0
@@ -22,6 +22,7 @@ CONFIG_SYS_NAND_OOBSIZE=0x100 CONFIG_AXP_ALDO3_VOLT=3300 CONFIG_AXP_ALDO4_VOLT=3300 CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/CSQ_CS908_defconfig +1 -0
@@ -16,6 +16,7 @@ CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO1_VOLT=3300 CONFIG_AXP_DLDO1_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Colombus_defconfig +1 -0
@@ -26,5 +26,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO1_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Cubieboard2_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Cubieboard_defconfig +1 -0
@@ -17,5 +17,6 @@ CONFIG_SCSI_AHCI=y CONFIG_MII=y CONFIG_SUN4I_EMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Cubietruck_plus_defconfig +1 -0
@@ -23,6 +23,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-cubietruck-plus" CONFIG_AXP_DLDO3_VOLT=2500 CONFIG_AXP_DLDO4_VOLT=3300 CONFIG_AXP_FLDO1_VOLT=1200 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Hummingbird_A31_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO1_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Itead_Ibox_A20_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Linksprite_pcDuino3_Nano_defconfig +1 -0
@@ -21,5 +21,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Linksprite_pcDuino3_defconfig +1 -0
@@ -20,5 +20,6 @@ CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y CONFIG_DM_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Linksprite_pcDuino_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-pcduino" CONFIG_MII=y CONFIG_SUN4I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/MK808C_defconfig +1 -0
@@ -10,5 +10,6 @@ CONFIG_SPL_I2C_SUPPORT=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-mk808c" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Marsboard_A10_defconfig +1 -0
@@ -14,5 +14,6 @@ CONFIG_MII=y CONFIG_SUN4I_EMAC=y CONFIG_SUNXI_NO_PMIC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mele_A1000G_quad_defconfig +1 -0
@@ -19,6 +19,7 @@ CONFIG_AXP_DCDC1_VOLT=3300 CONFIG_AXP_ALDO1_VOLT=3300 CONFIG_AXP_DLDO1_VOLT=3300 CONFIG_AXP_DLDO4_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mele_A1000_defconfig +1 -0
@@ -17,5 +17,6 @@ CONFIG_SCSI_AHCI=y CONFIG_MII=y CONFIG_SUN4I_EMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mele_I7_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_AXP_DCDC1_VOLT=3300 CONFIG_AXP_ALDO1_VOLT=3300 CONFIG_AXP_DLDO1_VOLT=3300 CONFIG_AXP_DLDO4_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mele_M3_defconfig +1 -0
@@ -17,5 +17,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-m3" CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mele_M5_defconfig +1 -0
@@ -19,5 +19,6 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mele_M9_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_AXP_DCDC1_VOLT=3300 CONFIG_AXP_ALDO1_VOLT=3300 CONFIG_AXP_DLDO1_VOLT=3300 CONFIG_AXP_DLDO4_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Mini-X_defconfig +1 -0
@@ -12,5 +12,6 @@ CONFIG_SPL_I2C_SUPPORT=y # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-mini-xplus" CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Orangepi_defconfig +1 -0
@@ -23,5 +23,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Orangepi_mini_defconfig +1 -0
@@ -25,5 +25,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Sinlinx_SinA31s_defconfig +1 -0
@@ -19,5 +19,6 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_AXP_DLDO1_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Sinlinx_SinA33_defconfig +1 -0
@@ -20,6 +20,7 @@ CONFIG_CMD_DFU=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-a33-sinlinx-sina33" CONFIG_DFU_RAM=y CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Sinovoip_BPI_M2_Plus_defconfig +1 -0
@@ -14,6 +14,7 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Sinovoip_BPI_M2_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO1_VOLT=3300 CONFIG_AXP_ALDO2_VOLT=1800 CONFIG_AXP_DLDO1_VOLT=3000 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Sinovoip_BPI_M3_defconfig +1 -0
@@ -24,6 +24,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-bananapi-m3" CONFIG_AXP_DCDC5_VOLT=1200 CONFIG_AXP_DLDO3_VOLT=2500 CONFIG_AXP_SW_ON=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Wexler_TAB7200_defconfig +1 -0
@@ -18,6 +18,7 @@ CONFIG_SPL_I2C_SUPPORT=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-wexler-tab7200" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/Wobo_i5_defconfig +1 -0
@@ -15,5 +15,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-wobo-i5" CONFIG_AXP_ALDO3_VOLT=3300 CONFIG_AXP_ALDO4_VOLT=3300 CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/a64-olinuxino_defconfig +1 -0
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-olinuxino" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/ba10_tv_box_defconfig +1 -0
@@ -16,6 +16,7 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-ba10-tvbox" CONFIG_MII=y CONFIG_SUN4I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/bananapi_m1_plus_defconfig +1 -0
@@ -21,4 +21,5 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_SCSI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y
configs/bananapi_m64_defconfig +1 -0
@@ -12,6 +12,7 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/ga10h_v1_1_defconfig +1 -0
@@ -23,6 +23,7 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a33-ga10h-v1.1" CONFIG_AXP_DLDO1_VOLT=3300 CONFIG_CONS_INDEX=5 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/h8_homlet_v2_defconfig +1 -0
@@ -16,6 +16,7 @@ CONFIG_CONSOLE_MUX=y # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-allwinner-h8homlet-v2" CONFIG_AXP_DLDO4_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/i12-tvbox_defconfig +1 -0
@@ -15,5 +15,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox" CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/icnova-a20-swac_defconfig +1 -0
@@ -22,5 +22,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-icnova-swac" CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/inet1_defconfig +1 -0
@@ -19,6 +19,7 @@ CONFIG_SPL_I2C_SUPPORT=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-inet1" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/inet_q972_defconfig +1 -0
@@ -20,6 +20,7 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31s-inet-q972" CONFIG_AXP_DLDO1_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/jesurun_q5_defconfig +1 -0
@@ -15,6 +15,7 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5" CONFIG_MII=y CONFIG_SUN4I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_HOST=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/libretech_all_h3_cc_h2_plus_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-libretech-all-h3-cc" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/libretech_all_h3_cc_h3_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-libretech-all-h3-cc" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/libretech_all_h3_cc_h5_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-libretech-all-h3-cc" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/mixtile_loftq_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y CONFIG_AXP_ALDO1_VOLT=3300 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/mk802_a10s_defconfig +1 -0
@@ -14,5 +14,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-mk802" CONFIG_AXP152_POWER=y CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/mk802_defconfig +1 -0
@@ -10,5 +10,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-mk802" CONFIG_SUNXI_NO_PMIC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/mk802ii_defconfig +1 -0
@@ -9,5 +9,6 @@ CONFIG_SPL_I2C_SUPPORT=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-mk802ii" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_a64_defconfig +1 -0
@@ -10,5 +10,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-nanopi-a64" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_m1_defconfig +1 -0
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_m1_plus_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_neo2_defconfig +1 -0
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-nanopi-neo2" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_neo_air_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_CONSOLE_MUX=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-neo-air" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_neo_defconfig +1 -0
@@ -14,5 +14,6 @@ CONFIG_CONSOLE_MUX=y # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-neo" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/nanopi_neo_plus2_defconfig +1 -0
@@ -13,4 +13,5 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-nanopi-neo-plus2" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y
configs/orangepi_2_defconfig +1 -0
@@ -16,5 +16,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-2" CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_lite_defconfig +1 -0
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-lite" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_one_defconfig +1 -0
@@ -12,5 +12,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-one" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_pc2_defconfig +1 -0
@@ -13,6 +13,7 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-pc2" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_pc_defconfig +1 -0
@@ -14,5 +14,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc" CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_pc_plus_defconfig +1 -0
@@ -15,5 +15,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc-plus" CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_plus2e_defconfig +1 -0
@@ -16,5 +16,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e" CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_plus_defconfig +1 -0
@@ -18,5 +18,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus" CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_prime_defconfig +1 -0
@@ -11,6 +11,7 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-prime" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_r1_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_CONSOLE_MUX=y # CONFIG_CMD_FLASH is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-orangepi-r1" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_win_defconfig +1 -0
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_zero_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_CONSOLE_MUX=y # CONFIG_CMD_FLASH is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-orangepi-zero" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_zero_plus2_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-zero-plus2" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/orangepi_zero_plus_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-zero-plus" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/parrot_r16_defconfig +1 -0
@@ -18,6 +18,7 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_DEFAULT_DEVICE_TREE="sun8i-r16-parrot" CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_CONS_INDEX=5 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/pine64_plus_defconfig +1 -0
@@ -14,5 +14,6 @@ CONFIG_OF_LIST="sun50i-a64-pine64 sun50i-a64-pine64-plus" CONFIG_PHY_REALTEK=y CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/r7-tv-dongle_defconfig +1 -0
@@ -13,5 +13,6 @@ CONFIG_SPL_I2C_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-r7-tv-dongle" CONFIG_AXP152_POWER=y CONFIG_CONS_INDEX=2 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/sopine_baseboard_defconfig +1 -0
@@ -16,5 +16,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard" CONFIG_SUN8I_EMAC=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/sun8i_a23_evb_defconfig +1 -0
@@ -14,5 +14,6 @@ CONFIG_NR_DRAM_BANKS=1 # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-evb" CONFIG_CONS_INDEX=5 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/sunxi_Gemei_G9_defconfig +1 -0
@@ -16,5 +16,6 @@ CONFIG_SPL_I2C_SUPPORT=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-gemei-g9" +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
configs/tbs_a711_defconfig +1 -0
@@ -19,6 +19,7 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-tbs-a711" CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_AXP_DCDC5_VOLT=1200 +CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_FUNCTION_MASS_STORAGE=y
drivers/usb/host/Kconfig +2 -0
@@ -190,6 +190,7 @@ config USB_EHCI_GENERIC bool "Support for generic EHCI USB controller" depends on OF_CONTROL depends on DM_USB + default ARCH_SUNXI default n ---help--- Enables support for generic EHCI controller.
@@ -220,6 +221,7 @@ config USB_OHCI_GENERIC bool "Support for generic OHCI USB controller" depends on OF_CONTROL depends on DM_USB + default ARCH_SUNXI select USB_HOST ---help--- Enables support for generic OHCI controller.
include/configs/sun4i.h +0 -4
@@ -11,10 +11,6 @@* A10 specific configuration */ -#ifdef CONFIG_USB_EHCI_HCD -#define CONFIG_USB_EHCI_SUNXI -#endif -/* * Include common sunxi configuration where most the settings are */
include/configs/sun50i.h +0 -5
@@ -10,11 +10,6 @@* A64 specific configuration */ -#ifdef CONFIG_USB_EHCI_HCD -#define CONFIG_USB_EHCI_SUNXI -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#endif -#ifndef CONFIG_MACH_SUN50I_H6 #define GICD_BASE 0x1c81000#define GICC_BASE 0x1c82000
include/configs/sun5i.h +0 -4
@@ -11,10 +11,6 @@* High Level Configuration Options */ -#ifdef CONFIG_USB_EHCI_HCD -#define CONFIG_USB_EHCI_SUNXI -#endif -/* * Include common sunxi configuration where most the settings are */
include/configs/sun6i.h +0 -4
@@ -14,10 +14,6 @@* A31 specific configuration */ -#ifdef CONFIG_USB_EHCI_HCD -#define CONFIG_USB_EHCI_SUNXI -#endif -#define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE#define CONFIG_ARMV7_SECURE_MAX_SIZE (64 * 1024)/* 64 KB */
include/configs/sun7i.h +0 -4
@@ -12,10 +12,6 @@* A20 specific configuration */ -#ifdef CONFIG_USB_EHCI_HCD -#define CONFIG_USB_EHCI_SUNXI -#endif -#define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE#define CONFIG_ARMV7_SECURE_MAX_SIZE (64 * 1024)/* 64 KB */
include/configs/sun8i.h +0 -4
@@ -12,10 +12,6 @@* A23 specific configuration */ -#ifdef CONFIG_USB_EHCI_HCD -#define CONFIG_USB_EHCI_SUNXI -#endif -/* * Include common sunxi configuration where most the settings are */
include/configs/sunxi-common.h +0 -1
@@ -295,7 +295,6 @@ extern int soft_i2c_gpio_scl;#ifdef CONFIG_USB_EHCI_HCD #define CONFIG_USB_OHCI_NEW -#define CONFIG_USB_OHCI_SUNXI #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1#endif
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 21/26 usb: host: Drop [e-o]hci-sunxi drivers
In reply to Jagan TekiNow Allwinner platform is all set to use Generic USB controller drivers, so remove the legacy sunxi drivers.
--- drivers/usb/host/Makefile | 2 - drivers/usb/host/ehci-sunxi.c | 204 ----------------------------- drivers/usb/host/ohci-sunxi.c | 233 ---------------------------------- scripts/config_whitelist.txt | 2 - 4 files changed, 441 deletions(-) delete mode 100644 drivers/usb/host/ehci-sunxi.c delete mode 100644 drivers/usb/host/ohci-sunxi.c
drivers/usb/host/Makefile +0 -2
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o -obj-$(CONFIG_USB_OHCI_SUNXI) += ohci-sunxi.o obj-$(CONFIG_USB_OHCI_LPC32XX) += ohci-lpc32xx.o obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o
@@ -37,7 +36,6 @@ obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o -obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o obj-$(CONFIG_USB_EHCI_VF) += ehci-vf.o
drivers/usb/host/ehci-sunxi.c deleted +0 -204
204 lines not on this page · raw message
drivers/usb/host/ohci-sunxi.c deleted +0 -233
233 lines not on this page · raw message
scripts/config_whitelist.txt +0 -2
@@ -4548,7 +4548,6 @@ CONFIG_USB_EHCI_MX5 CONFIG_USB_EHCI_MXC CONFIG_USB_EHCI_MXS CONFIG_USB_EHCI_SPEAR -CONFIG_USB_EHCI_SUNXI CONFIG_USB_EHCI_TEGRA CONFIG_USB_EHCI_TXFIFO_THRESH CONFIG_USB_EHCI_VCT
@@ -4587,7 +4586,6 @@ CONFIG_USB_MUSB_TUSB6010 CONFIG_USB_OHCI_EP93XX CONFIG_USB_OHCI_LPC32XX CONFIG_USB_OHCI_NEW -CONFIG_USB_OHCI_SUNXI CONFIG_USB_OTG CONFIG_USB_OTG_BLACKLIST_HUB CONFIG_USB_PHY_CFG_BASE
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 22/26 clk: sunxi: Implement SPI clocks
In reply to Jagan TekiImplement SPI AHB and MOD clocks for Allwinner A10/A20 and A10s/A13 SoC clock drivers via ccu clock gate table.
--- drivers/clk/sunxi/clk_a10.c | 9 +++++++++ drivers/clk/sunxi/clk_a10s.c | 7 +++++++ 2 files changed, 16 insertions(+)
drivers/clk/sunxi/clk_a10.c +9 -0
@@ -18,6 +18,15 @@ static struct ccu_clk_gate a10_gates[] = { [CLK_AHB_OHCI0] = GATE(0x060, BIT(2)), [CLK_AHB_EHCI1] = GATE(0x060, BIT(3)), [CLK_AHB_OHCI1] = GATE(0x060, BIT(4)), + [CLK_AHB_SPI0] = GATE(0x060, BIT(20)), + [CLK_AHB_SPI1] = GATE(0x060, BIT(21)), + [CLK_AHB_SPI2] = GATE(0x060, BIT(22)), + [CLK_AHB_SPI3] = GATE(0x060, BIT(23)), + + [CLK_SPI0] = GATE(0x0a0, BIT(31)), + [CLK_SPI1] = GATE(0x0a4, BIT(31)), + [CLK_SPI2] = GATE(0x0a8, BIT(31)), + [CLK_SPI3] = GATE(0x0d4, BIT(31)), [CLK_APB1_UART0] = GATE(0x06c, BIT(16)), [CLK_APB1_UART1] = GATE(0x06c, BIT(17)),
drivers/clk/sunxi/clk_a10s.c +7 -0
@@ -16,6 +16,13 @@ static struct ccu_clk_gate a10s_gates[] = { [CLK_AHB_OTG] = GATE(0x060, BIT(0)), [CLK_AHB_EHCI] = GATE(0x060, BIT(1)), [CLK_AHB_OHCI] = GATE(0x060, BIT(2)), + [CLK_AHB_SPI0] = GATE(0x060, BIT(20)), + [CLK_AHB_SPI1] = GATE(0x060, BIT(21)), + [CLK_AHB_SPI2] = GATE(0x060, BIT(22)), + + [CLK_SPI0] = GATE(0x0a0, BIT(31)), + [CLK_SPI1] = GATE(0x0a4, BIT(31)), + [CLK_SPI2] = GATE(0x0a8, BIT(31)), [CLK_APB1_UART0] = GATE(0x06c, BIT(16)), [CLK_APB1_UART1] = GATE(0x06c, BIT(17)),
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 23/26 spi: sun4i: Add CLK support
In reply to Jagan TekiAdd CLK support to enable AHB and MOD SPI clocks
on sun4i_spi driver.
--- drivers/spi/sun4i_spi.c | 46 +++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-)
drivers/spi/sun4i_spi.c +40 -6
@@ -19,6 +19,7 @@*/ #include <common.h> +#include <clk.h> #include <dm.h> #include <spi.h> #include <errno.h>
@@ -114,6 +115,8 @@ struct sun4i_spi_platdata {struct sun4i_spi_priv {struct sun4i_spi_regs *regs; +struct clk ahb_clk; +struct clk mod_clk;u32 freq;u32 mode;
@@ -238,13 +241,40 @@ static int sun4i_spi_parse_pins(struct udevice *dev)return 0 ; } -static inline void sun4i_spi_enable_clock (void ) +static inline int sun4i_spi_enable_clock (struct udevice *dev) { -struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *const )SUNXI_CCM_BASE ; +struct sun4i_spi_priv *priv =dev_get_priv (dev); +int ret; + + ret =clk_get_by_name (dev,"ahb" , &priv->ahb_clk); +if (ret) { +dev_err (dev,"failed to get ahb clock\n" ); +return ret; + } + + ret =clk_get_by_name (dev,"mod" , &priv->mod_clk); +if (ret) { +dev_err (dev,"failed to get mod clock\n" ); +return ret; + } + + ret =clk_enable (&priv->ahb_clk); +if (ret) { +dev_err (dev,"failed to enable ahb clock (ret=%d)\n" , ret); +return ret; + } + + ret =clk_enable (&priv->mod_clk); +if (ret) { +dev_err (dev,"failed to enable mod clock (ret=%d)\n" , ret); + goto err_ahb; + } -setbits_le32 (&ccm->ahb_gate0, (1 <<AHB_GATE_OFFSET_SPI0 )); -writel ((1 <<31 ), &ccm->spi0_clk_cfg); +return 0 ; + +err_ahb: +clk_disable (&priv->ahb_clk); +return ret; }static int sun4i_spi_ofdata_to_platdata (struct udevice *bus)
@@ -267,8 +297,12 @@ static int sun4i_spi_probe(struct udevice *bus) {struct sun4i_spi_platdata *plat =dev_get_platdata (bus);struct sun4i_spi_priv *priv =dev_get_priv (bus); +int ret; + + ret =sun4i_spi_enable_clock (bus); +if (ret) +return ret; -sun4i_spi_enable_clock ();sun4i_spi_parse_pins (bus); priv->regs = (struct sun4i_spi_regs *)(uintptr_t )plat->base_addr;
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 24/26 clk: sunxi: Implement A64 SPI clocks, resets
In reply to Jagan TekiImplement SPI AHB, MOD clocks and resets for Allwinner A64.
--- drivers/clk/sunxi/clk_a64.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/clk/sunxi/clk_a64.c +7 -0
@@ -52,6 +52,8 @@ static const struct ccu_clk_tree a64_tree[] = { };static const struct ccu_clk_gate a64_gates[] = { + [CLK_BUS_SPI0 ] =GATE (0x060 ,BIT (20 )), + [CLK_BUS_SPI1 ] =GATE (0x060 ,BIT (21 )), [CLK_BUS_OTG ] =GATE (0x060 ,BIT (23 )), [CLK_BUS_EHCI0 ] =GATE (0x060 ,BIT (24 )), [CLK_BUS_EHCI1 ] =GATE (0x060 ,BIT (25 )),
@@ -64,6 +66,9 @@ static const struct ccu_clk_gate a64_gates[] = { [CLK_BUS_UART3] = GATE(0x06c, BIT(19)), [CLK_BUS_UART4] = GATE(0x06c, BIT(20)), + [CLK_SPI0] = GATE(0x0a0, BIT(31)), + [CLK_SPI1] = GATE(0x0a4, BIT(31)), + [CLK_USB_PHY0] = GATE(0x0cc, BIT(8)), [CLK_USB_PHY1] = GATE(0x0cc, BIT(9)), [CLK_USB_HSIC] = GATE(0x0cc, BIT(10)),
@@ -77,6 +82,8 @@ static const struct ccu_reset a64_resets[] = { [RST_USB_PHY1] = RESET(0x0cc, BIT(1)), [RST_USB_HSIC] = RESET(0x0cc, BIT(2)), + [RST_BUS_SPI0] = RESET(0x2c0, BIT(20)), + [RST_BUS_SPI1] = RESET(0x2c0, BIT(21)), [RST_BUS_OTG] = RESET(0x2c0, BIT(23)), [RST_BUS_EHCI0] = RESET(0x2c0, BIT(24)), [RST_BUS_EHCI1] = RESET(0x2c0, BIT(25)),
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 25/26 spi: Add Allwinner A31 SPI driver
In reply to Jagan TekiAdd Allwinner sun6i SPI driver for A31, H3/H5 an A64.
--- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/sun6i_spi.c | 398 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 405 insertions(+) create mode 100644 drivers/spi/sun6i_spi.c
drivers/spi/Kconfig +6 -0
@@ -223,6 +223,12 @@ config SUN4I_SPI help SPI driver for Allwinner sun4i, sun5i and sun7i SoCs +config SUN6I_SPI + bool "Allwinner A31 SPI controller" + depends on ARCH_SUNXI + help + This enables using the SPI controller on the Allwinner A31 SoCs. + config TEGRA114_SPI bool "nVidia Tegra114 SPI driver" help
drivers/spi/Makefile +1 -0
@@ -50,6 +50,7 @@ obj-$(CONFIG_SH_SPI) += sh_spi.o obj-$(CONFIG_SH_QSPI) += sh_qspi.o obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o obj-$(CONFIG_SUN4I_SPI) += sun4i_spi.o +obj-$(CONFIG_SUN6I_SPI) += sun6i_spi.o obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
drivers/spi/sun6i_spi.c new file +398 -0
398 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 26/26 board: sopine: Enable SPI/SPI-FLASH
In reply to Jagan TekiSopine has Winbond SPI flash, so enable the same to use flash on Sopine board.
--- .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 ++++++++++++++++ configs/sopine_baseboard_defconfig | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file +16 -0
@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Jagan Teki <[email protected]> + */ + +/ { + aliases { + spi0 = &spi0; + }; +}; + +&spi0 { + flash at 0 { + compatible = "spi-flash"; + }; +};
configs/sopine_baseboard_defconfig +7 -0
@@ -12,9 +12,16 @@ CONFIG_SPL_SPI_SUNXI=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set +CONFIG_CMD_SF=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard" +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_SUN6I_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_EHCI_HCD=y
Signature · 1 line
2.18.0.321.gffc6fa0e3
PATCH v5 26/26 board: sopine: Enable SPI/SPI-FLASH
Quoted 41 lines · Jagan Teki
Sopine has Winbond SPI flash, so enable the same to use flash on Sopine board.
Cc TL Lim <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 ++++++++++++++++ configs/sopine_baseboard_defconfig | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsiarch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file +16
-0@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Jagan Teki <[email protected]> + */ + +/ { + aliases { + spi0 = &spi0; + }; +}; + +&spi0 { + flash at 0 { + compatible = "spi-flash"; + }; +};configs/sopine_baseboard_defconfig +0
-0@@ -12,9 +12,16 @@ CONFIG_SPL_SPI_SUNXI=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set
configs/sopine_baseboard_defconfig CONFIG_SPL_SPI_SUNXI=y · line 24
Quoted 10 lines
configs/sopine_baseboard_defconfig +7
-0+CONFIG_CMD_SF=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard" +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_SUN6I_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_WINBOND=y
SPI, DM_SPI and SUN6I_SPI seem redundant to me, just like SPI_FLASH_WINBOND, DM_SPI_FLASH, and SPI_FLASH.
We should do better to provide the needed Kconfig select/depends on/defaults to have to enable only the SPI_FLASH_WINBOND. Everything else can be derived from that.
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190107/04c82823/attachment.sig>
PATCH v5 26/26 board: sopine: Enable SPI/SPI-FLASH
In reply to Jagan Tekiarch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
Quoted 16 lines · Jagan Teki
Sopine has Winbond SPI flash, so enable the same to use flash on Sopine board.
Cc TL Lim <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 ++++++++++++++++ configs/sopine_baseboard_defconfig | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsiarch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file +0
-0
Where does this dtsi get included?
Alex
PATCH v5 26/26 board: sopine: Enable SPI/SPI-FLASH
Quoted 13 lines · On Tue, 22 Jan 2019 17:32:27 +0100 Alexander Graf <[email protected]> wrote:
Quoted 12 lines · Jagan Teki
Sopine has Winbond SPI flash, so enable the same to use flash on Sopine board.
Cc TL Lim <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 ++++++++++++++++ configs/sopine_baseboard_defconfig | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644
arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
Quoted 7 lines
arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
Quoted 5 lines
(quoted diff) +0
-0
b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsinew file mode 100644 index 0000000000..9661b95d15arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file +0
-0Where does this dtsi get included?
This is some U-Boot build system magic, more precisely by binman:
http://git.denx.de/?p=u-boot.git;a=blob;f=tools/binman/README;hb=HEAD#l564
Cheers,
Andre.
PATCH v5 26/26 board: sopine: Enable SPI/SPI-FLASH
Quoted 24 lines · Andre Przywara
Quoted 13 lines · On Tue, 22 Jan 2019 17:32:27 +0100 Alexander Graf <[email protected]> wrote:
Quoted 12 lines · Jagan Teki
Sopine has Winbond SPI flash, so enable the same to use flash on Sopine board.
Cc TL Lim <[email protected]>Signed-off-by Jagan Teki <[email protected]>--- .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 ++++++++++++++++ configs/sopine_baseboard_defconfig | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644
arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsiQuoted 7 lines
arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
Quoted 5 lines
(quoted diff) +0
-0
b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsinew file mode 100644 index 0000000000..9661b95d15arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file +0
-0Where does this dtsi get included?
Quoted 2 lines
This is some U-Boot build system magic, more precisely by binman:
http://git.denx.de/?p=u-boot.git;a=blob;f=tools/binman/README;hb=HEAD#l564
Well, scripts/Makefile.lib has the logic for searching for the most appropriate -u-boot.dtsi file.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190122/bf5be876/attachment.sig>
v5 cover clk: Add Allwinner CLK, RESET support
In reply to Jagan TekiQuoted 57 lines · Jagan Teki
Although the previous version[1] is properly handled the clock gates with enable and disable management, but this series is trying to add some more complex Allwinner CLK architecture by handling parent clock and other CLK attributes.
Allwinner Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management and these can be handled via
ccu_clock_gate, which is almost same as previous version changes.Tree clock has more Allwinner CLK attributes like clock type, fixed clocks, misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be managed via
ccu_clock_tree.On top of initial clock gates supported from previous version, this series is trying to add support for MP, NK, MISC, FIXED clock types with
get_ratefunctionality and that can eventually used by uart driver.On the summary, this would be an initial infrasture that can fit into remaining clock handle support like
set_rate, so the rest of code will add on the requirement basics.Once this is fine, I will try to add code for other parts especially for MMC since we have migration deadline for BLK, MMC, SCSI.
So, please do let me know if anyone have any inputs.
All these changes available at u-boot-sunxi/clk-next
thanks,
Jagan.[1] https://patchwork.ozlabs.org/cover/962226/
Jagan Teki (26):
clk: Add Allwinner A64 CLK driver
reset: Add Allwinner RESET driver
clk: sunxi: Add Allwinner H3/H5 CLK driver
clk: sunxi: Add Allwinner A10/A20 CLK driver
clk: sunxi: Add Allwinner A10s/A13 CLK driver
clk: sunxi: Add Allwinner A31 CLK driver
clk: sunxi: Add Allwinner A23/A33 CLK driver
clk: sunxi: Add Allwinner A83T CLK driver
clk: sunxi: Add Allwinner R40 CLK driver
clk: sunxi: Add Allwinner V3S CLK driver
clk: sunxi: Implement UART clocks
clk: sunxi: Implement UART resets
clk: sunxi: Add Allwinner H6 CLK driver
sunxi: A64: Updatesun50i-a64-ccu.h
clk: sunxi: Add ccu clock tree support
sunxi: Enable CLK
phy: sun4i-usb: Use CLK and RESET support
reset: Add reset valid
Quoted 8 lines
musb-new: sunxi: Use CLK and RESET support
sunxi: usb: Switch to Generic host controllers
usb: host: Drop [e-o]hci-sunxi drivers
clk: sunxi: Implement SPI clocks
spi: sun4i: Add CLK support
clk: sunxi: Implement A64 SPI clocks, resets
spi: Add Allwinner A31 SPI driver
board: sopine: Enable SPI/SPI-FLASH
I'm planning to pick gate clock patches and keep tree based clock for next version, let me know if anyone have any questions.
v5 cover clk: Add Allwinner CLK, RESET support
In reply to Jagan TekiOn 31/12/2018 16:59, Jagan Teki wrote:
Hi Jagan,
many thanks for picking this up, I was about to come back to this myself. I am looking at the pinctrl part at the moment, so good you are working on the clocks!
TL;DR: I am good with the first patches, but would like to drop the last five 5 patches from this series, and discuss the whole tree approach (or at least the patch) further.
Quoted 5 lines
Although the previous version[1] is properly handled the clock gates with enable and disable management, but this series is trying to add some more complex Allwinner CLK architecture by handling parent clock and other CLK attributes.
Quoted 7 lines
Allwinner Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management and these can be handled via
ccu_clock_gate, which is almost same as previous version changes.
So I like this part very much, all those gates and resets are nicely readable.
Also the removal of the special sunxi USB drivers is very welcome. So up until patch including 21/26, except 15/26, I am all in.
Quoted 3 lines
Tree clock has more Allwinner CLK attributes like clock type, fixed clocks, misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be managed via
ccu_clock_tree.
Mmmh, this looks quite complex for U-Boot's very limited needs to me. As far as I can see we basically have a static setup for most devices, the ones where we actually change the parent clocks are only clock consumers, namely DE/TCON and MMC. The former chooses a parent once, based on the calculated clock rate. Only for MMC we switch it from OSC24 (for the initial SPI-like setup phase) to PLL_PERIPH0 at runtime. But however this does not really affect the tree, and also we never do re-parenting.
Under this premises, can't we do this somewhat simpler? At the end of the day this is U-Boot, not a sophisticated kernel, and we got away with quite simple clock code so far.
Meanwhile I am struggling to understand your approach, which looks impressive on the first glance, but leave me scratching my head when looking at details. I will comment on 15/26 for the parts I am wondering about. I was trying to add MMC support and hit some issues.
On the SPI part:
I am bit puzzled about the last 5 patches dealing with SPI. I see that they depend on the others, but would like to deal with them separately.
First, patch 25/26 (the sun6i SPI driver) is a bit surprising to find in here. I guess you want to have an easy user for another clock, but I believe this should be a separate series. There were other posts already for a sun6i driver, also I think we should have a unified driver instead of duplicating most of it again. See Oskari's latest post.
Secondly: I don't think the SPI clocks are correct. You model them as simple gates only, kind of ignoring the divider settings. This is what the current sun4i driver does as well, but: it writes 1U << 31 into the clock register, which explicitly writes 0 to the other bits, setting 24 MHz as the input rate. Your approach would read-modify-write the register, just setting bit 31 and leaving the other ones as they were before.
So why isn't that using your new tree approach? Looks like a standard mux/divider clock to me.
Cheers,
Andre.
Quoted 199 lines
On top of initial clock gates supported from previous version, this series is trying to add support for MP, NK, MISC, FIXED clock types with
get_ratefunctionality and that can eventually used by uart driver.On the summary, this would be an initial infrasture that can fit into remaining clock handle support like
set_rate, so the rest of code will add on the requirement basics.Once this is fine, I will try to add code for other parts especially for MMC since we have migration deadline for BLK, MMC, SCSI.
So, please do let me know if anyone have any inputs.
All these changes available at u-boot-sunxi/clk-next
thanks,
Jagan.[1] https://patchwork.ozlabs.org/cover/962226/
Jagan Teki (26):
clk: Add Allwinner A64 CLK driver
reset: Add Allwinner RESET driver
clk: sunxi: Add Allwinner H3/H5 CLK driver
clk: sunxi: Add Allwinner A10/A20 CLK driver
clk: sunxi: Add Allwinner A10s/A13 CLK driver
clk: sunxi: Add Allwinner A31 CLK driver
clk: sunxi: Add Allwinner A23/A33 CLK driver
clk: sunxi: Add Allwinner A83T CLK driver
clk: sunxi: Add Allwinner R40 CLK driver
clk: sunxi: Add Allwinner V3S CLK driver
clk: sunxi: Implement UART clocks
clk: sunxi: Implement UART resets
clk: sunxi: Add Allwinner H6 CLK driver
sunxi: A64: Updatesun50i-a64-ccu.h
clk: sunxi: Add ccu clock tree support
sunxi: Enable CLK
phy: sun4i-usb: Use CLK and RESET support
reset: Add reset valid
musb-new: sunxi: Use CLK and RESET support
sunxi: usb: Switch to Generic host controllers
usb: host: Drop [e-o]hci-sunxi drivers
clk: sunxi: Implement SPI clocks
spi: sun4i: Add CLK support
clk: sunxi: Implement A64 SPI clocks, resets
spi: Add Allwinner A31 SPI driver
board: sopine: Enable SPI/SPI-FLASH.../sun50i-a64-sopine-baseboard-u-boot.dtsi | 16 + arch/arm/include/asm/arch-sunxi/ccu.h | 284 +++++++++++++ arch/arm/mach-sunxi/Kconfig | 12 + configs/A10-OLinuXino-Lime_defconfig | 1 + configs/A10s-OLinuXino-M_defconfig | 1 + configs/A13-OLinuXinoM_defconfig | 1 + configs/A13-OLinuXino_defconfig | 1 + configs/A20-OLinuXino-Lime2-eMMC_defconfig | 1 + configs/A20-OLinuXino-Lime2_defconfig | 1 + configs/A20-OLinuXino-Lime_defconfig | 1 + configs/A20-Olimex-SOM204-EVB_defconfig | 1 + configs/Auxtek-T003_defconfig | 1 + configs/Auxtek-T004_defconfig | 1 + configs/Bananapi_defconfig | 1 + configs/Bananapi_m2m_defconfig | 1 + configs/Bananapro_defconfig | 1 + configs/CHIP_defconfig | 1 + configs/CHIP_pro_defconfig | 1 + configs/CSQ_CS908_defconfig | 1 + configs/Colombus_defconfig | 1 + configs/Cubieboard2_defconfig | 1 + configs/Cubieboard_defconfig | 1 + configs/Cubietruck_plus_defconfig | 1 + configs/Hummingbird_A31_defconfig | 1 + configs/Itead_Ibox_A20_defconfig | 1 + configs/Linksprite_pcDuino3_Nano_defconfig | 1 + configs/Linksprite_pcDuino3_defconfig | 1 + configs/Linksprite_pcDuino_defconfig | 1 + configs/MK808C_defconfig | 1 + configs/Marsboard_A10_defconfig | 1 + configs/Mele_A1000G_quad_defconfig | 1 + configs/Mele_A1000_defconfig | 1 + configs/Mele_I7_defconfig | 1 + configs/Mele_M3_defconfig | 1 + configs/Mele_M5_defconfig | 1 + configs/Mele_M9_defconfig | 1 + configs/Mini-X_defconfig | 1 + configs/Orangepi_defconfig | 1 + configs/Orangepi_mini_defconfig | 1 + configs/Sinlinx_SinA31s_defconfig | 1 + configs/Sinlinx_SinA33_defconfig | 1 + configs/Sinovoip_BPI_M2_Plus_defconfig | 1 + configs/Sinovoip_BPI_M2_defconfig | 1 + configs/Sinovoip_BPI_M3_defconfig | 1 + configs/Wexler_TAB7200_defconfig | 1 + configs/Wobo_i5_defconfig | 1 + configs/a64-olinuxino_defconfig | 1 + configs/ba10_tv_box_defconfig | 1 + configs/bananapi_m1_plus_defconfig | 1 + configs/bananapi_m64_defconfig | 1 + configs/ga10h_v1_1_defconfig | 1 + configs/h8_homlet_v2_defconfig | 1 + configs/i12-tvbox_defconfig | 1 + configs/icnova-a20-swac_defconfig | 1 + configs/inet1_defconfig | 1 + configs/inet_q972_defconfig | 1 + configs/jesurun_q5_defconfig | 1 + configs/libretech_all_h3_cc_h2_plus_defconfig | 1 + configs/libretech_all_h3_cc_h3_defconfig | 1 + configs/libretech_all_h3_cc_h5_defconfig | 1 + configs/mixtile_loftq_defconfig | 1 + configs/mk802_a10s_defconfig | 1 + configs/mk802_defconfig | 1 + configs/mk802ii_defconfig | 1 + configs/nanopi_a64_defconfig | 1 + configs/nanopi_m1_defconfig | 1 + configs/nanopi_m1_plus_defconfig | 1 + configs/nanopi_neo2_defconfig | 1 + configs/nanopi_neo_air_defconfig | 1 + configs/nanopi_neo_defconfig | 1 + configs/nanopi_neo_plus2_defconfig | 1 + configs/orangepi_2_defconfig | 1 + configs/orangepi_lite_defconfig | 1 + configs/orangepi_one_defconfig | 1 + configs/orangepi_pc2_defconfig | 1 + configs/orangepi_pc_defconfig | 1 + configs/orangepi_pc_plus_defconfig | 1 + configs/orangepi_plus2e_defconfig | 1 + configs/orangepi_plus_defconfig | 1 + configs/orangepi_prime_defconfig | 1 + configs/orangepi_r1_defconfig | 1 + configs/orangepi_win_defconfig | 1 + configs/orangepi_zero_defconfig | 1 + configs/orangepi_zero_plus2_defconfig | 1 + configs/orangepi_zero_plus_defconfig | 1 + configs/parrot_r16_defconfig | 1 + configs/pine64_plus_defconfig | 1 + configs/r7-tv-dongle_defconfig | 1 + configs/sopine_baseboard_defconfig | 8 + configs/sun8i_a23_evb_defconfig | 1 + configs/sunxi_Gemei_G9_defconfig | 1 + configs/tbs_a711_defconfig | 1 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sunxi/Kconfig | 82 ++++ drivers/clk/sunxi/Makefile | 18 + drivers/clk/sunxi/clk_a10.c | 77 ++++ drivers/clk/sunxi/clk_a10s.c | 68 +++ drivers/clk/sunxi/clk_a23.c | 75 ++++ drivers/clk/sunxi/clk_a31.c | 82 ++++ drivers/clk/sunxi/clk_a64.c | 125 ++++++ drivers/clk/sunxi/clk_a83t.c | 75 ++++ drivers/clk/sunxi/clk_h3.c | 89 ++++ drivers/clk/sunxi/clk_h6.c | 53 +++ drivers/clk/sunxi/clk_r40.c | 88 ++++ drivers/clk/sunxi/clk_sunxi.c | 256 +++++++++++ drivers/clk/sunxi/clk_v3s.c | 59 +++ drivers/phy/allwinner/phy-sun4i-usb.c | 77 +++- drivers/reset/Kconfig | 8 + drivers/reset/Makefile | 1 + drivers/reset/reset-sunxi.c | 125 ++++++ drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/sun4i_spi.c | 46 +- drivers/spi/sun6i_spi.c | 398 ++++++++++++++++++ drivers/usb/host/Kconfig | 2 + drivers/usb/host/Makefile | 2 - drivers/usb/host/ehci-sunxi.c | 204 --------- drivers/usb/host/ohci-sunxi.c | 233 ---------- drivers/usb/musb-new/sunxi.c | 81 ++-- include/configs/sun4i.h | 4 - include/configs/sun50i.h | 5 - include/configs/sun5i.h | 4 - include/configs/sun6i.h | 4 - include/configs/sun7i.h | 4 - include/configs/sun8i.h | 4 - include/configs/sunxi-common.h | 1 - include/dt-bindings/clock/sun50i-a64-ccu.h | 2 + include/reset.h | 11 + scripts/config_whitelist.txt | 2 - 130 files changed, 2248 insertions(+), 534 deletions(-) create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi create mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h create mode 100644 drivers/clk/sunxi/Kconfig create mode 100644 drivers/clk/sunxi/Makefile create mode 100644 drivers/clk/sunxi/clk_a10.c create mode 100644 drivers/clk/sunxi/clk_a10s.c create mode 100644 drivers/clk/sunxi/clk_a23.c create mode 100644 drivers/clk/sunxi/clk_a31.c create mode 100644 drivers/clk/sunxi/clk_a64.c create mode 100644 drivers/clk/sunxi/clk_a83t.c create mode 100644 drivers/clk/sunxi/clk_h3.c create mode 100644 drivers/clk/sunxi/clk_h6.c create mode 100644 drivers/clk/sunxi/clk_r40.c create mode 100644 drivers/clk/sunxi/clk_sunxi.c create mode 100644 drivers/clk/sunxi/clk_v3s.c create mode 100644 drivers/reset/reset-sunxi.c create mode 100644 drivers/spi/sun6i_spi.c delete mode 100644 drivers/usb/host/ehci-sunxi.c delete mode 100644 drivers/usb/host/ohci-sunxi.c
v5 cover clk: Add Allwinner CLK, RESET support
Quoted 26 lines · André Przywara
On 31/12/2018 16:59, Jagan Teki wrote:
Hi Jagan,
many thanks for picking this up, I was about to come back to this myself. I am looking at the pinctrl part at the moment, so good you are working on the clocks!
TL;DR: I am good with the first patches, but would like to drop the last five 5 patches from this series, and discuss the whole tree approach (or at least the patch) further.
Quoted 5 lines
Although the previous version[1] is properly handled the clock gates with enable and disable management, but this series is trying to add some more complex Allwinner CLK architecture by handling parent clock and other CLK attributes.
Quoted 7 lines
Allwinner Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management and these can be handled via
ccu_clock_gate, which is almost same as previous version changes.
Quoted 4 lines
So I like this part very much, all those gates and resets are nicely readable.
Also the removal of the special sunxi USB drivers is very welcome. So up until patch including 21/26, except 15/26, I am all in.
Yes my plan is to do the same.
Quoted 5 lines
Quoted 4 lines
Tree clock has more Allwinner CLK attributes like clock type, fixed clocks, misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be managed via
ccu_clock_tree.
Quoted 11 lines
Mmmh, this looks quite complex for U-Boot's very limited needs to me. As far as I can see we basically have a static setup for most devices, the ones where we actually change the parent clocks are only clock consumers, namely DE/TCON and MMC. The former chooses a parent once, based on the calculated clock rate. Only for MMC we switch it from OSC24 (for the initial SPI-like setup phase) to
PLL_PERIPH0at runtime. But however this does not really affect the tree, and also we never do re-parenting.
Under this premises, can't we do this somewhat simpler? At the end of the day this is U-Boot, not a sophisticated kernel, and we got away with quite simple clock code so far.
Yes, Idea is to go with limited clock setups but the thing is as you know Allwinner deals numerous number of clock attributes and I found it difficult to handle them w/o traversing the re-parenting stuff. I have tried simple version of set_rate in previous version[2] but it wouldn't ended as we desired. These operations need re-parenting, so we have to handle parents in clock attributes.
So finally I came up with tree structure.
My idea here is to support get and set rate with minimal re-parenting like OSC24, PLL_PERIPH0, PLL_PERIPH1 not adding much code like Linux does. Like GATE macro, TREE macro is also a readable structure with all possible/needed clk attributes at one glance. The code that handle these tree attributes may look confusing, but it is obvious because it would need to handle re-parenting.
If SoC has a big CLK architecture like this and to support all or needed clock operations, re-parenting may be one of painful code for SoC driver in U-Boot, Since CLK framework doesn't handle these generically(may be no need) as compared to Linux. and the existing SoC like mediatek clock code does the same.
At, this point, I think this tree approach can be possible way to move since it handle all clock attribute types and yes we can only support clock re-parenting which are required for U-Boot.
Quoted 4 lines
Meanwhile I am struggling to understand your approach, which looks impressive on the first glance, but leave me scratching my head when looking at details. I will comment on 15/26 for the parts I am wondering about. I was trying to add MMC support and hit some issues.
As I said above there is no generic way to handle re-parenting in U-Boot, and we need to traverse based on the SoC Clock architecture.
15/26 handling get_rate, say for example UART request a get_rate.
|==> OSC_32K
UART-->APB2--->|==> OSC_24M
|==> PLL_PH0 ===> OSC_24M
|==> PLL_PH0Each clock tree, has clock type so UART is marked as MISC since it can't not usual clock tree unlike MMC. MMC can be MP clock type and so..on
So, if driver requesting get_rate with UART clock, then we need to traverse all the UART clock tree and get the rate based on the type and identified parent clock. UART is MISC so it can directly trigger parent clock abp2, apb2 need to find the parent using mux shift, width, once apb2 found the parent it will go to next as so on.
Quoted 4 lines
On the SPI part:
I am bit puzzled about the last 5 patches dealing with SPI. I see that they depend on the others, but would like to deal with them separately.
True, but these are previous version changes ie reason I grouped it here. anyway will handle accordingly in next versions.
Quoted 5 lines
First, patch 25/26 (the sun6i SPI driver) is a bit surprising to find in here. I guess you want to have an easy user for another clock, but I believe this should be a separate series. There were other posts already for a sun6i driver, also I think we should have a unified driver instead of duplicating most of it again. See Oskari's latest post.
Yes, I saw this sun6i driver is lasting for many releases and my plan it to unified the driver w/o any ifdef.
Quoted 10 lines
Secondly: I don't think the SPI clocks are correct. You model them as simple gates only, kind of ignoring the divider settings. This is what the current sun4i driver does as well, but: it writes 1U << 31 into the clock register, which explicitly writes 0 to the other bits, setting 24 MHz as the input rate. Your approach would read-modify-write the register, just setting bit 31 and leaving the other ones as they were before.
So why isn't that using your new tree approach? Looks like a standard mux/divider clock to me.
Yes these yet to implement, ie reason I have just added clk tree only on A64. Idea is to send next version for full support on all SoC types.
v5 cover clk: Add Allwinner CLK, RESET support
Quoted 51 lines · Jagan Teki
Quoted 26 lines · André Przywara
On 31/12/2018 16:59, Jagan Teki wrote:
Hi Jagan,
many thanks for picking this up, I was about to come back to this myself. I am looking at the pinctrl part at the moment, so good you are working on the clocks!
TL;DR: I am good with the first patches, but would like to drop the last five 5 patches from this series, and discuss the whole tree approach (or at least the patch) further.
Quoted 5 lines
Although the previous version[1] is properly handled the clock gates with enable and disable management, but this series is trying to add some more complex Allwinner CLK architecture by handling parent clock and other CLK attributes.
Quoted 7 lines
Allwinner Clock control unit comprises of parent clocks, gates, multiplexers, dividers, multipliers, pre/post dividers and flags etc.
So, the U-Boot implementation of ccu has divided into gates and tree. gates are generic clock configuration of enable/disable bit management and these can be handled via
ccu_clock_gate, which is almost same as previous version changes.Quoted 4 lines
So I like this part very much, all those gates and resets are nicely readable.
Also the removal of the special sunxi USB drivers is very welcome. So up until patch including 21/26, except 15/26, I am all in.Yes my plan is to do the same.
Quoted 5 lines
Quoted 4 lines
Tree clock has more Allwinner CLK attributes like clock type, fixed clocks, misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be managed via
ccu_clock_tree.Quoted 11 lines
Mmmh, this looks quite complex for U-Boot's very limited needs to me. As far as I can see we basically have a static setup for most devices, the ones where we actually change the parent clocks are only clock consumers, namely DE/TCON and MMC. The former chooses a parent once, based on the calculated clock rate. Only for MMC we switch it from OSC24 (for the initial SPI-like setup phase) to
PLL_PERIPH0at runtime. But however this does not really affect the tree, and also we never do re-parenting.
Under this premises, can't we do this somewhat simpler? At the end of the day this is U-Boot, not a sophisticated kernel, and we got away with quite simple clock code so far.
Quoted 6 lines
Yes, Idea is to go with limited clock setups but the thing is as you know Allwinner deals numerous number of clock attributes and I found it difficult to handle them w/o traversing the re-parenting stuff. I have tried simple version of
set_ratein previous version[2] but it wouldn't ended as we desired. These operations need re-parenting, so we have to handle parents in clock attributes.
Just for clarification: with re-parenting I meant selecting a different parent clock *at runtime*, potentially adjusting other clocks which depend on that. We would not need that in U-Boot, fortunately.
Quoted 1 line
So finally I came up with tree structure.
Yeah, so looking at patch 15/26 in more detail this is probably the way to go. I was just hit by that wall of code. Implementing get_rate in a recursive fashion reduces the file size drastically, see the reply to that patch.
I was just concerned that making this all data structure based (as opposed to handle them all in a giant switch/case) would require to abstract this too much, up to a point where it gets more complicated. Especially when it comes to special clocks like the MMC beast with its new clock mode.
Quoted 13 lines
My idea here is to support get and set rate with minimal re-parenting like OSC24,
PLL_PERIPH0,PLL_PERIPH1not adding much code like Linux does. Like GATE macro, TREE macro is also a readable structure with all possible/needed clk attributes at one glance. The code that handle these tree attributes may look confusing, but it is obvious because it would need to handle re-parenting.If SoC has a big CLK architecture like this and to support all or needed clock operations, re-parenting may be one of painful code for SoC driver in U-Boot, Since CLK framework doesn't handle these generically(may be no need) as compared to Linux. and the existing SoC like mediatek clock code does the same.
Quoted 3 lines
At, this point, I think this tree approach can be possible way to move since it handle all clock attribute types and yes we can only support clock re-parenting which are required for U-Boot.
Yeah, so we need to traverse a clock tree to get and set the parent rate. I think with the recursive rework this is now quite neat, especially as we can keep the per-SoC code small.
We just have to see how the special clocks blend in there.
Quoted 20 lines
Quoted 4 lines
Meanwhile I am struggling to understand your approach, which looks impressive on the first glance, but leave me scratching my head when looking at details. I will comment on 15/26 for the parts I am wondering about. I was trying to add MMC support and hit some issues.
As I said above there is no generic way to handle re-parenting in U-Boot, and we need to traverse based on the SoC Clock architecture.
15/26 handling
get_rate, say for example UART request aget_rate.|==> OSC_32K UART-->APB2--->|==> OSC_24M |==> PLL_PH0 ===> OSC_24M |==> PLL_PH0Each clock tree, has clock type so UART is marked as MISC since it can't not usual clock tree unlike MMC. MMC can be MP clock type and so..on
Quoted 5 lines
So, if driver requesting
get_ratewith UART clock, then we need to traverse all the UART clock tree and get the rate based on the type and identified parent clock. UART is MISC so it can directly trigger parent clock abp2, apb2 need to find the parent using mux shift, width, once apb2 found the parent it will go to next as so on.
Yeah, I understand this, but was hoping we could handle this in a switch/case, for clarity. Those macro designs look nice, but are hard to understand for outsiders.
But I now think that your data driven approach is better to support multiple SoCs. I can write up some documentation for this.
Quoted 7 lines
Quoted 3 lines
On the SPI part:
I am bit puzzled about the last 5 patches dealing with SPI. I see that they depend on the others, but would like to deal with them separately.True, but these are previous version changes ie reason I grouped it here. anyway will handle accordingly in next versions.
Quoted 8 lines
Quoted 5 lines
First, patch 25/26 (the sun6i SPI driver) is a bit surprising to find in here. I guess you want to have an easy user for another clock, but I believe this should be a separate series. There were other posts already for a sun6i driver, also I think we should have a unified driver instead of duplicating most of it again. See Oskari's latest post.
Yes, I saw this sun6i driver is lasting for many releases and my plan it to unified the driver w/o any ifdef.
So I did this, basically by introducing a register map for both versions. That works, but is not very nice. Oskari's patch has the advantage of being quite small, and we will probably never need to support both SPI devices in one build.
Quoted 10 lines
Quoted 9 lines
Secondly: I don't think the SPI clocks are correct. You model them as simple gates only, kind of ignoring the divider settings. This is what the current sun4i driver does as well, but: it writes 1U << 31 into the clock register, which explicitly writes 0 to the other bits, setting 24 MHz as the input rate. Your approach would read-modify-write the register, just setting bit 31 and leaving the other ones as they were before.
So why isn't that using your new tree approach? Looks like a standard mux/divider clock to me.
Quoted 3 lines
Yes these yet to implement, ie reason I have just added clk tree only on A64. Idea is to send next version for full support on all SoC types.
Do we need to merge this for all SoCs in the beginning? I think it would be safer to test this on one SoC (A64) first, to avoid breaking everyone in case of problems. Especially if we can't test this on every board.
Cheers,
Andre.