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