xref: /linux/drivers/platform/x86/mlx-platform.c (revision ec63e2a4897075e427c121d863bd89c44578094f)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*
3  * Mellanox platform driver
4  *
5  * Copyright (C) 2016-2018 Mellanox Technologies
6  * Copyright (C) 2016-2018 Vadim Pasternak <vadimp@mellanox.com>
7  */
8 
9 #include <linux/device.h>
10 #include <linux/dmi.h>
11 #include <linux/i2c.h>
12 #include <linux/i2c-mux.h>
13 #include <linux/io.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/platform_data/i2c-mux-reg.h>
17 #include <linux/platform_data/mlxreg.h>
18 #include <linux/regmap.h>
19 
20 #define MLX_PLAT_DEVICE_NAME		"mlxplat"
21 
22 /* LPC bus IO offsets */
23 #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR		0x2000
24 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR		0x2500
25 #define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET	0x00
26 #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET	0x01
27 #define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET	0x02
28 #define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET	0x03
29 #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET	0x1d
30 #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET	0x1e
31 #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET	0x1f
32 #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET	0x20
33 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET	0x21
34 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET	0x22
35 #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET	0x23
36 #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET	0x24
37 #define MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION	0x2a
38 #define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET		0x30
39 #define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET		0x31
40 #define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET		0x32
41 #define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET		0x33
42 #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET	0x37
43 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET	0x3a
44 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET	0x3b
45 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET	0x40
46 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET	0x41
47 #define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50
48 #define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET	0x51
49 #define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET	0x52
50 #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET		0x58
51 #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET	0x59
52 #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET	0x5a
53 #define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET		0x64
54 #define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET	0x65
55 #define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET	0x66
56 #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET		0x88
57 #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET	0x89
58 #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET	0x8a
59 #define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET	0xe3
60 #define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET	0xe4
61 #define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET	0xe5
62 #define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET	0xe6
63 #define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET	0xe7
64 #define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET	0xe8
65 #define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET	0xe9
66 #define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET	0xeb
67 #define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET	0xec
68 #define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET	0xed
69 #define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET	0xee
70 #define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET	0xef
71 #define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET	0xf0
72 #define MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET	0xf5
73 #define MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET	0xf6
74 #define MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET	0xf7
75 #define MLXPLAT_CPLD_LPC_IO_RANGE		0x100
76 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF		0xdb
77 #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF		0xda
78 
79 #define MLXPLAT_CPLD_LPC_PIO_OFFSET		0x10000UL
80 #define MLXPLAT_CPLD_LPC_REG1	((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
81 				  MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
82 				  MLXPLAT_CPLD_LPC_PIO_OFFSET)
83 #define MLXPLAT_CPLD_LPC_REG2	((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
84 				  MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
85 				  MLXPLAT_CPLD_LPC_PIO_OFFSET)
86 
87 /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */
88 #define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF	0x04
89 #define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF	0x08
90 #define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF	0x08
91 #define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF	0x40
92 #define MLXPLAT_CPLD_AGGR_MASK_DEF	(MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \
93 					 MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
94 					 MLXPLAT_CPLD_AGGR_FAN_MASK_DEF)
95 #define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG	0x01
96 #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF	0x04
97 #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW	0xc1
98 #define MLXPLAT_CPLD_PSU_MASK		GENMASK(1, 0)
99 #define MLXPLAT_CPLD_PWR_MASK		GENMASK(1, 0)
100 #define MLXPLAT_CPLD_FAN_MASK		GENMASK(3, 0)
101 #define MLXPLAT_CPLD_ASIC_MASK		GENMASK(1, 0)
102 #define MLXPLAT_CPLD_FAN_NG_MASK	GENMASK(5, 0)
103 #define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK	GENMASK(7, 4)
104 #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK	GENMASK(3, 0)
105 
106 /* Default I2C parent bus number */
107 #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR	1
108 
109 /* Maximum number of possible physical buses equipped on system */
110 #define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM	16
111 
112 /* Number of channels in group */
113 #define MLXPLAT_CPLD_GRP_CHNL_NUM		8
114 
115 /* Start channel numbers */
116 #define MLXPLAT_CPLD_CH1			2
117 #define MLXPLAT_CPLD_CH2			10
118 
119 /* Number of LPC attached MUX platform devices */
120 #define MLXPLAT_CPLD_LPC_MUX_DEVS		2
121 
122 /* Hotplug devices adapter numbers */
123 #define MLXPLAT_CPLD_NR_NONE			-1
124 #define MLXPLAT_CPLD_PSU_DEFAULT_NR		10
125 #define MLXPLAT_CPLD_PSU_MSNXXXX_NR		4
126 #define MLXPLAT_CPLD_FAN1_DEFAULT_NR		11
127 #define MLXPLAT_CPLD_FAN2_DEFAULT_NR		12
128 #define MLXPLAT_CPLD_FAN3_DEFAULT_NR		13
129 #define MLXPLAT_CPLD_FAN4_DEFAULT_NR		14
130 
131 /* mlxplat_priv - platform private data
132  * @pdev_i2c - i2c controller platform device
133  * @pdev_mux - array of mux platform devices
134  * @pdev_hotplug - hotplug platform devices
135  * @pdev_led - led platform devices
136  * @pdev_io_regs - register access platform devices
137  * @pdev_fan - FAN platform devices
138  */
139 struct mlxplat_priv {
140 	struct platform_device *pdev_i2c;
141 	struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
142 	struct platform_device *pdev_hotplug;
143 	struct platform_device *pdev_led;
144 	struct platform_device *pdev_io_regs;
145 	struct platform_device *pdev_fan;
146 };
147 
148 /* Regions for LPC I2C controller and LPC base register space */
149 static const struct resource mlxplat_lpc_resources[] = {
150 	[0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR,
151 			       MLXPLAT_CPLD_LPC_IO_RANGE,
152 			       "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO),
153 	[1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR,
154 			       MLXPLAT_CPLD_LPC_IO_RANGE,
155 			       "mlxplat_cpld_lpc_regs",
156 			       IORESOURCE_IO),
157 };
158 
159 /* Platform default channels */
160 static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
161 	{
162 		MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
163 		MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
164 		5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7
165 	},
166 	{
167 		MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2,
168 		MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 +
169 		5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7
170 	},
171 };
172 
173 /* Platform channels for MSN21xx system family */
174 static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
175 
176 /* Platform mux data */
177 static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
178 	{
179 		.parent = 1,
180 		.base_nr = MLXPLAT_CPLD_CH1,
181 		.write_only = 1,
182 		.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
183 		.reg_size = 1,
184 		.idle_in_use = 1,
185 	},
186 	{
187 		.parent = 1,
188 		.base_nr = MLXPLAT_CPLD_CH2,
189 		.write_only = 1,
190 		.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
191 		.reg_size = 1,
192 		.idle_in_use = 1,
193 	},
194 
195 };
196 
197 /* Platform hotplug devices */
198 static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
199 	{
200 		I2C_BOARD_INFO("24c02", 0x51),
201 	},
202 	{
203 		I2C_BOARD_INFO("24c02", 0x50),
204 	},
205 };
206 
207 static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = {
208 	{
209 		I2C_BOARD_INFO("24c32", 0x51),
210 	},
211 	{
212 		I2C_BOARD_INFO("24c32", 0x50),
213 	},
214 };
215 
216 static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
217 	{
218 		I2C_BOARD_INFO("dps460", 0x59),
219 	},
220 	{
221 		I2C_BOARD_INFO("dps460", 0x58),
222 	},
223 };
224 
225 static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
226 	{
227 		I2C_BOARD_INFO("24c32", 0x50),
228 	},
229 	{
230 		I2C_BOARD_INFO("24c32", 0x50),
231 	},
232 	{
233 		I2C_BOARD_INFO("24c32", 0x50),
234 	},
235 	{
236 		I2C_BOARD_INFO("24c32", 0x50),
237 	},
238 };
239 
240 /* Platform hotplug default data */
241 static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = {
242 	{
243 		.label = "psu1",
244 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
245 		.mask = BIT(0),
246 		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
247 		.hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
248 	},
249 	{
250 		.label = "psu2",
251 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
252 		.mask = BIT(1),
253 		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
254 		.hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
255 	},
256 };
257 
258 static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = {
259 	{
260 		.label = "pwr1",
261 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
262 		.mask = BIT(0),
263 		.hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
264 		.hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
265 	},
266 	{
267 		.label = "pwr2",
268 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
269 		.mask = BIT(1),
270 		.hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
271 		.hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
272 	},
273 };
274 
275 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
276 	{
277 		.label = "fan1",
278 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
279 		.mask = BIT(0),
280 		.hpdev.brdinfo = &mlxplat_mlxcpld_fan[0],
281 		.hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR,
282 	},
283 	{
284 		.label = "fan2",
285 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
286 		.mask = BIT(1),
287 		.hpdev.brdinfo = &mlxplat_mlxcpld_fan[1],
288 		.hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR,
289 	},
290 	{
291 		.label = "fan3",
292 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
293 		.mask = BIT(2),
294 		.hpdev.brdinfo = &mlxplat_mlxcpld_fan[2],
295 		.hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR,
296 	},
297 	{
298 		.label = "fan4",
299 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
300 		.mask = BIT(3),
301 		.hpdev.brdinfo = &mlxplat_mlxcpld_fan[3],
302 		.hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR,
303 	},
304 };
305 
306 static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = {
307 	{
308 		.label = "asic1",
309 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
310 		.mask = MLXPLAT_CPLD_ASIC_MASK,
311 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
312 	},
313 };
314 
315 static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
316 	{
317 		.data = mlxplat_mlxcpld_default_psu_items_data,
318 		.aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
319 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
320 		.mask = MLXPLAT_CPLD_PSU_MASK,
321 		.count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
322 		.inversed = 1,
323 		.health = false,
324 	},
325 	{
326 		.data = mlxplat_mlxcpld_default_pwr_items_data,
327 		.aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
328 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
329 		.mask = MLXPLAT_CPLD_PWR_MASK,
330 		.count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
331 		.inversed = 0,
332 		.health = false,
333 	},
334 	{
335 		.data = mlxplat_mlxcpld_default_fan_items_data,
336 		.aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
337 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
338 		.mask = MLXPLAT_CPLD_FAN_MASK,
339 		.count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
340 		.inversed = 1,
341 		.health = false,
342 	},
343 	{
344 		.data = mlxplat_mlxcpld_default_asic_items_data,
345 		.aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
346 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
347 		.mask = MLXPLAT_CPLD_ASIC_MASK,
348 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
349 		.inversed = 0,
350 		.health = true,
351 	},
352 };
353 
354 static
355 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
356 	.items = mlxplat_mlxcpld_default_items,
357 	.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
358 	.cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
359 	.mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
360 	.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
361 	.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
362 };
363 
364 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = {
365 	{
366 		.label = "pwr1",
367 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
368 		.mask = BIT(0),
369 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
370 	},
371 	{
372 		.label = "pwr2",
373 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
374 		.mask = BIT(1),
375 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
376 	},
377 };
378 
379 /* Platform hotplug MSN21xx system family data */
380 static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
381 	{
382 		.data = mlxplat_mlxcpld_msn21xx_pwr_items_data,
383 		.aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
384 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
385 		.mask = MLXPLAT_CPLD_PWR_MASK,
386 		.count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data),
387 		.inversed = 0,
388 		.health = false,
389 	},
390 	{
391 		.data = mlxplat_mlxcpld_default_asic_items_data,
392 		.aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
393 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
394 		.mask = MLXPLAT_CPLD_ASIC_MASK,
395 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
396 		.inversed = 0,
397 		.health = true,
398 	},
399 };
400 
401 static
402 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
403 	.items = mlxplat_mlxcpld_msn21xx_items,
404 	.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items),
405 	.cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
406 	.mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
407 	.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
408 	.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
409 };
410 
411 /* Platform hotplug msn274x system family data */
412 static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = {
413 	{
414 		.label = "psu1",
415 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
416 		.mask = BIT(0),
417 		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
418 		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
419 	},
420 	{
421 		.label = "psu2",
422 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
423 		.mask = BIT(1),
424 		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
425 		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
426 	},
427 };
428 
429 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = {
430 	{
431 		.label = "pwr1",
432 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
433 		.mask = BIT(0),
434 		.hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
435 		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
436 	},
437 	{
438 		.label = "pwr2",
439 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
440 		.mask = BIT(1),
441 		.hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
442 		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
443 	},
444 };
445 
446 static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = {
447 	{
448 		.label = "fan1",
449 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
450 		.mask = BIT(0),
451 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
452 	},
453 	{
454 		.label = "fan2",
455 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
456 		.mask = BIT(1),
457 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
458 	},
459 	{
460 		.label = "fan3",
461 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
462 		.mask = BIT(2),
463 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
464 	},
465 	{
466 		.label = "fan4",
467 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
468 		.mask = BIT(3),
469 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
470 	},
471 };
472 
473 static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = {
474 	{
475 		.data = mlxplat_mlxcpld_msn274x_psu_items_data,
476 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
477 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
478 		.mask = MLXPLAT_CPLD_PSU_MASK,
479 		.count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data),
480 		.inversed = 1,
481 		.health = false,
482 	},
483 	{
484 		.data = mlxplat_mlxcpld_default_ng_pwr_items_data,
485 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
486 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
487 		.mask = MLXPLAT_CPLD_PWR_MASK,
488 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
489 		.inversed = 0,
490 		.health = false,
491 	},
492 	{
493 		.data = mlxplat_mlxcpld_msn274x_fan_items_data,
494 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
495 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
496 		.mask = MLXPLAT_CPLD_FAN_MASK,
497 		.count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data),
498 		.inversed = 1,
499 		.health = false,
500 	},
501 	{
502 		.data = mlxplat_mlxcpld_default_asic_items_data,
503 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
504 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
505 		.mask = MLXPLAT_CPLD_ASIC_MASK,
506 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
507 		.inversed = 0,
508 		.health = true,
509 	},
510 };
511 
512 static
513 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = {
514 	.items = mlxplat_mlxcpld_msn274x_items,
515 	.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items),
516 	.cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
517 	.mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
518 	.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
519 	.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
520 };
521 
522 /* Platform hotplug MSN201x system family data */
523 static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = {
524 	{
525 		.label = "pwr1",
526 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
527 		.mask = BIT(0),
528 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
529 	},
530 	{
531 		.label = "pwr2",
532 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
533 		.mask = BIT(1),
534 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
535 	},
536 };
537 
538 static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
539 	{
540 		.data = mlxplat_mlxcpld_msn201x_pwr_items_data,
541 		.aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
542 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
543 		.mask = MLXPLAT_CPLD_PWR_MASK,
544 		.count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data),
545 		.inversed = 0,
546 		.health = false,
547 	},
548 	{
549 		.data = mlxplat_mlxcpld_default_asic_items_data,
550 		.aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
551 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
552 		.mask = MLXPLAT_CPLD_ASIC_MASK,
553 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
554 		.inversed = 0,
555 		.health = true,
556 	},
557 };
558 
559 static
560 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = {
561 	.items = mlxplat_mlxcpld_msn201x_items,
562 	.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items),
563 	.cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
564 	.mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
565 	.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
566 	.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
567 };
568 
569 /* Platform hotplug next generation system family data */
570 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = {
571 	{
572 		.label = "psu1",
573 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
574 		.mask = BIT(0),
575 		.hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0],
576 		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
577 	},
578 	{
579 		.label = "psu2",
580 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
581 		.mask = BIT(1),
582 		.hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1],
583 		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
584 	},
585 };
586 
587 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = {
588 	{
589 		.label = "fan1",
590 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
591 		.mask = BIT(0),
592 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
593 		.bit = BIT(0),
594 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
595 	},
596 	{
597 		.label = "fan2",
598 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
599 		.mask = BIT(1),
600 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
601 		.bit = BIT(1),
602 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
603 	},
604 	{
605 		.label = "fan3",
606 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
607 		.mask = BIT(2),
608 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
609 		.bit = BIT(2),
610 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
611 	},
612 	{
613 		.label = "fan4",
614 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
615 		.mask = BIT(3),
616 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
617 		.bit = BIT(3),
618 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
619 	},
620 	{
621 		.label = "fan5",
622 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
623 		.mask = BIT(4),
624 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
625 		.bit = BIT(4),
626 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
627 	},
628 	{
629 		.label = "fan6",
630 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
631 		.mask = BIT(5),
632 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
633 		.bit = BIT(5),
634 		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
635 	},
636 };
637 
638 static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = {
639 	{
640 		.data = mlxplat_mlxcpld_default_ng_psu_items_data,
641 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
642 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
643 		.mask = MLXPLAT_CPLD_PSU_MASK,
644 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data),
645 		.inversed = 1,
646 		.health = false,
647 	},
648 	{
649 		.data = mlxplat_mlxcpld_default_ng_pwr_items_data,
650 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
651 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
652 		.mask = MLXPLAT_CPLD_PWR_MASK,
653 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
654 		.inversed = 0,
655 		.health = false,
656 	},
657 	{
658 		.data = mlxplat_mlxcpld_default_ng_fan_items_data,
659 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
660 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
661 		.mask = MLXPLAT_CPLD_FAN_NG_MASK,
662 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data),
663 		.inversed = 1,
664 		.health = false,
665 	},
666 	{
667 		.data = mlxplat_mlxcpld_default_asic_items_data,
668 		.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
669 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
670 		.mask = MLXPLAT_CPLD_ASIC_MASK,
671 		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
672 		.inversed = 0,
673 		.health = true,
674 	},
675 };
676 
677 static
678 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
679 	.items = mlxplat_mlxcpld_default_ng_items,
680 	.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items),
681 	.cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
682 	.mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
683 	.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
684 	.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
685 };
686 
687 /* Platform led default data */
688 static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
689 	{
690 		.label = "status:green",
691 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
692 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
693 	},
694 	{
695 		.label = "status:red",
696 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
697 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
698 	},
699 	{
700 		.label = "psu:green",
701 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
702 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
703 	},
704 	{
705 		.label = "psu:red",
706 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
707 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
708 	},
709 	{
710 		.label = "fan1:green",
711 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
712 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
713 	},
714 	{
715 		.label = "fan1:red",
716 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
717 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
718 	},
719 	{
720 		.label = "fan2:green",
721 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
722 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
723 	},
724 	{
725 		.label = "fan2:red",
726 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
727 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
728 	},
729 	{
730 		.label = "fan3:green",
731 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
732 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
733 	},
734 	{
735 		.label = "fan3:red",
736 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
737 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
738 	},
739 	{
740 		.label = "fan4:green",
741 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
742 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
743 	},
744 	{
745 		.label = "fan4:red",
746 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
747 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
748 	},
749 };
750 
751 static struct mlxreg_core_platform_data mlxplat_default_led_data = {
752 		.data = mlxplat_mlxcpld_default_led_data,
753 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
754 };
755 
756 /* Platform led MSN21xx system family data */
757 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
758 	{
759 		.label = "status:green",
760 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
761 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
762 	},
763 	{
764 		.label = "status:red",
765 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
766 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
767 	},
768 	{
769 		.label = "fan:green",
770 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
771 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
772 	},
773 	{
774 		.label = "fan:red",
775 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
776 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
777 	},
778 	{
779 		.label = "psu1:green",
780 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
781 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
782 	},
783 	{
784 		.label = "psu1:red",
785 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
786 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
787 	},
788 	{
789 		.label = "psu2:green",
790 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
791 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
792 	},
793 	{
794 		.label = "psu2:red",
795 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
796 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
797 	},
798 	{
799 		.label = "uid:blue",
800 		.reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
801 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
802 	},
803 };
804 
805 static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
806 		.data = mlxplat_mlxcpld_msn21xx_led_data,
807 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
808 };
809 
810 /* Platform led for default data for 200GbE systems */
811 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
812 	{
813 		.label = "status:green",
814 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
815 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
816 	},
817 	{
818 		.label = "status:orange",
819 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
820 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
821 	},
822 	{
823 		.label = "psu:green",
824 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
825 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
826 	},
827 	{
828 		.label = "psu:orange",
829 		.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
830 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
831 	},
832 	{
833 		.label = "fan1:green",
834 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
835 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
836 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
837 		.bit = BIT(0),
838 	},
839 	{
840 		.label = "fan1:orange",
841 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
842 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
843 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
844 		.bit = BIT(0),
845 	},
846 	{
847 		.label = "fan2:green",
848 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
849 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
850 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
851 		.bit = BIT(1),
852 	},
853 	{
854 		.label = "fan2:orange",
855 		.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
856 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
857 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
858 		.bit = BIT(1),
859 	},
860 	{
861 		.label = "fan3:green",
862 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
863 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
864 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
865 		.bit = BIT(2),
866 	},
867 	{
868 		.label = "fan3:orange",
869 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
870 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
871 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
872 		.bit = BIT(2),
873 	},
874 	{
875 		.label = "fan4:green",
876 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
877 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
878 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
879 		.bit = BIT(3),
880 	},
881 	{
882 		.label = "fan4:orange",
883 		.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
884 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
885 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
886 		.bit = BIT(3),
887 	},
888 	{
889 		.label = "fan5:green",
890 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
891 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
892 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
893 		.bit = BIT(4),
894 	},
895 	{
896 		.label = "fan5:orange",
897 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
898 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
899 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
900 		.bit = BIT(4),
901 	},
902 	{
903 		.label = "fan6:green",
904 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
905 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
906 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
907 		.bit = BIT(5),
908 	},
909 	{
910 		.label = "fan6:orange",
911 		.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
912 		.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
913 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
914 		.bit = BIT(5),
915 	},
916 	{
917 		.label = "uid:blue",
918 		.reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
919 		.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
920 	},
921 };
922 
923 static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
924 		.data = mlxplat_mlxcpld_default_ng_led_data,
925 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
926 };
927 
928 /* Platform register access default */
929 static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
930 	{
931 		.label = "cpld1_version",
932 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
933 		.bit = GENMASK(7, 0),
934 		.mode = 0444,
935 	},
936 	{
937 		.label = "cpld2_version",
938 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
939 		.bit = GENMASK(7, 0),
940 		.mode = 0444,
941 	},
942 	{
943 		.label = "reset_long_pb",
944 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
945 		.mask = GENMASK(7, 0) & ~BIT(0),
946 		.mode = 0444,
947 	},
948 	{
949 		.label = "reset_short_pb",
950 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
951 		.mask = GENMASK(7, 0) & ~BIT(1),
952 		.mode = 0444,
953 	},
954 	{
955 		.label = "reset_aux_pwr_or_ref",
956 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
957 		.mask = GENMASK(7, 0) & ~BIT(2),
958 		.mode = 0444,
959 	},
960 	{
961 		.label = "reset_main_pwr_fail",
962 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
963 		.mask = GENMASK(7, 0) & ~BIT(3),
964 		.mode = 0444,
965 	},
966 	{
967 		.label = "reset_sw_reset",
968 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
969 		.mask = GENMASK(7, 0) & ~BIT(4),
970 		.mode = 0444,
971 	},
972 	{
973 		.label = "reset_fw_reset",
974 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
975 		.mask = GENMASK(7, 0) & ~BIT(5),
976 		.mode = 0444,
977 	},
978 	{
979 		.label = "reset_hotswap_or_wd",
980 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
981 		.mask = GENMASK(7, 0) & ~BIT(6),
982 		.mode = 0444,
983 	},
984 	{
985 		.label = "reset_asic_thermal",
986 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
987 		.mask = GENMASK(7, 0) & ~BIT(7),
988 		.mode = 0444,
989 	},
990 	{
991 		.label = "psu1_on",
992 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
993 		.mask = GENMASK(7, 0) & ~BIT(0),
994 		.mode = 0200,
995 	},
996 	{
997 		.label = "psu2_on",
998 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
999 		.mask = GENMASK(7, 0) & ~BIT(1),
1000 		.mode = 0200,
1001 	},
1002 	{
1003 		.label = "pwr_cycle",
1004 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1005 		.mask = GENMASK(7, 0) & ~BIT(2),
1006 		.mode = 0200,
1007 	},
1008 	{
1009 		.label = "pwr_down",
1010 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1011 		.mask = GENMASK(7, 0) & ~BIT(3),
1012 		.mode = 0200,
1013 	},
1014 	{
1015 		.label = "select_iio",
1016 		.reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
1017 		.mask = GENMASK(7, 0) & ~BIT(6),
1018 		.mode = 0644,
1019 	},
1020 	{
1021 		.label = "asic_health",
1022 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
1023 		.mask = MLXPLAT_CPLD_ASIC_MASK,
1024 		.bit = 1,
1025 		.mode = 0444,
1026 	},
1027 };
1028 
1029 static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = {
1030 		.data = mlxplat_mlxcpld_default_regs_io_data,
1031 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data),
1032 };
1033 
1034 /* Platform register access MSN21xx, MSN201x, MSN274x systems families data */
1035 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
1036 	{
1037 		.label = "cpld1_version",
1038 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
1039 		.bit = GENMASK(7, 0),
1040 		.mode = 0444,
1041 	},
1042 	{
1043 		.label = "cpld2_version",
1044 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
1045 		.bit = GENMASK(7, 0),
1046 		.mode = 0444,
1047 	},
1048 	{
1049 		.label = "reset_long_pb",
1050 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1051 		.mask = GENMASK(7, 0) & ~BIT(0),
1052 		.mode = 0444,
1053 	},
1054 	{
1055 		.label = "reset_short_pb",
1056 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1057 		.mask = GENMASK(7, 0) & ~BIT(1),
1058 		.mode = 0444,
1059 	},
1060 	{
1061 		.label = "reset_aux_pwr_or_ref",
1062 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1063 		.mask = GENMASK(7, 0) & ~BIT(2),
1064 		.mode = 0444,
1065 	},
1066 	{
1067 		.label = "reset_sw_reset",
1068 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1069 		.mask = GENMASK(7, 0) & ~BIT(3),
1070 		.mode = 0444,
1071 	},
1072 	{
1073 		.label = "reset_main_pwr_fail",
1074 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1075 		.mask = GENMASK(7, 0) & ~BIT(4),
1076 		.mode = 0444,
1077 	},
1078 	{
1079 		.label = "reset_asic_thermal",
1080 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1081 		.mask = GENMASK(7, 0) & ~BIT(5),
1082 		.mode = 0444,
1083 	},
1084 	{
1085 		.label = "reset_hotswap_or_halt",
1086 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1087 		.mask = GENMASK(7, 0) & ~BIT(6),
1088 		.mode = 0444,
1089 	},
1090 	{
1091 		.label = "psu1_on",
1092 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1093 		.mask = GENMASK(7, 0) & ~BIT(0),
1094 		.mode = 0200,
1095 	},
1096 	{
1097 		.label = "psu2_on",
1098 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1099 		.mask = GENMASK(7, 0) & ~BIT(1),
1100 		.mode = 0200,
1101 	},
1102 	{
1103 		.label = "pwr_cycle",
1104 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1105 		.mask = GENMASK(7, 0) & ~BIT(2),
1106 		.mode = 0200,
1107 	},
1108 	{
1109 		.label = "pwr_down",
1110 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1111 		.mask = GENMASK(7, 0) & ~BIT(3),
1112 		.mode = 0200,
1113 	},
1114 	{
1115 		.label = "asic_health",
1116 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
1117 		.mask = MLXPLAT_CPLD_ASIC_MASK,
1118 		.bit = 1,
1119 		.mode = 0444,
1120 	},
1121 };
1122 
1123 static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = {
1124 		.data = mlxplat_mlxcpld_msn21xx_regs_io_data,
1125 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data),
1126 };
1127 
1128 /* Platform register access for next generation systems families data */
1129 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
1130 	{
1131 		.label = "cpld1_version",
1132 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
1133 		.bit = GENMASK(7, 0),
1134 		.mode = 0444,
1135 	},
1136 	{
1137 		.label = "cpld2_version",
1138 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
1139 		.bit = GENMASK(7, 0),
1140 		.mode = 0444,
1141 	},
1142 	{
1143 		.label = "cpld3_version",
1144 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET,
1145 		.bit = GENMASK(7, 0),
1146 		.mode = 0444,
1147 	},
1148 	{
1149 		.label = "cpld4_version",
1150 		.reg = MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET,
1151 		.bit = GENMASK(7, 0),
1152 		.mode = 0444,
1153 	},
1154 	{
1155 		.label = "reset_long_pb",
1156 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1157 		.mask = GENMASK(7, 0) & ~BIT(0),
1158 		.mode = 0444,
1159 	},
1160 	{
1161 		.label = "reset_short_pb",
1162 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1163 		.mask = GENMASK(7, 0) & ~BIT(1),
1164 		.mode = 0444,
1165 	},
1166 	{
1167 		.label = "reset_aux_pwr_or_ref",
1168 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1169 		.mask = GENMASK(7, 0) & ~BIT(2),
1170 		.mode = 0444,
1171 	},
1172 	{
1173 		.label = "reset_from_comex",
1174 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1175 		.mask = GENMASK(7, 0) & ~BIT(4),
1176 		.mode = 0444,
1177 	},
1178 	{
1179 		.label = "reset_asic_thermal",
1180 		.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1181 		.mask = GENMASK(7, 0) & ~BIT(7),
1182 		.mode = 0444,
1183 	},
1184 	{
1185 		.label = "reset_comex_pwr_fail",
1186 		.reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET,
1187 		.mask = GENMASK(7, 0) & ~BIT(3),
1188 		.mode = 0444,
1189 	},
1190 	{
1191 		.label = "reset_voltmon_upgrade_fail",
1192 		.reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET,
1193 		.mask = GENMASK(7, 0) & ~BIT(0),
1194 		.mode = 0444,
1195 	},
1196 	{
1197 		.label = "reset_system",
1198 		.reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET,
1199 		.mask = GENMASK(7, 0) & ~BIT(1),
1200 		.mode = 0444,
1201 	},
1202 	{
1203 		.label = "psu1_on",
1204 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1205 		.mask = GENMASK(7, 0) & ~BIT(0),
1206 		.mode = 0200,
1207 	},
1208 	{
1209 		.label = "psu2_on",
1210 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1211 		.mask = GENMASK(7, 0) & ~BIT(1),
1212 		.mode = 0200,
1213 	},
1214 	{
1215 		.label = "pwr_cycle",
1216 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1217 		.mask = GENMASK(7, 0) & ~BIT(2),
1218 		.mode = 0200,
1219 	},
1220 	{
1221 		.label = "pwr_down",
1222 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1223 		.mask = GENMASK(7, 0) & ~BIT(3),
1224 		.mode = 0200,
1225 	},
1226 	{
1227 		.label = "jtag_enable",
1228 		.reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
1229 		.mask = GENMASK(7, 0) & ~BIT(4),
1230 		.mode = 0644,
1231 	},
1232 	{
1233 		.label = "asic_health",
1234 		.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
1235 		.mask = MLXPLAT_CPLD_ASIC_MASK,
1236 		.bit = 1,
1237 		.mode = 0444,
1238 	},
1239 	{
1240 		.label = "fan_dir",
1241 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION,
1242 		.bit = GENMASK(7, 0),
1243 		.mode = 0444,
1244 	},
1245 };
1246 
1247 static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = {
1248 		.data = mlxplat_mlxcpld_default_ng_regs_io_data,
1249 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_regs_io_data),
1250 };
1251 
1252 /* Platform FAN default */
1253 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
1254 	{
1255 		.label = "pwm1",
1256 		.reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET,
1257 	},
1258 	{
1259 		.label = "tacho1",
1260 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET,
1261 		.mask = GENMASK(7, 0),
1262 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1263 		.bit = BIT(0),
1264 	},
1265 	{
1266 		.label = "tacho2",
1267 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET,
1268 		.mask = GENMASK(7, 0),
1269 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1270 		.bit = BIT(1),
1271 	},
1272 	{
1273 		.label = "tacho3",
1274 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET,
1275 		.mask = GENMASK(7, 0),
1276 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1277 		.bit = BIT(2),
1278 	},
1279 	{
1280 		.label = "tacho4",
1281 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET,
1282 		.mask = GENMASK(7, 0),
1283 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1284 		.bit = BIT(3),
1285 	},
1286 	{
1287 		.label = "tacho5",
1288 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET,
1289 		.mask = GENMASK(7, 0),
1290 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1291 		.bit = BIT(4),
1292 	},
1293 	{
1294 		.label = "tacho6",
1295 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET,
1296 		.mask = GENMASK(7, 0),
1297 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1298 		.bit = BIT(5),
1299 	},
1300 	{
1301 		.label = "tacho7",
1302 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET,
1303 		.mask = GENMASK(7, 0),
1304 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1305 		.bit = BIT(6),
1306 	},
1307 	{
1308 		.label = "tacho8",
1309 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET,
1310 		.mask = GENMASK(7, 0),
1311 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
1312 		.bit = BIT(7),
1313 	},
1314 	{
1315 		.label = "tacho9",
1316 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET,
1317 		.mask = GENMASK(7, 0),
1318 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
1319 		.bit = BIT(0),
1320 	},
1321 	{
1322 		.label = "tacho10",
1323 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET,
1324 		.mask = GENMASK(7, 0),
1325 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
1326 		.bit = BIT(1),
1327 	},
1328 	{
1329 		.label = "tacho11",
1330 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET,
1331 		.mask = GENMASK(7, 0),
1332 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
1333 		.bit = BIT(2),
1334 	},
1335 	{
1336 		.label = "tacho12",
1337 		.reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
1338 		.mask = GENMASK(7, 0),
1339 		.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
1340 		.bit = BIT(3),
1341 	},
1342 };
1343 
1344 static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
1345 		.data = mlxplat_mlxcpld_default_fan_data,
1346 		.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
1347 };
1348 
1349 static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
1350 {
1351 	switch (reg) {
1352 	case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
1353 	case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
1354 	case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
1355 	case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
1356 	case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
1357 	case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
1358 	case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
1359 	case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
1360 	case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
1361 	case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
1362 	case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
1363 	case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
1364 	case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
1365 	case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
1366 	case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
1367 	case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
1368 	case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
1369 	case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
1370 	case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
1371 	case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
1372 	case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
1373 		return true;
1374 	}
1375 	return false;
1376 }
1377 
1378 static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
1379 {
1380 	switch (reg) {
1381 	case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
1382 	case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
1383 	case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
1384 	case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
1385 	case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
1386 	case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
1387 	case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
1388 	case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
1389 	case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
1390 	case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
1391 	case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
1392 	case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
1393 	case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION:
1394 	case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
1395 	case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
1396 	case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
1397 	case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
1398 	case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
1399 	case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
1400 	case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
1401 	case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
1402 	case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
1403 	case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
1404 	case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
1405 	case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
1406 	case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
1407 	case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
1408 	case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
1409 	case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
1410 	case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
1411 	case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
1412 	case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
1413 	case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
1414 	case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
1415 	case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
1416 	case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
1417 	case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
1418 	case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
1419 	case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
1420 	case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
1421 	case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
1422 	case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
1423 	case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
1424 	case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
1425 	case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
1426 	case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
1427 	case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
1428 	case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET:
1429 	case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET:
1430 	case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET:
1431 		return true;
1432 	}
1433 	return false;
1434 }
1435 
1436 static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
1437 {
1438 	switch (reg) {
1439 	case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
1440 	case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
1441 	case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
1442 	case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
1443 	case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
1444 	case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
1445 	case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
1446 	case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
1447 	case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
1448 	case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
1449 	case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
1450 	case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
1451 	case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION:
1452 	case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
1453 	case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
1454 	case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
1455 	case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
1456 	case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
1457 	case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
1458 	case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
1459 	case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
1460 	case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
1461 	case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
1462 	case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
1463 	case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
1464 	case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
1465 	case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
1466 	case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
1467 	case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
1468 	case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
1469 	case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
1470 	case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
1471 	case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
1472 	case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
1473 	case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
1474 	case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
1475 	case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
1476 	case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
1477 	case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
1478 	case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
1479 	case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
1480 	case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
1481 	case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
1482 	case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
1483 	case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
1484 	case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET:
1485 	case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET:
1486 	case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET:
1487 		return true;
1488 	}
1489 	return false;
1490 }
1491 
1492 static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
1493 	{ MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
1494 	{ MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
1495 	{ MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
1496 };
1497 
1498 struct mlxplat_mlxcpld_regmap_context {
1499 	void __iomem *base;
1500 };
1501 
1502 static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
1503 
1504 static int
1505 mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
1506 {
1507 	struct mlxplat_mlxcpld_regmap_context *ctx = context;
1508 
1509 	*val = ioread8(ctx->base + reg);
1510 	return 0;
1511 }
1512 
1513 static int
1514 mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val)
1515 {
1516 	struct mlxplat_mlxcpld_regmap_context *ctx = context;
1517 
1518 	iowrite8(val, ctx->base + reg);
1519 	return 0;
1520 }
1521 
1522 static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
1523 	.reg_bits = 8,
1524 	.val_bits = 8,
1525 	.max_register = 255,
1526 	.cache_type = REGCACHE_FLAT,
1527 	.writeable_reg = mlxplat_mlxcpld_writeable_reg,
1528 	.readable_reg = mlxplat_mlxcpld_readable_reg,
1529 	.volatile_reg = mlxplat_mlxcpld_volatile_reg,
1530 	.reg_defaults = mlxplat_mlxcpld_regmap_default,
1531 	.num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default),
1532 	.reg_read = mlxplat_mlxcpld_reg_read,
1533 	.reg_write = mlxplat_mlxcpld_reg_write,
1534 };
1535 
1536 static struct resource mlxplat_mlxcpld_resources[] = {
1537 	[0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
1538 };
1539 
1540 static struct platform_device *mlxplat_dev;
1541 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
1542 static struct mlxreg_core_platform_data *mlxplat_led;
1543 static struct mlxreg_core_platform_data *mlxplat_regs_io;
1544 static struct mlxreg_core_platform_data *mlxplat_fan;
1545 
1546 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
1547 {
1548 	int i;
1549 
1550 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1551 		mlxplat_mux_data[i].values = mlxplat_default_channels[i];
1552 		mlxplat_mux_data[i].n_values =
1553 				ARRAY_SIZE(mlxplat_default_channels[i]);
1554 	}
1555 	mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
1556 	mlxplat_hotplug->deferred_nr =
1557 		mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1558 	mlxplat_led = &mlxplat_default_led_data;
1559 	mlxplat_regs_io = &mlxplat_default_regs_io_data;
1560 
1561 	return 1;
1562 };
1563 
1564 static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
1565 {
1566 	int i;
1567 
1568 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1569 		mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1570 		mlxplat_mux_data[i].n_values =
1571 				ARRAY_SIZE(mlxplat_msn21xx_channels);
1572 	}
1573 	mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
1574 	mlxplat_hotplug->deferred_nr =
1575 		mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1576 	mlxplat_led = &mlxplat_msn21xx_led_data;
1577 	mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
1578 
1579 	return 1;
1580 };
1581 
1582 static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
1583 {
1584 	int i;
1585 
1586 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1587 		mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1588 		mlxplat_mux_data[i].n_values =
1589 				ARRAY_SIZE(mlxplat_msn21xx_channels);
1590 	}
1591 	mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
1592 	mlxplat_hotplug->deferred_nr =
1593 		mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1594 	mlxplat_led = &mlxplat_default_led_data;
1595 	mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
1596 
1597 	return 1;
1598 };
1599 
1600 static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
1601 {
1602 	int i;
1603 
1604 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1605 		mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1606 		mlxplat_mux_data[i].n_values =
1607 				ARRAY_SIZE(mlxplat_msn21xx_channels);
1608 	}
1609 	mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
1610 	mlxplat_hotplug->deferred_nr =
1611 		mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1612 	mlxplat_led = &mlxplat_msn21xx_led_data;
1613 	mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
1614 
1615 	return 1;
1616 };
1617 
1618 static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
1619 {
1620 	int i;
1621 
1622 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1623 		mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1624 		mlxplat_mux_data[i].n_values =
1625 				ARRAY_SIZE(mlxplat_msn21xx_channels);
1626 	}
1627 	mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
1628 	mlxplat_hotplug->deferred_nr =
1629 		mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1630 	mlxplat_led = &mlxplat_default_ng_led_data;
1631 	mlxplat_regs_io = &mlxplat_default_ng_regs_io_data;
1632 	mlxplat_fan = &mlxplat_default_fan_data;
1633 
1634 	return 1;
1635 };
1636 
1637 static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
1638 	{
1639 		.callback = mlxplat_dmi_msn274x_matched,
1640 		.matches = {
1641 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1642 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN274"),
1643 		},
1644 	},
1645 	{
1646 		.callback = mlxplat_dmi_default_matched,
1647 		.matches = {
1648 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1649 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
1650 		},
1651 	},
1652 	{
1653 		.callback = mlxplat_dmi_default_matched,
1654 		.matches = {
1655 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1656 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
1657 		},
1658 	},
1659 	{
1660 		.callback = mlxplat_dmi_default_matched,
1661 		.matches = {
1662 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1663 			DMI_MATCH(DMI_PRODUCT_NAME, "MSB"),
1664 		},
1665 	},
1666 	{
1667 		.callback = mlxplat_dmi_default_matched,
1668 		.matches = {
1669 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1670 			DMI_MATCH(DMI_PRODUCT_NAME, "MSX"),
1671 		},
1672 	},
1673 	{
1674 		.callback = mlxplat_dmi_msn21xx_matched,
1675 		.matches = {
1676 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1677 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"),
1678 		},
1679 	},
1680 	{
1681 		.callback = mlxplat_dmi_msn201x_matched,
1682 		.matches = {
1683 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1684 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN201"),
1685 		},
1686 	},
1687 	{
1688 		.callback = mlxplat_dmi_qmb7xx_matched,
1689 		.matches = {
1690 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1691 			DMI_MATCH(DMI_PRODUCT_NAME, "MQM87"),
1692 		},
1693 	},
1694 	{
1695 		.callback = mlxplat_dmi_qmb7xx_matched,
1696 		.matches = {
1697 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1698 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"),
1699 		},
1700 	},
1701 	{
1702 		.callback = mlxplat_dmi_qmb7xx_matched,
1703 		.matches = {
1704 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1705 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"),
1706 		},
1707 	},
1708 	{
1709 		.callback = mlxplat_dmi_qmb7xx_matched,
1710 		.matches = {
1711 			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1712 			DMI_MATCH(DMI_PRODUCT_NAME, "MSN38"),
1713 		},
1714 	},
1715 	{
1716 		.callback = mlxplat_dmi_default_matched,
1717 		.matches = {
1718 			DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
1719 		},
1720 	},
1721 	{
1722 		.callback = mlxplat_dmi_msn21xx_matched,
1723 		.matches = {
1724 			DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
1725 		},
1726 	},
1727 	{
1728 		.callback = mlxplat_dmi_msn274x_matched,
1729 		.matches = {
1730 			DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
1731 		},
1732 	},
1733 	{
1734 		.callback = mlxplat_dmi_msn201x_matched,
1735 		.matches = {
1736 			DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
1737 		},
1738 	},
1739 	{
1740 		.callback = mlxplat_dmi_qmb7xx_matched,
1741 		.matches = {
1742 			DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
1743 		},
1744 	},
1745 	{
1746 		.callback = mlxplat_dmi_qmb7xx_matched,
1747 		.matches = {
1748 			DMI_MATCH(DMI_BOARD_NAME, "VMOD0007"),
1749 		},
1750 	},
1751 	{ }
1752 };
1753 
1754 MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
1755 
1756 static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
1757 {
1758 	struct i2c_adapter *search_adap;
1759 	int shift, i;
1760 
1761 	/* Scan adapters from expected id to verify it is free. */
1762 	*nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
1763 	for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
1764 	     MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
1765 		search_adap = i2c_get_adapter(i);
1766 		if (search_adap) {
1767 			i2c_put_adapter(search_adap);
1768 			continue;
1769 		}
1770 
1771 		/* Return if expected parent adapter is free. */
1772 		if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
1773 			return 0;
1774 		break;
1775 	}
1776 
1777 	/* Return with error if free id for adapter is not found. */
1778 	if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
1779 		return -ENODEV;
1780 
1781 	/* Shift adapter ids, since expected parent adapter is not free. */
1782 	*nr = i;
1783 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1784 		shift = *nr - mlxplat_mux_data[i].parent;
1785 		mlxplat_mux_data[i].parent = *nr;
1786 		mlxplat_mux_data[i].base_nr += shift;
1787 		if (shift > 0)
1788 			mlxplat_hotplug->shift_nr = shift;
1789 	}
1790 
1791 	return 0;
1792 }
1793 
1794 static int __init mlxplat_init(void)
1795 {
1796 	struct mlxplat_priv *priv;
1797 	int i, j, nr, err;
1798 
1799 	if (!dmi_check_system(mlxplat_dmi_table))
1800 		return -ENODEV;
1801 
1802 	mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1,
1803 					mlxplat_lpc_resources,
1804 					ARRAY_SIZE(mlxplat_lpc_resources));
1805 
1806 	if (IS_ERR(mlxplat_dev))
1807 		return PTR_ERR(mlxplat_dev);
1808 
1809 	priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
1810 			    GFP_KERNEL);
1811 	if (!priv) {
1812 		err = -ENOMEM;
1813 		goto fail_alloc;
1814 	}
1815 	platform_set_drvdata(mlxplat_dev, priv);
1816 
1817 	err = mlxplat_mlxcpld_verify_bus_topology(&nr);
1818 	if (nr < 0)
1819 		goto fail_alloc;
1820 
1821 	nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
1822 	priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
1823 							 NULL, 0);
1824 	if (IS_ERR(priv->pdev_i2c)) {
1825 		err = PTR_ERR(priv->pdev_i2c);
1826 		goto fail_alloc;
1827 	}
1828 
1829 	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1830 		priv->pdev_mux[i] = platform_device_register_resndata(
1831 						&mlxplat_dev->dev,
1832 						"i2c-mux-reg", i, NULL,
1833 						0, &mlxplat_mux_data[i],
1834 						sizeof(mlxplat_mux_data[i]));
1835 		if (IS_ERR(priv->pdev_mux[i])) {
1836 			err = PTR_ERR(priv->pdev_mux[i]);
1837 			goto fail_platform_mux_register;
1838 		}
1839 	}
1840 
1841 	mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev,
1842 			       mlxplat_lpc_resources[1].start, 1);
1843 	if (!mlxplat_mlxcpld_regmap_ctx.base) {
1844 		err = -ENOMEM;
1845 		goto fail_platform_mux_register;
1846 	}
1847 
1848 	mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
1849 					&mlxplat_mlxcpld_regmap_ctx,
1850 					&mlxplat_mlxcpld_regmap_config);
1851 	if (IS_ERR(mlxplat_hotplug->regmap)) {
1852 		err = PTR_ERR(mlxplat_hotplug->regmap);
1853 		goto fail_platform_mux_register;
1854 	}
1855 
1856 	priv->pdev_hotplug = platform_device_register_resndata(
1857 				&mlxplat_dev->dev, "mlxreg-hotplug",
1858 				PLATFORM_DEVID_NONE,
1859 				mlxplat_mlxcpld_resources,
1860 				ARRAY_SIZE(mlxplat_mlxcpld_resources),
1861 				mlxplat_hotplug, sizeof(*mlxplat_hotplug));
1862 	if (IS_ERR(priv->pdev_hotplug)) {
1863 		err = PTR_ERR(priv->pdev_hotplug);
1864 		goto fail_platform_mux_register;
1865 	}
1866 
1867 	/* Set default registers. */
1868 	for (j = 0; j <  mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) {
1869 		err = regmap_write(mlxplat_hotplug->regmap,
1870 				   mlxplat_mlxcpld_regmap_default[j].reg,
1871 				   mlxplat_mlxcpld_regmap_default[j].def);
1872 		if (err)
1873 			goto fail_platform_mux_register;
1874 	}
1875 
1876 	/* Add LED driver. */
1877 	mlxplat_led->regmap = mlxplat_hotplug->regmap;
1878 	priv->pdev_led = platform_device_register_resndata(
1879 				&mlxplat_dev->dev, "leds-mlxreg",
1880 				PLATFORM_DEVID_NONE, NULL, 0,
1881 				mlxplat_led, sizeof(*mlxplat_led));
1882 	if (IS_ERR(priv->pdev_led)) {
1883 		err = PTR_ERR(priv->pdev_led);
1884 		goto fail_platform_hotplug_register;
1885 	}
1886 
1887 	/* Add registers io access driver. */
1888 	if (mlxplat_regs_io) {
1889 		mlxplat_regs_io->regmap = mlxplat_hotplug->regmap;
1890 		priv->pdev_io_regs = platform_device_register_resndata(
1891 					&mlxplat_dev->dev, "mlxreg-io",
1892 					PLATFORM_DEVID_NONE, NULL, 0,
1893 					mlxplat_regs_io,
1894 					sizeof(*mlxplat_regs_io));
1895 		if (IS_ERR(priv->pdev_io_regs)) {
1896 			err = PTR_ERR(priv->pdev_io_regs);
1897 			goto fail_platform_led_register;
1898 		}
1899 	}
1900 
1901 	/* Add FAN driver. */
1902 	if (mlxplat_fan) {
1903 		mlxplat_fan->regmap = mlxplat_hotplug->regmap;
1904 		priv->pdev_fan = platform_device_register_resndata(
1905 					&mlxplat_dev->dev, "mlxreg-fan",
1906 					PLATFORM_DEVID_NONE, NULL, 0,
1907 					mlxplat_fan,
1908 					sizeof(*mlxplat_fan));
1909 		if (IS_ERR(priv->pdev_fan)) {
1910 			err = PTR_ERR(priv->pdev_fan);
1911 			goto fail_platform_io_regs_register;
1912 		}
1913 	}
1914 
1915 	/* Sync registers with hardware. */
1916 	regcache_mark_dirty(mlxplat_hotplug->regmap);
1917 	err = regcache_sync(mlxplat_hotplug->regmap);
1918 	if (err)
1919 		goto fail_platform_fan_register;
1920 
1921 	return 0;
1922 
1923 fail_platform_fan_register:
1924 	if (mlxplat_fan)
1925 		platform_device_unregister(priv->pdev_fan);
1926 fail_platform_io_regs_register:
1927 	if (mlxplat_regs_io)
1928 		platform_device_unregister(priv->pdev_io_regs);
1929 fail_platform_led_register:
1930 	platform_device_unregister(priv->pdev_led);
1931 fail_platform_hotplug_register:
1932 	platform_device_unregister(priv->pdev_hotplug);
1933 fail_platform_mux_register:
1934 	while (--i >= 0)
1935 		platform_device_unregister(priv->pdev_mux[i]);
1936 	platform_device_unregister(priv->pdev_i2c);
1937 fail_alloc:
1938 	platform_device_unregister(mlxplat_dev);
1939 
1940 	return err;
1941 }
1942 module_init(mlxplat_init);
1943 
1944 static void __exit mlxplat_exit(void)
1945 {
1946 	struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
1947 	int i;
1948 
1949 	if (priv->pdev_fan)
1950 		platform_device_unregister(priv->pdev_fan);
1951 	if (priv->pdev_io_regs)
1952 		platform_device_unregister(priv->pdev_io_regs);
1953 	platform_device_unregister(priv->pdev_led);
1954 	platform_device_unregister(priv->pdev_hotplug);
1955 
1956 	for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
1957 		platform_device_unregister(priv->pdev_mux[i]);
1958 
1959 	platform_device_unregister(priv->pdev_i2c);
1960 	platform_device_unregister(mlxplat_dev);
1961 }
1962 module_exit(mlxplat_exit);
1963 
1964 MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
1965 MODULE_DESCRIPTION("Mellanox platform driver");
1966 MODULE_LICENSE("Dual BSD/GPL");
1967