brintos

brintos / linux-shallow public Read only

0
0
Text · 35.5 KiB · abe7be6 Raw
1269 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Nvidia sn2201 driver4 *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          0x200021#define NVSW_SN2201_CPLD_LPC_IO_RANGE               0x10022#define NVSW_SN2201_HW_VER_ID_OFFSET                0x0023#define NVSW_SN2201_BOARD_ID_OFFSET                 0x0124#define NVSW_SN2201_CPLD_VER_OFFSET                 0x0225#define NVSW_SN2201_CPLD_MVER_OFFSET                0x0326#define NVSW_SN2201_CPLD_ID_OFFSET                  0x0427#define NVSW_SN2201_CPLD_PN_OFFSET                  0x0528#define NVSW_SN2201_CPLD_PN1_OFFSET                 0x0629#define NVSW_SN2201_PSU_CTRL_OFFSET                 0x0a30#define NVSW_SN2201_QSFP28_STATUS_OFFSET            0x0b31#define NVSW_SN2201_QSFP28_INT_STATUS_OFFSET        0x0c32#define NVSW_SN2201_QSFP28_LP_STATUS_OFFSET         0x0d33#define NVSW_SN2201_QSFP28_RST_STATUS_OFFSET        0x0e34#define NVSW_SN2201_SYS_STATUS_OFFSET               0x0f35#define NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET       0x1036#define NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET       0x1237#define NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET       0x1338#define NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET   0x1439#define NVSW_SN2201_SYS_RST_STATUS_OFFSET           0x1540#define NVSW_SN2201_SYS_INT_STATUS_OFFSET           0x2141#define NVSW_SN2201_SYS_INT_MASK_OFFSET             0x2242#define NVSW_SN2201_ASIC_STATUS_OFFSET              0x2443#define NVSW_SN2201_ASIC_EVENT_OFFSET               0x2544#define NVSW_SN2201_ASIC_MAKS_OFFSET                0x2645#define NVSW_SN2201_THML_STATUS_OFFSET              0x2746#define NVSW_SN2201_THML_EVENT_OFFSET               0x2847#define NVSW_SN2201_THML_MASK_OFFSET                0x2948#define NVSW_SN2201_PS_ALT_STATUS_OFFSET            0x2a49#define NVSW_SN2201_PS_ALT_EVENT_OFFSET             0x2b50#define NVSW_SN2201_PS_ALT_MASK_OFFSET              0x2c51#define NVSW_SN2201_PS_PRSNT_STATUS_OFFSET          0x3052#define NVSW_SN2201_PS_PRSNT_EVENT_OFFSET           0x3153#define NVSW_SN2201_PS_PRSNT_MASK_OFFSET            0x3254#define NVSW_SN2201_PS_DC_OK_STATUS_OFFSET          0x3355#define NVSW_SN2201_PS_DC_OK_EVENT_OFFSET           0x3456#define NVSW_SN2201_PS_DC_OK_MASK_OFFSET            0x3557#define NVSW_SN2201_RST_CAUSE1_OFFSET               0x3658#define NVSW_SN2201_RST_CAUSE2_OFFSET               0x3759#define NVSW_SN2201_RST_SW_CTRL_OFFSET              0x3860#define NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET         0x3a61#define NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET          0x3b62#define NVSW_SN2201_FAN_PRSNT_MASK_OFFSET           0x3c63#define NVSW_SN2201_WD_TMR_OFFSET_LSB               0x4064#define NVSW_SN2201_WD_TMR_OFFSET_MSB               0x4165#define NVSW_SN2201_WD_ACT_OFFSET                   0x4266#define NVSW_SN2201_FAN_LED1_CTRL_OFFSET            0x5067#define NVSW_SN2201_FAN_LED2_CTRL_OFFSET            0x5168#define NVSW_SN2201_REG_MAX                         0x5269 70/* Number of physical I2C busses. */71#define NVSW_SN2201_PHY_I2C_BUS_NUM		272/* Number of main mux channels. */73#define NVSW_SN2201_MAIN_MUX_CHNL_NUM		874 75#define NVSW_SN2201_MAIN_NR			076#define NVSW_SN2201_MAIN_MUX_NR			177#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_NUM81#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_NR93#define NVSW_SN2201_NR_NONE		-194 95/* Masks for aggregation, PSU presence and power, ASIC events96 * in CPLD related registers.97 */98#define NVSW_SN2201_CPLD_AGGR_ASIC_MASK_DEF	0xe099#define NVSW_SN2201_CPLD_AGGR_PSU_MASK_DEF	0x04100#define NVSW_SN2201_CPLD_AGGR_PWR_MASK_DEF	0x02101#define NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF	0x10102#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			26114#define NVSW_SN2201_LPC_SYSIRQ			28115#define NVSW_SN2201_CPLD_I2CADDR		0x41116 117#define NVSW_SN2201_WD_DFLT_TIMEOUT		600118 119/* nvsw_sn2201 - device private data120 * @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 517static518struct 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 int892nvsw_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	int ret;1202 1203	nvsw_sn2201 = devm_kzalloc(&pdev->dev, sizeof(*nvsw_sn2201), GFP_KERNEL);1204	if (!nvsw_sn2201)1205		return -ENOMEM;1206 1207	nvsw_sn2201->dev = &pdev->dev;1208	platform_set_drvdata(pdev, nvsw_sn2201);1209	ret = platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources,1210				      ARRAY_SIZE(nvsw_sn2201_lpc_io_resources));1211	if (ret)1212		return ret;1213 1214	nvsw_sn2201->main_mux_deferred_nr = NVSW_SN2201_MAIN_MUX_DEFER_NR;1215	nvsw_sn2201->main_mux_devs = nvsw_sn2201_main_mux_brdinfo;1216	nvsw_sn2201->cpld_devs = nvsw_sn2201_cpld_brdinfo;1217	nvsw_sn2201->sn2201_devs = nvsw_sn2201_static_brdinfo;1218	nvsw_sn2201->sn2201_devs_num = ARRAY_SIZE(nvsw_sn2201_static_brdinfo);1219 1220	return nvsw_sn2201_config_pre_init(nvsw_sn2201);1221}1222 1223static void nvsw_sn2201_remove(struct platform_device *pdev)1224{1225	struct nvsw_sn2201 *nvsw_sn2201 = platform_get_drvdata(pdev);1226 1227	/* Unregister underlying drivers. */1228	nvsw_sn2201_config_exit(nvsw_sn2201);1229 1230	/* Destroy SN2201 static I2C devices. */1231	nvsw_sn2201_destroy_static_devices(nvsw_sn2201,1232					   nvsw_sn2201->sn2201_devs,1233					   nvsw_sn2201->sn2201_devs_num);1234 1235	i2c_put_adapter(nvsw_sn2201->cpld_devs->adapter);1236	nvsw_sn2201->cpld_devs->adapter = NULL;1237	/* Destroy main mux device. */1238	nvsw_sn2201_destroy_static_devices(nvsw_sn2201,1239					   nvsw_sn2201->main_mux_devs,1240					   nvsw_sn2201->main_mux_devs_num);1241 1242	/* Unregister I2C controller. */1243	if (nvsw_sn2201->pdev_i2c)1244		platform_device_unregister(nvsw_sn2201->pdev_i2c);1245}1246 1247static const struct acpi_device_id nvsw_sn2201_acpi_ids[] = {1248	{"NVSN2201", 0},1249	{}1250};1251 1252MODULE_DEVICE_TABLE(acpi, nvsw_sn2201_acpi_ids);1253 1254static struct platform_driver nvsw_sn2201_driver = {1255	.probe = nvsw_sn2201_probe,1256	.remove_new = nvsw_sn2201_remove,1257	.driver = {1258		.name = "nvsw-sn2201",1259	.acpi_match_table = nvsw_sn2201_acpi_ids,1260	},1261};1262 1263module_platform_driver(nvsw_sn2201_driver);1264 1265MODULE_AUTHOR("Nvidia");1266MODULE_DESCRIPTION("Nvidia sn2201 platform driver");1267MODULE_LICENSE("Dual BSD/GPL");1268MODULE_ALIAS("platform:nvsw-sn2201");1269