xref: /linux/drivers/dpll/zl3073x/core.c (revision 2df8e64e01c10a4b75ea7797629f9e764a840eb0)
1*2df8e64eSIvan Vecera // SPDX-License-Identifier: GPL-2.0-only
2*2df8e64eSIvan Vecera 
3*2df8e64eSIvan Vecera #include <linux/array_size.h>
4*2df8e64eSIvan Vecera #include <linux/bitfield.h>
5*2df8e64eSIvan Vecera #include <linux/bits.h>
6*2df8e64eSIvan Vecera #include <linux/dev_printk.h>
7*2df8e64eSIvan Vecera #include <linux/device.h>
8*2df8e64eSIvan Vecera #include <linux/export.h>
9*2df8e64eSIvan Vecera #include <linux/module.h>
10*2df8e64eSIvan Vecera #include <linux/netlink.h>
11*2df8e64eSIvan Vecera #include <linux/regmap.h>
12*2df8e64eSIvan Vecera #include <linux/sprintf.h>
13*2df8e64eSIvan Vecera #include <linux/unaligned.h>
14*2df8e64eSIvan Vecera #include <net/devlink.h>
15*2df8e64eSIvan Vecera 
16*2df8e64eSIvan Vecera #include "core.h"
17*2df8e64eSIvan Vecera #include "devlink.h"
18*2df8e64eSIvan Vecera #include "regs.h"
19*2df8e64eSIvan Vecera 
20*2df8e64eSIvan Vecera /* Chip IDs for zl30731 */
21*2df8e64eSIvan Vecera static const u16 zl30731_ids[] = {
22*2df8e64eSIvan Vecera 	0x0E93,
23*2df8e64eSIvan Vecera 	0x1E93,
24*2df8e64eSIvan Vecera 	0x2E93,
25*2df8e64eSIvan Vecera };
26*2df8e64eSIvan Vecera 
27*2df8e64eSIvan Vecera const struct zl3073x_chip_info zl30731_chip_info = {
28*2df8e64eSIvan Vecera 	.ids = zl30731_ids,
29*2df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30731_ids),
30*2df8e64eSIvan Vecera 	.num_channels = 1,
31*2df8e64eSIvan Vecera };
32*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30731_chip_info, "ZL3073X");
33*2df8e64eSIvan Vecera 
34*2df8e64eSIvan Vecera /* Chip IDs for zl30732 */
35*2df8e64eSIvan Vecera static const u16 zl30732_ids[] = {
36*2df8e64eSIvan Vecera 	0x0E30,
37*2df8e64eSIvan Vecera 	0x0E94,
38*2df8e64eSIvan Vecera 	0x1E94,
39*2df8e64eSIvan Vecera 	0x1F60,
40*2df8e64eSIvan Vecera 	0x2E94,
41*2df8e64eSIvan Vecera 	0x3FC4,
42*2df8e64eSIvan Vecera };
43*2df8e64eSIvan Vecera 
44*2df8e64eSIvan Vecera const struct zl3073x_chip_info zl30732_chip_info = {
45*2df8e64eSIvan Vecera 	.ids = zl30732_ids,
46*2df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30732_ids),
47*2df8e64eSIvan Vecera 	.num_channels = 2,
48*2df8e64eSIvan Vecera };
49*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30732_chip_info, "ZL3073X");
50*2df8e64eSIvan Vecera 
51*2df8e64eSIvan Vecera /* Chip IDs for zl30733 */
52*2df8e64eSIvan Vecera static const u16 zl30733_ids[] = {
53*2df8e64eSIvan Vecera 	0x0E95,
54*2df8e64eSIvan Vecera 	0x1E95,
55*2df8e64eSIvan Vecera 	0x2E95,
56*2df8e64eSIvan Vecera };
57*2df8e64eSIvan Vecera 
58*2df8e64eSIvan Vecera const struct zl3073x_chip_info zl30733_chip_info = {
59*2df8e64eSIvan Vecera 	.ids = zl30733_ids,
60*2df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30733_ids),
61*2df8e64eSIvan Vecera 	.num_channels = 3,
62*2df8e64eSIvan Vecera };
63*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30733_chip_info, "ZL3073X");
64*2df8e64eSIvan Vecera 
65*2df8e64eSIvan Vecera /* Chip IDs for zl30734 */
66*2df8e64eSIvan Vecera static const u16 zl30734_ids[] = {
67*2df8e64eSIvan Vecera 	0x0E96,
68*2df8e64eSIvan Vecera 	0x1E96,
69*2df8e64eSIvan Vecera 	0x2E96,
70*2df8e64eSIvan Vecera };
71*2df8e64eSIvan Vecera 
72*2df8e64eSIvan Vecera const struct zl3073x_chip_info zl30734_chip_info = {
73*2df8e64eSIvan Vecera 	.ids = zl30734_ids,
74*2df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30734_ids),
75*2df8e64eSIvan Vecera 	.num_channels = 4,
76*2df8e64eSIvan Vecera };
77*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30734_chip_info, "ZL3073X");
78*2df8e64eSIvan Vecera 
79*2df8e64eSIvan Vecera /* Chip IDs for zl30735 */
80*2df8e64eSIvan Vecera static const u16 zl30735_ids[] = {
81*2df8e64eSIvan Vecera 	0x0E97,
82*2df8e64eSIvan Vecera 	0x1E97,
83*2df8e64eSIvan Vecera 	0x2E97,
84*2df8e64eSIvan Vecera };
85*2df8e64eSIvan Vecera 
86*2df8e64eSIvan Vecera const struct zl3073x_chip_info zl30735_chip_info = {
87*2df8e64eSIvan Vecera 	.ids = zl30735_ids,
88*2df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30735_ids),
89*2df8e64eSIvan Vecera 	.num_channels = 5,
90*2df8e64eSIvan Vecera };
91*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X");
92*2df8e64eSIvan Vecera 
93*2df8e64eSIvan Vecera #define ZL_RANGE_OFFSET		0x80
94*2df8e64eSIvan Vecera #define ZL_PAGE_SIZE		0x80
95*2df8e64eSIvan Vecera #define ZL_NUM_PAGES		15
96*2df8e64eSIvan Vecera #define ZL_PAGE_SEL		0x7F
97*2df8e64eSIvan Vecera #define ZL_PAGE_SEL_MASK	GENMASK(3, 0)
98*2df8e64eSIvan Vecera #define ZL_NUM_REGS		(ZL_NUM_PAGES * ZL_PAGE_SIZE)
99*2df8e64eSIvan Vecera 
100*2df8e64eSIvan Vecera /* Regmap range configuration */
101*2df8e64eSIvan Vecera static const struct regmap_range_cfg zl3073x_regmap_range = {
102*2df8e64eSIvan Vecera 	.range_min	= ZL_RANGE_OFFSET,
103*2df8e64eSIvan Vecera 	.range_max	= ZL_RANGE_OFFSET + ZL_NUM_REGS - 1,
104*2df8e64eSIvan Vecera 	.selector_reg	= ZL_PAGE_SEL,
105*2df8e64eSIvan Vecera 	.selector_mask	= ZL_PAGE_SEL_MASK,
106*2df8e64eSIvan Vecera 	.selector_shift	= 0,
107*2df8e64eSIvan Vecera 	.window_start	= 0,
108*2df8e64eSIvan Vecera 	.window_len	= ZL_PAGE_SIZE,
109*2df8e64eSIvan Vecera };
110*2df8e64eSIvan Vecera 
111*2df8e64eSIvan Vecera static bool
112*2df8e64eSIvan Vecera zl3073x_is_volatile_reg(struct device *dev __maybe_unused, unsigned int reg)
113*2df8e64eSIvan Vecera {
114*2df8e64eSIvan Vecera 	/* Only page selector is non-volatile */
115*2df8e64eSIvan Vecera 	return reg != ZL_PAGE_SEL;
116*2df8e64eSIvan Vecera }
117*2df8e64eSIvan Vecera 
118*2df8e64eSIvan Vecera const struct regmap_config zl3073x_regmap_config = {
119*2df8e64eSIvan Vecera 	.reg_bits	= 8,
120*2df8e64eSIvan Vecera 	.val_bits	= 8,
121*2df8e64eSIvan Vecera 	.max_register	= ZL_RANGE_OFFSET + ZL_NUM_REGS - 1,
122*2df8e64eSIvan Vecera 	.ranges		= &zl3073x_regmap_range,
123*2df8e64eSIvan Vecera 	.num_ranges	= 1,
124*2df8e64eSIvan Vecera 	.cache_type	= REGCACHE_MAPLE,
125*2df8e64eSIvan Vecera 	.volatile_reg	= zl3073x_is_volatile_reg,
126*2df8e64eSIvan Vecera };
127*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl3073x_regmap_config, "ZL3073X");
128*2df8e64eSIvan Vecera 
129*2df8e64eSIvan Vecera static bool
130*2df8e64eSIvan Vecera zl3073x_check_reg(struct zl3073x_dev *zldev, unsigned int reg, size_t size)
131*2df8e64eSIvan Vecera {
132*2df8e64eSIvan Vecera 	/* Check that multiop lock is held when accessing registers
133*2df8e64eSIvan Vecera 	 * from page 10 and above.
134*2df8e64eSIvan Vecera 	 */
135*2df8e64eSIvan Vecera 	if (ZL_REG_PAGE(reg) >= 10)
136*2df8e64eSIvan Vecera 		lockdep_assert_held(&zldev->multiop_lock);
137*2df8e64eSIvan Vecera 
138*2df8e64eSIvan Vecera 	/* Check the index is in valid range for indexed register */
139*2df8e64eSIvan Vecera 	if (ZL_REG_OFFSET(reg) > ZL_REG_MAX_OFFSET(reg)) {
140*2df8e64eSIvan Vecera 		dev_err(zldev->dev, "Index out of range for reg 0x%04lx\n",
141*2df8e64eSIvan Vecera 			ZL_REG_ADDR(reg));
142*2df8e64eSIvan Vecera 		return false;
143*2df8e64eSIvan Vecera 	}
144*2df8e64eSIvan Vecera 	/* Check the requested size corresponds to register size */
145*2df8e64eSIvan Vecera 	if (ZL_REG_SIZE(reg) != size) {
146*2df8e64eSIvan Vecera 		dev_err(zldev->dev, "Invalid size %zu for reg 0x%04lx\n",
147*2df8e64eSIvan Vecera 			size, ZL_REG_ADDR(reg));
148*2df8e64eSIvan Vecera 		return false;
149*2df8e64eSIvan Vecera 	}
150*2df8e64eSIvan Vecera 
151*2df8e64eSIvan Vecera 	return true;
152*2df8e64eSIvan Vecera }
153*2df8e64eSIvan Vecera 
154*2df8e64eSIvan Vecera static int
155*2df8e64eSIvan Vecera zl3073x_read_reg(struct zl3073x_dev *zldev, unsigned int reg, void *val,
156*2df8e64eSIvan Vecera 		 size_t size)
157*2df8e64eSIvan Vecera {
158*2df8e64eSIvan Vecera 	int rc;
159*2df8e64eSIvan Vecera 
160*2df8e64eSIvan Vecera 	if (!zl3073x_check_reg(zldev, reg, size))
161*2df8e64eSIvan Vecera 		return -EINVAL;
162*2df8e64eSIvan Vecera 
163*2df8e64eSIvan Vecera 	/* Map the register address to virtual range */
164*2df8e64eSIvan Vecera 	reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET;
165*2df8e64eSIvan Vecera 
166*2df8e64eSIvan Vecera 	rc = regmap_bulk_read(zldev->regmap, reg, val, size);
167*2df8e64eSIvan Vecera 	if (rc) {
168*2df8e64eSIvan Vecera 		dev_err(zldev->dev, "Failed to read reg 0x%04x: %pe\n", reg,
169*2df8e64eSIvan Vecera 			ERR_PTR(rc));
170*2df8e64eSIvan Vecera 		return rc;
171*2df8e64eSIvan Vecera 	}
172*2df8e64eSIvan Vecera 
173*2df8e64eSIvan Vecera 	return 0;
174*2df8e64eSIvan Vecera }
175*2df8e64eSIvan Vecera 
176*2df8e64eSIvan Vecera static int
177*2df8e64eSIvan Vecera zl3073x_write_reg(struct zl3073x_dev *zldev, unsigned int reg, const void *val,
178*2df8e64eSIvan Vecera 		  size_t size)
179*2df8e64eSIvan Vecera {
180*2df8e64eSIvan Vecera 	int rc;
181*2df8e64eSIvan Vecera 
182*2df8e64eSIvan Vecera 	if (!zl3073x_check_reg(zldev, reg, size))
183*2df8e64eSIvan Vecera 		return -EINVAL;
184*2df8e64eSIvan Vecera 
185*2df8e64eSIvan Vecera 	/* Map the register address to virtual range */
186*2df8e64eSIvan Vecera 	reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET;
187*2df8e64eSIvan Vecera 
188*2df8e64eSIvan Vecera 	rc = regmap_bulk_write(zldev->regmap, reg, val, size);
189*2df8e64eSIvan Vecera 	if (rc) {
190*2df8e64eSIvan Vecera 		dev_err(zldev->dev, "Failed to write reg 0x%04x: %pe\n", reg,
191*2df8e64eSIvan Vecera 			ERR_PTR(rc));
192*2df8e64eSIvan Vecera 		return rc;
193*2df8e64eSIvan Vecera 	}
194*2df8e64eSIvan Vecera 
195*2df8e64eSIvan Vecera 	return 0;
196*2df8e64eSIvan Vecera }
197*2df8e64eSIvan Vecera 
198*2df8e64eSIvan Vecera /**
199*2df8e64eSIvan Vecera  * zl3073x_read_u8 - read value from 8bit register
200*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
201*2df8e64eSIvan Vecera  * @reg: register to write to
202*2df8e64eSIvan Vecera  * @val: value to write
203*2df8e64eSIvan Vecera  *
204*2df8e64eSIvan Vecera  * Reads value from given 8bit register.
205*2df8e64eSIvan Vecera  *
206*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
207*2df8e64eSIvan Vecera  */
208*2df8e64eSIvan Vecera int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val)
209*2df8e64eSIvan Vecera {
210*2df8e64eSIvan Vecera 	return zl3073x_read_reg(zldev, reg, val, sizeof(*val));
211*2df8e64eSIvan Vecera }
212*2df8e64eSIvan Vecera 
213*2df8e64eSIvan Vecera /**
214*2df8e64eSIvan Vecera  * zl3073x_write_u8 - write value to 16bit register
215*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
216*2df8e64eSIvan Vecera  * @reg: register to write to
217*2df8e64eSIvan Vecera  * @val: value to write
218*2df8e64eSIvan Vecera  *
219*2df8e64eSIvan Vecera  * Writes value into given 8bit register.
220*2df8e64eSIvan Vecera  *
221*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
222*2df8e64eSIvan Vecera  */
223*2df8e64eSIvan Vecera int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val)
224*2df8e64eSIvan Vecera {
225*2df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, &val, sizeof(val));
226*2df8e64eSIvan Vecera }
227*2df8e64eSIvan Vecera 
228*2df8e64eSIvan Vecera /**
229*2df8e64eSIvan Vecera  * zl3073x_read_u16 - read value from 16bit register
230*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
231*2df8e64eSIvan Vecera  * @reg: register to write to
232*2df8e64eSIvan Vecera  * @val: value to write
233*2df8e64eSIvan Vecera  *
234*2df8e64eSIvan Vecera  * Reads value from given 16bit register.
235*2df8e64eSIvan Vecera  *
236*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
237*2df8e64eSIvan Vecera  */
238*2df8e64eSIvan Vecera int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val)
239*2df8e64eSIvan Vecera {
240*2df8e64eSIvan Vecera 	int rc;
241*2df8e64eSIvan Vecera 
242*2df8e64eSIvan Vecera 	rc = zl3073x_read_reg(zldev, reg, val, sizeof(*val));
243*2df8e64eSIvan Vecera 	if (!rc)
244*2df8e64eSIvan Vecera 		be16_to_cpus(val);
245*2df8e64eSIvan Vecera 
246*2df8e64eSIvan Vecera 	return rc;
247*2df8e64eSIvan Vecera }
248*2df8e64eSIvan Vecera 
249*2df8e64eSIvan Vecera /**
250*2df8e64eSIvan Vecera  * zl3073x_write_u16 - write value to 16bit register
251*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
252*2df8e64eSIvan Vecera  * @reg: register to write to
253*2df8e64eSIvan Vecera  * @val: value to write
254*2df8e64eSIvan Vecera  *
255*2df8e64eSIvan Vecera  * Writes value into given 16bit register.
256*2df8e64eSIvan Vecera  *
257*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
258*2df8e64eSIvan Vecera  */
259*2df8e64eSIvan Vecera int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val)
260*2df8e64eSIvan Vecera {
261*2df8e64eSIvan Vecera 	cpu_to_be16s(&val);
262*2df8e64eSIvan Vecera 
263*2df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, &val, sizeof(val));
264*2df8e64eSIvan Vecera }
265*2df8e64eSIvan Vecera 
266*2df8e64eSIvan Vecera /**
267*2df8e64eSIvan Vecera  * zl3073x_read_u32 - read value from 32bit register
268*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
269*2df8e64eSIvan Vecera  * @reg: register to write to
270*2df8e64eSIvan Vecera  * @val: value to write
271*2df8e64eSIvan Vecera  *
272*2df8e64eSIvan Vecera  * Reads value from given 32bit register.
273*2df8e64eSIvan Vecera  *
274*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
275*2df8e64eSIvan Vecera  */
276*2df8e64eSIvan Vecera int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val)
277*2df8e64eSIvan Vecera {
278*2df8e64eSIvan Vecera 	int rc;
279*2df8e64eSIvan Vecera 
280*2df8e64eSIvan Vecera 	rc = zl3073x_read_reg(zldev, reg, val, sizeof(*val));
281*2df8e64eSIvan Vecera 	if (!rc)
282*2df8e64eSIvan Vecera 		be32_to_cpus(val);
283*2df8e64eSIvan Vecera 
284*2df8e64eSIvan Vecera 	return rc;
285*2df8e64eSIvan Vecera }
286*2df8e64eSIvan Vecera 
287*2df8e64eSIvan Vecera /**
288*2df8e64eSIvan Vecera  * zl3073x_write_u32 - write value to 32bit register
289*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
290*2df8e64eSIvan Vecera  * @reg: register to write to
291*2df8e64eSIvan Vecera  * @val: value to write
292*2df8e64eSIvan Vecera  *
293*2df8e64eSIvan Vecera  * Writes value into given 32bit register.
294*2df8e64eSIvan Vecera  *
295*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
296*2df8e64eSIvan Vecera  */
297*2df8e64eSIvan Vecera int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val)
298*2df8e64eSIvan Vecera {
299*2df8e64eSIvan Vecera 	cpu_to_be32s(&val);
300*2df8e64eSIvan Vecera 
301*2df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, &val, sizeof(val));
302*2df8e64eSIvan Vecera }
303*2df8e64eSIvan Vecera 
304*2df8e64eSIvan Vecera /**
305*2df8e64eSIvan Vecera  * zl3073x_read_u48 - read value from 48bit register
306*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
307*2df8e64eSIvan Vecera  * @reg: register to write to
308*2df8e64eSIvan Vecera  * @val: value to write
309*2df8e64eSIvan Vecera  *
310*2df8e64eSIvan Vecera  * Reads value from given 48bit register.
311*2df8e64eSIvan Vecera  *
312*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
313*2df8e64eSIvan Vecera  */
314*2df8e64eSIvan Vecera int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val)
315*2df8e64eSIvan Vecera {
316*2df8e64eSIvan Vecera 	u8 buf[6];
317*2df8e64eSIvan Vecera 	int rc;
318*2df8e64eSIvan Vecera 
319*2df8e64eSIvan Vecera 	rc = zl3073x_read_reg(zldev, reg, buf, sizeof(buf));
320*2df8e64eSIvan Vecera 	if (!rc)
321*2df8e64eSIvan Vecera 		*val = get_unaligned_be48(buf);
322*2df8e64eSIvan Vecera 
323*2df8e64eSIvan Vecera 	return rc;
324*2df8e64eSIvan Vecera }
325*2df8e64eSIvan Vecera 
326*2df8e64eSIvan Vecera /**
327*2df8e64eSIvan Vecera  * zl3073x_write_u48 - write value to 48bit register
328*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
329*2df8e64eSIvan Vecera  * @reg: register to write to
330*2df8e64eSIvan Vecera  * @val: value to write
331*2df8e64eSIvan Vecera  *
332*2df8e64eSIvan Vecera  * Writes value into given 48bit register.
333*2df8e64eSIvan Vecera  * The value must be from the interval -S48_MIN to U48_MAX.
334*2df8e64eSIvan Vecera  *
335*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
336*2df8e64eSIvan Vecera  */
337*2df8e64eSIvan Vecera int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val)
338*2df8e64eSIvan Vecera {
339*2df8e64eSIvan Vecera 	u8 buf[6];
340*2df8e64eSIvan Vecera 
341*2df8e64eSIvan Vecera 	/* Check the value belongs to <S48_MIN, U48_MAX>
342*2df8e64eSIvan Vecera 	 * Any value >= S48_MIN has bits 47..63 set.
343*2df8e64eSIvan Vecera 	 */
344*2df8e64eSIvan Vecera 	if (val > GENMASK_ULL(47, 0) && val < GENMASK_ULL(63, 47)) {
345*2df8e64eSIvan Vecera 		dev_err(zldev->dev, "Value 0x%0llx out of range\n", val);
346*2df8e64eSIvan Vecera 		return -EINVAL;
347*2df8e64eSIvan Vecera 	}
348*2df8e64eSIvan Vecera 
349*2df8e64eSIvan Vecera 	put_unaligned_be48(val, buf);
350*2df8e64eSIvan Vecera 
351*2df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, buf, sizeof(buf));
352*2df8e64eSIvan Vecera }
353*2df8e64eSIvan Vecera 
354*2df8e64eSIvan Vecera /**
355*2df8e64eSIvan Vecera  * zl3073x_poll_zero_u8 - wait for register to be cleared by device
356*2df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
357*2df8e64eSIvan Vecera  * @reg: register to poll (has to be 8bit register)
358*2df8e64eSIvan Vecera  * @mask: bit mask for polling
359*2df8e64eSIvan Vecera  *
360*2df8e64eSIvan Vecera  * Waits for bits specified by @mask in register @reg value to be cleared
361*2df8e64eSIvan Vecera  * by the device.
362*2df8e64eSIvan Vecera  *
363*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
364*2df8e64eSIvan Vecera  */
365*2df8e64eSIvan Vecera int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask)
366*2df8e64eSIvan Vecera {
367*2df8e64eSIvan Vecera 	/* Register polling sleep & timeout */
368*2df8e64eSIvan Vecera #define ZL_POLL_SLEEP_US   10
369*2df8e64eSIvan Vecera #define ZL_POLL_TIMEOUT_US 2000000
370*2df8e64eSIvan Vecera 	unsigned int val;
371*2df8e64eSIvan Vecera 
372*2df8e64eSIvan Vecera 	/* Check the register is 8bit */
373*2df8e64eSIvan Vecera 	if (ZL_REG_SIZE(reg) != 1) {
374*2df8e64eSIvan Vecera 		dev_err(zldev->dev, "Invalid reg 0x%04lx size for polling\n",
375*2df8e64eSIvan Vecera 			ZL_REG_ADDR(reg));
376*2df8e64eSIvan Vecera 		return -EINVAL;
377*2df8e64eSIvan Vecera 	}
378*2df8e64eSIvan Vecera 
379*2df8e64eSIvan Vecera 	/* Map the register address to virtual range */
380*2df8e64eSIvan Vecera 	reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET;
381*2df8e64eSIvan Vecera 
382*2df8e64eSIvan Vecera 	return regmap_read_poll_timeout(zldev->regmap, reg, val, !(val & mask),
383*2df8e64eSIvan Vecera 					ZL_POLL_SLEEP_US, ZL_POLL_TIMEOUT_US);
384*2df8e64eSIvan Vecera }
385*2df8e64eSIvan Vecera 
386*2df8e64eSIvan Vecera /**
387*2df8e64eSIvan Vecera  * zl3073x_dev_probe - initialize zl3073x device
388*2df8e64eSIvan Vecera  * @zldev: pointer to zl3073x device
389*2df8e64eSIvan Vecera  * @chip_info: chip info based on compatible
390*2df8e64eSIvan Vecera  *
391*2df8e64eSIvan Vecera  * Common initialization of zl3073x device structure.
392*2df8e64eSIvan Vecera  *
393*2df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
394*2df8e64eSIvan Vecera  */
395*2df8e64eSIvan Vecera int zl3073x_dev_probe(struct zl3073x_dev *zldev,
396*2df8e64eSIvan Vecera 		      const struct zl3073x_chip_info *chip_info)
397*2df8e64eSIvan Vecera {
398*2df8e64eSIvan Vecera 	u16 id, revision, fw_ver;
399*2df8e64eSIvan Vecera 	unsigned int i;
400*2df8e64eSIvan Vecera 	u32 cfg_ver;
401*2df8e64eSIvan Vecera 	int rc;
402*2df8e64eSIvan Vecera 
403*2df8e64eSIvan Vecera 	/* Read chip ID */
404*2df8e64eSIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id);
405*2df8e64eSIvan Vecera 	if (rc)
406*2df8e64eSIvan Vecera 		return rc;
407*2df8e64eSIvan Vecera 
408*2df8e64eSIvan Vecera 	/* Check it matches */
409*2df8e64eSIvan Vecera 	for (i = 0; i < chip_info->num_ids; i++) {
410*2df8e64eSIvan Vecera 		if (id == chip_info->ids[i])
411*2df8e64eSIvan Vecera 			break;
412*2df8e64eSIvan Vecera 	}
413*2df8e64eSIvan Vecera 
414*2df8e64eSIvan Vecera 	if (i == chip_info->num_ids) {
415*2df8e64eSIvan Vecera 		return dev_err_probe(zldev->dev, -ENODEV,
416*2df8e64eSIvan Vecera 				     "Unknown or non-match chip ID: 0x%0x\n",
417*2df8e64eSIvan Vecera 				     id);
418*2df8e64eSIvan Vecera 	}
419*2df8e64eSIvan Vecera 
420*2df8e64eSIvan Vecera 	/* Read revision, firmware version and custom config version */
421*2df8e64eSIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
422*2df8e64eSIvan Vecera 	if (rc)
423*2df8e64eSIvan Vecera 		return rc;
424*2df8e64eSIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver);
425*2df8e64eSIvan Vecera 	if (rc)
426*2df8e64eSIvan Vecera 		return rc;
427*2df8e64eSIvan Vecera 	rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver);
428*2df8e64eSIvan Vecera 	if (rc)
429*2df8e64eSIvan Vecera 		return rc;
430*2df8e64eSIvan Vecera 
431*2df8e64eSIvan Vecera 	dev_dbg(zldev->dev, "ChipID(%X), ChipRev(%X), FwVer(%u)\n", id,
432*2df8e64eSIvan Vecera 		revision, fw_ver);
433*2df8e64eSIvan Vecera 	dev_dbg(zldev->dev, "Custom config version: %lu.%lu.%lu.%lu\n",
434*2df8e64eSIvan Vecera 		FIELD_GET(GENMASK(31, 24), cfg_ver),
435*2df8e64eSIvan Vecera 		FIELD_GET(GENMASK(23, 16), cfg_ver),
436*2df8e64eSIvan Vecera 		FIELD_GET(GENMASK(15, 8), cfg_ver),
437*2df8e64eSIvan Vecera 		FIELD_GET(GENMASK(7, 0), cfg_ver));
438*2df8e64eSIvan Vecera 
439*2df8e64eSIvan Vecera 	/* Generate random clock ID as the device has not such property that
440*2df8e64eSIvan Vecera 	 * could be used for this purpose. A user can later change this value
441*2df8e64eSIvan Vecera 	 * using devlink.
442*2df8e64eSIvan Vecera 	 */
443*2df8e64eSIvan Vecera 	zldev->clock_id = get_random_u64();
444*2df8e64eSIvan Vecera 
445*2df8e64eSIvan Vecera 	/* Initialize mutex for operations where multiple reads, writes
446*2df8e64eSIvan Vecera 	 * and/or polls are required to be done atomically.
447*2df8e64eSIvan Vecera 	 */
448*2df8e64eSIvan Vecera 	rc = devm_mutex_init(zldev->dev, &zldev->multiop_lock);
449*2df8e64eSIvan Vecera 	if (rc)
450*2df8e64eSIvan Vecera 		return dev_err_probe(zldev->dev, rc,
451*2df8e64eSIvan Vecera 				     "Failed to initialize mutex\n");
452*2df8e64eSIvan Vecera 
453*2df8e64eSIvan Vecera 	/* Register the devlink instance and parameters */
454*2df8e64eSIvan Vecera 	rc = zl3073x_devlink_register(zldev);
455*2df8e64eSIvan Vecera 	if (rc)
456*2df8e64eSIvan Vecera 		return dev_err_probe(zldev->dev, rc,
457*2df8e64eSIvan Vecera 				     "Failed to register devlink instance\n");
458*2df8e64eSIvan Vecera 
459*2df8e64eSIvan Vecera 	return 0;
460*2df8e64eSIvan Vecera }
461*2df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X");
462*2df8e64eSIvan Vecera 
463*2df8e64eSIvan Vecera MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>");
464*2df8e64eSIvan Vecera MODULE_DESCRIPTION("Microchip ZL3073x core driver");
465*2df8e64eSIvan Vecera MODULE_LICENSE("GPL");
466