[U-Boot] [PATCH 0/4] Meson clock driver

Hi,
this is a basic clock driver for u-boot that supports enabling/disabling clock gates and getting their frequency. With this, some hardcoded initializations can be removed from the board code, and drivers can use the information from device tree to initialize clocks.
Beniamino Galvani (4): ARM: dts: update gxbb-clkc.h from Linux 4.14 ARM: meson: add clock measurement function clk: add Amlogic meson clock driver meson: use the clock driver
arch/arm/include/asm/arch-meson/clock.h | 34 ++++++ arch/arm/include/asm/arch-meson/gxbb.h | 10 -- arch/arm/include/asm/arch-meson/i2c.h | 11 -- arch/arm/mach-meson/Kconfig | 2 + arch/arm/mach-meson/Makefile | 2 +- arch/arm/mach-meson/clock.c | 45 ++++++++ board/amlogic/odroid-c2/odroid-c2.c | 4 +- board/amlogic/p212/p212.c | 3 +- drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++ drivers/i2c/meson_i2c.c | 20 +++- include/dt-bindings/clock/gxbb-clkc.h | 75 ++++++++++++ 12 files changed, 373 insertions(+), 30 deletions(-) create mode 100644 arch/arm/include/asm/arch-meson/clock.h delete mode 100644 arch/arm/include/asm/arch-meson/i2c.h create mode 100644 arch/arm/mach-meson/clock.c create mode 100644 drivers/clk/clk_meson.c

Update gxbb-clkc.h from Linux 4.14 as it contains new clock ids.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com --- include/dt-bindings/clock/gxbb-clkc.h | 75 +++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+)
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index e3e9f7919c..8ba99a5e3f 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * GXBB clock tree IDs */ @@ -5,37 +6,96 @@ #ifndef __GXBB_CLKC_H #define __GXBB_CLKC_H
+#define CLKID_SYS_PLL 0 #define CLKID_HDMI_PLL 2 +#define CLKID_FIXED_PLL 3 #define CLKID_FCLK_DIV2 4 #define CLKID_FCLK_DIV3 5 #define CLKID_FCLK_DIV4 6 +#define CLKID_FCLK_DIV5 7 +#define CLKID_FCLK_DIV7 8 #define CLKID_GP0_PLL 9 #define CLKID_CLK81 12 +#define CLKID_MPLL0 13 +#define CLKID_MPLL1 14 #define CLKID_MPLL2 15 +#define CLKID_DDR 16 +#define CLKID_DOS 17 +#define CLKID_ISA 18 +#define CLKID_PL301 19 +#define CLKID_PERIPHS 20 #define CLKID_SPICC 21 #define CLKID_I2C 22 #define CLKID_SAR_ADC 23 +#define CLKID_SMART_CARD 24 #define CLKID_RNG0 25 #define CLKID_UART0 26 +#define CLKID_SDHC 27 +#define CLKID_STREAM 28 +#define CLKID_ASYNC_FIFO 29 +#define CLKID_SDIO 30 +#define CLKID_ABUF 31 +#define CLKID_HIU_IFACE 32 +#define CLKID_ASSIST_MISC 33 #define CLKID_SPI 34 #define CLKID_ETH 36 +#define CLKID_I2S_SPDIF 35 +#define CLKID_DEMUX 37 #define CLKID_AIU_GLUE 38 #define CLKID_IEC958 39 #define CLKID_I2S_OUT 40 +#define CLKID_AMCLK 41 +#define CLKID_AIFIFO2 42 +#define CLKID_MIXER 43 #define CLKID_MIXER_IFACE 44 +#define CLKID_ADC 45 +#define CLKID_BLKMV 46 #define CLKID_AIU 47 #define CLKID_UART1 48 +#define CLKID_G2D 49 #define CLKID_USB0 50 #define CLKID_USB1 51 +#define CLKID_RESET 52 +#define CLKID_NAND 53 +#define CLKID_DOS_PARSER 54 #define CLKID_USB 55 +#define CLKID_VDIN1 56 +#define CLKID_AHB_ARB0 57 +#define CLKID_EFUSE 58 +#define CLKID_BOOT_ROM 59 +#define CLKID_AHB_DATA_BUS 60 +#define CLKID_AHB_CTRL_BUS 61 +#define CLKID_HDMI_INTR_SYNC 62 #define CLKID_HDMI_PCLK 63 #define CLKID_USB1_DDR_BRIDGE 64 #define CLKID_USB0_DDR_BRIDGE 65 +#define CLKID_MMC_PCLK 66 +#define CLKID_DVIN 67 #define CLKID_UART2 68 #define CLKID_SANA 69 +#define CLKID_VPU_INTR 70 +#define CLKID_SEC_AHB_AHB3_BRIDGE 71 +#define CLKID_CLK81_A53 72 +#define CLKID_VCLK2_VENCI0 73 +#define CLKID_VCLK2_VENCI1 74 +#define CLKID_VCLK2_VENCP0 75 +#define CLKID_VCLK2_VENCP1 76 #define CLKID_GCLK_VENCI_INT0 77 +#define CLKID_GCLK_VENCI_INT 78 +#define CLKID_DAC_CLK 79 #define CLKID_AOCLK_GATE 80 #define CLKID_IEC958_GATE 81 +#define CLKID_ENC480P 82 +#define CLKID_RNG1 83 +#define CLKID_GCLK_VENCI_INT1 84 +#define CLKID_VCLK2_VENCLMCC 85 +#define CLKID_VCLK2_VENCL 86 +#define CLKID_VCLK_OTHER 87 +#define CLKID_EDP 88 +#define CLKID_AO_MEDIA_CPU 89 +#define CLKID_AO_AHB_SRAM 90 +#define CLKID_AO_AHB_BUS 91 +#define CLKID_AO_IFACE 92 #define CLKID_AO_I2C 93 #define CLKID_SD_EMMC_A 94 #define CLKID_SD_EMMC_B 95 @@ -50,5 +110,20 @@ #define CLKID_CTS_AMCLK 107 #define CLKID_CTS_MCLK_I958 110 #define CLKID_CTS_I958 113 +#define CLKID_32K_CLK 114 +#define CLKID_SD_EMMC_A_CLK0 119 +#define CLKID_SD_EMMC_B_CLK0 122 +#define CLKID_SD_EMMC_C_CLK0 125 +#define CLKID_VPU_0_SEL 126 +#define CLKID_VPU_0 128 +#define CLKID_VPU_1_SEL 129 +#define CLKID_VPU_1 131 +#define CLKID_VPU 132 +#define CLKID_VAPB_0_SEL 133 +#define CLKID_VAPB_0 135 +#define CLKID_VAPB_1_SEL 136 +#define CLKID_VAPB_1 138 +#define CLKID_VAPB_SEL 139 +#define CLKID_VAPB 140
#endif /* __GXBB_CLKC_H */

