Revision | eafc727f106e09a9ded921f5dc23daa2015cad3c (tree) |
---|---|
Time | 2020-07-26 17:58:23 |
Author | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
Add RX62N CPG
@@ -187,4 +187,10 @@ config SANDBOX_CLK_CCF | ||
187 | 187 | Enable this option if you want to test the Linux kernel's Common |
188 | 188 | Clock Framework [CCF] code in U-Boot's Sandbox clock driver. |
189 | 189 | |
190 | +config CLK_RX62N | |
191 | + bool "Enable clock driver support for Renesas RX62N" | |
192 | + depends on CLK && RX | |
193 | + help | |
194 | + Enable this to support the clocks on Renesas RX62N MCU. | |
195 | + | |
190 | 196 | endmenu |
@@ -47,3 +47,4 @@ obj-$(CONFIG_STM32H7) += clk_stm32h7.o | ||
47 | 47 | obj-$(CONFIG_CLK_TI_SCI) += clk-ti-sci.o |
48 | 48 | obj-$(CONFIG_CLK_VERSAL) += clk_versal.o |
49 | 49 | obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o |
50 | +obj-$(CONFIG_CLK_RX62N) += rx62n-cpg.o |
@@ -0,0 +1,109 @@ | ||
1 | +// SPDX-License-Identifier: GPL-2.0+ | |
2 | +/* | |
3 | + * Copyright (c) 2020 Yoshinori Sato <ysato@users.sourceforge.jp> | |
4 | + */ | |
5 | + | |
6 | +#include <common.h> | |
7 | +#include <clk-uclass.h> | |
8 | +#include <div64.h> | |
9 | +#include <dm.h> | |
10 | +#include <linux/err.h> | |
11 | +#include <asm/io.h> | |
12 | + | |
13 | +struct rx62n_cpg_priv { | |
14 | + struct clk parent; | |
15 | + void *base; | |
16 | + int out; | |
17 | +}; | |
18 | + | |
19 | +static ulong rx62n_cpg_get_rate(struct clk *clk) | |
20 | +{ | |
21 | + struct rx62n_cpg_priv *priv = dev_get_priv(clk->dev); | |
22 | + u64 rate; | |
23 | + int shift; | |
24 | + int divrate; | |
25 | + | |
26 | + rate = clk_get_rate(&priv->parent); | |
27 | + if (IS_ERR_VALUE(rate)) | |
28 | + return rate; | |
29 | + shift = 8 * (priv->out + 1); | |
30 | + divrate = readl(priv->base); | |
31 | + divrate = (divrate >> shift) & 0x0f; | |
32 | + divrate = 1 << divrate; | |
33 | + | |
34 | + do_div(rate, divrate); | |
35 | + return rate; | |
36 | +} | |
37 | + | |
38 | +static ulong rx62n_cpg_set_rate(struct clk *clk, ulong rate) | |
39 | +{ | |
40 | + struct rx62n_cpg_priv *priv = dev_get_priv(clk->dev); | |
41 | + u32 sckcr; | |
42 | + int shift; | |
43 | + u64 divrate; | |
44 | + int i; | |
45 | + | |
46 | + divrate = clk_get_rate(&priv->parent); | |
47 | + if (IS_ERR_VALUE(divrate)) | |
48 | + return divrate; | |
49 | + | |
50 | + shift = 8 * (priv->out + 1); | |
51 | + do_div(divrate, rate); | |
52 | + for (i = 0; i < 4; i++) { | |
53 | + if (divrate == 1) { | |
54 | + sckcr = readl(priv->base); | |
55 | + sckcr &= ~(0x0f << shift); | |
56 | + sckcr |= i << shift; | |
57 | + writel(sckcr, priv->base); | |
58 | + return 0; | |
59 | + } | |
60 | + divrate >>= 1; | |
61 | + } | |
62 | + return -EINVAL; | |
63 | +} | |
64 | + | |
65 | +const struct clk_ops rx62n_cpg_ops = { | |
66 | + .get_rate = rx62n_cpg_get_rate, | |
67 | + .set_rate = rx62n_cpg_set_rate, | |
68 | +}; | |
69 | + | |
70 | + | |
71 | +static int rx62n_cpg_probe(struct udevice *dev) | |
72 | +{ | |
73 | + struct rx62n_cpg_priv *priv = dev_get_priv(dev); | |
74 | + int err; | |
75 | + fdt_addr_t addr; | |
76 | + static char *names[] = {"pck", "bck", "ick"}; | |
77 | + int id; | |
78 | + | |
79 | + addr = dev_read_addr(dev); | |
80 | + if (addr == FDT_ADDR_T_NONE) | |
81 | + return -EINVAL; | |
82 | + priv->base = (void *)addr; | |
83 | + err = clk_get_by_index(dev, 0, &priv->parent); | |
84 | + if (err) | |
85 | + return err; | |
86 | + for (id = 0; id < 3; id++) { | |
87 | + if (strcmp(dev->name, names[id]) == 0) { | |
88 | + priv->out = id; | |
89 | + break; | |
90 | + } | |
91 | + } | |
92 | + return 0; | |
93 | +} | |
94 | + | |
95 | +static const struct udevice_id rx62n_cpg_ids[] = { | |
96 | + { | |
97 | + .compatible = "renesas,rx62n-cpg", | |
98 | + }, | |
99 | + { } | |
100 | +}; | |
101 | + | |
102 | +U_BOOT_DRIVER(rx62n_cpg) = { | |
103 | + .name = "rx62n_cpg", | |
104 | + .id = UCLASS_CLK, | |
105 | + .of_match = rx62n_cpg_ids, | |
106 | + .ops = &rx62n_cpg_ops, | |
107 | + .probe = rx62n_cpg_probe, | |
108 | + .priv_auto_alloc_size = sizeof(struct rx62n_cpg_priv), | |
109 | +}; |