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