On 03/12/2017 10:17, Beniamino Galvani wrote:
Update gxbb-clkc.h from Linux 4.14 as it contains new clock ids.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
include/dt-bindings/clock/gxbb-clkc.h | 75 +++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+)
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index e3e9f7919c..8ba99a5e3f 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*
- GXBB clock tree IDs
*/ @@ -5,37 +6,96 @@ #ifndef __GXBB_CLKC_H #define __GXBB_CLKC_H
+#define CLKID_SYS_PLL 0 #define CLKID_HDMI_PLL 2 +#define CLKID_FIXED_PLL 3 #define CLKID_FCLK_DIV2 4 #define CLKID_FCLK_DIV3 5 #define CLKID_FCLK_DIV4 6 +#define CLKID_FCLK_DIV5 7 +#define CLKID_FCLK_DIV7 8 #define CLKID_GP0_PLL 9 #define CLKID_CLK81 12 +#define CLKID_MPLL0 13 +#define CLKID_MPLL1 14 #define CLKID_MPLL2 15 +#define CLKID_DDR 16 +#define CLKID_DOS 17 +#define CLKID_ISA 18 +#define CLKID_PL301 19 +#define CLKID_PERIPHS 20 #define CLKID_SPICC 21 #define CLKID_I2C 22 #define CLKID_SAR_ADC 23 +#define CLKID_SMART_CARD 24 #define CLKID_RNG0 25 #define CLKID_UART0 26 +#define CLKID_SDHC 27 +#define CLKID_STREAM 28 +#define CLKID_ASYNC_FIFO 29 +#define CLKID_SDIO 30 +#define CLKID_ABUF 31 +#define CLKID_HIU_IFACE 32 +#define CLKID_ASSIST_MISC 33 #define CLKID_SPI 34 #define CLKID_ETH 36 +#define CLKID_I2S_SPDIF 35 +#define CLKID_DEMUX 37 #define CLKID_AIU_GLUE 38 #define CLKID_IEC958 39 #define CLKID_I2S_OUT 40 +#define CLKID_AMCLK 41 +#define CLKID_AIFIFO2 42 +#define CLKID_MIXER 43 #define CLKID_MIXER_IFACE 44 +#define CLKID_ADC 45 +#define CLKID_BLKMV 46 #define CLKID_AIU 47 #define CLKID_UART1 48 +#define CLKID_G2D 49 #define CLKID_USB0 50 #define CLKID_USB1 51 +#define CLKID_RESET 52 +#define CLKID_NAND 53 +#define CLKID_DOS_PARSER 54 #define CLKID_USB 55 +#define CLKID_VDIN1 56 +#define CLKID_AHB_ARB0 57 +#define CLKID_EFUSE 58 +#define CLKID_BOOT_ROM 59 +#define CLKID_AHB_DATA_BUS 60 +#define CLKID_AHB_CTRL_BUS 61 +#define CLKID_HDMI_INTR_SYNC 62 #define CLKID_HDMI_PCLK 63 #define CLKID_USB1_DDR_BRIDGE 64 #define CLKID_USB0_DDR_BRIDGE 65 +#define CLKID_MMC_PCLK 66 +#define CLKID_DVIN 67 #define CLKID_UART2 68 #define CLKID_SANA 69 +#define CLKID_VPU_INTR 70 +#define CLKID_SEC_AHB_AHB3_BRIDGE 71 +#define CLKID_CLK81_A53 72 +#define CLKID_VCLK2_VENCI0 73 +#define CLKID_VCLK2_VENCI1 74 +#define CLKID_VCLK2_VENCP0 75 +#define CLKID_VCLK2_VENCP1 76 #define CLKID_GCLK_VENCI_INT0 77 +#define CLKID_GCLK_VENCI_INT 78 +#define CLKID_DAC_CLK 79 #define CLKID_AOCLK_GATE 80 #define CLKID_IEC958_GATE 81 +#define CLKID_ENC480P 82 +#define CLKID_RNG1 83 +#define CLKID_GCLK_VENCI_INT1 84 +#define CLKID_VCLK2_VENCLMCC 85 +#define CLKID_VCLK2_VENCL 86 +#define CLKID_VCLK_OTHER 87 +#define CLKID_EDP 88 +#define CLKID_AO_MEDIA_CPU 89 +#define CLKID_AO_AHB_SRAM 90 +#define CLKID_AO_AHB_BUS 91 +#define CLKID_AO_IFACE 92 #define CLKID_AO_I2C 93 #define CLKID_SD_EMMC_A 94 #define CLKID_SD_EMMC_B 95 @@ -50,5 +110,20 @@ #define CLKID_CTS_AMCLK 107 #define CLKID_CTS_MCLK_I958 110 #define CLKID_CTS_I958 113 +#define CLKID_32K_CLK 114 +#define CLKID_SD_EMMC_A_CLK0 119 +#define CLKID_SD_EMMC_B_CLK0 122 +#define CLKID_SD_EMMC_C_CLK0 125 +#define CLKID_VPU_0_SEL 126 +#define CLKID_VPU_0 128 +#define CLKID_VPU_1_SEL 129 +#define CLKID_VPU_1 131 +#define CLKID_VPU 132 +#define CLKID_VAPB_0_SEL 133 +#define CLKID_VAPB_0 135 +#define CLKID_VAPB_1_SEL 136 +#define CLKID_VAPB_1 138 +#define CLKID_VAPB_SEL 139 +#define CLKID_VAPB 140
#endif /* __GXBB_CLKC_H */
Reviewed-by: Neil Armstrong narmstrong@baylibre.com

Add add a function to measure the current clock rate.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com --- arch/arm/include/asm/arch-meson/clock.h | 34 +++++++++++++++++++++++++ arch/arm/mach-meson/Makefile | 2 +- arch/arm/mach-meson/clock.c | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-meson/clock.h create mode 100644 arch/arm/mach-meson/clock.c
diff --git a/arch/arm/include/asm/arch-meson/clock.h b/arch/arm/include/asm/arch-meson/clock.h new file mode 100644 index 0000000000..b43b23386c --- /dev/null +++ b/arch/arm/include/asm/arch-meson/clock.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 - Beniamino Galvani b.galvani@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _MESON_CLOCK_H_ +#define _MESON_CLOCK_H_ + +/* CBUS clock measure registers */ +#define MSR_CLK_DUTY 0xc1108758 +#define MSR_CLK_REG0 0xc110875c +#define MSR_CLK_REG1 0xc1108760 +#define MSR_CLK_REG2 0xc1108764 + +#define CLK_GP0_PLL 4 +#define CLK_GP1_PLL 5 +#define CLK_81 7 +#define CLK_MMC 23 +#define CLK_MOD_ETH_TX 40 +#define CLK_MOD_ETH_RX_RMII 41 +#define CLK_FCLK_DIV5 43 +#define CLK_SD_EMMC_CLK_C 51 +#define CLK_SD_EMMC_CLK_B 52 + +/* Clock gates */ +#define HHI_GCLK_MPEG0 0x140 +#define HHI_GCLK_MPEG1 0x144 +#define HHI_GCLK_MPEG2 0x148 +#define HHI_GCLK_OTHER 0x150 +#define HHI_GCLK_AO 0x154 + +ulong meson_measure_clk_rate(unsigned int clk); + +#endif diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile index bf49b8b1e5..e7ea4fc5b0 100644 --- a/arch/arm/mach-meson/Makefile +++ b/arch/arm/mach-meson/Makefile @@ -4,4 +4,4 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y += board.o sm.o +obj-y += board.o clock.o sm.o diff --git a/arch/arm/mach-meson/clock.c b/arch/arm/mach-meson/clock.c new file mode 100644 index 0000000000..73be11e90d --- /dev/null +++ b/arch/arm/mach-meson/clock.c @@ -0,0 +1,45 @@ +/* + * (C) Copyright 2016 Beniamino Galvani b.galvani@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Clock rate measuring. + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h> + +ulong meson_measure_clk_rate(unsigned int clk) +{ + ulong start; + ulong mhz; + + writel(0, MSR_CLK_REG0); + + /* Set the measurement gate to 64uS */ + clrsetbits_le32(MSR_CLK_REG0, 0xffff, 64 - 1); + clrbits_le32(MSR_CLK_REG0, + BIT(17) | /* disable continuous measurement */ + BIT(18)); /* disable interrupts */ + clrsetbits_le32(MSR_CLK_REG0, + GENMASK(20, 26), + clk << 20); /* select the clock */ + setbits_le32(MSR_CLK_REG0, + BIT(19) | /* enable the clock */ + BIT(16)); /* enable measuring */ + + start = get_timer(0); + while (readl(MSR_CLK_REG0) & BIT(31)) { + if (get_timer(start) > 100) { + debug("could not measure clk %u rate\n", clk); + return -ETIMEDOUT; + } + } + + /* Disable measuring */ + clrbits_le32(MSR_CLK_REG0, BIT(16)); + + mhz = ((readl(MSR_CLK_REG2) + 31) & 0xfffff) >> 6; + return mhz * 1000000; +}

