brintos

brintos / linux-shallow public Read only

0
0
Text · 26.2 KiB · 43d119e Raw
959 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Nvidia line card driver4 *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		0x250018#define MLXREG_LC_REG_FPGA1_VER_OFFSET		0x250119#define MLXREG_LC_REG_CPLD1_PN_OFFSET		0x250420#define MLXREG_LC_REG_FPGA1_PN_OFFSET		0x250621#define MLXREG_LC_REG_RESET_CAUSE_OFFSET	0x251d22#define MLXREG_LC_REG_LED1_OFFSET		0x252023#define MLXREG_LC_REG_GP0_OFFSET		0x252e24#define MLXREG_LC_REG_FIELD_UPGRADE		0x253425#define MLXREG_LC_CHANNEL_I2C_REG		0x25dc26#define MLXREG_LC_REG_CPLD1_MVER_OFFSET		0x25de27#define MLXREG_LC_REG_FPGA1_MVER_OFFSET		0x25df28#define MLXREG_LC_REG_MAX_POWER_OFFSET		0x25f129#define MLXREG_LC_REG_CONFIG_OFFSET		0x25fb30#define MLXREG_LC_REG_MAX			0x3fff31 32/**33 * enum mlxreg_lc_type - line cards types34 *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 state43 *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 data57 * @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, 0x4f172};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 int412mlxreg_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 void443mlxreg_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	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);464	if (err)465		goto regmap_read_fail;466 467	if (action)468		regval |= BIT(mlxreg_lc->data->slot - 1);469	else470		regval &= ~BIT(mlxreg_lc->data->slot - 1);471 472	err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, regval);473 474regmap_read_fail:475	return err;476}477 478static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)479{480	u32 regval;481	int err;482 483	/*484	 * Hardware holds the line card after powering on in the disabled state. Holding line card485	 * in disabled state protects access to the line components, like FPGA and gearboxes.486	 * Line card should be enabled in order to get it in operational state. Line card could be487	 * disabled for moving it to non-operational state. Enabling line card does not affect the488	 * line card which is already has been enabled. Disabling does not affect the disabled line489	 * card.490	 */491	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, &regval);492	if (err)493		goto regmap_read_fail;494 495	if (action)496		regval |= BIT(mlxreg_lc->data->slot - 1);497	else498		regval &= ~BIT(mlxreg_lc->data->slot - 1);499 500	err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, regval);501 502regmap_read_fail:503	return err;504}505 506static int507mlxreg_lc_sn4800_c16_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,508				 struct mlxreg_core_data *data)509{510	struct device *dev = &data->hpdev.client->dev;511 512	/* Set line card configuration according to the type. */513	mlxreg_lc->mux_data = mlxreg_lc_mux_data;514	mlxreg_lc->io_data = &mlxreg_lc_regs_io;515	mlxreg_lc->led_data = &mlxreg_lc_led;516	mlxreg_lc->mux_brdinfo = &mlxreg_lc_mux_brdinfo;517 518	mlxreg_lc->aux_devs = devm_kmemdup(dev, mlxreg_lc_aux_pwr_brdinfo,519					   sizeof(mlxreg_lc_aux_pwr_brdinfo), GFP_KERNEL);520	if (!mlxreg_lc->aux_devs)521		return -ENOMEM;522	mlxreg_lc->aux_devs_num = ARRAY_SIZE(mlxreg_lc_aux_pwr_brdinfo);523	mlxreg_lc->main_devs = devm_kmemdup(dev, mlxreg_lc_main_pwr_brdinfo,524					    sizeof(mlxreg_lc_main_pwr_brdinfo), GFP_KERNEL);525	if (!mlxreg_lc->main_devs)526		return -ENOMEM;527	mlxreg_lc->main_devs_num = ARRAY_SIZE(mlxreg_lc_main_pwr_brdinfo);528 529	return 0;530}531 532static void533mlxreg_lc_state_update(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)534{535	if (action)536		mlxreg_lc->state |= state;537	else538		mlxreg_lc->state &= ~state;539}540 541static void542mlxreg_lc_state_update_locked(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)543{544	mutex_lock(&mlxreg_lc->lock);545 546	if (action)547		mlxreg_lc->state |= state;548	else549		mlxreg_lc->state &= ~state;550 551	mutex_unlock(&mlxreg_lc->lock);552}553 554/*555 * Callback is to be called from mlxreg-hotplug driver to notify about line card about received556 * event.557 */558static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind, u8 action)559{560	struct mlxreg_lc *mlxreg_lc = handle;561	int err = 0;562 563	dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n",564		 mlxreg_lc->data->slot, mlxreg_lc->state, kind, action);565 566	mutex_lock(&mlxreg_lc->lock);567	if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED))568		goto mlxreg_lc_non_initialzed_exit;569 570	switch (kind) {571	case MLXREG_HOTPLUG_LC_SYNCED:572		/*573		 * Synchronization event - hardware and firmware are synchronized. Power on/off574		 * line card - to allow/disallow main power source.575		 */576		mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, action);577		/* Power line card if it is not powered yet. */578		if (!(mlxreg_lc->state & MLXREG_LC_POWERED) && action) {579			err = mlxreg_lc_power_on_off(mlxreg_lc, 1);580			if (err)581				goto mlxreg_lc_power_on_off_fail;582		}583		/* In case line card is configured - enable it. */584		if (mlxreg_lc->state & MLXREG_LC_CONFIGURED && action)585			err = mlxreg_lc_enable_disable(mlxreg_lc, 1);586		break;587	case MLXREG_HOTPLUG_LC_POWERED:588		/* Power event - attach or de-attach line card device feeding by the main power. */589		if (action) {590			/* Do not create devices, if line card is already powered. */591			if (mlxreg_lc->state & MLXREG_LC_POWERED) {592				/* In case line card is configured - enable it. */593				if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)594					err = mlxreg_lc_enable_disable(mlxreg_lc, 1);595 596				goto mlxreg_lc_enable_disable_exit;597			}598			err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,599							      mlxreg_lc->main_devs_num);600			if (err)601				goto mlxreg_lc_create_static_devices_fail;602 603			/* In case line card is already in ready state - enable it. */604			if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)605				err = mlxreg_lc_enable_disable(mlxreg_lc, 1);606		} else {607			mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,608							 mlxreg_lc->main_devs_num);609		}610		mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, action);611		break;612	case MLXREG_HOTPLUG_LC_READY:613		/*614		 * Ready event – enable line card by releasing it from reset or disable it by put615		 * to reset state.616		 */617		err = mlxreg_lc_enable_disable(mlxreg_lc, !!action);618		break;619	case MLXREG_HOTPLUG_LC_THERMAL:620		/* Thermal shutdown event – power off line card. */621		if (action)622			err = mlxreg_lc_power_on_off(mlxreg_lc, 0);623		break;624	default:625		break;626	}627 628mlxreg_lc_enable_disable_exit:629mlxreg_lc_power_on_off_fail:630mlxreg_lc_create_static_devices_fail:631mlxreg_lc_non_initialzed_exit:632	mutex_unlock(&mlxreg_lc->lock);633 634	return err;635}636 637/*638 * Callback is to be called from i2c-mux-mlxcpld driver to indicate that all adapter devices has639 * been created.640 */641static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,642				       struct i2c_adapter *adapters[])643{644	struct mlxreg_hotplug_device *main_dev, *aux_dev;645	struct mlxreg_lc *mlxreg_lc = handle;646	u32 regval;647	int i, err;648 649	/* Update I2C devices feeding by auxiliary power. */650	aux_dev = mlxreg_lc->aux_devs;651	for (i = 0; i < mlxreg_lc->aux_devs_num; i++, aux_dev++) {652		aux_dev->adapter = adapters[aux_dev->nr];653		aux_dev->nr = adapters[aux_dev->nr]->nr;654	}655 656	err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->aux_devs,657					      mlxreg_lc->aux_devs_num);658	if (err)659		return err;660 661	/* Update I2C devices feeding by main power. */662	main_dev = mlxreg_lc->main_devs;663	for (i = 0; i < mlxreg_lc->main_devs_num; i++, main_dev++) {664		main_dev->adapter = adapters[main_dev->nr];665		main_dev->nr = adapters[main_dev->nr]->nr;666	}667 668	/* Verify if line card is powered. */669	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);670	if (err)671		goto mlxreg_lc_regmap_read_power_fail;672 673	if (regval & mlxreg_lc->data->mask) {674		err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,675						      mlxreg_lc->main_devs_num);676		if (err)677			goto mlxreg_lc_create_static_devices_failed;678 679		mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_POWERED, 1);680	}681 682	/* Verify if line card is synchronized. */683	err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_sync, &regval);684	if (err)685		goto mlxreg_lc_regmap_read_sync_fail;686 687	/* Power on line card if necessary. */688	if (regval & mlxreg_lc->data->mask) {689		mlxreg_lc->state |= MLXREG_LC_SYNCED;690		mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_SYNCED, 1);691		if (mlxreg_lc->state & ~MLXREG_LC_POWERED) {692			err = mlxreg_lc_power_on_off(mlxreg_lc, 1);693			if (err)694				goto mlxreg_lc_regmap_power_on_off_fail;695		}696	}697 698	mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);699 700	return 0;701 702mlxreg_lc_regmap_power_on_off_fail:703mlxreg_lc_regmap_read_sync_fail:704	if (mlxreg_lc->state & MLXREG_LC_POWERED)705		mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,706						 mlxreg_lc->main_devs_num);707mlxreg_lc_create_static_devices_failed:708	mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->aux_devs, mlxreg_lc->aux_devs_num);709mlxreg_lc_regmap_read_power_fail:710	return err;711}712 713static int714mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,715		      struct mlxreg_core_data *data)716{717	struct device *dev = &data->hpdev.client->dev;718	int lsb, err;719	u32 regval;720 721	/* Validate line card type. */722	err = regmap_read(regmap, MLXREG_LC_REG_CONFIG_OFFSET, &lsb);723	err = (!err) ? regmap_read(regmap, MLXREG_LC_REG_CONFIG_OFFSET, &regval) : err;724	if (err)725		return err;726	regval = (regval & GENMASK(7, 0)) << 8 | (lsb & GENMASK(7, 0));727	switch (regval) {728	case MLXREG_LC_SN4800_C16:729		err = mlxreg_lc_sn4800_c16_config_init(mlxreg_lc, regmap, data);730		if (err) {731			dev_err(dev, "Failed to config client %s at bus %d at addr 0x%02x\n",732				data->hpdev.brdinfo->type, data->hpdev.nr,733				data->hpdev.brdinfo->addr);734			return err;735		}736		break;737	default:738		return -ENODEV;739	}740 741	/* Create mux infrastructure. */742	mlxreg_lc->mux_data->handle = mlxreg_lc;743	mlxreg_lc->mux_data->completion_notify = mlxreg_lc_completion_notify;744	mlxreg_lc->mux_brdinfo->platform_data = mlxreg_lc->mux_data;745	mlxreg_lc->mux = platform_device_register_resndata(dev, "i2c-mux-mlxcpld", data->hpdev.nr,746							   NULL, 0, mlxreg_lc->mux_data,747							   sizeof(*mlxreg_lc->mux_data));748	if (IS_ERR(mlxreg_lc->mux)) {749		dev_err(dev, "Failed to create mux infra for client %s at bus %d at addr 0x%02x\n",750			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);751		return PTR_ERR(mlxreg_lc->mux);752	}753 754	/* Register IO access driver. */755	if (mlxreg_lc->io_data) {756		mlxreg_lc->io_data->regmap = regmap;757		mlxreg_lc->io_regs =758		platform_device_register_resndata(dev, "mlxreg-io", data->hpdev.nr, NULL, 0,759						  mlxreg_lc->io_data, sizeof(*mlxreg_lc->io_data));760		if (IS_ERR(mlxreg_lc->io_regs)) {761			dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n",762				data->hpdev.brdinfo->type, data->hpdev.nr,763				data->hpdev.brdinfo->addr);764			err = PTR_ERR(mlxreg_lc->io_regs);765			goto fail_register_io;766		}767	}768 769	/* Register LED driver. */770	if (mlxreg_lc->led_data) {771		mlxreg_lc->led_data->regmap = regmap;772		mlxreg_lc->led =773		platform_device_register_resndata(dev, "leds-mlxreg", data->hpdev.nr, NULL, 0,774						  mlxreg_lc->led_data,775						  sizeof(*mlxreg_lc->led_data));776		if (IS_ERR(mlxreg_lc->led)) {777			dev_err(dev, "Failed to create LED objects for client %s at bus %d at addr 0x%02x\n",778				data->hpdev.brdinfo->type, data->hpdev.nr,779				data->hpdev.brdinfo->addr);780			err = PTR_ERR(mlxreg_lc->led);781			goto fail_register_led;782		}783	}784 785	return 0;786 787fail_register_led:788	if (mlxreg_lc->io_regs)789		platform_device_unregister(mlxreg_lc->io_regs);790fail_register_io:791	if (mlxreg_lc->mux)792		platform_device_unregister(mlxreg_lc->mux);793 794	return err;795}796 797static void mlxreg_lc_config_exit(struct mlxreg_lc *mlxreg_lc)798{799	/* Unregister LED driver. */800	if (mlxreg_lc->led)801		platform_device_unregister(mlxreg_lc->led);802	/* Unregister IO access driver. */803	if (mlxreg_lc->io_regs)804		platform_device_unregister(mlxreg_lc->io_regs);805	/* Remove mux infrastructure. */806	if (mlxreg_lc->mux)807		platform_device_unregister(mlxreg_lc->mux);808}809 810static int mlxreg_lc_probe(struct platform_device *pdev)811{812	struct mlxreg_core_hotplug_platform_data *par_pdata;813	struct mlxreg_core_data *data;814	struct mlxreg_lc *mlxreg_lc;815	void *regmap;816	int i, err;817 818	data = dev_get_platdata(&pdev->dev);819	if (!data)820		return -EINVAL;821 822	mlxreg_lc = devm_kzalloc(&pdev->dev, sizeof(*mlxreg_lc), GFP_KERNEL);823	if (!mlxreg_lc)824		return -ENOMEM;825 826	mutex_init(&mlxreg_lc->lock);827	/* Set event notification callback. */828	data->notifier->user_handler = mlxreg_lc_event_handler;829	data->notifier->handle = mlxreg_lc;830 831	data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);832	if (!data->hpdev.adapter) {833		dev_err(&pdev->dev, "Failed to get adapter for bus %d\n",834			data->hpdev.nr);835		err = -EFAULT;836		goto i2c_get_adapter_fail;837	}838 839	/* Create device at the top of line card I2C tree.*/840	data->hpdev.client = i2c_new_client_device(data->hpdev.adapter,841						   data->hpdev.brdinfo);842	if (IS_ERR(data->hpdev.client)) {843		dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",844			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);845		err = PTR_ERR(data->hpdev.client);846		goto i2c_new_device_fail;847	}848 849	regmap = devm_regmap_init_i2c(data->hpdev.client,850				      &mlxreg_lc_regmap_conf);851	if (IS_ERR(regmap)) {852		dev_err(&pdev->dev, "Failed to create regmap for client %s at bus %d at addr 0x%02x\n",853			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);854		err = PTR_ERR(regmap);855		goto devm_regmap_init_i2c_fail;856	}857 858	/* Set default registers. */859	for (i = 0; i < mlxreg_lc_regmap_conf.num_reg_defaults; i++) {860		err = regmap_write(regmap, mlxreg_lc_regmap_default[i].reg,861				   mlxreg_lc_regmap_default[i].def);862		if (err) {863			dev_err(&pdev->dev, "Failed to set default regmap %d for client %s at bus %d at addr 0x%02x\n",864				i, data->hpdev.brdinfo->type, data->hpdev.nr,865				data->hpdev.brdinfo->addr);866			goto regmap_write_fail;867		}868	}869 870	/* Sync registers with hardware. */871	regcache_mark_dirty(regmap);872	err = regcache_sync(regmap);873	if (err) {874		dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n",875			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);876		goto regcache_sync_fail;877	}878 879	par_pdata = data->hpdev.brdinfo->platform_data;880	mlxreg_lc->par_regmap = par_pdata->regmap;881	mlxreg_lc->data = data;882	mlxreg_lc->dev = &pdev->dev;883	platform_set_drvdata(pdev, mlxreg_lc);884 885	/* Configure line card. */886	err = mlxreg_lc_config_init(mlxreg_lc, regmap, data);887	if (err)888		goto mlxreg_lc_config_init_fail;889 890	return 0;891 892mlxreg_lc_config_init_fail:893regcache_sync_fail:894regmap_write_fail:895devm_regmap_init_i2c_fail:896	i2c_unregister_device(data->hpdev.client);897	data->hpdev.client = NULL;898i2c_new_device_fail:899	i2c_put_adapter(data->hpdev.adapter);900	data->hpdev.adapter = NULL;901i2c_get_adapter_fail:902	/* Clear event notification callback and handle. */903	if (data->notifier) {904		data->notifier->user_handler = NULL;905		data->notifier->handle = NULL;906	}907	return err;908}909 910static void mlxreg_lc_remove(struct platform_device *pdev)911{912	struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);913	struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev);914 915	mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 0);916 917	/*918	 * Probing and removing are invoked by hotplug events raised upon line card insertion and919	 * removing. If probing procedure fails all data is cleared. However, hotplug event still920	 * will be raised on line card removing and activate removing procedure. In this case there921	 * is nothing to remove.922	 */923	if (!data->notifier || !data->notifier->handle)924		return;925 926	/* Clear event notification callback and handle. */927	data->notifier->user_handler = NULL;928	data->notifier->handle = NULL;929 930	/* Destroy static I2C device feeding by main power. */931	mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,932					 mlxreg_lc->main_devs_num);933	/* Destroy static I2C device feeding by auxiliary power. */934	mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->aux_devs, mlxreg_lc->aux_devs_num);935	/* Unregister underlying drivers. */936	mlxreg_lc_config_exit(mlxreg_lc);937	if (data->hpdev.client) {938		i2c_unregister_device(data->hpdev.client);939		data->hpdev.client = NULL;940		i2c_put_adapter(data->hpdev.adapter);941		data->hpdev.adapter = NULL;942	}943}944 945static struct platform_driver mlxreg_lc_driver = {946	.probe = mlxreg_lc_probe,947	.remove_new = mlxreg_lc_remove,948	.driver = {949		.name = "mlxreg-lc",950	},951};952 953module_platform_driver(mlxreg_lc_driver);954 955MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");956MODULE_DESCRIPTION("Nvidia line card platform driver");957MODULE_LICENSE("Dual BSD/GPL");958MODULE_ALIAS("platform:mlxreg-lc");959