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