On 03/12/2017 10:17, Beniamino Galvani wrote:
Add add a function to measure the current clock rate.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/include/asm/arch-meson/clock.h | 34 +++++++++++++++++++++++++ arch/arm/mach-meson/Makefile | 2 +- arch/arm/mach-meson/clock.c | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-meson/clock.h create mode 100644 arch/arm/mach-meson/clock.c
diff --git a/arch/arm/include/asm/arch-meson/clock.h b/arch/arm/include/asm/arch-meson/clock.h new file mode 100644 index 0000000000..b43b23386c --- /dev/null +++ b/arch/arm/include/asm/arch-meson/clock.h @@ -0,0 +1,34 @@ +/*
- Copyright 2017 - Beniamino Galvani b.galvani@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _MESON_CLOCK_H_ +#define _MESON_CLOCK_H_
+/* CBUS clock measure registers */ +#define MSR_CLK_DUTY 0xc1108758 +#define MSR_CLK_REG0 0xc110875c +#define MSR_CLK_REG1 0xc1108760 +#define MSR_CLK_REG2 0xc1108764
+#define CLK_GP0_PLL 4 +#define CLK_GP1_PLL 5 +#define CLK_81 7 +#define CLK_MMC 23 +#define CLK_MOD_ETH_TX 40 +#define CLK_MOD_ETH_RX_RMII 41 +#define CLK_FCLK_DIV5 43 +#define CLK_SD_EMMC_CLK_C 51 +#define CLK_SD_EMMC_CLK_B 52
+/* Clock gates */ +#define HHI_GCLK_MPEG0 0x140 +#define HHI_GCLK_MPEG1 0x144 +#define HHI_GCLK_MPEG2 0x148 +#define HHI_GCLK_OTHER 0x150 +#define HHI_GCLK_AO 0x154
+ulong meson_measure_clk_rate(unsigned int clk);
+#endif diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile index bf49b8b1e5..e7ea4fc5b0 100644 --- a/arch/arm/mach-meson/Makefile +++ b/arch/arm/mach-meson/Makefile @@ -4,4 +4,4 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y += board.o sm.o +obj-y += board.o clock.o sm.o diff --git a/arch/arm/mach-meson/clock.c b/arch/arm/mach-meson/clock.c new file mode 100644 index 0000000000..73be11e90d --- /dev/null +++ b/arch/arm/mach-meson/clock.c @@ -0,0 +1,45 @@ +/*
- (C) Copyright 2016 Beniamino Galvani b.galvani@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- Clock rate measuring.
- */
+#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h>
+ulong meson_measure_clk_rate(unsigned int clk) +{
- ulong start;
- ulong mhz;
- writel(0, MSR_CLK_REG0);
- /* Set the measurement gate to 64uS */
- clrsetbits_le32(MSR_CLK_REG0, 0xffff, 64 - 1);
- clrbits_le32(MSR_CLK_REG0,
BIT(17) | /* disable continuous measurement */
BIT(18)); /* disable interrupts */
You can maybe document these bits somehow.
- clrsetbits_le32(MSR_CLK_REG0,
GENMASK(20, 26),
clk << 20); /* select the clock */
- setbits_le32(MSR_CLK_REG0,
BIT(19) | /* enable the clock */
BIT(16)); /* enable measuring */
Same here.
- start = get_timer(0);
- while (readl(MSR_CLK_REG0) & BIT(31)) {
if (get_timer(start) > 100) {
debug("could not measure clk %u rate\n", clk);
return -ETIMEDOUT;
}
- }
- /* Disable measuring */
- clrbits_le32(MSR_CLK_REG0, BIT(16));
- mhz = ((readl(MSR_CLK_REG2) + 31) & 0xfffff) >> 6;
- return mhz * 1000000;
+}
I'm skeptical about this, but it simplifies a lot the clock driver !
Anyway, it can be changed later if we want to control the PLLs and so on.
Reviewed-by: Neil Armstrong narmstrong@baylibre.com

