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