Merge tag 'arc-last-minute-fixes-for-2020.04' of https://gitlab.denx.de/u-boot/custod...
[oweals/u-boot.git] / drivers / clk / clk-cdce9xx.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Texas Instruments CDCE913/925/937/949 clock synthesizer driver
4  *
5  * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
6  *      Tero Kristo <t-kristo@ti.com>
7  *
8  * Based on Linux kernel clk-cdce925.c.
9  */
10
11 #include <common.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <clk-uclass.h>
15 #include <i2c.h>
16 #include <dm/device_compat.h>
17
18 #define MAX_NUMBER_OF_PLLS              4
19 #define MAX_NUMER_OF_OUTPUTS            9
20
21 #define CDCE9XX_REG_GLOBAL1             0x01
22 #define CDCE9XX_REG_Y1SPIPDIVH          0x02
23 #define CDCE9XX_REG_PDIV1L              0x03
24 #define CDCE9XX_REG_XCSEL               0x05
25
26 #define CDCE9XX_PDIV1_H_MASK            0x3
27
28 #define CDCE9XX_REG_PDIV(clk)           (0x16 + (((clk) - 1) & 1) + \
29                                          ((clk) - 1) / 2 * 0x10)
30
31 #define CDCE9XX_PDIV_MASK               0x7f
32
33 #define CDCE9XX_BYTE_TRANSFER           BIT(7)
34
35 struct cdce9xx_chip_info {
36         int num_plls;
37         int num_outputs;
38 };
39
40 struct cdce9xx_clk_data {
41         struct udevice *i2c;
42         struct cdce9xx_chip_info *chip;
43         u32 xtal_rate;
44 };
45
46 static const struct cdce9xx_chip_info cdce913_chip_info = {
47         .num_plls = 1, .num_outputs = 3,
48 };
49
50 static const struct cdce9xx_chip_info cdce925_chip_info = {
51         .num_plls = 2, .num_outputs = 5,
52 };
53
54 static const struct cdce9xx_chip_info cdce937_chip_info = {
55         .num_plls = 3, .num_outputs = 7,
56 };
57
58 static const struct cdce9xx_chip_info cdce949_chip_info = {
59         .num_plls = 4, .num_outputs = 9,
60 };
61
62 static int cdce9xx_reg_read(struct udevice *dev, u8 addr, u8 *buf)
63 {
64         struct cdce9xx_clk_data *data = dev_get_priv(dev);
65         int ret;
66
67         ret = dm_i2c_read(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, buf, 1);
68         if (ret)
69                 dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__,
70                         addr, ret);
71
72         return ret;
73 }
74
75 static int cdce9xx_reg_write(struct udevice *dev, u8 addr, u8 val)
76 {
77         struct cdce9xx_clk_data *data = dev_get_priv(dev);
78         int ret;
79
80         ret = dm_i2c_write(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, &val, 1);
81         if (ret)
82                 dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__,
83                         addr, ret);
84
85         return ret;
86 }
87
88 static int cdce9xx_clk_of_xlate(struct clk *clk,
89                                 struct ofnode_phandle_args *args)
90 {
91         struct cdce9xx_clk_data *data = dev_get_priv(clk->dev);
92
93         if (args->args_count != 1)
94                 return -EINVAL;
95
96         if (args->args[0] > data->chip->num_outputs)
97                 return -EINVAL;
98
99         clk->id = args->args[0];
100
101         return 0;
102 }
103
104 static int cdce9xx_clk_probe(struct udevice *dev)
105 {
106         struct cdce9xx_clk_data *data = dev_get_priv(dev);
107         struct cdce9xx_chip_info *chip = (void *)dev_get_driver_data(dev);
108         int ret;
109         u32 val;
110         struct clk clk;
111
112         val = (u32)dev_read_addr_ptr(dev);
113
114         ret = i2c_get_chip(dev->parent, val, 1, &data->i2c);
115         if (ret) {
116                 dev_err(dev, "I2C probe failed.\n");
117                 return ret;
118         }
119
120         data->chip = chip;
121
122         ret = clk_get_by_index(dev, 0, &clk);
123         data->xtal_rate = clk_get_rate(&clk);
124
125         val = dev_read_u32_default(dev, "xtal-load-pf", -1);
126         if (val >= 0)
127                 cdce9xx_reg_write(dev, CDCE9XX_REG_XCSEL, val << 3);
128
129         return 0;
130 }
131
132 static u16 cdce9xx_clk_get_pdiv(struct clk *clk)
133 {
134         u8 val;
135         u16 pdiv;
136         int ret;
137
138         if (clk->id == 0) {
139                 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val);
140                 if (ret)
141                         return 0;
142
143                 pdiv = (val & CDCE9XX_PDIV1_H_MASK) << 8;
144
145                 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV1L, &val);
146                 if (ret)
147                         return 0;
148
149                 pdiv |= val;
150         } else {
151                 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id),
152                                        &val);
153                 if (ret)
154                         return 0;
155
156                 pdiv = val & CDCE9XX_PDIV_MASK;
157         }
158
159         return pdiv;
160 }
161
162 static u32 cdce9xx_clk_get_parent_rate(struct clk *clk)
163 {
164         struct cdce9xx_clk_data *data = dev_get_priv(clk->dev);
165
166         return data->xtal_rate;
167 }
168
169 static ulong cdce9xx_clk_get_rate(struct clk *clk)
170 {
171         u32 parent_rate;
172         u16 pdiv;
173
174         parent_rate = cdce9xx_clk_get_parent_rate(clk);
175
176         pdiv = cdce9xx_clk_get_pdiv(clk);
177
178         return parent_rate / pdiv;
179 }
180
181 static ulong cdce9xx_clk_set_rate(struct clk *clk, ulong rate)
182 {
183         u32 parent_rate;
184         int pdiv;
185         u32 diff;
186         u8 val;
187         int ret;
188
189         parent_rate = cdce9xx_clk_get_parent_rate(clk);
190
191         pdiv = parent_rate / rate;
192
193         diff = rate - parent_rate / pdiv;
194
195         if (rate - parent_rate / (pdiv + 1) < diff)
196                 pdiv++;
197
198         if (clk->id == 0) {
199                 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val);
200                 if (ret)
201                         return ret;
202
203                 val &= ~CDCE9XX_PDIV1_H_MASK;
204
205                 val |= (pdiv >> 8);
206
207                 ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, val);
208                 if (ret)
209                         return ret;
210
211                 ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV1L,
212                                         (pdiv & 0xff));
213                 if (ret)
214                         return ret;
215         } else {
216                 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id),
217                                        &val);
218                 if (ret)
219                         return ret;
220
221                 val &= ~CDCE9XX_PDIV_MASK;
222
223                 val |= pdiv;
224
225                 ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV(clk->id),
226                                         val);
227                 if (ret)
228                         return ret;
229         }
230
231         return 0;
232 }
233
234 static const struct udevice_id cdce9xx_clk_of_match[] = {
235         { .compatible = "ti,cdce913", .data = (u32)&cdce913_chip_info },
236         { .compatible = "ti,cdce925", .data = (u32)&cdce925_chip_info },
237         { .compatible = "ti,cdce937", .data = (u32)&cdce937_chip_info },
238         { .compatible = "ti,cdce949", .data = (u32)&cdce949_chip_info },
239         { /* sentinel */ },
240 };
241
242 static const struct clk_ops cdce9xx_clk_ops = {
243         .of_xlate = cdce9xx_clk_of_xlate,
244         .get_rate = cdce9xx_clk_get_rate,
245         .set_rate = cdce9xx_clk_set_rate,
246 };
247
248 U_BOOT_DRIVER(cdce9xx_clk) = {
249         .name = "cdce9xx-clk",
250         .id = UCLASS_CLK,
251         .of_match = cdce9xx_clk_of_match,
252         .probe = cdce9xx_clk_probe,
253         .priv_auto_alloc_size = sizeof(struct cdce9xx_clk_data),
254         .ops = &cdce9xx_clk_ops,
255 };