Hi Benjamin,
On 3 December 2017 at 02:17, Beniamino Galvani b.galvani@gmail.com wrote:
Add add a function to measure the current clock rate.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/include/asm/arch-meson/clock.h | 34 +++++++++++++++++++++++++ arch/arm/mach-meson/Makefile | 2 +- arch/arm/mach-meson/clock.c | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-meson/clock.h create mode 100644 arch/arm/mach-meson/clock.c
diff --git a/arch/arm/include/asm/arch-meson/clock.h b/arch/arm/include/asm/arch-meson/clock.h new file mode 100644 index 0000000000..b43b23386c --- /dev/null +++ b/arch/arm/include/asm/arch-meson/clock.h @@ -0,0 +1,34 @@ +/*
- Copyright 2017 - Beniamino Galvani b.galvani@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _MESON_CLOCK_H_ +#define _MESON_CLOCK_H_
+/* CBUS clock measure registers */ +#define MSR_CLK_DUTY 0xc1108758 +#define MSR_CLK_REG0 0xc110875c +#define MSR_CLK_REG1 0xc1108760 +#define MSR_CLK_REG2 0xc1108764
+#define CLK_GP0_PLL 4 +#define CLK_GP1_PLL 5 +#define CLK_81 7 +#define CLK_MMC 23 +#define CLK_MOD_ETH_TX 40 +#define CLK_MOD_ETH_RX_RMII 41 +#define CLK_FCLK_DIV5 43 +#define CLK_SD_EMMC_CLK_C 51 +#define CLK_SD_EMMC_CLK_B 52
Are these constants in the dt-binding file somewhere?
+/* Clock gates */ +#define HHI_GCLK_MPEG0 0x140 +#define HHI_GCLK_MPEG1 0x144 +#define HHI_GCLK_MPEG2 0x148 +#define HHI_GCLK_OTHER 0x150 +#define HHI_GCLK_AO 0x154
+ulong meson_measure_clk_rate(unsigned int clk);
Please can you add a function comment and mention error-return values also?
+#endif diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile index bf49b8b1e5..e7ea4fc5b0 100644 --- a/arch/arm/mach-meson/Makefile +++ b/arch/arm/mach-meson/Makefile @@ -4,4 +4,4 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y += board.o sm.o +obj-y += board.o clock.o sm.o diff --git a/arch/arm/mach-meson/clock.c b/arch/arm/mach-meson/clock.c new file mode 100644 index 0000000000..73be11e90d --- /dev/null +++ b/arch/arm/mach-meson/clock.c @@ -0,0 +1,45 @@ +/*
- (C) Copyright 2016 Beniamino Galvani b.galvani@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- Clock rate measuring.
- */
+#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h>
+ulong meson_measure_clk_rate(unsigned int clk) +{
ulong start;
ulong mhz;
writel(0, MSR_CLK_REG0);
/* Set the measurement gate to 64uS */
clrsetbits_le32(MSR_CLK_REG0, 0xffff, 64 - 1);
clrbits_le32(MSR_CLK_REG0,
BIT(17) | /* disable continuous measurement */
BIT(18)); /* disable interrupts */
clrsetbits_le32(MSR_CLK_REG0,
GENMASK(20, 26),
clk << 20); /* select the clock */
setbits_le32(MSR_CLK_REG0,
BIT(19) | /* enable the clock */
BIT(16)); /* enable measuring */
start = get_timer(0);
while (readl(MSR_CLK_REG0) & BIT(31)) {
if (get_timer(start) > 100) {
How long does this take to measure? Is it up to 100ms?
debug("could not measure clk %u rate\n", clk);
return -ETIMEDOUT;
}
}
/* Disable measuring */
clrbits_le32(MSR_CLK_REG0, BIT(16));
mhz = ((readl(MSR_CLK_REG2) + 31) & 0xfffff) >> 6;
return mhz * 1000000;
+}
2.14.3
Regards, Simon

Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com --- arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index d4bd230be3..7acee3bc5c 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -3,6 +3,7 @@ if ARCH_MESON config MESON_GXBB bool "Support Meson GXBaby" select ARM64 + select CLK select DM select DM_SERIAL help @@ -12,6 +13,7 @@ config MESON_GXBB config MESON_GXL bool "Support Meson GXL" select ARM64 + select CLK select DM select DM_SERIAL help diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index bcc8f82fb6..67da27873d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -7,6 +7,7 @@
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ +obj-$(CONFIG_ARCH_MESON) += clk_meson.o obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o obj-$(CONFIG_MACH_PIC32) += clk_pic32.o diff --git a/drivers/clk/clk_meson.c b/drivers/clk/clk_meson.c new file mode 100644 index 0000000000..3cf9372e05 --- /dev/null +++ b/drivers/clk/clk_meson.c @@ -0,0 +1,196 @@ +/* + * (C) Copyright 2017 - Beniamino Galvani b.galvani@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dt-bindings/clock/gxbb-clkc.h> + +struct meson_clk { + void __iomem *addr; + ulong rate; +}; + +struct meson_gate { + unsigned int reg; + unsigned int bit; +}; + +#define MESON_GATE(id, _reg, _bit) \ + [id] = { \ + .reg = (_reg), \ + .bit = (_bit), \ + } + +struct meson_gate gates[] = { + /* Everything Else (EE) domain gates */ + MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0), + MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1), + MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5), + MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6), + MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7), + MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8), + MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9), + MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10), + MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11), + MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12), + MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13), + MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14), + MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15), + MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16), + MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17), + MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18), + MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19), + MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23), + MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24), + MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25), + MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26), + MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30), + + MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2), + MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3), + MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4), + MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6), + MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7), + MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8), + MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9), + MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10), + MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11), + MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12), + MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13), + MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14), + MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15), + MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16), + MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20), + MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21), + MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22), + MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23), + MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24), + MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25), + MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26), + MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28), + MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29), + MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30), + MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31), + + MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1), + MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2), + MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3), + MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4), + MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8), + MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9), + MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11), + MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12), + MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15), + MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22), + MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25), + MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26), + MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29), + + MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1), + MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2), + MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3), + MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4), + MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8), + MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10), + MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14), + MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16), + MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20), + MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21), + MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22), + MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24), + MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25), + MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26), + MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31), + + /* Always On (AO) domain gates */ + MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0), + MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1), + MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2), + MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3), + MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4), +}; + +static int meson_set_gate(struct clk *clk, bool on) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + struct meson_gate *gate; + + if (clk->id >= ARRAY_SIZE(gates)) + return -ENOENT; + + gate = &gates[clk->id]; + + if (gate->reg == 0) + return -ENOENT; + + clrsetbits_le32(priv->addr + gate->reg, + BIT(gate->bit), on ? BIT(gate->bit) : 0); + return 0; +} + +static int meson_clk_enable(struct clk *clk) +{ + return meson_set_gate(clk, true); +} + +static int meson_clk_disable(struct clk *clk) +{ + return meson_set_gate(clk, false); +} + +static ulong meson_clk_get_rate(struct clk *clk) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + + if (clk->id != CLKID_CLK81) { + if (clk->id >= ARRAY_SIZE(gates)) + return -ENOENT; + if (gates[clk->id].reg == 0) + return -ENOENT; + } + + /* Use cached value if available */ + if (priv->rate) + return priv->rate; + + priv->rate = meson_measure_clk_rate(CLK_81); + + return priv->rate; +} + +static int meson_clk_probe(struct udevice *dev) +{ + struct meson_clk *priv = dev_get_priv(dev); + + priv->addr = dev_read_addr_ptr(dev); + debug("meson-clk: probed at addr %p\n", priv->addr); + + return 0; +} + +static struct clk_ops meson_clk_ops = { + .disable = meson_clk_disable, + .enable = meson_clk_enable, + .get_rate = meson_clk_get_rate, +}; + +static const struct udevice_id meson_clk_ids[] = { + { .compatible = "amlogic,gxbb-clkc" }, + { .compatible = "amlogic,gxl-clkc" }, + { } +}; + +U_BOOT_DRIVER(meson_clk) = { + .name = "meson_clk", + .id = UCLASS_CLK, + .of_match = meson_clk_ids, + .priv_auto_alloc_size = sizeof(struct meson_clk), + .ops = &meson_clk_ops, + .probe = meson_clk_probe, +};

