Linux Audio

Check our new training course

Linux kernel drivers training

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