File Index
Files and directories
Sign in
FILE

nvsw-sn2201.c

File preview with syntax highlighting.

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