xref: /linux/drivers/regulator/pf0900-regulator.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright 2025 NXP.
3 // NXP PF0900 pmic driver
4 
5 #include <linux/bitfield.h>
6 #include <linux/crc8.h>
7 #include <linux/err.h>
8 #include <linux/gpio/consumer.h>
9 #include <linux/i2c.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_device.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 #include <linux/regulator/driver.h>
18 #include <linux/regulator/machine.h>
19 #include <linux/regulator/of_regulator.h>
20 
21 enum pf0900_regulators {
22 	PF0900_SW1 = 0,
23 	PF0900_SW2,
24 	PF0900_SW3,
25 	PF0900_SW4,
26 	PF0900_SW5,
27 	PF0900_LDO1,
28 	PF0900_LDO2,
29 	PF0900_LDO3,
30 	PF0900_VAON,
31 	PF0900_REGULATOR_CNT,
32 };
33 
34 enum {
35 	PF0900_DVS_LEVEL_RUN = 0,
36 	PF0900_DVS_LEVEL_STANDBY,
37 	PF0900_DVS_LEVEL_MAX,
38 };
39 
40 
41 #define PF0900_VAON_VOLTAGE_NUM 0x03
42 #define PF0900_SW_VOLTAGE_NUM   0x100
43 #define PF0900_LDO_VOLTAGE_NUM  0x20
44 
45 #define REGU_SW_CNT             0x5
46 #define REGU_LDO_VAON_CNT       0x4
47 
48 enum {
49 	PF0900_REG_DEV_ID	    = 0x00,
50 	PF0900_REG_DEV_FAM	    = 0x01,
51 	PF0900_REG_REV_ID	    = 0x02,
52 	PF0900_REG_PROG_ID1	    = 0x03,
53 	PF0900_REG_PROG_ID2	    = 0x04,
54 	PF0900_REG_SYSTEM_INT	    = 0x05,
55 	PF0900_REG_STATUS1_INT	    = 0x06,
56 	PF0900_REG_STATUS1_MSK      = 0x07,
57 	PF0900_REG_STATUS1_SNS	    = 0x08,
58 	PF0900_REG_STATUS2_INT      = 0x09,
59 	PF0900_REG_STATUS2_MSK      = 0x0A,
60 	PF0900_REG_STATUS2_SNS	    = 0x0B,
61 	PF0900_REG_STATUS3_INT      = 0x0C,
62 	PF0900_REG_STATUS3_MSK      = 0x0D,
63 	PF0900_REG_SW_MODE_INT      = 0x0E,
64 	PF0900_REG_SW_MODE_MSK      = 0x0F,
65 	PF0900_REG_SW_ILIM_INT      = 0x10,
66 	PF0900_REG_SW_ILIM_MSK      = 0x11,
67 	PF0900_REG_SW_ILIM_SNS      = 0x12,
68 	PF0900_REG_LDO_ILIM_INT     = 0x13,
69 	PF0900_REG_LDO_ILIM_MSK     = 0x14,
70 	PF0900_REG_LDO_ILIM_SNS     = 0x15,
71 	PF0900_REG_SW_UV_INT        = 0x16,
72 	PF0900_REG_SW_UV_MSK        = 0x17,
73 	PF0900_REG_SW_UV_SNS        = 0x18,
74 	PF0900_REG_SW_OV_INT        = 0x19,
75 	PF0900_REG_SW_OV_MSK        = 0x1A,
76 	PF0900_REG_SW_OV_SNS        = 0x1B,
77 	PF0900_REG_LDO_UV_INT       = 0x1C,
78 	PF0900_REG_LDO_UV_MSK       = 0x1D,
79 	PF0900_REG_LDO_UV_SNS       = 0x1E,
80 	PF0900_REG_LDO_OV_INT       = 0x1F,
81 	PF0900_REG_LDO_OV_MSK       = 0x20,
82 	PF0900_REG_LDO_OV_SNS       = 0x21,
83 	PF0900_REG_PWRON_INT        = 0x22,
84 	PF0900_REG_IO_INT           = 0x24,
85 	PF0900_REG_IO_MSK           = 0x25,
86 	PF0900_REG_IO_SNS           = 0x26,
87 	PF0900_REG_IOSHORT_SNS      = 0x27,
88 	PF0900_REG_ABIST_OV1        = 0x28,
89 	PF0900_REG_ABIST_OV2        = 0x29,
90 	PF0900_REG_ABIST_UV1        = 0x2A,
91 	PF0900_REG_ABIST_UV2        = 0x2B,
92 	PF0900_REG_ABIST_IO         = 0x2C,
93 	PF0900_REG_TEST_FLAGS       = 0x2D,
94 	PF0900_REG_HFAULT_FLAGS     = 0x2E,
95 	PF0900_REG_FAULT_FLAGS      = 0x2F,
96 	PF0900_REG_FS0B_CFG         = 0x30,
97 	PF0900_REG_FCCU_CFG         = 0x31,
98 	PF0900_REG_RSTB_CFG1        = 0x32,
99 	PF0900_REG_SYSTEM_CMD       = 0x33,
100 	PF0900_REG_FS0B_CMD         = 0x34,
101 	PF0900_REG_SECURE_WR1       = 0x35,
102 	PF0900_REG_SECURE_WR2       = 0x36,
103 	PF0900_REG_VMON_CFG1        = 0x37,
104 	PF0900_REG_SYS_CFG1         = 0x38,
105 	PF0900_REG_GPO_CFG          = 0x39,
106 	PF0900_REG_GPO_CTRL         = 0x3A,
107 	PF0900_REG_PWRUP_CFG        = 0x3B,
108 	PF0900_REG_RSTB_PWRUP       = 0x3C,
109 	PF0900_REG_GPIO1_PWRUP      = 0x3D,
110 	PF0900_REG_GPIO2_PWRUP      = 0x3E,
111 	PF0900_REG_GPIO3_PWRUP      = 0x3F,
112 	PF0900_REG_GPIO4_PWRUP      = 0x40,
113 	PF0900_REG_VMON1_PWRUP      = 0x41,
114 	PF0900_REG_VMON2_PWRUP      = 0x42,
115 	PF0900_REG_SW1_PWRUP        = 0x43,
116 	PF0900_REG_SW2_PWRUP        = 0x44,
117 	PF0900_REG_SW3_PWRUP        = 0x45,
118 	PF0900_REG_SW4_PWRUP        = 0x46,
119 	PF0900_REG_SW5_PWRUP        = 0x47,
120 	PF0900_REG_LDO1_PWRUP       = 0x48,
121 	PF0900_REG_LDO2_PWRUP       = 0x49,
122 	PF0900_REG_LDO3_PWRUP       = 0x4A,
123 	PF0900_REG_VAON_PWRUP       = 0x4B,
124 	PF0900_REG_FREQ_CTRL        = 0x4C,
125 	PF0900_REG_PWRON_CFG        = 0x4D,
126 	PF0900_REG_WD_CTRL1         = 0x4E,
127 	PF0900_REG_WD_CTRL2         = 0x4F,
128 	PF0900_REG_WD_CFG1          = 0x50,
129 	PF0900_REG_WD_CFG2          = 0x51,
130 	PF0900_REG_WD_CNT1          = 0x52,
131 	PF0900_REG_WD_CNT2          = 0x53,
132 	PF0900_REG_FAULT_CFG        = 0x54,
133 	PF0900_REG_FAULT_CNT        = 0x55,
134 	PF0900_REG_DFS_CNT          = 0x56,
135 	PF0900_REG_AMUX_CFG         = 0x57,
136 	PF0900_REG_VMON1_RUN_CFG    = 0x58,
137 	PF0900_REG_VMON1_STBY_CFG   = 0x59,
138 	PF0900_REG_VMON1_CTRL       = 0x5A,
139 	PF0900_REG_VMON2_RUN_CFG    = 0x5B,
140 	PF0900_REG_VMON2_STBY_CFG   = 0x5C,
141 	PF0900_REG_VMON2_CTRL       = 0x5D,
142 	PF0900_REG_SW1_VRUN         = 0x5E,
143 	PF0900_REG_SW1_VSTBY        = 0x5F,
144 	PF0900_REG_SW1_MODE         = 0x60,
145 	PF0900_REG_SW1_CFG1         = 0x61,
146 	PF0900_REG_SW1_CFG2         = 0x62,
147 	PF0900_REG_SW2_VRUN         = 0x63,
148 	PF0900_REG_SW2_VSTBY        = 0x64,
149 	PF0900_REG_SW2_MODE         = 0x65,
150 	PF0900_REG_SW2_CFG1         = 0x66,
151 	PF0900_REG_SW2_CFG2         = 0x67,
152 	PF0900_REG_SW3_VRUN         = 0x68,
153 	PF0900_REG_SW3_VSTBY        = 0x69,
154 	PF0900_REG_SW3_MODE         = 0x6A,
155 	PF0900_REG_SW3_CFG1         = 0x6B,
156 	PF0900_REG_SW3_CFG2         = 0x6C,
157 	PF0900_REG_SW4_VRUN         = 0x6D,
158 	PF0900_REG_SW4_VSTBY        = 0x6E,
159 	PF0900_REG_SW4_MODE         = 0x6F,
160 	PF0900_REG_SW4_CFG1         = 0x70,
161 	PF0900_REG_SW4_CFG2         = 0x71,
162 	PF0900_REG_SW5_VRUN         = 0x72,
163 	PF0900_REG_SW5_VSTBY        = 0x73,
164 	PF0900_REG_SW5_MODE         = 0x74,
165 	PF0900_REG_SW5_CFG1         = 0x75,
166 	PF0900_REG_SW5_CFG2         = 0x76,
167 	PF0900_REG_LDO1_RUN         = 0x77,
168 	PF0900_REG_LDO1_STBY        = 0x78,
169 	PF0900_REG_LDO1_CFG2        = 0x79,
170 	PF0900_REG_LDO2_RUN         = 0x7A,
171 	PF0900_REG_LDO2_STBY        = 0x7B,
172 	PF0900_REG_LDO2_CFG2        = 0x7C,
173 	PF0900_REG_LDO3_RUN         = 0x7D,
174 	PF0900_REG_LDO3_STBY        = 0x7E,
175 	PF0900_REG_LDO3_CFG2        = 0x7F,
176 	PF0900_REG_VAON_CFG1        = 0x80,
177 	PF0900_REG_VAON_CFG2        = 0x81,
178 	PF0900_REG_SYS_DIAG         = 0x82,
179 	PF0900_MAX_REGISTER,
180 };
181 
182 /* PF0900 SW MODE */
183 #define SW_RUN_MODE_OFF                 0x00
184 #define SW_RUN_MODE_PWM                 0x01
185 #define SW_RUN_MODE_PFM                 0x02
186 #define SW_STBY_MODE_OFF                0x00
187 #define SW_STBY_MODE_PWM                0x04
188 #define SW_STBY_MODE_PFM                0x08
189 
190 /* PF0900 SW MODE MASK */
191 #define SW_RUN_MODE_MASK                GENMASK(1, 0)
192 #define SW_STBY_MODE_MASK               GENMASK(3, 2)
193 
194 /* PF0900 SW VRUN/VSTBY MASK */
195 #define PF0900_SW_VOL_MASK              GENMASK(7, 0)
196 
197 /* PF0900_REG_VAON_CFG1 bits */
198 #define PF0900_VAON_1P8V                0x01
199 
200 #define PF0900_VAON_MASK                GENMASK(1, 0)
201 
202 /* PF0900_REG_SWX_CFG1 MASK */
203 #define PF0900_SW_DVS_MASK              GENMASK(4, 3)
204 
205 /* PF0900_REG_LDO_RUN MASK */
206 #define VLDO_RUN_MASK                   GENMASK(4, 0)
207 #define LDO_RUN_EN_MASK                 BIT(5)
208 
209 /* PF0900_REG_STATUS1_INT bits */
210 #define PF0900_IRQ_PWRUP                BIT(3)
211 
212 /* PF0900_REG_ILIM_INT bits */
213 #define PF0900_IRQ_SW1_IL               BIT(0)
214 #define PF0900_IRQ_SW2_IL               BIT(1)
215 #define PF0900_IRQ_SW3_IL               BIT(2)
216 #define PF0900_IRQ_SW4_IL               BIT(3)
217 #define PF0900_IRQ_SW5_IL               BIT(4)
218 
219 #define PF0900_IRQ_LDO1_IL              BIT(0)
220 #define PF0900_IRQ_LDO2_IL              BIT(1)
221 #define PF0900_IRQ_LDO3_IL              BIT(2)
222 
223 /* PF0900_REG_UV_INT bits */
224 #define PF0900_IRQ_SW1_UV               BIT(0)
225 #define PF0900_IRQ_SW2_UV               BIT(1)
226 #define PF0900_IRQ_SW3_UV               BIT(2)
227 #define PF0900_IRQ_SW4_UV               BIT(3)
228 #define PF0900_IRQ_SW5_UV               BIT(4)
229 
230 #define PF0900_IRQ_LDO1_UV              BIT(0)
231 #define PF0900_IRQ_LDO2_UV              BIT(1)
232 #define PF0900_IRQ_LDO3_UV              BIT(2)
233 #define PF0900_IRQ_VAON_UV              BIT(3)
234 
235 /* PF0900_REG_OV_INT bits */
236 #define PF0900_IRQ_SW1_OV               BIT(0)
237 #define PF0900_IRQ_SW2_OV               BIT(1)
238 #define PF0900_IRQ_SW3_OV               BIT(2)
239 #define PF0900_IRQ_SW4_OV               BIT(3)
240 #define PF0900_IRQ_SW5_OV               BIT(4)
241 
242 #define PF0900_IRQ_LDO1_OV              BIT(0)
243 #define PF0900_IRQ_LDO2_OV              BIT(1)
244 #define PF0900_IRQ_LDO3_OV              BIT(2)
245 #define PF0900_IRQ_VAON_OV              BIT(3)
246 
247 struct pf0900_regulator_desc {
248 	struct regulator_desc desc;
249 	unsigned int suspend_enable_mask;
250 	unsigned int suspend_voltage_reg;
251 	unsigned int suspend_voltage_cache;
252 };
253 
254 struct pf0900_drvdata {
255 	const struct pf0900_regulator_desc *desc;
256 	unsigned int rcnt;
257 };
258 
259 struct pf0900 {
260 	struct device *dev;
261 	struct regmap *regmap;
262 	const struct pf0900_drvdata *drvdata;
263 	struct regulator_dev *rdevs[PF0900_REGULATOR_CNT];
264 	int irq;
265 	unsigned short addr;
266 	bool crc_en;
267 };
268 
269 enum pf0900_regulator_type {
270 	PF0900_SW = 0,
271 	PF0900_LDO,
272 };
273 
274 #define PF0900_REGU_IRQ(_reg, _type, _event)	\
275 	{					\
276 		.reg = _reg,			\
277 		.type = _type,			\
278 		.event = _event,		\
279 	}
280 
281 struct pf0900_regulator_irq {
282 	unsigned int  reg;
283 	unsigned int  type;
284 	unsigned int  event;
285 };
286 
287 static const struct regmap_range pf0900_range = {
288 	.range_min = PF0900_REG_DEV_ID,
289 	.range_max = PF0900_REG_SYS_DIAG,
290 };
291 
292 static const struct regmap_access_table pf0900_volatile_regs = {
293 	.yes_ranges = &pf0900_range,
294 	.n_yes_ranges = 1,
295 };
296 
297 static const struct regmap_config pf0900_regmap_config = {
298 	.reg_bits = 8,
299 	.val_bits = 8,
300 	.volatile_table = &pf0900_volatile_regs,
301 	.max_register = PF0900_MAX_REGISTER - 1,
302 	.cache_type = REGCACHE_MAPLE,
303 };
304 
305 static uint8_t crc8_j1850(unsigned short addr, unsigned int reg,
306 			  unsigned int val)
307 {
308 	uint8_t crcBuf[3];
309 	uint8_t t_crc;
310 	uint8_t i, j;
311 
312 	crcBuf[0] = addr;
313 	crcBuf[1] = reg;
314 	crcBuf[2] = val;
315 	t_crc = 0xFF;
316 
317 	/*
318 	 * The CRC calculation is based on the standard CRC-8-SAE as
319 	 * defined in the SAE-J1850 specification with the following
320 	 * characteristics.
321 	 * Polynomial = 0x1D
322 	 * Initial Value = 0xFF
323 	 * The CRC byte is calculated by shifting 24-bit data through
324 	 * the CRC polynomial.The 24-bits package is built as follows:
325 	 * DEVICE_ADDR[b8] + REGISTER_ADDR [b8] +DATA[b8]
326 	 * The DEVICE_ADDR is calculated as the 7-bit slave address
327 	 * shifted left one space plus the corresponding read/write bit.
328 	 * (7Bit Address [b7] << 1 ) + R/W = DEVICE_ADDR[b8]
329 	 */
330 	for (i = 0; i < sizeof(crcBuf); i++) {
331 		t_crc ^= crcBuf[i];
332 		for (j = 0; j < 8; j++) {
333 			if ((t_crc & 0x80) != 0) {
334 				t_crc <<= 1;
335 				t_crc ^= 0x1D;
336 			} else {
337 				t_crc <<= 1;
338 			}
339 		}
340 	}
341 
342 	return t_crc;
343 }
344 
345 static int pf0900_regmap_read(void *context, unsigned int reg,
346 			      unsigned int *val)
347 {
348 	struct device *dev = context;
349 	struct i2c_client *i2c = to_i2c_client(dev);
350 	struct pf0900 *pf0900 = dev_get_drvdata(dev);
351 	int ret;
352 	u8 crc;
353 
354 	if (!pf0900 || !pf0900->dev)
355 		return -EINVAL;
356 
357 	if (reg >= PF0900_MAX_REGISTER) {
358 		dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg);
359 		return -EINVAL;
360 	}
361 
362 	if (pf0900->crc_en) {
363 		ret = i2c_smbus_read_word_data(i2c, reg);
364 		if (ret < 0) {
365 			dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret);
366 			return ret;
367 		}
368 
369 		*val = (u16)ret;
370 		crc = crc8_j1850(pf0900->addr << 1 | 0x1, reg, FIELD_GET(GENMASK(7, 0), *val));
371 		if (crc != FIELD_GET(GENMASK(15, 8), *val)) {
372 			dev_err(pf0900->dev, "Crc check error!\n");
373 			return -EINVAL;
374 		}
375 		*val = FIELD_GET(GENMASK(7, 0), *val);
376 	} else {
377 		ret = i2c_smbus_read_byte_data(i2c, reg);
378 		if (ret < 0) {
379 			dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret);
380 			return ret;
381 		}
382 		*val = ret;
383 	}
384 
385 	return 0;
386 }
387 
388 static int pf0900_regmap_write(void *context, unsigned int reg,
389 			       unsigned int val)
390 {
391 	struct device *dev = context;
392 	struct i2c_client *i2c = to_i2c_client(dev);
393 	struct pf0900 *pf0900 = dev_get_drvdata(dev);
394 	uint8_t data[2];
395 	int ret;
396 
397 	if (!pf0900 || !pf0900->dev)
398 		return -EINVAL;
399 
400 	if (reg >= PF0900_MAX_REGISTER) {
401 		dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg);
402 		return -EINVAL;
403 	}
404 
405 	data[0] = val;
406 	if (pf0900->crc_en) {
407 		/* Get CRC */
408 		data[1] = crc8_j1850(pf0900->addr << 1, reg, data[0]);
409 		val = FIELD_PREP(GENMASK(15, 8), data[1]) | data[0];
410 		ret = i2c_smbus_write_word_data(i2c, reg, val);
411 	} else {
412 		ret = i2c_smbus_write_byte_data(i2c, reg, data[0]);
413 	}
414 
415 	if (ret) {
416 		dev_err(pf0900->dev, "Write reg=0x%x error!\n", reg);
417 		return ret;
418 	}
419 
420 	return 0;
421 }
422 
423 static int pf0900_suspend_enable(struct regulator_dev *rdev)
424 {
425 	struct pf0900_regulator_desc *rdata = rdev_get_drvdata(rdev);
426 	struct regmap *rmap = rdev_get_regmap(rdev);
427 
428 	return regmap_update_bits(rmap, rdata->desc.enable_reg,
429 				  rdata->suspend_enable_mask, SW_STBY_MODE_PFM);
430 }
431 
432 static int pf0900_suspend_disable(struct regulator_dev *rdev)
433 {
434 	struct pf0900_regulator_desc *rdata = rdev_get_drvdata(rdev);
435 	struct regmap *rmap = rdev_get_regmap(rdev);
436 
437 	return regmap_update_bits(rmap, rdata->desc.enable_reg,
438 				  rdata->suspend_enable_mask, SW_STBY_MODE_OFF);
439 }
440 
441 static int pf0900_set_suspend_voltage(struct regulator_dev *rdev, int uV)
442 {
443 	struct pf0900_regulator_desc *rdata = rdev_get_drvdata(rdev);
444 	struct regmap *rmap = rdev_get_regmap(rdev);
445 	int ret;
446 
447 	if (rdata->suspend_voltage_cache == uV)
448 		return 0;
449 
450 	ret = regulator_map_voltage_iterate(rdev, uV, uV);
451 	if (ret < 0) {
452 		dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV);
453 		return ret;
454 	}
455 
456 	dev_dbg(rdev_get_dev(rdev), "uV: %i, reg: 0x%x, msk: 0x%x, val: 0x%x\n",
457 		uV, rdata->suspend_voltage_reg, rdata->desc.vsel_mask, ret);
458 	ret = regmap_update_bits(rmap, rdata->suspend_voltage_reg,
459 				 rdata->desc.vsel_mask, ret);
460 	if (ret < 0) {
461 		dev_err(rdev_get_dev(rdev), "failed to set %i uV\n", uV);
462 		return ret;
463 	}
464 
465 	rdata->suspend_voltage_cache = uV;
466 
467 	return 0;
468 }
469 
470 static const struct regmap_bus pf0900_regmap_bus = {
471 	.reg_read = pf0900_regmap_read,
472 	.reg_write = pf0900_regmap_write,
473 };
474 
475 static const struct regulator_ops pf0900_avon_regulator_ops = {
476 	.list_voltage = regulator_list_voltage_table,
477 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
478 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
479 };
480 
481 static const struct regulator_ops pf0900_dvs_sw_regulator_ops = {
482 	.enable = regulator_enable_regmap,
483 	.disable = regulator_disable_regmap,
484 	.is_enabled = regulator_is_enabled_regmap,
485 	.list_voltage = regulator_list_voltage_linear_range,
486 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
487 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
488 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
489 	.set_ramp_delay	= regulator_set_ramp_delay_regmap,
490 	.set_suspend_enable = pf0900_suspend_enable,
491 	.set_suspend_disable = pf0900_suspend_disable,
492 	.set_suspend_voltage = pf0900_set_suspend_voltage,
493 };
494 
495 static const struct regulator_ops pf0900_ldo_regulator_ops = {
496 	.enable = regulator_enable_regmap,
497 	.disable = regulator_disable_regmap,
498 	.is_enabled = regulator_is_enabled_regmap,
499 	.list_voltage = regulator_list_voltage_linear_range,
500 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
501 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
502 };
503 
504 /*
505  * SW1/2/3/4/5
506  * SW1_DVS[1:0] SW1 DVS ramp rate setting
507  * 00: 15.6mV/8usec
508  * 01: 15.6mV/4usec
509  * 10: 15.6mV/2usec
510  * 11: 15.6mV/1usec
511  */
512 static const unsigned int pf0900_dvs_sw_ramp_table[] = {
513 	1950, 3900, 7800, 15600
514 };
515 
516 /* VAON 1.8V, 3.0V, or 3.3V */
517 static const int pf0900_vaon_voltages[] = {
518 	0, 1800000, 3000000, 3300000,
519 };
520 
521 /*
522  * SW1 0.5V to 3.3V
523  * 0.5V to 1.35V (6.25mV step)
524  * 1.8V to 2.5V (125mV step)
525  * 2.8V to 3.3V (250mV step)
526  */
527 static const struct linear_range pf0900_dvs_sw1_volts[] = {
528 	REGULATOR_LINEAR_RANGE(0,        0x00, 0x08, 0),
529 	REGULATOR_LINEAR_RANGE(500000,   0x09, 0x91, 6250),
530 	REGULATOR_LINEAR_RANGE(0,        0x92, 0x9E, 0),
531 	REGULATOR_LINEAR_RANGE(1500000,  0x9F, 0x9F, 0),
532 	REGULATOR_LINEAR_RANGE(1800000,  0xA0, 0xD8, 12500),
533 	REGULATOR_LINEAR_RANGE(0,        0xD9, 0xDF, 0),
534 	REGULATOR_LINEAR_RANGE(2800000,  0xE0, 0xF4, 25000),
535 	REGULATOR_LINEAR_RANGE(0,        0xF5, 0xFF, 0),
536 };
537 
538 /*
539  * SW2/3/4/5 0.3V to 3.3V
540  * 0.45V to 1.35V (6.25mV step)
541  * 1.8V to 2.5V (125mV step)
542  * 2.8V to 3.3V (250mV step)
543  */
544 static const struct linear_range pf0900_dvs_sw2345_volts[] = {
545 	REGULATOR_LINEAR_RANGE(300000,   0x00, 0x00, 0),
546 	REGULATOR_LINEAR_RANGE(450000,   0x01, 0x91, 6250),
547 	REGULATOR_LINEAR_RANGE(0,        0x92, 0x9E, 0),
548 	REGULATOR_LINEAR_RANGE(1500000,  0x9F, 0x9F, 0),
549 	REGULATOR_LINEAR_RANGE(1800000,  0xA0, 0xD8, 12500),
550 	REGULATOR_LINEAR_RANGE(0,        0xD9, 0xDF, 0),
551 	REGULATOR_LINEAR_RANGE(2800000,  0xE0, 0xF4, 25000),
552 	REGULATOR_LINEAR_RANGE(0,        0xF5, 0xFF, 0),
553 };
554 
555 /*
556  * LDO1
557  * 0.75V to 3.3V
558  */
559 static const struct linear_range pf0900_ldo1_volts[] = {
560 	REGULATOR_LINEAR_RANGE(750000,   0x00, 0x0F, 50000),
561 	REGULATOR_LINEAR_RANGE(1800000,  0x10, 0x1F, 100000),
562 };
563 
564 /*
565  * LDO2/3
566  * 0.65V to 3.3V (50mV step)
567  */
568 static const struct linear_range pf0900_ldo23_volts[] = {
569 	REGULATOR_LINEAR_RANGE(650000,   0x00, 0x0D, 50000),
570 	REGULATOR_LINEAR_RANGE(1400000,  0x0E, 0x0F, 100000),
571 	REGULATOR_LINEAR_RANGE(1800000,  0x10, 0x1F, 100000),
572 };
573 
574 static const struct pf0900_regulator_desc pf0900_regulators[] = {
575 	{
576 		.desc = {
577 			.name = "sw1",
578 			.of_match = of_match_ptr("sw1"),
579 			.regulators_node = of_match_ptr("regulators"),
580 			.id = PF0900_SW1,
581 			.ops = &pf0900_dvs_sw_regulator_ops,
582 			.type = REGULATOR_VOLTAGE,
583 			.n_voltages = PF0900_SW_VOLTAGE_NUM,
584 			.linear_ranges = pf0900_dvs_sw1_volts,
585 			.n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw1_volts),
586 			.vsel_reg = PF0900_REG_SW1_VRUN,
587 			.vsel_mask = PF0900_SW_VOL_MASK,
588 			.enable_reg = PF0900_REG_SW1_MODE,
589 			.enable_mask = SW_RUN_MODE_MASK,
590 			.enable_val = SW_RUN_MODE_PWM,
591 			.ramp_reg = PF0900_REG_SW1_CFG1,
592 			.ramp_mask = PF0900_SW_DVS_MASK,
593 			.ramp_delay_table = pf0900_dvs_sw_ramp_table,
594 			.n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
595 			.owner = THIS_MODULE,
596 		},
597 		.suspend_enable_mask = SW_STBY_MODE_MASK,
598 		.suspend_voltage_reg = PF0900_REG_SW1_VSTBY,
599 	},
600 	{
601 		.desc = {
602 			.name = "sw2",
603 			.of_match = of_match_ptr("sw2"),
604 			.regulators_node = of_match_ptr("regulators"),
605 			.id = PF0900_SW2,
606 			.ops = &pf0900_dvs_sw_regulator_ops,
607 			.type = REGULATOR_VOLTAGE,
608 			.n_voltages = PF0900_SW_VOLTAGE_NUM,
609 			.linear_ranges = pf0900_dvs_sw2345_volts,
610 			.n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
611 			.vsel_reg = PF0900_REG_SW2_VRUN,
612 			.vsel_mask = PF0900_SW_VOL_MASK,
613 			.enable_reg = PF0900_REG_SW2_MODE,
614 			.enable_mask = SW_RUN_MODE_MASK,
615 			.enable_val = SW_RUN_MODE_PWM,
616 			.ramp_reg = PF0900_REG_SW2_CFG1,
617 			.ramp_mask = PF0900_SW_DVS_MASK,
618 			.ramp_delay_table = pf0900_dvs_sw_ramp_table,
619 			.n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
620 			.owner = THIS_MODULE,
621 		},
622 		.suspend_enable_mask = SW_STBY_MODE_MASK,
623 		.suspend_voltage_reg = PF0900_REG_SW2_VSTBY,
624 	},
625 	{
626 		.desc = {
627 			.name = "sw3",
628 			.of_match = of_match_ptr("sw3"),
629 			.regulators_node = of_match_ptr("regulators"),
630 			.id = PF0900_SW3,
631 			.ops = &pf0900_dvs_sw_regulator_ops,
632 			.type = REGULATOR_VOLTAGE,
633 			.n_voltages = PF0900_SW_VOLTAGE_NUM,
634 			.linear_ranges = pf0900_dvs_sw2345_volts,
635 			.n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
636 			.vsel_reg = PF0900_REG_SW3_VRUN,
637 			.vsel_mask = PF0900_SW_VOL_MASK,
638 			.enable_reg = PF0900_REG_SW3_MODE,
639 			.enable_mask = SW_RUN_MODE_MASK,
640 			.enable_val = SW_RUN_MODE_PWM,
641 			.ramp_reg = PF0900_REG_SW3_CFG1,
642 			.ramp_mask = PF0900_SW_DVS_MASK,
643 			.ramp_delay_table = pf0900_dvs_sw_ramp_table,
644 			.n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
645 			.owner = THIS_MODULE,
646 		},
647 		.suspend_enable_mask = SW_STBY_MODE_MASK,
648 		.suspend_voltage_reg = PF0900_REG_SW3_VSTBY,
649 	},
650 	{
651 		.desc = {
652 			.name = "sw4",
653 			.of_match = of_match_ptr("sw4"),
654 			.regulators_node = of_match_ptr("regulators"),
655 			.id = PF0900_SW4,
656 			.ops = &pf0900_dvs_sw_regulator_ops,
657 			.type = REGULATOR_VOLTAGE,
658 			.n_voltages = PF0900_SW_VOLTAGE_NUM,
659 			.linear_ranges = pf0900_dvs_sw2345_volts,
660 			.n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
661 			.vsel_reg = PF0900_REG_SW4_VRUN,
662 			.vsel_mask = PF0900_SW_VOL_MASK,
663 			.enable_reg = PF0900_REG_SW4_MODE,
664 			.enable_mask = SW_RUN_MODE_MASK,
665 			.enable_val = SW_RUN_MODE_PWM,
666 			.ramp_reg = PF0900_REG_SW4_CFG1,
667 			.ramp_mask = PF0900_SW_DVS_MASK,
668 			.ramp_delay_table = pf0900_dvs_sw_ramp_table,
669 			.n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
670 			.owner = THIS_MODULE,
671 		},
672 		.suspend_enable_mask = SW_STBY_MODE_MASK,
673 		.suspend_voltage_reg = PF0900_REG_SW4_VSTBY,
674 	},
675 	{
676 		.desc = {
677 			.name = "sw5",
678 			.of_match = of_match_ptr("sw5"),
679 			.regulators_node = of_match_ptr("regulators"),
680 			.id = PF0900_SW5,
681 			.ops = &pf0900_dvs_sw_regulator_ops,
682 			.type = REGULATOR_VOLTAGE,
683 			.n_voltages = PF0900_SW_VOLTAGE_NUM,
684 			.linear_ranges = pf0900_dvs_sw2345_volts,
685 			.n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
686 			.vsel_reg = PF0900_REG_SW5_VRUN,
687 			.vsel_mask = PF0900_SW_VOL_MASK,
688 			.enable_reg = PF0900_REG_SW5_MODE,
689 			.enable_mask = SW_RUN_MODE_MASK,
690 			.enable_val = SW_RUN_MODE_PWM,
691 			.ramp_reg = PF0900_REG_SW5_CFG1,
692 			.ramp_mask = PF0900_SW_DVS_MASK,
693 			.ramp_delay_table = pf0900_dvs_sw_ramp_table,
694 			.n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
695 			.owner = THIS_MODULE,
696 		},
697 		.suspend_enable_mask = SW_STBY_MODE_MASK,
698 		.suspend_voltage_reg = PF0900_REG_SW5_VSTBY,
699 	},
700 	{
701 		.desc = {
702 			.name = "ldo1",
703 			.of_match = of_match_ptr("ldo1"),
704 			.regulators_node = of_match_ptr("regulators"),
705 			.id = PF0900_LDO1,
706 			.ops = &pf0900_ldo_regulator_ops,
707 			.type = REGULATOR_VOLTAGE,
708 			.n_voltages = PF0900_LDO_VOLTAGE_NUM,
709 			.linear_ranges = pf0900_ldo1_volts,
710 			.n_linear_ranges = ARRAY_SIZE(pf0900_ldo1_volts),
711 			.vsel_reg = PF0900_REG_LDO1_RUN,
712 			.vsel_mask = VLDO_RUN_MASK,
713 			.enable_reg = PF0900_REG_LDO1_RUN,
714 			.enable_mask = LDO_RUN_EN_MASK,
715 			.owner = THIS_MODULE,
716 		},
717 	},
718 	{
719 		.desc = {
720 			.name = "ldo2",
721 			.of_match = of_match_ptr("ldo2"),
722 			.regulators_node = of_match_ptr("regulators"),
723 			.id = PF0900_LDO2,
724 			.ops = &pf0900_ldo_regulator_ops,
725 			.type = REGULATOR_VOLTAGE,
726 			.n_voltages = PF0900_LDO_VOLTAGE_NUM,
727 			.linear_ranges = pf0900_ldo23_volts,
728 			.n_linear_ranges = ARRAY_SIZE(pf0900_ldo23_volts),
729 			.vsel_reg = PF0900_REG_LDO2_RUN,
730 			.vsel_mask = VLDO_RUN_MASK,
731 			.enable_reg = PF0900_REG_LDO2_RUN,
732 			.enable_mask = LDO_RUN_EN_MASK,
733 			.owner = THIS_MODULE,
734 		},
735 	},
736 	{
737 		.desc = {
738 			.name = "ldo3",
739 			.of_match = of_match_ptr("ldo3"),
740 			.regulators_node = of_match_ptr("regulators"),
741 			.id = PF0900_LDO3,
742 			.ops = &pf0900_ldo_regulator_ops,
743 			.type = REGULATOR_VOLTAGE,
744 			.n_voltages = PF0900_LDO_VOLTAGE_NUM,
745 			.linear_ranges = pf0900_ldo23_volts,
746 			.n_linear_ranges = ARRAY_SIZE(pf0900_ldo23_volts),
747 			.vsel_reg = PF0900_REG_LDO3_RUN,
748 			.vsel_mask = VLDO_RUN_MASK,
749 			.enable_reg = PF0900_REG_LDO3_RUN,
750 			.enable_mask = LDO_RUN_EN_MASK,
751 			.owner = THIS_MODULE,
752 		},
753 	},
754 	{
755 		.desc = {
756 			.name = "vaon",
757 			.of_match = of_match_ptr("vaon"),
758 			.regulators_node = of_match_ptr("regulators"),
759 			.id = PF0900_VAON,
760 			.ops = &pf0900_avon_regulator_ops,
761 			.type = REGULATOR_VOLTAGE,
762 			.n_voltages = PF0900_VAON_VOLTAGE_NUM,
763 			.volt_table = pf0900_vaon_voltages,
764 			.enable_reg = PF0900_REG_VAON_CFG1,
765 			.enable_mask = PF0900_VAON_MASK,
766 			.enable_val = PF0900_VAON_1P8V,
767 			.vsel_reg = PF0900_REG_VAON_CFG1,
768 			.vsel_mask = PF0900_VAON_MASK,
769 			.owner = THIS_MODULE,
770 		},
771 	},
772 };
773 
774 struct pf0900_regulator_irq regu_irqs[] = {
775 	PF0900_REGU_IRQ(PF0900_REG_SW_ILIM_INT, PF0900_SW, REGULATOR_ERROR_OVER_CURRENT_WARN),
776 	PF0900_REGU_IRQ(PF0900_REG_LDO_ILIM_INT, PF0900_LDO, REGULATOR_ERROR_OVER_CURRENT_WARN),
777 	PF0900_REGU_IRQ(PF0900_REG_SW_UV_INT, PF0900_SW, REGULATOR_ERROR_UNDER_VOLTAGE_WARN),
778 	PF0900_REGU_IRQ(PF0900_REG_LDO_UV_INT, PF0900_LDO, REGULATOR_ERROR_UNDER_VOLTAGE_WARN),
779 	PF0900_REGU_IRQ(PF0900_REG_SW_OV_INT, PF0900_SW, REGULATOR_ERROR_OVER_VOLTAGE_WARN),
780 	PF0900_REGU_IRQ(PF0900_REG_LDO_OV_INT, PF0900_LDO, REGULATOR_ERROR_OVER_VOLTAGE_WARN),
781 };
782 
783 static irqreturn_t pf0900_irq_handler(int irq, void *data)
784 {
785 	unsigned int val, regu, i, index;
786 	struct pf0900 *pf0900 = data;
787 	int ret;
788 
789 	for (i = 0; i < ARRAY_SIZE(regu_irqs); i++) {
790 		ret = regmap_read(pf0900->regmap, regu_irqs[i].reg, &val);
791 		if (ret < 0) {
792 			dev_err(pf0900->dev, "Failed to read %d\n", ret);
793 			return IRQ_NONE;
794 		}
795 		if (val) {
796 			ret = regmap_write_bits(pf0900->regmap, regu_irqs[i].reg, val, val);
797 			if (ret < 0) {
798 				dev_err(pf0900->dev, "Failed to update %d\n", ret);
799 				return IRQ_NONE;
800 			}
801 
802 			if (regu_irqs[i].type == PF0900_SW) {
803 				for (index = 0; index < REGU_SW_CNT; index++) {
804 					if (val & BIT(index)) {
805 						regu = (enum pf0900_regulators)index;
806 						regulator_notifier_call_chain(pf0900->rdevs[regu],
807 									      regu_irqs[i].event,
808 									      NULL);
809 					}
810 				}
811 			} else if (regu_irqs[i].type == PF0900_LDO) {
812 				for (index = 0; index < REGU_LDO_VAON_CNT; index++) {
813 					if (val & BIT(index)) {
814 						regu = (enum pf0900_regulators)index + PF0900_LDO1;
815 						regulator_notifier_call_chain(pf0900->rdevs[regu],
816 									      regu_irqs[i].event,
817 									      NULL);
818 					}
819 				}
820 			}
821 		}
822 	}
823 
824 	return IRQ_HANDLED;
825 }
826 
827 static int pf0900_i2c_probe(struct i2c_client *i2c)
828 {
829 	const struct pf0900_regulator_desc *regulator_desc;
830 	const struct pf0900_drvdata *drvdata = NULL;
831 	struct device_node *np = i2c->dev.of_node;
832 	unsigned int device_id, device_fam, i;
833 	struct regulator_config config = { };
834 	struct pf0900 *pf0900;
835 	int ret;
836 
837 	if (!i2c->irq)
838 		return dev_err_probe(&i2c->dev, -EINVAL, "No IRQ configured?\n");
839 
840 	pf0900 = devm_kzalloc(&i2c->dev, sizeof(struct pf0900), GFP_KERNEL);
841 	if (!pf0900)
842 		return -ENOMEM;
843 
844 	drvdata = device_get_match_data(&i2c->dev);
845 	if (!drvdata)
846 		return dev_err_probe(&i2c->dev, -EINVAL, "unable to find driver data\n");
847 
848 	regulator_desc = drvdata->desc;
849 	pf0900->drvdata = drvdata;
850 	pf0900->crc_en = of_property_read_bool(np, "nxp,i2c-crc-enable");
851 	pf0900->irq = i2c->irq;
852 	pf0900->dev = &i2c->dev;
853 	pf0900->addr = i2c->addr;
854 
855 	dev_set_drvdata(&i2c->dev, pf0900);
856 
857 	pf0900->regmap = devm_regmap_init(&i2c->dev, &pf0900_regmap_bus, &i2c->dev,
858 					       &pf0900_regmap_config);
859 	if (IS_ERR(pf0900->regmap))
860 		return dev_err_probe(&i2c->dev, PTR_ERR(pf0900->regmap),
861 				     "regmap initialization failed\n");
862 	ret = regmap_read(pf0900->regmap, PF0900_REG_DEV_ID, &device_id);
863 	if (ret)
864 		return dev_err_probe(&i2c->dev, ret, "Read device id error\n");
865 
866 	ret = regmap_read(pf0900->regmap, PF0900_REG_DEV_FAM, &device_fam);
867 	if (ret)
868 		return dev_err_probe(&i2c->dev, ret, "Read device fam error\n");
869 
870 	/* Check your board and dts for match the right pmic */
871 	if (device_fam == 0x09 && (device_id & 0x1F) != 0x0)
872 		return dev_err_probe(&i2c->dev, -EINVAL, "Device id(%x) mismatched\n",
873 				     device_id >> 4);
874 
875 	for (i = 0; i < drvdata->rcnt; i++) {
876 		const struct regulator_desc *desc;
877 		const struct pf0900_regulator_desc *r;
878 
879 		r = &regulator_desc[i];
880 		desc = &r->desc;
881 		config.regmap = pf0900->regmap;
882 		config.driver_data = (void *)r;
883 		config.dev = pf0900->dev;
884 
885 		pf0900->rdevs[i] = devm_regulator_register(pf0900->dev, desc, &config);
886 		if (IS_ERR(pf0900->rdevs[i]))
887 			return dev_err_probe(pf0900->dev, PTR_ERR(pf0900->rdevs[i]),
888 					     "Failed to register regulator(%s)\n", desc->name);
889 	}
890 
891 	ret = devm_request_threaded_irq(pf0900->dev, pf0900->irq, NULL,
892 					pf0900_irq_handler,
893 					(IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
894 					"pf0900-irq", pf0900);
895 
896 	if (ret != 0)
897 		return dev_err_probe(pf0900->dev, ret, "Failed to request IRQ: %d\n",
898 				     pf0900->irq);
899 	/*
900 	 * The PWRUP_M is unmasked by default. When the device enter in RUN state,
901 	 * it will assert the PWRUP_I interrupt and assert the INTB pin to inform
902 	 * the MCU that it has finished the power up sequence properly.
903 	 */
904 	ret = regmap_write_bits(pf0900->regmap, PF0900_REG_STATUS1_INT, PF0900_IRQ_PWRUP,
905 				PF0900_IRQ_PWRUP);
906 	if (ret)
907 		return dev_err_probe(&i2c->dev, ret, "Clean PWRUP_I error\n");
908 
909 	/* mask interrupt PWRUP */
910 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_STATUS1_MSK, PF0900_IRQ_PWRUP,
911 				 PF0900_IRQ_PWRUP);
912 	if (ret)
913 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
914 
915 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_ILIM_MSK, PF0900_IRQ_SW1_IL |
916 				 PF0900_IRQ_SW2_IL | PF0900_IRQ_SW3_IL | PF0900_IRQ_SW4_IL |
917 				 PF0900_IRQ_SW5_IL, 0);
918 	if (ret)
919 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
920 
921 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_UV_MSK, PF0900_IRQ_SW1_UV |
922 				 PF0900_IRQ_SW2_UV | PF0900_IRQ_SW3_UV | PF0900_IRQ_SW4_UV |
923 				 PF0900_IRQ_SW5_UV, 0);
924 	if (ret)
925 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
926 
927 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_OV_MSK, PF0900_IRQ_SW1_OV |
928 				 PF0900_IRQ_SW2_OV | PF0900_IRQ_SW3_OV | PF0900_IRQ_SW4_OV |
929 				 PF0900_IRQ_SW5_OV, 0);
930 	if (ret)
931 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
932 
933 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_ILIM_MSK, PF0900_IRQ_LDO1_IL |
934 				 PF0900_IRQ_LDO2_IL | PF0900_IRQ_LDO3_IL, 0);
935 	if (ret)
936 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
937 
938 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_UV_MSK, PF0900_IRQ_LDO1_UV |
939 				 PF0900_IRQ_LDO2_UV | PF0900_IRQ_LDO3_UV | PF0900_IRQ_VAON_UV, 0);
940 	if (ret)
941 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
942 
943 	ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_OV_MSK, PF0900_IRQ_LDO1_OV |
944 				 PF0900_IRQ_LDO2_OV | PF0900_IRQ_LDO3_OV | PF0900_IRQ_VAON_OV, 0);
945 	if (ret)
946 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
947 
948 	return 0;
949 }
950 
951 static struct pf0900_drvdata pf0900_drvdata = {
952 	.desc = pf0900_regulators,
953 	.rcnt = ARRAY_SIZE(pf0900_regulators),
954 };
955 
956 static const struct of_device_id pf0900_of_match[] = {
957 	{ .compatible = "nxp,pf0900", .data = &pf0900_drvdata},
958 	{ }
959 };
960 
961 MODULE_DEVICE_TABLE(of, pf0900_of_match);
962 
963 static struct i2c_driver pf0900_i2c_driver = {
964 	.driver = {
965 		.name = "nxp-pf0900",
966 		.of_match_table = pf0900_of_match,
967 	},
968 	.probe = pf0900_i2c_probe,
969 };
970 
971 module_i2c_driver(pf0900_i2c_driver);
972 
973 MODULE_AUTHOR("Joy Zou <joy.zou@nxp.com>");
974 MODULE_DESCRIPTION("NXP PF0900 Power Management IC driver");
975 MODULE_LICENSE("GPL");
976