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