1*ae485b54SManivannan Sadhasivam // SPDX-License-Identifier: GPL-2.0+
2*ae485b54SManivannan Sadhasivam /*
3*ae485b54SManivannan Sadhasivam * Actions Semi S900 clock driver
4*ae485b54SManivannan Sadhasivam *
5*ae485b54SManivannan Sadhasivam * Copyright (C) 2015 Actions Semi Co., Ltd.
6*ae485b54SManivannan Sadhasivam * Copyright (C) 2018 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
7*ae485b54SManivannan Sadhasivam */
8*ae485b54SManivannan Sadhasivam
9*ae485b54SManivannan Sadhasivam #include <common.h>
10*ae485b54SManivannan Sadhasivam #include <dm.h>
11*ae485b54SManivannan Sadhasivam #include <asm/arch-owl/clk_s900.h>
12*ae485b54SManivannan Sadhasivam #include <asm/arch-owl/regs_s900.h>
13*ae485b54SManivannan Sadhasivam #include <asm/io.h>
14*ae485b54SManivannan Sadhasivam
15*ae485b54SManivannan Sadhasivam #include <dt-bindings/clock/s900_cmu.h>
16*ae485b54SManivannan Sadhasivam
owl_clk_init(struct owl_clk_priv * priv)17*ae485b54SManivannan Sadhasivam void owl_clk_init(struct owl_clk_priv *priv)
18*ae485b54SManivannan Sadhasivam {
19*ae485b54SManivannan Sadhasivam u32 bus_clk = 0, core_pll, dev_pll;
20*ae485b54SManivannan Sadhasivam
21*ae485b54SManivannan Sadhasivam /* Enable ASSIST_PLL */
22*ae485b54SManivannan Sadhasivam setbits_le32(priv->base + CMU_ASSISTPLL, BIT(0));
23*ae485b54SManivannan Sadhasivam
24*ae485b54SManivannan Sadhasivam udelay(PLL_STABILITY_WAIT_US);
25*ae485b54SManivannan Sadhasivam
26*ae485b54SManivannan Sadhasivam /* Source HOSC to DEV_CLK */
27*ae485b54SManivannan Sadhasivam clrbits_le32(priv->base + CMU_DEVPLL, CMU_DEVPLL_CLK);
28*ae485b54SManivannan Sadhasivam
29*ae485b54SManivannan Sadhasivam /* Configure BUS_CLK */
30*ae485b54SManivannan Sadhasivam bus_clk |= (CMU_PDBGDIV_DIV | CMU_PERDIV_DIV | CMU_NOCDIV_DIV |
31*ae485b54SManivannan Sadhasivam CMU_DMMCLK_SRC | CMU_APBCLK_DIV | CMU_AHBCLK_DIV |
32*ae485b54SManivannan Sadhasivam CMU_NOCCLK_SRC | CMU_CORECLK_HOSC);
33*ae485b54SManivannan Sadhasivam writel(bus_clk, priv->base + CMU_BUSCLK);
34*ae485b54SManivannan Sadhasivam
35*ae485b54SManivannan Sadhasivam udelay(PLL_STABILITY_WAIT_US);
36*ae485b54SManivannan Sadhasivam
37*ae485b54SManivannan Sadhasivam /* Configure CORE_PLL */
38*ae485b54SManivannan Sadhasivam core_pll = readl(priv->base + CMU_COREPLL);
39*ae485b54SManivannan Sadhasivam core_pll |= (CMU_COREPLL_EN | CMU_COREPLL_HOSC_EN | CMU_COREPLL_OUT);
40*ae485b54SManivannan Sadhasivam writel(core_pll, priv->base + CMU_COREPLL);
41*ae485b54SManivannan Sadhasivam
42*ae485b54SManivannan Sadhasivam udelay(PLL_STABILITY_WAIT_US);
43*ae485b54SManivannan Sadhasivam
44*ae485b54SManivannan Sadhasivam /* Configure DEV_PLL */
45*ae485b54SManivannan Sadhasivam dev_pll = readl(priv->base + CMU_DEVPLL);
46*ae485b54SManivannan Sadhasivam dev_pll |= (CMU_DEVPLL_EN | CMU_DEVPLL_OUT);
47*ae485b54SManivannan Sadhasivam writel(dev_pll, priv->base + CMU_DEVPLL);
48*ae485b54SManivannan Sadhasivam
49*ae485b54SManivannan Sadhasivam udelay(PLL_STABILITY_WAIT_US);
50*ae485b54SManivannan Sadhasivam
51*ae485b54SManivannan Sadhasivam /* Source CORE_PLL for CORE_CLK */
52*ae485b54SManivannan Sadhasivam clrsetbits_le32(priv->base + CMU_BUSCLK, CMU_CORECLK_MASK,
53*ae485b54SManivannan Sadhasivam CMU_CORECLK_CPLL);
54*ae485b54SManivannan Sadhasivam
55*ae485b54SManivannan Sadhasivam /* Source DEV_PLL for DEV_CLK */
56*ae485b54SManivannan Sadhasivam setbits_le32(priv->base + CMU_DEVPLL, CMU_DEVPLL_CLK);
57*ae485b54SManivannan Sadhasivam
58*ae485b54SManivannan Sadhasivam udelay(PLL_STABILITY_WAIT_US);
59*ae485b54SManivannan Sadhasivam }
60*ae485b54SManivannan Sadhasivam
owl_uart_clk_enable(struct owl_clk_priv * priv)61*ae485b54SManivannan Sadhasivam void owl_uart_clk_enable(struct owl_clk_priv *priv)
62*ae485b54SManivannan Sadhasivam {
63*ae485b54SManivannan Sadhasivam /* Source HOSC for UART5 interface */
64*ae485b54SManivannan Sadhasivam clrbits_le32(priv->base + CMU_UART5CLK, CMU_UARTCLK_SRC_DEVPLL);
65*ae485b54SManivannan Sadhasivam
66*ae485b54SManivannan Sadhasivam /* Enable UART5 interface clock */
67*ae485b54SManivannan Sadhasivam setbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART5);
68*ae485b54SManivannan Sadhasivam }
69*ae485b54SManivannan Sadhasivam
owl_uart_clk_disable(struct owl_clk_priv * priv)70*ae485b54SManivannan Sadhasivam void owl_uart_clk_disable(struct owl_clk_priv *priv)
71*ae485b54SManivannan Sadhasivam {
72*ae485b54SManivannan Sadhasivam /* Disable UART5 interface clock */
73*ae485b54SManivannan Sadhasivam clrbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART5);
74*ae485b54SManivannan Sadhasivam }
75*ae485b54SManivannan Sadhasivam
owl_clk_enable(struct clk * clk)76*ae485b54SManivannan Sadhasivam int owl_clk_enable(struct clk *clk)
77*ae485b54SManivannan Sadhasivam {
78*ae485b54SManivannan Sadhasivam struct owl_clk_priv *priv = dev_get_priv(clk->dev);
79*ae485b54SManivannan Sadhasivam
80*ae485b54SManivannan Sadhasivam switch (clk->id) {
81*ae485b54SManivannan Sadhasivam case CLOCK_UART5:
82*ae485b54SManivannan Sadhasivam owl_uart_clk_enable(priv);
83*ae485b54SManivannan Sadhasivam break;
84*ae485b54SManivannan Sadhasivam default:
85*ae485b54SManivannan Sadhasivam return 0;
86*ae485b54SManivannan Sadhasivam }
87*ae485b54SManivannan Sadhasivam
88*ae485b54SManivannan Sadhasivam return 0;
89*ae485b54SManivannan Sadhasivam }
90*ae485b54SManivannan Sadhasivam
owl_clk_disable(struct clk * clk)91*ae485b54SManivannan Sadhasivam int owl_clk_disable(struct clk *clk)
92*ae485b54SManivannan Sadhasivam {
93*ae485b54SManivannan Sadhasivam struct owl_clk_priv *priv = dev_get_priv(clk->dev);
94*ae485b54SManivannan Sadhasivam
95*ae485b54SManivannan Sadhasivam switch (clk->id) {
96*ae485b54SManivannan Sadhasivam case CLOCK_UART5:
97*ae485b54SManivannan Sadhasivam owl_uart_clk_disable(priv);
98*ae485b54SManivannan Sadhasivam break;
99*ae485b54SManivannan Sadhasivam default:
100*ae485b54SManivannan Sadhasivam return 0;
101*ae485b54SManivannan Sadhasivam }
102*ae485b54SManivannan Sadhasivam
103*ae485b54SManivannan Sadhasivam return 0;
104*ae485b54SManivannan Sadhasivam }
105*ae485b54SManivannan Sadhasivam
owl_clk_probe(struct udevice * dev)106*ae485b54SManivannan Sadhasivam static int owl_clk_probe(struct udevice *dev)
107*ae485b54SManivannan Sadhasivam {
108*ae485b54SManivannan Sadhasivam struct owl_clk_priv *priv = dev_get_priv(dev);
109*ae485b54SManivannan Sadhasivam
110*ae485b54SManivannan Sadhasivam priv->base = dev_read_addr(dev);
111*ae485b54SManivannan Sadhasivam if (priv->base == FDT_ADDR_T_NONE)
112*ae485b54SManivannan Sadhasivam return -EINVAL;
113*ae485b54SManivannan Sadhasivam
114*ae485b54SManivannan Sadhasivam /* setup necessary clocks */
115*ae485b54SManivannan Sadhasivam owl_clk_init(priv);
116*ae485b54SManivannan Sadhasivam
117*ae485b54SManivannan Sadhasivam return 0;
118*ae485b54SManivannan Sadhasivam }
119*ae485b54SManivannan Sadhasivam
120*ae485b54SManivannan Sadhasivam static struct clk_ops owl_clk_ops = {
121*ae485b54SManivannan Sadhasivam .enable = owl_clk_enable,
122*ae485b54SManivannan Sadhasivam .disable = owl_clk_disable,
123*ae485b54SManivannan Sadhasivam };
124*ae485b54SManivannan Sadhasivam
125*ae485b54SManivannan Sadhasivam static const struct udevice_id owl_clk_ids[] = {
126*ae485b54SManivannan Sadhasivam { .compatible = "actions,s900-cmu" },
127*ae485b54SManivannan Sadhasivam { }
128*ae485b54SManivannan Sadhasivam };
129*ae485b54SManivannan Sadhasivam
130*ae485b54SManivannan Sadhasivam U_BOOT_DRIVER(clk_owl) = {
131*ae485b54SManivannan Sadhasivam .name = "clk_s900",
132*ae485b54SManivannan Sadhasivam .id = UCLASS_CLK,
133*ae485b54SManivannan Sadhasivam .of_match = owl_clk_ids,
134*ae485b54SManivannan Sadhasivam .ops = &owl_clk_ops,
135*ae485b54SManivannan Sadhasivam .priv_auto_alloc_size = sizeof(struct owl_clk_priv),
136*ae485b54SManivannan Sadhasivam .probe = owl_clk_probe,
137*ae485b54SManivannan Sadhasivam };
138