From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Wed, 20 Apr 2016 08:41:00 -0600 Subject: [U-Boot] [PATCH 4/9] clk: exynos: add clock driver for Exynos7420 Soc In-Reply-To: <1460544222-5342-5-git-send-email-ta.omasab@gmail.com> References: <1460544222-5342-1-git-send-email-ta.omasab@gmail.com> <1460544222-5342-5-git-send-email-ta.omasab@gmail.com> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Thomas, On 13 April 2016 at 04:43, Thomas Abraham wrote: > From: Thomas Abraham > > Add a clock driver for Exynos7420 SoC. There are about 25 clock controller > blocks in Exynos7420 out of which support for topc, top0 and peric1 blocks > are added in this initial version of the driver. > > Cc: Minkyu Kang > Cc: Simon Glass > Signed-off-by: Thomas Abraham > --- > drivers/clk/Kconfig | 1 + > drivers/clk/Makefile | 1 + > drivers/clk/exynos/Kconfig | 18 +++ > drivers/clk/exynos/Makefile | 9 + > drivers/clk/exynos/clk-exynos7420.c | 227 ++++++++++++++++++++++++++++ > drivers/clk/exynos/clk-pll.c | 35 +++++ > drivers/clk/exynos/clk-pll.h | 9 + > include/dt-bindings/clock/exynos7420-clk.h | 207 +++++++++++++++++++++++++ > 8 files changed, 507 insertions(+), 0 deletions(-) > create mode 100644 drivers/clk/exynos/Kconfig > create mode 100644 drivers/clk/exynos/Makefile > create mode 100644 drivers/clk/exynos/clk-exynos7420.c > create mode 100644 drivers/clk/exynos/clk-pll.c > create mode 100644 drivers/clk/exynos/clk-pll.h > create mode 100644 include/dt-bindings/clock/exynos7420-clk.h > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig > index a98b74b..6eee8eb 100644 > --- a/drivers/clk/Kconfig > +++ b/drivers/clk/Kconfig > @@ -21,5 +21,6 @@ config SPL_CLK > used as U-Boot proper. > > source "drivers/clk/uniphier/Kconfig" > +source "drivers/clk/exynos/Kconfig" > > endmenu > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile > index c51db15..81fe600 100644 > --- a/drivers/clk/Makefile > +++ b/drivers/clk/Makefile > @@ -11,3 +11,4 @@ obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o > obj-$(CONFIG_SANDBOX) += clk_sandbox.o > obj-$(CONFIG_MACH_PIC32) += clk_pic32.o > obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ > +obj-$(CONFIG_CLK_EXYNOS) += exynos/ > diff --git a/drivers/clk/exynos/Kconfig b/drivers/clk/exynos/Kconfig > new file mode 100644 > index 0000000..eb0efa9 > --- /dev/null > +++ b/drivers/clk/exynos/Kconfig > @@ -0,0 +1,18 @@ > +config CLK_EXYNOS > + bool > + select CLK > + help > + This enables support for common clock driver API on Samsung > + Exynos SoCs. > + > +menu "Clock drivers for Exynos SoCs" > + depends on CLK_EXYNOS > + > +config CLK_EXYNOS7420 > + bool "Clock driver for Samsung's Exynos7420 SoC" > + default y > + help > + This enables common clock driver support for platforms based > + on Samsung Exynos7420 SoC. > + > +endmenu > diff --git a/drivers/clk/exynos/Makefile b/drivers/clk/exynos/Makefile > new file mode 100644 > index 0000000..1df10fe > --- /dev/null > +++ b/drivers/clk/exynos/Makefile > @@ -0,0 +1,9 @@ > +# > +# Copyright (C) 2016 Samsung Electronics > +# Thomas Abraham > +# > +# SPDX-License-Identifier: GPL-2.0+ > +# > + > +obj-y += clk-pll.o > +obj-$(CONFIG_CLK_EXYNOS7420) += clk-exynos7420.o > diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c > new file mode 100644 > index 0000000..1feaea4 > --- /dev/null > +++ b/drivers/clk/exynos/clk-exynos7420.c > @@ -0,0 +1,226 @@ > +/* > + * Samsung Exynos7420 clock driver. > + * Copyright (C) 2016 Samsung Electronics > + * Thomas Abraham > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include "clk-pll.h" > +#include Please see include order. http://www.denx.de/wiki/U-Boot/CodingStyle > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#define DIVIDER(reg, shift, mask) \ > + (((readl(reg) >> shift) & mask) + 1) > + > +struct exynos7420_clk_cmu_topc { > + unsigned int rsvd1[68]; > + unsigned int bus0_pll_con[2]; > + unsigned int rsvd2[2]; > + unsigned int bus1_pll_con[2]; > + unsigned int rsvd3[54]; > + unsigned int mux_sel[6]; > + unsigned int rsvd4[250]; > + unsigned int div[4]; > +}; > + > +struct exynos7420_clk_topc_priv { > + struct exynos7420_clk_cmu_topc *topc; > + unsigned long fin_freq; > + unsigned long sclk_bus0_pll_a; > + unsigned long sclk_bus1_pll_a; Comments on these members please. > +}; > + > +static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph) > +{ > + struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); > + > + switch (periph) { > + case DOUT_SCLK_BUS0_PLL: > + case SCLK_BUS0_PLL_A: > + case SCLK_BUS0_PLL_B: > + return priv->sclk_bus0_pll_a; > + case DOUT_SCLK_BUS1_PLL: > + case SCLK_BUS1_PLL_A: > + case SCLK_BUS1_PLL_B: > + return priv->sclk_bus1_pll_a; > + default: > + return 0; > + } > +} > + > +static struct clk_ops exynos7420_clk_topc_ops = { > + .get_periph_rate = exynos7420_topc_get_periph_rate, > +}; > + > +static int exynos7420_clk_topc_probe(struct udevice *dev) > +{ > + struct exynos7420_clk_topc_priv *priv; > + struct exynos7420_clk_cmu_topc *topc; > + struct udevice *clk_dev; > + unsigned long rate; > + fdt_addr_t base; > + int ret; > + > + priv = dev_get_priv(dev); > + if (!priv) This cannot happen as it is auto-allocated. > + return -EINVAL; > + > + base = dev_get_addr(dev); > + if (base == FDT_ADDR_T_NONE) > + return -EINVAL; > + > + topc = (struct exynos7420_clk_cmu_topc *)base; > + priv->topc = topc; > + > + ret = clk_get_by_index(dev, 0, &clk_dev); > + if (ret >= 0) > + priv->fin_freq = clk_get_rate(clk_dev); > + > + rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq); > + if (readl(&topc->mux_sel[1]) & (1 << 16)) > + rate >>= 1; > + rate /= DIVIDER(&topc->div[3], 0, 0xf); > + priv->sclk_bus0_pll_a = rate; > + > + rate = pll145x_get_rate(&topc->bus1_pll_con[0], priv->fin_freq) / > + DIVIDER(&topc->div[3], 8, 0xf); > + priv->sclk_bus1_pll_a = rate; > + > + return 0; > +} > + > +static const struct udevice_id exynos7420_clk_topc_compat[] = { > + { .compatible = "samsung,exynos7-clock-topc" }, > + { } > +}; > + > +U_BOOT_DRIVER(exynos7420_clk_topc) = { > + .name = "exynos7420-clock-topc", > + .id = UCLASS_CLK, > + .of_match = exynos7420_clk_topc_compat, > + .probe = exynos7420_clk_topc_probe, > + .priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv), > + .ops = &exynos7420_clk_topc_ops, > + .flags = DM_FLAG_PRE_RELOC, > +}; > + > +struct exynos7420_clk_cmu_top0 { > + unsigned int rsvd0[128]; > + unsigned int mux_sel[7]; > + unsigned int rsvd1[261]; > + unsigned int div_peric[5]; > +}; > + > +struct exynos7420_clk_top0_priv { > + struct exynos7420_clk_cmu_top0 *top0; > + unsigned long mout_top0_bus0_pll_half; > + unsigned long sclk_uart2; > +}; > + > +static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph) > +{ > + struct exynos7420_clk_top0_priv *priv = dev_get_priv(dev); > + struct exynos7420_clk_cmu_top0 *top0 = priv->top0; > + > + switch (periph) { > + case CLK_SCLK_UART2: > + return priv->mout_top0_bus0_pll_half / > + DIVIDER(&top0->div_peric[3], 8, 0xf); > + default: > + return 0; > + } > +} > + > +static struct clk_ops exynos7420_clk_top0_ops = { > + .get_periph_rate = exynos7420_top0_get_periph_rate, > +}; > + > +static int exynos7420_clk_top0_probe(struct udevice *dev) > +{ > + struct exynos7420_clk_top0_priv *priv; > + struct exynos7420_clk_cmu_top0 *top0; > + struct udevice *clk_dev; > + fdt_addr_t base; > + int ret; > + > + priv = dev_get_priv(dev); > + if (!priv) > + return -EINVAL; > + > + base = dev_get_addr(dev); > + if (base == FDT_ADDR_T_NONE) > + return -EINVAL; > + > + top0 = (struct exynos7420_clk_cmu_top0 *)base; > + priv->top0 = top0; > + > + ret = clk_get_by_index(dev, 1, &clk_dev); > + if (ret >= 0) { > + priv->mout_top0_bus0_pll_half = > + clk_get_periph_rate(clk_dev, ret); > + if (readl(&top0->mux_sel[1]) & (1 << 16)) > + priv->mout_top0_bus0_pll_half >>= 1; > + } > + > + return 0; > +} > + > +static const struct udevice_id exynos7420_clk_top0_compat[] = { > + { .compatible = "samsung,exynos7-clock-top0" }, > + { } > +}; > + > +U_BOOT_DRIVER(exynos7420_clk_top0) = { It might be better to put all the U_BOOT_DRIVER() and compatible stuff at the end of the file? > + .name = "exynos7420-clock-top0", > + .id = UCLASS_CLK, > + .of_match = exynos7420_clk_top0_compat, > + .probe = exynos7420_clk_top0_probe, > + .priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv), > + .ops = &exynos7420_clk_top0_ops, > + .flags = DM_FLAG_PRE_RELOC, > +}; > + > +static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph) > +{ > + struct udevice *clk_dev; > + unsigned int ret; > + > + switch (periph) { > + case SCLK_UART2: > + ret = clk_get_by_index(dev, 3, &clk_dev); Shouldn't this be: if (ret < 0) return ret; > + if (ret >= 0) > + return clk_get_periph_rate(clk_dev, ret); > + default: > + return 0; > + } > +} > + > +static struct clk_ops exynos7420_clk_peric1_ops = { > + .get_periph_rate = exynos7420_peric1_get_periph_rate, > +}; > + > +static int exynos7420_clk_peric1_probe(struct udevice *dev) > +{ > + return 0; Then you can omit this function. > +} > + > +static const struct udevice_id exynos7420_clk_peric1_compat[] = { > + { .compatible = "samsung,exynos7-clock-peric1" }, > + { } > +}; > + > +U_BOOT_DRIVER(exynos7420_clk_peric1) = { > + .name = "exynos7420-clock-peric1", > + .id = UCLASS_CLK, > + .of_match = exynos7420_clk_peric1_compat, > + .probe = exynos7420_clk_peric1_probe, > + .ops = &exynos7420_clk_peric1_ops, > + .flags = DM_FLAG_PRE_RELOC, > +}; > diff --git a/drivers/clk/exynos/clk-pll.c b/drivers/clk/exynos/clk-pll.c > new file mode 100644 > index 0000000..dd11268 > --- /dev/null > +++ b/drivers/clk/exynos/clk-pll.c > @@ -0,0 +1,33 @@ > +/* > + * Exynos PLL helper functions for clock drivers. > + * Copyright (C) 2016 Samsung Electronics > + * Thomas Abraham > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > + > +#define PLL145X_MDIV_SHIFT 16 > +#define PLL145X_MDIV_MASK 0x3ff > +#define PLL145X_PDIV_SHIFT 8 > +#define PLL145X_PDIV_MASK 0x3f > +#define PLL145X_SDIV_SHIFT 0 > +#define PLL145X_SDIV_MASK 0x7 > + > +unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq) > +{ > + unsigned long pll_con1 = readl(con1); > + unsigned long mdiv, sdiv, pdiv; > + uint64_t fvco = fin_freq; > + > + mdiv = (pll_con1 >> PLL145X_MDIV_SHIFT) & PLL145X_MDIV_MASK; > + pdiv = (pll_con1 >> PLL145X_PDIV_SHIFT) & PLL145X_PDIV_MASK; > + sdiv = (pll_con1 >> PLL145X_SDIV_SHIFT) & PLL145X_SDIV_MASK; > + > + fvco *= mdiv; > + do_div(fvco, (pdiv << sdiv)); > + return (unsigned long)fvco; > +} > diff --git a/drivers/clk/exynos/clk-pll.h b/drivers/clk/exynos/clk-pll.h > new file mode 100644 > index 0000000..631d035 > --- /dev/null > +++ b/drivers/clk/exynos/clk-pll.h > @@ -0,0 +1,9 @@ > +/* > + * Exynos PLL helper functions for clock drivers. > + * Copyright (C) 2016 Samsung Electronics > + * Thomas Abraham > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq); > diff --git a/include/dt-bindings/clock/exynos7420-clk.h b/include/dt-bindings/clock/exynos7420-clk.h > new file mode 100644 > index 0000000..10c5586 > --- /dev/null > +++ b/include/dt-bindings/clock/exynos7420-clk.h > @@ -0,0 +1,207 @@ > +/* > + * Copyright (c) 2014 Samsung Electronics Co., Ltd. > + * Author: Naveen Krishna Ch > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > +*/ > + > +#ifndef _DT_BINDINGS_CLOCK_EXYNOS7_H > +#define _DT_BINDINGS_CLOCK_EXYNOS7_H > + > +/* TOPC */ > +#define DOUT_ACLK_PERIS 1 > +#define DOUT_SCLK_BUS0_PLL 2 > +#define DOUT_SCLK_BUS1_PLL 3 > +#define DOUT_SCLK_CC_PLL 4 > +#define DOUT_SCLK_MFC_PLL 5 > +#define DOUT_ACLK_CCORE_133 6 > +#define DOUT_ACLK_MSCL_532 7 > +#define ACLK_MSCL_532 8 > +#define DOUT_SCLK_AUD_PLL 9 > +#define FOUT_AUD_PLL 10 > +#define SCLK_AUD_PLL 11 > +#define SCLK_MFC_PLL_B 12 > +#define SCLK_MFC_PLL_A 13 > +#define SCLK_BUS1_PLL_B 14 > +#define SCLK_BUS1_PLL_A 15 > +#define SCLK_BUS0_PLL_B 16 > +#define SCLK_BUS0_PLL_A 17 > +#define SCLK_CC_PLL_B 18 > +#define SCLK_CC_PLL_A 19 > +#define ACLK_CCORE_133 20 > +#define ACLK_PERIS_66 21 > +#define TOPC_NR_CLK 22 > + > +/* TOP0 */ > +#define DOUT_ACLK_PERIC1 1 > +#define DOUT_ACLK_PERIC0 2 > +#define CLK_SCLK_UART0 3 > +#define CLK_SCLK_UART1 4 > +#define CLK_SCLK_UART2 5 > +#define CLK_SCLK_UART3 6 > +#define CLK_SCLK_SPI0 7 > +#define CLK_SCLK_SPI1 8 > +#define CLK_SCLK_SPI2 9 > +#define CLK_SCLK_SPI3 10 > +#define CLK_SCLK_SPI4 11 > +#define CLK_SCLK_SPDIF 12 > +#define CLK_SCLK_PCM1 13 > +#define CLK_SCLK_I2S1 14 > +#define CLK_ACLK_PERIC0_66 15 > +#define CLK_ACLK_PERIC1_66 16 > +#define TOP0_NR_CLK 17 > + > +/* TOP1 */ > +#define DOUT_ACLK_FSYS1_200 1 > +#define DOUT_ACLK_FSYS0_200 2 > +#define DOUT_SCLK_MMC2 3 > +#define DOUT_SCLK_MMC1 4 > +#define DOUT_SCLK_MMC0 5 > +#define CLK_SCLK_MMC2 6 > +#define CLK_SCLK_MMC1 7 > +#define CLK_SCLK_MMC0 8 > +#define CLK_ACLK_FSYS0_200 9 > +#define CLK_ACLK_FSYS1_200 10 > +#define CLK_SCLK_PHY_FSYS1 11 > +#define CLK_SCLK_PHY_FSYS1_26M 12 > +#define MOUT_SCLK_UFSUNIPRO20 13 > +#define DOUT_SCLK_UFSUNIPRO20 14 > +#define CLK_SCLK_UFSUNIPRO20 15 > +#define DOUT_SCLK_PHY_FSYS1 16 > +#define DOUT_SCLK_PHY_FSYS1_26M 17 > +#define TOP1_NR_CLK 18 > + > +/* CCORE */ > +#define PCLK_RTC 1 > +#define CCORE_NR_CLK 2 > + > +/* PERIC0 */ > +#define PCLK_UART0 1 > +#define SCLK_UART0 2 > +#define PCLK_HSI2C0 3 > +#define PCLK_HSI2C1 4 > +#define PCLK_HSI2C4 5 > +#define PCLK_HSI2C5 6 > +#define PCLK_HSI2C9 7 > +#define PCLK_HSI2C10 8 > +#define PCLK_HSI2C11 9 > +#define PCLK_PWM 10 > +#define SCLK_PWM 11 > +#define PCLK_ADCIF 12 > +#define PERIC0_NR_CLK 13 > + > +/* PERIC1 */ > +#define PCLK_UART1 1 > +#define PCLK_UART2 2 > +#define PCLK_UART3 3 > +#define SCLK_UART1 4 > +#define SCLK_UART2 5 > +#define SCLK_UART3 6 > +#define PCLK_HSI2C2 7 > +#define PCLK_HSI2C3 8 > +#define PCLK_HSI2C6 9 > +#define PCLK_HSI2C7 10 > +#define PCLK_HSI2C8 11 > +#define PCLK_SPI0 12 > +#define PCLK_SPI1 13 > +#define PCLK_SPI2 14 > +#define PCLK_SPI3 15 > +#define PCLK_SPI4 16 > +#define SCLK_SPI0 17 > +#define SCLK_SPI1 18 > +#define SCLK_SPI2 19 > +#define SCLK_SPI3 20 > +#define SCLK_SPI4 21 > +#define PCLK_I2S1 22 > +#define PCLK_PCM1 23 > +#define PCLK_SPDIF 24 > +#define SCLK_I2S1 25 > +#define SCLK_PCM1 26 > +#define SCLK_SPDIF 27 > +#define PERIC1_NR_CLK 28 > + > +/* PERIS */ > +#define PCLK_CHIPID 1 > +#define SCLK_CHIPID 2 > +#define PCLK_WDT 3 > +#define PCLK_TMU 4 > +#define SCLK_TMU 5 > +#define PERIS_NR_CLK 6 > + > +/* FSYS0 */ > +#define ACLK_MMC2 1 > +#define ACLK_AXIUS_USBDRD30X_FSYS0X 2 > +#define ACLK_USBDRD300 3 > +#define SCLK_USBDRD300_SUSPENDCLK 4 > +#define SCLK_USBDRD300_REFCLK 5 > +#define PHYCLK_USBDRD300_UDRD30_PIPE_PCLK_USER 6 > +#define PHYCLK_USBDRD300_UDRD30_PHYCLK_USER 7 > +#define OSCCLK_PHY_CLKOUT_USB30_PHY 8 > +#define ACLK_PDMA0 9 > +#define ACLK_PDMA1 10 > +#define FSYS0_NR_CLK 11 > + > +/* FSYS1 */ > +#define ACLK_MMC1 1 > +#define ACLK_MMC0 2 > +#define PHYCLK_UFS20_TX0_SYMBOL 3 > +#define PHYCLK_UFS20_RX0_SYMBOL 4 > +#define PHYCLK_UFS20_RX1_SYMBOL 5 > +#define ACLK_UFS20_LINK 6 > +#define SCLK_UFSUNIPRO20_USER 7 > +#define PHYCLK_UFS20_RX1_SYMBOL_USER 8 > +#define PHYCLK_UFS20_RX0_SYMBOL_USER 9 > +#define PHYCLK_UFS20_TX0_SYMBOL_USER 10 > +#define OSCCLK_PHY_CLKOUT_EMBEDDED_COMBO_PHY 11 > +#define SCLK_COMBO_PHY_EMBEDDED_26M 12 > +#define DOUT_PCLK_FSYS1 13 > +#define PCLK_GPIO_FSYS1 14 > +#define MOUT_FSYS1_PHYCLK_SEL1 15 > +#define FSYS1_NR_CLK 16 > + > +/* MSCL */ > +#define USERMUX_ACLK_MSCL_532 1 > +#define DOUT_PCLK_MSCL 2 > +#define ACLK_MSCL_0 3 > +#define ACLK_MSCL_1 4 > +#define ACLK_JPEG 5 > +#define ACLK_G2D 6 > +#define ACLK_LH_ASYNC_SI_MSCL_0 7 > +#define ACLK_LH_ASYNC_SI_MSCL_1 8 > +#define ACLK_AXI2ACEL_BRIDGE 9 > +#define ACLK_XIU_MSCLX_0 10 > +#define ACLK_XIU_MSCLX_1 11 > +#define ACLK_QE_MSCL_0 12 > +#define ACLK_QE_MSCL_1 13 > +#define ACLK_QE_JPEG 14 > +#define ACLK_QE_G2D 15 > +#define ACLK_PPMU_MSCL_0 16 > +#define ACLK_PPMU_MSCL_1 17 > +#define ACLK_MSCLNP_133 18 > +#define ACLK_AHB2APB_MSCL0P 19 > +#define ACLK_AHB2APB_MSCL1P 20 > + > +#define PCLK_MSCL_0 21 > +#define PCLK_MSCL_1 22 > +#define PCLK_JPEG 23 > +#define PCLK_G2D 24 > +#define PCLK_QE_MSCL_0 25 > +#define PCLK_QE_MSCL_1 26 > +#define PCLK_QE_JPEG 27 > +#define PCLK_QE_G2D 28 > +#define PCLK_PPMU_MSCL_0 29 > +#define PCLK_PPMU_MSCL_1 30 > +#define PCLK_AXI2ACEL_BRIDGE 31 > +#define PCLK_PMU_MSCL 32 > +#define MSCL_NR_CLK 33 > + > +/* AUD */ > +#define SCLK_I2S 1 > +#define SCLK_PCM 2 > +#define PCLK_I2S 3 > +#define PCLK_PCM 4 > +#define ACLK_ADMA 5 > +#define AUD_NR_CLK 6 > +#endif /* _DT_BINDINGS_CLOCK_EXYNOS7_H */ > -- > 1.6.6.rc2 > Regards, Simon