2 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
3 * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
34 #include <linux/device.h>
35 #include <linux/dmi.h>
36 #include <linux/i2c.h>
37 #include <linux/i2c-mux.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>
45 #define MLX_PLAT_DEVICE_NAME "mlxplat"
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
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)
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)
123 /* Default I2C parent bus number */
124 #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
126 /* Maximum number of possible physical buses equipped on system */
127 #define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
129 /* Number of channels in group */
130 #define MLXPLAT_CPLD_GRP_CHNL_NUM 8
132 /* Start channel numbers */
133 #define MLXPLAT_CPLD_CH1 2
134 #define MLXPLAT_CPLD_CH2 10
136 /* Number of LPC attached MUX platform devices */
137 #define MLXPLAT_CPLD_LPC_MUX_DEVS 2
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
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
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;
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",
176 /* Platform default channels */
177 static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
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
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
190 /* Platform channels for MSN21xx system family */
191 static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
193 /* Platform mux data */
194 static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
197 .base_nr = MLXPLAT_CPLD_CH1,
199 .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
205 .base_nr = MLXPLAT_CPLD_CH2,
207 .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
214 /* Platform hotplug devices */
215 static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
217 I2C_BOARD_INFO("dps460", 0x59),
220 I2C_BOARD_INFO("dps460", 0x58),
224 static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
226 I2C_BOARD_INFO("24c32", 0x50),
229 I2C_BOARD_INFO("24c32", 0x50),
232 I2C_BOARD_INFO("24c32", 0x50),
235 I2C_BOARD_INFO("24c32", 0x50),
239 /* Platform hotplug default data */
240 static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = {
243 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
245 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
249 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
251 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
255 static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = {
258 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
260 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
261 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
265 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
267 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
268 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
272 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
275 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
277 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0],
278 .hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR,
282 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
284 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1],
285 .hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR,
289 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
291 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2],
292 .hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR,
296 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
298 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3],
299 .hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR,
303 static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = {
306 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
307 .mask = MLXPLAT_CPLD_ASIC_MASK,
308 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
312 static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
314 .data = mlxplat_mlxcpld_default_psu_items_data,
315 .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
316 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
317 .mask = MLXPLAT_CPLD_PSU_MASK,
318 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_psu_items_data),
323 .data = mlxplat_mlxcpld_default_pwr_items_data,
324 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
325 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
326 .mask = MLXPLAT_CPLD_PWR_MASK,
327 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_items_data),
332 .data = mlxplat_mlxcpld_default_fan_items_data,
333 .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
334 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
335 .mask = MLXPLAT_CPLD_FAN_MASK,
336 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_items_data),
341 .data = mlxplat_mlxcpld_default_asic_items_data,
342 .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
343 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
344 .mask = MLXPLAT_CPLD_ASIC_MASK,
345 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
352 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
353 .items = mlxplat_mlxcpld_default_items,
354 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
355 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
356 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
357 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
358 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
361 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = {
364 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
366 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
370 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
372 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
376 /* Platform hotplug MSN21xx system family data */
377 static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
379 .data = mlxplat_mlxcpld_msn21xx_pwr_items_data,
380 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
381 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
382 .mask = MLXPLAT_CPLD_PWR_MASK,
383 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data),
388 .data = mlxplat_mlxcpld_default_asic_items_data,
389 .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
390 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
391 .mask = MLXPLAT_CPLD_ASIC_MASK,
392 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
399 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
400 .items = mlxplat_mlxcpld_msn21xx_items,
401 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items),
402 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
403 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
404 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
405 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
408 /* Platform hotplug msn274x system family data */
409 static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = {
412 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
414 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
418 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
420 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
424 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = {
427 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
429 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
430 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
434 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
436 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
437 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
441 static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = {
444 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
446 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
450 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
452 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
456 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
458 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
462 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
464 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
468 static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = {
470 .data = mlxplat_mlxcpld_msn274x_psu_items_data,
471 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
472 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
473 .mask = MLXPLAT_CPLD_PSU_MASK,
474 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data),
479 .data = mlxplat_mlxcpld_default_ng_pwr_items_data,
480 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
481 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
482 .mask = MLXPLAT_CPLD_PWR_MASK,
483 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
488 .data = mlxplat_mlxcpld_msn274x_fan_items_data,
489 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
490 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
491 .mask = MLXPLAT_CPLD_FAN_MASK,
492 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data),
497 .data = mlxplat_mlxcpld_default_asic_items_data,
498 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
499 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
500 .mask = MLXPLAT_CPLD_ASIC_MASK,
501 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
508 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = {
509 .items = mlxplat_mlxcpld_msn274x_items,
510 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items),
511 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
512 .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
513 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
514 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
517 /* Platform hotplug MSN201x system family data */
518 static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = {
521 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
523 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
527 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
529 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
533 static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
535 .data = mlxplat_mlxcpld_msn201x_pwr_items_data,
536 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
537 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
538 .mask = MLXPLAT_CPLD_PWR_MASK,
539 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data),
544 .data = mlxplat_mlxcpld_default_asic_items_data,
545 .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
546 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
547 .mask = MLXPLAT_CPLD_ASIC_MASK,
548 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
555 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = {
556 .items = mlxplat_mlxcpld_msn201x_items,
557 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items),
558 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
559 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
560 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
561 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
564 /* Platform hotplug next generation system family data */
565 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = {
568 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
570 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
574 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
576 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
580 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = {
583 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
585 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
589 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
591 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
595 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
597 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
601 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
603 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
607 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
609 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
613 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
615 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
619 static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = {
621 .data = mlxplat_mlxcpld_default_ng_psu_items_data,
622 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
623 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
624 .mask = MLXPLAT_CPLD_PSU_MASK,
625 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data),
630 .data = mlxplat_mlxcpld_default_ng_pwr_items_data,
631 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
632 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
633 .mask = MLXPLAT_CPLD_PWR_MASK,
634 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
639 .data = mlxplat_mlxcpld_default_ng_fan_items_data,
640 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
641 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
642 .mask = MLXPLAT_CPLD_FAN_NG_MASK,
643 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data),
648 .data = mlxplat_mlxcpld_default_asic_items_data,
649 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
650 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
651 .mask = MLXPLAT_CPLD_ASIC_MASK,
652 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
659 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
660 .items = mlxplat_mlxcpld_default_ng_items,
661 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items),
662 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
663 .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
664 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
665 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
668 /* Platform led default data */
669 static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
671 .label = "status:green",
672 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
673 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
676 .label = "status:red",
677 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
678 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
681 .label = "psu:green",
682 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
683 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
687 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
688 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
691 .label = "fan1:green",
692 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
693 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
697 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
698 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
701 .label = "fan2:green",
702 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
703 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
707 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
708 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
711 .label = "fan3:green",
712 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
713 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
717 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
718 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
721 .label = "fan4:green",
722 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
723 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
727 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
728 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
732 static struct mlxreg_core_platform_data mlxplat_default_led_data = {
733 .data = mlxplat_mlxcpld_default_led_data,
734 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
737 /* Platform led MSN21xx system family data */
738 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
740 .label = "status:green",
741 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
742 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
745 .label = "status:red",
746 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
747 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
750 .label = "fan:green",
751 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
752 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
756 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
757 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
760 .label = "psu1:green",
761 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
762 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
766 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
767 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
770 .label = "psu2:green",
771 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
772 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
776 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
777 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
781 .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
782 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
786 static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
787 .data = mlxplat_mlxcpld_msn21xx_led_data,
788 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
791 /* Platform led for default data for 200GbE systems */
792 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
794 .label = "status:green",
795 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
796 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
799 .label = "status:orange",
800 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
801 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
804 .label = "psu:green",
805 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
806 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
809 .label = "psu:orange",
810 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
811 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
814 .label = "fan1:green",
815 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
816 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
819 .label = "fan1:orange",
820 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
821 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
824 .label = "fan2:green",
825 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
826 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
829 .label = "fan2:orange",
830 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
831 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
834 .label = "fan3:green",
835 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
836 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
839 .label = "fan3:orange",
840 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
841 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
844 .label = "fan4:green",
845 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
846 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
849 .label = "fan4:orange",
850 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
851 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
854 .label = "fan5:green",
855 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
856 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
859 .label = "fan5:orange",
860 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
861 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
864 .label = "fan6:green",
865 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
866 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
869 .label = "fan6:orange",
870 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
871 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
875 static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
876 .data = mlxplat_mlxcpld_default_ng_led_data,
877 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
880 /* Platform register access default */
881 static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
883 .label = "cpld1_version",
884 .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
885 .bit = GENMASK(7, 0),
889 .label = "cpld2_version",
890 .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
891 .bit = GENMASK(7, 0),
895 .label = "reset_long_pb",
896 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
897 .mask = GENMASK(7, 0) & ~BIT(0),
901 .label = "reset_short_pb",
902 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
903 .mask = GENMASK(7, 0) & ~BIT(1),
907 .label = "reset_aux_pwr_or_ref",
908 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
909 .mask = GENMASK(7, 0) & ~BIT(2),
913 .label = "reset_main_pwr_fail",
914 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
915 .mask = GENMASK(7, 0) & ~BIT(3),
919 .label = "reset_sw_reset",
920 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
921 .mask = GENMASK(7, 0) & ~BIT(4),
925 .label = "reset_fw_reset",
926 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
927 .mask = GENMASK(7, 0) & ~BIT(5),
931 .label = "reset_hotswap_or_wd",
932 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
933 .mask = GENMASK(7, 0) & ~BIT(6),
937 .label = "reset_asic_thermal",
938 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
939 .mask = GENMASK(7, 0) & ~BIT(7),
944 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
945 .mask = GENMASK(7, 0) & ~BIT(0),
950 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
951 .mask = GENMASK(7, 0) & ~BIT(1),
955 .label = "pwr_cycle",
956 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
957 .mask = GENMASK(7, 0) & ~BIT(2),
962 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
963 .mask = GENMASK(7, 0) & ~BIT(3),
967 .label = "select_iio",
968 .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
969 .mask = GENMASK(7, 0) & ~BIT(6),
973 .label = "asic_health",
974 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
975 .mask = MLXPLAT_CPLD_ASIC_MASK,
981 static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = {
982 .data = mlxplat_mlxcpld_default_regs_io_data,
983 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data),
986 /* Platform register access MSN21xx, MSN201x, MSN274x systems families data */
987 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
989 .label = "cpld1_version",
990 .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
991 .bit = GENMASK(7, 0),
995 .label = "cpld2_version",
996 .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
997 .bit = GENMASK(7, 0),
1001 .label = "reset_long_pb",
1002 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1003 .mask = GENMASK(7, 0) & ~BIT(0),
1007 .label = "reset_short_pb",
1008 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1009 .mask = GENMASK(7, 0) & ~BIT(1),
1013 .label = "reset_aux_pwr_or_ref",
1014 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1015 .mask = GENMASK(7, 0) & ~BIT(2),
1019 .label = "reset_sw_reset",
1020 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1021 .mask = GENMASK(7, 0) & ~BIT(3),
1025 .label = "reset_main_pwr_fail",
1026 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1027 .mask = GENMASK(7, 0) & ~BIT(4),
1031 .label = "reset_asic_thermal",
1032 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1033 .mask = GENMASK(7, 0) & ~BIT(5),
1037 .label = "reset_hotswap_or_halt",
1038 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
1039 .mask = GENMASK(7, 0) & ~BIT(6),
1044 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1045 .mask = GENMASK(7, 0) & ~BIT(0),
1050 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1051 .mask = GENMASK(7, 0) & ~BIT(1),
1055 .label = "pwr_cycle",
1056 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1057 .mask = GENMASK(7, 0) & ~BIT(2),
1061 .label = "pwr_down",
1062 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
1063 .mask = GENMASK(7, 0) & ~BIT(3),
1067 .label = "asic_health",
1068 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
1069 .mask = MLXPLAT_CPLD_ASIC_MASK,
1075 static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = {
1076 .data = mlxplat_mlxcpld_msn21xx_regs_io_data,
1077 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data),
1080 /* Platform FAN default */
1081 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
1084 .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET,
1088 .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET,
1089 .mask = GENMASK(7, 0),
1093 .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET,
1094 .mask = GENMASK(7, 0),
1098 .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET,
1099 .mask = GENMASK(7, 0),
1103 .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET,
1104 .mask = GENMASK(7, 0),
1108 .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET,
1109 .mask = GENMASK(7, 0),
1113 .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET,
1114 .mask = GENMASK(7, 0),
1118 .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET,
1119 .mask = GENMASK(7, 0),
1123 .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET,
1124 .mask = GENMASK(7, 0),
1128 .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET,
1129 .mask = GENMASK(7, 0),
1133 .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET,
1134 .mask = GENMASK(7, 0),
1138 .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET,
1139 .mask = GENMASK(7, 0),
1143 .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
1144 .mask = GENMASK(7, 0),
1148 static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
1149 .data = mlxplat_mlxcpld_default_fan_data,
1150 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
1153 static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
1156 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
1157 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
1158 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
1159 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
1160 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
1161 case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
1162 case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
1163 case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
1164 case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
1165 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
1166 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
1167 case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
1168 case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
1169 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
1170 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
1171 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
1172 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
1173 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
1174 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
1175 case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
1176 case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
1182 static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
1185 case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
1186 case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
1187 case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
1188 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
1189 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
1190 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
1191 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
1192 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
1193 case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
1194 case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
1195 case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
1196 case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
1197 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
1198 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
1199 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
1200 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
1201 case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
1202 case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
1203 case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
1204 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
1205 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
1206 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
1207 case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
1208 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
1209 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
1210 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
1211 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
1212 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
1213 case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
1214 case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
1215 case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
1216 case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
1217 case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
1218 case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
1219 case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
1220 case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
1221 case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
1222 case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
1223 case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
1224 case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
1225 case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
1226 case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
1232 static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
1235 case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
1236 case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
1237 case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
1238 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
1239 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
1240 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
1241 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
1242 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
1243 case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
1244 case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
1245 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
1246 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
1247 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
1248 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
1249 case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
1250 case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
1251 case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
1252 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
1253 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
1254 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
1255 case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
1256 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
1257 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
1258 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
1259 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
1260 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
1261 case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
1262 case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
1263 case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
1264 case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
1265 case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
1266 case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
1267 case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
1268 case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
1269 case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
1270 case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
1271 case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
1272 case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
1273 case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
1274 case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
1280 static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
1281 { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
1282 { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
1283 { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
1286 struct mlxplat_mlxcpld_regmap_context {
1290 static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
1293 mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
1295 struct mlxplat_mlxcpld_regmap_context *ctx = context;
1297 *val = ioread8(ctx->base + reg);
1302 mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val)
1304 struct mlxplat_mlxcpld_regmap_context *ctx = context;
1306 iowrite8(val, ctx->base + reg);
1310 static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
1313 .max_register = 255,
1314 .cache_type = REGCACHE_FLAT,
1315 .writeable_reg = mlxplat_mlxcpld_writeable_reg,
1316 .readable_reg = mlxplat_mlxcpld_readable_reg,
1317 .volatile_reg = mlxplat_mlxcpld_volatile_reg,
1318 .reg_defaults = mlxplat_mlxcpld_regmap_default,
1319 .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default),
1320 .reg_read = mlxplat_mlxcpld_reg_read,
1321 .reg_write = mlxplat_mlxcpld_reg_write,
1324 static struct resource mlxplat_mlxcpld_resources[] = {
1325 [0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
1328 static struct platform_device *mlxplat_dev;
1329 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
1330 static struct mlxreg_core_platform_data *mlxplat_led;
1331 static struct mlxreg_core_platform_data *mlxplat_regs_io;
1332 static struct mlxreg_core_platform_data *mlxplat_fan;
1334 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
1338 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1339 mlxplat_mux_data[i].values = mlxplat_default_channels[i];
1340 mlxplat_mux_data[i].n_values =
1341 ARRAY_SIZE(mlxplat_default_channels[i]);
1343 mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
1344 mlxplat_hotplug->deferred_nr =
1345 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1346 mlxplat_led = &mlxplat_default_led_data;
1347 mlxplat_regs_io = &mlxplat_default_regs_io_data;
1352 static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
1356 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1357 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1358 mlxplat_mux_data[i].n_values =
1359 ARRAY_SIZE(mlxplat_msn21xx_channels);
1361 mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
1362 mlxplat_hotplug->deferred_nr =
1363 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1364 mlxplat_led = &mlxplat_msn21xx_led_data;
1365 mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
1370 static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
1374 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1375 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1376 mlxplat_mux_data[i].n_values =
1377 ARRAY_SIZE(mlxplat_msn21xx_channels);
1379 mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
1380 mlxplat_hotplug->deferred_nr =
1381 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1382 mlxplat_led = &mlxplat_default_led_data;
1383 mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
1388 static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
1392 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1393 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1394 mlxplat_mux_data[i].n_values =
1395 ARRAY_SIZE(mlxplat_msn21xx_channels);
1397 mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
1398 mlxplat_hotplug->deferred_nr =
1399 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1400 mlxplat_led = &mlxplat_msn21xx_led_data;
1401 mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
1406 static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
1410 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1411 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1412 mlxplat_mux_data[i].n_values =
1413 ARRAY_SIZE(mlxplat_msn21xx_channels);
1415 mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
1416 mlxplat_hotplug->deferred_nr =
1417 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
1418 mlxplat_led = &mlxplat_default_ng_led_data;
1419 mlxplat_fan = &mlxplat_default_fan_data;
1424 static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
1426 .callback = mlxplat_dmi_msn274x_matched,
1428 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1429 DMI_MATCH(DMI_PRODUCT_NAME, "MSN274"),
1433 .callback = mlxplat_dmi_default_matched,
1435 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1436 DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
1440 .callback = mlxplat_dmi_default_matched,
1442 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1443 DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
1447 .callback = mlxplat_dmi_default_matched,
1449 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1450 DMI_MATCH(DMI_PRODUCT_NAME, "MSB"),
1454 .callback = mlxplat_dmi_default_matched,
1456 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1457 DMI_MATCH(DMI_PRODUCT_NAME, "MSX"),
1461 .callback = mlxplat_dmi_msn21xx_matched,
1463 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1464 DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"),
1468 .callback = mlxplat_dmi_msn201x_matched,
1470 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1471 DMI_MATCH(DMI_PRODUCT_NAME, "MSN201"),
1475 .callback = mlxplat_dmi_qmb7xx_matched,
1477 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1478 DMI_MATCH(DMI_PRODUCT_NAME, "QMB7"),
1482 .callback = mlxplat_dmi_qmb7xx_matched,
1484 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1485 DMI_MATCH(DMI_PRODUCT_NAME, "SN37"),
1489 .callback = mlxplat_dmi_qmb7xx_matched,
1491 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1492 DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
1496 .callback = mlxplat_dmi_default_matched,
1498 DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
1502 .callback = mlxplat_dmi_msn21xx_matched,
1504 DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
1508 .callback = mlxplat_dmi_msn274x_matched,
1510 DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
1514 .callback = mlxplat_dmi_msn201x_matched,
1516 DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
1520 .callback = mlxplat_dmi_qmb7xx_matched,
1522 DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
1528 MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
1530 static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
1532 struct i2c_adapter *search_adap;
1535 /* Scan adapters from expected id to verify it is free. */
1536 *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
1537 for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
1538 MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
1539 search_adap = i2c_get_adapter(i);
1541 i2c_put_adapter(search_adap);
1545 /* Return if expected parent adapter is free. */
1546 if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
1551 /* Return with error if free id for adapter is not found. */
1552 if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
1555 /* Shift adapter ids, since expected parent adapter is not free. */
1557 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1558 shift = *nr - mlxplat_mux_data[i].parent;
1559 mlxplat_mux_data[i].parent = *nr;
1560 mlxplat_mux_data[i].base_nr += shift;
1562 mlxplat_hotplug->shift_nr = shift;
1568 static int __init mlxplat_init(void)
1570 struct mlxplat_priv *priv;
1573 if (!dmi_check_system(mlxplat_dmi_table))
1576 mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1,
1577 mlxplat_lpc_resources,
1578 ARRAY_SIZE(mlxplat_lpc_resources));
1580 if (IS_ERR(mlxplat_dev))
1581 return PTR_ERR(mlxplat_dev);
1583 priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
1589 platform_set_drvdata(mlxplat_dev, priv);
1591 err = mlxplat_mlxcpld_verify_bus_topology(&nr);
1595 nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
1596 priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
1598 if (IS_ERR(priv->pdev_i2c)) {
1599 err = PTR_ERR(priv->pdev_i2c);
1603 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1604 priv->pdev_mux[i] = platform_device_register_resndata(
1605 &priv->pdev_i2c->dev,
1606 "i2c-mux-reg", i, NULL,
1607 0, &mlxplat_mux_data[i],
1608 sizeof(mlxplat_mux_data[i]));
1609 if (IS_ERR(priv->pdev_mux[i])) {
1610 err = PTR_ERR(priv->pdev_mux[i]);
1611 goto fail_platform_mux_register;
1615 mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev,
1616 mlxplat_lpc_resources[1].start, 1);
1617 if (!mlxplat_mlxcpld_regmap_ctx.base) {
1619 goto fail_platform_mux_register;
1622 mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
1623 &mlxplat_mlxcpld_regmap_ctx,
1624 &mlxplat_mlxcpld_regmap_config);
1625 if (IS_ERR(mlxplat_hotplug->regmap)) {
1626 err = PTR_ERR(mlxplat_hotplug->regmap);
1627 goto fail_platform_mux_register;
1630 priv->pdev_hotplug = platform_device_register_resndata(
1631 &mlxplat_dev->dev, "mlxreg-hotplug",
1632 PLATFORM_DEVID_NONE,
1633 mlxplat_mlxcpld_resources,
1634 ARRAY_SIZE(mlxplat_mlxcpld_resources),
1635 mlxplat_hotplug, sizeof(*mlxplat_hotplug));
1636 if (IS_ERR(priv->pdev_hotplug)) {
1637 err = PTR_ERR(priv->pdev_hotplug);
1638 goto fail_platform_mux_register;
1641 /* Set default registers. */
1642 for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) {
1643 err = regmap_write(mlxplat_hotplug->regmap,
1644 mlxplat_mlxcpld_regmap_default[j].reg,
1645 mlxplat_mlxcpld_regmap_default[j].def);
1647 goto fail_platform_mux_register;
1650 /* Add LED driver. */
1651 mlxplat_led->regmap = mlxplat_hotplug->regmap;
1652 priv->pdev_led = platform_device_register_resndata(
1653 &mlxplat_dev->dev, "leds-mlxreg",
1654 PLATFORM_DEVID_NONE, NULL, 0,
1655 mlxplat_led, sizeof(*mlxplat_led));
1656 if (IS_ERR(priv->pdev_led)) {
1657 err = PTR_ERR(priv->pdev_led);
1658 goto fail_platform_hotplug_register;
1661 /* Add registers io access driver. */
1662 if (mlxplat_regs_io) {
1663 mlxplat_regs_io->regmap = mlxplat_hotplug->regmap;
1664 priv->pdev_io_regs = platform_device_register_resndata(
1665 &mlxplat_dev->dev, "mlxreg-io",
1666 PLATFORM_DEVID_NONE, NULL, 0,
1668 sizeof(*mlxplat_regs_io));
1669 if (IS_ERR(priv->pdev_io_regs)) {
1670 err = PTR_ERR(priv->pdev_io_regs);
1671 goto fail_platform_led_register;
1675 /* Add FAN driver. */
1677 mlxplat_fan->regmap = mlxplat_hotplug->regmap;
1678 priv->pdev_fan = platform_device_register_resndata(
1679 &mlxplat_dev->dev, "mlxreg-fan",
1680 PLATFORM_DEVID_NONE, NULL, 0,
1682 sizeof(*mlxplat_fan));
1683 if (IS_ERR(priv->pdev_fan)) {
1684 err = PTR_ERR(priv->pdev_fan);
1685 goto fail_platform_io_regs_register;
1689 /* Sync registers with hardware. */
1690 regcache_mark_dirty(mlxplat_hotplug->regmap);
1691 err = regcache_sync(mlxplat_hotplug->regmap);
1693 goto fail_platform_fan_register;
1697 fail_platform_fan_register:
1699 platform_device_unregister(priv->pdev_fan);
1700 fail_platform_io_regs_register:
1701 if (mlxplat_regs_io)
1702 platform_device_unregister(priv->pdev_io_regs);
1703 fail_platform_led_register:
1704 platform_device_unregister(priv->pdev_led);
1705 fail_platform_hotplug_register:
1706 platform_device_unregister(priv->pdev_hotplug);
1707 fail_platform_mux_register:
1709 platform_device_unregister(priv->pdev_mux[i]);
1710 platform_device_unregister(priv->pdev_i2c);
1712 platform_device_unregister(mlxplat_dev);
1716 module_init(mlxplat_init);
1718 static void __exit mlxplat_exit(void)
1720 struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
1724 platform_device_unregister(priv->pdev_fan);
1725 if (priv->pdev_io_regs)
1726 platform_device_unregister(priv->pdev_io_regs);
1727 platform_device_unregister(priv->pdev_led);
1728 platform_device_unregister(priv->pdev_hotplug);
1730 for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
1731 platform_device_unregister(priv->pdev_mux[i]);
1733 platform_device_unregister(priv->pdev_i2c);
1734 platform_device_unregister(mlxplat_dev);
1736 module_exit(mlxplat_exit);
1738 MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
1739 MODULE_DESCRIPTION("Mellanox platform driver");
1740 MODULE_LICENSE("Dual BSD/GPL");