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