blob: a0fd9aa6d93258f7305dae2dd60506f9f1464689 [file] [log] [blame]
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001/*
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00002 * 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>
Vadim Pasternakc6acad62018-01-22 19:55:11 -080038#include <linux/io.h>
Vadim Pasternak58cbbee2016-09-22 21:13:42 +000039#include <linux/module.h>
40#include <linux/platform_device.h>
41#include <linux/platform_data/i2c-mux-reg.h>
Vadim Pasternak1f976f62018-01-17 18:21:53 +000042#include <linux/platform_data/mlxreg.h>
Vadim Pasternakc6acad62018-01-22 19:55:11 -080043#include <linux/regmap.h>
Vadim Pasternak58cbbee2016-09-22 21:13:42 +000044
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
Vadim Pasternak11894562018-05-07 06:48:53 +000050#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
51#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
52#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
53#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23
54#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24
Vadim Pasternakc6acad62018-01-22 19:55:11 -080055#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +000056#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
57#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
58#define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41
Vadim Pasternakc6acad62018-01-22 19:55:11 -080059#define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +000060#define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59
61#define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a
Vadim Pasternakc6acad62018-01-22 19:55:11 -080062#define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +000063#define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET 0x65
64#define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET 0x66
Vadim Pasternakc6acad62018-01-22 19:55:11 -080065#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +000066#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89
67#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a
Vadim Pasternak58cbbee2016-09-22 21:13:42 +000068#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
69#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
70#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
71#define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL
72#define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
73 MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
74 MLXPLAT_CPLD_LPC_PIO_OFFSET)
75#define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
76 MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
77 MLXPLAT_CPLD_LPC_PIO_OFFSET)
78
Vadim Pasternak9a38b672016-12-14 12:05:15 +000079/* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */
80#define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08
81#define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08
82#define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40
83#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
84 MLXPLAT_CPLD_AGGR_FAN_MASK_DEF)
Vadim Pasternak6016f7d2018-02-02 08:45:47 +000085#define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04
86#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc0
Vadim Pasternak9a38b672016-12-14 12:05:15 +000087#define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04
88#define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0)
89#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
90#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
Vadim Pasternak1bd42d92018-02-09 23:59:32 +000091#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
Vadim Pasternak11894562018-05-07 06:48:53 +000092#define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4)
93#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0)
Vadim Pasternak9a38b672016-12-14 12:05:15 +000094
Vadim Pasternakef0f6222018-02-13 22:09:36 +000095/* Default I2C parent bus number */
96#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
97
98/* Maximum number of possible physical buses equipped on system */
99#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
100
Vadim Pasternakd066f142018-02-13 22:09:33 +0000101/* Number of channels in group */
102#define MLXPLAT_CPLD_GRP_CHNL_NUM 8
103
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000104/* Start channel numbers */
105#define MLXPLAT_CPLD_CH1 2
106#define MLXPLAT_CPLD_CH2 10
107
108/* Number of LPC attached MUX platform devices */
109#define MLXPLAT_CPLD_LPC_MUX_DEVS 2
110
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000111/* Hotplug devices adapter numbers */
Vadim Pasternak1778567a2018-02-02 08:45:46 +0000112#define MLXPLAT_CPLD_NR_NONE -1
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000113#define MLXPLAT_CPLD_PSU_DEFAULT_NR 10
Vadim Pasternakef08e142018-02-09 23:59:30 +0000114#define MLXPLAT_CPLD_PSU_MSNXXXX_NR 4
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000115#define MLXPLAT_CPLD_FAN1_DEFAULT_NR 11
116#define MLXPLAT_CPLD_FAN2_DEFAULT_NR 12
117#define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13
118#define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14
119
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000120/* mlxplat_priv - platform private data
121 * @pdev_i2c - i2c controller platform device
122 * @pdev_mux - array of mux platform devices
Vadim Pasternakb4d3dbc2018-01-25 14:02:53 -0800123 * @pdev_hotplug - hotplug platform devices
Vadim Pasternak11894562018-05-07 06:48:53 +0000124 * @pdev_led - led platform devices
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000125 */
126struct mlxplat_priv {
127 struct platform_device *pdev_i2c;
128 struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
Vadim Pasternakafc47152016-10-27 19:55:54 +0000129 struct platform_device *pdev_hotplug;
Vadim Pasternak11894562018-05-07 06:48:53 +0000130 struct platform_device *pdev_led;
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000131};
132
133/* Regions for LPC I2C controller and LPC base register space */
134static const struct resource mlxplat_lpc_resources[] = {
135 [0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR,
136 MLXPLAT_CPLD_LPC_IO_RANGE,
137 "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO),
138 [1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR,
139 MLXPLAT_CPLD_LPC_IO_RANGE,
140 "mlxplat_cpld_lpc_regs",
141 IORESOURCE_IO),
142};
143
144/* Platform default channels */
Vadim Pasternakd066f142018-02-13 22:09:33 +0000145static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000146 {
147 MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
148 MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
149 5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7
150 },
151 {
152 MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2,
153 MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 +
154 5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7
155 },
156};
157
158/* Platform channels for MSN21xx system family */
159static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
160
161/* Platform mux data */
162static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
163 {
164 .parent = 1,
165 .base_nr = MLXPLAT_CPLD_CH1,
166 .write_only = 1,
167 .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
168 .reg_size = 1,
169 .idle_in_use = 1,
170 },
171 {
172 .parent = 1,
173 .base_nr = MLXPLAT_CPLD_CH2,
174 .write_only = 1,
175 .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
176 .reg_size = 1,
177 .idle_in_use = 1,
178 },
179
180};
181
Vadim Pasternakafc47152016-10-27 19:55:54 +0000182/* Platform hotplug devices */
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800183static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
Vadim Pasternakafc47152016-10-27 19:55:54 +0000184 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800185 I2C_BOARD_INFO("24c02", 0x51),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000186 },
187 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800188 I2C_BOARD_INFO("24c02", 0x50),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000189 },
190};
191
Vadim Pasternak1bd42d92018-02-09 23:59:32 +0000192static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = {
193 {
194 I2C_BOARD_INFO("24c32", 0x51),
195 },
196 {
197 I2C_BOARD_INFO("24c32", 0x50),
198 },
199};
200
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800201static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
Vadim Pasternakafc47152016-10-27 19:55:54 +0000202 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800203 I2C_BOARD_INFO("dps460", 0x59),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000204 },
205 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800206 I2C_BOARD_INFO("dps460", 0x58),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000207 },
208};
209
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800210static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
Vadim Pasternakafc47152016-10-27 19:55:54 +0000211 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800212 I2C_BOARD_INFO("24c32", 0x50),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000213 },
214 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800215 I2C_BOARD_INFO("24c32", 0x50),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000216 },
217 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800218 I2C_BOARD_INFO("24c32", 0x50),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000219 },
220 {
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800221 I2C_BOARD_INFO("24c32", 0x50),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000222 },
223};
224
225/* Platform hotplug default data */
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800226static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = {
227 {
228 .label = "psu1",
229 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
230 .mask = BIT(0),
231 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000232 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800233 },
234 {
235 .label = "psu2",
236 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
237 .mask = BIT(1),
238 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000239 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800240 },
241};
242
243static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = {
244 {
245 .label = "pwr1",
246 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
247 .mask = BIT(0),
248 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000249 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800250 },
251 {
252 .label = "pwr2",
253 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
254 .mask = BIT(1),
255 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000256 .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800257 },
258};
259
260static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
261 {
262 .label = "fan1",
263 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
264 .mask = BIT(0),
265 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000266 .hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800267 },
268 {
269 .label = "fan2",
270 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
271 .mask = BIT(1),
272 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000273 .hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800274 },
275 {
276 .label = "fan3",
277 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
278 .mask = BIT(2),
279 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000280 .hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800281 },
282 {
283 .label = "fan4",
284 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
285 .mask = BIT(3),
286 .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3],
Vadim Pasternakba814fd2018-02-02 08:45:45 +0000287 .hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800288 },
289};
290
291static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
292 {
293 .data = mlxplat_mlxcpld_default_psu_items_data,
294 .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
295 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
296 .mask = MLXPLAT_CPLD_PSU_MASK,
297 .count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
298 .inversed = 1,
299 .health = false,
300 },
301 {
302 .data = mlxplat_mlxcpld_default_pwr_items_data,
303 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
304 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
305 .mask = MLXPLAT_CPLD_PWR_MASK,
306 .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
307 .inversed = 0,
308 .health = false,
309 },
310 {
311 .data = mlxplat_mlxcpld_default_fan_items_data,
312 .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
313 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
314 .mask = MLXPLAT_CPLD_FAN_MASK,
315 .count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
316 .inversed = 1,
317 .health = false,
318 },
319};
320
Vadim Pasternakafc47152016-10-27 19:55:54 +0000321static
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800322struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
323 .items = mlxplat_mlxcpld_default_items,
324 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
325 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
326 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
Vadim Pasternakafc47152016-10-27 19:55:54 +0000327};
328
Vadim Pasternak6016f7d2018-02-02 08:45:47 +0000329static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = {
330 {
331 .label = "pwr1",
332 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
333 .mask = BIT(0),
334 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
335 },
336 {
337 .label = "pwr2",
338 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
339 .mask = BIT(1),
340 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
341 },
342};
343
Vadim Pasternakafc47152016-10-27 19:55:54 +0000344/* Platform hotplug MSN21xx system family data */
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800345static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
346 {
Vadim Pasternak6016f7d2018-02-02 08:45:47 +0000347 .data = mlxplat_mlxcpld_msn21xx_pwr_items_data,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800348 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
349 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
350 .mask = MLXPLAT_CPLD_PWR_MASK,
Vadim Pasternak6016f7d2018-02-02 08:45:47 +0000351 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data),
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800352 .inversed = 0,
353 .health = false,
354 },
355};
356
Vadim Pasternakafc47152016-10-27 19:55:54 +0000357static
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800358struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
359 .items = mlxplat_mlxcpld_msn21xx_items,
360 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items),
361 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
362 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
Vadim Pasternak6016f7d2018-02-02 08:45:47 +0000363 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
364 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800365};
366
Vadim Pasternakef08e142018-02-09 23:59:30 +0000367/* Platform hotplug msn274x system family data */
368static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = {
369 {
370 .label = "psu1",
371 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
372 .mask = BIT(0),
373 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
374 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
375 },
376 {
377 .label = "psu2",
378 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
379 .mask = BIT(1),
380 .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
381 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
382 },
383};
384
385static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = {
386 {
387 .label = "pwr1",
388 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
389 .mask = BIT(0),
390 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
391 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
392 },
393 {
394 .label = "pwr2",
395 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
396 .mask = BIT(1),
397 .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
398 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
399 },
400};
401
402static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = {
403 {
404 .label = "fan1",
405 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
406 .mask = BIT(0),
407 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
408 },
409 {
410 .label = "fan2",
411 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
412 .mask = BIT(1),
413 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
414 },
415 {
416 .label = "fan3",
417 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
418 .mask = BIT(2),
419 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
420 },
421 {
422 .label = "fan4",
423 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
424 .mask = BIT(3),
425 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
426 },
427};
428
429static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = {
430 {
431 .data = mlxplat_mlxcpld_msn274x_psu_items_data,
432 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
433 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
434 .mask = MLXPLAT_CPLD_PSU_MASK,
435 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data),
436 .inversed = 1,
437 .health = false,
438 },
439 {
440 .data = mlxplat_mlxcpld_default_ng_pwr_items_data,
441 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
442 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
443 .mask = MLXPLAT_CPLD_PWR_MASK,
444 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
445 .inversed = 0,
446 .health = false,
447 },
448 {
449 .data = mlxplat_mlxcpld_msn274x_fan_items_data,
450 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
451 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
452 .mask = MLXPLAT_CPLD_FAN_MASK,
453 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data),
454 .inversed = 1,
455 .health = false,
456 },
457};
458
459static
460struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = {
461 .items = mlxplat_mlxcpld_msn274x_items,
462 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items),
463 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
464 .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
465 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
466 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
467};
468
Vadim Pasternaka49a4142018-02-09 23:59:31 +0000469/* Platform hotplug MSN201x system family data */
470static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = {
471 {
472 .label = "pwr1",
473 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
474 .mask = BIT(0),
475 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
476 },
477 {
478 .label = "pwr2",
479 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
480 .mask = BIT(1),
481 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
482 },
483};
484
485static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
486 {
487 .data = mlxplat_mlxcpld_msn201x_pwr_items_data,
488 .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
489 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
490 .mask = MLXPLAT_CPLD_PWR_MASK,
491 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data),
492 .inversed = 0,
493 .health = false,
494 },
495};
496
497static
498struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = {
499 .items = mlxplat_mlxcpld_msn21xx_items,
500 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items),
501 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
502 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
503 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
504 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
505};
506
Vadim Pasternak1bd42d92018-02-09 23:59:32 +0000507/* Platform hotplug next generation system family data */
508static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = {
509 {
510 .label = "psu1",
511 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
512 .mask = BIT(0),
513 .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0],
514 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
515 },
516 {
517 .label = "psu2",
518 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
519 .mask = BIT(1),
520 .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1],
521 .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
522 },
523};
524
525static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = {
526 {
527 .label = "fan1",
528 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
529 .mask = BIT(0),
530 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
531 },
532 {
533 .label = "fan2",
534 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
535 .mask = BIT(1),
536 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
537 },
538 {
539 .label = "fan3",
540 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
541 .mask = BIT(2),
542 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
543 },
544 {
545 .label = "fan4",
546 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
547 .mask = BIT(3),
548 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
549 },
550 {
551 .label = "fan5",
552 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
553 .mask = BIT(4),
554 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
555 },
556 {
557 .label = "fan6",
558 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
559 .mask = BIT(5),
560 .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
561 },
562};
563
564static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = {
565 {
566 .data = mlxplat_mlxcpld_default_ng_psu_items_data,
567 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
568 .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
569 .mask = MLXPLAT_CPLD_PSU_MASK,
570 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data),
571 .inversed = 1,
572 .health = false,
573 },
574 {
575 .data = mlxplat_mlxcpld_default_ng_pwr_items_data,
576 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
577 .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
578 .mask = MLXPLAT_CPLD_PWR_MASK,
579 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data),
580 .inversed = 0,
581 .health = false,
582 },
583 {
584 .data = mlxplat_mlxcpld_default_ng_fan_items_data,
585 .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
586 .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
587 .mask = MLXPLAT_CPLD_FAN_NG_MASK,
588 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data),
589 .inversed = 1,
590 .health = false,
591 },
592};
593
594static
595struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
596 .items = mlxplat_mlxcpld_default_ng_items,
597 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items),
598 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
599 .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
600 .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
601 .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
602};
603
Vadim Pasternak11894562018-05-07 06:48:53 +0000604/* Platform led default data */
605static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
606 {
607 .label = "status:green",
608 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
609 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
610 },
611 {
612 .label = "status:red",
613 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
614 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
615 },
616 {
617 .label = "psu:green",
618 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
619 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
620 },
621 {
622 .label = "psu:red",
623 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
624 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
625 },
626 {
627 .label = "fan1:green",
628 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
629 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
630 },
631 {
632 .label = "fan1:red",
633 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
634 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
635 },
636 {
637 .label = "fan2:green",
638 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
639 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
640 },
641 {
642 .label = "fan2:red",
643 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
644 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
645 },
646 {
647 .label = "fan3:green",
648 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
649 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
650 },
651 {
652 .label = "fan3:red",
653 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
654 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
655 },
656 {
657 .label = "fan4:green",
658 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
659 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
660 },
661 {
662 .label = "fan4:red",
663 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
664 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
665 },
666};
667
668static struct mlxreg_core_platform_data mlxplat_default_led_data = {
669 .data = mlxplat_mlxcpld_default_led_data,
670 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
671};
672
673/* Platform led MSN21xx system family data */
674static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
675 {
676 .label = "status:green",
677 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
678 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
679 },
680 {
681 .label = "status:red",
682 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
683 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
684 },
685 {
686 .label = "fan:green",
687 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
688 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
689 },
690 {
691 .label = "fan:red",
692 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
693 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
694 },
695 {
696 .label = "psu1:green",
697 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
698 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
699 },
700 {
701 .label = "psu1:red",
702 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
703 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
704 },
705 {
706 .label = "psu2:green",
707 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
708 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
709 },
710 {
711 .label = "psu2:red",
712 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
713 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
714 },
715 {
716 .label = "uid:blue",
717 .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
718 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
719 },
720};
721
722static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
723 .data = mlxplat_mlxcpld_msn21xx_led_data,
724 .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
725};
726
727/* Platform led for default data for 200GbE systems */
728static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
729 {
730 .label = "status:green",
731 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
732 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
733 },
734 {
735 .label = "status:orange",
736 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
737 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
738 },
739 {
740 .label = "psu:green",
741 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
742 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
743 },
744 {
745 .label = "psu:orange",
746 .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
747 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
748 },
749 {
750 .label = "fan1:green",
751 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
752 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
753 },
754 {
755 .label = "fan1:orange",
756 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
757 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
758 },
759 {
760 .label = "fan2:green",
761 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
762 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
763 },
764 {
765 .label = "fan2:orange",
766 .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
767 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
768 },
769 {
770 .label = "fan3:green",
771 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
772 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
773 },
774 {
775 .label = "fan3:orange",
776 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
777 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
778 },
779 {
780 .label = "fan4:green",
781 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
782 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
783 },
784 {
785 .label = "fan4:orange",
786 .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
787 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
788 },
789 {
790 .label = "fan5:green",
791 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
792 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
793 },
794 {
795 .label = "fan5:orange",
796 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
797 .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
798 },
799 {
800 .label = "fan6:green",
801 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
802 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
803 },
804 {
805 .label = "fan6:orange",
806 .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
807 .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
808 },
809};
810
811static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
812 .data = mlxplat_mlxcpld_default_ng_led_data,
813 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
814};
815
816
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +0000817static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
818{
819 switch (reg) {
Vadim Pasternak11894562018-05-07 06:48:53 +0000820 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
821 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
822 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
823 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
824 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +0000825 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
826 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
827 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
828 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
829 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
830 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
831 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
832 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
833 return true;
834 }
835 return false;
836}
837
838static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
839{
840 switch (reg) {
Vadim Pasternak11894562018-05-07 06:48:53 +0000841 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
842 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
843 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
844 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
845 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +0000846 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
847 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
848 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
849 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
850 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
851 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
852 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
853 case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
854 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
855 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
856 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
857 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
858 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
859 return true;
860 }
861 return false;
862}
863
864static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
865{
866 switch (reg) {
Vadim Pasternak11894562018-05-07 06:48:53 +0000867 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
868 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
869 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
870 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
871 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +0000872 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
873 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
874 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
875 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
876 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
877 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
878 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
879 case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET:
880 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
881 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
882 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
883 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
884 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
885 return true;
886 }
887 return false;
888}
889
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800890struct mlxplat_mlxcpld_regmap_context {
891 void __iomem *base;
892};
893
894static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
895
896static int
897mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
898{
899 struct mlxplat_mlxcpld_regmap_context *ctx = context;
900
901 *val = ioread8(ctx->base + reg);
902 return 0;
903}
904
905static int
906mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val)
907{
908 struct mlxplat_mlxcpld_regmap_context *ctx = context;
909
910 iowrite8(val, ctx->base + reg);
911 return 0;
912}
913
914static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
915 .reg_bits = 8,
916 .val_bits = 8,
917 .max_register = 255,
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +0000918 .cache_type = REGCACHE_FLAT,
919 .writeable_reg = mlxplat_mlxcpld_writeable_reg,
920 .readable_reg = mlxplat_mlxcpld_readable_reg,
921 .volatile_reg = mlxplat_mlxcpld_volatile_reg,
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800922 .reg_read = mlxplat_mlxcpld_reg_read,
923 .reg_write = mlxplat_mlxcpld_reg_write,
Vadim Pasternakafc47152016-10-27 19:55:54 +0000924};
925
Vadim Pasternak9a38b672016-12-14 12:05:15 +0000926static struct resource mlxplat_mlxcpld_resources[] = {
Vadim Pasternak1f976f62018-01-17 18:21:53 +0000927 [0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
Vadim Pasternakafc47152016-10-27 19:55:54 +0000928};
929
Colin Ian King36c282b2017-10-05 11:42:11 +0100930static struct platform_device *mlxplat_dev;
Vadim Pasternakc6acad62018-01-22 19:55:11 -0800931static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
Vadim Pasternak11894562018-05-07 06:48:53 +0000932static struct mlxreg_core_platform_data *mlxplat_led;
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000933
934static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
935{
936 int i;
937
938 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
939 mlxplat_mux_data[i].values = mlxplat_default_channels[i];
940 mlxplat_mux_data[i].n_values =
941 ARRAY_SIZE(mlxplat_default_channels[i]);
942 }
Vadim Pasternak9a38b672016-12-14 12:05:15 +0000943 mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
Vadim Pasternakd726f6b2018-02-13 22:09:34 +0000944 mlxplat_hotplug->deferred_nr =
945 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
Vadim Pasternak11894562018-05-07 06:48:53 +0000946 mlxplat_led = &mlxplat_default_led_data;
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000947
948 return 1;
949};
950
951static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
952{
953 int i;
954
955 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
956 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
957 mlxplat_mux_data[i].n_values =
958 ARRAY_SIZE(mlxplat_msn21xx_channels);
959 }
Vadim Pasternak9a38b672016-12-14 12:05:15 +0000960 mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
Vadim Pasternakd726f6b2018-02-13 22:09:34 +0000961 mlxplat_hotplug->deferred_nr =
962 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
Vadim Pasternak11894562018-05-07 06:48:53 +0000963 mlxplat_led = &mlxplat_msn21xx_led_data;
Vadim Pasternak58cbbee2016-09-22 21:13:42 +0000964
965 return 1;
966};
967
Vadim Pasternakef08e142018-02-09 23:59:30 +0000968static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
969{
970 int i;
971
972 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
973 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
974 mlxplat_mux_data[i].n_values =
975 ARRAY_SIZE(mlxplat_msn21xx_channels);
976 }
977 mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
Vadim Pasternakd726f6b2018-02-13 22:09:34 +0000978 mlxplat_hotplug->deferred_nr =
979 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
Vadim Pasternak11894562018-05-07 06:48:53 +0000980 mlxplat_led = &mlxplat_default_led_data;
Vadim Pasternakef08e142018-02-09 23:59:30 +0000981
982 return 1;
983};
984
Vadim Pasternaka49a4142018-02-09 23:59:31 +0000985static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
986{
987 int i;
988
989 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
990 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
991 mlxplat_mux_data[i].n_values =
992 ARRAY_SIZE(mlxplat_msn21xx_channels);
993 }
994 mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
Vadim Pasternakd726f6b2018-02-13 22:09:34 +0000995 mlxplat_hotplug->deferred_nr =
996 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
Vadim Pasternak11894562018-05-07 06:48:53 +0000997 mlxplat_led = &mlxplat_default_ng_led_data;
Vadim Pasternaka49a4142018-02-09 23:59:31 +0000998
999 return 1;
1000};
1001
Vadim Pasternak1bd42d92018-02-09 23:59:32 +00001002static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
1003{
1004 int i;
1005
1006 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1007 mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
1008 mlxplat_mux_data[i].n_values =
1009 ARRAY_SIZE(mlxplat_msn21xx_channels);
1010 }
1011 mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
Vadim Pasternakd726f6b2018-02-13 22:09:34 +00001012 mlxplat_hotplug->deferred_nr =
1013 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
Vadim Pasternak11894562018-05-07 06:48:53 +00001014 mlxplat_led = &mlxplat_msn21xx_led_data;
Vadim Pasternak1bd42d92018-02-09 23:59:32 +00001015
1016 return 1;
1017};
1018
Christoph Hellwig6faadbb2017-09-14 11:59:30 +02001019static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001020 {
Vadim Pasternakef08e142018-02-09 23:59:30 +00001021 .callback = mlxplat_dmi_msn274x_matched,
1022 .matches = {
1023 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1024 DMI_MATCH(DMI_PRODUCT_NAME, "MSN274"),
1025 },
1026 },
1027 {
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001028 .callback = mlxplat_dmi_default_matched,
1029 .matches = {
1030 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1031 DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
1032 },
1033 },
1034 {
1035 .callback = mlxplat_dmi_default_matched,
1036 .matches = {
1037 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1038 DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
1039 },
1040 },
1041 {
1042 .callback = mlxplat_dmi_default_matched,
1043 .matches = {
1044 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1045 DMI_MATCH(DMI_PRODUCT_NAME, "MSB"),
1046 },
1047 },
1048 {
1049 .callback = mlxplat_dmi_default_matched,
1050 .matches = {
1051 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1052 DMI_MATCH(DMI_PRODUCT_NAME, "MSX"),
1053 },
1054 },
1055 {
1056 .callback = mlxplat_dmi_msn21xx_matched,
1057 .matches = {
1058 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1059 DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"),
1060 },
1061 },
Vadim Pasternaka49a4142018-02-09 23:59:31 +00001062 {
1063 .callback = mlxplat_dmi_msn201x_matched,
1064 .matches = {
1065 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1066 DMI_MATCH(DMI_PRODUCT_NAME, "MSN201"),
1067 },
1068 },
Vadim Pasternak1bd42d92018-02-09 23:59:32 +00001069 {
1070 .callback = mlxplat_dmi_qmb7xx_matched,
1071 .matches = {
1072 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1073 DMI_MATCH(DMI_PRODUCT_NAME, "QMB7"),
1074 },
1075 },
1076 {
1077 .callback = mlxplat_dmi_qmb7xx_matched,
1078 .matches = {
1079 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1080 DMI_MATCH(DMI_PRODUCT_NAME, "SN37"),
1081 },
1082 },
1083 {
1084 .callback = mlxplat_dmi_qmb7xx_matched,
1085 .matches = {
1086 DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
1087 DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
1088 },
1089 },
Vadim Pasternakcbf7ff82018-05-07 06:48:52 +00001090 {
1091 .callback = mlxplat_dmi_default_matched,
1092 .matches = {
1093 DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
1094 },
1095 },
1096 {
1097 .callback = mlxplat_dmi_msn21xx_matched,
1098 .matches = {
1099 DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
1100 },
1101 },
1102 {
1103 .callback = mlxplat_dmi_msn274x_matched,
1104 .matches = {
1105 DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
1106 },
1107 },
1108 {
1109 .callback = mlxplat_dmi_msn201x_matched,
1110 .matches = {
1111 DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
1112 },
1113 },
1114 {
1115 .callback = mlxplat_dmi_qmb7xx_matched,
1116 .matches = {
1117 DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
1118 },
1119 },
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001120 { }
1121};
1122
Ivan Vecera580d8342018-01-22 15:20:43 +01001123MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
1124
Vadim Pasternakef0f6222018-02-13 22:09:36 +00001125static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
1126{
1127 struct i2c_adapter *search_adap;
1128 int shift, i;
1129
1130 /* Scan adapters from expected id to verify it is free. */
1131 *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
1132 for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
1133 MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
1134 search_adap = i2c_get_adapter(i);
1135 if (search_adap) {
1136 i2c_put_adapter(search_adap);
1137 continue;
1138 }
1139
1140 /* Return if expected parent adapter is free. */
1141 if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
1142 return 0;
1143 break;
1144 }
1145
1146 /* Return with error if free id for adapter is not found. */
1147 if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
1148 return -ENODEV;
1149
1150 /* Shift adapter ids, since expected parent adapter is not free. */
1151 *nr = i;
1152 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1153 shift = *nr - mlxplat_mux_data[i].parent;
1154 mlxplat_mux_data[i].parent = *nr;
1155 mlxplat_mux_data[i].base_nr += shift;
1156 if (shift > 0)
1157 mlxplat_hotplug->shift_nr = shift;
1158 }
1159
1160 return 0;
1161}
1162
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001163static int __init mlxplat_init(void)
1164{
1165 struct mlxplat_priv *priv;
Vadim Pasternakef0f6222018-02-13 22:09:36 +00001166 int i, nr, err;
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001167
1168 if (!dmi_check_system(mlxplat_dmi_table))
1169 return -ENODEV;
1170
1171 mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1,
1172 mlxplat_lpc_resources,
1173 ARRAY_SIZE(mlxplat_lpc_resources));
1174
Wei Yongjun65f74222016-09-24 11:48:13 +00001175 if (IS_ERR(mlxplat_dev))
1176 return PTR_ERR(mlxplat_dev);
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001177
1178 priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
1179 GFP_KERNEL);
1180 if (!priv) {
1181 err = -ENOMEM;
1182 goto fail_alloc;
1183 }
1184 platform_set_drvdata(mlxplat_dev, priv);
1185
Vadim Pasternakef0f6222018-02-13 22:09:36 +00001186 err = mlxplat_mlxcpld_verify_bus_topology(&nr);
1187 if (nr < 0)
1188 goto fail_alloc;
1189
1190 nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
1191 priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001192 NULL, 0);
1193 if (IS_ERR(priv->pdev_i2c)) {
1194 err = PTR_ERR(priv->pdev_i2c);
1195 goto fail_alloc;
kbuild test robotc3886c92016-10-28 01:26:50 +08001196 }
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001197
1198 for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
1199 priv->pdev_mux[i] = platform_device_register_resndata(
1200 &mlxplat_dev->dev,
1201 "i2c-mux-reg", i, NULL,
1202 0, &mlxplat_mux_data[i],
1203 sizeof(mlxplat_mux_data[i]));
1204 if (IS_ERR(priv->pdev_mux[i])) {
1205 err = PTR_ERR(priv->pdev_mux[i]);
1206 goto fail_platform_mux_register;
1207 }
1208 }
1209
Vadim Pasternakc6acad62018-01-22 19:55:11 -08001210 mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev,
1211 mlxplat_lpc_resources[1].start, 1);
Dan Carpenter8a0f5b62018-02-06 15:45:36 +03001212 if (!mlxplat_mlxcpld_regmap_ctx.base) {
1213 err = -ENOMEM;
Vadim Pasternakc6acad62018-01-22 19:55:11 -08001214 goto fail_platform_mux_register;
1215 }
1216
1217 mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
1218 &mlxplat_mlxcpld_regmap_ctx,
1219 &mlxplat_mlxcpld_regmap_config);
1220 if (IS_ERR(mlxplat_hotplug->regmap)) {
1221 err = PTR_ERR(mlxplat_hotplug->regmap);
1222 goto fail_platform_mux_register;
1223 }
1224
Vadim Pasternakafc47152016-10-27 19:55:54 +00001225 priv->pdev_hotplug = platform_device_register_resndata(
Vadim Pasternak1f976f62018-01-17 18:21:53 +00001226 &mlxplat_dev->dev, "mlxreg-hotplug",
Vadim Pasternak9a38b672016-12-14 12:05:15 +00001227 PLATFORM_DEVID_NONE,
1228 mlxplat_mlxcpld_resources,
1229 ARRAY_SIZE(mlxplat_mlxcpld_resources),
Vadim Pasternakafc47152016-10-27 19:55:54 +00001230 mlxplat_hotplug, sizeof(*mlxplat_hotplug));
1231 if (IS_ERR(priv->pdev_hotplug)) {
1232 err = PTR_ERR(priv->pdev_hotplug);
1233 goto fail_platform_mux_register;
1234 }
1235
Vadim Pasternak11894562018-05-07 06:48:53 +00001236 /* Add LED driver. */
1237 mlxplat_led->regmap = mlxplat_hotplug->regmap;
1238 priv->pdev_led = platform_device_register_resndata(
1239 &mlxplat_dev->dev, "leds-mlxreg",
1240 PLATFORM_DEVID_NONE, NULL, 0,
1241 mlxplat_led, sizeof(*mlxplat_led));
1242 if (IS_ERR(priv->pdev_led)) {
1243 err = PTR_ERR(priv->pdev_led);
1244 goto fail_platform_hotplug_register;
1245 }
1246
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +00001247 /* Sync registers with hardware. */
1248 regcache_mark_dirty(mlxplat_hotplug->regmap);
1249 err = regcache_sync(mlxplat_hotplug->regmap);
1250 if (err)
Vadim Pasternak11894562018-05-07 06:48:53 +00001251 goto fail_platform_led_register;
Vadim Pasternak0b78b1c2018-01-26 19:03:44 +00001252
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001253 return 0;
1254
Vadim Pasternak11894562018-05-07 06:48:53 +00001255fail_platform_led_register:
1256 platform_device_unregister(priv->pdev_led);
Vadim Pasternak47260982018-01-31 21:55:13 +00001257fail_platform_hotplug_register:
1258 platform_device_unregister(priv->pdev_hotplug);
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001259fail_platform_mux_register:
Dan Carpenter63d762b2017-01-07 09:33:34 +03001260 while (--i >= 0)
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001261 platform_device_unregister(priv->pdev_mux[i]);
1262 platform_device_unregister(priv->pdev_i2c);
1263fail_alloc:
1264 platform_device_unregister(mlxplat_dev);
1265
1266 return err;
1267}
1268module_init(mlxplat_init);
1269
1270static void __exit mlxplat_exit(void)
1271{
1272 struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
1273 int i;
1274
Vadim Pasternak11894562018-05-07 06:48:53 +00001275 platform_device_unregister(priv->pdev_led);
Vadim Pasternakafc47152016-10-27 19:55:54 +00001276 platform_device_unregister(priv->pdev_hotplug);
1277
Vadim Pasternak58cbbee2016-09-22 21:13:42 +00001278 for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
1279 platform_device_unregister(priv->pdev_mux[i]);
1280
1281 platform_device_unregister(priv->pdev_i2c);
1282 platform_device_unregister(mlxplat_dev);
1283}
1284module_exit(mlxplat_exit);
1285
1286MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
1287MODULE_DESCRIPTION("Mellanox platform driver");
1288MODULE_LICENSE("Dual BSD/GPL");