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