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