mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 23:51:33 +00:00
rockchip: rk3588: Add support for sdmmc clocks in SPL
Booting from sdmmc on RK3588 currently works because of a workaround in
the device tree, clocks are reordered so that the driver use ciu-sample
instead of ciu, and the BootRom initializes sdmmc clocks before SPL is
loaded into DRAM.
The sdmmc clocks are normally controlled by TF-A using SCMI. However,
there is a need to control these clocks in SPL, before TF-A has started.
This adds a rk3588_scru driver to control the sdmmc clocks in SPL before
TF-A has started, using scru regs. It also adds a small glue driver to
bind the scmi clock node to the rk3588_scru driver in SPL.
Fixes: 7a474df740
("clk: rockchip: Add rk3588 clk support")
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
This commit is contained in:
parent
2229758118
commit
6737771600
3 changed files with 143 additions and 2 deletions
|
@ -194,6 +194,5 @@ int rockchip_get_clk(struct udevice **devp);
|
|||
* Return: 0 success, or error value
|
||||
*/
|
||||
int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number);
|
||||
int rockchip_get_scmi_clk(struct udevice **devp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
#define KHz 1000
|
||||
#define OSC_HZ (24 * MHz)
|
||||
|
||||
#define CPU_PVTPLL_HZ (1008 * MHz)
|
||||
#define LPLL_HZ (816 * MHz)
|
||||
#define GPLL_HZ (1188 * MHz)
|
||||
#define CPLL_HZ (1500 * MHz)
|
||||
#define NPLL_HZ (850 * MHz)
|
||||
#define PPLL_HZ (1100 * MHz)
|
||||
#define SPLL_HZ (702 * MHz)
|
||||
|
||||
/* RK3588 pll id */
|
||||
enum rk3588_pll_id {
|
||||
|
@ -447,5 +447,22 @@ enum {
|
|||
CLK_I2C0_SEL_MASK = 1 << CLK_I2C0_SEL_SHIFT,
|
||||
CLK_I2C_SEL_200M = 0,
|
||||
CLK_I2C_SEL_100M,
|
||||
|
||||
/* SECURECRU_CLKSEL_CON01 */
|
||||
SCMI_HCLK_SD_SEL_SHIFT = 2,
|
||||
SCMI_HCLK_SD_SEL_MASK = 3 << SCMI_HCLK_SD_SEL_SHIFT,
|
||||
SCMI_HCLK_SD_SEL_150M = 0,
|
||||
SCMI_HCLK_SD_SEL_100M,
|
||||
SCMI_HCLK_SD_SEL_50M,
|
||||
SCMI_HCLK_SD_SEL_24M,
|
||||
|
||||
/* SECURECRU_CLKSEL_CON03 */
|
||||
SCMI_CCLK_SD_SEL_SHIFT = 12,
|
||||
SCMI_CCLK_SD_SEL_MASK = 3 << SCMI_CCLK_SD_SEL_SHIFT,
|
||||
SCMI_CCLK_SD_SEL_GPLL = 0,
|
||||
SCMI_CCLK_SD_SEL_SPLL,
|
||||
SCMI_CCLK_SD_SEL_24M,
|
||||
SCMI_CCLK_SD_DIV_SHIFT = 6,
|
||||
SCMI_CCLK_SD_DIV_MASK = 0x3f << SCMI_CCLK_SD_DIV_SHIFT,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <scmi_protocols.h>
|
||||
#include <syscon.h>
|
||||
#include <asm/arch-rockchip/cru_rk3588.h>
|
||||
#include <asm/arch-rockchip/clock.h>
|
||||
|
@ -1994,3 +1995,127 @@ U_BOOT_DRIVER(rockchip_rk3588_cru) = {
|
|||
.bind = rk3588_clk_bind,
|
||||
.probe = rk3588_clk_probe,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
#define SCRU_BASE 0xfd7d0000
|
||||
|
||||
static ulong rk3588_scru_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
u32 con, div, sel, parent;
|
||||
|
||||
switch (clk->id) {
|
||||
case SCMI_CCLK_SD:
|
||||
con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
|
||||
sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
|
||||
div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
|
||||
if (sel == SCMI_CCLK_SD_SEL_GPLL)
|
||||
parent = GPLL_HZ;
|
||||
else if (sel == SCMI_CCLK_SD_SEL_SPLL)
|
||||
parent = SPLL_HZ;
|
||||
else
|
||||
parent = OSC_HZ;
|
||||
return DIV_TO_RATE(parent, div);
|
||||
case SCMI_HCLK_SD:
|
||||
con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
|
||||
sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
|
||||
if (sel == SCMI_HCLK_SD_SEL_150M)
|
||||
return 150 * MHz;
|
||||
else if (sel == SCMI_HCLK_SD_SEL_100M)
|
||||
return 100 * MHz;
|
||||
else if (sel == SCMI_HCLK_SD_SEL_50M)
|
||||
return 50 * MHz;
|
||||
else
|
||||
return OSC_HZ;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
u32 div, sel;
|
||||
|
||||
switch (clk->id) {
|
||||
case SCMI_CCLK_SD:
|
||||
if ((OSC_HZ % rate) == 0) {
|
||||
sel = SCMI_CCLK_SD_SEL_24M;
|
||||
div = DIV_ROUND_UP(OSC_HZ, rate);
|
||||
} else if ((SPLL_HZ % rate) == 0) {
|
||||
sel = SCMI_CCLK_SD_SEL_SPLL;
|
||||
div = DIV_ROUND_UP(SPLL_HZ, rate);
|
||||
} else {
|
||||
sel = SCMI_CCLK_SD_SEL_GPLL;
|
||||
div = DIV_ROUND_UP(GPLL_HZ, rate);
|
||||
}
|
||||
rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
|
||||
SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
|
||||
sel << SCMI_CCLK_SD_SEL_SHIFT |
|
||||
(div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
|
||||
break;
|
||||
case SCMI_HCLK_SD:
|
||||
if (rate >= 150 * MHz)
|
||||
sel = SCMI_HCLK_SD_SEL_150M;
|
||||
else if (rate >= 100 * MHz)
|
||||
sel = SCMI_HCLK_SD_SEL_100M;
|
||||
else if (rate >= 50 * MHz)
|
||||
sel = SCMI_HCLK_SD_SEL_50M;
|
||||
else
|
||||
sel = SCMI_HCLK_SD_SEL_24M;
|
||||
rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
|
||||
SCMI_HCLK_SD_SEL_MASK,
|
||||
sel << SCMI_HCLK_SD_SEL_SHIFT);
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return rk3588_scru_clk_get_rate(clk);
|
||||
}
|
||||
|
||||
static const struct clk_ops rk3588_scru_clk_ops = {
|
||||
.get_rate = rk3588_scru_clk_get_rate,
|
||||
.set_rate = rk3588_scru_clk_set_rate,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(rockchip_rk3588_scru) = {
|
||||
.name = "rockchip_rk3588_scru",
|
||||
.id = UCLASS_CLK,
|
||||
.ops = &rk3588_scru_clk_ops,
|
||||
};
|
||||
|
||||
static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode node;
|
||||
u32 protocol_id;
|
||||
const char *name;
|
||||
|
||||
dev_for_each_subnode(node, dev) {
|
||||
if (!ofnode_is_enabled(node))
|
||||
continue;
|
||||
|
||||
if (ofnode_read_u32(node, "reg", &protocol_id))
|
||||
continue;
|
||||
|
||||
if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
|
||||
continue;
|
||||
|
||||
name = ofnode_get_name(node);
|
||||
return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
|
||||
name, node, NULL);
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
|
||||
{ .compatible = "arm,scmi-smc" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
|
||||
.name = "rk3588_scmi_spl_glue",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = rk3588_scmi_spl_glue_ids,
|
||||
.bind = rk3588_scmi_spl_glue_bind,
|
||||
};
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue