cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mlxreg-lc.c (24492B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Nvidia line card driver
      4 *
      5 * Copyright (C) 2020 Nvidia Technologies Ltd.
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/i2c.h>
     10#include <linux/module.h>
     11#include <linux/platform_data/mlxcpld.h>
     12#include <linux/platform_data/mlxreg.h>
     13#include <linux/platform_device.h>
     14#include <linux/regmap.h>
     15
     16/* I2C bus IO offsets */
     17#define MLXREG_LC_REG_CPLD1_VER_OFFSET		0x2500
     18#define MLXREG_LC_REG_FPGA1_VER_OFFSET		0x2501
     19#define MLXREG_LC_REG_CPLD1_PN_OFFSET		0x2504
     20#define MLXREG_LC_REG_FPGA1_PN_OFFSET		0x2506
     21#define MLXREG_LC_REG_RESET_CAUSE_OFFSET	0x251d
     22#define MLXREG_LC_REG_LED1_OFFSET		0x2520
     23#define MLXREG_LC_REG_GP0_OFFSET		0x252e
     24#define MLXREG_LC_REG_FIELD_UPGRADE		0x2534
     25#define MLXREG_LC_CHANNEL_I2C_REG		0x25dc
     26#define MLXREG_LC_REG_CPLD1_MVER_OFFSET		0x25de
     27#define MLXREG_LC_REG_FPGA1_MVER_OFFSET		0x25df
     28#define MLXREG_LC_REG_MAX_POWER_OFFSET		0x25f1
     29#define MLXREG_LC_REG_CONFIG_OFFSET		0x25fb
     30#define MLXREG_LC_REG_MAX			0x3fff
     31
     32/**
     33 * enum mlxreg_lc_type - line cards types
     34 *
     35 * @MLXREG_LC_SN4800_C16: 100GbE line card with 16 QSFP28 ports;
     36 */
     37enum mlxreg_lc_type {
     38	MLXREG_LC_SN4800_C16 = 0x0000,
     39};
     40
     41/**
     42 * enum mlxreg_lc_state - line cards state
     43 *
     44 * @MLXREG_LC_INITIALIZED: line card is initialized;
     45 * @MLXREG_LC_POWERED: line card is powered;
     46 * @MLXREG_LC_SYNCED: line card is synchronized between hardware and firmware;
     47 */
     48enum mlxreg_lc_state {
     49	MLXREG_LC_INITIALIZED = BIT(0),
     50	MLXREG_LC_POWERED = BIT(1),
     51	MLXREG_LC_SYNCED = BIT(2),
     52};
     53
     54#define MLXREG_LC_CONFIGURED	(MLXREG_LC_INITIALIZED | MLXREG_LC_POWERED | MLXREG_LC_SYNCED)
     55
     56/* mlxreg_lc - device private data
     57 * @dev: platform device;
     58 * @lock: line card lock;
     59 * @par_regmap: parent device regmap handle;
     60 * @data: pltaform core data;
     61 * @io_data: register access platform data;
     62 * @led_data: LED platform data ;
     63 * @mux_data: MUX platform data;
     64 * @led: LED device;
     65 * @io_regs: register access device;
     66 * @mux_brdinfo: mux configuration;
     67 * @mux: mux devices;
     68 * @aux_devs: I2C devices feeding by auxiliary power;
     69 * @aux_devs_num: number of I2C devices feeding by auxiliary power;
     70 * @main_devs: I2C devices feeding by main power;
     71 * @main_devs_num: number of I2C devices feeding by main power;
     72 * @state: line card state;
     73 */
     74struct mlxreg_lc {
     75	struct device *dev;
     76	struct mutex lock; /* line card access lock */
     77	void *par_regmap;
     78	struct mlxreg_core_data *data;
     79	struct mlxreg_core_platform_data *io_data;
     80	struct mlxreg_core_platform_data *led_data;
     81	struct mlxcpld_mux_plat_data *mux_data;
     82	struct platform_device *led;
     83	struct platform_device *io_regs;
     84	struct i2c_board_info *mux_brdinfo;
     85	struct platform_device *mux;
     86	struct mlxreg_hotplug_device *aux_devs;
     87	int aux_devs_num;
     88	struct mlxreg_hotplug_device *main_devs;
     89	int main_devs_num;
     90	enum mlxreg_lc_state state;
     91};
     92
     93static bool mlxreg_lc_writeable_reg(struct device *dev, unsigned int reg)
     94{
     95	switch (reg) {
     96	case MLXREG_LC_REG_LED1_OFFSET:
     97	case MLXREG_LC_REG_GP0_OFFSET:
     98	case MLXREG_LC_REG_FIELD_UPGRADE:
     99	case MLXREG_LC_CHANNEL_I2C_REG:
    100		return true;
    101	}
    102	return false;
    103}
    104
    105static bool mlxreg_lc_readable_reg(struct device *dev, unsigned int reg)
    106{
    107	switch (reg) {
    108	case MLXREG_LC_REG_CPLD1_VER_OFFSET:
    109	case MLXREG_LC_REG_FPGA1_VER_OFFSET:
    110	case MLXREG_LC_REG_CPLD1_PN_OFFSET:
    111	case MLXREG_LC_REG_FPGA1_PN_OFFSET:
    112	case MLXREG_LC_REG_RESET_CAUSE_OFFSET:
    113	case MLXREG_LC_REG_LED1_OFFSET:
    114	case MLXREG_LC_REG_GP0_OFFSET:
    115	case MLXREG_LC_REG_FIELD_UPGRADE:
    116	case MLXREG_LC_CHANNEL_I2C_REG:
    117	case MLXREG_LC_REG_CPLD1_MVER_OFFSET:
    118	case MLXREG_LC_REG_FPGA1_MVER_OFFSET:
    119	case MLXREG_LC_REG_MAX_POWER_OFFSET:
    120	case MLXREG_LC_REG_CONFIG_OFFSET:
    121		return true;
    122	}
    123	return false;
    124}
    125
    126static bool mlxreg_lc_volatile_reg(struct device *dev, unsigned int reg)
    127{
    128	switch (reg) {
    129	case MLXREG_LC_REG_CPLD1_VER_OFFSET:
    130	case MLXREG_LC_REG_FPGA1_VER_OFFSET:
    131	case MLXREG_LC_REG_CPLD1_PN_OFFSET:
    132	case MLXREG_LC_REG_FPGA1_PN_OFFSET:
    133	case MLXREG_LC_REG_RESET_CAUSE_OFFSET:
    134	case MLXREG_LC_REG_LED1_OFFSET:
    135	case MLXREG_LC_REG_GP0_OFFSET:
    136	case MLXREG_LC_REG_FIELD_UPGRADE:
    137	case MLXREG_LC_CHANNEL_I2C_REG:
    138	case MLXREG_LC_REG_CPLD1_MVER_OFFSET:
    139	case MLXREG_LC_REG_FPGA1_MVER_OFFSET:
    140	case MLXREG_LC_REG_MAX_POWER_OFFSET:
    141	case MLXREG_LC_REG_CONFIG_OFFSET:
    142		return true;
    143	}
    144	return false;
    145}
    146
    147static const struct reg_default mlxreg_lc_regmap_default[] = {
    148	{ MLXREG_LC_CHANNEL_I2C_REG, 0x00 },
    149};
    150
    151/* Configuration for the register map of a device with 2 bytes address space. */
    152static const struct regmap_config mlxreg_lc_regmap_conf = {
    153	.reg_bits = 16,
    154	.val_bits = 8,
    155	.max_register = MLXREG_LC_REG_MAX,
    156	.cache_type = REGCACHE_FLAT,
    157	.writeable_reg = mlxreg_lc_writeable_reg,
    158	.readable_reg = mlxreg_lc_readable_reg,
    159	.volatile_reg = mlxreg_lc_volatile_reg,
    160	.reg_defaults = mlxreg_lc_regmap_default,
    161	.num_reg_defaults = ARRAY_SIZE(mlxreg_lc_regmap_default),
    162};
    163
    164/* Default channels vector.
    165 * It contains only the channels, which physically connected to the devices,
    166 * empty channels are skipped.
    167 */
    168static int mlxreg_lc_chan[] = {
    169	0x04, 0x05, 0x06, 0x07, 0x08, 0x10, 0x20, 0x21, 0x22, 0x23, 0x40, 0x41,
    170	0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
    171	0x4e, 0x4f
    172};
    173
    174/* Defaul mux configuration. */
    175static struct mlxcpld_mux_plat_data mlxreg_lc_mux_data[] = {
    176	{
    177		.chan_ids = mlxreg_lc_chan,
    178		.num_adaps = ARRAY_SIZE(mlxreg_lc_chan),
    179		.sel_reg_addr = MLXREG_LC_CHANNEL_I2C_REG,
    180		.reg_size = 2,
    181	},
    182};
    183
    184/* Defaul mux board info. */
    185static struct i2c_board_info mlxreg_lc_mux_brdinfo = {
    186	I2C_BOARD_INFO("i2c-mux-mlxcpld", 0x32),
    187};
    188
    189/* Line card default auxiliary power static devices. */
    190static struct i2c_board_info mlxreg_lc_aux_pwr_devices[] = {
    191	{
    192		I2C_BOARD_INFO("24c32", 0x51),
    193	},
    194	{
    195		I2C_BOARD_INFO("24c32", 0x51),
    196	},
    197};
    198
    199/* Line card default auxiliary power board info. */
    200static struct mlxreg_hotplug_device mlxreg_lc_aux_pwr_brdinfo[] = {
    201	{
    202		.brdinfo = &mlxreg_lc_aux_pwr_devices[0],
    203		.nr = 3,
    204	},
    205	{
    206		.brdinfo = &mlxreg_lc_aux_pwr_devices[1],
    207		.nr = 4,
    208	},
    209};
    210
    211/* Line card default main power static devices. */
    212static struct i2c_board_info mlxreg_lc_main_pwr_devices[] = {
    213	{
    214		I2C_BOARD_INFO("mp2975", 0x62),
    215	},
    216	{
    217		I2C_BOARD_INFO("mp2975", 0x64),
    218	},
    219	{
    220		I2C_BOARD_INFO("max11603", 0x6d),
    221	},
    222	{
    223		I2C_BOARD_INFO("lm25066", 0x15),
    224	},
    225};
    226
    227/* Line card default main power board info. */
    228static struct mlxreg_hotplug_device mlxreg_lc_main_pwr_brdinfo[] = {
    229	{
    230		.brdinfo = &mlxreg_lc_main_pwr_devices[0],
    231		.nr = 0,
    232	},
    233	{
    234		.brdinfo = &mlxreg_lc_main_pwr_devices[1],
    235		.nr = 0,
    236	},
    237	{
    238		.brdinfo = &mlxreg_lc_main_pwr_devices[2],
    239		.nr = 1,
    240	},
    241	{
    242		.brdinfo = &mlxreg_lc_main_pwr_devices[3],
    243		.nr = 2,
    244	},
    245};
    246
    247/* LED default data. */
    248static struct mlxreg_core_data mlxreg_lc_led_data[] = {
    249	{
    250		.label = "status:green",
    251		.reg = MLXREG_LC_REG_LED1_OFFSET,
    252		.mask = GENMASK(7, 4),
    253	},
    254	{
    255		.label = "status:orange",
    256		.reg = MLXREG_LC_REG_LED1_OFFSET,
    257		.mask = GENMASK(7, 4),
    258	},
    259};
    260
    261static struct mlxreg_core_platform_data mlxreg_lc_led = {
    262	.identity = "pci",
    263	.data = mlxreg_lc_led_data,
    264	.counter = ARRAY_SIZE(mlxreg_lc_led_data),
    265};
    266
    267/* Default register access data. */
    268static struct mlxreg_core_data mlxreg_lc_io_data[] = {
    269	{
    270		.label = "cpld1_version",
    271		.reg = MLXREG_LC_REG_CPLD1_VER_OFFSET,
    272		.bit = GENMASK(7, 0),
    273		.mode = 0444,
    274	},
    275	{
    276		.label = "fpga1_version",
    277		.reg = MLXREG_LC_REG_FPGA1_VER_OFFSET,
    278		.bit = GENMASK(7, 0),
    279		.mode = 0444,
    280	},
    281	{
    282		.label = "cpld1_pn",
    283		.reg = MLXREG_LC_REG_CPLD1_PN_OFFSET,
    284		.bit = GENMASK(15, 0),
    285		.mode = 0444,
    286		.regnum = 2,
    287	},
    288	{
    289		.label = "fpga1_pn",
    290		.reg = MLXREG_LC_REG_FPGA1_PN_OFFSET,
    291		.bit = GENMASK(15, 0),
    292		.mode = 0444,
    293		.regnum = 2,
    294	},
    295	{
    296		.label = "cpld1_version_min",
    297		.reg = MLXREG_LC_REG_CPLD1_MVER_OFFSET,
    298		.bit = GENMASK(7, 0),
    299		.mode = 0444,
    300	},
    301	{
    302		.label = "fpga1_version_min",
    303		.reg = MLXREG_LC_REG_FPGA1_MVER_OFFSET,
    304		.bit = GENMASK(7, 0),
    305		.mode = 0444,
    306	},
    307	{
    308		.label = "reset_fpga_not_done",
    309		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    310		.mask = GENMASK(7, 0) & ~BIT(1),
    311		.mode = 0444,
    312	},
    313	{
    314		.label = "reset_aux_pwr_or_ref",
    315		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    316		.mask = GENMASK(7, 0) & ~BIT(2),
    317		.mode = 0444,
    318	},
    319	{
    320		.label = "reset_dc_dc_pwr_fail",
    321		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    322		.mask = GENMASK(7, 0) & ~BIT(3),
    323		.mode = 0444,
    324	},
    325	{
    326		.label = "reset_from_chassis",
    327		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    328		.mask = GENMASK(7, 0) & ~BIT(4),
    329		.mode = 0444,
    330	},
    331	{
    332		.label = "reset_pwr_off_from_chassis",
    333		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    334		.mask = GENMASK(7, 0) & ~BIT(5),
    335		.mode = 0444,
    336	},
    337	{
    338		.label = "reset_line_card",
    339		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    340		.mask = GENMASK(7, 0) & ~BIT(6),
    341		.mode = 0444,
    342	},
    343	{
    344		.label = "reset_line_card_pwr_en",
    345		.reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
    346		.mask = GENMASK(7, 0) & ~BIT(7),
    347		.mode = 0444,
    348	},
    349	{
    350		.label = "cpld_upgrade_en",
    351		.reg = MLXREG_LC_REG_FIELD_UPGRADE,
    352		.mask = GENMASK(7, 0) & ~BIT(0),
    353		.mode = 0644,
    354		.secured = 1,
    355	},
    356	{
    357		.label = "fpga_upgrade_en",
    358		.reg = MLXREG_LC_REG_FIELD_UPGRADE,
    359		.mask = GENMASK(7, 0) & ~BIT(1),
    360		.mode = 0644,
    361		.secured = 1,
    362	},
    363	{
    364		.label = "qsfp_pwr_en",
    365		.reg = MLXREG_LC_REG_GP0_OFFSET,
    366		.mask = GENMASK(7, 0) & ~BIT(0),
    367		.mode = 0644,
    368	},
    369	{
    370		.label = "vpd_wp",
    371		.reg = MLXREG_LC_REG_GP0_OFFSET,
    372		.mask = GENMASK(7, 0) & ~BIT(3),
    373		.mode = 0644,
    374		.secured = 1,
    375	},
    376	{
    377		.label = "agb_spi_burn_en",
    378		.reg = MLXREG_LC_REG_GP0_OFFSET,
    379		.mask = GENMASK(7, 0) & ~BIT(5),
    380		.mode = 0644,
    381		.secured = 1,
    382	},
    383	{
    384		.label = "fpga_spi_burn_en",
    385		.reg = MLXREG_LC_REG_GP0_OFFSET,
    386		.mask = GENMASK(7, 0) & ~BIT(6),
    387		.mode = 0644,
    388		.secured = 1,
    389	},
    390	{
    391		.label = "max_power",
    392		.reg = MLXREG_LC_REG_MAX_POWER_OFFSET,
    393		.bit = GENMASK(15, 0),
    394		.mode = 0444,
    395		.regnum = 2,
    396	},
    397	{
    398		.label = "config",
    399		.reg = MLXREG_LC_REG_CONFIG_OFFSET,
    400		.bit = GENMASK(15, 0),
    401		.mode = 0444,
    402		.regnum = 2,
    403	},
    404};
    405
    406static struct mlxreg_core_platform_data mlxreg_lc_regs_io = {
    407	.data = mlxreg_lc_io_data,
    408	.counter = ARRAY_SIZE(mlxreg_lc_io_data),
    409};
    410
    411static int
    412mlxreg_lc_create_static_devices(struct mlxreg_lc *mlxreg_lc, struct mlxreg_hotplug_device *devs,
    413				int size)
    414{
    415	struct mlxreg_hotplug_device *dev = devs;
    416	int i, ret;
    417
    418	/* Create static I2C device feeding by auxiliary or main power. */
    419	for (i = 0; i < size; i++, dev++) {
    420		dev->client = i2c_new_client_device(dev->adapter, dev->brdinfo);
    421		if (IS_ERR(dev->client)) {
    422			dev_err(mlxreg_lc->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
    423				dev->brdinfo->type, dev->nr, dev->brdinfo->addr);
    424
    425			dev->adapter = NULL;
    426			ret = PTR_ERR(dev->client);
    427			goto fail_create_static_devices;
    428		}
    429	}
    430
    431	return 0;
    432
    433fail_create_static_devices:
    434	while (--i >= 0) {
    435		dev = devs + i;
    436		i2c_unregister_device(dev->client);
    437		dev->client = NULL;
    438	}
    439	return ret;
    440}
    441
    442static void
    443mlxreg_lc_destroy_static_devices(struct mlxreg_lc *mlxreg_lc, struct mlxreg_hotplug_device *devs,
    444				 int size)
    445{
    446	struct mlxreg_hotplug_device *dev = devs;
    447	int i;
    448
    449	/* Destroy static I2C device feeding by auxiliary or main power. */
    450	for (i = 0; i < size; i++, dev++) {
    451		if (dev->client) {
    452			i2c_unregister_device(dev->client);
    453			dev->client = NULL;
    454		}
    455	}
    456}
    457
    458static int mlxreg_lc_power_on_off(struct mlxreg_lc *mlxreg_lc, u8 action)
    459{
    460	u32 regval;
    461	int err;
    462
    463	mutex_lock(&mlxreg_lc->lock);
    464
    465	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);
    466	if (err)
    467		goto regmap_read_fail;
    468
    469	if (action)
    470		regval |= BIT(mlxreg_lc->data->slot - 1);
    471	else
    472		regval &= ~BIT(mlxreg_lc->data->slot - 1);
    473
    474	err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, regval);
    475
    476regmap_read_fail:
    477	mutex_unlock(&mlxreg_lc->lock);
    478	return err;
    479}
    480
    481static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)
    482{
    483	u32 regval;
    484	int err;
    485
    486	/*
    487	 * Hardware holds the line card after powering on in the disabled state. Holding line card
    488	 * in disabled state protects access to the line components, like FPGA and gearboxes.
    489	 * Line card should be enabled in order to get it in operational state. Line card could be
    490	 * disabled for moving it to non-operational state. Enabling line card does not affect the
    491	 * line card which is already has been enabled. Disabling does not affect the disabled line
    492	 * card.
    493	 */
    494	mutex_lock(&mlxreg_lc->lock);
    495
    496	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, &regval);
    497	if (err)
    498		goto regmap_read_fail;
    499
    500	if (action)
    501		regval |= BIT(mlxreg_lc->data->slot - 1);
    502	else
    503		regval &= ~BIT(mlxreg_lc->data->slot - 1);
    504
    505	err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, regval);
    506
    507regmap_read_fail:
    508	mutex_unlock(&mlxreg_lc->lock);
    509	return err;
    510}
    511
    512static int
    513mlxreg_lc_sn4800_c16_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,
    514				 struct mlxreg_core_data *data)
    515{
    516	struct device *dev = &data->hpdev.client->dev;
    517
    518	/* Set line card configuration according to the type. */
    519	mlxreg_lc->mux_data = mlxreg_lc_mux_data;
    520	mlxreg_lc->io_data = &mlxreg_lc_regs_io;
    521	mlxreg_lc->led_data = &mlxreg_lc_led;
    522	mlxreg_lc->mux_brdinfo = &mlxreg_lc_mux_brdinfo;
    523
    524	mlxreg_lc->aux_devs = devm_kmemdup(dev, mlxreg_lc_aux_pwr_brdinfo,
    525					   sizeof(mlxreg_lc_aux_pwr_brdinfo), GFP_KERNEL);
    526	if (!mlxreg_lc->aux_devs)
    527		return -ENOMEM;
    528	mlxreg_lc->aux_devs_num = ARRAY_SIZE(mlxreg_lc_aux_pwr_brdinfo);
    529	mlxreg_lc->main_devs = devm_kmemdup(dev, mlxreg_lc_main_pwr_brdinfo,
    530					    sizeof(mlxreg_lc_main_pwr_brdinfo), GFP_KERNEL);
    531	if (!mlxreg_lc->main_devs)
    532		return -ENOMEM;
    533	mlxreg_lc->main_devs_num = ARRAY_SIZE(mlxreg_lc_main_pwr_brdinfo);
    534
    535	return 0;
    536}
    537
    538static void
    539mlxreg_lc_state_update(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
    540{
    541	mutex_lock(&mlxreg_lc->lock);
    542
    543	if (action)
    544		mlxreg_lc->state |= state;
    545	else
    546		mlxreg_lc->state &= ~state;
    547
    548	mutex_unlock(&mlxreg_lc->lock);
    549}
    550
    551/*
    552 * Callback is to be called from mlxreg-hotplug driver to notify about line card about received
    553 * event.
    554 */
    555static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind, u8 action)
    556{
    557	struct mlxreg_lc *mlxreg_lc = handle;
    558	int err = 0;
    559
    560	dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n",
    561		 mlxreg_lc->data->slot, mlxreg_lc->state, kind, action);
    562
    563	if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED))
    564		return 0;
    565
    566	switch (kind) {
    567	case MLXREG_HOTPLUG_LC_SYNCED:
    568		/*
    569		 * Synchronization event - hardware and firmware are synchronized. Power on/off
    570		 * line card - to allow/disallow main power source.
    571		 */
    572		mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, action);
    573		/* Power line card if it is not powered yet. */
    574		if (!(mlxreg_lc->state & MLXREG_LC_POWERED) && action) {
    575			err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
    576			if (err)
    577				return err;
    578		}
    579		/* In case line card is configured - enable it. */
    580		if (mlxreg_lc->state & MLXREG_LC_CONFIGURED && action)
    581			err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
    582		break;
    583	case MLXREG_HOTPLUG_LC_POWERED:
    584		/* Power event - attach or de-attach line card device feeding by the main power. */
    585		if (action) {
    586			/* Do not create devices, if line card is already powered. */
    587			if (mlxreg_lc->state & MLXREG_LC_POWERED) {
    588				/* In case line card is configured - enable it. */
    589				if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
    590					err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
    591				return err;
    592			}
    593			err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
    594							      mlxreg_lc->main_devs_num);
    595			if (err)
    596				return err;
    597
    598			/* In case line card is already in ready state - enable it. */
    599			if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
    600				err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
    601		} else {
    602			mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
    603							 mlxreg_lc->main_devs_num);
    604		}
    605		mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, action);
    606		break;
    607	case MLXREG_HOTPLUG_LC_READY:
    608		/*
    609		 * Ready event – enable line card by releasing it from reset or disable it by put
    610		 * to reset state.
    611		 */
    612		err = mlxreg_lc_enable_disable(mlxreg_lc, !!action);
    613		break;
    614	case MLXREG_HOTPLUG_LC_THERMAL:
    615		/* Thermal shutdown event – power off line card. */
    616		if (action)
    617			err = mlxreg_lc_power_on_off(mlxreg_lc, 0);
    618		break;
    619	default:
    620		break;
    621	}
    622
    623	return err;
    624}
    625
    626/*
    627 * Callback is to be called from i2c-mux-mlxcpld driver to indicate that all adapter devices has
    628 * been created.
    629 */
    630static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
    631				       struct i2c_adapter *adapters[])
    632{
    633	struct mlxreg_hotplug_device *main_dev, *aux_dev;
    634	struct mlxreg_lc *mlxreg_lc = handle;
    635	u32 regval;
    636	int i, err;
    637
    638	/* Update I2C devices feeding by auxiliary power. */
    639	aux_dev = mlxreg_lc->aux_devs;
    640	for (i = 0; i < mlxreg_lc->aux_devs_num; i++, aux_dev++) {
    641		aux_dev->adapter = adapters[aux_dev->nr];
    642		aux_dev->nr = adapters[aux_dev->nr]->nr;
    643	}
    644
    645	err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->aux_devs,
    646					      mlxreg_lc->aux_devs_num);
    647	if (err)
    648		return err;
    649
    650	/* Update I2C devices feeding by main power. */
    651	main_dev = mlxreg_lc->main_devs;
    652	for (i = 0; i < mlxreg_lc->main_devs_num; i++, main_dev++) {
    653		main_dev->adapter = adapters[main_dev->nr];
    654		main_dev->nr = adapters[main_dev->nr]->nr;
    655	}
    656
    657	/* Verify if line card is powered. */
    658	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);
    659	if (err)
    660		goto mlxreg_lc_regmap_read_power_fail;
    661
    662	if (regval & mlxreg_lc->data->mask) {
    663		err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
    664						      mlxreg_lc->main_devs_num);
    665		if (err)
    666			goto mlxreg_lc_create_static_devices_failed;
    667
    668		mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, 1);
    669	}
    670
    671	/* Verify if line card is synchronized. */
    672	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_sync, &regval);
    673	if (err)
    674		goto mlxreg_lc_regmap_read_sync_fail;
    675
    676	/* Power on line card if necessary. */
    677	if (regval & mlxreg_lc->data->mask) {
    678		mlxreg_lc->state |= MLXREG_LC_SYNCED;
    679		mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, 1);
    680		if (mlxreg_lc->state & ~MLXREG_LC_POWERED) {
    681			err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
    682			if (err)
    683				goto mlxreg_lc_regmap_power_on_off_fail;
    684		}
    685	}
    686
    687	mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);
    688
    689	return 0;
    690
    691mlxreg_lc_regmap_power_on_off_fail:
    692mlxreg_lc_regmap_read_sync_fail:
    693	if (mlxreg_lc->state & MLXREG_LC_POWERED)
    694		mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
    695						 mlxreg_lc->main_devs_num);
    696mlxreg_lc_create_static_devices_failed:
    697	mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->aux_devs, mlxreg_lc->aux_devs_num);
    698mlxreg_lc_regmap_read_power_fail:
    699	return err;
    700}
    701
    702static int
    703mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,
    704		      struct mlxreg_core_data *data)
    705{
    706	struct device *dev = &data->hpdev.client->dev;
    707	int lsb, err;
    708	u32 regval;
    709
    710	/* Validate line card type. */
    711	err = regmap_read(regmap, MLXREG_LC_REG_CONFIG_OFFSET, &lsb);
    712	err = (!err) ? regmap_read(regmap, MLXREG_LC_REG_CONFIG_OFFSET, &regval) : err;
    713	if (err)
    714		return err;
    715	regval = (regval & GENMASK(7, 0)) << 8 | (lsb & GENMASK(7, 0));
    716	switch (regval) {
    717	case MLXREG_LC_SN4800_C16:
    718		err = mlxreg_lc_sn4800_c16_config_init(mlxreg_lc, regmap, data);
    719		if (err)
    720			return err;
    721		break;
    722	default:
    723		return -ENODEV;
    724	}
    725
    726	/* Create mux infrastructure. */
    727	mlxreg_lc->mux_data->handle = mlxreg_lc;
    728	mlxreg_lc->mux_data->completion_notify = mlxreg_lc_completion_notify;
    729	mlxreg_lc->mux_brdinfo->platform_data = mlxreg_lc->mux_data;
    730	mlxreg_lc->mux = platform_device_register_resndata(dev, "i2c-mux-mlxcpld", data->hpdev.nr,
    731							   NULL, 0, mlxreg_lc->mux_data,
    732							   sizeof(*mlxreg_lc->mux_data));
    733	if (IS_ERR(mlxreg_lc->mux))
    734		return PTR_ERR(mlxreg_lc->mux);
    735
    736	/* Register IO access driver. */
    737	if (mlxreg_lc->io_data) {
    738		mlxreg_lc->io_data->regmap = regmap;
    739		mlxreg_lc->io_regs =
    740		platform_device_register_resndata(dev, "mlxreg-io", data->hpdev.nr, NULL, 0,
    741						  mlxreg_lc->io_data, sizeof(*mlxreg_lc->io_data));
    742		if (IS_ERR(mlxreg_lc->io_regs)) {
    743			err = PTR_ERR(mlxreg_lc->io_regs);
    744			goto fail_register_io;
    745		}
    746	}
    747
    748	/* Register LED driver. */
    749	if (mlxreg_lc->led_data) {
    750		mlxreg_lc->led_data->regmap = regmap;
    751		mlxreg_lc->led =
    752		platform_device_register_resndata(dev, "leds-mlxreg", data->hpdev.nr, NULL, 0,
    753						  mlxreg_lc->led_data,
    754						  sizeof(*mlxreg_lc->led_data));
    755		if (IS_ERR(mlxreg_lc->led)) {
    756			err = PTR_ERR(mlxreg_lc->led);
    757			goto fail_register_led;
    758		}
    759	}
    760
    761	return 0;
    762
    763fail_register_led:
    764	if (mlxreg_lc->io_regs)
    765		platform_device_unregister(mlxreg_lc->io_regs);
    766fail_register_io:
    767	if (mlxreg_lc->mux)
    768		platform_device_unregister(mlxreg_lc->mux);
    769
    770	return err;
    771}
    772
    773static void mlxreg_lc_config_exit(struct mlxreg_lc *mlxreg_lc)
    774{
    775	/* Unregister LED driver. */
    776	if (mlxreg_lc->led)
    777		platform_device_unregister(mlxreg_lc->led);
    778	/* Unregister IO access driver. */
    779	if (mlxreg_lc->io_regs)
    780		platform_device_unregister(mlxreg_lc->io_regs);
    781	/* Remove mux infrastructure. */
    782	if (mlxreg_lc->mux)
    783		platform_device_unregister(mlxreg_lc->mux);
    784}
    785
    786static int mlxreg_lc_probe(struct platform_device *pdev)
    787{
    788	struct mlxreg_core_hotplug_platform_data *par_pdata;
    789	struct mlxreg_core_data *data;
    790	struct mlxreg_lc *mlxreg_lc;
    791	void *regmap;
    792	int i, err;
    793
    794	data = dev_get_platdata(&pdev->dev);
    795	if (!data)
    796		return -EINVAL;
    797
    798	mlxreg_lc = devm_kzalloc(&pdev->dev, sizeof(*mlxreg_lc), GFP_KERNEL);
    799	if (!mlxreg_lc)
    800		return -ENOMEM;
    801
    802	mutex_init(&mlxreg_lc->lock);
    803	/* Set event notification callback. */
    804	if (data->notifier) {
    805		data->notifier->user_handler = mlxreg_lc_event_handler;
    806		data->notifier->handle = mlxreg_lc;
    807	}
    808	data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
    809	if (!data->hpdev.adapter) {
    810		dev_err(&pdev->dev, "Failed to get adapter for bus %d\n",
    811			data->hpdev.nr);
    812		return -EFAULT;
    813	}
    814
    815	/* Create device at the top of line card I2C tree.*/
    816	data->hpdev.client = i2c_new_client_device(data->hpdev.adapter,
    817						   data->hpdev.brdinfo);
    818	if (IS_ERR(data->hpdev.client)) {
    819		dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
    820			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
    821
    822		i2c_put_adapter(data->hpdev.adapter);
    823		data->hpdev.adapter = NULL;
    824		return PTR_ERR(data->hpdev.client);
    825	}
    826
    827	regmap = devm_regmap_init_i2c(data->hpdev.client,
    828				      &mlxreg_lc_regmap_conf);
    829	if (IS_ERR(regmap)) {
    830		err = PTR_ERR(regmap);
    831		goto mlxreg_lc_probe_fail;
    832	}
    833
    834	/* Set default registers. */
    835	for (i = 0; i < mlxreg_lc_regmap_conf.num_reg_defaults; i++) {
    836		err = regmap_write(regmap, mlxreg_lc_regmap_default[i].reg,
    837				   mlxreg_lc_regmap_default[i].def);
    838		if (err)
    839			goto mlxreg_lc_probe_fail;
    840	}
    841
    842	/* Sync registers with hardware. */
    843	regcache_mark_dirty(regmap);
    844	err = regcache_sync(regmap);
    845	if (err)
    846		goto mlxreg_lc_probe_fail;
    847
    848	par_pdata = data->hpdev.brdinfo->platform_data;
    849	mlxreg_lc->par_regmap = par_pdata->regmap;
    850	mlxreg_lc->data = data;
    851	mlxreg_lc->dev = &pdev->dev;
    852	platform_set_drvdata(pdev, mlxreg_lc);
    853
    854	/* Configure line card. */
    855	err = mlxreg_lc_config_init(mlxreg_lc, regmap, data);
    856	if (err)
    857		goto mlxreg_lc_probe_fail;
    858
    859	return err;
    860
    861mlxreg_lc_probe_fail:
    862	i2c_put_adapter(data->hpdev.adapter);
    863	return err;
    864}
    865
    866static int mlxreg_lc_remove(struct platform_device *pdev)
    867{
    868	struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
    869	struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev);
    870
    871	/* Clear event notification callback. */
    872	if (data->notifier) {
    873		data->notifier->user_handler = NULL;
    874		data->notifier->handle = NULL;
    875	}
    876
    877	/* Destroy static I2C device feeding by main power. */
    878	mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
    879					 mlxreg_lc->main_devs_num);
    880	/* Destroy static I2C device feeding by auxiliary power. */
    881	mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->aux_devs, mlxreg_lc->aux_devs_num);
    882	/* Unregister underlying drivers. */
    883	mlxreg_lc_config_exit(mlxreg_lc);
    884	if (data->hpdev.client) {
    885		i2c_unregister_device(data->hpdev.client);
    886		data->hpdev.client = NULL;
    887		i2c_put_adapter(data->hpdev.adapter);
    888		data->hpdev.adapter = NULL;
    889	}
    890
    891	return 0;
    892}
    893
    894static struct platform_driver mlxreg_lc_driver = {
    895	.probe = mlxreg_lc_probe,
    896	.remove = mlxreg_lc_remove,
    897	.driver = {
    898		.name = "mlxreg-lc",
    899	},
    900};
    901
    902module_platform_driver(mlxreg_lc_driver);
    903
    904MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");
    905MODULE_DESCRIPTION("Nvidia line card platform driver");
    906MODULE_LICENSE("Dual BSD/GPL");
    907MODULE_ALIAS("platform:mlxreg-lc");