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