1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Driver for Renesas 9-series PCIe clock generator driver |
4 | * |
5 | * The following series can be supported: |
6 | * - 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ |
7 | * Currently supported: |
8 | * - 9FGV0241 |
9 | * - 9FGV0441 |
10 | * - 9FGV0841 |
11 | * |
12 | * Copyright (C) 2022 Marek Vasut <marex@denx.de> |
13 | */ |
14 | |
15 | #include <linux/clk-provider.h> |
16 | #include <linux/i2c.h> |
17 | #include <linux/mod_devicetable.h> |
18 | #include <linux/module.h> |
19 | #include <linux/of.h> |
20 | #include <linux/regmap.h> |
21 | |
22 | #define RS9_REG_OE 0x0 |
23 | #define RS9_REG_SS 0x1 |
24 | #define RS9_REG_SS_AMP_0V6 0x0 |
25 | #define RS9_REG_SS_AMP_0V7 0x1 |
26 | #define RS9_REG_SS_AMP_0V8 0x2 |
27 | #define RS9_REG_SS_AMP_0V9 0x3 |
28 | #define RS9_REG_SS_AMP_MASK 0x3 |
29 | #define RS9_REG_SS_SSC_100 0 |
30 | #define RS9_REG_SS_SSC_M025 (1 << 3) |
31 | #define RS9_REG_SS_SSC_M050 (3 << 3) |
32 | #define RS9_REG_SS_SSC_MASK (3 << 3) |
33 | #define RS9_REG_SS_SSC_LOCK BIT(5) |
34 | #define RS9_REG_SR 0x2 |
35 | #define RS9_REG_REF 0x3 |
36 | #define RS9_REG_REF_OE BIT(4) |
37 | #define RS9_REG_REF_OD BIT(5) |
38 | #define RS9_REG_REF_SR_SLOWEST 0 |
39 | #define RS9_REG_REF_SR_SLOW (1 << 6) |
40 | #define RS9_REG_REF_SR_FAST (2 << 6) |
41 | #define RS9_REG_REF_SR_FASTER (3 << 6) |
42 | #define RS9_REG_VID 0x5 |
43 | #define RS9_REG_DID 0x6 |
44 | #define RS9_REG_BCP 0x7 |
45 | |
46 | #define RS9_REG_VID_MASK GENMASK(3, 0) |
47 | #define RS9_REG_VID_IDT 0x01 |
48 | |
49 | #define RS9_REG_DID_TYPE_FGV (0x0 << RS9_REG_DID_TYPE_SHIFT) |
50 | #define RS9_REG_DID_TYPE_DBV (0x1 << RS9_REG_DID_TYPE_SHIFT) |
51 | #define RS9_REG_DID_TYPE_DMV (0x2 << RS9_REG_DID_TYPE_SHIFT) |
52 | #define RS9_REG_DID_TYPE_SHIFT 0x6 |
53 | |
54 | /* Structure to describe features of a particular 9-series model */ |
55 | struct rs9_chip_info { |
56 | unsigned int num_clks; |
57 | u8 outshift; |
58 | u8 did; |
59 | }; |
60 | |
61 | struct rs9_driver_data { |
62 | struct i2c_client *client; |
63 | struct regmap *regmap; |
64 | const struct rs9_chip_info *chip_info; |
65 | struct clk_hw *clk_dif[4]; |
66 | u8 pll_amplitude; |
67 | u8 pll_ssc; |
68 | u8 clk_dif_sr; |
69 | }; |
70 | |
71 | /* |
72 | * Renesas 9-series i2c regmap |
73 | */ |
74 | static const struct regmap_range rs9_readable_ranges[] = { |
75 | regmap_reg_range(RS9_REG_OE, RS9_REG_REF), |
76 | regmap_reg_range(RS9_REG_VID, RS9_REG_BCP), |
77 | }; |
78 | |
79 | static const struct regmap_access_table rs9_readable_table = { |
80 | .yes_ranges = rs9_readable_ranges, |
81 | .n_yes_ranges = ARRAY_SIZE(rs9_readable_ranges), |
82 | }; |
83 | |
84 | static const struct regmap_range rs9_writeable_ranges[] = { |
85 | regmap_reg_range(RS9_REG_OE, RS9_REG_REF), |
86 | regmap_reg_range(RS9_REG_BCP, RS9_REG_BCP), |
87 | }; |
88 | |
89 | static const struct regmap_access_table rs9_writeable_table = { |
90 | .yes_ranges = rs9_writeable_ranges, |
91 | .n_yes_ranges = ARRAY_SIZE(rs9_writeable_ranges), |
92 | }; |
93 | |
94 | static int rs9_regmap_i2c_write(void *context, |
95 | unsigned int reg, unsigned int val) |
96 | { |
97 | struct i2c_client *i2c = context; |
98 | const u8 data[3] = { reg, 1, val }; |
99 | const int count = ARRAY_SIZE(data); |
100 | int ret; |
101 | |
102 | ret = i2c_master_send(client: i2c, buf: data, count); |
103 | if (ret == count) |
104 | return 0; |
105 | else if (ret < 0) |
106 | return ret; |
107 | else |
108 | return -EIO; |
109 | } |
110 | |
111 | static int rs9_regmap_i2c_read(void *context, |
112 | unsigned int reg, unsigned int *val) |
113 | { |
114 | struct i2c_client *i2c = context; |
115 | struct i2c_msg xfer[2]; |
116 | u8 txdata = reg; |
117 | u8 rxdata[2]; |
118 | int ret; |
119 | |
120 | xfer[0].addr = i2c->addr; |
121 | xfer[0].flags = 0; |
122 | xfer[0].len = 1; |
123 | xfer[0].buf = (void *)&txdata; |
124 | |
125 | xfer[1].addr = i2c->addr; |
126 | xfer[1].flags = I2C_M_RD; |
127 | xfer[1].len = 2; |
128 | xfer[1].buf = (void *)rxdata; |
129 | |
130 | ret = i2c_transfer(adap: i2c->adapter, msgs: xfer, num: 2); |
131 | if (ret < 0) |
132 | return ret; |
133 | if (ret != 2) |
134 | return -EIO; |
135 | |
136 | /* |
137 | * Byte 0 is transfer length, which is always 1 due |
138 | * to BCP register programming to 1 in rs9_probe(), |
139 | * ignore it and use data from Byte 1. |
140 | */ |
141 | *val = rxdata[1]; |
142 | return 0; |
143 | } |
144 | |
145 | static const struct regmap_config rs9_regmap_config = { |
146 | .reg_bits = 8, |
147 | .val_bits = 8, |
148 | .cache_type = REGCACHE_FLAT, |
149 | .max_register = RS9_REG_BCP, |
150 | .num_reg_defaults_raw = 0x8, |
151 | .rd_table = &rs9_readable_table, |
152 | .wr_table = &rs9_writeable_table, |
153 | .reg_write = rs9_regmap_i2c_write, |
154 | .reg_read = rs9_regmap_i2c_read, |
155 | }; |
156 | |
157 | static u8 rs9_calc_dif(const struct rs9_driver_data *rs9, int idx) |
158 | { |
159 | /* |
160 | * On 9FGV0241, the DIF OE0 is BIT(1) and DIF OE(1) is BIT(2), |
161 | * on 9FGV0441 and 9FGV0841 the DIF OE0 is BIT(0) and so on. |
162 | * Increment the index in the 9FGV0241 special case here. |
163 | */ |
164 | return BIT(idx + rs9->chip_info->outshift); |
165 | } |
166 | |
167 | static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx) |
168 | { |
169 | struct i2c_client *client = rs9->client; |
170 | u8 dif = rs9_calc_dif(rs9, idx); |
171 | unsigned char name[5] = "DIF0" ; |
172 | struct device_node *np; |
173 | int ret; |
174 | u32 sr; |
175 | |
176 | /* Set defaults */ |
177 | rs9->clk_dif_sr |= dif; |
178 | |
179 | snprintf(buf: name, size: 5, fmt: "DIF%d" , idx); |
180 | np = of_get_child_by_name(node: client->dev.of_node, name); |
181 | if (!np) |
182 | return 0; |
183 | |
184 | /* Output clock slew rate */ |
185 | ret = of_property_read_u32(np, propname: "renesas,slew-rate" , out_value: &sr); |
186 | of_node_put(node: np); |
187 | if (!ret) { |
188 | if (sr == 2000000) { /* 2V/ns */ |
189 | rs9->clk_dif_sr &= ~dif; |
190 | } else if (sr == 3000000) { /* 3V/ns (default) */ |
191 | rs9->clk_dif_sr |= dif; |
192 | } else |
193 | ret = dev_err_probe(dev: &client->dev, err: -EINVAL, |
194 | fmt: "Invalid renesas,slew-rate value\n" ); |
195 | } |
196 | |
197 | return ret; |
198 | } |
199 | |
200 | static int rs9_get_common_config(struct rs9_driver_data *rs9) |
201 | { |
202 | struct i2c_client *client = rs9->client; |
203 | struct device_node *np = client->dev.of_node; |
204 | unsigned int amp, ssc; |
205 | int ret; |
206 | |
207 | /* Set defaults */ |
208 | rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; |
209 | rs9->pll_ssc = RS9_REG_SS_SSC_100; |
210 | |
211 | /* Output clock amplitude */ |
212 | ret = of_property_read_u32(np, propname: "renesas,out-amplitude-microvolt" , |
213 | out_value: &); |
214 | if (!ret) { |
215 | if (amp == 600000) /* 0.6V */ |
216 | rs9->pll_amplitude = RS9_REG_SS_AMP_0V6; |
217 | else if (amp == 700000) /* 0.7V (default) */ |
218 | rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; |
219 | else if (amp == 800000) /* 0.8V */ |
220 | rs9->pll_amplitude = RS9_REG_SS_AMP_0V8; |
221 | else if (amp == 900000) /* 0.9V */ |
222 | rs9->pll_amplitude = RS9_REG_SS_AMP_0V9; |
223 | else |
224 | return dev_err_probe(dev: &client->dev, err: -EINVAL, |
225 | fmt: "Invalid renesas,out-amplitude-microvolt value\n" ); |
226 | } |
227 | |
228 | /* Output clock spread spectrum */ |
229 | ret = of_property_read_u32(np, propname: "renesas,out-spread-spectrum" , out_value: &ssc); |
230 | if (!ret) { |
231 | if (ssc == 100000) /* 100% ... no spread (default) */ |
232 | rs9->pll_ssc = RS9_REG_SS_SSC_100; |
233 | else if (ssc == 99750) /* -0.25% ... down spread */ |
234 | rs9->pll_ssc = RS9_REG_SS_SSC_M025; |
235 | else if (ssc == 99500) /* -0.50% ... down spread */ |
236 | rs9->pll_ssc = RS9_REG_SS_SSC_M050; |
237 | else |
238 | return dev_err_probe(dev: &client->dev, err: -EINVAL, |
239 | fmt: "Invalid renesas,out-spread-spectrum value\n" ); |
240 | } |
241 | |
242 | return 0; |
243 | } |
244 | |
245 | static void rs9_update_config(struct rs9_driver_data *rs9) |
246 | { |
247 | int i; |
248 | |
249 | /* If amplitude is non-default, update it. */ |
250 | if (rs9->pll_amplitude != RS9_REG_SS_AMP_0V7) { |
251 | regmap_update_bits(map: rs9->regmap, RS9_REG_SS, RS9_REG_SS_AMP_MASK, |
252 | val: rs9->pll_amplitude); |
253 | } |
254 | |
255 | /* If SSC is non-default, update it. */ |
256 | if (rs9->pll_ssc != RS9_REG_SS_SSC_100) { |
257 | regmap_update_bits(map: rs9->regmap, RS9_REG_SS, RS9_REG_SS_SSC_MASK, |
258 | val: rs9->pll_ssc); |
259 | } |
260 | |
261 | for (i = 0; i < rs9->chip_info->num_clks; i++) { |
262 | u8 dif = rs9_calc_dif(rs9, idx: i); |
263 | |
264 | if (rs9->clk_dif_sr & dif) |
265 | continue; |
266 | |
267 | regmap_update_bits(map: rs9->regmap, RS9_REG_SR, mask: dif, |
268 | val: rs9->clk_dif_sr & dif); |
269 | } |
270 | } |
271 | |
272 | static struct clk_hw * |
273 | rs9_of_clk_get(struct of_phandle_args *clkspec, void *data) |
274 | { |
275 | struct rs9_driver_data *rs9 = data; |
276 | unsigned int idx = clkspec->args[0]; |
277 | |
278 | return rs9->clk_dif[idx]; |
279 | } |
280 | |
281 | static int rs9_probe(struct i2c_client *client) |
282 | { |
283 | unsigned char name[5] = "DIF0" ; |
284 | struct rs9_driver_data *rs9; |
285 | unsigned int vid, did; |
286 | struct clk_hw *hw; |
287 | int i, ret; |
288 | |
289 | rs9 = devm_kzalloc(dev: &client->dev, size: sizeof(*rs9), GFP_KERNEL); |
290 | if (!rs9) |
291 | return -ENOMEM; |
292 | |
293 | i2c_set_clientdata(client, data: rs9); |
294 | rs9->client = client; |
295 | rs9->chip_info = i2c_get_match_data(client); |
296 | if (!rs9->chip_info) |
297 | return -EINVAL; |
298 | |
299 | /* Fetch common configuration from DT (if specified) */ |
300 | ret = rs9_get_common_config(rs9); |
301 | if (ret) |
302 | return ret; |
303 | |
304 | /* Fetch DIFx output configuration from DT (if specified) */ |
305 | for (i = 0; i < rs9->chip_info->num_clks; i++) { |
306 | ret = rs9_get_output_config(rs9, idx: i); |
307 | if (ret) |
308 | return ret; |
309 | } |
310 | |
311 | rs9->regmap = devm_regmap_init(&client->dev, NULL, |
312 | client, &rs9_regmap_config); |
313 | if (IS_ERR(ptr: rs9->regmap)) |
314 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: rs9->regmap), |
315 | fmt: "Failed to allocate register map\n" ); |
316 | |
317 | /* Always read back 1 Byte via I2C */ |
318 | ret = regmap_write(map: rs9->regmap, RS9_REG_BCP, val: 1); |
319 | if (ret < 0) |
320 | return ret; |
321 | |
322 | ret = regmap_read(map: rs9->regmap, RS9_REG_VID, val: &vid); |
323 | if (ret < 0) |
324 | return ret; |
325 | |
326 | ret = regmap_read(map: rs9->regmap, RS9_REG_DID, val: &did); |
327 | if (ret < 0) |
328 | return ret; |
329 | |
330 | vid &= RS9_REG_VID_MASK; |
331 | if (vid != RS9_REG_VID_IDT || did != rs9->chip_info->did) |
332 | return dev_err_probe(dev: &client->dev, err: -ENODEV, |
333 | fmt: "Incorrect VID/DID: %#02x, %#02x. Expected %#02x, %#02x\n" , |
334 | vid, did, RS9_REG_VID_IDT, |
335 | rs9->chip_info->did); |
336 | |
337 | /* Register clock */ |
338 | for (i = 0; i < rs9->chip_info->num_clks; i++) { |
339 | snprintf(buf: name, size: 5, fmt: "DIF%d" , i); |
340 | hw = devm_clk_hw_register_fixed_factor_index(dev: &client->dev, name, |
341 | index: 0, flags: 0, mult: 4, div: 1); |
342 | if (IS_ERR(ptr: hw)) |
343 | return PTR_ERR(ptr: hw); |
344 | |
345 | rs9->clk_dif[i] = hw; |
346 | } |
347 | |
348 | ret = devm_of_clk_add_hw_provider(dev: &client->dev, get: rs9_of_clk_get, data: rs9); |
349 | if (!ret) |
350 | rs9_update_config(rs9); |
351 | |
352 | return ret; |
353 | } |
354 | |
355 | static int __maybe_unused rs9_suspend(struct device *dev) |
356 | { |
357 | struct rs9_driver_data *rs9 = dev_get_drvdata(dev); |
358 | |
359 | regcache_cache_only(map: rs9->regmap, enable: true); |
360 | regcache_mark_dirty(map: rs9->regmap); |
361 | |
362 | return 0; |
363 | } |
364 | |
365 | static int __maybe_unused rs9_resume(struct device *dev) |
366 | { |
367 | struct rs9_driver_data *rs9 = dev_get_drvdata(dev); |
368 | int ret; |
369 | |
370 | regcache_cache_only(map: rs9->regmap, enable: false); |
371 | ret = regcache_sync(map: rs9->regmap); |
372 | if (ret) |
373 | dev_err(dev, "Failed to restore register map: %d\n" , ret); |
374 | return ret; |
375 | } |
376 | |
377 | static const struct rs9_chip_info renesas_9fgv0241_info = { |
378 | .num_clks = 2, |
379 | .outshift = 1, |
380 | .did = RS9_REG_DID_TYPE_FGV | 0x02, |
381 | }; |
382 | |
383 | static const struct rs9_chip_info renesas_9fgv0441_info = { |
384 | .num_clks = 4, |
385 | .outshift = 0, |
386 | .did = RS9_REG_DID_TYPE_FGV | 0x04, |
387 | }; |
388 | |
389 | static const struct rs9_chip_info renesas_9fgv0841_info = { |
390 | .num_clks = 8, |
391 | .outshift = 0, |
392 | .did = RS9_REG_DID_TYPE_FGV | 0x08, |
393 | }; |
394 | |
395 | static const struct i2c_device_id rs9_id[] = { |
396 | { "9fgv0241" , .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info }, |
397 | { "9fgv0441" , .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info }, |
398 | { "9fgv0841" , .driver_data = (kernel_ulong_t)&renesas_9fgv0841_info }, |
399 | { } |
400 | }; |
401 | MODULE_DEVICE_TABLE(i2c, rs9_id); |
402 | |
403 | static const struct of_device_id clk_rs9_of_match[] = { |
404 | { .compatible = "renesas,9fgv0241" , .data = &renesas_9fgv0241_info }, |
405 | { .compatible = "renesas,9fgv0441" , .data = &renesas_9fgv0441_info }, |
406 | { .compatible = "renesas,9fgv0841" , .data = &renesas_9fgv0841_info }, |
407 | { } |
408 | }; |
409 | MODULE_DEVICE_TABLE(of, clk_rs9_of_match); |
410 | |
411 | static SIMPLE_DEV_PM_OPS(rs9_pm_ops, rs9_suspend, rs9_resume); |
412 | |
413 | static struct i2c_driver rs9_driver = { |
414 | .driver = { |
415 | .name = "clk-renesas-pcie-9series" , |
416 | .pm = &rs9_pm_ops, |
417 | .of_match_table = clk_rs9_of_match, |
418 | }, |
419 | .probe = rs9_probe, |
420 | .id_table = rs9_id, |
421 | }; |
422 | module_i2c_driver(rs9_driver); |
423 | |
424 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>" ); |
425 | MODULE_DESCRIPTION("Renesas 9-series PCIe clock generator driver" ); |
426 | MODULE_LICENSE("GPL" ); |
427 | |