1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for Renesas 9-series PCIe clock generator driver
5 * The following series can be supported:
6 * - 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ
12 * Copyright (C) 2022 Marek Vasut <marex@denx.de>
15 #include <linux/clk-provider.h>
16 #include <linux/i2c.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/module.h>
20 #include <linux/regmap.h>
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_DEFAULT RS9_REG_SS_AMP_0V8
29 #define RS9_REG_SS_AMP_MASK 0x3
30 #define RS9_REG_SS_SSC_100 0
31 #define RS9_REG_SS_SSC_M025 (1 << 3)
32 #define RS9_REG_SS_SSC_M050 (3 << 3)
33 #define RS9_REG_SS_SSC_DEFAULT RS9_REG_SS_SSC_100
34 #define RS9_REG_SS_SSC_MASK (3 << 3)
35 #define RS9_REG_SS_SSC_LOCK BIT(5)
36 #define RS9_REG_SR 0x2
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
48 #define RS9_REG_VID_MASK GENMASK(3, 0)
49 #define RS9_REG_VID_IDT 0x01
51 #define RS9_REG_DID_TYPE_FGV (0x0 << RS9_REG_DID_TYPE_SHIFT)
52 #define RS9_REG_DID_TYPE_DBV (0x1 << RS9_REG_DID_TYPE_SHIFT)
53 #define RS9_REG_DID_TYPE_DMV (0x2 << RS9_REG_DID_TYPE_SHIFT)
54 #define RS9_REG_DID_TYPE_SHIFT 0x6
56 /* Structure to describe features of a particular 9-series model */
57 struct rs9_chip_info
{
58 unsigned int num_clks
;
63 struct rs9_driver_data
{
64 struct i2c_client
*client
;
65 struct regmap
*regmap
;
66 const struct rs9_chip_info
*chip_info
;
67 struct clk_hw
*clk_dif
[4];
74 * Renesas 9-series i2c regmap
76 static const struct regmap_range rs9_readable_ranges
[] = {
77 regmap_reg_range(RS9_REG_OE
, RS9_REG_REF
),
78 regmap_reg_range(RS9_REG_VID
, RS9_REG_BCP
),
81 static const struct regmap_access_table rs9_readable_table
= {
82 .yes_ranges
= rs9_readable_ranges
,
83 .n_yes_ranges
= ARRAY_SIZE(rs9_readable_ranges
),
86 static const struct regmap_range rs9_writeable_ranges
[] = {
87 regmap_reg_range(RS9_REG_OE
, RS9_REG_REF
),
88 regmap_reg_range(RS9_REG_BCP
, RS9_REG_BCP
),
91 static const struct regmap_access_table rs9_writeable_table
= {
92 .yes_ranges
= rs9_writeable_ranges
,
93 .n_yes_ranges
= ARRAY_SIZE(rs9_writeable_ranges
),
96 static int rs9_regmap_i2c_write(void *context
,
97 unsigned int reg
, unsigned int val
)
99 struct i2c_client
*i2c
= context
;
100 const u8 data
[3] = { reg
, 1, val
};
101 const int count
= ARRAY_SIZE(data
);
104 ret
= i2c_master_send(i2c
, data
, count
);
113 static int rs9_regmap_i2c_read(void *context
,
114 unsigned int reg
, unsigned int *val
)
116 struct i2c_client
*i2c
= context
;
117 struct i2c_msg xfer
[2];
122 xfer
[0].addr
= i2c
->addr
;
125 xfer
[0].buf
= (void *)&txdata
;
127 xfer
[1].addr
= i2c
->addr
;
128 xfer
[1].flags
= I2C_M_RD
;
130 xfer
[1].buf
= (void *)rxdata
;
132 ret
= i2c_transfer(i2c
->adapter
, xfer
, 2);
139 * Byte 0 is transfer length, which is always 1 due
140 * to BCP register programming to 1 in rs9_probe(),
141 * ignore it and use data from Byte 1.
147 static const struct regmap_config rs9_regmap_config
= {
150 .cache_type
= REGCACHE_FLAT
,
151 .max_register
= RS9_REG_BCP
,
152 .num_reg_defaults_raw
= 0x8,
153 .rd_table
= &rs9_readable_table
,
154 .wr_table
= &rs9_writeable_table
,
155 .reg_write
= rs9_regmap_i2c_write
,
156 .reg_read
= rs9_regmap_i2c_read
,
159 static u8
rs9_calc_dif(const struct rs9_driver_data
*rs9
, int idx
)
162 * On 9FGV0241, the DIF OE0 is BIT(1) and DIF OE(1) is BIT(2),
163 * on 9FGV0441 and 9FGV0841 the DIF OE0 is BIT(0) and so on.
164 * Increment the index in the 9FGV0241 special case here.
166 return BIT(idx
+ rs9
->chip_info
->outshift
);
169 static int rs9_get_output_config(struct rs9_driver_data
*rs9
, int idx
)
171 struct i2c_client
*client
= rs9
->client
;
172 u8 dif
= rs9_calc_dif(rs9
, idx
);
173 unsigned char name
[5] = "DIF0";
174 struct device_node
*np
;
179 rs9
->clk_dif_sr
|= dif
;
181 snprintf(name
, 5, "DIF%d", idx
);
182 np
= of_get_child_by_name(client
->dev
.of_node
, name
);
186 /* Output clock slew rate */
187 ret
= of_property_read_u32(np
, "renesas,slew-rate", &sr
);
190 if (sr
== 2000000) { /* 2V/ns */
191 rs9
->clk_dif_sr
&= ~dif
;
192 } else if (sr
== 3000000) { /* 3V/ns (default) */
193 rs9
->clk_dif_sr
|= dif
;
195 ret
= dev_err_probe(&client
->dev
, -EINVAL
,
196 "Invalid renesas,slew-rate value\n");
202 static int rs9_get_common_config(struct rs9_driver_data
*rs9
)
204 struct i2c_client
*client
= rs9
->client
;
205 struct device_node
*np
= client
->dev
.of_node
;
206 unsigned int amp
, ssc
;
210 rs9
->pll_amplitude
= RS9_REG_SS_AMP_DEFAULT
;
211 rs9
->pll_ssc
= RS9_REG_SS_SSC_DEFAULT
;
213 /* Output clock amplitude */
214 ret
= of_property_read_u32(np
, "renesas,out-amplitude-microvolt",
217 if (amp
== 600000) /* 0.6V */
218 rs9
->pll_amplitude
= RS9_REG_SS_AMP_0V6
;
219 else if (amp
== 700000) /* 0.7V (default) */
220 rs9
->pll_amplitude
= RS9_REG_SS_AMP_0V7
;
221 else if (amp
== 800000) /* 0.8V */
222 rs9
->pll_amplitude
= RS9_REG_SS_AMP_0V8
;
223 else if (amp
== 900000) /* 0.9V */
224 rs9
->pll_amplitude
= RS9_REG_SS_AMP_0V9
;
226 return dev_err_probe(&client
->dev
, -EINVAL
,
227 "Invalid renesas,out-amplitude-microvolt value\n");
230 /* Output clock spread spectrum */
231 ret
= of_property_read_u32(np
, "renesas,out-spread-spectrum", &ssc
);
233 if (ssc
== 100000) /* 100% ... no spread (default) */
234 rs9
->pll_ssc
= RS9_REG_SS_SSC_100
;
235 else if (ssc
== 99750) /* -0.25% ... down spread */
236 rs9
->pll_ssc
= RS9_REG_SS_SSC_M025
;
237 else if (ssc
== 99500) /* -0.50% ... down spread */
238 rs9
->pll_ssc
= RS9_REG_SS_SSC_M050
;
240 return dev_err_probe(&client
->dev
, -EINVAL
,
241 "Invalid renesas,out-spread-spectrum value\n");
247 static void rs9_update_config(struct rs9_driver_data
*rs9
)
251 /* If amplitude is non-default, update it. */
252 if (rs9
->pll_amplitude
!= RS9_REG_SS_AMP_DEFAULT
) {
253 regmap_update_bits(rs9
->regmap
, RS9_REG_SS
, RS9_REG_SS_AMP_MASK
,
257 /* If SSC is non-default, update it. */
258 if (rs9
->pll_ssc
!= RS9_REG_SS_SSC_DEFAULT
) {
259 regmap_update_bits(rs9
->regmap
, RS9_REG_SS
, RS9_REG_SS_SSC_MASK
,
263 for (i
= 0; i
< rs9
->chip_info
->num_clks
; i
++) {
264 u8 dif
= rs9_calc_dif(rs9
, i
);
266 if (rs9
->clk_dif_sr
& dif
)
269 regmap_update_bits(rs9
->regmap
, RS9_REG_SR
, dif
,
270 rs9
->clk_dif_sr
& dif
);
274 static struct clk_hw
*
275 rs9_of_clk_get(struct of_phandle_args
*clkspec
, void *data
)
277 struct rs9_driver_data
*rs9
= data
;
278 unsigned int idx
= clkspec
->args
[0];
280 return rs9
->clk_dif
[idx
];
283 static int rs9_probe(struct i2c_client
*client
)
285 unsigned char name
[5] = "DIF0";
286 struct rs9_driver_data
*rs9
;
287 unsigned int vid
, did
;
291 rs9
= devm_kzalloc(&client
->dev
, sizeof(*rs9
), GFP_KERNEL
);
295 i2c_set_clientdata(client
, rs9
);
296 rs9
->client
= client
;
297 rs9
->chip_info
= i2c_get_match_data(client
);
301 /* Fetch common configuration from DT (if specified) */
302 ret
= rs9_get_common_config(rs9
);
306 /* Fetch DIFx output configuration from DT (if specified) */
307 for (i
= 0; i
< rs9
->chip_info
->num_clks
; i
++) {
308 ret
= rs9_get_output_config(rs9
, i
);
313 rs9
->regmap
= devm_regmap_init(&client
->dev
, NULL
,
314 client
, &rs9_regmap_config
);
315 if (IS_ERR(rs9
->regmap
))
316 return dev_err_probe(&client
->dev
, PTR_ERR(rs9
->regmap
),
317 "Failed to allocate register map\n");
319 /* Always read back 1 Byte via I2C */
320 ret
= regmap_write(rs9
->regmap
, RS9_REG_BCP
, 1);
324 ret
= regmap_read(rs9
->regmap
, RS9_REG_VID
, &vid
);
328 ret
= regmap_read(rs9
->regmap
, RS9_REG_DID
, &did
);
332 vid
&= RS9_REG_VID_MASK
;
333 if (vid
!= RS9_REG_VID_IDT
|| did
!= rs9
->chip_info
->did
)
334 return dev_err_probe(&client
->dev
, -ENODEV
,
335 "Incorrect VID/DID: %#02x, %#02x. Expected %#02x, %#02x\n",
336 vid
, did
, RS9_REG_VID_IDT
,
337 rs9
->chip_info
->did
);
340 for (i
= 0; i
< rs9
->chip_info
->num_clks
; i
++) {
341 snprintf(name
, 5, "DIF%d", i
);
342 hw
= devm_clk_hw_register_fixed_factor_index(&client
->dev
, name
,
347 rs9
->clk_dif
[i
] = hw
;
350 ret
= devm_of_clk_add_hw_provider(&client
->dev
, rs9_of_clk_get
, rs9
);
352 rs9_update_config(rs9
);
357 static int __maybe_unused
rs9_suspend(struct device
*dev
)
359 struct rs9_driver_data
*rs9
= dev_get_drvdata(dev
);
361 regcache_cache_only(rs9
->regmap
, true);
362 regcache_mark_dirty(rs9
->regmap
);
367 static int __maybe_unused
rs9_resume(struct device
*dev
)
369 struct rs9_driver_data
*rs9
= dev_get_drvdata(dev
);
372 regcache_cache_only(rs9
->regmap
, false);
373 ret
= regcache_sync(rs9
->regmap
);
375 dev_err(dev
, "Failed to restore register map: %d\n", ret
);
379 static const struct rs9_chip_info renesas_9fgv0241_info
= {
382 .did
= RS9_REG_DID_TYPE_FGV
| 0x02,
385 static const struct rs9_chip_info renesas_9fgv0441_info
= {
388 .did
= RS9_REG_DID_TYPE_FGV
| 0x04,
391 static const struct rs9_chip_info renesas_9fgv0841_info
= {
394 .did
= RS9_REG_DID_TYPE_FGV
| 0x08,
397 static const struct i2c_device_id rs9_id
[] = {
398 { "9fgv0241", .driver_data
= (kernel_ulong_t
)&renesas_9fgv0241_info
},
399 { "9fgv0441", .driver_data
= (kernel_ulong_t
)&renesas_9fgv0441_info
},
400 { "9fgv0841", .driver_data
= (kernel_ulong_t
)&renesas_9fgv0841_info
},
403 MODULE_DEVICE_TABLE(i2c
, rs9_id
);
405 static const struct of_device_id clk_rs9_of_match
[] = {
406 { .compatible
= "renesas,9fgv0241", .data
= &renesas_9fgv0241_info
},
407 { .compatible
= "renesas,9fgv0441", .data
= &renesas_9fgv0441_info
},
408 { .compatible
= "renesas,9fgv0841", .data
= &renesas_9fgv0841_info
},
411 MODULE_DEVICE_TABLE(of
, clk_rs9_of_match
);
413 static SIMPLE_DEV_PM_OPS(rs9_pm_ops
, rs9_suspend
, rs9_resume
);
415 static struct i2c_driver rs9_driver
= {
417 .name
= "clk-renesas-pcie-9series",
419 .of_match_table
= clk_rs9_of_match
,
424 module_i2c_driver(rs9_driver
);
426 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
427 MODULE_DESCRIPTION("Renesas 9-series PCIe clock generator driver");
428 MODULE_LICENSE("GPL");