/* nvsw_sn2201 - device private data * @dev: platform device; * @io_data: register access platform data; * @led_data: LED platform data; * @hotplug_data: hotplug platform data; * @i2c_data: I2C controller platform data; * @led: LED device; * @io_regs: register access device; * @pdev_hotplug: hotplug device; * @sn2201_devs: I2C devices for sn2201 devices; * @sn2201_devs_num: number of I2C devices for sn2201 device; * @main_mux_devs: I2C devices for main mux; * @main_mux_devs_num: number of I2C devices for main mux; * @cpld_devs: I2C devices for cpld; * @cpld_devs_num: number of I2C devices for cpld; * @main_mux_deferred_nr: I2C adapter number must be exist prior creating devices execution; * @ext_pwr_source: true if system powered by external power supply; false - by internal;
*/ struct nvsw_sn2201 { struct device *dev; struct mlxreg_core_platform_data *io_data; struct mlxreg_core_platform_data *led_data; struct mlxreg_core_platform_data *wd_data; struct mlxreg_core_hotplug_platform_data *hotplug_data; struct mlxreg_core_hotplug_platform_data *i2c_data; struct platform_device *led; struct platform_device *wd; struct platform_device *io_regs; struct platform_device *pdev_hotplug; struct platform_device *pdev_i2c; struct mlxreg_hotplug_device *sn2201_devs; int sn2201_devs_num; struct mlxreg_hotplug_device *main_mux_devs; int main_mux_devs_num; struct mlxreg_hotplug_device *cpld_devs; int cpld_devs_num; int main_mux_deferred_nr; bool ext_pwr_source;
};
staticbool nvsw_sn2201_writeable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case NVSW_SN2201_PSU_CTRL_OFFSET: case NVSW_SN2201_QSFP28_LP_STATUS_OFFSET: case NVSW_SN2201_QSFP28_RST_STATUS_OFFSET: case NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET: case NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET: case NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET: case NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET: case NVSW_SN2201_SYS_RST_STATUS_OFFSET: case NVSW_SN2201_SYS_INT_MASK_OFFSET: case NVSW_SN2201_ASIC_EVENT_OFFSET: case NVSW_SN2201_ASIC_MAKS_OFFSET: case NVSW_SN2201_THML_EVENT_OFFSET: case NVSW_SN2201_THML_MASK_OFFSET: case NVSW_SN2201_PS_ALT_EVENT_OFFSET: case NVSW_SN2201_PS_ALT_MASK_OFFSET: case NVSW_SN2201_PS_PRSNT_EVENT_OFFSET: case NVSW_SN2201_PS_PRSNT_MASK_OFFSET: case NVSW_SN2201_PS_DC_OK_EVENT_OFFSET: case NVSW_SN2201_PS_DC_OK_MASK_OFFSET: case NVSW_SN2201_RST_SW_CTRL_OFFSET: case NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET: case NVSW_SN2201_FAN_PRSNT_MASK_OFFSET: case NVSW_SN2201_WD_TMR_OFFSET_LSB: case NVSW_SN2201_WD_TMR_OFFSET_MSB: case NVSW_SN2201_WD_ACT_OFFSET: case NVSW_SN2201_FAN_LED1_CTRL_OFFSET: case NVSW_SN2201_FAN_LED2_CTRL_OFFSET: returntrue;
} returnfalse;
}
staticbool nvsw_sn2201_readable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case NVSW_SN2201_HW_VER_ID_OFFSET: case NVSW_SN2201_BOARD_ID_OFFSET: case NVSW_SN2201_CPLD_VER_OFFSET: case NVSW_SN2201_CPLD_MVER_OFFSET: case NVSW_SN2201_CPLD_ID_OFFSET: case NVSW_SN2201_CPLD_PN_OFFSET: case NVSW_SN2201_CPLD_PN1_OFFSET: case NVSW_SN2201_PSU_CTRL_OFFSET: case NVSW_SN2201_QSFP28_STATUS_OFFSET: case NVSW_SN2201_QSFP28_INT_STATUS_OFFSET: case NVSW_SN2201_QSFP28_LP_STATUS_OFFSET: case NVSW_SN2201_QSFP28_RST_STATUS_OFFSET: case NVSW_SN2201_SYS_STATUS_OFFSET: case NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET: case NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET: case NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET: case NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET: case NVSW_SN2201_SYS_RST_STATUS_OFFSET: case NVSW_SN2201_RST_CAUSE1_OFFSET: case NVSW_SN2201_RST_CAUSE2_OFFSET: case NVSW_SN2201_SYS_INT_STATUS_OFFSET: case NVSW_SN2201_SYS_INT_MASK_OFFSET: case NVSW_SN2201_ASIC_STATUS_OFFSET: case NVSW_SN2201_ASIC_EVENT_OFFSET: case NVSW_SN2201_ASIC_MAKS_OFFSET: case NVSW_SN2201_THML_STATUS_OFFSET: case NVSW_SN2201_THML_EVENT_OFFSET: case NVSW_SN2201_THML_MASK_OFFSET: case NVSW_SN2201_PS_ALT_STATUS_OFFSET: case NVSW_SN2201_PS_ALT_EVENT_OFFSET: case NVSW_SN2201_PS_ALT_MASK_OFFSET: case NVSW_SN2201_PS_PRSNT_STATUS_OFFSET: case NVSW_SN2201_PS_PRSNT_EVENT_OFFSET: case NVSW_SN2201_PS_PRSNT_MASK_OFFSET: case NVSW_SN2201_PS_DC_OK_STATUS_OFFSET: case NVSW_SN2201_PS_DC_OK_EVENT_OFFSET: case NVSW_SN2201_PS_DC_OK_MASK_OFFSET: case NVSW_SN2201_RST_SW_CTRL_OFFSET: case NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET: case NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET: case NVSW_SN2201_FAN_PRSNT_MASK_OFFSET: case NVSW_SN2201_WD_TMR_OFFSET_LSB: case NVSW_SN2201_WD_TMR_OFFSET_MSB: case NVSW_SN2201_WD_ACT_OFFSET: case NVSW_SN2201_FAN_LED1_CTRL_OFFSET: case NVSW_SN2201_FAN_LED2_CTRL_OFFSET: returntrue;
} returnfalse;
}
staticbool nvsw_sn2201_volatile_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case NVSW_SN2201_HW_VER_ID_OFFSET: case NVSW_SN2201_BOARD_ID_OFFSET: case NVSW_SN2201_CPLD_VER_OFFSET: case NVSW_SN2201_CPLD_MVER_OFFSET: case NVSW_SN2201_CPLD_ID_OFFSET: case NVSW_SN2201_CPLD_PN_OFFSET: case NVSW_SN2201_CPLD_PN1_OFFSET: case NVSW_SN2201_PSU_CTRL_OFFSET: case NVSW_SN2201_QSFP28_STATUS_OFFSET: case NVSW_SN2201_QSFP28_INT_STATUS_OFFSET: case NVSW_SN2201_QSFP28_LP_STATUS_OFFSET: case NVSW_SN2201_QSFP28_RST_STATUS_OFFSET: case NVSW_SN2201_SYS_STATUS_OFFSET: case NVSW_SN2201_FRONT_SYS_LED_CTRL_OFFSET: case NVSW_SN2201_FRONT_PSU_LED_CTRL_OFFSET: case NVSW_SN2201_FRONT_UID_LED_CTRL_OFFSET: case NVSW_SN2201_QSFP28_LED_TEST_STATUS_OFFSET: case NVSW_SN2201_SYS_RST_STATUS_OFFSET: case NVSW_SN2201_RST_CAUSE1_OFFSET: case NVSW_SN2201_RST_CAUSE2_OFFSET: case NVSW_SN2201_SYS_INT_STATUS_OFFSET: case NVSW_SN2201_SYS_INT_MASK_OFFSET: case NVSW_SN2201_ASIC_STATUS_OFFSET: case NVSW_SN2201_ASIC_EVENT_OFFSET: case NVSW_SN2201_ASIC_MAKS_OFFSET: case NVSW_SN2201_THML_STATUS_OFFSET: case NVSW_SN2201_THML_EVENT_OFFSET: case NVSW_SN2201_THML_MASK_OFFSET: case NVSW_SN2201_PS_ALT_STATUS_OFFSET: case NVSW_SN2201_PS_ALT_EVENT_OFFSET: case NVSW_SN2201_PS_ALT_MASK_OFFSET: case NVSW_SN2201_PS_PRSNT_STATUS_OFFSET: case NVSW_SN2201_PS_PRSNT_EVENT_OFFSET: case NVSW_SN2201_PS_PRSNT_MASK_OFFSET: case NVSW_SN2201_PS_DC_OK_STATUS_OFFSET: case NVSW_SN2201_PS_DC_OK_EVENT_OFFSET: case NVSW_SN2201_PS_DC_OK_MASK_OFFSET: case NVSW_SN2201_RST_SW_CTRL_OFFSET: case NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET: case NVSW_SN2201_FAN_PRSNT_EVENT_OFFSET: case NVSW_SN2201_FAN_PRSNT_MASK_OFFSET: case NVSW_SN2201_WD_TMR_OFFSET_LSB: case NVSW_SN2201_WD_TMR_OFFSET_MSB: case NVSW_SN2201_FAN_LED1_CTRL_OFFSET: case NVSW_SN2201_FAN_LED2_CTRL_OFFSET: returntrue;
} returnfalse;
}
staticint
nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201, struct mlxreg_hotplug_device *devs, int size)
{ struct mlxreg_hotplug_device *dev = devs; int ret; int i;
/* Create I2C static devices. */ for (i = 0; i < size; i++, dev++) {
dev->client = i2c_new_client_device(dev->adapter, dev->brdinfo); if (IS_ERR(dev->client)) {
dev_err(nvsw_sn2201->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
dev->brdinfo->type,
dev->nr, dev->brdinfo->addr);
dev->adapter = NULL;
ret = PTR_ERR(dev->client); goto fail_create_static_devices;
}
}
staticvoid nvsw_sn2201_destroy_static_devices(struct nvsw_sn2201 *nvsw_sn2201, struct mlxreg_hotplug_device *devs, int size)
{ struct mlxreg_hotplug_device *dev = devs; int i;
/* Destroy static I2C device for SN2201 static devices. */ for (i = 0; i < size; i++, dev++) { if (dev->client) {
i2c_unregister_device(dev->client);
dev->client = NULL;
i2c_put_adapter(dev->adapter);
dev->adapter = NULL;
}
}
}
staticint nvsw_sn2201_config_post_init(struct nvsw_sn2201 *nvsw_sn2201)
{ struct mlxreg_hotplug_device *sn2201_dev; struct i2c_adapter *adap; struct device *dev; int i, err;
dev = nvsw_sn2201->dev;
adap = i2c_get_adapter(nvsw_sn2201->main_mux_deferred_nr); if (!adap) {
dev_err(dev, "Failed to get adapter for bus %d\n",
nvsw_sn2201->main_mux_deferred_nr); return -ENODEV;
}
i2c_put_adapter(adap);
/* Update board info. */
sn2201_dev = nvsw_sn2201->sn2201_devs; for (i = 0; i < nvsw_sn2201->sn2201_devs_num; i++, sn2201_dev++) {
sn2201_dev->adapter = i2c_get_adapter(sn2201_dev->nr); if (!sn2201_dev->adapter) return -ENODEV;
i2c_put_adapter(sn2201_dev->adapter);
}
err = nvsw_sn2201_create_static_devices(nvsw_sn2201, nvsw_sn2201->sn2201_devs,
nvsw_sn2201->sn2201_devs_num); if (err)
dev_err(dev, "Failed to create static devices\n");
fail_register_hotplug: if (nvsw_sn2201->wd)
platform_device_unregister(nvsw_sn2201->wd);
fail_register_wd: if (nvsw_sn2201->led)
platform_device_unregister(nvsw_sn2201->led);
fail_register_led: if (nvsw_sn2201->io_regs)
platform_device_unregister(nvsw_sn2201->io_regs);
fail_register_io:
return err;
}
staticvoid nvsw_sn2201_config_exit(struct nvsw_sn2201 *nvsw_sn2201)
{ /* Unregister hotplug driver. */ if (nvsw_sn2201->pdev_hotplug)
platform_device_unregister(nvsw_sn2201->pdev_hotplug); /* Unregister WD driver. */ if (nvsw_sn2201->wd)
platform_device_unregister(nvsw_sn2201->wd); /* Unregister LED driver. */ if (nvsw_sn2201->led)
platform_device_unregister(nvsw_sn2201->led); /* Unregister IO access driver. */ if (nvsw_sn2201->io_regs)
platform_device_unregister(nvsw_sn2201->io_regs);
}
/* * Initialization is divided into two parts: * - I2C main bus init. * - Mux creation and attaching devices to the mux, * which assumes that the main bus is already created. * This separation is required for synchronization between these two parts. * Completion notify callback is used to make this flow synchronized.
*/ staticint nvsw_sn2201_i2c_completion_notify(void *handle, int id)
{ struct nvsw_sn2201 *nvsw_sn2201 = handle; void *regmap; int i, err;
/* Create main mux. */
nvsw_sn2201->main_mux_devs->adapter = i2c_get_adapter(nvsw_sn2201->main_mux_devs->nr); if (!nvsw_sn2201->main_mux_devs->adapter) {
err = -ENODEV;
dev_err(nvsw_sn2201->dev, "Failed to get adapter for bus %d\n",
nvsw_sn2201->main_mux_devs->nr); goto i2c_get_adapter_main_fail;
}
nvsw_sn2201->main_mux_devs_num = ARRAY_SIZE(nvsw_sn2201_main_mux_brdinfo);
err = nvsw_sn2201_create_static_devices(nvsw_sn2201, nvsw_sn2201->main_mux_devs,
nvsw_sn2201->main_mux_devs_num); if (err) {
dev_err(nvsw_sn2201->dev, "Failed to create main mux devices\n"); goto nvsw_sn2201_create_static_devices_fail;
}
nvsw_sn2201->cpld_devs->adapter = i2c_get_adapter(nvsw_sn2201->cpld_devs->nr); if (!nvsw_sn2201->cpld_devs->adapter) {
err = -ENODEV;
dev_err(nvsw_sn2201->dev, "Failed to get adapter for bus %d\n",
nvsw_sn2201->cpld_devs->nr); goto i2c_get_adapter_fail;
}
/* Create CPLD device. */
nvsw_sn2201->cpld_devs->client = i2c_new_dummy_device(nvsw_sn2201->cpld_devs->adapter,
NVSW_SN2201_CPLD_I2CADDR); if (IS_ERR(nvsw_sn2201->cpld_devs->client)) {
err = PTR_ERR(nvsw_sn2201->cpld_devs->client);
dev_err(nvsw_sn2201->dev, "Failed to create %s cpld device at bus %d at addr 0x%02x\n",
nvsw_sn2201->cpld_devs->brdinfo->type, nvsw_sn2201->cpld_devs->nr,
nvsw_sn2201->cpld_devs->brdinfo->addr); goto i2c_new_dummy_fail;
}
regmap = devm_regmap_init_i2c(nvsw_sn2201->cpld_devs->client, &nvsw_sn2201_regmap_conf); if (IS_ERR(regmap)) {
err = PTR_ERR(regmap);
dev_err(nvsw_sn2201->dev, "Failed to initialise managed register map\n"); goto devm_regmap_init_i2c_fail;
}
/* Set default registers. */ for (i = 0; i < nvsw_sn2201_regmap_conf.num_reg_defaults; i++) {
err = regmap_write(regmap, nvsw_sn2201_regmap_default[i].reg,
nvsw_sn2201_regmap_default[i].def); if (err) {
dev_err(nvsw_sn2201->dev, "Failed to set register at offset 0x%02x to default value: 0x%02x\n",
nvsw_sn2201_regmap_default[i].reg,
nvsw_sn2201_regmap_default[i].def); goto regmap_write_fail;
}
}
/* Sync registers with hardware. */
regcache_mark_dirty(regmap);
err = regcache_sync(regmap); if (err) {
dev_err(nvsw_sn2201->dev, "Failed to Sync registers with hardware\n"); goto regcache_sync_fail;
}
/* Configure SN2201 board. */
err = nvsw_sn2201_config_init(nvsw_sn2201, regmap); if (err) {
dev_err(nvsw_sn2201->dev, "Failed to configure board\n"); goto nvsw_sn2201_config_init_fail;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.