On 03/12/2017 10:17, Beniamino Galvani wrote:
Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index d4bd230be3..7acee3bc5c 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -3,6 +3,7 @@ if ARCH_MESON config MESON_GXBB bool "Support Meson GXBaby" select ARM64
- select CLK select DM select DM_SERIAL help
@@ -12,6 +13,7 @@ config MESON_GXBB config MESON_GXL bool "Support Meson GXL" select ARM64
- select CLK select DM select DM_SERIAL help
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index bcc8f82fb6..67da27873d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -7,6 +7,7 @@
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ +obj-$(CONFIG_ARCH_MESON) += clk_meson.o obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o obj-$(CONFIG_MACH_PIC32) += clk_pic32.o diff --git a/drivers/clk/clk_meson.c b/drivers/clk/clk_meson.c new file mode 100644 index 0000000000..3cf9372e05 --- /dev/null +++ b/drivers/clk/clk_meson.c @@ -0,0 +1,196 @@ +/*
- (C) Copyright 2017 - Beniamino Galvani b.galvani@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dt-bindings/clock/gxbb-clkc.h>
+struct meson_clk {
- void __iomem *addr;
- ulong rate;
+};
+struct meson_gate {
- unsigned int reg;
- unsigned int bit;
+};
+#define MESON_GATE(id, _reg, _bit) \
- [id] = { \
.reg = (_reg), \
.bit = (_bit), \
- }
+struct meson_gate gates[] = {
- /* Everything Else (EE) domain gates */
- MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0),
- MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1),
- MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5),
- MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6),
- MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7),
- MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8),
- MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9),
- MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10),
- MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11),
- MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12),
- MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13),
- MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14),
- MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15),
- MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16),
- MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17),
- MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18),
- MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19),
- MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23),
- MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24),
- MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25),
- MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26),
- MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30),
- MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2),
- MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
- MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4),
- MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6),
- MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7),
- MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8),
- MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9),
- MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10),
- MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11),
- MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12),
- MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13),
- MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14),
- MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15),
- MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
- MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20),
- MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21),
- MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22),
- MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23),
- MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24),
- MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25),
- MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26),
- MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28),
- MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29),
- MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30),
- MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31),
- MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1),
- MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2),
- MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3),
- MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4),
- MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
- MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9),
- MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11),
- MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12),
- MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15),
- MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22),
- MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
- MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26),
- MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29),
- MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1),
- MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2),
- MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3),
- MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4),
- MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8),
- MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10),
- MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14),
- MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16),
- MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20),
- MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21),
- MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22),
- MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24),
- MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25),
- MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26),
- MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31),
- /* Always On (AO) domain gates */
- MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0),
- MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1),
- MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2),
- MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3),
- MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4),
+};
+static int meson_set_gate(struct clk *clk, bool on) +{
- struct meson_clk *priv = dev_get_priv(clk->dev);
- struct meson_gate *gate;
- if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
- gate = &gates[clk->id];
- if (gate->reg == 0)
return -ENOENT;
- clrsetbits_le32(priv->addr + gate->reg,
BIT(gate->bit), on ? BIT(gate->bit) : 0);
- return 0;
+}
+static int meson_clk_enable(struct clk *clk) +{
- return meson_set_gate(clk, true);
+}
+static int meson_clk_disable(struct clk *clk) +{
- return meson_set_gate(clk, false);
+}
+static ulong meson_clk_get_rate(struct clk *clk) +{
- struct meson_clk *priv = dev_get_priv(clk->dev);
- if (clk->id != CLKID_CLK81) {
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
if (gates[clk->id].reg == 0)
return -ENOENT;
- }
- /* Use cached value if available */
- if (priv->rate)
return priv->rate;
- priv->rate = meson_measure_clk_rate(CLK_81);
- return priv->rate;
+}
+static int meson_clk_probe(struct udevice *dev) +{
- struct meson_clk *priv = dev_get_priv(dev);
- priv->addr = dev_read_addr_ptr(dev);
- debug("meson-clk: probed at addr %p\n", priv->addr);
- return 0;
+}
+static struct clk_ops meson_clk_ops = {
- .disable = meson_clk_disable,
- .enable = meson_clk_enable,
- .get_rate = meson_clk_get_rate,
+};
+static const struct udevice_id meson_clk_ids[] = {
- { .compatible = "amlogic,gxbb-clkc" },
- { .compatible = "amlogic,gxl-clkc" },
- { }
+};
+U_BOOT_DRIVER(meson_clk) = {
- .name = "meson_clk",
- .id = UCLASS_CLK,
- .of_match = meson_clk_ids,
- .priv_auto_alloc_size = sizeof(struct meson_clk),
- .ops = &meson_clk_ops,
- .probe = meson_clk_probe,
+};
Ok for now to only handle the gates with the clock measure function.
Reviewed-by: Neil Armstrong narmstrong@baylibre.com

Hi Benjamin,
On 3 December 2017 at 02:17, Beniamino Galvani b.galvani@gmail.com wrote:
Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
Reviewed-by: Simon Glass sjg@chromium.org

Hi Beniamino,
On 03/12/2017 10:17, Beniamino Galvani wrote:
Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index d4bd230be3..7acee3bc5c 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig
[...]
+static int meson_set_gate(struct clk *clk, bool on) +{
- struct meson_clk *priv = dev_get_priv(clk->dev);
- struct meson_gate *gate;
- if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
This should be -ENOSYS, otherwise it breaks the ethernet driver since it waits -ENOSYS if clock cannot be enabled.
- gate = &gates[clk->id];
- if (gate->reg == 0)
return -ENOENT;
Same here -ENOSYS
- clrsetbits_le32(priv->addr + gate->reg,
BIT(gate->bit), on ? BIT(gate->bit) : 0);
- return 0;
+}
+static int meson_clk_enable(struct clk *clk) +{
- return meson_set_gate(clk, true);
+}
+static int meson_clk_disable(struct clk *clk) +{
- return meson_set_gate(clk, false);
+}
+static ulong meson_clk_get_rate(struct clk *clk) +{
- struct meson_clk *priv = dev_get_priv(clk->dev);
- if (clk->id != CLKID_CLK81) {
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
Same here -ENOSYS
if (gates[clk->id].reg == 0)
return -ENOENT;
Same here -ENOSYS
- }
- /* Use cached value if available */
- if (priv->rate)
return priv->rate;
- priv->rate = meson_measure_clk_rate(CLK_81);
- return priv->rate;
+}
[...]
Neil

Hi Neil,
On 29 March 2018 at 16:42, Neil Armstrong narmstrong@baylibre.com wrote:
Hi Beniamino,
On 03/12/2017 10:17, Beniamino Galvani wrote:
Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index d4bd230be3..7acee3bc5c 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig
[...]
+static int meson_set_gate(struct clk *clk, bool on) +{
struct meson_clk *priv = dev_get_priv(clk->dev);
struct meson_gate *gate;
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
This should be -ENOSYS, otherwise it breaks the ethernet driver since it waits -ENOSYS if clock cannot be enabled.
Perhaps, but this is a genuine error, so it is OK to break the Ethernet driver, isn't it? We don't want errors to be silently ignored.
Not having a device is one thing, but having a device that does not work is bad.
Also I have tried to keep -ENOSYS for cases where the driver does not support the operation. We should be very clear in clk-uclass.h as to what errors are returned. At present I don't see ENOSYS mentioned. At the very least we should update the docs if certain behaviour is expected. I would also expect us to have a sandbox test for it.
gate = &gates[clk->id];
if (gate->reg == 0)
return -ENOENT;
Same here -ENOSYS
clrsetbits_le32(priv->addr + gate->reg,
BIT(gate->bit), on ? BIT(gate->bit) : 0);
return 0;
+}
+static int meson_clk_enable(struct clk *clk) +{
return meson_set_gate(clk, true);
+}
+static int meson_clk_disable(struct clk *clk) +{
return meson_set_gate(clk, false);
+}
+static ulong meson_clk_get_rate(struct clk *clk) +{
struct meson_clk *priv = dev_get_priv(clk->dev);
if (clk->id != CLKID_CLK81) {
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
Same here -ENOSYS
if (gates[clk->id].reg == 0)
return -ENOENT;
Same here -ENOSYS
}
/* Use cached value if available */
if (priv->rate)
return priv->rate;
priv->rate = meson_measure_clk_rate(CLK_81);
return priv->rate;
+}
[...]
Neil
Regards, Simon

