xref: /linux/drivers/platform/mellanox/nvsw-sn2201.c (revision 3c4fc7bf4c9e66fe71abcbf93f62f4ddb89b7f15)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Nvidia sn2201 driver
4  *
5  * Copyright (C) 2022 Nvidia Technologies Ltd.
6  */
7 
8 #include <linux/device.h>
9 #include <linux/i2c.h>
10 #include <linux/interrupt.h>
11 #include <linux/irq.h>
12 #include <linux/gpio.h>
13 #include <linux/module.h>
14 #include <linux/platform_data/mlxcpld.h>
15 #include <linux/platform_data/mlxreg.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 
19 /* SN2201 CPLD register offset. */
20 #define NVSW_SN2201_CPLD_LPC_I2C_BASE_ADRR          0x2000
21 #define NVSW_SN2201_CPLD_LPC_IO_RANGE               0x100
22 #define NVSW_SN2201_HW_VER_ID_OFFSET                0x00
23 #define NVSW_SN2201_BOARD_ID_OFFSET                 0x01
24 #define NVSW_SN2201_CPLD_VER_OFFSET                 0x02
25 #define NVSW_SN2201_CPLD_MVER_OFFSET                0x03
26 #define NVSW_SN2201_CPLD_ID_OFFSET                  0x04
27 #define NVSW_SN2201_CPLD_PN_OFFSET                  0x05
28 #define NVSW_SN2201_CPLD_PN1_OFFSET                 0x06
29 #define NVSW_SN2201_PSU_CTRL_OFFSET                 0x0a
30 #define NVSW_SN2201_QSFP28_STATUS_OFFSET            0x0b
31 #define NVSW_SN2201_QSFP28_INT_STATUS_OFFSET        0x0c
32 #define NVSW_SN2201_QSFP28_LP_STATUS_OFFSET         0x0d
33 #define NVSW_SN2201_QSFP28_RST_STATUS_OFFSET        0x0e
34 #define NVSW_SN2201_SYS_STATUS_OFFSET               0x0f
35 #define NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET       0x10
36 #define NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET       0x12
37 #define NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET       0x13
38 #define NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET   0x14
39 #define NVSW_SN2201_SYS_RST_STATUS_OFFSET           0x15
40 #define NVSW_SN2201_SYS_INT_STATUS_OFFSET           0x21
41 #define NVSW_SN2201_SYS_INT_MASK_OFFSET             0x22
42 #define NVSW_SN2201_ASIC_STATUS_OFFSET              0x24
43 #define NVSW_SN2201_ASIC_EVENT_OFFSET               0x25
44 #define NVSW_SN2201_ASIC_MAKS_OFFSET                0x26
45 #define NVSW_SN2201_THML_STATUS_OFFSET              0x27
46 #define NVSW_SN2201_THML_EVENT_OFFSET               0x28
47 #define NVSW_SN2201_THML_MASK_OFFSET                0x29
48 #define NVSW_SN2201_PS_ALT_STATUS_OFFSET            0x2a
49 #define NVSW_SN2201_PS_ALT_EVENT_OFFSET             0x2b
50 #define NVSW_SN2201_PS_ALT_MASK_OFFSET              0x2c
51 #define NVSW_SN2201_PS_PRSNT_STATUS_OFFSET          0x30
52 #define NVSW_SN2201_PS_PRSNT_EVENT_OFFSET           0x31
53 #define NVSW_SN2201_PS_PRSNT_MASK_OFFSET            0x32
54 #define NVSW_SN2201_PS_DC_OK_STATUS_OFFSET          0x33
55 #define NVSW_SN2201_PS_DC_OK_EVENT_OFFSET           0x34
56 #define NVSW_SN2201_PS_DC_OK_MASK_OFFSET            0x35
57 #define NVSW_SN2201_RST_CAUSE1_OFFSET               0x36
58 #define NVSW_SN2201_RST_CAUSE2_OFFSET               0x37
59 #define NVSW_SN2201_RST_SW_CTRL_OFFSET              0x38
60 #define NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET         0x3a
61 #define NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET          0x3b
62 #define NVSW_SN2201_FAN_PRSNT_MASK_OFFSET           0x3c
63 #define NVSW_SN2201_WD_TMR_OFFSET_LSB               0x40
64 #define NVSW_SN2201_WD_TMR_OFFSET_MSB               0x41
65 #define NVSW_SN2201_WD_ACT_OFFSET                   0x42
66 #define NVSW_SN2201_FAN_LED1_CTRL_OFFSET            0x50
67 #define NVSW_SN2201_FAN_LED2_CTRL_OFFSET            0x51
68 #define NVSW_SN2201_REG_MAX                         0x52
69 
70 /* Number of physical I2C busses. */
71 #define NVSW_SN2201_PHY_I2C_BUS_NUM		2
72 /* Number of main mux channels. */
73 #define NVSW_SN2201_MAIN_MUX_CHNL_NUM		8
74 
75 #define NVSW_SN2201_MAIN_NR			0
76 #define NVSW_SN2201_MAIN_MUX_NR			1
77 #define NVSW_SN2201_MAIN_MUX_DEFER_NR		(NVSW_SN2201_PHY_I2C_BUS_NUM + \
78 						 NVSW_SN2201_MAIN_MUX_CHNL_NUM - 1)
79 
80 #define NVSW_SN2201_MAIN_MUX_CH0_NR	NVSW_SN2201_PHY_I2C_BUS_NUM
81 #define NVSW_SN2201_MAIN_MUX_CH1_NR	(NVSW_SN2201_MAIN_MUX_CH0_NR + 1)
82 #define NVSW_SN2201_MAIN_MUX_CH2_NR	(NVSW_SN2201_MAIN_MUX_CH0_NR + 2)
83 #define NVSW_SN2201_MAIN_MUX_CH3_NR	(NVSW_SN2201_MAIN_MUX_CH0_NR + 3)
84 #define NVSW_SN2201_MAIN_MUX_CH5_NR	(NVSW_SN2201_MAIN_MUX_CH0_NR + 5)
85 #define NVSW_SN2201_MAIN_MUX_CH6_NR	(NVSW_SN2201_MAIN_MUX_CH0_NR + 6)
86 #define NVSW_SN2201_MAIN_MUX_CH7_NR	(NVSW_SN2201_MAIN_MUX_CH0_NR + 7)
87 
88 #define NVSW_SN2201_CPLD_NR		NVSW_SN2201_MAIN_MUX_CH0_NR
89 #define NVSW_SN2201_NR_NONE		-1
90 
91 /* Masks for aggregation, PSU presence and power, ASIC events
92  * in CPLD related registers.
93  */
94 #define NVSW_SN2201_CPLD_AGGR_ASIC_MASK_DEF	0xe0
95 #define NVSW_SN2201_CPLD_AGGR_PSU_MASK_DEF	0x04
96 #define NVSW_SN2201_CPLD_AGGR_PWR_MASK_DEF	0x02
97 #define NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF	0x10
98 #define NVSW_SN2201_CPLD_AGGR_MASK_DEF      \
99 	(NVSW_SN2201_CPLD_AGGR_ASIC_MASK_DEF \
100 	| NVSW_SN2201_CPLD_AGGR_PSU_MASK_DEF \
101 	| NVSW_SN2201_CPLD_AGGR_PWR_MASK_DEF \
102 	| NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF)
103 
104 #define NVSW_SN2201_CPLD_ASIC_MASK		GENMASK(3, 1)
105 #define NVSW_SN2201_CPLD_PSU_MASK		GENMASK(1, 0)
106 #define NVSW_SN2201_CPLD_PWR_MASK		GENMASK(1, 0)
107 #define NVSW_SN2201_CPLD_FAN_MASK		GENMASK(3, 0)
108 
109 #define NVSW_SN2201_CPLD_SYSIRQ			26
110 #define NVSW_SN2201_LPC_SYSIRQ			28
111 #define NVSW_SN2201_CPLD_I2CADDR		0x41
112 
113 #define NVSW_SN2201_WD_DFLT_TIMEOUT		600
114 
115 /* nvsw_sn2201 - device private data
116  * @dev: platform device;
117  * @io_data: register access platform data;
118  * @led_data: LED platform data;
119  * @hotplug_data: hotplug platform data;
120  * @i2c_data: I2C controller platform data;
121  * @led: LED device;
122  * @io_regs: register access device;
123  * @pdev_hotplug: hotplug device;
124  * @sn2201_devs: I2C devices for sn2201 devices;
125  * @sn2201_devs_num: number of I2C devices for sn2201 device;
126  * @main_mux_devs: I2C devices for main mux;
127  * @main_mux_devs_num: number of I2C devices for main mux;
128  * @cpld_devs: I2C devices for cpld;
129  * @cpld_devs_num: number of I2C devices for cpld;
130  * @main_mux_deferred_nr: I2C adapter number must be exist prior creating devices execution;
131  */
132 struct nvsw_sn2201 {
133 	struct device *dev;
134 	struct mlxreg_core_platform_data *io_data;
135 	struct mlxreg_core_platform_data *led_data;
136 	struct mlxreg_core_platform_data *wd_data;
137 	struct mlxreg_core_hotplug_platform_data *hotplug_data;
138 	struct mlxreg_core_hotplug_platform_data *i2c_data;
139 	struct platform_device *led;
140 	struct platform_device *wd;
141 	struct platform_device *io_regs;
142 	struct platform_device *pdev_hotplug;
143 	struct platform_device *pdev_i2c;
144 	struct mlxreg_hotplug_device *sn2201_devs;
145 	int sn2201_devs_num;
146 	struct mlxreg_hotplug_device *main_mux_devs;
147 	int main_mux_devs_num;
148 	struct mlxreg_hotplug_device *cpld_devs;
149 	int cpld_devs_num;
150 	int main_mux_deferred_nr;
151 };
152 
153 static bool nvsw_sn2201_writeable_reg(struct device *dev, unsigned int reg)
154 {
155 	switch (reg) {
156 	case NVSW_SN2201_PSU_CTRL_OFFSET:
157 	case NVSW_SN2201_QSFP28_LP_STATUS_OFFSET:
158 	case NVSW_SN2201_QSFP28_RST_STATUS_OFFSET:
159 	case NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET:
160 	case NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET:
161 	case NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET:
162 	case NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET:
163 	case NVSW_SN2201_SYS_RST_STATUS_OFFSET:
164 	case NVSW_SN2201_SYS_INT_MASK_OFFSET:
165 	case NVSW_SN2201_ASIC_EVENT_OFFSET:
166 	case NVSW_SN2201_ASIC_MAKS_OFFSET:
167 	case NVSW_SN2201_THML_EVENT_OFFSET:
168 	case NVSW_SN2201_THML_MASK_OFFSET:
169 	case NVSW_SN2201_PS_ALT_EVENT_OFFSET:
170 	case NVSW_SN2201_PS_ALT_MASK_OFFSET:
171 	case NVSW_SN2201_PS_PRSNT_EVENT_OFFSET:
172 	case NVSW_SN2201_PS_PRSNT_MASK_OFFSET:
173 	case NVSW_SN2201_PS_DC_OK_EVENT_OFFSET:
174 	case NVSW_SN2201_PS_DC_OK_MASK_OFFSET:
175 	case NVSW_SN2201_RST_SW_CTRL_OFFSET:
176 	case NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET:
177 	case NVSW_SN2201_FAN_PRSNT_MASK_OFFSET:
178 	case NVSW_SN2201_WD_TMR_OFFSET_LSB:
179 	case NVSW_SN2201_WD_TMR_OFFSET_MSB:
180 	case NVSW_SN2201_WD_ACT_OFFSET:
181 	case NVSW_SN2201_FAN_LED1_CTRL_OFFSET:
182 	case NVSW_SN2201_FAN_LED2_CTRL_OFFSET:
183 		return true;
184 	}
185 	return false;
186 }
187 
188 static bool nvsw_sn2201_readable_reg(struct device *dev, unsigned int reg)
189 {
190 	switch (reg) {
191 	case NVSW_SN2201_HW_VER_ID_OFFSET:
192 	case NVSW_SN2201_BOARD_ID_OFFSET:
193 	case NVSW_SN2201_CPLD_VER_OFFSET:
194 	case NVSW_SN2201_CPLD_MVER_OFFSET:
195 	case NVSW_SN2201_CPLD_ID_OFFSET:
196 	case NVSW_SN2201_CPLD_PN_OFFSET:
197 	case NVSW_SN2201_CPLD_PN1_OFFSET:
198 	case NVSW_SN2201_PSU_CTRL_OFFSET:
199 	case NVSW_SN2201_QSFP28_STATUS_OFFSET:
200 	case NVSW_SN2201_QSFP28_INT_STATUS_OFFSET:
201 	case NVSW_SN2201_QSFP28_LP_STATUS_OFFSET:
202 	case NVSW_SN2201_QSFP28_RST_STATUS_OFFSET:
203 	case NVSW_SN2201_SYS_STATUS_OFFSET:
204 	case NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET:
205 	case NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET:
206 	case NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET:
207 	case NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET:
208 	case NVSW_SN2201_SYS_RST_STATUS_OFFSET:
209 	case NVSW_SN2201_RST_CAUSE1_OFFSET:
210 	case NVSW_SN2201_RST_CAUSE2_OFFSET:
211 	case NVSW_SN2201_SYS_INT_STATUS_OFFSET:
212 	case NVSW_SN2201_SYS_INT_MASK_OFFSET:
213 	case NVSW_SN2201_ASIC_STATUS_OFFSET:
214 	case NVSW_SN2201_ASIC_EVENT_OFFSET:
215 	case NVSW_SN2201_ASIC_MAKS_OFFSET:
216 	case NVSW_SN2201_THML_STATUS_OFFSET:
217 	case NVSW_SN2201_THML_EVENT_OFFSET:
218 	case NVSW_SN2201_THML_MASK_OFFSET:
219 	case NVSW_SN2201_PS_ALT_STATUS_OFFSET:
220 	case NVSW_SN2201_PS_ALT_EVENT_OFFSET:
221 	case NVSW_SN2201_PS_ALT_MASK_OFFSET:
222 	case NVSW_SN2201_PS_PRSNT_STATUS_OFFSET:
223 	case NVSW_SN2201_PS_PRSNT_EVENT_OFFSET:
224 	case NVSW_SN2201_PS_PRSNT_MASK_OFFSET:
225 	case NVSW_SN2201_PS_DC_OK_STATUS_OFFSET:
226 	case NVSW_SN2201_PS_DC_OK_EVENT_OFFSET:
227 	case NVSW_SN2201_PS_DC_OK_MASK_OFFSET:
228 	case NVSW_SN2201_RST_SW_CTRL_OFFSET:
229 	case NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET:
230 	case NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET:
231 	case NVSW_SN2201_FAN_PRSNT_MASK_OFFSET:
232 	case NVSW_SN2201_WD_TMR_OFFSET_LSB:
233 	case NVSW_SN2201_WD_TMR_OFFSET_MSB:
234 	case NVSW_SN2201_WD_ACT_OFFSET:
235 	case NVSW_SN2201_FAN_LED1_CTRL_OFFSET:
236 	case NVSW_SN2201_FAN_LED2_CTRL_OFFSET:
237 		return true;
238 	}
239 	return false;
240 }
241 
242 static bool nvsw_sn2201_volatile_reg(struct device *dev, unsigned int reg)
243 {
244 	switch (reg) {
245 	case NVSW_SN2201_HW_VER_ID_OFFSET:
246 	case NVSW_SN2201_BOARD_ID_OFFSET:
247 	case NVSW_SN2201_CPLD_VER_OFFSET:
248 	case NVSW_SN2201_CPLD_MVER_OFFSET:
249 	case NVSW_SN2201_CPLD_ID_OFFSET:
250 	case NVSW_SN2201_CPLD_PN_OFFSET:
251 	case NVSW_SN2201_CPLD_PN1_OFFSET:
252 	case NVSW_SN2201_PSU_CTRL_OFFSET:
253 	case NVSW_SN2201_QSFP28_STATUS_OFFSET:
254 	case NVSW_SN2201_QSFP28_INT_STATUS_OFFSET:
255 	case NVSW_SN2201_QSFP28_LP_STATUS_OFFSET:
256 	case NVSW_SN2201_QSFP28_RST_STATUS_OFFSET:
257 	case NVSW_SN2201_SYS_STATUS_OFFSET:
258 	case NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET:
259 	case NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET:
260 	case NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET:
261 	case NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET:
262 	case NVSW_SN2201_SYS_RST_STATUS_OFFSET:
263 	case NVSW_SN2201_RST_CAUSE1_OFFSET:
264 	case NVSW_SN2201_RST_CAUSE2_OFFSET:
265 	case NVSW_SN2201_SYS_INT_STATUS_OFFSET:
266 	case NVSW_SN2201_SYS_INT_MASK_OFFSET:
267 	case NVSW_SN2201_ASIC_STATUS_OFFSET:
268 	case NVSW_SN2201_ASIC_EVENT_OFFSET:
269 	case NVSW_SN2201_ASIC_MAKS_OFFSET:
270 	case NVSW_SN2201_THML_STATUS_OFFSET:
271 	case NVSW_SN2201_THML_EVENT_OFFSET:
272 	case NVSW_SN2201_THML_MASK_OFFSET:
273 	case NVSW_SN2201_PS_ALT_STATUS_OFFSET:
274 	case NVSW_SN2201_PS_ALT_EVENT_OFFSET:
275 	case NVSW_SN2201_PS_ALT_MASK_OFFSET:
276 	case NVSW_SN2201_PS_PRSNT_STATUS_OFFSET:
277 	case NVSW_SN2201_PS_PRSNT_EVENT_OFFSET:
278 	case NVSW_SN2201_PS_PRSNT_MASK_OFFSET:
279 	case NVSW_SN2201_PS_DC_OK_STATUS_OFFSET:
280 	case NVSW_SN2201_PS_DC_OK_EVENT_OFFSET:
281 	case NVSW_SN2201_PS_DC_OK_MASK_OFFSET:
282 	case NVSW_SN2201_RST_SW_CTRL_OFFSET:
283 	case NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET:
284 	case NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET:
285 	case NVSW_SN2201_FAN_PRSNT_MASK_OFFSET:
286 	case NVSW_SN2201_WD_TMR_OFFSET_LSB:
287 	case NVSW_SN2201_WD_TMR_OFFSET_MSB:
288 	case NVSW_SN2201_FAN_LED1_CTRL_OFFSET:
289 	case NVSW_SN2201_FAN_LED2_CTRL_OFFSET:
290 		return true;
291 	}
292 	return false;
293 }
294 
295 static const struct reg_default nvsw_sn2201_regmap_default[] = {
296 	{ NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET, 0x00 },
297 	{ NVSW_SN2201_WD_ACT_OFFSET, 0x00 },
298 };
299 
300 /* Configuration for the register map of a device with 1 bytes address space. */
301 static const struct regmap_config nvsw_sn2201_regmap_conf = {
302 	.reg_bits = 8,
303 	.val_bits = 8,
304 	.max_register = NVSW_SN2201_REG_MAX,
305 	.cache_type = REGCACHE_FLAT,
306 	.writeable_reg = nvsw_sn2201_writeable_reg,
307 	.readable_reg = nvsw_sn2201_readable_reg,
308 	.volatile_reg = nvsw_sn2201_volatile_reg,
309 	.reg_defaults = nvsw_sn2201_regmap_default,
310 	.num_reg_defaults = ARRAY_SIZE(nvsw_sn2201_regmap_default),
311 };
312 
313 /* Regions for LPC I2C controller and LPC base register space. */
314 static const struct resource nvsw_sn2201_lpc_io_resources[] = {
315 	[0] = DEFINE_RES_NAMED(NVSW_SN2201_CPLD_LPC_I2C_BASE_ADRR,
316 			       NVSW_SN2201_CPLD_LPC_IO_RANGE,
317 			       "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO),
318 };
319 
320 static struct resource nvsw_sn2201_cpld_res[] = {
321 	[0] = DEFINE_RES_IRQ_NAMED(NVSW_SN2201_CPLD_SYSIRQ, "mlxreg-hotplug"),
322 };
323 
324 static struct resource nvsw_sn2201_lpc_res[] = {
325 	[0] = DEFINE_RES_IRQ_NAMED(NVSW_SN2201_LPC_SYSIRQ, "i2c-mlxcpld"),
326 };
327 
328 /* SN2201 I2C platform data. */
329 static struct mlxreg_core_hotplug_platform_data nvsw_sn2201_i2c_data = {
330 	.irq = NVSW_SN2201_CPLD_SYSIRQ,
331 };
332 
333 /* SN2201 CPLD device. */
334 static struct i2c_board_info nvsw_sn2201_cpld_devices[] = {
335 	{
336 		I2C_BOARD_INFO("nvsw-sn2201", 0x41),
337 	},
338 };
339 
340 /* SN2201 CPLD board info. */
341 static struct mlxreg_hotplug_device nvsw_sn2201_cpld_brdinfo[] = {
342 	{
343 		.brdinfo = &nvsw_sn2201_cpld_devices[0],
344 		.nr = NVSW_SN2201_CPLD_NR,
345 	},
346 };
347 
348 /* SN2201 main mux device. */
349 static struct i2c_board_info nvsw_sn2201_main_mux_devices[] = {
350 	{
351 		I2C_BOARD_INFO("pca9548", 0x70),
352 	},
353 };
354 
355 /* SN2201 main mux board info. */
356 static struct mlxreg_hotplug_device nvsw_sn2201_main_mux_brdinfo[] = {
357 	{
358 		.brdinfo = &nvsw_sn2201_main_mux_devices[0],
359 		.nr = NVSW_SN2201_MAIN_MUX_NR,
360 	},
361 };
362 
363 /* SN2201 power devices. */
364 static struct i2c_board_info nvsw_sn2201_pwr_devices[] = {
365 	{
366 		I2C_BOARD_INFO("pmbus", 0x58),
367 	},
368 	{
369 		I2C_BOARD_INFO("pmbus", 0x58),
370 	},
371 };
372 
373 /* SN2201 fan devices. */
374 static struct i2c_board_info nvsw_sn2201_fan_devices[] = {
375 	{
376 		I2C_BOARD_INFO("24c02", 0x50),
377 	},
378 	{
379 		I2C_BOARD_INFO("24c02", 0x51),
380 	},
381 	{
382 		I2C_BOARD_INFO("24c02", 0x52),
383 	},
384 	{
385 		I2C_BOARD_INFO("24c02", 0x53),
386 	},
387 };
388 
389 /* SN2201 hotplug default data. */
390 static struct mlxreg_core_data nvsw_sn2201_psu_items_data[] = {
391 	{
392 		.label = "psu1",
393 		.reg = NVSW_SN2201_PS_PRSNT_STATUS_OFFSET,
394 		.mask = BIT(0),
395 		.hpdev.nr = NVSW_SN2201_NR_NONE,
396 	},
397 	{
398 		.label = "psu2",
399 		.reg = NVSW_SN2201_PS_PRSNT_STATUS_OFFSET,
400 		.mask = BIT(1),
401 		.hpdev.nr = NVSW_SN2201_NR_NONE,
402 	},
403 };
404 
405 static struct mlxreg_core_data nvsw_sn2201_pwr_items_data[] = {
406 	{
407 		.label = "pwr1",
408 		.reg = NVSW_SN2201_PS_DC_OK_STATUS_OFFSET,
409 		.mask = BIT(0),
410 		.hpdev.brdinfo = &nvsw_sn2201_pwr_devices[0],
411 		.hpdev.nr = NVSW_SN2201_MAIN_MUX_CH1_NR,
412 	},
413 	{
414 		.label = "pwr2",
415 		.reg = NVSW_SN2201_PS_DC_OK_STATUS_OFFSET,
416 		.mask = BIT(1),
417 		.hpdev.brdinfo = &nvsw_sn2201_pwr_devices[1],
418 		.hpdev.nr = NVSW_SN2201_MAIN_MUX_CH2_NR,
419 	},
420 };
421 
422 static struct mlxreg_core_data nvsw_sn2201_fan_items_data[] = {
423 	{
424 		.label = "fan1",
425 		.reg = NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET,
426 		.mask = BIT(0),
427 		.hpdev.brdinfo = &nvsw_sn2201_fan_devices[0],
428 		.hpdev.nr = NVSW_SN2201_NR_NONE,
429 	},
430 	{
431 		.label = "fan2",
432 		.reg = NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET,
433 		.mask = BIT(1),
434 		.hpdev.brdinfo = &nvsw_sn2201_fan_devices[1],
435 		.hpdev.nr = NVSW_SN2201_NR_NONE,
436 	},
437 	{
438 		.label = "fan3",
439 		.reg = NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET,
440 		.mask = BIT(2),
441 		.hpdev.brdinfo = &nvsw_sn2201_fan_devices[2],
442 		.hpdev.nr = NVSW_SN2201_NR_NONE,
443 	},
444 	{
445 		.label = "fan4",
446 		.reg = NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET,
447 		.mask = BIT(3),
448 		.hpdev.brdinfo = &nvsw_sn2201_fan_devices[3],
449 		.hpdev.nr = NVSW_SN2201_NR_NONE,
450 	},
451 };
452 
453 static struct mlxreg_core_data nvsw_sn2201_sys_items_data[] = {
454 	{
455 		.label = "nic_smb_alert",
456 		.reg = NVSW_SN2201_ASIC_STATUS_OFFSET,
457 		.mask = BIT(1),
458 		.hpdev.nr = NVSW_SN2201_NR_NONE,
459 	},
460 	{
461 		.label = "cpu_sd",
462 		.reg = NVSW_SN2201_ASIC_STATUS_OFFSET,
463 		.mask = BIT(2),
464 		.hpdev.nr = NVSW_SN2201_NR_NONE,
465 	},
466 	{
467 		.label = "mac_health",
468 		.reg = NVSW_SN2201_ASIC_STATUS_OFFSET,
469 		.mask = BIT(3),
470 		.hpdev.nr = NVSW_SN2201_NR_NONE,
471 	},
472 };
473 
474 static struct mlxreg_core_item nvsw_sn2201_items[] = {
475 	{
476 		.data = nvsw_sn2201_psu_items_data,
477 		.aggr_mask = NVSW_SN2201_CPLD_AGGR_PSU_MASK_DEF,
478 		.reg = NVSW_SN2201_PS_PRSNT_STATUS_OFFSET,
479 		.mask = NVSW_SN2201_CPLD_PSU_MASK,
480 		.count = ARRAY_SIZE(nvsw_sn2201_psu_items_data),
481 		.inversed = 1,
482 		.health = false,
483 	},
484 	{
485 		.data = nvsw_sn2201_pwr_items_data,
486 		.aggr_mask = NVSW_SN2201_CPLD_AGGR_PWR_MASK_DEF,
487 		.reg = NVSW_SN2201_PS_DC_OK_STATUS_OFFSET,
488 		.mask = NVSW_SN2201_CPLD_PWR_MASK,
489 		.count = ARRAY_SIZE(nvsw_sn2201_pwr_items_data),
490 		.inversed = 0,
491 		.health = false,
492 	},
493 	{
494 		.data = nvsw_sn2201_fan_items_data,
495 		.aggr_mask = NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF,
496 		.reg = NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET,
497 		.mask = NVSW_SN2201_CPLD_FAN_MASK,
498 		.count = ARRAY_SIZE(nvsw_sn2201_fan_items_data),
499 		.inversed = 1,
500 		.health = false,
501 	},
502 	{
503 		.data = nvsw_sn2201_sys_items_data,
504 		.aggr_mask = NVSW_SN2201_CPLD_AGGR_ASIC_MASK_DEF,
505 		.reg = NVSW_SN2201_ASIC_STATUS_OFFSET,
506 		.mask = NVSW_SN2201_CPLD_ASIC_MASK,
507 		.count = ARRAY_SIZE(nvsw_sn2201_sys_items_data),
508 		.inversed = 1,
509 		.health = false,
510 	},
511 };
512 
513 static
514 struct mlxreg_core_hotplug_platform_data nvsw_sn2201_hotplug = {
515 	.items = nvsw_sn2201_items,
516 	.counter = ARRAY_SIZE(nvsw_sn2201_items),
517 	.cell = NVSW_SN2201_SYS_INT_STATUS_OFFSET,
518 	.mask = NVSW_SN2201_CPLD_AGGR_MASK_DEF,
519 };
520 
521 /* SN2201 static devices. */
522 static struct i2c_board_info nvsw_sn2201_static_devices[] = {
523 	{
524 		I2C_BOARD_INFO("24c02", 0x57),
525 	},
526 	{
527 		I2C_BOARD_INFO("lm75", 0x4b),
528 	},
529 	{
530 		I2C_BOARD_INFO("24c64", 0x56),
531 	},
532 	{
533 		I2C_BOARD_INFO("ads1015", 0x49),
534 	},
535 	{
536 		I2C_BOARD_INFO("pca9546", 0x71),
537 	},
538 	{
539 		I2C_BOARD_INFO("emc2305", 0x4d),
540 	},
541 	{
542 		I2C_BOARD_INFO("lm75", 0x49),
543 	},
544 	{
545 		I2C_BOARD_INFO("pca9555", 0x27),
546 	},
547 	{
548 		I2C_BOARD_INFO("powr1014", 0x37),
549 	},
550 	{
551 		I2C_BOARD_INFO("lm75", 0x4f),
552 	},
553 	{
554 		I2C_BOARD_INFO("pmbus", 0x40),
555 	},
556 };
557 
558 /* SN2201 default static board info. */
559 static struct mlxreg_hotplug_device nvsw_sn2201_static_brdinfo[] = {
560 	{
561 		.brdinfo = &nvsw_sn2201_static_devices[0],
562 		.nr = NVSW_SN2201_MAIN_NR,
563 	},
564 	{
565 		.brdinfo = &nvsw_sn2201_static_devices[1],
566 		.nr = NVSW_SN2201_MAIN_MUX_CH0_NR,
567 	},
568 	{
569 		.brdinfo = &nvsw_sn2201_static_devices[2],
570 		.nr = NVSW_SN2201_MAIN_MUX_CH0_NR,
571 	},
572 	{
573 		.brdinfo = &nvsw_sn2201_static_devices[3],
574 		.nr = NVSW_SN2201_MAIN_MUX_CH0_NR,
575 	},
576 	{
577 		.brdinfo = &nvsw_sn2201_static_devices[4],
578 		.nr = NVSW_SN2201_MAIN_MUX_CH3_NR,
579 	},
580 	{
581 		.brdinfo = &nvsw_sn2201_static_devices[5],
582 		.nr = NVSW_SN2201_MAIN_MUX_CH5_NR,
583 	},
584 	{
585 		.brdinfo = &nvsw_sn2201_static_devices[6],
586 		.nr = NVSW_SN2201_MAIN_MUX_CH5_NR,
587 	},
588 	{
589 		.brdinfo = &nvsw_sn2201_static_devices[7],
590 		.nr = NVSW_SN2201_MAIN_MUX_CH5_NR,
591 	},
592 	{
593 		.brdinfo = &nvsw_sn2201_static_devices[8],
594 		.nr = NVSW_SN2201_MAIN_MUX_CH6_NR,
595 	},
596 	{
597 		.brdinfo = &nvsw_sn2201_static_devices[9],
598 		.nr = NVSW_SN2201_MAIN_MUX_CH6_NR,
599 	},
600 	{
601 		.brdinfo = &nvsw_sn2201_static_devices[10],
602 		.nr = NVSW_SN2201_MAIN_MUX_CH7_NR,
603 	},
604 };
605 
606 /* LED default data. */
607 static struct mlxreg_core_data nvsw_sn2201_led_data[] = {
608 	{
609 		.label = "status:green",
610 		.reg = NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET,
611 		.mask = GENMASK(7, 4),
612 	},
613 	{
614 		.label = "status:orange",
615 		.reg = NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET,
616 		.mask = GENMASK(7, 4),
617 	},
618 	{
619 		.label = "psu:green",
620 		.reg = NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET,
621 		.mask = GENMASK(7, 4),
622 	},
623 	{
624 		.label = "psu:orange",
625 		.reg = NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET,
626 		.mask = GENMASK(7, 4),
627 	},
628 	{
629 		.label = "uid:blue",
630 		.reg = NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET,
631 		.mask = GENMASK(7, 4),
632 	},
633 	{
634 		.label = "fan1:green",
635 		.reg = NVSW_SN2201_FAN_LED1_CTRL_OFFSET,
636 		.mask = GENMASK(7, 4),
637 	},
638 	{
639 		.label = "fan1:orange",
640 		.reg = NVSW_SN2201_FAN_LED1_CTRL_OFFSET,
641 		.mask = GENMASK(7, 4),
642 	},
643 	{
644 		.label = "fan2:green",
645 		.reg = NVSW_SN2201_FAN_LED1_CTRL_OFFSET,
646 		.mask = GENMASK(3, 0),
647 	},
648 	{
649 		.label = "fan2:orange",
650 		.reg = NVSW_SN2201_FAN_LED1_CTRL_OFFSET,
651 		.mask = GENMASK(3, 0),
652 	},
653 	{
654 		.label = "fan3:green",
655 		.reg = NVSW_SN2201_FAN_LED2_CTRL_OFFSET,
656 		.mask = GENMASK(7, 4),
657 	},
658 	{
659 		.label = "fan3:orange",
660 		.reg = NVSW_SN2201_FAN_LED2_CTRL_OFFSET,
661 		.mask = GENMASK(7, 4),
662 	},
663 	{
664 		.label = "fan4:green",
665 		.reg = NVSW_SN2201_FAN_LED2_CTRL_OFFSET,
666 		.mask = GENMASK(3, 0),
667 	},
668 	{
669 		.label = "fan4:orange",
670 		.reg = NVSW_SN2201_FAN_LED2_CTRL_OFFSET,
671 		.mask = GENMASK(3, 0),
672 	},
673 };
674 
675 static struct mlxreg_core_platform_data nvsw_sn2201_led = {
676 	.data = nvsw_sn2201_led_data,
677 	.counter = ARRAY_SIZE(nvsw_sn2201_led_data),
678 };
679 
680 /* Default register access data. */
681 static struct mlxreg_core_data nvsw_sn2201_io_data[] = {
682 	{
683 		.label = "cpld1_version",
684 		.reg = NVSW_SN2201_CPLD_VER_OFFSET,
685 		.bit = GENMASK(7, 0),
686 		.mode = 0444,
687 	},
688 	{
689 		.label = "cpld1_version_min",
690 		.reg = NVSW_SN2201_CPLD_MVER_OFFSET,
691 		.bit = GENMASK(7, 0),
692 		.mode = 0444,
693 	},
694 	{
695 		.label = "cpld1_pn",
696 		.reg = NVSW_SN2201_CPLD_PN_OFFSET,
697 		.bit = GENMASK(15, 0),
698 		.mode = 0444,
699 		.regnum = 2,
700 	},
701 	{
702 		.label = "psu1_on",
703 		.reg = NVSW_SN2201_PSU_CTRL_OFFSET,
704 		.mask = GENMASK(7, 0) & ~BIT(0),
705 		.mode = 0644,
706 	},
707 	{
708 		.label = "psu2_on",
709 		.reg = NVSW_SN2201_PSU_CTRL_OFFSET,
710 		.mask = GENMASK(7, 0) & ~BIT(1),
711 		.mode = 0644,
712 	},
713 	{
714 		.label = "pwr_cycle",
715 		.reg = NVSW_SN2201_PSU_CTRL_OFFSET,
716 		.mask = GENMASK(7, 0) & ~BIT(2),
717 		.mode = 0644,
718 	},
719 	{
720 		.label = "asic_health",
721 		.reg = NVSW_SN2201_SYS_STATUS_OFFSET,
722 		.mask = GENMASK(4, 3),
723 		.bit = 4,
724 		.mode = 0444,
725 	},
726 	{
727 		.label = "qsfp_pwr_good",
728 		.reg = NVSW_SN2201_SYS_STATUS_OFFSET,
729 		.mask = GENMASK(7, 0) & ~BIT(0),
730 		.mode = 0444,
731 	},
732 	{
733 		.label = "phy_reset",
734 		.reg = NVSW_SN2201_SYS_RST_STATUS_OFFSET,
735 		.mask = GENMASK(7, 0) & ~BIT(3),
736 		.mode = 0644,
737 	},
738 	{
739 		.label = "mac_reset",
740 		.reg = NVSW_SN2201_SYS_RST_STATUS_OFFSET,
741 		.mask = GENMASK(7, 0) & ~BIT(2),
742 		.mode = 0644,
743 	},
744 	{
745 		.label = "pwr_down",
746 		.reg = NVSW_SN2201_RST_SW_CTRL_OFFSET,
747 		.mask = GENMASK(7, 0) & ~BIT(0),
748 		.mode = 0644,
749 	},
750 	{
751 		.label = "reset_long_pb",
752 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
753 		.mask = GENMASK(7, 0) & ~BIT(0),
754 		.mode = 0444,
755 	},
756 	{
757 		.label = "reset_short_pb",
758 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
759 		.mask = GENMASK(7, 0) & ~BIT(1),
760 		.mode = 0444,
761 	},
762 	{
763 		.label = "reset_aux_pwr_or_fu",
764 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
765 		.mask = GENMASK(7, 0) & ~BIT(2),
766 		.mode = 0444,
767 	},
768 	{
769 		.label = "reset_swb_dc_dc_pwr_fail",
770 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
771 		.mask = GENMASK(7, 0) & ~BIT(3),
772 		.mode = 0444,
773 	},
774 	{
775 		.label = "reset_sw_reset",
776 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
777 		.mask = GENMASK(7, 0) & ~BIT(4),
778 		.mode = 0444,
779 	},
780 	{
781 		.label = "reset_fw_reset",
782 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
783 		.mask = GENMASK(7, 0) & ~BIT(5),
784 		.mode = 0444,
785 	},
786 	{
787 		.label = "reset_swb_wd",
788 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
789 		.mask = GENMASK(7, 0) & ~BIT(6),
790 		.mode = 0444,
791 	},
792 	{
793 		.label = "reset_asic_thermal",
794 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
795 		.mask = GENMASK(7, 0) & ~BIT(7),
796 		.mode = 0444,
797 	},
798 	{
799 		.label = "reset_system",
800 		.reg = NVSW_SN2201_RST_CAUSE2_OFFSET,
801 		.mask = GENMASK(7, 0) & ~BIT(1),
802 		.mode = 0444,
803 	},
804 	{
805 		.label = "reset_sw_pwr_off",
806 		.reg = NVSW_SN2201_RST_CAUSE2_OFFSET,
807 		.mask = GENMASK(7, 0) & ~BIT(2),
808 		.mode = 0444,
809 	},
810 	{
811 		.label = "reset_cpu_pwr_fail_thermal",
812 		.reg = NVSW_SN2201_RST_CAUSE2_OFFSET,
813 		.mask = GENMASK(7, 0) & ~BIT(4),
814 		.mode = 0444,
815 	},
816 	{
817 		.label = "reset_reload_bios",
818 		.reg = NVSW_SN2201_RST_CAUSE2_OFFSET,
819 		.mask = GENMASK(7, 0) & ~BIT(5),
820 		.mode = 0444,
821 	},
822 	{
823 		.label = "reset_ac_pwr_fail",
824 		.reg = NVSW_SN2201_RST_CAUSE2_OFFSET,
825 		.mask = GENMASK(7, 0) & ~BIT(6),
826 		.mode = 0444,
827 	},
828 	{
829 		.label = "psu1",
830 		.reg = NVSW_SN2201_PS_PRSNT_STATUS_OFFSET,
831 		.mask = GENMASK(7, 0) & ~BIT(0),
832 		.mode = 0444,
833 	},
834 	{
835 		.label = "psu2",
836 		.reg = NVSW_SN2201_PS_PRSNT_STATUS_OFFSET,
837 		.mask = GENMASK(7, 0) & ~BIT(1),
838 		.mode = 0444,
839 	},
840 };
841 
842 static struct mlxreg_core_platform_data nvsw_sn2201_regs_io = {
843 	.data = nvsw_sn2201_io_data,
844 	.counter = ARRAY_SIZE(nvsw_sn2201_io_data),
845 };
846 
847 /* Default watchdog data. */
848 static struct mlxreg_core_data nvsw_sn2201_wd_data[] = {
849 	{
850 		.label = "action",
851 		.reg = NVSW_SN2201_WD_ACT_OFFSET,
852 		.mask = GENMASK(7, 1),
853 		.bit = 0,
854 	},
855 	{
856 		.label = "timeout",
857 		.reg = NVSW_SN2201_WD_TMR_OFFSET_LSB,
858 		.mask = 0,
859 		.health_cntr = NVSW_SN2201_WD_DFLT_TIMEOUT,
860 	},
861 	{
862 		.label = "timeleft",
863 		.reg = NVSW_SN2201_WD_TMR_OFFSET_LSB,
864 		.mask = 0,
865 	},
866 	{
867 		.label = "ping",
868 		.reg = NVSW_SN2201_WD_ACT_OFFSET,
869 		.mask = GENMASK(7, 1),
870 		.bit = 0,
871 	},
872 	{
873 		.label = "reset",
874 		.reg = NVSW_SN2201_RST_CAUSE1_OFFSET,
875 		.mask = GENMASK(7, 0) & ~BIT(6),
876 		.bit = 6,
877 	},
878 };
879 
880 static struct mlxreg_core_platform_data nvsw_sn2201_wd = {
881 	.data = nvsw_sn2201_wd_data,
882 	.counter = ARRAY_SIZE(nvsw_sn2201_wd_data),
883 	.version = MLX_WDT_TYPE3,
884 	.identity = "mlx-wdt-main",
885 };
886 
887 static int
888 nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
889 				  struct mlxreg_hotplug_device *devs,
890 				  int size)
891 {
892 	struct mlxreg_hotplug_device *dev = devs;
893 	int ret;
894 	int i;
895 
896 	/* Create I2C static devices. */
897 	for (i = 0; i < size; i++, dev++) {
898 		dev->client = i2c_new_client_device(dev->adapter, dev->brdinfo);
899 		if (IS_ERR(dev->client)) {
900 			dev_err(nvsw_sn2201->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
901 				dev->brdinfo->type,
902 				dev->nr, dev->brdinfo->addr);
903 
904 			dev->adapter = NULL;
905 			ret = PTR_ERR(dev->client);
906 			goto fail_create_static_devices;
907 		}
908 	}
909 
910 	return 0;
911 
912 fail_create_static_devices:
913 	while (--i >= 0) {
914 		dev = devs + i;
915 		i2c_unregister_device(dev->client);
916 		dev->client = NULL;
917 		dev->adapter = NULL;
918 	}
919 	return ret;
920 }
921 
922 static void nvsw_sn2201_destroy_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
923 					       struct mlxreg_hotplug_device *devs, int size)
924 {
925 	struct mlxreg_hotplug_device *dev = devs;
926 	int i;
927 
928 	/* Destroy static I2C device for SN2201 static devices. */
929 	for (i = 0; i < size; i++, dev++) {
930 		if (dev->client) {
931 			i2c_unregister_device(dev->client);
932 			dev->client = NULL;
933 			i2c_put_adapter(dev->adapter);
934 			dev->adapter = NULL;
935 		}
936 	}
937 }
938 
939 static int nvsw_sn2201_config_post_init(struct nvsw_sn2201 *nvsw_sn2201)
940 {
941 	struct mlxreg_hotplug_device *sn2201_dev;
942 	struct i2c_adapter *adap;
943 	struct device *dev;
944 	int i, err;
945 
946 	dev = nvsw_sn2201->dev;
947 	adap = i2c_get_adapter(nvsw_sn2201->main_mux_deferred_nr);
948 	if (!adap) {
949 		dev_err(dev, "Failed to get adapter for bus %d\n",
950 			nvsw_sn2201->main_mux_deferred_nr);
951 		return -ENODEV;
952 	}
953 	i2c_put_adapter(adap);
954 
955 	/* Update board info. */
956 	sn2201_dev = nvsw_sn2201->sn2201_devs;
957 	for (i = 0; i < nvsw_sn2201->sn2201_devs_num; i++, sn2201_dev++) {
958 		sn2201_dev->adapter = i2c_get_adapter(sn2201_dev->nr);
959 		if (!sn2201_dev->adapter)
960 			return -ENODEV;
961 		i2c_put_adapter(sn2201_dev->adapter);
962 	}
963 
964 	err = nvsw_sn2201_create_static_devices(nvsw_sn2201, nvsw_sn2201->sn2201_devs,
965 						nvsw_sn2201->sn2201_devs_num);
966 	if (err)
967 		dev_err(dev, "Failed to create static devices\n");
968 
969 	return err;
970 }
971 
972 static int nvsw_sn2201_config_init(struct nvsw_sn2201 *nvsw_sn2201, void *regmap)
973 {
974 	struct device *dev = nvsw_sn2201->dev;
975 	int err;
976 
977 	nvsw_sn2201->io_data = &nvsw_sn2201_regs_io;
978 	nvsw_sn2201->led_data = &nvsw_sn2201_led;
979 	nvsw_sn2201->wd_data = &nvsw_sn2201_wd;
980 	nvsw_sn2201->hotplug_data = &nvsw_sn2201_hotplug;
981 
982 	/* Register IO access driver. */
983 	if (nvsw_sn2201->io_data) {
984 		nvsw_sn2201->io_data->regmap = regmap;
985 		nvsw_sn2201->io_regs =
986 		platform_device_register_resndata(dev, "mlxreg-io", PLATFORM_DEVID_NONE, NULL, 0,
987 						  nvsw_sn2201->io_data,
988 						  sizeof(*nvsw_sn2201->io_data));
989 		if (IS_ERR(nvsw_sn2201->io_regs)) {
990 			err = PTR_ERR(nvsw_sn2201->io_regs);
991 			goto fail_register_io;
992 		}
993 	}
994 
995 	/* Register LED driver. */
996 	if (nvsw_sn2201->led_data) {
997 		nvsw_sn2201->led_data->regmap = regmap;
998 		nvsw_sn2201->led =
999 		platform_device_register_resndata(dev, "leds-mlxreg", PLATFORM_DEVID_NONE, NULL, 0,
1000 						  nvsw_sn2201->led_data,
1001 						  sizeof(*nvsw_sn2201->led_data));
1002 		if (IS_ERR(nvsw_sn2201->led)) {
1003 			err = PTR_ERR(nvsw_sn2201->led);
1004 			goto fail_register_led;
1005 		}
1006 	}
1007 
1008 	/* Register WD driver. */
1009 	if (nvsw_sn2201->wd_data) {
1010 		nvsw_sn2201->wd_data->regmap = regmap;
1011 		nvsw_sn2201->wd =
1012 		platform_device_register_resndata(dev, "mlx-wdt", PLATFORM_DEVID_NONE, NULL, 0,
1013 						  nvsw_sn2201->wd_data,
1014 						  sizeof(*nvsw_sn2201->wd_data));
1015 		if (IS_ERR(nvsw_sn2201->wd)) {
1016 			err = PTR_ERR(nvsw_sn2201->wd);
1017 			goto fail_register_wd;
1018 		}
1019 	}
1020 
1021 	/* Register hotplug driver. */
1022 	if (nvsw_sn2201->hotplug_data) {
1023 		nvsw_sn2201->hotplug_data->regmap = regmap;
1024 		nvsw_sn2201->pdev_hotplug =
1025 		platform_device_register_resndata(dev, "mlxreg-hotplug", PLATFORM_DEVID_NONE,
1026 						  nvsw_sn2201_cpld_res,
1027 						  ARRAY_SIZE(nvsw_sn2201_cpld_res),
1028 						  nvsw_sn2201->hotplug_data,
1029 						  sizeof(*nvsw_sn2201->hotplug_data));
1030 		if (IS_ERR(nvsw_sn2201->pdev_hotplug)) {
1031 			err = PTR_ERR(nvsw_sn2201->pdev_hotplug);
1032 			goto fail_register_hotplug;
1033 		}
1034 	}
1035 
1036 	return nvsw_sn2201_config_post_init(nvsw_sn2201);
1037 
1038 fail_register_hotplug:
1039 	if (nvsw_sn2201->wd)
1040 		platform_device_unregister(nvsw_sn2201->wd);
1041 fail_register_wd:
1042 	if (nvsw_sn2201->led)
1043 		platform_device_unregister(nvsw_sn2201->led);
1044 fail_register_led:
1045 	if (nvsw_sn2201->io_regs)
1046 		platform_device_unregister(nvsw_sn2201->io_regs);
1047 fail_register_io:
1048 
1049 	return err;
1050 }
1051 
1052 static void nvsw_sn2201_config_exit(struct nvsw_sn2201 *nvsw_sn2201)
1053 {
1054 	/* Unregister hotplug driver. */
1055 	if (nvsw_sn2201->pdev_hotplug)
1056 		platform_device_unregister(nvsw_sn2201->pdev_hotplug);
1057 	/* Unregister WD driver. */
1058 	if (nvsw_sn2201->wd)
1059 		platform_device_unregister(nvsw_sn2201->wd);
1060 	/* Unregister LED driver. */
1061 	if (nvsw_sn2201->led)
1062 		platform_device_unregister(nvsw_sn2201->led);
1063 	/* Unregister IO access driver. */
1064 	if (nvsw_sn2201->io_regs)
1065 		platform_device_unregister(nvsw_sn2201->io_regs);
1066 }
1067 
1068 /*
1069  * Initialization is divided into two parts:
1070  * - I2C main bus init.
1071  * - Mux creation and attaching devices to the mux,
1072  *   which assumes that the main bus is already created.
1073  * This separation is required for synchronization between these two parts.
1074  * Completion notify callback is used to make this flow synchronized.
1075  */
1076 static int nvsw_sn2201_i2c_completion_notify(void *handle, int id)
1077 {
1078 	struct nvsw_sn2201 *nvsw_sn2201 = handle;
1079 	void *regmap;
1080 	int i, err;
1081 
1082 	/* Create main mux. */
1083 	nvsw_sn2201->main_mux_devs->adapter = i2c_get_adapter(nvsw_sn2201->main_mux_devs->nr);
1084 	if (!nvsw_sn2201->main_mux_devs->adapter) {
1085 		err = -ENODEV;
1086 		dev_err(nvsw_sn2201->dev, "Failed to get adapter for bus %d\n",
1087 			nvsw_sn2201->cpld_devs->nr);
1088 		goto i2c_get_adapter_main_fail;
1089 	}
1090 
1091 	nvsw_sn2201->main_mux_devs_num = ARRAY_SIZE(nvsw_sn2201_main_mux_brdinfo);
1092 	err = nvsw_sn2201_create_static_devices(nvsw_sn2201, nvsw_sn2201->main_mux_devs,
1093 						nvsw_sn2201->main_mux_devs_num);
1094 	if (err) {
1095 		dev_err(nvsw_sn2201->dev, "Failed to create main mux devices\n");
1096 		goto nvsw_sn2201_create_static_devices_fail;
1097 	}
1098 
1099 	nvsw_sn2201->cpld_devs->adapter = i2c_get_adapter(nvsw_sn2201->cpld_devs->nr);
1100 	if (!nvsw_sn2201->cpld_devs->adapter) {
1101 		err = -ENODEV;
1102 		dev_err(nvsw_sn2201->dev, "Failed to get adapter for bus %d\n",
1103 			nvsw_sn2201->cpld_devs->nr);
1104 		goto i2c_get_adapter_fail;
1105 	}
1106 
1107 	/* Create CPLD device. */
1108 	nvsw_sn2201->cpld_devs->client = i2c_new_dummy_device(nvsw_sn2201->cpld_devs->adapter,
1109 							      NVSW_SN2201_CPLD_I2CADDR);
1110 	if (IS_ERR(nvsw_sn2201->cpld_devs->client)) {
1111 		err = PTR_ERR(nvsw_sn2201->cpld_devs->client);
1112 		dev_err(nvsw_sn2201->dev, "Failed to create %s cpld device at bus %d at addr 0x%02x\n",
1113 			nvsw_sn2201->cpld_devs->brdinfo->type, nvsw_sn2201->cpld_devs->nr,
1114 			nvsw_sn2201->cpld_devs->brdinfo->addr);
1115 		goto i2c_new_dummy_fail;
1116 	}
1117 
1118 	regmap = devm_regmap_init_i2c(nvsw_sn2201->cpld_devs->client, &nvsw_sn2201_regmap_conf);
1119 	if (IS_ERR(regmap)) {
1120 		err = PTR_ERR(regmap);
1121 		dev_err(nvsw_sn2201->dev, "Failed to initialise managed register map\n");
1122 		goto devm_regmap_init_i2c_fail;
1123 	}
1124 
1125 	/* Set default registers. */
1126 	for (i = 0; i < nvsw_sn2201_regmap_conf.num_reg_defaults; i++) {
1127 		err = regmap_write(regmap, nvsw_sn2201_regmap_default[i].reg,
1128 				   nvsw_sn2201_regmap_default[i].def);
1129 		if (err) {
1130 			dev_err(nvsw_sn2201->dev, "Failed to set register at offset 0x%02x to default value: 0x%02x\n",
1131 				nvsw_sn2201_regmap_default[i].reg,
1132 				nvsw_sn2201_regmap_default[i].def);
1133 			goto regmap_write_fail;
1134 		}
1135 	}
1136 
1137 	/* Sync registers with hardware. */
1138 	regcache_mark_dirty(regmap);
1139 	err = regcache_sync(regmap);
1140 	if (err) {
1141 		dev_err(nvsw_sn2201->dev, "Failed to Sync registers with hardware\n");
1142 		goto regcache_sync_fail;
1143 	}
1144 
1145 	/* Configure SN2201 board. */
1146 	err = nvsw_sn2201_config_init(nvsw_sn2201, regmap);
1147 	if (err) {
1148 		dev_err(nvsw_sn2201->dev, "Failed to configure board\n");
1149 		goto nvsw_sn2201_config_init_fail;
1150 	}
1151 
1152 	return 0;
1153 
1154 nvsw_sn2201_config_init_fail:
1155 	nvsw_sn2201_config_exit(nvsw_sn2201);
1156 regcache_sync_fail:
1157 regmap_write_fail:
1158 devm_regmap_init_i2c_fail:
1159 i2c_new_dummy_fail:
1160 	i2c_put_adapter(nvsw_sn2201->cpld_devs->adapter);
1161 	nvsw_sn2201->cpld_devs->adapter = NULL;
1162 i2c_get_adapter_fail:
1163 	/* Destroy SN2201 static I2C devices. */
1164 	nvsw_sn2201_destroy_static_devices(nvsw_sn2201, nvsw_sn2201->sn2201_devs,
1165 					   nvsw_sn2201->sn2201_devs_num);
1166 	/* Destroy main mux device. */
1167 	nvsw_sn2201_destroy_static_devices(nvsw_sn2201, nvsw_sn2201->main_mux_devs,
1168 					   nvsw_sn2201->main_mux_devs_num);
1169 nvsw_sn2201_create_static_devices_fail:
1170 	i2c_put_adapter(nvsw_sn2201->main_mux_devs->adapter);
1171 i2c_get_adapter_main_fail:
1172 	return err;
1173 }
1174 
1175 static int nvsw_sn2201_config_pre_init(struct nvsw_sn2201 *nvsw_sn2201)
1176 {
1177 	nvsw_sn2201->i2c_data = &nvsw_sn2201_i2c_data;
1178 
1179 	/* Register I2C controller. */
1180 	nvsw_sn2201->i2c_data->handle = nvsw_sn2201;
1181 	nvsw_sn2201->i2c_data->completion_notify = nvsw_sn2201_i2c_completion_notify;
1182 	nvsw_sn2201->pdev_i2c = platform_device_register_resndata(nvsw_sn2201->dev, "i2c_mlxcpld",
1183 								  NVSW_SN2201_MAIN_MUX_NR,
1184 								  nvsw_sn2201_lpc_res,
1185 								  ARRAY_SIZE(nvsw_sn2201_lpc_res),
1186 								  nvsw_sn2201->i2c_data,
1187 								  sizeof(*nvsw_sn2201->i2c_data));
1188 	if (IS_ERR(nvsw_sn2201->pdev_i2c))
1189 		return PTR_ERR(nvsw_sn2201->pdev_i2c);
1190 
1191 	return 0;
1192 }
1193 
1194 static int nvsw_sn2201_probe(struct platform_device *pdev)
1195 {
1196 	struct nvsw_sn2201 *nvsw_sn2201;
1197 
1198 	nvsw_sn2201 = devm_kzalloc(&pdev->dev, sizeof(*nvsw_sn2201), GFP_KERNEL);
1199 	if (!nvsw_sn2201)
1200 		return -ENOMEM;
1201 
1202 	nvsw_sn2201->dev = &pdev->dev;
1203 	platform_set_drvdata(pdev, nvsw_sn2201);
1204 	platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources,
1205 				      ARRAY_SIZE(nvsw_sn2201_lpc_io_resources));
1206 
1207 	nvsw_sn2201->main_mux_deferred_nr = NVSW_SN2201_MAIN_MUX_DEFER_NR;
1208 	nvsw_sn2201->main_mux_devs = nvsw_sn2201_main_mux_brdinfo;
1209 	nvsw_sn2201->cpld_devs = nvsw_sn2201_cpld_brdinfo;
1210 	nvsw_sn2201->sn2201_devs = nvsw_sn2201_static_brdinfo;
1211 	nvsw_sn2201->sn2201_devs_num = ARRAY_SIZE(nvsw_sn2201_static_brdinfo);
1212 
1213 	return nvsw_sn2201_config_pre_init(nvsw_sn2201);
1214 }
1215 
1216 static int nvsw_sn2201_remove(struct platform_device *pdev)
1217 {
1218 	struct nvsw_sn2201 *nvsw_sn2201 = platform_get_drvdata(pdev);
1219 
1220 	/* Unregister underlying drivers. */
1221 	nvsw_sn2201_config_exit(nvsw_sn2201);
1222 
1223 	/* Destroy SN2201 static I2C devices. */
1224 	nvsw_sn2201_destroy_static_devices(nvsw_sn2201,
1225 					   nvsw_sn2201->sn2201_devs,
1226 					   nvsw_sn2201->sn2201_devs_num);
1227 
1228 	i2c_put_adapter(nvsw_sn2201->cpld_devs->adapter);
1229 	nvsw_sn2201->cpld_devs->adapter = NULL;
1230 	/* Destroy main mux device. */
1231 	nvsw_sn2201_destroy_static_devices(nvsw_sn2201,
1232 					   nvsw_sn2201->main_mux_devs,
1233 					   nvsw_sn2201->main_mux_devs_num);
1234 
1235 	/* Unregister I2C controller. */
1236 	if (nvsw_sn2201->pdev_i2c)
1237 		platform_device_unregister(nvsw_sn2201->pdev_i2c);
1238 
1239 	return 0;
1240 }
1241 
1242 static const struct acpi_device_id nvsw_sn2201_acpi_ids[] = {
1243 	{"NVSN2201", 0},
1244 	{}
1245 };
1246 
1247 MODULE_DEVICE_TABLE(acpi, nvsw_sn2201_acpi_ids);
1248 
1249 static struct platform_driver nvsw_sn2201_driver = {
1250 	.probe = nvsw_sn2201_probe,
1251 	.remove = nvsw_sn2201_remove,
1252 	.driver = {
1253 		.name = "nvsw-sn2201",
1254 	.acpi_match_table = nvsw_sn2201_acpi_ids,
1255 	},
1256 };
1257 
1258 module_platform_driver(nvsw_sn2201_driver);
1259 
1260 MODULE_AUTHOR("Nvidia");
1261 MODULE_DESCRIPTION("Nvidia sn2201 platform driver");
1262 MODULE_LICENSE("Dual BSD/GPL");
1263 MODULE_ALIAS("platform:nvsw-sn2201");
1264