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