1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /* 3 * Mellanox platform driver 4 * 5 * Copyright (C) 2016-2018 Mellanox Technologies 6 * Copyright (C) 2016-2018 Vadim Pasternak <vadimp@mellanox.com> 7 */ 8 9 #include <linux/device.h> 10 #include <linux/dmi.h> 11 #include <linux/i2c.h> 12 #include <linux/i2c-mux.h> 13 #include <linux/io.h> 14 #include <linux/module.h> 15 #include <linux/platform_device.h> 16 #include <linux/platform_data/i2c-mux-reg.h> 17 #include <linux/platform_data/mlxreg.h> 18 #include <linux/regmap.h> 19 20 #define MLX_PLAT_DEVICE_NAME "mlxplat" 21 22 /* LPC bus IO offsets */ 23 #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 24 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 25 #define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 26 #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 27 #define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02 28 #define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03 29 #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d 30 #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e 31 #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f 32 #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 33 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 34 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 35 #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23 36 #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24 37 #define MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION 0x2a 38 #define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 39 #define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31 40 #define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32 41 #define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET 0x33 42 #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 43 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a 44 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b 45 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 46 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 47 #define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50 48 #define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51 49 #define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52 50 #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 51 #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59 52 #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a 53 #define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64 54 #define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET 0x65 55 #define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET 0x66 56 #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 57 #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 58 #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a 59 #define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3 60 #define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4 61 #define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5 62 #define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET 0xe6 63 #define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7 64 #define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8 65 #define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9 66 #define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xeb 67 #define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xec 68 #define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xed 69 #define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xee 70 #define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xef 71 #define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xf0 72 #define MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET 0xf5 73 #define MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET 0xf6 74 #define MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET 0xf7 75 #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 76 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb 77 #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda 78 79 #define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL 80 #define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ 81 MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \ 82 MLXPLAT_CPLD_LPC_PIO_OFFSET) 83 #define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ 84 MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \ 85 MLXPLAT_CPLD_LPC_PIO_OFFSET) 86 87 /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */ 88 #define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF 0x04 89 #define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08 90 #define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08 91 #define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40 92 #define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \ 93 MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \ 94 MLXPLAT_CPLD_AGGR_FAN_MASK_DEF) 95 #define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG 0x01 96 #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04 97 #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 98 #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) 99 #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) 100 #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) 101 #define MLXPLAT_CPLD_ASIC_MASK GENMASK(1, 0) 102 #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0) 103 #define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4) 104 #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0) 105 106 /* Default I2C parent bus number */ 107 #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 108 109 /* Maximum number of possible physical buses equipped on system */ 110 #define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16 111 112 /* Number of channels in group */ 113 #define MLXPLAT_CPLD_GRP_CHNL_NUM 8 114 115 /* Start channel numbers */ 116 #define MLXPLAT_CPLD_CH1 2 117 #define MLXPLAT_CPLD_CH2 10 118 119 /* Number of LPC attached MUX platform devices */ 120 #define MLXPLAT_CPLD_LPC_MUX_DEVS 2 121 122 /* Hotplug devices adapter numbers */ 123 #define MLXPLAT_CPLD_NR_NONE -1 124 #define MLXPLAT_CPLD_PSU_DEFAULT_NR 10 125 #define MLXPLAT_CPLD_PSU_MSNXXXX_NR 4 126 #define MLXPLAT_CPLD_FAN1_DEFAULT_NR 11 127 #define MLXPLAT_CPLD_FAN2_DEFAULT_NR 12 128 #define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13 129 #define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14 130 131 /* mlxplat_priv - platform private data 132 * @pdev_i2c - i2c controller platform device 133 * @pdev_mux - array of mux platform devices 134 * @pdev_hotplug - hotplug platform devices 135 * @pdev_led - led platform devices 136 * @pdev_io_regs - register access platform devices 137 * @pdev_fan - FAN platform devices 138 */ 139 struct mlxplat_priv { 140 struct platform_device *pdev_i2c; 141 struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS]; 142 struct platform_device *pdev_hotplug; 143 struct platform_device *pdev_led; 144 struct platform_device *pdev_io_regs; 145 struct platform_device *pdev_fan; 146 }; 147 148 /* Regions for LPC I2C controller and LPC base register space */ 149 static const struct resource mlxplat_lpc_resources[] = { 150 [0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR, 151 MLXPLAT_CPLD_LPC_IO_RANGE, 152 "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO), 153 [1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR, 154 MLXPLAT_CPLD_LPC_IO_RANGE, 155 "mlxplat_cpld_lpc_regs", 156 IORESOURCE_IO), 157 }; 158 159 /* Platform default channels */ 160 static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = { 161 { 162 MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2, 163 MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 + 164 5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7 165 }, 166 { 167 MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2, 168 MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 + 169 5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7 170 }, 171 }; 172 173 /* Platform channels for MSN21xx system family */ 174 static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 175 176 /* Platform mux data */ 177 static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = { 178 { 179 .parent = 1, 180 .base_nr = MLXPLAT_CPLD_CH1, 181 .write_only = 1, 182 .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, 183 .reg_size = 1, 184 .idle_in_use = 1, 185 }, 186 { 187 .parent = 1, 188 .base_nr = MLXPLAT_CPLD_CH2, 189 .write_only = 1, 190 .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, 191 .reg_size = 1, 192 .idle_in_use = 1, 193 }, 194 195 }; 196 197 /* Platform hotplug devices */ 198 static struct i2c_board_info mlxplat_mlxcpld_psu[] = { 199 { 200 I2C_BOARD_INFO("24c02", 0x51), 201 }, 202 { 203 I2C_BOARD_INFO("24c02", 0x50), 204 }, 205 }; 206 207 static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = { 208 { 209 I2C_BOARD_INFO("24c32", 0x51), 210 }, 211 { 212 I2C_BOARD_INFO("24c32", 0x50), 213 }, 214 }; 215 216 static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { 217 { 218 I2C_BOARD_INFO("dps460", 0x59), 219 }, 220 { 221 I2C_BOARD_INFO("dps460", 0x58), 222 }, 223 }; 224 225 static struct i2c_board_info mlxplat_mlxcpld_fan[] = { 226 { 227 I2C_BOARD_INFO("24c32", 0x50), 228 }, 229 { 230 I2C_BOARD_INFO("24c32", 0x50), 231 }, 232 { 233 I2C_BOARD_INFO("24c32", 0x50), 234 }, 235 { 236 I2C_BOARD_INFO("24c32", 0x50), 237 }, 238 }; 239 240 /* Platform hotplug default data */ 241 static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { 242 { 243 .label = "psu1", 244 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 245 .mask = BIT(0), 246 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], 247 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, 248 }, 249 { 250 .label = "psu2", 251 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 252 .mask = BIT(1), 253 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], 254 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, 255 }, 256 }; 257 258 static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = { 259 { 260 .label = "pwr1", 261 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 262 .mask = BIT(0), 263 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], 264 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, 265 }, 266 { 267 .label = "pwr2", 268 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 269 .mask = BIT(1), 270 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], 271 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, 272 }, 273 }; 274 275 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { 276 { 277 .label = "fan1", 278 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 279 .mask = BIT(0), 280 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0], 281 .hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR, 282 }, 283 { 284 .label = "fan2", 285 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 286 .mask = BIT(1), 287 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1], 288 .hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR, 289 }, 290 { 291 .label = "fan3", 292 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 293 .mask = BIT(2), 294 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2], 295 .hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR, 296 }, 297 { 298 .label = "fan4", 299 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 300 .mask = BIT(3), 301 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3], 302 .hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR, 303 }, 304 }; 305 306 static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = { 307 { 308 .label = "asic1", 309 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 310 .mask = MLXPLAT_CPLD_ASIC_MASK, 311 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 312 }, 313 }; 314 315 static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { 316 { 317 .data = mlxplat_mlxcpld_default_psu_items_data, 318 .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, 319 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 320 .mask = MLXPLAT_CPLD_PSU_MASK, 321 .count = ARRAY_SIZE(mlxplat_mlxcpld_psu), 322 .inversed = 1, 323 .health = false, 324 }, 325 { 326 .data = mlxplat_mlxcpld_default_pwr_items_data, 327 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, 328 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 329 .mask = MLXPLAT_CPLD_PWR_MASK, 330 .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), 331 .inversed = 0, 332 .health = false, 333 }, 334 { 335 .data = mlxplat_mlxcpld_default_fan_items_data, 336 .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF, 337 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 338 .mask = MLXPLAT_CPLD_FAN_MASK, 339 .count = ARRAY_SIZE(mlxplat_mlxcpld_fan), 340 .inversed = 1, 341 .health = false, 342 }, 343 { 344 .data = mlxplat_mlxcpld_default_asic_items_data, 345 .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, 346 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 347 .mask = MLXPLAT_CPLD_ASIC_MASK, 348 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 349 .inversed = 0, 350 .health = true, 351 }, 352 }; 353 354 static 355 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = { 356 .items = mlxplat_mlxcpld_default_items, 357 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items), 358 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, 359 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, 360 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, 361 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, 362 }; 363 364 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = { 365 { 366 .label = "pwr1", 367 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 368 .mask = BIT(0), 369 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 370 }, 371 { 372 .label = "pwr2", 373 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 374 .mask = BIT(1), 375 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 376 }, 377 }; 378 379 /* Platform hotplug MSN21xx system family data */ 380 static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = { 381 { 382 .data = mlxplat_mlxcpld_msn21xx_pwr_items_data, 383 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, 384 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 385 .mask = MLXPLAT_CPLD_PWR_MASK, 386 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data), 387 .inversed = 0, 388 .health = false, 389 }, 390 { 391 .data = mlxplat_mlxcpld_default_asic_items_data, 392 .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, 393 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 394 .mask = MLXPLAT_CPLD_ASIC_MASK, 395 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 396 .inversed = 0, 397 .health = true, 398 }, 399 }; 400 401 static 402 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { 403 .items = mlxplat_mlxcpld_msn21xx_items, 404 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items), 405 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, 406 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, 407 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, 408 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, 409 }; 410 411 /* Platform hotplug msn274x system family data */ 412 static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = { 413 { 414 .label = "psu1", 415 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 416 .mask = BIT(0), 417 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], 418 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, 419 }, 420 { 421 .label = "psu2", 422 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 423 .mask = BIT(1), 424 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], 425 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, 426 }, 427 }; 428 429 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = { 430 { 431 .label = "pwr1", 432 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 433 .mask = BIT(0), 434 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], 435 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, 436 }, 437 { 438 .label = "pwr2", 439 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 440 .mask = BIT(1), 441 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], 442 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, 443 }, 444 }; 445 446 static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = { 447 { 448 .label = "fan1", 449 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 450 .mask = BIT(0), 451 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 452 }, 453 { 454 .label = "fan2", 455 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 456 .mask = BIT(1), 457 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 458 }, 459 { 460 .label = "fan3", 461 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 462 .mask = BIT(2), 463 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 464 }, 465 { 466 .label = "fan4", 467 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 468 .mask = BIT(3), 469 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 470 }, 471 }; 472 473 static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = { 474 { 475 .data = mlxplat_mlxcpld_msn274x_psu_items_data, 476 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 477 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 478 .mask = MLXPLAT_CPLD_PSU_MASK, 479 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data), 480 .inversed = 1, 481 .health = false, 482 }, 483 { 484 .data = mlxplat_mlxcpld_default_ng_pwr_items_data, 485 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 486 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 487 .mask = MLXPLAT_CPLD_PWR_MASK, 488 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data), 489 .inversed = 0, 490 .health = false, 491 }, 492 { 493 .data = mlxplat_mlxcpld_msn274x_fan_items_data, 494 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 495 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 496 .mask = MLXPLAT_CPLD_FAN_MASK, 497 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data), 498 .inversed = 1, 499 .health = false, 500 }, 501 { 502 .data = mlxplat_mlxcpld_default_asic_items_data, 503 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 504 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 505 .mask = MLXPLAT_CPLD_ASIC_MASK, 506 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 507 .inversed = 0, 508 .health = true, 509 }, 510 }; 511 512 static 513 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = { 514 .items = mlxplat_mlxcpld_msn274x_items, 515 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items), 516 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, 517 .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 518 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, 519 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, 520 }; 521 522 /* Platform hotplug MSN201x system family data */ 523 static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = { 524 { 525 .label = "pwr1", 526 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 527 .mask = BIT(0), 528 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 529 }, 530 { 531 .label = "pwr2", 532 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 533 .mask = BIT(1), 534 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 535 }, 536 }; 537 538 static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = { 539 { 540 .data = mlxplat_mlxcpld_msn201x_pwr_items_data, 541 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, 542 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 543 .mask = MLXPLAT_CPLD_PWR_MASK, 544 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data), 545 .inversed = 0, 546 .health = false, 547 }, 548 { 549 .data = mlxplat_mlxcpld_default_asic_items_data, 550 .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, 551 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 552 .mask = MLXPLAT_CPLD_ASIC_MASK, 553 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 554 .inversed = 0, 555 .health = true, 556 }, 557 }; 558 559 static 560 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = { 561 .items = mlxplat_mlxcpld_msn201x_items, 562 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items), 563 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, 564 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, 565 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, 566 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, 567 }; 568 569 /* Platform hotplug next generation system family data */ 570 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = { 571 { 572 .label = "psu1", 573 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 574 .mask = BIT(0), 575 .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0], 576 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, 577 }, 578 { 579 .label = "psu2", 580 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 581 .mask = BIT(1), 582 .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1], 583 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, 584 }, 585 }; 586 587 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = { 588 { 589 .label = "fan1", 590 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 591 .mask = BIT(0), 592 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 593 .bit = BIT(0), 594 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 595 }, 596 { 597 .label = "fan2", 598 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 599 .mask = BIT(1), 600 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 601 .bit = BIT(1), 602 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 603 }, 604 { 605 .label = "fan3", 606 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 607 .mask = BIT(2), 608 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 609 .bit = BIT(2), 610 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 611 }, 612 { 613 .label = "fan4", 614 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 615 .mask = BIT(3), 616 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 617 .bit = BIT(3), 618 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 619 }, 620 { 621 .label = "fan5", 622 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 623 .mask = BIT(4), 624 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 625 .bit = BIT(4), 626 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 627 }, 628 { 629 .label = "fan6", 630 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 631 .mask = BIT(5), 632 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 633 .bit = BIT(5), 634 .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 635 }, 636 }; 637 638 static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = { 639 { 640 .data = mlxplat_mlxcpld_default_ng_psu_items_data, 641 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 642 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, 643 .mask = MLXPLAT_CPLD_PSU_MASK, 644 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data), 645 .inversed = 1, 646 .health = false, 647 }, 648 { 649 .data = mlxplat_mlxcpld_default_ng_pwr_items_data, 650 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 651 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, 652 .mask = MLXPLAT_CPLD_PWR_MASK, 653 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data), 654 .inversed = 0, 655 .health = false, 656 }, 657 { 658 .data = mlxplat_mlxcpld_default_ng_fan_items_data, 659 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 660 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, 661 .mask = MLXPLAT_CPLD_FAN_NG_MASK, 662 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), 663 .inversed = 1, 664 .health = false, 665 }, 666 { 667 .data = mlxplat_mlxcpld_default_asic_items_data, 668 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 669 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 670 .mask = MLXPLAT_CPLD_ASIC_MASK, 671 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 672 .inversed = 0, 673 .health = true, 674 }, 675 }; 676 677 static 678 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = { 679 .items = mlxplat_mlxcpld_default_ng_items, 680 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items), 681 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, 682 .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 683 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, 684 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, 685 }; 686 687 /* Platform led default data */ 688 static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = { 689 { 690 .label = "status:green", 691 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 692 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 693 }, 694 { 695 .label = "status:red", 696 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 697 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK 698 }, 699 { 700 .label = "psu:green", 701 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 702 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 703 }, 704 { 705 .label = "psu:red", 706 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 707 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 708 }, 709 { 710 .label = "fan1:green", 711 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 712 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 713 }, 714 { 715 .label = "fan1:red", 716 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 717 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 718 }, 719 { 720 .label = "fan2:green", 721 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 722 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 723 }, 724 { 725 .label = "fan2:red", 726 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 727 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 728 }, 729 { 730 .label = "fan3:green", 731 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 732 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 733 }, 734 { 735 .label = "fan3:red", 736 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 737 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 738 }, 739 { 740 .label = "fan4:green", 741 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 742 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 743 }, 744 { 745 .label = "fan4:red", 746 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 747 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 748 }, 749 }; 750 751 static struct mlxreg_core_platform_data mlxplat_default_led_data = { 752 .data = mlxplat_mlxcpld_default_led_data, 753 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data), 754 }; 755 756 /* Platform led MSN21xx system family data */ 757 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = { 758 { 759 .label = "status:green", 760 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 761 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 762 }, 763 { 764 .label = "status:red", 765 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 766 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK 767 }, 768 { 769 .label = "fan:green", 770 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 771 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 772 }, 773 { 774 .label = "fan:red", 775 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 776 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 777 }, 778 { 779 .label = "psu1:green", 780 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 781 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 782 }, 783 { 784 .label = "psu1:red", 785 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 786 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 787 }, 788 { 789 .label = "psu2:green", 790 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 791 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 792 }, 793 { 794 .label = "psu2:red", 795 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 796 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 797 }, 798 { 799 .label = "uid:blue", 800 .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, 801 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 802 }, 803 }; 804 805 static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = { 806 .data = mlxplat_mlxcpld_msn21xx_led_data, 807 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data), 808 }; 809 810 /* Platform led for default data for 200GbE systems */ 811 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = { 812 { 813 .label = "status:green", 814 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 815 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 816 }, 817 { 818 .label = "status:orange", 819 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 820 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK 821 }, 822 { 823 .label = "psu:green", 824 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 825 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 826 }, 827 { 828 .label = "psu:orange", 829 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, 830 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 831 }, 832 { 833 .label = "fan1:green", 834 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 835 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 836 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 837 .bit = BIT(0), 838 }, 839 { 840 .label = "fan1:orange", 841 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 842 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 843 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 844 .bit = BIT(0), 845 }, 846 { 847 .label = "fan2:green", 848 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 849 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 850 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 851 .bit = BIT(1), 852 }, 853 { 854 .label = "fan2:orange", 855 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, 856 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 857 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 858 .bit = BIT(1), 859 }, 860 { 861 .label = "fan3:green", 862 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 863 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 864 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 865 .bit = BIT(2), 866 }, 867 { 868 .label = "fan3:orange", 869 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 870 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 871 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 872 .bit = BIT(2), 873 }, 874 { 875 .label = "fan4:green", 876 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 877 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 878 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 879 .bit = BIT(3), 880 }, 881 { 882 .label = "fan4:orange", 883 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, 884 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 885 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 886 .bit = BIT(3), 887 }, 888 { 889 .label = "fan5:green", 890 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 891 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 892 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 893 .bit = BIT(4), 894 }, 895 { 896 .label = "fan5:orange", 897 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 898 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 899 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 900 .bit = BIT(4), 901 }, 902 { 903 .label = "fan6:green", 904 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 905 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 906 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 907 .bit = BIT(5), 908 }, 909 { 910 .label = "fan6:orange", 911 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, 912 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, 913 .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, 914 .bit = BIT(5), 915 }, 916 { 917 .label = "uid:blue", 918 .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, 919 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, 920 }, 921 }; 922 923 static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = { 924 .data = mlxplat_mlxcpld_default_ng_led_data, 925 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data), 926 }; 927 928 /* Platform register access default */ 929 static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { 930 { 931 .label = "cpld1_version", 932 .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, 933 .bit = GENMASK(7, 0), 934 .mode = 0444, 935 }, 936 { 937 .label = "cpld2_version", 938 .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, 939 .bit = GENMASK(7, 0), 940 .mode = 0444, 941 }, 942 { 943 .label = "reset_long_pb", 944 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 945 .mask = GENMASK(7, 0) & ~BIT(0), 946 .mode = 0444, 947 }, 948 { 949 .label = "reset_short_pb", 950 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 951 .mask = GENMASK(7, 0) & ~BIT(1), 952 .mode = 0444, 953 }, 954 { 955 .label = "reset_aux_pwr_or_ref", 956 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 957 .mask = GENMASK(7, 0) & ~BIT(2), 958 .mode = 0444, 959 }, 960 { 961 .label = "reset_main_pwr_fail", 962 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 963 .mask = GENMASK(7, 0) & ~BIT(3), 964 .mode = 0444, 965 }, 966 { 967 .label = "reset_sw_reset", 968 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 969 .mask = GENMASK(7, 0) & ~BIT(4), 970 .mode = 0444, 971 }, 972 { 973 .label = "reset_fw_reset", 974 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 975 .mask = GENMASK(7, 0) & ~BIT(5), 976 .mode = 0444, 977 }, 978 { 979 .label = "reset_hotswap_or_wd", 980 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 981 .mask = GENMASK(7, 0) & ~BIT(6), 982 .mode = 0444, 983 }, 984 { 985 .label = "reset_asic_thermal", 986 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 987 .mask = GENMASK(7, 0) & ~BIT(7), 988 .mode = 0444, 989 }, 990 { 991 .label = "psu1_on", 992 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 993 .mask = GENMASK(7, 0) & ~BIT(0), 994 .mode = 0200, 995 }, 996 { 997 .label = "psu2_on", 998 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 999 .mask = GENMASK(7, 0) & ~BIT(1), 1000 .mode = 0200, 1001 }, 1002 { 1003 .label = "pwr_cycle", 1004 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1005 .mask = GENMASK(7, 0) & ~BIT(2), 1006 .mode = 0200, 1007 }, 1008 { 1009 .label = "pwr_down", 1010 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1011 .mask = GENMASK(7, 0) & ~BIT(3), 1012 .mode = 0200, 1013 }, 1014 { 1015 .label = "select_iio", 1016 .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 1017 .mask = GENMASK(7, 0) & ~BIT(6), 1018 .mode = 0644, 1019 }, 1020 { 1021 .label = "asic_health", 1022 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 1023 .mask = MLXPLAT_CPLD_ASIC_MASK, 1024 .bit = 1, 1025 .mode = 0444, 1026 }, 1027 }; 1028 1029 static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = { 1030 .data = mlxplat_mlxcpld_default_regs_io_data, 1031 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data), 1032 }; 1033 1034 /* Platform register access MSN21xx, MSN201x, MSN274x systems families data */ 1035 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = { 1036 { 1037 .label = "cpld1_version", 1038 .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, 1039 .bit = GENMASK(7, 0), 1040 .mode = 0444, 1041 }, 1042 { 1043 .label = "cpld2_version", 1044 .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, 1045 .bit = GENMASK(7, 0), 1046 .mode = 0444, 1047 }, 1048 { 1049 .label = "reset_long_pb", 1050 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1051 .mask = GENMASK(7, 0) & ~BIT(0), 1052 .mode = 0444, 1053 }, 1054 { 1055 .label = "reset_short_pb", 1056 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1057 .mask = GENMASK(7, 0) & ~BIT(1), 1058 .mode = 0444, 1059 }, 1060 { 1061 .label = "reset_aux_pwr_or_ref", 1062 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1063 .mask = GENMASK(7, 0) & ~BIT(2), 1064 .mode = 0444, 1065 }, 1066 { 1067 .label = "reset_sw_reset", 1068 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1069 .mask = GENMASK(7, 0) & ~BIT(3), 1070 .mode = 0444, 1071 }, 1072 { 1073 .label = "reset_main_pwr_fail", 1074 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1075 .mask = GENMASK(7, 0) & ~BIT(4), 1076 .mode = 0444, 1077 }, 1078 { 1079 .label = "reset_asic_thermal", 1080 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1081 .mask = GENMASK(7, 0) & ~BIT(5), 1082 .mode = 0444, 1083 }, 1084 { 1085 .label = "reset_hotswap_or_halt", 1086 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1087 .mask = GENMASK(7, 0) & ~BIT(6), 1088 .mode = 0444, 1089 }, 1090 { 1091 .label = "psu1_on", 1092 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1093 .mask = GENMASK(7, 0) & ~BIT(0), 1094 .mode = 0200, 1095 }, 1096 { 1097 .label = "psu2_on", 1098 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1099 .mask = GENMASK(7, 0) & ~BIT(1), 1100 .mode = 0200, 1101 }, 1102 { 1103 .label = "pwr_cycle", 1104 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1105 .mask = GENMASK(7, 0) & ~BIT(2), 1106 .mode = 0200, 1107 }, 1108 { 1109 .label = "pwr_down", 1110 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1111 .mask = GENMASK(7, 0) & ~BIT(3), 1112 .mode = 0200, 1113 }, 1114 { 1115 .label = "asic_health", 1116 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 1117 .mask = MLXPLAT_CPLD_ASIC_MASK, 1118 .bit = 1, 1119 .mode = 0444, 1120 }, 1121 }; 1122 1123 static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = { 1124 .data = mlxplat_mlxcpld_msn21xx_regs_io_data, 1125 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data), 1126 }; 1127 1128 /* Platform register access for next generation systems families data */ 1129 static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { 1130 { 1131 .label = "cpld1_version", 1132 .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, 1133 .bit = GENMASK(7, 0), 1134 .mode = 0444, 1135 }, 1136 { 1137 .label = "cpld2_version", 1138 .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, 1139 .bit = GENMASK(7, 0), 1140 .mode = 0444, 1141 }, 1142 { 1143 .label = "cpld3_version", 1144 .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET, 1145 .bit = GENMASK(7, 0), 1146 .mode = 0444, 1147 }, 1148 { 1149 .label = "cpld4_version", 1150 .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET, 1151 .bit = GENMASK(7, 0), 1152 .mode = 0444, 1153 }, 1154 { 1155 .label = "reset_long_pb", 1156 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1157 .mask = GENMASK(7, 0) & ~BIT(0), 1158 .mode = 0444, 1159 }, 1160 { 1161 .label = "reset_short_pb", 1162 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1163 .mask = GENMASK(7, 0) & ~BIT(1), 1164 .mode = 0444, 1165 }, 1166 { 1167 .label = "reset_aux_pwr_or_ref", 1168 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1169 .mask = GENMASK(7, 0) & ~BIT(2), 1170 .mode = 0444, 1171 }, 1172 { 1173 .label = "reset_from_comex", 1174 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1175 .mask = GENMASK(7, 0) & ~BIT(4), 1176 .mode = 0444, 1177 }, 1178 { 1179 .label = "reset_asic_thermal", 1180 .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 1181 .mask = GENMASK(7, 0) & ~BIT(7), 1182 .mode = 0444, 1183 }, 1184 { 1185 .label = "reset_comex_pwr_fail", 1186 .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, 1187 .mask = GENMASK(7, 0) & ~BIT(3), 1188 .mode = 0444, 1189 }, 1190 { 1191 .label = "reset_voltmon_upgrade_fail", 1192 .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, 1193 .mask = GENMASK(7, 0) & ~BIT(0), 1194 .mode = 0444, 1195 }, 1196 { 1197 .label = "reset_system", 1198 .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, 1199 .mask = GENMASK(7, 0) & ~BIT(1), 1200 .mode = 0444, 1201 }, 1202 { 1203 .label = "psu1_on", 1204 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1205 .mask = GENMASK(7, 0) & ~BIT(0), 1206 .mode = 0200, 1207 }, 1208 { 1209 .label = "psu2_on", 1210 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1211 .mask = GENMASK(7, 0) & ~BIT(1), 1212 .mode = 0200, 1213 }, 1214 { 1215 .label = "pwr_cycle", 1216 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1217 .mask = GENMASK(7, 0) & ~BIT(2), 1218 .mode = 0200, 1219 }, 1220 { 1221 .label = "pwr_down", 1222 .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 1223 .mask = GENMASK(7, 0) & ~BIT(3), 1224 .mode = 0200, 1225 }, 1226 { 1227 .label = "jtag_enable", 1228 .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 1229 .mask = GENMASK(7, 0) & ~BIT(4), 1230 .mode = 0644, 1231 }, 1232 { 1233 .label = "asic_health", 1234 .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 1235 .mask = MLXPLAT_CPLD_ASIC_MASK, 1236 .bit = 1, 1237 .mode = 0444, 1238 }, 1239 { 1240 .label = "fan_dir", 1241 .reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION, 1242 .bit = GENMASK(7, 0), 1243 .mode = 0444, 1244 }, 1245 }; 1246 1247 static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = { 1248 .data = mlxplat_mlxcpld_default_ng_regs_io_data, 1249 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_regs_io_data), 1250 }; 1251 1252 /* Platform FAN default */ 1253 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { 1254 { 1255 .label = "pwm1", 1256 .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET, 1257 }, 1258 { 1259 .label = "tacho1", 1260 .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET, 1261 .mask = GENMASK(7, 0), 1262 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1263 .bit = BIT(0), 1264 }, 1265 { 1266 .label = "tacho2", 1267 .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET, 1268 .mask = GENMASK(7, 0), 1269 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1270 .bit = BIT(1), 1271 }, 1272 { 1273 .label = "tacho3", 1274 .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET, 1275 .mask = GENMASK(7, 0), 1276 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1277 .bit = BIT(2), 1278 }, 1279 { 1280 .label = "tacho4", 1281 .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET, 1282 .mask = GENMASK(7, 0), 1283 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1284 .bit = BIT(3), 1285 }, 1286 { 1287 .label = "tacho5", 1288 .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET, 1289 .mask = GENMASK(7, 0), 1290 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1291 .bit = BIT(4), 1292 }, 1293 { 1294 .label = "tacho6", 1295 .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET, 1296 .mask = GENMASK(7, 0), 1297 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1298 .bit = BIT(5), 1299 }, 1300 { 1301 .label = "tacho7", 1302 .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET, 1303 .mask = GENMASK(7, 0), 1304 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1305 .bit = BIT(6), 1306 }, 1307 { 1308 .label = "tacho8", 1309 .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET, 1310 .mask = GENMASK(7, 0), 1311 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, 1312 .bit = BIT(7), 1313 }, 1314 { 1315 .label = "tacho9", 1316 .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET, 1317 .mask = GENMASK(7, 0), 1318 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, 1319 .bit = BIT(0), 1320 }, 1321 { 1322 .label = "tacho10", 1323 .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET, 1324 .mask = GENMASK(7, 0), 1325 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, 1326 .bit = BIT(1), 1327 }, 1328 { 1329 .label = "tacho11", 1330 .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET, 1331 .mask = GENMASK(7, 0), 1332 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, 1333 .bit = BIT(2), 1334 }, 1335 { 1336 .label = "tacho12", 1337 .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET, 1338 .mask = GENMASK(7, 0), 1339 .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, 1340 .bit = BIT(3), 1341 }, 1342 }; 1343 1344 static struct mlxreg_core_platform_data mlxplat_default_fan_data = { 1345 .data = mlxplat_mlxcpld_default_fan_data, 1346 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data), 1347 }; 1348 1349 static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) 1350 { 1351 switch (reg) { 1352 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: 1353 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: 1354 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: 1355 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: 1356 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: 1357 case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: 1358 case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: 1359 case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: 1360 case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: 1361 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: 1362 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: 1363 case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: 1364 case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: 1365 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: 1366 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: 1367 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: 1368 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: 1369 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: 1370 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: 1371 case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: 1372 case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: 1373 return true; 1374 } 1375 return false; 1376 } 1377 1378 static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) 1379 { 1380 switch (reg) { 1381 case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: 1382 case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: 1383 case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: 1384 case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: 1385 case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: 1386 case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: 1387 case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: 1388 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: 1389 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: 1390 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: 1391 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: 1392 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: 1393 case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION: 1394 case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: 1395 case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: 1396 case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: 1397 case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: 1398 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: 1399 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: 1400 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: 1401 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: 1402 case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: 1403 case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: 1404 case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: 1405 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: 1406 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: 1407 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: 1408 case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: 1409 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: 1410 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: 1411 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: 1412 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: 1413 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: 1414 case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: 1415 case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: 1416 case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: 1417 case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: 1418 case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: 1419 case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: 1420 case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: 1421 case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: 1422 case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: 1423 case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: 1424 case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: 1425 case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: 1426 case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: 1427 case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: 1428 case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET: 1429 case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET: 1430 case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET: 1431 return true; 1432 } 1433 return false; 1434 } 1435 1436 static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) 1437 { 1438 switch (reg) { 1439 case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: 1440 case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: 1441 case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: 1442 case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: 1443 case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: 1444 case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: 1445 case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: 1446 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: 1447 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: 1448 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: 1449 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: 1450 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: 1451 case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION: 1452 case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: 1453 case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: 1454 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: 1455 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: 1456 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: 1457 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: 1458 case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: 1459 case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: 1460 case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: 1461 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: 1462 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: 1463 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: 1464 case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: 1465 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: 1466 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: 1467 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: 1468 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: 1469 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: 1470 case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: 1471 case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: 1472 case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: 1473 case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: 1474 case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: 1475 case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: 1476 case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: 1477 case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: 1478 case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: 1479 case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: 1480 case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: 1481 case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: 1482 case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: 1483 case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: 1484 case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET: 1485 case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET: 1486 case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET: 1487 return true; 1488 } 1489 return false; 1490 } 1491 1492 static const struct reg_default mlxplat_mlxcpld_regmap_default[] = { 1493 { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 }, 1494 { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 }, 1495 { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, 1496 }; 1497 1498 struct mlxplat_mlxcpld_regmap_context { 1499 void __iomem *base; 1500 }; 1501 1502 static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx; 1503 1504 static int 1505 mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val) 1506 { 1507 struct mlxplat_mlxcpld_regmap_context *ctx = context; 1508 1509 *val = ioread8(ctx->base + reg); 1510 return 0; 1511 } 1512 1513 static int 1514 mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val) 1515 { 1516 struct mlxplat_mlxcpld_regmap_context *ctx = context; 1517 1518 iowrite8(val, ctx->base + reg); 1519 return 0; 1520 } 1521 1522 static const struct regmap_config mlxplat_mlxcpld_regmap_config = { 1523 .reg_bits = 8, 1524 .val_bits = 8, 1525 .max_register = 255, 1526 .cache_type = REGCACHE_FLAT, 1527 .writeable_reg = mlxplat_mlxcpld_writeable_reg, 1528 .readable_reg = mlxplat_mlxcpld_readable_reg, 1529 .volatile_reg = mlxplat_mlxcpld_volatile_reg, 1530 .reg_defaults = mlxplat_mlxcpld_regmap_default, 1531 .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default), 1532 .reg_read = mlxplat_mlxcpld_reg_read, 1533 .reg_write = mlxplat_mlxcpld_reg_write, 1534 }; 1535 1536 static struct resource mlxplat_mlxcpld_resources[] = { 1537 [0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"), 1538 }; 1539 1540 static struct platform_device *mlxplat_dev; 1541 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; 1542 static struct mlxreg_core_platform_data *mlxplat_led; 1543 static struct mlxreg_core_platform_data *mlxplat_regs_io; 1544 static struct mlxreg_core_platform_data *mlxplat_fan; 1545 1546 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) 1547 { 1548 int i; 1549 1550 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1551 mlxplat_mux_data[i].values = mlxplat_default_channels[i]; 1552 mlxplat_mux_data[i].n_values = 1553 ARRAY_SIZE(mlxplat_default_channels[i]); 1554 } 1555 mlxplat_hotplug = &mlxplat_mlxcpld_default_data; 1556 mlxplat_hotplug->deferred_nr = 1557 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1558 mlxplat_led = &mlxplat_default_led_data; 1559 mlxplat_regs_io = &mlxplat_default_regs_io_data; 1560 1561 return 1; 1562 }; 1563 1564 static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) 1565 { 1566 int i; 1567 1568 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1569 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; 1570 mlxplat_mux_data[i].n_values = 1571 ARRAY_SIZE(mlxplat_msn21xx_channels); 1572 } 1573 mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data; 1574 mlxplat_hotplug->deferred_nr = 1575 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1576 mlxplat_led = &mlxplat_msn21xx_led_data; 1577 mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; 1578 1579 return 1; 1580 }; 1581 1582 static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) 1583 { 1584 int i; 1585 1586 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1587 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; 1588 mlxplat_mux_data[i].n_values = 1589 ARRAY_SIZE(mlxplat_msn21xx_channels); 1590 } 1591 mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data; 1592 mlxplat_hotplug->deferred_nr = 1593 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1594 mlxplat_led = &mlxplat_default_led_data; 1595 mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; 1596 1597 return 1; 1598 }; 1599 1600 static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) 1601 { 1602 int i; 1603 1604 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1605 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; 1606 mlxplat_mux_data[i].n_values = 1607 ARRAY_SIZE(mlxplat_msn21xx_channels); 1608 } 1609 mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; 1610 mlxplat_hotplug->deferred_nr = 1611 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1612 mlxplat_led = &mlxplat_msn21xx_led_data; 1613 mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; 1614 1615 return 1; 1616 }; 1617 1618 static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) 1619 { 1620 int i; 1621 1622 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1623 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; 1624 mlxplat_mux_data[i].n_values = 1625 ARRAY_SIZE(mlxplat_msn21xx_channels); 1626 } 1627 mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; 1628 mlxplat_hotplug->deferred_nr = 1629 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1630 mlxplat_led = &mlxplat_default_ng_led_data; 1631 mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; 1632 mlxplat_fan = &mlxplat_default_fan_data; 1633 1634 return 1; 1635 }; 1636 1637 static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { 1638 { 1639 .callback = mlxplat_dmi_msn274x_matched, 1640 .matches = { 1641 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1642 DMI_MATCH(DMI_PRODUCT_NAME, "MSN274"), 1643 }, 1644 }, 1645 { 1646 .callback = mlxplat_dmi_default_matched, 1647 .matches = { 1648 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1649 DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"), 1650 }, 1651 }, 1652 { 1653 .callback = mlxplat_dmi_default_matched, 1654 .matches = { 1655 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1656 DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"), 1657 }, 1658 }, 1659 { 1660 .callback = mlxplat_dmi_default_matched, 1661 .matches = { 1662 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1663 DMI_MATCH(DMI_PRODUCT_NAME, "MSB"), 1664 }, 1665 }, 1666 { 1667 .callback = mlxplat_dmi_default_matched, 1668 .matches = { 1669 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1670 DMI_MATCH(DMI_PRODUCT_NAME, "MSX"), 1671 }, 1672 }, 1673 { 1674 .callback = mlxplat_dmi_msn21xx_matched, 1675 .matches = { 1676 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1677 DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"), 1678 }, 1679 }, 1680 { 1681 .callback = mlxplat_dmi_msn201x_matched, 1682 .matches = { 1683 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1684 DMI_MATCH(DMI_PRODUCT_NAME, "MSN201"), 1685 }, 1686 }, 1687 { 1688 .callback = mlxplat_dmi_qmb7xx_matched, 1689 .matches = { 1690 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1691 DMI_MATCH(DMI_PRODUCT_NAME, "MQM87"), 1692 }, 1693 }, 1694 { 1695 .callback = mlxplat_dmi_qmb7xx_matched, 1696 .matches = { 1697 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1698 DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"), 1699 }, 1700 }, 1701 { 1702 .callback = mlxplat_dmi_qmb7xx_matched, 1703 .matches = { 1704 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1705 DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"), 1706 }, 1707 }, 1708 { 1709 .callback = mlxplat_dmi_qmb7xx_matched, 1710 .matches = { 1711 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), 1712 DMI_MATCH(DMI_PRODUCT_NAME, "MSN38"), 1713 }, 1714 }, 1715 { 1716 .callback = mlxplat_dmi_default_matched, 1717 .matches = { 1718 DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"), 1719 }, 1720 }, 1721 { 1722 .callback = mlxplat_dmi_msn21xx_matched, 1723 .matches = { 1724 DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"), 1725 }, 1726 }, 1727 { 1728 .callback = mlxplat_dmi_msn274x_matched, 1729 .matches = { 1730 DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"), 1731 }, 1732 }, 1733 { 1734 .callback = mlxplat_dmi_msn201x_matched, 1735 .matches = { 1736 DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"), 1737 }, 1738 }, 1739 { 1740 .callback = mlxplat_dmi_qmb7xx_matched, 1741 .matches = { 1742 DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"), 1743 }, 1744 }, 1745 { 1746 .callback = mlxplat_dmi_qmb7xx_matched, 1747 .matches = { 1748 DMI_MATCH(DMI_BOARD_NAME, "VMOD0007"), 1749 }, 1750 }, 1751 { } 1752 }; 1753 1754 MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table); 1755 1756 static int mlxplat_mlxcpld_verify_bus_topology(int *nr) 1757 { 1758 struct i2c_adapter *search_adap; 1759 int shift, i; 1760 1761 /* Scan adapters from expected id to verify it is free. */ 1762 *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; 1763 for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i < 1764 MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) { 1765 search_adap = i2c_get_adapter(i); 1766 if (search_adap) { 1767 i2c_put_adapter(search_adap); 1768 continue; 1769 } 1770 1771 /* Return if expected parent adapter is free. */ 1772 if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR) 1773 return 0; 1774 break; 1775 } 1776 1777 /* Return with error if free id for adapter is not found. */ 1778 if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) 1779 return -ENODEV; 1780 1781 /* Shift adapter ids, since expected parent adapter is not free. */ 1782 *nr = i; 1783 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1784 shift = *nr - mlxplat_mux_data[i].parent; 1785 mlxplat_mux_data[i].parent = *nr; 1786 mlxplat_mux_data[i].base_nr += shift; 1787 if (shift > 0) 1788 mlxplat_hotplug->shift_nr = shift; 1789 } 1790 1791 return 0; 1792 } 1793 1794 static int __init mlxplat_init(void) 1795 { 1796 struct mlxplat_priv *priv; 1797 int i, j, nr, err; 1798 1799 if (!dmi_check_system(mlxplat_dmi_table)) 1800 return -ENODEV; 1801 1802 mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1, 1803 mlxplat_lpc_resources, 1804 ARRAY_SIZE(mlxplat_lpc_resources)); 1805 1806 if (IS_ERR(mlxplat_dev)) 1807 return PTR_ERR(mlxplat_dev); 1808 1809 priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv), 1810 GFP_KERNEL); 1811 if (!priv) { 1812 err = -ENOMEM; 1813 goto fail_alloc; 1814 } 1815 platform_set_drvdata(mlxplat_dev, priv); 1816 1817 err = mlxplat_mlxcpld_verify_bus_topology(&nr); 1818 if (nr < 0) 1819 goto fail_alloc; 1820 1821 nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr; 1822 priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr, 1823 NULL, 0); 1824 if (IS_ERR(priv->pdev_i2c)) { 1825 err = PTR_ERR(priv->pdev_i2c); 1826 goto fail_alloc; 1827 } 1828 1829 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) { 1830 priv->pdev_mux[i] = platform_device_register_resndata( 1831 &mlxplat_dev->dev, 1832 "i2c-mux-reg", i, NULL, 1833 0, &mlxplat_mux_data[i], 1834 sizeof(mlxplat_mux_data[i])); 1835 if (IS_ERR(priv->pdev_mux[i])) { 1836 err = PTR_ERR(priv->pdev_mux[i]); 1837 goto fail_platform_mux_register; 1838 } 1839 } 1840 1841 mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev, 1842 mlxplat_lpc_resources[1].start, 1); 1843 if (!mlxplat_mlxcpld_regmap_ctx.base) { 1844 err = -ENOMEM; 1845 goto fail_platform_mux_register; 1846 } 1847 1848 mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL, 1849 &mlxplat_mlxcpld_regmap_ctx, 1850 &mlxplat_mlxcpld_regmap_config); 1851 if (IS_ERR(mlxplat_hotplug->regmap)) { 1852 err = PTR_ERR(mlxplat_hotplug->regmap); 1853 goto fail_platform_mux_register; 1854 } 1855 1856 priv->pdev_hotplug = platform_device_register_resndata( 1857 &mlxplat_dev->dev, "mlxreg-hotplug", 1858 PLATFORM_DEVID_NONE, 1859 mlxplat_mlxcpld_resources, 1860 ARRAY_SIZE(mlxplat_mlxcpld_resources), 1861 mlxplat_hotplug, sizeof(*mlxplat_hotplug)); 1862 if (IS_ERR(priv->pdev_hotplug)) { 1863 err = PTR_ERR(priv->pdev_hotplug); 1864 goto fail_platform_mux_register; 1865 } 1866 1867 /* Set default registers. */ 1868 for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) { 1869 err = regmap_write(mlxplat_hotplug->regmap, 1870 mlxplat_mlxcpld_regmap_default[j].reg, 1871 mlxplat_mlxcpld_regmap_default[j].def); 1872 if (err) 1873 goto fail_platform_mux_register; 1874 } 1875 1876 /* Add LED driver. */ 1877 mlxplat_led->regmap = mlxplat_hotplug->regmap; 1878 priv->pdev_led = platform_device_register_resndata( 1879 &mlxplat_dev->dev, "leds-mlxreg", 1880 PLATFORM_DEVID_NONE, NULL, 0, 1881 mlxplat_led, sizeof(*mlxplat_led)); 1882 if (IS_ERR(priv->pdev_led)) { 1883 err = PTR_ERR(priv->pdev_led); 1884 goto fail_platform_hotplug_register; 1885 } 1886 1887 /* Add registers io access driver. */ 1888 if (mlxplat_regs_io) { 1889 mlxplat_regs_io->regmap = mlxplat_hotplug->regmap; 1890 priv->pdev_io_regs = platform_device_register_resndata( 1891 &mlxplat_dev->dev, "mlxreg-io", 1892 PLATFORM_DEVID_NONE, NULL, 0, 1893 mlxplat_regs_io, 1894 sizeof(*mlxplat_regs_io)); 1895 if (IS_ERR(priv->pdev_io_regs)) { 1896 err = PTR_ERR(priv->pdev_io_regs); 1897 goto fail_platform_led_register; 1898 } 1899 } 1900 1901 /* Add FAN driver. */ 1902 if (mlxplat_fan) { 1903 mlxplat_fan->regmap = mlxplat_hotplug->regmap; 1904 priv->pdev_fan = platform_device_register_resndata( 1905 &mlxplat_dev->dev, "mlxreg-fan", 1906 PLATFORM_DEVID_NONE, NULL, 0, 1907 mlxplat_fan, 1908 sizeof(*mlxplat_fan)); 1909 if (IS_ERR(priv->pdev_fan)) { 1910 err = PTR_ERR(priv->pdev_fan); 1911 goto fail_platform_io_regs_register; 1912 } 1913 } 1914 1915 /* Sync registers with hardware. */ 1916 regcache_mark_dirty(mlxplat_hotplug->regmap); 1917 err = regcache_sync(mlxplat_hotplug->regmap); 1918 if (err) 1919 goto fail_platform_fan_register; 1920 1921 return 0; 1922 1923 fail_platform_fan_register: 1924 if (mlxplat_fan) 1925 platform_device_unregister(priv->pdev_fan); 1926 fail_platform_io_regs_register: 1927 if (mlxplat_regs_io) 1928 platform_device_unregister(priv->pdev_io_regs); 1929 fail_platform_led_register: 1930 platform_device_unregister(priv->pdev_led); 1931 fail_platform_hotplug_register: 1932 platform_device_unregister(priv->pdev_hotplug); 1933 fail_platform_mux_register: 1934 while (--i >= 0) 1935 platform_device_unregister(priv->pdev_mux[i]); 1936 platform_device_unregister(priv->pdev_i2c); 1937 fail_alloc: 1938 platform_device_unregister(mlxplat_dev); 1939 1940 return err; 1941 } 1942 module_init(mlxplat_init); 1943 1944 static void __exit mlxplat_exit(void) 1945 { 1946 struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); 1947 int i; 1948 1949 if (priv->pdev_fan) 1950 platform_device_unregister(priv->pdev_fan); 1951 if (priv->pdev_io_regs) 1952 platform_device_unregister(priv->pdev_io_regs); 1953 platform_device_unregister(priv->pdev_led); 1954 platform_device_unregister(priv->pdev_hotplug); 1955 1956 for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--) 1957 platform_device_unregister(priv->pdev_mux[i]); 1958 1959 platform_device_unregister(priv->pdev_i2c); 1960 platform_device_unregister(mlxplat_dev); 1961 } 1962 module_exit(mlxplat_exit); 1963 1964 MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)"); 1965 MODULE_DESCRIPTION("Mellanox platform driver"); 1966 MODULE_LICENSE("Dual BSD/GPL"); 1967