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