summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2017-05-10 21:40:11 (GMT)
committerTom Rini <trini@konsulko.com>2017-05-10 21:40:11 (GMT)
commit1f5541c8818d3ecd243f9bbf58db9ea5f55a3195 (patch)
tree83053c0f224f8fe641550492e95818033e5af7e2 /drivers/clk
parent102d86552abc82818c22b39fdef4b3a280a60643 (diff)
parent2085de57f3928d72b27338f68d4250d1fb302d04 (diff)
downloadu-boot-fsl-qoriq-1f5541c8818d3ecd243f9bbf58db9ea5f55a3195.tar.xz
Merge git://git.denx.de/u-boot-rockchip
This adds a new firefly-rk3399 board, MIPI support for rk3399 and rk3288, rk818 pmic support, mkimage improvements for rockchip and a few other things.
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/rockchip/clk_rk3036.c5
-rw-r--r--drivers/clk/rockchip/clk_rk3188.c12
-rw-r--r--drivers/clk/rockchip/clk_rk3288.c12
-rw-r--r--drivers/clk/rockchip/clk_rk3328.c8
-rw-r--r--drivers/clk/rockchip/clk_rk3399.c131
5 files changed, 161 insertions, 7 deletions
diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
index 7e3bf96..d866d0b 100644
--- a/drivers/clk/rockchip/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -228,11 +228,13 @@ static ulong rockchip_mmc_get_clk(struct rk3036_cru *cru, uint clk_general_rate,
switch (periph) {
case HCLK_EMMC:
+ case SCLK_EMMC:
con = readl(&cru->cru_clksel_con[12]);
mux = (con >> EMMC_PLL_SHIFT) & EMMC_PLL_MASK;
div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
break;
case HCLK_SDIO:
+ case SCLK_SDIO:
con = readl(&cru->cru_clksel_con[12]);
mux = (con >> MMC0_PLL_SHIFT) & MMC0_PLL_MASK;
div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
@@ -265,6 +267,7 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate,
switch (periph) {
case HCLK_EMMC:
+ case SCLK_EMMC:
rk_clrsetreg(&cru->cru_clksel_con[12],
EMMC_PLL_MASK << EMMC_PLL_SHIFT |
EMMC_DIV_MASK << EMMC_DIV_SHIFT,
@@ -272,6 +275,7 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate,
(src_clk_div - 1) << EMMC_DIV_SHIFT);
break;
case HCLK_SDIO:
+ case SCLK_SDIO:
rk_clrsetreg(&cru->cru_clksel_con[11],
MMC0_PLL_MASK << MMC0_PLL_SHIFT |
MMC0_DIV_MASK << MMC0_DIV_SHIFT,
@@ -307,6 +311,7 @@ static ulong rk3036_clk_set_rate(struct clk *clk, ulong rate)
case 0 ... 63:
return 0;
case HCLK_EMMC:
+ case SCLK_EMMC:
new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate,
clk->id, rate);
break;
diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c
index d36cf8f..b32491d 100644
--- a/drivers/clk/rockchip/clk_rk3188.c
+++ b/drivers/clk/rockchip/clk_rk3188.c
@@ -269,14 +269,17 @@ static ulong rockchip_mmc_get_clk(struct rk3188_cru *cru, uint gclk_rate,
switch (periph) {
case HCLK_EMMC:
+ case SCLK_EMMC:
con = readl(&cru->cru_clksel_con[12]);
div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
break;
case HCLK_SDMMC:
+ case SCLK_SDMMC:
con = readl(&cru->cru_clksel_con[11]);
div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
break;
case HCLK_SDIO:
+ case SCLK_SDIO:
con = readl(&cru->cru_clksel_con[12]);
div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK;
break;
@@ -298,16 +301,19 @@ static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate,
switch (periph) {
case HCLK_EMMC:
+ case SCLK_EMMC:
rk_clrsetreg(&cru->cru_clksel_con[12],
EMMC_DIV_MASK << EMMC_DIV_SHIFT,
src_clk_div << EMMC_DIV_SHIFT);
break;
case HCLK_SDMMC:
+ case SCLK_SDMMC:
rk_clrsetreg(&cru->cru_clksel_con[11],
MMC0_DIV_MASK << MMC0_DIV_SHIFT,
src_clk_div << MMC0_DIV_SHIFT);
break;
case HCLK_SDIO:
+ case SCLK_SDIO:
rk_clrsetreg(&cru->cru_clksel_con[12],
SDIO_DIV_MASK << SDIO_DIV_SHIFT,
src_clk_div << SDIO_DIV_SHIFT);
@@ -466,6 +472,9 @@ static ulong rk3188_clk_get_rate(struct clk *clk)
case HCLK_EMMC:
case HCLK_SDMMC:
case HCLK_SDIO:
+ case SCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_SDIO:
new_rate = rockchip_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
clk->id);
break;
@@ -505,6 +514,9 @@ static ulong rk3188_clk_set_rate(struct clk *clk, ulong rate)
case HCLK_EMMC:
case HCLK_SDMMC:
case HCLK_SDIO:
+ case SCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_SDIO:
new_rate = rockchip_mmc_set_clk(cru, PERI_HCLK_HZ,
clk->id, rate);
break;
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 7835676..fc369dd 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -513,16 +513,19 @@ static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint gclk_rate,
switch (periph) {
case HCLK_EMMC:
+ case SCLK_EMMC:
con = readl(&cru->cru_clksel_con[12]);
mux = (con >> EMMC_PLL_SHIFT) & EMMC_PLL_MASK;
div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
break;
case HCLK_SDMMC:
+ case SCLK_SDMMC:
con = readl(&cru->cru_clksel_con[11]);
mux = (con >> MMC0_PLL_SHIFT) & MMC0_PLL_MASK;
div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
break;
case HCLK_SDIO0:
+ case SCLK_SDIO0:
con = readl(&cru->cru_clksel_con[12]);
mux = (con >> SDIO0_PLL_SHIFT) & SDIO0_PLL_MASK;
div = (con >> SDIO0_DIV_SHIFT) & SDIO0_DIV_MASK;
@@ -556,6 +559,7 @@ static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint gclk_rate,
}
switch (periph) {
case HCLK_EMMC:
+ case SCLK_EMMC:
rk_clrsetreg(&cru->cru_clksel_con[12],
EMMC_PLL_MASK << EMMC_PLL_SHIFT |
EMMC_DIV_MASK << EMMC_DIV_SHIFT,
@@ -563,6 +567,7 @@ static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint gclk_rate,
(src_clk_div - 1) << EMMC_DIV_SHIFT);
break;
case HCLK_SDMMC:
+ case SCLK_SDMMC:
rk_clrsetreg(&cru->cru_clksel_con[11],
MMC0_PLL_MASK << MMC0_PLL_SHIFT |
MMC0_DIV_MASK << MMC0_DIV_SHIFT,
@@ -570,6 +575,7 @@ static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint gclk_rate,
(src_clk_div - 1) << MMC0_DIV_SHIFT);
break;
case HCLK_SDIO0:
+ case SCLK_SDIO0:
rk_clrsetreg(&cru->cru_clksel_con[12],
SDIO0_PLL_MASK << SDIO0_PLL_SHIFT |
SDIO0_DIV_MASK << SDIO0_DIV_SHIFT,
@@ -662,6 +668,9 @@ static ulong rk3288_clk_get_rate(struct clk *clk)
case HCLK_EMMC:
case HCLK_SDMMC:
case HCLK_SDIO0:
+ case SCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_SDIO0:
new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, clk->id);
break;
case SCLK_SPI0:
@@ -706,6 +715,9 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
case HCLK_EMMC:
case HCLK_SDMMC:
case HCLK_SDIO0:
+ case SCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_SDIO0:
new_rate = rockchip_mmc_set_clk(cru, gclk_rate, clk->id, rate);
break;
case SCLK_SPI0:
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 0ff1e30..8ec1574 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -397,9 +397,11 @@ static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
switch (clk_id) {
case HCLK_SDMMC:
+ case SCLK_SDMMC:
con_id = 30;
break;
case HCLK_EMMC:
+ case SCLK_EMMC:
con_id = 32;
break;
default:
@@ -423,9 +425,11 @@ static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
switch (clk_id) {
case HCLK_SDMMC:
+ case SCLK_SDMMC:
con_id = 30;
break;
case HCLK_EMMC:
+ case SCLK_EMMC:
con_id = 32;
break;
default:
@@ -483,6 +487,8 @@ static ulong rk3328_clk_get_rate(struct clk *clk)
return 0;
case HCLK_SDMMC:
case HCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_EMMC:
rate = rk3328_mmc_get_clk(priv->cru, clk->id);
break;
case SCLK_I2C0:
@@ -511,6 +517,8 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
return 0;
case HCLK_SDMMC:
case HCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_EMMC:
ret = rk3328_mmc_set_clk(priv->cru, clk->id, rate);
break;
case SCLK_I2C0:
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index ff3cc37..026ed4d 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -1,5 +1,6 @@
/*
* (C) Copyright 2015 Google, Inc
+ * (C) 2017 Theobroma Systems Design und Consulting GmbH
*
* SPDX-License-Identifier: GPL-2.0
*/
@@ -207,12 +208,15 @@ enum {
DCLK_VOP_DIV_CON_SHIFT = 0,
/* CLKSEL_CON58 */
- CLK_SPI_PLL_SEL_MASK = 1,
- CLK_SPI_PLL_SEL_CPLL = 0,
- CLK_SPI_PLL_SEL_GPLL = 1,
- CLK_SPI_PLL_DIV_CON_MASK = 0x7f,
- CLK_SPI5_PLL_DIV_CON_SHIFT = 8,
- CLK_SPI5_PLL_SEL_SHIFT = 15,
+ CLK_SPI_PLL_SEL_WIDTH = 1,
+ CLK_SPI_PLL_SEL_MASK = ((1 < CLK_SPI_PLL_SEL_WIDTH) - 1),
+ CLK_SPI_PLL_SEL_CPLL = 0,
+ CLK_SPI_PLL_SEL_GPLL = 1,
+ CLK_SPI_PLL_DIV_CON_WIDTH = 7,
+ CLK_SPI_PLL_DIV_CON_MASK = ((1 << CLK_SPI_PLL_DIV_CON_WIDTH) - 1),
+
+ CLK_SPI5_PLL_DIV_CON_SHIFT = 8,
+ CLK_SPI5_PLL_SEL_SHIFT = 15,
/* CLKSEL_CON59 */
CLK_SPI1_PLL_SEL_SHIFT = 15,
@@ -602,7 +606,96 @@ static ulong rk3399_i2c_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
return -EINVAL;
}
- return DIV_TO_RATE(GPLL_HZ, src_clk_div);
+ return rk3399_i2c_get_clk(cru, clk_id);
+}
+
+/*
+ * RK3399 SPI clocks have a common divider-width (7 bits) and a single bit
+ * to select either CPLL or GPLL as the clock-parent. The location within
+ * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable.
+ */
+
+struct spi_clkreg {
+ uint8_t reg; /* CLKSEL_CON[reg] register in CRU */
+ uint8_t div_shift;
+ uint8_t sel_shift;
+};
+
+/*
+ * The entries are numbered relative to their offset from SCLK_SPI0.
+ *
+ * Note that SCLK_SPI3 (which is configured via PMUCRU and requires different
+ * logic is not supported).
+ */
+static const struct spi_clkreg spi_clkregs[] = {
+ [0] = { .reg = 59,
+ .div_shift = CLK_SPI0_PLL_DIV_CON_SHIFT,
+ .sel_shift = CLK_SPI0_PLL_SEL_SHIFT, },
+ [1] = { .reg = 59,
+ .div_shift = CLK_SPI1_PLL_DIV_CON_SHIFT,
+ .sel_shift = CLK_SPI1_PLL_SEL_SHIFT, },
+ [2] = { .reg = 60,
+ .div_shift = CLK_SPI2_PLL_DIV_CON_SHIFT,
+ .sel_shift = CLK_SPI2_PLL_SEL_SHIFT, },
+ [3] = { .reg = 60,
+ .div_shift = CLK_SPI4_PLL_DIV_CON_SHIFT,
+ .sel_shift = CLK_SPI4_PLL_SEL_SHIFT, },
+ [4] = { .reg = 58,
+ .div_shift = CLK_SPI5_PLL_DIV_CON_SHIFT,
+ .sel_shift = CLK_SPI5_PLL_SEL_SHIFT, },
+};
+
+static inline u32 extract_bits(u32 val, unsigned width, unsigned shift)
+{
+ return (val >> shift) & ((1 << width) - 1);
+}
+
+static ulong rk3399_spi_get_clk(struct rk3399_cru *cru, ulong clk_id)
+{
+ const struct spi_clkreg *spiclk = NULL;
+ u32 div, val;
+
+ switch (clk_id) {
+ case SCLK_SPI0 ... SCLK_SPI5:
+ spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+ break;
+
+ default:
+ error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+ return -EINVAL;
+ }
+
+ val = readl(&cru->clksel_con[spiclk->reg]);
+ div = extract_bits(val, CLK_SPI_PLL_DIV_CON_WIDTH, spiclk->div_shift);
+
+ return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rk3399_spi_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
+{
+ const struct spi_clkreg *spiclk = NULL;
+ int src_clk_div;
+
+ src_clk_div = RATE_TO_DIV(GPLL_HZ, hz);
+ assert(src_clk_div < 127);
+
+ switch (clk_id) {
+ case SCLK_SPI1 ... SCLK_SPI5:
+ spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+ break;
+
+ default:
+ error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+ return -EINVAL;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[spiclk->reg],
+ ((CLK_SPI_PLL_DIV_CON_MASK << spiclk->div_shift) |
+ (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)),
+ ((src_clk_div << spiclk->div_shift) |
+ (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)));
+
+ return rk3399_spi_get_clk(cru, clk_id);
}
static ulong rk3399_vop_set_clk(struct rk3399_cru *cru, ulong clk_id, u32 hz)
@@ -654,6 +747,7 @@ static ulong rk3399_mmc_get_clk(struct rk3399_cru *cru, uint clk_id)
u32 div, con;
switch (clk_id) {
+ case HCLK_SDMMC:
case SCLK_SDMMC:
con = readl(&cru->clksel_con[16]);
break;
@@ -679,6 +773,7 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
int aclk_emmc = 198*MHz;
switch (clk_id) {
+ case HCLK_SDMMC:
case SCLK_SDMMC:
/* Select clk_sdmmc source from GPLL by default */
src_clk_div = GPLL_HZ / set_rate;
@@ -768,6 +863,7 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
switch (clk->id) {
case 0 ... 63:
return 0;
+ case HCLK_SDMMC:
case SCLK_SDMMC:
case SCLK_EMMC:
rate = rk3399_mmc_get_clk(priv->cru, clk->id);
@@ -780,9 +876,20 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
case SCLK_I2C7:
rate = rk3399_i2c_get_clk(priv->cru, clk->id);
break;
+ case SCLK_SPI0...SCLK_SPI5:
+ rate = rk3399_spi_get_clk(priv->cru, clk->id);
+ break;
+ case SCLK_UART0:
+ case SCLK_UART2:
+ return 24000000;
+ break;
+ case PCLK_HDMI_CTRL:
+ break;
case DCLK_VOP0:
case DCLK_VOP1:
break;
+ case PCLK_EFUSE1024NS:
+ break;
default:
return -ENOENT;
}
@@ -798,6 +905,7 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
switch (clk->id) {
case 0 ... 63:
return 0;
+ case HCLK_SDMMC:
case SCLK_SDMMC:
case SCLK_EMMC:
ret = rk3399_mmc_set_clk(priv->cru, clk->id, rate);
@@ -814,6 +922,13 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_I2C7:
ret = rk3399_i2c_set_clk(priv->cru, clk->id, rate);
break;
+ case SCLK_SPI0...SCLK_SPI5:
+ ret = rk3399_spi_set_clk(priv->cru, clk->id, rate);
+ break;
+ case PCLK_HDMI_CTRL:
+ case PCLK_VIO_GRF:
+ /* the PCLK gates for video are enabled by default */
+ break;
case DCLK_VOP0:
case DCLK_VOP1:
ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
@@ -821,6 +936,8 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_DDRCLK:
ret = rk3399_ddr_set_clk(priv->cru, rate);
break;
+ case PCLK_EFUSE1024NS:
+ break;
default:
return -ENOENT;
}