Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Nvidia line card driver
0004  *
0005  * Copyright (C) 2020 Nvidia Technologies Ltd.
0006  */
0007 
0008 #include <linux/device.h>
0009 #include <linux/i2c.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_data/mlxcpld.h>
0012 #include <linux/platform_data/mlxreg.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regmap.h>
0015 
0016 /* I2C bus IO offsets */
0017 #define MLXREG_LC_REG_CPLD1_VER_OFFSET      0x2500
0018 #define MLXREG_LC_REG_FPGA1_VER_OFFSET      0x2501
0019 #define MLXREG_LC_REG_CPLD1_PN_OFFSET       0x2504
0020 #define MLXREG_LC_REG_FPGA1_PN_OFFSET       0x2506
0021 #define MLXREG_LC_REG_RESET_CAUSE_OFFSET    0x251d
0022 #define MLXREG_LC_REG_LED1_OFFSET       0x2520
0023 #define MLXREG_LC_REG_GP0_OFFSET        0x252e
0024 #define MLXREG_LC_REG_FIELD_UPGRADE     0x2534
0025 #define MLXREG_LC_CHANNEL_I2C_REG       0x25dc
0026 #define MLXREG_LC_REG_CPLD1_MVER_OFFSET     0x25de
0027 #define MLXREG_LC_REG_FPGA1_MVER_OFFSET     0x25df
0028 #define MLXREG_LC_REG_MAX_POWER_OFFSET      0x25f1
0029 #define MLXREG_LC_REG_CONFIG_OFFSET     0x25fb
0030 #define MLXREG_LC_REG_MAX           0x3fff
0031 
0032 /**
0033  * enum mlxreg_lc_type - line cards types
0034  *
0035  * @MLXREG_LC_SN4800_C16: 100GbE line card with 16 QSFP28 ports;
0036  */
0037 enum mlxreg_lc_type {
0038     MLXREG_LC_SN4800_C16 = 0x0000,
0039 };
0040 
0041 /**
0042  * enum mlxreg_lc_state - line cards state
0043  *
0044  * @MLXREG_LC_INITIALIZED: line card is initialized;
0045  * @MLXREG_LC_POWERED: line card is powered;
0046  * @MLXREG_LC_SYNCED: line card is synchronized between hardware and firmware;
0047  */
0048 enum mlxreg_lc_state {
0049     MLXREG_LC_INITIALIZED = BIT(0),
0050     MLXREG_LC_POWERED = BIT(1),
0051     MLXREG_LC_SYNCED = BIT(2),
0052 };
0053 
0054 #define MLXREG_LC_CONFIGURED    (MLXREG_LC_INITIALIZED | MLXREG_LC_POWERED | MLXREG_LC_SYNCED)
0055 
0056 /* mlxreg_lc - device private data
0057  * @dev: platform device;
0058  * @lock: line card lock;
0059  * @par_regmap: parent device regmap handle;
0060  * @data: pltaform core data;
0061  * @io_data: register access platform data;
0062  * @led_data: LED platform data ;
0063  * @mux_data: MUX platform data;
0064  * @led: LED device;
0065  * @io_regs: register access device;
0066  * @mux_brdinfo: mux configuration;
0067  * @mux: mux devices;
0068  * @aux_devs: I2C devices feeding by auxiliary power;
0069  * @aux_devs_num: number of I2C devices feeding by auxiliary power;
0070  * @main_devs: I2C devices feeding by main power;
0071  * @main_devs_num: number of I2C devices feeding by main power;
0072  * @state: line card state;
0073  */
0074 struct mlxreg_lc {
0075     struct device *dev;
0076     struct mutex lock; /* line card access lock */
0077     void *par_regmap;
0078     struct mlxreg_core_data *data;
0079     struct mlxreg_core_platform_data *io_data;
0080     struct mlxreg_core_platform_data *led_data;
0081     struct mlxcpld_mux_plat_data *mux_data;
0082     struct platform_device *led;
0083     struct platform_device *io_regs;
0084     struct i2c_board_info *mux_brdinfo;
0085     struct platform_device *mux;
0086     struct mlxreg_hotplug_device *aux_devs;
0087     int aux_devs_num;
0088     struct mlxreg_hotplug_device *main_devs;
0089     int main_devs_num;
0090     enum mlxreg_lc_state state;
0091 };
0092 
0093 static bool mlxreg_lc_writeable_reg(struct device *dev, unsigned int reg)
0094 {
0095     switch (reg) {
0096     case MLXREG_LC_REG_LED1_OFFSET:
0097     case MLXREG_LC_REG_GP0_OFFSET:
0098     case MLXREG_LC_REG_FIELD_UPGRADE:
0099     case MLXREG_LC_CHANNEL_I2C_REG:
0100         return true;
0101     }
0102     return false;
0103 }
0104 
0105 static bool mlxreg_lc_readable_reg(struct device *dev, unsigned int reg)
0106 {
0107     switch (reg) {
0108     case MLXREG_LC_REG_CPLD1_VER_OFFSET:
0109     case MLXREG_LC_REG_FPGA1_VER_OFFSET:
0110     case MLXREG_LC_REG_CPLD1_PN_OFFSET:
0111     case MLXREG_LC_REG_FPGA1_PN_OFFSET:
0112     case MLXREG_LC_REG_RESET_CAUSE_OFFSET:
0113     case MLXREG_LC_REG_LED1_OFFSET:
0114     case MLXREG_LC_REG_GP0_OFFSET:
0115     case MLXREG_LC_REG_FIELD_UPGRADE:
0116     case MLXREG_LC_CHANNEL_I2C_REG:
0117     case MLXREG_LC_REG_CPLD1_MVER_OFFSET:
0118     case MLXREG_LC_REG_FPGA1_MVER_OFFSET:
0119     case MLXREG_LC_REG_MAX_POWER_OFFSET:
0120     case MLXREG_LC_REG_CONFIG_OFFSET:
0121         return true;
0122     }
0123     return false;
0124 }
0125 
0126 static bool mlxreg_lc_volatile_reg(struct device *dev, unsigned int reg)
0127 {
0128     switch (reg) {
0129     case MLXREG_LC_REG_CPLD1_VER_OFFSET:
0130     case MLXREG_LC_REG_FPGA1_VER_OFFSET:
0131     case MLXREG_LC_REG_CPLD1_PN_OFFSET:
0132     case MLXREG_LC_REG_FPGA1_PN_OFFSET:
0133     case MLXREG_LC_REG_RESET_CAUSE_OFFSET:
0134     case MLXREG_LC_REG_LED1_OFFSET:
0135     case MLXREG_LC_REG_GP0_OFFSET:
0136     case MLXREG_LC_REG_FIELD_UPGRADE:
0137     case MLXREG_LC_CHANNEL_I2C_REG:
0138     case MLXREG_LC_REG_CPLD1_MVER_OFFSET:
0139     case MLXREG_LC_REG_FPGA1_MVER_OFFSET:
0140     case MLXREG_LC_REG_MAX_POWER_OFFSET:
0141     case MLXREG_LC_REG_CONFIG_OFFSET:
0142         return true;
0143     }
0144     return false;
0145 }
0146 
0147 static const struct reg_default mlxreg_lc_regmap_default[] = {
0148     { MLXREG_LC_CHANNEL_I2C_REG, 0x00 },
0149 };
0150 
0151 /* Configuration for the register map of a device with 2 bytes address space. */
0152 static const struct regmap_config mlxreg_lc_regmap_conf = {
0153     .reg_bits = 16,
0154     .val_bits = 8,
0155     .max_register = MLXREG_LC_REG_MAX,
0156     .cache_type = REGCACHE_FLAT,
0157     .writeable_reg = mlxreg_lc_writeable_reg,
0158     .readable_reg = mlxreg_lc_readable_reg,
0159     .volatile_reg = mlxreg_lc_volatile_reg,
0160     .reg_defaults = mlxreg_lc_regmap_default,
0161     .num_reg_defaults = ARRAY_SIZE(mlxreg_lc_regmap_default),
0162 };
0163 
0164 /* Default channels vector.
0165  * It contains only the channels, which physically connected to the devices,
0166  * empty channels are skipped.
0167  */
0168 static int mlxreg_lc_chan[] = {
0169     0x04, 0x05, 0x06, 0x07, 0x08, 0x10, 0x20, 0x21, 0x22, 0x23, 0x40, 0x41,
0170     0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
0171     0x4e, 0x4f
0172 };
0173 
0174 /* Defaul mux configuration. */
0175 static struct mlxcpld_mux_plat_data mlxreg_lc_mux_data[] = {
0176     {
0177         .chan_ids = mlxreg_lc_chan,
0178         .num_adaps = ARRAY_SIZE(mlxreg_lc_chan),
0179         .sel_reg_addr = MLXREG_LC_CHANNEL_I2C_REG,
0180         .reg_size = 2,
0181     },
0182 };
0183 
0184 /* Defaul mux board info. */
0185 static struct i2c_board_info mlxreg_lc_mux_brdinfo = {
0186     I2C_BOARD_INFO("i2c-mux-mlxcpld", 0x32),
0187 };
0188 
0189 /* Line card default auxiliary power static devices. */
0190 static struct i2c_board_info mlxreg_lc_aux_pwr_devices[] = {
0191     {
0192         I2C_BOARD_INFO("24c32", 0x51),
0193     },
0194     {
0195         I2C_BOARD_INFO("24c32", 0x51),
0196     },
0197 };
0198 
0199 /* Line card default auxiliary power board info. */
0200 static struct mlxreg_hotplug_device mlxreg_lc_aux_pwr_brdinfo[] = {
0201     {
0202         .brdinfo = &mlxreg_lc_aux_pwr_devices[0],
0203         .nr = 3,
0204     },
0205     {
0206         .brdinfo = &mlxreg_lc_aux_pwr_devices[1],
0207         .nr = 4,
0208     },
0209 };
0210 
0211 /* Line card default main power static devices. */
0212 static struct i2c_board_info mlxreg_lc_main_pwr_devices[] = {
0213     {
0214         I2C_BOARD_INFO("mp2975", 0x62),
0215     },
0216     {
0217         I2C_BOARD_INFO("mp2975", 0x64),
0218     },
0219     {
0220         I2C_BOARD_INFO("max11603", 0x6d),
0221     },
0222     {
0223         I2C_BOARD_INFO("lm25066", 0x15),
0224     },
0225 };
0226 
0227 /* Line card default main power board info. */
0228 static struct mlxreg_hotplug_device mlxreg_lc_main_pwr_brdinfo[] = {
0229     {
0230         .brdinfo = &mlxreg_lc_main_pwr_devices[0],
0231         .nr = 0,
0232     },
0233     {
0234         .brdinfo = &mlxreg_lc_main_pwr_devices[1],
0235         .nr = 0,
0236     },
0237     {
0238         .brdinfo = &mlxreg_lc_main_pwr_devices[2],
0239         .nr = 1,
0240     },
0241     {
0242         .brdinfo = &mlxreg_lc_main_pwr_devices[3],
0243         .nr = 2,
0244     },
0245 };
0246 
0247 /* LED default data. */
0248 static struct mlxreg_core_data mlxreg_lc_led_data[] = {
0249     {
0250         .label = "status:green",
0251         .reg = MLXREG_LC_REG_LED1_OFFSET,
0252         .mask = GENMASK(7, 4),
0253     },
0254     {
0255         .label = "status:orange",
0256         .reg = MLXREG_LC_REG_LED1_OFFSET,
0257         .mask = GENMASK(7, 4),
0258     },
0259 };
0260 
0261 static struct mlxreg_core_platform_data mlxreg_lc_led = {
0262     .identity = "pci",
0263     .data = mlxreg_lc_led_data,
0264     .counter = ARRAY_SIZE(mlxreg_lc_led_data),
0265 };
0266 
0267 /* Default register access data. */
0268 static struct mlxreg_core_data mlxreg_lc_io_data[] = {
0269     {
0270         .label = "cpld1_version",
0271         .reg = MLXREG_LC_REG_CPLD1_VER_OFFSET,
0272         .bit = GENMASK(7, 0),
0273         .mode = 0444,
0274     },
0275     {
0276         .label = "fpga1_version",
0277         .reg = MLXREG_LC_REG_FPGA1_VER_OFFSET,
0278         .bit = GENMASK(7, 0),
0279         .mode = 0444,
0280     },
0281     {
0282         .label = "cpld1_pn",
0283         .reg = MLXREG_LC_REG_CPLD1_PN_OFFSET,
0284         .bit = GENMASK(15, 0),
0285         .mode = 0444,
0286         .regnum = 2,
0287     },
0288     {
0289         .label = "fpga1_pn",
0290         .reg = MLXREG_LC_REG_FPGA1_PN_OFFSET,
0291         .bit = GENMASK(15, 0),
0292         .mode = 0444,
0293         .regnum = 2,
0294     },
0295     {
0296         .label = "cpld1_version_min",
0297         .reg = MLXREG_LC_REG_CPLD1_MVER_OFFSET,
0298         .bit = GENMASK(7, 0),
0299         .mode = 0444,
0300     },
0301     {
0302         .label = "fpga1_version_min",
0303         .reg = MLXREG_LC_REG_FPGA1_MVER_OFFSET,
0304         .bit = GENMASK(7, 0),
0305         .mode = 0444,
0306     },
0307     {
0308         .label = "reset_fpga_not_done",
0309         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0310         .mask = GENMASK(7, 0) & ~BIT(1),
0311         .mode = 0444,
0312     },
0313     {
0314         .label = "reset_aux_pwr_or_ref",
0315         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0316         .mask = GENMASK(7, 0) & ~BIT(2),
0317         .mode = 0444,
0318     },
0319     {
0320         .label = "reset_dc_dc_pwr_fail",
0321         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0322         .mask = GENMASK(7, 0) & ~BIT(3),
0323         .mode = 0444,
0324     },
0325     {
0326         .label = "reset_from_chassis",
0327         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0328         .mask = GENMASK(7, 0) & ~BIT(4),
0329         .mode = 0444,
0330     },
0331     {
0332         .label = "reset_pwr_off_from_chassis",
0333         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0334         .mask = GENMASK(7, 0) & ~BIT(5),
0335         .mode = 0444,
0336     },
0337     {
0338         .label = "reset_line_card",
0339         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0340         .mask = GENMASK(7, 0) & ~BIT(6),
0341         .mode = 0444,
0342     },
0343     {
0344         .label = "reset_line_card_pwr_en",
0345         .reg = MLXREG_LC_REG_RESET_CAUSE_OFFSET,
0346         .mask = GENMASK(7, 0) & ~BIT(7),
0347         .mode = 0444,
0348     },
0349     {
0350         .label = "cpld_upgrade_en",
0351         .reg = MLXREG_LC_REG_FIELD_UPGRADE,
0352         .mask = GENMASK(7, 0) & ~BIT(0),
0353         .mode = 0644,
0354         .secured = 1,
0355     },
0356     {
0357         .label = "fpga_upgrade_en",
0358         .reg = MLXREG_LC_REG_FIELD_UPGRADE,
0359         .mask = GENMASK(7, 0) & ~BIT(1),
0360         .mode = 0644,
0361         .secured = 1,
0362     },
0363     {
0364         .label = "qsfp_pwr_en",
0365         .reg = MLXREG_LC_REG_GP0_OFFSET,
0366         .mask = GENMASK(7, 0) & ~BIT(0),
0367         .mode = 0644,
0368     },
0369     {
0370         .label = "vpd_wp",
0371         .reg = MLXREG_LC_REG_GP0_OFFSET,
0372         .mask = GENMASK(7, 0) & ~BIT(3),
0373         .mode = 0644,
0374         .secured = 1,
0375     },
0376     {
0377         .label = "agb_spi_burn_en",
0378         .reg = MLXREG_LC_REG_GP0_OFFSET,
0379         .mask = GENMASK(7, 0) & ~BIT(5),
0380         .mode = 0644,
0381         .secured = 1,
0382     },
0383     {
0384         .label = "fpga_spi_burn_en",
0385         .reg = MLXREG_LC_REG_GP0_OFFSET,
0386         .mask = GENMASK(7, 0) & ~BIT(6),
0387         .mode = 0644,
0388         .secured = 1,
0389     },
0390     {
0391         .label = "max_power",
0392         .reg = MLXREG_LC_REG_MAX_POWER_OFFSET,
0393         .bit = GENMASK(15, 0),
0394         .mode = 0444,
0395         .regnum = 2,
0396     },
0397     {
0398         .label = "config",
0399         .reg = MLXREG_LC_REG_CONFIG_OFFSET,
0400         .bit = GENMASK(15, 0),
0401         .mode = 0444,
0402         .regnum = 2,
0403     },
0404 };
0405 
0406 static struct mlxreg_core_platform_data mlxreg_lc_regs_io = {
0407     .data = mlxreg_lc_io_data,
0408     .counter = ARRAY_SIZE(mlxreg_lc_io_data),
0409 };
0410 
0411 static int
0412 mlxreg_lc_create_static_devices(struct mlxreg_lc *mlxreg_lc, struct mlxreg_hotplug_device *devs,
0413                 int size)
0414 {
0415     struct mlxreg_hotplug_device *dev = devs;
0416     int i, ret;
0417 
0418     /* Create static I2C device feeding by auxiliary or main power. */
0419     for (i = 0; i < size; i++, dev++) {
0420         dev->client = i2c_new_client_device(dev->adapter, dev->brdinfo);
0421         if (IS_ERR(dev->client)) {
0422             dev_err(mlxreg_lc->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
0423                 dev->brdinfo->type, dev->nr, dev->brdinfo->addr);
0424 
0425             dev->adapter = NULL;
0426             ret = PTR_ERR(dev->client);
0427             goto fail_create_static_devices;
0428         }
0429     }
0430 
0431     return 0;
0432 
0433 fail_create_static_devices:
0434     while (--i >= 0) {
0435         dev = devs + i;
0436         i2c_unregister_device(dev->client);
0437         dev->client = NULL;
0438     }
0439     return ret;
0440 }
0441 
0442 static void
0443 mlxreg_lc_destroy_static_devices(struct mlxreg_lc *mlxreg_lc, struct mlxreg_hotplug_device *devs,
0444                  int size)
0445 {
0446     struct mlxreg_hotplug_device *dev = devs;
0447     int i;
0448 
0449     /* Destroy static I2C device feeding by auxiliary or main power. */
0450     for (i = 0; i < size; i++, dev++) {
0451         if (dev->client) {
0452             i2c_unregister_device(dev->client);
0453             dev->client = NULL;
0454         }
0455     }
0456 }
0457 
0458 static int mlxreg_lc_power_on_off(struct mlxreg_lc *mlxreg_lc, u8 action)
0459 {
0460     u32 regval;
0461     int err;
0462 
0463     err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);
0464     if (err)
0465         goto regmap_read_fail;
0466 
0467     if (action)
0468         regval |= BIT(mlxreg_lc->data->slot - 1);
0469     else
0470         regval &= ~BIT(mlxreg_lc->data->slot - 1);
0471 
0472     err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, regval);
0473 
0474 regmap_read_fail:
0475     return err;
0476 }
0477 
0478 static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)
0479 {
0480     u32 regval;
0481     int err;
0482 
0483     /*
0484      * Hardware holds the line card after powering on in the disabled state. Holding line card
0485      * in disabled state protects access to the line components, like FPGA and gearboxes.
0486      * Line card should be enabled in order to get it in operational state. Line card could be
0487      * disabled for moving it to non-operational state. Enabling line card does not affect the
0488      * line card which is already has been enabled. Disabling does not affect the disabled line
0489      * card.
0490      */
0491     err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, &regval);
0492     if (err)
0493         goto regmap_read_fail;
0494 
0495     if (action)
0496         regval |= BIT(mlxreg_lc->data->slot - 1);
0497     else
0498         regval &= ~BIT(mlxreg_lc->data->slot - 1);
0499 
0500     err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, regval);
0501 
0502 regmap_read_fail:
0503     return err;
0504 }
0505 
0506 static int
0507 mlxreg_lc_sn4800_c16_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,
0508                  struct mlxreg_core_data *data)
0509 {
0510     struct device *dev = &data->hpdev.client->dev;
0511 
0512     /* Set line card configuration according to the type. */
0513     mlxreg_lc->mux_data = mlxreg_lc_mux_data;
0514     mlxreg_lc->io_data = &mlxreg_lc_regs_io;
0515     mlxreg_lc->led_data = &mlxreg_lc_led;
0516     mlxreg_lc->mux_brdinfo = &mlxreg_lc_mux_brdinfo;
0517 
0518     mlxreg_lc->aux_devs = devm_kmemdup(dev, mlxreg_lc_aux_pwr_brdinfo,
0519                        sizeof(mlxreg_lc_aux_pwr_brdinfo), GFP_KERNEL);
0520     if (!mlxreg_lc->aux_devs)
0521         return -ENOMEM;
0522     mlxreg_lc->aux_devs_num = ARRAY_SIZE(mlxreg_lc_aux_pwr_brdinfo);
0523     mlxreg_lc->main_devs = devm_kmemdup(dev, mlxreg_lc_main_pwr_brdinfo,
0524                         sizeof(mlxreg_lc_main_pwr_brdinfo), GFP_KERNEL);
0525     if (!mlxreg_lc->main_devs)
0526         return -ENOMEM;
0527     mlxreg_lc->main_devs_num = ARRAY_SIZE(mlxreg_lc_main_pwr_brdinfo);
0528 
0529     return 0;
0530 }
0531 
0532 static void
0533 mlxreg_lc_state_update(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
0534 {
0535     if (action)
0536         mlxreg_lc->state |= state;
0537     else
0538         mlxreg_lc->state &= ~state;
0539 }
0540 
0541 static void
0542 mlxreg_lc_state_update_locked(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
0543 {
0544     mutex_lock(&mlxreg_lc->lock);
0545 
0546     if (action)
0547         mlxreg_lc->state |= state;
0548     else
0549         mlxreg_lc->state &= ~state;
0550 
0551     mutex_unlock(&mlxreg_lc->lock);
0552 }
0553 
0554 /*
0555  * Callback is to be called from mlxreg-hotplug driver to notify about line card about received
0556  * event.
0557  */
0558 static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind, u8 action)
0559 {
0560     struct mlxreg_lc *mlxreg_lc = handle;
0561     int err = 0;
0562 
0563     dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n",
0564          mlxreg_lc->data->slot, mlxreg_lc->state, kind, action);
0565 
0566     mutex_lock(&mlxreg_lc->lock);
0567     if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED)) {
0568         mutex_unlock(&mlxreg_lc->lock);
0569         return 0;
0570     }
0571 
0572     switch (kind) {
0573     case MLXREG_HOTPLUG_LC_SYNCED:
0574         /*
0575          * Synchronization event - hardware and firmware are synchronized. Power on/off
0576          * line card - to allow/disallow main power source.
0577          */
0578         mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, action);
0579         /* Power line card if it is not powered yet. */
0580         if (!(mlxreg_lc->state & MLXREG_LC_POWERED) && action) {
0581             err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
0582             if (err)
0583                 goto mlxreg_lc_power_on_off_fail;
0584         }
0585         /* In case line card is configured - enable it. */
0586         if (mlxreg_lc->state & MLXREG_LC_CONFIGURED && action)
0587             err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
0588         break;
0589     case MLXREG_HOTPLUG_LC_POWERED:
0590         /* Power event - attach or de-attach line card device feeding by the main power. */
0591         if (action) {
0592             /* Do not create devices, if line card is already powered. */
0593             if (mlxreg_lc->state & MLXREG_LC_POWERED) {
0594                 /* In case line card is configured - enable it. */
0595                 if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
0596                     err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
0597                 mutex_unlock(&mlxreg_lc->lock);
0598                 return err;
0599             }
0600             err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
0601                                   mlxreg_lc->main_devs_num);
0602             if (err)
0603                 goto mlxreg_lc_create_static_devices_fail;
0604 
0605             /* In case line card is already in ready state - enable it. */
0606             if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
0607                 err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
0608         } else {
0609             mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
0610                              mlxreg_lc->main_devs_num);
0611         }
0612         mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, action);
0613         break;
0614     case MLXREG_HOTPLUG_LC_READY:
0615         /*
0616          * Ready event – enable line card by releasing it from reset or disable it by put
0617          * to reset state.
0618          */
0619         err = mlxreg_lc_enable_disable(mlxreg_lc, !!action);
0620         break;
0621     case MLXREG_HOTPLUG_LC_THERMAL:
0622         /* Thermal shutdown event – power off line card. */
0623         if (action)
0624             err = mlxreg_lc_power_on_off(mlxreg_lc, 0);
0625         break;
0626     default:
0627         break;
0628     }
0629 
0630 mlxreg_lc_power_on_off_fail:
0631 mlxreg_lc_create_static_devices_fail:
0632     mutex_unlock(&mlxreg_lc->lock);
0633 
0634     return err;
0635 }
0636 
0637 /*
0638  * Callback is to be called from i2c-mux-mlxcpld driver to indicate that all adapter devices has
0639  * been created.
0640  */
0641 static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
0642                        struct i2c_adapter *adapters[])
0643 {
0644     struct mlxreg_hotplug_device *main_dev, *aux_dev;
0645     struct mlxreg_lc *mlxreg_lc = handle;
0646     u32 regval;
0647     int i, err;
0648 
0649     /* Update I2C devices feeding by auxiliary power. */
0650     aux_dev = mlxreg_lc->aux_devs;
0651     for (i = 0; i < mlxreg_lc->aux_devs_num; i++, aux_dev++) {
0652         aux_dev->adapter = adapters[aux_dev->nr];
0653         aux_dev->nr = adapters[aux_dev->nr]->nr;
0654     }
0655 
0656     err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->aux_devs,
0657                           mlxreg_lc->aux_devs_num);
0658     if (err)
0659         return err;
0660 
0661     /* Update I2C devices feeding by main power. */
0662     main_dev = mlxreg_lc->main_devs;
0663     for (i = 0; i < mlxreg_lc->main_devs_num; i++, main_dev++) {
0664         main_dev->adapter = adapters[main_dev->nr];
0665         main_dev->nr = adapters[main_dev->nr]->nr;
0666     }
0667 
0668     /* Verify if line card is powered. */
0669     err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);
0670     if (err)
0671         goto mlxreg_lc_regmap_read_power_fail;
0672 
0673     if (regval & mlxreg_lc->data->mask) {
0674         err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
0675                               mlxreg_lc->main_devs_num);
0676         if (err)
0677             goto mlxreg_lc_create_static_devices_failed;
0678 
0679         mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_POWERED, 1);
0680     }
0681 
0682     /* Verify if line card is synchronized. */
0683     err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_sync, &regval);
0684     if (err)
0685         goto mlxreg_lc_regmap_read_sync_fail;
0686 
0687     /* Power on line card if necessary. */
0688     if (regval & mlxreg_lc->data->mask) {
0689         mlxreg_lc->state |= MLXREG_LC_SYNCED;
0690         mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_SYNCED, 1);
0691         if (mlxreg_lc->state & ~MLXREG_LC_POWERED) {
0692             err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
0693             if (err)
0694                 goto mlxreg_lc_regmap_power_on_off_fail;
0695         }
0696     }
0697 
0698     mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);
0699 
0700     return 0;
0701 
0702 mlxreg_lc_regmap_power_on_off_fail:
0703 mlxreg_lc_regmap_read_sync_fail:
0704     if (mlxreg_lc->state & MLXREG_LC_POWERED)
0705         mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
0706                          mlxreg_lc->main_devs_num);
0707 mlxreg_lc_create_static_devices_failed:
0708     mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->aux_devs, mlxreg_lc->aux_devs_num);
0709 mlxreg_lc_regmap_read_power_fail:
0710     return err;
0711 }
0712 
0713 static int
0714 mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,
0715               struct mlxreg_core_data *data)
0716 {
0717     struct device *dev = &data->hpdev.client->dev;
0718     int lsb, err;
0719     u32 regval;
0720 
0721     /* Validate line card type. */
0722     err = regmap_read(regmap, MLXREG_LC_REG_CONFIG_OFFSET, &lsb);
0723     err = (!err) ? regmap_read(regmap, MLXREG_LC_REG_CONFIG_OFFSET, &regval) : err;
0724     if (err)
0725         return err;
0726     regval = (regval & GENMASK(7, 0)) << 8 | (lsb & GENMASK(7, 0));
0727     switch (regval) {
0728     case MLXREG_LC_SN4800_C16:
0729         err = mlxreg_lc_sn4800_c16_config_init(mlxreg_lc, regmap, data);
0730         if (err) {
0731             dev_err(dev, "Failed to config client %s at bus %d at addr 0x%02x\n",
0732                 data->hpdev.brdinfo->type, data->hpdev.nr,
0733                 data->hpdev.brdinfo->addr);
0734             return err;
0735         }
0736         break;
0737     default:
0738         return -ENODEV;
0739     }
0740 
0741     /* Create mux infrastructure. */
0742     mlxreg_lc->mux_data->handle = mlxreg_lc;
0743     mlxreg_lc->mux_data->completion_notify = mlxreg_lc_completion_notify;
0744     mlxreg_lc->mux_brdinfo->platform_data = mlxreg_lc->mux_data;
0745     mlxreg_lc->mux = platform_device_register_resndata(dev, "i2c-mux-mlxcpld", data->hpdev.nr,
0746                                NULL, 0, mlxreg_lc->mux_data,
0747                                sizeof(*mlxreg_lc->mux_data));
0748     if (IS_ERR(mlxreg_lc->mux)) {
0749         dev_err(dev, "Failed to create mux infra for client %s at bus %d at addr 0x%02x\n",
0750             data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
0751         return PTR_ERR(mlxreg_lc->mux);
0752     }
0753 
0754     /* Register IO access driver. */
0755     if (mlxreg_lc->io_data) {
0756         mlxreg_lc->io_data->regmap = regmap;
0757         mlxreg_lc->io_regs =
0758         platform_device_register_resndata(dev, "mlxreg-io", data->hpdev.nr, NULL, 0,
0759                           mlxreg_lc->io_data, sizeof(*mlxreg_lc->io_data));
0760         if (IS_ERR(mlxreg_lc->io_regs)) {
0761             dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n",
0762                 data->hpdev.brdinfo->type, data->hpdev.nr,
0763                 data->hpdev.brdinfo->addr);
0764             err = PTR_ERR(mlxreg_lc->io_regs);
0765             goto fail_register_io;
0766         }
0767     }
0768 
0769     /* Register LED driver. */
0770     if (mlxreg_lc->led_data) {
0771         mlxreg_lc->led_data->regmap = regmap;
0772         mlxreg_lc->led =
0773         platform_device_register_resndata(dev, "leds-mlxreg", data->hpdev.nr, NULL, 0,
0774                           mlxreg_lc->led_data,
0775                           sizeof(*mlxreg_lc->led_data));
0776         if (IS_ERR(mlxreg_lc->led)) {
0777             dev_err(dev, "Failed to create LED objects for client %s at bus %d at addr 0x%02x\n",
0778                 data->hpdev.brdinfo->type, data->hpdev.nr,
0779                 data->hpdev.brdinfo->addr);
0780             err = PTR_ERR(mlxreg_lc->led);
0781             goto fail_register_led;
0782         }
0783     }
0784 
0785     return 0;
0786 
0787 fail_register_led:
0788     if (mlxreg_lc->io_regs)
0789         platform_device_unregister(mlxreg_lc->io_regs);
0790 fail_register_io:
0791     if (mlxreg_lc->mux)
0792         platform_device_unregister(mlxreg_lc->mux);
0793 
0794     return err;
0795 }
0796 
0797 static void mlxreg_lc_config_exit(struct mlxreg_lc *mlxreg_lc)
0798 {
0799     /* Unregister LED driver. */
0800     if (mlxreg_lc->led)
0801         platform_device_unregister(mlxreg_lc->led);
0802     /* Unregister IO access driver. */
0803     if (mlxreg_lc->io_regs)
0804         platform_device_unregister(mlxreg_lc->io_regs);
0805     /* Remove mux infrastructure. */
0806     if (mlxreg_lc->mux)
0807         platform_device_unregister(mlxreg_lc->mux);
0808 }
0809 
0810 static int mlxreg_lc_probe(struct platform_device *pdev)
0811 {
0812     struct mlxreg_core_hotplug_platform_data *par_pdata;
0813     struct mlxreg_core_data *data;
0814     struct mlxreg_lc *mlxreg_lc;
0815     void *regmap;
0816     int i, err;
0817 
0818     data = dev_get_platdata(&pdev->dev);
0819     if (!data)
0820         return -EINVAL;
0821 
0822     mlxreg_lc = devm_kzalloc(&pdev->dev, sizeof(*mlxreg_lc), GFP_KERNEL);
0823     if (!mlxreg_lc)
0824         return -ENOMEM;
0825 
0826     mutex_init(&mlxreg_lc->lock);
0827     /* Set event notification callback. */
0828     data->notifier->user_handler = mlxreg_lc_event_handler;
0829     data->notifier->handle = mlxreg_lc;
0830 
0831     data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
0832     if (!data->hpdev.adapter) {
0833         dev_err(&pdev->dev, "Failed to get adapter for bus %d\n",
0834             data->hpdev.nr);
0835         err = -EFAULT;
0836         goto i2c_get_adapter_fail;
0837     }
0838 
0839     /* Create device at the top of line card I2C tree.*/
0840     data->hpdev.client = i2c_new_client_device(data->hpdev.adapter,
0841                            data->hpdev.brdinfo);
0842     if (IS_ERR(data->hpdev.client)) {
0843         dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
0844             data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
0845         err = PTR_ERR(data->hpdev.client);
0846         goto i2c_new_device_fail;
0847     }
0848 
0849     regmap = devm_regmap_init_i2c(data->hpdev.client,
0850                       &mlxreg_lc_regmap_conf);
0851     if (IS_ERR(regmap)) {
0852         dev_err(&pdev->dev, "Failed to create regmap for client %s at bus %d at addr 0x%02x\n",
0853             data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
0854         err = PTR_ERR(regmap);
0855         goto devm_regmap_init_i2c_fail;
0856     }
0857 
0858     /* Set default registers. */
0859     for (i = 0; i < mlxreg_lc_regmap_conf.num_reg_defaults; i++) {
0860         err = regmap_write(regmap, mlxreg_lc_regmap_default[i].reg,
0861                    mlxreg_lc_regmap_default[i].def);
0862         if (err) {
0863             dev_err(&pdev->dev, "Failed to set default regmap %d for client %s at bus %d at addr 0x%02x\n",
0864                 i, data->hpdev.brdinfo->type, data->hpdev.nr,
0865                 data->hpdev.brdinfo->addr);
0866             goto regmap_write_fail;
0867         }
0868     }
0869 
0870     /* Sync registers with hardware. */
0871     regcache_mark_dirty(regmap);
0872     err = regcache_sync(regmap);
0873     if (err) {
0874         dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n",
0875             data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
0876         goto regcache_sync_fail;
0877     }
0878 
0879     par_pdata = data->hpdev.brdinfo->platform_data;
0880     mlxreg_lc->par_regmap = par_pdata->regmap;
0881     mlxreg_lc->data = data;
0882     mlxreg_lc->dev = &pdev->dev;
0883     platform_set_drvdata(pdev, mlxreg_lc);
0884 
0885     /* Configure line card. */
0886     err = mlxreg_lc_config_init(mlxreg_lc, regmap, data);
0887     if (err)
0888         goto mlxreg_lc_config_init_fail;
0889 
0890     return 0;
0891 
0892 mlxreg_lc_config_init_fail:
0893 regcache_sync_fail:
0894 regmap_write_fail:
0895 devm_regmap_init_i2c_fail:
0896     i2c_unregister_device(data->hpdev.client);
0897     data->hpdev.client = NULL;
0898 i2c_new_device_fail:
0899     i2c_put_adapter(data->hpdev.adapter);
0900     data->hpdev.adapter = NULL;
0901 i2c_get_adapter_fail:
0902     /* Clear event notification callback and handle. */
0903     if (data->notifier) {
0904         data->notifier->user_handler = NULL;
0905         data->notifier->handle = NULL;
0906     }
0907     return err;
0908 }
0909 
0910 static int mlxreg_lc_remove(struct platform_device *pdev)
0911 {
0912     struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
0913     struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev);
0914 
0915     mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 0);
0916 
0917     /*
0918      * Probing and removing are invoked by hotplug events raised upon line card insertion and
0919      * removing. If probing procedure fails all data is cleared. However, hotplug event still
0920      * will be raised on line card removing and activate removing procedure. In this case there
0921      * is nothing to remove.
0922      */
0923     if (!data->notifier || !data->notifier->handle)
0924         return 0;
0925 
0926     /* Clear event notification callback and handle. */
0927     data->notifier->user_handler = NULL;
0928     data->notifier->handle = NULL;
0929 
0930     /* Destroy static I2C device feeding by main power. */
0931     mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
0932                      mlxreg_lc->main_devs_num);
0933     /* Destroy static I2C device feeding by auxiliary power. */
0934     mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->aux_devs, mlxreg_lc->aux_devs_num);
0935     /* Unregister underlying drivers. */
0936     mlxreg_lc_config_exit(mlxreg_lc);
0937     if (data->hpdev.client) {
0938         i2c_unregister_device(data->hpdev.client);
0939         data->hpdev.client = NULL;
0940         i2c_put_adapter(data->hpdev.adapter);
0941         data->hpdev.adapter = NULL;
0942     }
0943 
0944     return 0;
0945 }
0946 
0947 static struct platform_driver mlxreg_lc_driver = {
0948     .probe = mlxreg_lc_probe,
0949     .remove = mlxreg_lc_remove,
0950     .driver = {
0951         .name = "mlxreg-lc",
0952     },
0953 };
0954 
0955 module_platform_driver(mlxreg_lc_driver);
0956 
0957 MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");
0958 MODULE_DESCRIPTION("Nvidia line card platform driver");
0959 MODULE_LICENSE("Dual BSD/GPL");
0960 MODULE_ALIAS("platform:mlxreg-lc");