On 30/03/2018 00:41, Simon Glass wrote:
Hi Neil,
On 29 March 2018 at 16:42, Neil Armstrong narmstrong@baylibre.com wrote:
Hi Beniamino,
On 03/12/2017 10:17, Beniamino Galvani wrote:
Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index d4bd230be3..7acee3bc5c 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig
[...]
+static int meson_set_gate(struct clk *clk, bool on) +{
struct meson_clk *priv = dev_get_priv(clk->dev);
struct meson_gate *gate;
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
This should be -ENOSYS, otherwise it breaks the ethernet driver since it waits -ENOSYS if clock cannot be enabled.
Perhaps, but this is a genuine error, so it is OK to break the Ethernet driver, isn't it? We don't want errors to be silently ignored.
Not having a device is one thing, but having a device that does not work is bad.
The driver only manages the gates, enabling and disabling them and getting their freq. The missing clocks of the ethernet driver in this case are dividers of the PLL, thus we don't need to enable them, and for now the driver don't need the freq.
Also I have tried to keep -ENOSYS for cases where the driver does not support the operation. We should be very clear in clk-uclass.h as to what errors are returned. At present I don't see ENOSYS mentioned. At the very least we should update the docs if certain behaviour is expected. I would also expect us to have a sandbox test for it.
In this case, the driver does not support the operation for these clocks, but maybe it would be better to add them with reg=0 and return -ENOSYS in the following return :
gate = &gates[clk->id];
if (gate->reg == 0)
return -ENOENT;
Same here -ENOSYS
Here thsi means it's not a gate.
clrsetbits_le32(priv->addr + gate->reg,
BIT(gate->bit), on ? BIT(gate->bit) : 0);
return 0;
+}
+static int meson_clk_enable(struct clk *clk) +{
return meson_set_gate(clk, true);
+}
+static int meson_clk_disable(struct clk *clk) +{
return meson_set_gate(clk, false);
+}
+static ulong meson_clk_get_rate(struct clk *clk) +{
struct meson_clk *priv = dev_get_priv(clk->dev);
if (clk->id != CLKID_CLK81) {
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
Same here -ENOSYS
if (gates[clk->id].reg == 0)
return -ENOENT;
Same here -ENOSYS
}
/* Use cached value if available */
if (priv->rate)
return priv->rate;
priv->rate = meson_measure_clk_rate(CLK_81);
return priv->rate;
+}
[...]
Neil
Regards, Simon

Hi Neil,
On 30 March 2018 at 15:53, Neil Armstrong narmstrong@baylibre.com wrote:
On 30/03/2018 00:41, Simon Glass wrote:
Hi Neil,
On 29 March 2018 at 16:42, Neil Armstrong narmstrong@baylibre.com wrote:
Hi Beniamino,
On 03/12/2017 10:17, Beniamino Galvani wrote:
Introduce a basic clock driver for Amlogic Meson SoCs which supports enabling/disabling clock gates and getting their frequency.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/mach-meson/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 drivers/clk/clk_meson.c
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index d4bd230be3..7acee3bc5c 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig
[...]
+static int meson_set_gate(struct clk *clk, bool on) +{
struct meson_clk *priv = dev_get_priv(clk->dev);
struct meson_gate *gate;
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
This should be -ENOSYS, otherwise it breaks the ethernet driver since it waits -ENOSYS if clock cannot be enabled.
Perhaps, but this is a genuine error, so it is OK to break the Ethernet driver, isn't it? We don't want errors to be silently ignored.
Not having a device is one thing, but having a device that does not work is bad.
The driver only manages the gates, enabling and disabling them and getting their freq. The missing clocks of the ethernet driver in this case are dividers of the PLL, thus we don't need to enable them, and for now the driver don't need the freq.
Yes but -ENOSYS means that the driver does not support the operation at all. Put it another way: you can't return -ENOSYS for some parameters and not for others.
Also I have tried to keep -ENOSYS for cases where the driver does not support the operation. We should be very clear in clk-uclass.h as to what errors are returned. At present I don't see ENOSYS mentioned. At the very least we should update the docs if certain behaviour is expected. I would also expect us to have a sandbox test for it.
In this case, the driver does not support the operation for these clocks, but maybe it would be better to add them with reg=0 and return -ENOSYS in the following return :
I don't like that - ENOENT seems better.
gate = &gates[clk->id];
if (gate->reg == 0)
return -ENOENT;
Same here -ENOSYS
Here thsi means it's not a gate.
Yes, but the driver still supports the operation. The problem is that its inputs are invalid. So use -ENOENT to mean that.
clrsetbits_le32(priv->addr + gate->reg,
BIT(gate->bit), on ? BIT(gate->bit) : 0);
return 0;
+}
+static int meson_clk_enable(struct clk *clk) +{
return meson_set_gate(clk, true);
+}
+static int meson_clk_disable(struct clk *clk) +{
return meson_set_gate(clk, false);
+}
+static ulong meson_clk_get_rate(struct clk *clk) +{
struct meson_clk *priv = dev_get_priv(clk->dev);
if (clk->id != CLKID_CLK81) {
if (clk->id >= ARRAY_SIZE(gates))
return -ENOENT;
Same here -ENOSYS
if (gates[clk->id].reg == 0)
return -ENOENT;
Same here -ENOSYS
}
/* Use cached value if available */
if (priv->rate)
return priv->rate;
priv->rate = meson_measure_clk_rate(CLK_81);
return priv->rate;
+}
[...]
Neil
Regards, Simon
Regards, Simon

Hi guys,
Am 30.03.2018 um 10:41 schrieb Simon Glass:
On 30 March 2018 at 15:53, Neil Armstrong narmstrong@baylibre.com wrote:
On 30/03/2018 00:41, Simon Glass wrote:
On 29 March 2018 at 16:42, Neil Armstrong narmstrong@baylibre.com wrote:
On 03/12/2017 10:17, Beniamino Galvani wrote:
gate = &gates[clk->id];
if (gate->reg == 0)
return -ENOENT;
Same here -ENOSYS
Here thsi means it's not a gate.
Yes, but the driver still supports the operation. The problem is that its inputs are invalid. So use -ENOENT to mean that.
Isn't that the definition of -EINVAL?
Cheers, Andreas

