aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Pasternak <vadimp@mellanox.com>2016-09-08 03:25:53 -0400
committerJacek Anaszewski <j.anaszewski@samsung.com>2016-09-15 10:49:39 -0400
commitbe4fdf99fa4dc95aa01144b207caf2cc9fa074d8 (patch)
tree3f976a3e9ad156a779a4fdd839a270d85348f0f2
parent1f70cb4045cba47287fed3ba98dadc7187f13ef8 (diff)
leds: add driver for Mellanox systems LEDs
This makes it possible to create a set of LEDs for Mellanox systems: "msx6710", "msx6720", "msb7700", "msn2700", "msx1410", "msn2410", "msb7800", "msn2740", "msn2100". Driver obtains LED devices according to system configuration, provided through system DMI data, like mlxcpld:fan1:green, mlxcpld:fan1:red and creates devices in form: "devicename:colour:function". LED setting is controlled through on board CPLD Lattice device. For setting particular LED off, solid, blink: echo 0 > /sys/class/leds/mlxcpld\:status\:green/brightness echo 1 > /sys/class/leds/mlxcpld\:status\:green/brightness echo timer > /sys/class/leds/mlxcpld\:status\:green/trigger On module probing all LEDs are set green, on removing - off. Last setting overwrites previous, f.e. sequence for changing LED from green - red - green: echo 1 > /sys/class/leds/mlxcpld\:psu\:green/brightness echo 1 > /sys/class/leds/mlxcpld\:psu\:red/brightness echo 1 > /sys/class/leds/mlxcpld\:psu\:green/brightness Note: LEDs cannot be turned on/off simultaneously. The Kconfig currently controlling compilation of this code is: drivers/leds/Kconfig:config LEDS_MLXCPLD Signed-off-by: Vadim Pasternak <vadimp@mellanox.com> Reviewed-by: Jiri Pirko <jiri@mellanox.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
-rw-r--r--Documentation/leds/leds-mlxcpld.txt110
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-mlxcpld.c430
5 files changed, 556 insertions, 0 deletions
diff --git a/Documentation/leds/leds-mlxcpld.txt b/Documentation/leds/leds-mlxcpld.txt
new file mode 100644
index 000000000000..a0e8fd457117
--- /dev/null
+++ b/Documentation/leds/leds-mlxcpld.txt
@@ -0,0 +1,110 @@
1Kernel driver for Mellanox systems LEDs
2=======================================
3
4Provide system LED support for the nex Mellanox systems:
5"msx6710", "msx6720", "msb7700", "msn2700", "msx1410",
6"msn2410", "msb7800", "msn2740", "msn2100".
7
8Description
9-----------
10Driver provides the following LEDs for the systems "msx6710", "msx6720",
11"msb7700", "msn2700", "msx1410", "msn2410", "msb7800", "msn2740":
12 mlxcpld:fan1:green
13 mlxcpld:fan1:red
14 mlxcpld:fan2:green
15 mlxcpld:fan2:red
16 mlxcpld:fan3:green
17 mlxcpld:fan3:red
18 mlxcpld:fan4:green
19 mlxcpld:fan4:red
20 mlxcpld:psu:green
21 mlxcpld:psu:red
22 mlxcpld:status:green
23 mlxcpld:status:red
24
25 "status"
26 CPLD reg offset: 0x20
27 Bits [3:0]
28
29 "psu"
30 CPLD reg offset: 0x20
31 Bits [7:4]
32
33 "fan1"
34 CPLD reg offset: 0x21
35 Bits [3:0]
36
37 "fan2"
38 CPLD reg offset: 0x21
39 Bits [7:4]
40
41 "fan3"
42 CPLD reg offset: 0x22
43 Bits [3:0]
44
45 "fan4"
46 CPLD reg offset: 0x22
47 Bits [7:4]
48
49 Color mask for all the above LEDs:
50 [bit3,bit2,bit1,bit0] or
51 [bit7,bit6,bit5,bit4]:
52 [0,0,0,0] = LED OFF
53 [0,1,0,1] = Red static ON
54 [1,1,0,1] = Green static ON
55 [0,1,1,0] = Red blink 3Hz
56 [1,1,1,0] = Green blink 3Hz
57 [0,1,1,1] = Red blink 6Hz
58 [1,1,1,1] = Green blink 6Hz
59
60Driver provides the following LEDs for the system "msn2100":
61 mlxcpld:fan:green
62 mlxcpld:fan:red
63 mlxcpld:psu1:green
64 mlxcpld:psu1:red
65 mlxcpld:psu2:green
66 mlxcpld:psu2:red
67 mlxcpld:status:green
68 mlxcpld:status:red
69 mlxcpld:uid:blue
70
71 "status"
72 CPLD reg offset: 0x20
73 Bits [3:0]
74
75 "fan"
76 CPLD reg offset: 0x21
77 Bits [3:0]
78
79 "psu1"
80 CPLD reg offset: 0x23
81 Bits [3:0]
82
83 "psu2"
84 CPLD reg offset: 0x23
85 Bits [7:4]
86
87 "uid"
88 CPLD reg offset: 0x24
89 Bits [3:0]
90
91 Color mask for all the above LEDs, excepted uid:
92 [bit3,bit2,bit1,bit0] or
93 [bit7,bit6,bit5,bit4]:
94 [0,0,0,0] = LED OFF
95 [0,1,0,1] = Red static ON
96 [1,1,0,1] = Green static ON
97 [0,1,1,0] = Red blink 3Hz
98 [1,1,1,0] = Green blink 3Hz
99 [0,1,1,1] = Red blink 6Hz
100 [1,1,1,1] = Green blink 6Hz
101
102 Color mask for uid LED:
103 [bit3,bit2,bit1,bit0]:
104 [0,0,0,0] = LED OFF
105 [1,1,0,1] = Blue static ON
106 [1,1,1,0] = Blue blink 3Hz
107 [1,1,1,1] = Blue blink 6Hz
108
109Driver supports HW blinking at 3Hz and 6Hz frequency (50% duty cycle).
110For 3Hz duty cylce is about 167 msec, for 6Hz is about 83 msec.
diff --git a/MAINTAINERS b/MAINTAINERS
index a306795a7450..f742e88ccf21 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7649,6 +7649,13 @@ W: http://www.mellanox.com
7649Q: http://patchwork.ozlabs.org/project/netdev/list/ 7649Q: http://patchwork.ozlabs.org/project/netdev/list/
7650F: drivers/net/ethernet/mellanox/mlxsw/ 7650F: drivers/net/ethernet/mellanox/mlxsw/
7651 7651
7652MELLANOX MLXCPLD LED DRIVER
7653M: Vadim Pasternak <vadimp@mellanox.com>
7654L: linux-leds@vger.kernel.org
7655S: Supported
7656F: drivers/leds/leds-mlxcpld.c
7657F: Documentation/leds/leds-mlxcpld.txt
7658
7652SOFT-ROCE DRIVER (rxe) 7659SOFT-ROCE DRIVER (rxe)
7653M: Moni Shoua <monis@mellanox.com> 7660M: Moni Shoua <monis@mellanox.com>
7654L: linux-rdma@vger.kernel.org 7661L: linux-rdma@vger.kernel.org
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 969c720dfd10..7a628c6516f6 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -651,6 +651,14 @@ config LEDS_PM8058
651 Choose this option if you want to use the LED drivers in 651 Choose this option if you want to use the LED drivers in
652 the Qualcomm PM8058 PMIC. 652 the Qualcomm PM8058 PMIC.
653 653
654config LEDS_MLXCPLD
655 tristate "LED support for the Mellanox boards"
656 depends on X86_64 && DMI
657 depends on LEDS_CLASS
658 help
659 This option enabled support for the LEDs on the Mellanox
660 boards. Say Y to enabled these.
661
654comment "LED Triggers" 662comment "LED Triggers"
655source "drivers/leds/trigger/Kconfig" 663source "drivers/leds/trigger/Kconfig"
656 664
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 06a27ef17554..3965070190f5 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_LEDS_SEAD3) += leds-sead3.o
70obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o 70obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o
71obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o 71obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o
72obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o 72obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o
73obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o
73 74
74# LED SPI Drivers 75# LED SPI Drivers
75obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 76obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-mlxcpld.c b/drivers/leds/leds-mlxcpld.c
new file mode 100644
index 000000000000..197ab9b29a9c
--- /dev/null
+++ b/drivers/leds/leds-mlxcpld.c
@@ -0,0 +1,430 @@
1/*
2 * drivers/leds/leds-mlxcpld.c
3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the names of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <linux/acpi.h>
36#include <linux/device.h>
37#include <linux/dmi.h>
38#include <linux/hwmon.h>
39#include <linux/hwmon-sysfs.h>
40#include <linux/io.h>
41#include <linux/leds.h>
42#include <linux/module.h>
43#include <linux/mod_devicetable.h>
44#include <linux/platform_device.h>
45#include <linux/slab.h>
46
47#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 /* LPC bus access */
48
49/* Color codes for LEDs */
50#define MLXCPLD_LED_OFFSET_HALF 0x01 /* Offset from solid: 3Hz blink */
51#define MLXCPLD_LED_OFFSET_FULL 0x02 /* Offset from solid: 6Hz blink */
52#define MLXCPLD_LED_IS_OFF 0x00 /* Off */
53#define MLXCPLD_LED_RED_STATIC_ON 0x05 /* Solid red */
54#define MLXCPLD_LED_RED_BLINK_HALF (MLXCPLD_LED_RED_STATIC_ON + \
55 MLXCPLD_LED_OFFSET_HALF)
56#define MLXCPLD_LED_RED_BLINK_FULL (MLXCPLD_LED_RED_STATIC_ON + \
57 MLXCPLD_LED_OFFSET_FULL)
58#define MLXCPLD_LED_GREEN_STATIC_ON 0x0D /* Solid green */
59#define MLXCPLD_LED_GREEN_BLINK_HALF (MLXCPLD_LED_GREEN_STATIC_ON + \
60 MLXCPLD_LED_OFFSET_HALF)
61#define MLXCPLD_LED_GREEN_BLINK_FULL (MLXCPLD_LED_GREEN_STATIC_ON + \
62 MLXCPLD_LED_OFFSET_FULL)
63#define MLXCPLD_LED_BLINK_3HZ 167 /* ~167 msec off/on */
64#define MLXCPLD_LED_BLINK_6HZ 83 /* ~83 msec off/on */
65
66/**
67 * mlxcpld_param - LED access parameters:
68 * @offset - offset for LED access in CPLD device
69 * @mask - mask for LED access in CPLD device
70 * @base_color - base color code for LED
71**/
72struct mlxcpld_param {
73 u8 offset;
74 u8 mask;
75 u8 base_color;
76};
77
78/**
79 * mlxcpld_led_priv - LED private data:
80 * @cled - LED class device instance
81 * @param - LED CPLD access parameters
82**/
83struct mlxcpld_led_priv {
84 struct led_classdev cdev;
85 struct mlxcpld_param param;
86};
87
88#define cdev_to_priv(c) container_of(c, struct mlxcpld_led_priv, cdev)
89
90/**
91 * mlxcpld_led_profile - system LED profile (defined per system class):
92 * @offset - offset for LED access in CPLD device
93 * @mask - mask for LED access in CPLD device
94 * @base_color - base color code
95 * @brightness - default brightness setting (on/off)
96 * @name - LED name
97**/
98struct mlxcpld_led_profile {
99 u8 offset;
100 u8 mask;
101 u8 base_color;
102 enum led_brightness brightness;
103 const char *name;
104};
105
106/**
107 * mlxcpld_led_pdata - system LED private data
108 * @pdev - platform device pointer
109 * @pled - LED class device instance
110 * @profile - system configuration profile
111 * @num_led_instances - number of LED instances
112 * @lock - device access lock
113**/
114struct mlxcpld_led_pdata {
115 struct platform_device *pdev;
116 struct mlxcpld_led_priv *pled;
117 struct mlxcpld_led_profile *profile;
118 int num_led_instances;
119 spinlock_t lock;
120};
121
122static struct mlxcpld_led_pdata *mlxcpld_led;
123
124/* Default profile fit the next Mellanox systems:
125 * "msx6710", "msx6720", "msb7700", "msn2700", "msx1410",
126 * "msn2410", "msb7800", "msn2740"
127 */
128static struct mlxcpld_led_profile mlxcpld_led_default_profile[] = {
129 {
130 0x21, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, 1,
131 "mlxcpld:fan1:green",
132 },
133 {
134 0x21, 0xf0, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
135 "mlxcpld:fan1:red",
136 },
137 {
138 0x21, 0x0f, MLXCPLD_LED_GREEN_STATIC_ON, 1,
139 "mlxcpld:fan2:green",
140 },
141 {
142 0x21, 0x0f, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
143 "mlxcpld:fan2:red",
144 },
145 {
146 0x22, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, 1,
147 "mlxcpld:fan3:green",
148 },
149 {
150 0x22, 0xf0, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
151 "mlxcpld:fan3:red",
152 },
153 {
154 0x22, 0x0f, MLXCPLD_LED_GREEN_STATIC_ON, 1,
155 "mlxcpld:fan4:green",
156 },
157 {
158 0x22, 0x0f, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
159 "mlxcpld:fan4:red",
160 },
161 {
162 0x20, 0x0f, MLXCPLD_LED_GREEN_STATIC_ON, 1,
163 "mlxcpld:psu:green",
164 },
165 {
166 0x20, 0x0f, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
167 "mlxcpld:psu:red",
168 },
169 {
170 0x20, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, 1,
171 "mlxcpld:status:green",
172 },
173 {
174 0x20, 0xf0, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
175 "mlxcpld:status:red",
176 },
177};
178
179/* Profile fit the Mellanox systems based on "msn2100" */
180static struct mlxcpld_led_profile mlxcpld_led_msn2100_profile[] = {
181 {
182 0x21, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, 1,
183 "mlxcpld:fan:green",
184 },
185 {
186 0x21, 0xf0, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
187 "mlxcpld:fan:red",
188 },
189 {
190 0x23, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, 1,
191 "mlxcpld:psu1:green",
192 },
193 {
194 0x23, 0xf0, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
195 "mlxcpld:psu1:red",
196 },
197 {
198 0x23, 0x0f, MLXCPLD_LED_GREEN_STATIC_ON, 1,
199 "mlxcpld:psu2:green",
200 },
201 {
202 0x23, 0x0f, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
203 "mlxcpld:psu2:red",
204 },
205 {
206 0x20, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, 1,
207 "mlxcpld:status:green",
208 },
209 {
210 0x20, 0xf0, MLXCPLD_LED_RED_STATIC_ON, LED_OFF,
211 "mlxcpld:status:red",
212 },
213 {
214 0x24, 0xf0, MLXCPLD_LED_GREEN_STATIC_ON, LED_OFF,
215 "mlxcpld:uid:blue",
216 },
217};
218
219enum mlxcpld_led_platform_types {
220 MLXCPLD_LED_PLATFORM_DEFAULT,
221 MLXCPLD_LED_PLATFORM_MSN2100,
222};
223
224static const char *mlx_product_names[] = {
225 "DEFAULT",
226 "MSN2100",
227};
228
229static enum
230mlxcpld_led_platform_types mlxcpld_led_platform_check_sys_type(void)
231{
232 const char *mlx_product_name;
233 int i;
234
235 mlx_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
236 if (!mlx_product_name)
237 return MLXCPLD_LED_PLATFORM_DEFAULT;
238
239 for (i = 1; i < ARRAY_SIZE(mlx_product_names); i++) {
240 if (strstr(mlx_product_name, mlx_product_names[i]))
241 return i;
242 }
243
244 return MLXCPLD_LED_PLATFORM_DEFAULT;
245}
246
247static void mlxcpld_led_bus_access_func(u16 base, u8 offset, u8 rw_flag,
248 u8 *data)
249{
250 u32 addr = base + offset;
251
252 if (rw_flag == 0)
253 outb(*data, addr);
254 else
255 *data = inb(addr);
256}
257
258static void mlxcpld_led_store_hw(u8 mask, u8 off, u8 vset)
259{
260 u8 nib, val;
261
262 /*
263 * Each LED is controlled through low or high nibble of the relevant
264 * CPLD register. Register offset is specified by off parameter.
265 * Parameter vset provides color code: 0x0 for off, 0x5 for solid red,
266 * 0x6 for 3Hz blink red, 0xd for solid green, 0xe for 3Hz blink
267 * green.
268 * Parameter mask specifies which nibble is used for specific LED: mask
269 * 0xf0 - lower nibble is to be used (bits from 0 to 3), mask 0x0f -
270 * higher nibble (bits from 4 to 7).
271 */
272 spin_lock(&mlxcpld_led->lock);
273 mlxcpld_led_bus_access_func(MLXPLAT_CPLD_LPC_REG_BASE_ADRR, off, 1,
274 &val);
275 nib = (mask == 0xf0) ? vset : (vset << 4);
276 val = (val & mask) | nib;
277 mlxcpld_led_bus_access_func(MLXPLAT_CPLD_LPC_REG_BASE_ADRR, off, 0,
278 &val);
279 spin_unlock(&mlxcpld_led->lock);
280}
281
282static void mlxcpld_led_brightness_set(struct led_classdev *led,
283 enum led_brightness value)
284{
285 struct mlxcpld_led_priv *pled = cdev_to_priv(led);
286
287 if (value) {
288 mlxcpld_led_store_hw(pled->param.mask, pled->param.offset,
289 pled->param.base_color);
290 return;
291 }
292
293 mlxcpld_led_store_hw(pled->param.mask, pled->param.offset,
294 MLXCPLD_LED_IS_OFF);
295}
296
297static int mlxcpld_led_blink_set(struct led_classdev *led,
298 unsigned long *delay_on,
299 unsigned long *delay_off)
300{
301 struct mlxcpld_led_priv *pled = cdev_to_priv(led);
302
303 /*
304 * HW supports two types of blinking: full (6Hz) and half (3Hz).
305 * For delay on/off zero default setting 3Hz is used.
306 */
307 if (!(*delay_on == 0 && *delay_off == 0) &&
308 !(*delay_on == MLXCPLD_LED_BLINK_3HZ &&
309 *delay_off == MLXCPLD_LED_BLINK_3HZ) &&
310 !(*delay_on == MLXCPLD_LED_BLINK_6HZ &&
311 *delay_off == MLXCPLD_LED_BLINK_6HZ))
312 return -EINVAL;
313
314 if (*delay_on == MLXCPLD_LED_BLINK_6HZ)
315 mlxcpld_led_store_hw(pled->param.mask, pled->param.offset,
316 pled->param.base_color +
317 MLXCPLD_LED_OFFSET_FULL);
318 else
319 mlxcpld_led_store_hw(pled->param.mask, pled->param.offset,
320 pled->param.base_color +
321 MLXCPLD_LED_OFFSET_HALF);
322
323 return 0;
324}
325
326static int mlxcpld_led_config(struct device *dev,
327 struct mlxcpld_led_pdata *cpld)
328{
329 int i;
330 int err;
331
332 cpld->pled = devm_kzalloc(dev, sizeof(struct mlxcpld_led_priv) *
333 cpld->num_led_instances, GFP_KERNEL);
334 if (!cpld->pled)
335 return -ENOMEM;
336
337 for (i = 0; i < cpld->num_led_instances; i++) {
338 cpld->pled[i].cdev.name = cpld->profile[i].name;
339 cpld->pled[i].cdev.brightness = cpld->profile[i].brightness;
340 cpld->pled[i].cdev.max_brightness = 1;
341 cpld->pled[i].cdev.brightness_set = mlxcpld_led_brightness_set;
342 cpld->pled[i].cdev.blink_set = mlxcpld_led_blink_set;
343 cpld->pled[i].cdev.flags = LED_CORE_SUSPENDRESUME;
344 err = devm_led_classdev_register(dev, &cpld->pled[i].cdev);
345 if (err)
346 return err;
347
348 cpld->pled[i].param.offset = mlxcpld_led->profile[i].offset;
349 cpld->pled[i].param.mask = mlxcpld_led->profile[i].mask;
350 cpld->pled[i].param.base_color =
351 mlxcpld_led->profile[i].base_color;
352
353 if (mlxcpld_led->profile[i].brightness)
354 mlxcpld_led_brightness_set(&cpld->pled[i].cdev,
355 mlxcpld_led->profile[i].brightness);
356 }
357
358 return 0;
359}
360
361static int __init mlxcpld_led_probe(struct platform_device *pdev)
362{
363 enum mlxcpld_led_platform_types mlxcpld_led_plat =
364 mlxcpld_led_platform_check_sys_type();
365
366 mlxcpld_led = devm_kzalloc(&pdev->dev, sizeof(*mlxcpld_led),
367 GFP_KERNEL);
368 if (!mlxcpld_led)
369 return -ENOMEM;
370
371 mlxcpld_led->pdev = pdev;
372
373 switch (mlxcpld_led_plat) {
374 case MLXCPLD_LED_PLATFORM_MSN2100:
375 mlxcpld_led->profile = mlxcpld_led_msn2100_profile;
376 mlxcpld_led->num_led_instances =
377 ARRAY_SIZE(mlxcpld_led_msn2100_profile);
378 break;
379
380 default:
381 mlxcpld_led->profile = mlxcpld_led_default_profile;
382 mlxcpld_led->num_led_instances =
383 ARRAY_SIZE(mlxcpld_led_default_profile);
384 break;
385 }
386
387 spin_lock_init(&mlxcpld_led->lock);
388
389 return mlxcpld_led_config(&pdev->dev, mlxcpld_led);
390}
391
392static struct platform_driver mlxcpld_led_driver = {
393 .driver = {
394 .name = KBUILD_MODNAME,
395 },
396};
397
398static int __init mlxcpld_led_init(void)
399{
400 struct platform_device *pdev;
401 int err;
402
403 pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
404 if (IS_ERR(pdev)) {
405 pr_err("Device allocation failed\n");
406 return PTR_ERR(pdev);
407 }
408
409 err = platform_driver_probe(&mlxcpld_led_driver, mlxcpld_led_probe);
410 if (err) {
411 pr_err("Probe platform driver failed\n");
412 platform_device_unregister(pdev);
413 }
414
415 return err;
416}
417
418static void __exit mlxcpld_led_exit(void)
419{
420 platform_device_unregister(mlxcpld_led->pdev);
421 platform_driver_unregister(&mlxcpld_led_driver);
422}
423
424module_init(mlxcpld_led_init);
425module_exit(mlxcpld_led_exit);
426
427MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
428MODULE_DESCRIPTION("Mellanox board LED driver");
429MODULE_LICENSE("GPL v2");
430MODULE_ALIAS("platform:leds_mlxcpld");