Hi Andreas,
On 30 March 2018 at 22:27, Andreas Färber afaerber@suse.de wrote:
Hi guys,
Am 30.03.2018 um 10:41 schrieb Simon Glass:
On 30 March 2018 at 15:53, Neil Armstrong narmstrong@baylibre.com wrote:
On 30/03/2018 00:41, Simon Glass wrote:
On 29 March 2018 at 16:42, Neil Armstrong narmstrong@baylibre.com wrote:
On 03/12/2017 10:17, Beniamino Galvani wrote:
gate = &gates[clk->id];
if (gate->reg == 0)
return -ENOENT;
Same here -ENOSYS
Here thsi means it's not a gate.
Yes, but the driver still supports the operation. The problem is that its inputs are invalid. So use -ENOENT to mean that.
Isn't that the definition of -EINVAL?
We tend to use that to indicate a failure to read the DT config.
I should probably not have said 'invalid'. The input value is reasonable (it isn't -ve, for example) but the selected item does not exist.
Regards, Simon

Use the clk framework to initialize clocks from drivers that need them instead of having hardcoded frequencies and initializations from board code.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com --- arch/arm/include/asm/arch-meson/gxbb.h | 10 ---------- arch/arm/include/asm/arch-meson/i2c.h | 11 ----------- board/amlogic/odroid-c2/odroid-c2.c | 4 +--- board/amlogic/p212/p212.c | 3 +-- drivers/i2c/meson_i2c.c | 20 +++++++++++++++++--- 5 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 arch/arm/include/asm/arch-meson/i2c.h
diff --git a/arch/arm/include/asm/arch-meson/gxbb.h b/arch/arm/include/asm/arch-meson/gxbb.h index 95a6fe6998..48a2ab7425 100644 --- a/arch/arm/include/asm/arch-meson/gxbb.h +++ b/arch/arm/include/asm/arch-meson/gxbb.h @@ -40,14 +40,4 @@ /* Ethernet memory power domain */ #define GXBB_MEM_PD_REG_0_ETH_MASK (BIT(2) | BIT(3))
-/* Clock gates */ -#define GXBB_GCLK_MPEG_0 GXBB_HIU_ADDR(0x50) -#define GXBB_GCLK_MPEG_1 GXBB_HIU_ADDR(0x51) -#define GXBB_GCLK_MPEG_2 GXBB_HIU_ADDR(0x52) -#define GXBB_GCLK_MPEG_OTHER GXBB_HIU_ADDR(0x53) -#define GXBB_GCLK_MPEG_AO GXBB_HIU_ADDR(0x54) - -#define GXBB_GCLK_MPEG_0_I2C BIT(9) -#define GXBB_GCLK_MPEG_1_ETH BIT(3) - #endif /* __GXBB_H__ */ diff --git a/arch/arm/include/asm/arch-meson/i2c.h b/arch/arm/include/asm/arch-meson/i2c.h deleted file mode 100644 index 783bc3786f..0000000000 --- a/arch/arm/include/asm/arch-meson/i2c.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2017 - Beniamino Galvani b.galvani@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#ifndef _MESON_I2C_H_ -#define _MESON_I2C_H_ - -#define MESON_I2C_CLK_RATE 167000000 - -#endif diff --git a/board/amlogic/odroid-c2/odroid-c2.c b/board/amlogic/odroid-c2/odroid-c2.c index a5ea8dc5af..833f01b4cf 100644 --- a/board/amlogic/odroid-c2/odroid-c2.c +++ b/board/amlogic/odroid-c2/odroid-c2.c @@ -34,9 +34,7 @@ int misc_init_r(void) GXBB_ETH_REG_0_PHY_CLK_EN | GXBB_ETH_REG_0_CLK_EN);
- /* Enable power and clock gate */ - setbits_le32(GXBB_GCLK_MPEG_0, GXBB_GCLK_MPEG_0_I2C); - setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH); + /* Enable power */ clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
/* Reset PHY on GPIOZ_14 */ diff --git a/board/amlogic/p212/p212.c b/board/amlogic/p212/p212.c index ece8096c5c..907bbb286e 100644 --- a/board/amlogic/p212/p212.c +++ b/board/amlogic/p212/p212.c @@ -36,8 +36,7 @@ int misc_init_r(void) out_le32(GXBB_ETH_REG_2, 0x10110181); out_le32(GXBB_ETH_REG_3, 0xe40908ff);
- /* Enable power and clock gate */ - setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH); + /* Enable power */ clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
if (!eth_env_get_enetaddr("ethaddr", mac_addr)) { diff --git a/drivers/i2c/meson_i2c.c b/drivers/i2c/meson_i2c.c index 2434d9ed53..1d92b09c32 100644 --- a/drivers/i2c/meson_i2c.c +++ b/drivers/i2c/meson_i2c.c @@ -4,8 +4,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> -#include <asm/arch/i2c.h> #include <asm/io.h> +#include <clk.h> #include <dm.h> #include <i2c.h>
@@ -43,6 +43,7 @@ struct i2c_regs { };
struct meson_i2c { + struct clk clk; struct i2c_regs *regs; struct i2c_msg *msg; bool last; @@ -209,9 +210,13 @@ static int meson_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) { struct meson_i2c *i2c = dev_get_priv(bus); - unsigned int clk_rate = MESON_I2C_CLK_RATE; + ulong clk_rate; unsigned int div;
+ clk_rate = clk_get_rate(&i2c->clk); + if (IS_ERR_VALUE(clk_rate)) + return -EINVAL; + div = DIV_ROUND_UP(clk_rate, speed * 4);
/* clock divider has 12 bits */ @@ -226,7 +231,7 @@ static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) clrsetbits_le32(&i2c->regs->ctrl, REG_CTRL_CLKDIVEXT_MASK, (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
- debug("meson i2c: set clk %u, src %u, div %u\n", speed, clk_rate, div); + debug("meson i2c: set clk %u, src %lu, div %u\n", speed, clk_rate, div);
return 0; } @@ -234,6 +239,15 @@ static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) static int meson_i2c_probe(struct udevice *bus) { struct meson_i2c *i2c = dev_get_priv(bus); + int ret; + + ret = clk_get_by_index(bus, 0, &i2c->clk); + if (ret < 0) + return ret; + + ret = clk_enable(&i2c->clk); + if (ret) + return ret;
i2c->regs = dev_read_addr_ptr(bus); clrbits_le32(&i2c->regs->ctrl, REG_CTRL_START);

On 03/12/2017 10:17, Beniamino Galvani wrote:
Use the clk framework to initialize clocks from drivers that need them instead of having hardcoded frequencies and initializations from board code.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/include/asm/arch-meson/gxbb.h | 10 ---------- arch/arm/include/asm/arch-meson/i2c.h | 11 ----------- board/amlogic/odroid-c2/odroid-c2.c | 4 +--- board/amlogic/p212/p212.c | 3 +-- drivers/i2c/meson_i2c.c | 20 +++++++++++++++++--- 5 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 arch/arm/include/asm/arch-meson/i2c.h
diff --git a/arch/arm/include/asm/arch-meson/gxbb.h b/arch/arm/include/asm/arch-meson/gxbb.h index 95a6fe6998..48a2ab7425 100644 --- a/arch/arm/include/asm/arch-meson/gxbb.h +++ b/arch/arm/include/asm/arch-meson/gxbb.h @@ -40,14 +40,4 @@ /* Ethernet memory power domain */ #define GXBB_MEM_PD_REG_0_ETH_MASK (BIT(2) | BIT(3))
-/* Clock gates */ -#define GXBB_GCLK_MPEG_0 GXBB_HIU_ADDR(0x50) -#define GXBB_GCLK_MPEG_1 GXBB_HIU_ADDR(0x51) -#define GXBB_GCLK_MPEG_2 GXBB_HIU_ADDR(0x52) -#define GXBB_GCLK_MPEG_OTHER GXBB_HIU_ADDR(0x53) -#define GXBB_GCLK_MPEG_AO GXBB_HIU_ADDR(0x54)
-#define GXBB_GCLK_MPEG_0_I2C BIT(9) -#define GXBB_GCLK_MPEG_1_ETH BIT(3)
#endif /* __GXBB_H__ */ diff --git a/arch/arm/include/asm/arch-meson/i2c.h b/arch/arm/include/asm/arch-meson/i2c.h deleted file mode 100644 index 783bc3786f..0000000000 --- a/arch/arm/include/asm/arch-meson/i2c.h +++ /dev/null @@ -1,11 +0,0 @@ -/*
- Copyright 2017 - Beniamino Galvani b.galvani@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
-#ifndef _MESON_I2C_H_ -#define _MESON_I2C_H_
-#define MESON_I2C_CLK_RATE 167000000
-#endif diff --git a/board/amlogic/odroid-c2/odroid-c2.c b/board/amlogic/odroid-c2/odroid-c2.c index a5ea8dc5af..833f01b4cf 100644 --- a/board/amlogic/odroid-c2/odroid-c2.c +++ b/board/amlogic/odroid-c2/odroid-c2.c @@ -34,9 +34,7 @@ int misc_init_r(void) GXBB_ETH_REG_0_PHY_CLK_EN | GXBB_ETH_REG_0_CLK_EN);
- /* Enable power and clock gate */
- setbits_le32(GXBB_GCLK_MPEG_0, GXBB_GCLK_MPEG_0_I2C);
- setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH);
/* Enable power */ clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
/* Reset PHY on GPIOZ_14 */
diff --git a/board/amlogic/p212/p212.c b/board/amlogic/p212/p212.c index ece8096c5c..907bbb286e 100644 --- a/board/amlogic/p212/p212.c +++ b/board/amlogic/p212/p212.c @@ -36,8 +36,7 @@ int misc_init_r(void) out_le32(GXBB_ETH_REG_2, 0x10110181); out_le32(GXBB_ETH_REG_3, 0xe40908ff);
- /* Enable power and clock gate */
- setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH);
/* Enable power */ clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
diff --git a/drivers/i2c/meson_i2c.c b/drivers/i2c/meson_i2c.c index 2434d9ed53..1d92b09c32 100644 --- a/drivers/i2c/meson_i2c.c +++ b/drivers/i2c/meson_i2c.c @@ -4,8 +4,8 @@
- SPDX-License-Identifier: GPL-2.0+
*/ #include <common.h> -#include <asm/arch/i2c.h> #include <asm/io.h> +#include <clk.h> #include <dm.h> #include <i2c.h>
@@ -43,6 +43,7 @@ struct i2c_regs { };
struct meson_i2c {
- struct clk clk; struct i2c_regs *regs; struct i2c_msg *msg; bool last;
@@ -209,9 +210,13 @@ static int meson_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) { struct meson_i2c *i2c = dev_get_priv(bus);
- unsigned int clk_rate = MESON_I2C_CLK_RATE;
ulong clk_rate; unsigned int div;
clk_rate = clk_get_rate(&i2c->clk);
if (IS_ERR_VALUE(clk_rate))
return -EINVAL;
div = DIV_ROUND_UP(clk_rate, speed * 4);
/* clock divider has 12 bits */
@@ -226,7 +231,7 @@ static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) clrsetbits_le32(&i2c->regs->ctrl, REG_CTRL_CLKDIVEXT_MASK, (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
- debug("meson i2c: set clk %u, src %u, div %u\n", speed, clk_rate, div);
debug("meson i2c: set clk %u, src %lu, div %u\n", speed, clk_rate, div);
return 0;
} @@ -234,6 +239,15 @@ static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) static int meson_i2c_probe(struct udevice *bus) { struct meson_i2c *i2c = dev_get_priv(bus);
int ret;
ret = clk_get_by_index(bus, 0, &i2c->clk);
if (ret < 0)
return ret;
ret = clk_enable(&i2c->clk);
if (ret)
return ret;
i2c->regs = dev_read_addr_ptr(bus); clrbits_le32(&i2c->regs->ctrl, REG_CTRL_START);
You must now rebase it to master since tom merged the Khadas and LibreTech-CC patches.
Thanks for the patchset, it looks very good.
Neil

On 3 December 2017 at 02:17, Beniamino Galvani b.galvani@gmail.com wrote:
Use the clk framework to initialize clocks from drivers that need them instead of having hardcoded frequencies and initializations from board code.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com
arch/arm/include/asm/arch-meson/gxbb.h | 10 ---------- arch/arm/include/asm/arch-meson/i2c.h | 11 ----------- board/amlogic/odroid-c2/odroid-c2.c | 4 +--- board/amlogic/p212/p212.c | 3 +-- drivers/i2c/meson_i2c.c | 20 +++++++++++++++++--- 5 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 arch/arm/include/asm/arch-meson/i2c.h
Reviewed-by: Simon Glass sjg@chromium.org

On Sun, Dec 03, 2017 at 10:17:13AM +0100, Beniamino Galvani wrote:
Use the clk framework to initialize clocks from drivers that need them instead of having hardcoded frequencies and initializations from board code.
Signed-off-by: Beniamino Galvani b.galvani@gmail.com Reviewed-by: Simon Glass sjg@chromium.org
arch/arm/include/asm/arch-meson/gxbb.h | 10 ---------- arch/arm/include/asm/arch-meson/i2c.h | 11 ----------- board/amlogic/odroid-c2/odroid-c2.c | 4 +--- board/amlogic/p212/p212.c | 3 +-- drivers/i2c/meson_i2c.c | 20 +++++++++++++++++--- 5 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 arch/arm/include/asm/arch-meson/i2c.h
This fails to apply in non-trivial ways, please update and re-test, thanks!

Hi Beniamino,
On 03/12/2017 10:17, Beniamino Galvani wrote:
Hi,
this is a basic clock driver for u-boot that supports enabling/disabling clock gates and getting their frequency. With this, some hardcoded initializations can be removed from the board code, and drivers can use the information from device tree to initialize clocks.
Beniamino Galvani (4): ARM: dts: update gxbb-clkc.h from Linux 4.14 ARM: meson: add clock measurement function clk: add Amlogic meson clock driver meson: use the clock driver
arch/arm/include/asm/arch-meson/clock.h | 34 ++++++ arch/arm/include/asm/arch-meson/gxbb.h | 10 -- arch/arm/include/asm/arch-meson/i2c.h | 11 -- arch/arm/mach-meson/Kconfig | 2 + arch/arm/mach-meson/Makefile | 2 +- arch/arm/mach-meson/clock.c | 45 ++++++++ board/amlogic/odroid-c2/odroid-c2.c | 4 +- board/amlogic/p212/p212.c | 3 +- drivers/clk/Makefile | 1 + drivers/clk/clk_meson.c | 196 ++++++++++++++++++++++++++++++++ drivers/i2c/meson_i2c.c | 20 +++- include/dt-bindings/clock/gxbb-clkc.h | 75 ++++++++++++ 12 files changed, 373 insertions(+), 30 deletions(-) create mode 100644 arch/arm/include/asm/arch-meson/clock.h delete mode 100644 arch/arm/include/asm/arch-meson/i2c.h create mode 100644 arch/arm/mach-meson/clock.c create mode 100644 drivers/clk/clk_meson.c
Do you plan to re-send the driver soon ?
Thanks, Neil

2018-03-28 10:59 GMT+02:00 Neil Armstrong narmstrong@baylibre.com:
Do you plan to re-send the driver soon ?
Yes, I plan to submit it again in the next days.
Beniamino

On 28/03/2018 12:52, Beniamino Galvani wrote:
2018-03-28 10:59 GMT+02:00 Neil Armstrong narmstrong@baylibre.com:
Do you plan to re-send the driver soon ?
Yes, I plan to submit it again in the next days.
Beniamino
Cool ! Thanks !
Can you base it after my "ARM: meson: rename GXBB to GX" patch ?
It will be simpler to merge everything !
Thanks, Neil
participants (5)
-
Andreas Färber
-
Beniamino Galvani
-
Neil Armstrong
-
Simon Glass
-
Tom Rini