Commit e8a2a176 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'leds_for_4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds

Pull LED updates from Jacek Anaszewski:

 - Move the out-of-LED-tree led-sead3 driver to the LED subsystem.

 - Add 'invert' sysfs attribute to the heartbeat trigger.

 - Add Device Tree support to the leds-netxbig driver and add related DT
   nodes to the kirkwood-netxbig.dtsi and kirkwood-net5big.dts files.
   Remove static LED setup from the related board files.

 - Remove redundant brightness conversion operation from leds-netxbig.

 - Improve leds-bcm6328 driver: improve default-state handling, add more
   init configuration options, print invalid LED instead of warning only
   about maximum LED value.

 - Add a shutdown function for setting gpio-leds into off state when
   shutting down.

 - Fix DT flash timeout property naming in leds-aat1290.txt.

 - Switch to using devm prefixed version of led_classdev_register()
   (leds-cobalt-qube, leds-hp6xx, leds-ot200, leds-ipaq-micro,
   leds-netxbig, leds-locomo, leds-menf21bmc, leds-net48xx, leds-wrap).

 - Add missing of_node_put (leds-powernv, leds-bcm6358, leds-bcm6328,
   leds-88pm860x).

 - Coding style fixes and cleanups: led-class/led-core, leds-ipaq-micro.

* tag 'leds_for_4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds: (27 commits)
  leds: 88pm860x: add missing of_node_put
  leds: bcm6328: add missing of_node_put
  leds: bcm6358: add missing of_node_put
  powerpc/powernv: add missing of_node_put
  leds: leds-wrap.c: Use devm_led_classdev_register
  leds: aat1290: Fix property naming of flash-timeout-us
  leds: leds-net48xx: Use devm_led_classdev_register
  leds: leds-menf21bmc.c: Use devm_led_class_register
  leds: leds-locomo.c: Use devm_led_classdev_register
  leds: leds-gpio: add shutdown function
  Documentation: leds: update DT bindings for leds-bcm6328
  leds-bcm6328: add more init configuration options
  leds-bcm6328: simplify and improve default-state handling
  leds-bcm6328: print invalid LED
  leds: netxbig: set led_classdev max_brightness
  leds: netxbig: convert to use the devm_ functions
  ARM: mvebu: remove static LED setup for netxbig boards
  ARM: Kirkwood: add LED DT entries for netxbig boards
  leds: netxbig: add device tree binding
  leds: triggers: add invert to heartbeat
  ...
parents 5062ecdb ffdc307d
Binding for the GPIO extension bus found on some LaCie/Seagate boards
(Example: 2Big/5Big Network v2, 2Big NAS).
Required properties:
- compatible: "lacie,netxbig-gpio-ext".
- addr-gpios: GPIOs representing the address register (LSB -> MSB).
- data-gpios: GPIOs representing the data register (LSB -> MSB).
- enable-gpio: latches the new configuration (address, data) on raising edge.
Example:
netxbig_gpio_ext: netxbig-gpio-ext {
compatible = "lacie,netxbig-gpio-ext";
addr-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH
&gpio1 16 GPIO_ACTIVE_HIGH
&gpio1 17 GPIO_ACTIVE_HIGH>;
data-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH
&gpio1 13 GPIO_ACTIVE_HIGH
&gpio1 14 GPIO_ACTIVE_HIGH>;
enable-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
...@@ -27,9 +27,9 @@ Required properties of the LED child node: ...@@ -27,9 +27,9 @@ Required properties of the LED child node:
- flash-max-microamp : see Documentation/devicetree/bindings/leds/common.txt - flash-max-microamp : see Documentation/devicetree/bindings/leds/common.txt
Maximum flash LED supply current can be calculated using Maximum flash LED supply current can be calculated using
following formula: I = 1A * 162kohm / Rset. following formula: I = 1A * 162kohm / Rset.
- flash-timeout-us : see Documentation/devicetree/bindings/leds/common.txt - flash-max-timeout-us : see Documentation/devicetree/bindings/leds/common.txt
Maximum flash timeout can be calculated using following Maximum flash timeout can be calculated using following
formula: T = 8.82 * 10^9 * Ct. formula: T = 8.82 * 10^9 * Ct.
Optional properties of the LED child node: Optional properties of the LED child node:
- label : see Documentation/devicetree/bindings/leds/common.txt - label : see Documentation/devicetree/bindings/leds/common.txt
...@@ -54,7 +54,7 @@ aat1290 { ...@@ -54,7 +54,7 @@ aat1290 {
label = "aat1290-flash"; label = "aat1290-flash";
led-max-microamp = <520833>; led-max-microamp = <520833>;
flash-max-microamp = <1012500>; flash-max-microamp = <1012500>;
flash-timeout-us = <1940000>; flash-max-timeout-us = <1940000>;
}; };
}; };
......
...@@ -29,6 +29,14 @@ Required properties: ...@@ -29,6 +29,14 @@ Required properties:
Optional properties: Optional properties:
- brcm,serial-leds : Boolean, enables Serial LEDs. - brcm,serial-leds : Boolean, enables Serial LEDs.
Default : false Default : false
- brcm,serial-mux : Boolean, enables Serial LEDs multiplexing.
Default : false
- brcm,serial-clk-low : Boolean, makes clock signal active low.
Default : false
- brcm,serial-dat-low : Boolean, makes data signal active low.
Default : false
- brcm,serial-shift-inv : Boolean, inverts Serial LEDs shift direction.
Default : false
Each LED is represented as a sub-node of the brcm,bcm6328-leds device. Each LED is represented as a sub-node of the brcm,bcm6328-leds device.
...@@ -110,6 +118,8 @@ Scenario 2 : BCM63268 with Serial/GPHY0 LEDs ...@@ -110,6 +118,8 @@ Scenario 2 : BCM63268 with Serial/GPHY0 LEDs
#size-cells = <0>; #size-cells = <0>;
reg = <0x10001900 0x24>; reg = <0x10001900 0x24>;
brcm,serial-leds; brcm,serial-leds;
brcm,serial-dat-low;
brcm,serial-shift-inv;
gphy0_spd0@0 { gphy0_spd0@0 {
reg = <0>; reg = <0>;
......
Binding for the CPLD LEDs (GPIO extension bus) found on some LaCie/Seagate
boards (Example: 2Big/5Big Network v2, 2Big NAS).
Required properties:
- compatible: "lacie,netxbig-leds".
- gpio-ext: Phandle for the gpio-ext bus.
Optional properties:
- timers: Timer array. Each timer entry is represented by three integers:
Mode (gpio-ext bus), delay_on and delay_off.
Each LED is represented as a sub-node of the netxbig-leds device.
Required sub-node properties:
- mode-addr: Mode register address on gpio-ext bus.
- mode-val: Mode to value mapping. Each entry is represented by two integers:
A mode and the corresponding value on the gpio-ext bus.
- bright-addr: Brightness register address on gpio-ext bus.
- max-brightness: Maximum brightness value.
Optional sub-node properties:
- label: Name for this LED. If omitted, the label is taken from the node name.
- linux,default-trigger: Trigger assigned to the LED.
Example:
netxbig-leds {
compatible = "lacie,netxbig-leds";
gpio-ext = &gpio_ext;
timers = <NETXBIG_LED_TIMER1 500 500
NETXBIG_LED_TIMER2 500 1000>;
blue-power {
label = "netxbig:blue:power";
mode-addr = <0>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 1
NETXBIG_LED_TIMER1 3
NETXBIG_LED_TIMER2 7>;
bright-addr = <1>;
max-brightness = <7>;
};
red-power {
label = "netxbig:red:power";
mode-addr = <0>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <1>;
max-brightness = <7>;
};
blue-sata0 {
label = "netxbig:blue:sata0";
mode-addr = <3>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata0 {
label = "netxbig:red:sata0";
mode-addr = <3>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
blue-sata1 {
label = "netxbig:blue:sata1";
mode-addr = <4>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata1 {
label = "netxbig:red:sata1";
mode-addr = <4>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
};
...@@ -86,6 +86,66 @@ g762_clk: g762-oscillator { ...@@ -86,6 +86,66 @@ g762_clk: g762-oscillator {
clock-frequency = <32768>; clock-frequency = <32768>;
}; };
}; };
netxbig-leds {
blue-sata2 {
label = "netxbig:blue:sata2";
mode-addr = <5>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata2 {
label = "netxbig:red:sata2";
mode-addr = <5>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
blue-sata3 {
label = "netxbig:blue:sata3";
mode-addr = <6>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata3 {
label = "netxbig:red:sata3";
mode-addr = <6>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
blue-sata4 {
label = "netxbig:blue:sata4";
mode-addr = <7>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata4 {
label = "netxbig:red:sata4";
mode-addr = <7>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
};
}; };
&mdio { &mdio {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#include <dt-bindings/leds/leds-netxbig.h>
#include "kirkwood.dtsi" #include "kirkwood.dtsi"
#include "kirkwood-6281.dtsi" #include "kirkwood-6281.dtsi"
...@@ -105,6 +106,85 @@ regulator@1 { ...@@ -105,6 +106,85 @@ regulator@1 {
gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>; gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>;
}; };
}; };
netxbig_gpio_ext: netxbig-gpio-ext {
compatible = "lacie,netxbig-gpio-ext";
addr-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH
&gpio1 16 GPIO_ACTIVE_HIGH
&gpio1 17 GPIO_ACTIVE_HIGH>;
data-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH
&gpio1 13 GPIO_ACTIVE_HIGH
&gpio1 14 GPIO_ACTIVE_HIGH>;
enable-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
netxbig-leds {
compatible = "lacie,netxbig-leds";
gpio-ext = <&netxbig_gpio_ext>;
timers = <NETXBIG_LED_TIMER1 500 500
NETXBIG_LED_TIMER2 500 1000>;
blue-power {
label = "netxbig:blue:power";
mode-addr = <0>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 1
NETXBIG_LED_TIMER1 3
NETXBIG_LED_TIMER2 7>;
bright-addr = <1>;
max-brightness = <7>;
};
red-power {
label = "netxbig:red:power";
mode-addr = <0>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <1>;
max-brightness = <7>;
};
blue-sata0 {
label = "netxbig:blue:sata0";
mode-addr = <3>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata0 {
label = "netxbig:red:sata0";
mode-addr = <3>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
blue-sata1 {
label = "netxbig:blue:sata1";
mode-addr = <4>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 7
NETXBIG_LED_SATA 1
NETXBIG_LED_TIMER1 3>;
bright-addr = <2>;
max-brightness = <7>;
};
red-sata1 {
label = "netxbig:red:sata1";
mode-addr = <4>;
mode-val = <NETXBIG_LED_OFF 0
NETXBIG_LED_ON 2
NETXBIG_LED_TIMER1 4>;
bright-addr = <2>;
max-brightness = <7>;
};
};
}; };
&mdio { &mdio {
......
...@@ -117,11 +117,4 @@ config MACH_KIRKWOOD ...@@ -117,11 +117,4 @@ config MACH_KIRKWOOD
Say 'Y' here if you want your kernel to support boards based Say 'Y' here if you want your kernel to support boards based
on the Marvell Kirkwood device tree. on the Marvell Kirkwood device tree.
config MACH_NETXBIG
bool "LaCie 2Big and 5Big Network v2"
depends on MACH_KIRKWOOD
help
Say 'Y' here if you want your kernel to support the
LaCie 2Big and 5Big Network v2
endif endif
...@@ -13,4 +13,3 @@ endif ...@@ -13,4 +13,3 @@ endif
obj-$(CONFIG_MACH_DOVE) += dove.o obj-$(CONFIG_MACH_DOVE) += dove.o
obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o
obj-$(CONFIG_MACH_NETXBIG) += netxbig.o
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "kirkwood.h" #include "kirkwood.h"
#include "kirkwood-pm.h" #include "kirkwood-pm.h"
#include "common.h" #include "common.h"
#include "board.h"
static struct resource kirkwood_cpufreq_resources[] = { static struct resource kirkwood_cpufreq_resources[] = {
[0] = { [0] = {
...@@ -180,9 +179,6 @@ static void __init kirkwood_dt_init(void) ...@@ -180,9 +179,6 @@ static void __init kirkwood_dt_init(void)
kirkwood_pm_init(); kirkwood_pm_init();
kirkwood_dt_eth_fixup(); kirkwood_dt_eth_fixup();
if (of_machine_is_compatible("lacie,netxbig"))
netxbig_init();
of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL); of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
} }
......
/*
* arch/arm/mach-mvbu/board-netxbig.c
*
* LaCie 2Big and 5Big Network v2 board setup
*
* Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/leds-kirkwood-netxbig.h>
#include "common.h"
/*****************************************************************************
* GPIO extension LEDs
****************************************************************************/
/*
* The LEDs are controlled by a CPLD and can be configured through a GPIO
* extension bus:
*
* - address register : bit [0-2] -> GPIO [47-49]
* - data register : bit [0-2] -> GPIO [44-46]
* - enable register : GPIO 29
*/
static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
.addr = netxbig_v2_gpio_ext_addr,
.num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
.data = netxbig_v2_gpio_ext_data,
.num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
.enable = 29,
};
/*
* Address register selection:
*
* addr | register
* ----------------------------
* 0 | front LED
* 1 | front LED brightness
* 2 | SATA LED brightness
* 3 | SATA0 LED
* 4 | SATA1 LED
* 5 | SATA2 LED
* 6 | SATA3 LED
* 7 | SATA4 LED
*
* Data register configuration:
*
* data | LED brightness
* -------------------------------------------------
* 0 | min (off)
* - | -
* 7 | max
*
* data | front LED mode
* -------------------------------------------------
* 0 | fix off
* 1 | fix blue on
* 2 | fix red on
* 3 | blink blue on=1 sec and blue off=1 sec
* 4 | blink red on=1 sec and red off=1 sec
* 5 | blink blue on=2.5 sec and red on=0.5 sec
* 6 | blink blue on=1 sec and red on=1 sec
* 7 | blink blue on=0.5 sec and blue off=2.5 sec
*
* data | SATA LED mode
* -------------------------------------------------
* 0 | fix off
* 1 | SATA activity blink
* 2 | fix red on
* 3 | blink blue on=1 sec and blue off=1 sec
* 4 | blink red on=1 sec and red off=1 sec
* 5 | blink blue on=2.5 sec and red on=0.5 sec
* 6 | blink blue on=1 sec and red on=1 sec
* 7 | fix blue on
*/
static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
[NETXBIG_LED_OFF] = 0,
[NETXBIG_LED_ON] = 2,
[NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
[NETXBIG_LED_TIMER1] = 4,
[NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
};
static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
[NETXBIG_LED_OFF] = 0,
[NETXBIG_LED_ON] = 1,
[NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
[NETXBIG_LED_TIMER1] = 3,
[NETXBIG_LED_TIMER2] = 7,
};
static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
[NETXBIG_LED_OFF] = 0,
[NETXBIG_LED_ON] = 7,
[NETXBIG_LED_SATA] = 1,
[NETXBIG_LED_TIMER1] = 3,
[NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
};
static struct netxbig_led_timer netxbig_v2_led_timer[] = {
[0] = {
.delay_on = 500,
.delay_off = 500,
.mode = NETXBIG_LED_TIMER1,
},
[1] = {
.delay_on = 500,
.delay_off = 1000,
.mode = NETXBIG_LED_TIMER2,
},
};
#define NETXBIG_LED(_name, maddr, mval, baddr) \
{ .name = _name, \
.mode_addr = maddr, \
.mode_val = mval, \
.bright_addr = baddr }
static struct netxbig_led net2big_v2_leds_ctrl[] = {
NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1),
NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
};
static struct netxbig_led_platform_data net2big_v2_leds_data = {
.gpio_ext = &netxbig_v2_gpio_ext,
.timer = netxbig_v2_led_timer,
.num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
.leds = net2big_v2_leds_ctrl,
.num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl),
};
static struct netxbig_led net5big_v2_leds_ctrl[] = {
NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1),
NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata4", 7, netxbig_v2_red_mled, 2),
};
static struct netxbig_led_platform_data net5big_v2_leds_data = {
.gpio_ext = &netxbig_v2_gpio_ext,
.timer = netxbig_v2_led_timer,
.num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
.leds = net5big_v2_leds_ctrl,
.num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl),
};
static struct platform_device netxbig_v2_leds = {
.name = "leds-netxbig",
.id = -1,
.dev = {
.platform_data = &net2big_v2_leds_data,
},
};
void __init netxbig_init(void)
{
if (of_machine_is_compatible("lacie,net5big_v2"))
netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
platform_device_register(&netxbig_v2_leds);
}
...@@ -12,6 +12,4 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ ...@@ -12,6 +12,4 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \
sead3-int.o sead3-platform.o sead3-reset.o \ sead3-int.o sead3-platform.o sead3-reset.o \
sead3-setup.o sead3-time.o sead3-setup.o sead3-time.o
obj-y += leds-sead3.o
obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
...@@ -556,6 +556,16 @@ config LEDS_KTD2692 ...@@ -556,6 +556,16 @@ config LEDS_KTD2692
Say Y to enable this driver. Say Y to enable this driver.
config LEDS_SEAD3
tristate "LED support for the MIPS SEAD 3 board"
depends on LEDS_CLASS && MIPS_SEAD3
help
Say Y here to include support for the FLED and PLED LEDs on SEAD3 eval
boards.
This driver can also be built as a module. If so the module
will be called leds-sead3.
comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)"
config LEDS_BLINKM config LEDS_BLINKM
......
...@@ -65,6 +65,7 @@ obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o ...@@ -65,6 +65,7 @@ obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o
obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o
obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o
obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o
obj-$(CONFIG_LEDS_SEAD3) += leds-sead3.o
# LED SPI Drivers # LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
......
...@@ -102,70 +102,6 @@ static const struct attribute_group *led_groups[] = { ...@@ -102,70 +102,6 @@ static const struct attribute_group *led_groups[] = {
NULL, NULL,
}; };
static void led_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (void *)data;
unsigned long brightness;
unsigned long delay;
if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
led_set_brightness_async(led_cdev, LED_OFF);
return;
}
if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
return;
}
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
if (led_cdev->delayed_set_value) {
led_cdev->blink_brightness =
led_cdev->delayed_set_value;
led_cdev->delayed_set_value = 0;
}
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
*/
led_cdev->blink_brightness = brightness;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
led_set_brightness_async(led_cdev, brightness);
/* Return in next iteration if led is in one-shot mode and we are in
* the final blink state so that the led is toggled each delay_on +
* delay_off milliseconds in worst case.
*/
if (led_cdev->flags & LED_BLINK_ONESHOT) {
if (led_cdev->flags & LED_BLINK_INVERT) {
if (brightness)
led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
} else {
if (!brightness)
led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
}
}
mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
}
static void set_brightness_delayed(struct work_struct *ws)
{
struct led_classdev *led_cdev =
container_of(ws, struct led_classdev, set_brightness_work);
led_stop_software_blink(led_cdev);
led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
}
/** /**
* led_classdev_suspend - suspend an led_classdev. * led_classdev_suspend - suspend an led_classdev.
* @led_cdev: the led_classdev to suspend. * @led_cdev: the led_classdev to suspend.
...@@ -283,10 +219,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -283,10 +219,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
led_update_brightness(led_cdev); led_update_brightness(led_cdev);
INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); led_init_core(led_cdev);
setup_timer(&led_cdev->blink_timer, led_timer_function,
(unsigned long)led_cdev);
#ifdef CONFIG_LEDS_TRIGGERS #ifdef CONFIG_LEDS_TRIGGERS
led_trigger_set_default(led_cdev); led_trigger_set_default(led_cdev);
......
...@@ -25,6 +25,70 @@ EXPORT_SYMBOL_GPL(leds_list_lock); ...@@ -25,6 +25,70 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
LIST_HEAD(leds_list); LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list); EXPORT_SYMBOL_GPL(leds_list);
static void led_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (void *)data;
unsigned long brightness;
unsigned long delay;
if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
led_set_brightness_async(led_cdev, LED_OFF);
return;
}
if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
return;
}
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
if (led_cdev->delayed_set_value) {
led_cdev->blink_brightness =
led_cdev->delayed_set_value;
led_cdev->delayed_set_value = 0;
}
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
*/
led_cdev->blink_brightness = brightness;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
led_set_brightness_async(led_cdev, brightness);
/* Return in next iteration if led is in one-shot mode and we are in
* the final blink state so that the led is toggled each delay_on +
* delay_off milliseconds in worst case.
*/
if (led_cdev->flags & LED_BLINK_ONESHOT) {
if (led_cdev->flags & LED_BLINK_INVERT) {
if (brightness)
led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
} else {
if (!brightness)
led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
}
}
mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
}
static void set_brightness_delayed(struct work_struct *ws)
{
struct led_classdev *led_cdev =
container_of(ws, struct led_classdev, set_brightness_work);
led_stop_software_blink(led_cdev);
led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
}
static void led_set_software_blink(struct led_classdev *led_cdev, static void led_set_software_blink(struct led_classdev *led_cdev,
unsigned long delay_on, unsigned long delay_on,
unsigned long delay_off) unsigned long delay_off)
...@@ -72,6 +136,15 @@ static void led_blink_setup(struct led_classdev *led_cdev, ...@@ -72,6 +136,15 @@ static void led_blink_setup(struct led_classdev *led_cdev,
led_set_software_blink(led_cdev, *delay_on, *delay_off); led_set_software_blink(led_cdev, *delay_on, *delay_off);
} }
void led_init_core(struct led_classdev *led_cdev)
{
INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
setup_timer(&led_cdev->blink_timer, led_timer_function,
(unsigned long)led_cdev);
}
EXPORT_SYMBOL_GPL(led_init_core);
void led_blink_set(struct led_classdev *led_cdev, void led_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on, unsigned long *delay_on,
unsigned long *delay_off) unsigned long *delay_off)
......
...@@ -142,6 +142,7 @@ static int pm860x_led_dt_init(struct platform_device *pdev, ...@@ -142,6 +142,7 @@ static int pm860x_led_dt_init(struct platform_device *pdev,
of_property_read_u32(np, "marvell,88pm860x-iset", of_property_read_u32(np, "marvell,88pm860x-iset",
&iset); &iset);
data->iset = PM8606_LED_CURRENT(iset); data->iset = PM8606_LED_CURRENT(iset);
of_node_put(np);
break; break;
} }
} }
......
...@@ -41,6 +41,11 @@ ...@@ -41,6 +41,11 @@
#define BCM6328_SERIAL_LED_SHIFT_DIR BIT(16) #define BCM6328_SERIAL_LED_SHIFT_DIR BIT(16)
#define BCM6328_LED_SHIFT_TEST BIT(30) #define BCM6328_LED_SHIFT_TEST BIT(30)
#define BCM6328_LED_TEST BIT(31) #define BCM6328_LED_TEST BIT(31)
#define BCM6328_INIT_MASK (BCM6328_SERIAL_LED_EN | \
BCM6328_SERIAL_LED_MUX | \
BCM6328_SERIAL_LED_CLK_NPOL | \
BCM6328_SERIAL_LED_DATA_PPOL | \
BCM6328_SERIAL_LED_SHIFT_DIR)
#define BCM6328_LED_MODE_MASK 3 #define BCM6328_LED_MODE_MASK 3
#define BCM6328_LED_MODE_OFF 0 #define BCM6328_LED_MODE_OFF 0
...@@ -281,11 +286,10 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg, ...@@ -281,11 +286,10 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
"linux,default-trigger", "linux,default-trigger",
NULL); NULL);
spin_lock_irqsave(lock, flags);
if (!of_property_read_string(nc, "default-state", &state)) { if (!of_property_read_string(nc, "default-state", &state)) {
spin_lock_irqsave(lock, flags);
if (!strcmp(state, "on")) { if (!strcmp(state, "on")) {
led->cdev.brightness = LED_FULL; led->cdev.brightness = LED_FULL;
bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
} else if (!strcmp(state, "keep")) { } else if (!strcmp(state, "keep")) {
void __iomem *mode; void __iomem *mode;
unsigned long val, shift; unsigned long val, shift;
...@@ -296,21 +300,28 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg, ...@@ -296,21 +300,28 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
else else
mode = mem + BCM6328_REG_MODE_LO; mode = mem + BCM6328_REG_MODE_LO;
val = bcm6328_led_read(mode) >> (shift % 16); val = bcm6328_led_read(mode) >>
BCM6328_LED_SHIFT(shift % 16);
val &= BCM6328_LED_MODE_MASK; val &= BCM6328_LED_MODE_MASK;
if (val == BCM6328_LED_MODE_ON) if ((led->active_low && val == BCM6328_LED_MODE_ON) ||
(!led->active_low && val == BCM6328_LED_MODE_OFF))
led->cdev.brightness = LED_FULL; led->cdev.brightness = LED_FULL;
else { else
led->cdev.brightness = LED_OFF; led->cdev.brightness = LED_OFF;
bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
}
} else { } else {
led->cdev.brightness = LED_OFF; led->cdev.brightness = LED_OFF;
bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
} }
spin_unlock_irqrestore(lock, flags); } else {
led->cdev.brightness = LED_OFF;
} }
if ((led->active_low && led->cdev.brightness == LED_FULL) ||
(!led->active_low && led->cdev.brightness == LED_OFF))
bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
else
bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
spin_unlock_irqrestore(lock, flags);
led->cdev.brightness_set = bcm6328_led_set; led->cdev.brightness_set = bcm6328_led_set;
led->cdev.blink_set = bcm6328_blink_set; led->cdev.blink_set = bcm6328_blink_set;
...@@ -360,9 +371,17 @@ static int bcm6328_leds_probe(struct platform_device *pdev) ...@@ -360,9 +371,17 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_LO, 0); bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_LO, 0);
val = bcm6328_led_read(mem + BCM6328_REG_INIT); val = bcm6328_led_read(mem + BCM6328_REG_INIT);
val &= ~BCM6328_SERIAL_LED_EN; val &= ~(BCM6328_INIT_MASK);
if (of_property_read_bool(np, "brcm,serial-leds")) if (of_property_read_bool(np, "brcm,serial-leds"))
val |= BCM6328_SERIAL_LED_EN; val |= BCM6328_SERIAL_LED_EN;
if (of_property_read_bool(np, "brcm,serial-mux"))
val |= BCM6328_SERIAL_LED_MUX;
if (of_property_read_bool(np, "brcm,serial-clk-low"))
val |= BCM6328_SERIAL_LED_CLK_NPOL;
if (!of_property_read_bool(np, "brcm,serial-dat-low"))
val |= BCM6328_SERIAL_LED_DATA_PPOL;
if (!of_property_read_bool(np, "brcm,serial-shift-inv"))
val |= BCM6328_SERIAL_LED_SHIFT_DIR;
bcm6328_led_write(mem + BCM6328_REG_INIT, val); bcm6328_led_write(mem + BCM6328_REG_INIT, val);
for_each_available_child_of_node(np, child) { for_each_available_child_of_node(np, child) {
...@@ -373,7 +392,7 @@ static int bcm6328_leds_probe(struct platform_device *pdev) ...@@ -373,7 +392,7 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
continue; continue;
if (reg >= BCM6328_LED_MAX_COUNT) { if (reg >= BCM6328_LED_MAX_COUNT) {
dev_err(dev, "invalid LED (>= %d)\n", dev_err(dev, "invalid LED (%u >= %d)\n", reg,
BCM6328_LED_MAX_COUNT); BCM6328_LED_MAX_COUNT);
continue; continue;
} }
...@@ -384,8 +403,10 @@ static int bcm6328_leds_probe(struct platform_device *pdev) ...@@ -384,8 +403,10 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
rc = bcm6328_led(dev, child, reg, mem, lock, rc = bcm6328_led(dev, child, reg, mem, lock,
blink_leds, blink_delay); blink_leds, blink_delay);
if (rc < 0) if (rc < 0) {
of_node_put(child);
return rc; return rc;
}
} }
return 0; return 0;
......
...@@ -215,8 +215,10 @@ static int bcm6358_leds_probe(struct platform_device *pdev) ...@@ -215,8 +215,10 @@ static int bcm6358_leds_probe(struct platform_device *pdev)
} }
rc = bcm6358_led(dev, child, reg, mem, lock); rc = bcm6358_led(dev, child, reg, mem, lock);
if (rc < 0) if (rc < 0) {
of_node_put(child);
return rc; return rc;
}
} }
return 0; return 0;
......
...@@ -36,7 +36,6 @@ static struct led_classdev qube_front_led = { ...@@ -36,7 +36,6 @@ static struct led_classdev qube_front_led = {
static int cobalt_qube_led_probe(struct platform_device *pdev) static int cobalt_qube_led_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int retval;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) if (!res)
...@@ -49,31 +48,11 @@ static int cobalt_qube_led_probe(struct platform_device *pdev) ...@@ -49,31 +48,11 @@ static int cobalt_qube_led_probe(struct platform_device *pdev)
led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT; led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
writeb(led_value, led_port); writeb(led_value, led_port);
retval = led_classdev_register(&pdev->dev, &qube_front_led); return devm_led_classdev_register(&pdev->dev, &qube_front_led);
if (retval)
goto err_null;
return 0;
err_null:
led_port = NULL;
return retval;
}
static int cobalt_qube_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&qube_front_led);
if (led_port)
led_port = NULL;
return 0;
} }
static struct platform_driver cobalt_qube_led_driver = { static struct platform_driver cobalt_qube_led_driver = {
.probe = cobalt_qube_led_probe, .probe = cobalt_qube_led_probe,
.remove = cobalt_qube_led_remove,
.driver = { .driver = {
.name = "cobalt-qube-leds", .name = "cobalt-qube-leds",
}, },
......
...@@ -291,9 +291,22 @@ static int gpio_led_remove(struct platform_device *pdev) ...@@ -291,9 +291,22 @@ static int gpio_led_remove(struct platform_device *pdev)
return 0; return 0;
} }
static void gpio_led_shutdown(struct platform_device *pdev)
{
struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
int i;
for (i = 0; i < priv->num_leds; i++) {
struct gpio_led_data *led = &priv->leds[i];
gpio_led_set(&led->cdev, LED_OFF);
}
}
static struct platform_driver gpio_led_driver = { static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe, .probe = gpio_led_probe,
.remove = gpio_led_remove, .remove = gpio_led_remove,
.shutdown = gpio_led_shutdown,
.driver = { .driver = {
.name = "leds-gpio", .name = "leds-gpio",
.of_match_table = of_gpio_leds_match, .of_match_table = of_gpio_leds_match,
......
...@@ -59,28 +59,15 @@ static int hp6xxled_probe(struct platform_device *pdev) ...@@ -59,28 +59,15 @@ static int hp6xxled_probe(struct platform_device *pdev)
{ {
int ret; int ret;
ret = led_classdev_register(&pdev->dev, &hp6xx_red_led); ret = devm_led_classdev_register(&pdev->dev, &hp6xx_red_led);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = led_classdev_register(&pdev->dev, &hp6xx_green_led); return devm_led_classdev_register(&pdev->dev, &hp6xx_green_led);
if (ret < 0)
led_classdev_unregister(&hp6xx_red_led);
return ret;
}
static int hp6xxled_remove(struct platform_device *pdev)
{
led_classdev_unregister(&hp6xx_red_led);
led_classdev_unregister(&hp6xx_green_led);
return 0;
} }
static struct platform_driver hp6xxled_driver = { static struct platform_driver hp6xxled_driver = {
.probe = hp6xxled_probe, .probe = hp6xxled_probe,
.remove = hp6xxled_remove,
.driver = { .driver = {
.name = "hp6xx-led", .name = "hp6xx-led",
}, },
......
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
#define LED_YELLOW 0x00 #define LED_YELLOW 0x00
#define LED_GREEN 0x01 #define LED_GREEN 0x01
#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */ #define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */
#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */ #define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */ #define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
static void micro_leds_brightness_set(struct led_classdev *led_cdev, static void micro_leds_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value) enum led_brightness value)
...@@ -79,14 +79,14 @@ static int micro_leds_blink_set(struct led_classdev *led_cdev, ...@@ -79,14 +79,14 @@ static int micro_leds_blink_set(struct led_classdev *led_cdev,
}; };
msg.tx_data[0] = LED_GREEN; msg.tx_data[0] = LED_GREEN;
if (*delay_on > IPAQ_LED_MAX_DUTY || if (*delay_on > IPAQ_LED_MAX_DUTY ||
*delay_off > IPAQ_LED_MAX_DUTY) *delay_off > IPAQ_LED_MAX_DUTY)
return -EINVAL; return -EINVAL;
if (*delay_on == 0 && *delay_off == 0) { if (*delay_on == 0 && *delay_off == 0) {
*delay_on = 100; *delay_on = 100;
*delay_off = 100; *delay_off = 100;
} }
msg.tx_data[1] = 0; msg.tx_data[1] = 0;
if (*delay_on >= IPAQ_LED_MAX_DUTY) if (*delay_on >= IPAQ_LED_MAX_DUTY)
...@@ -111,7 +111,7 @@ static int micro_leds_probe(struct platform_device *pdev) ...@@ -111,7 +111,7 @@ static int micro_leds_probe(struct platform_device *pdev)
{ {
int ret; int ret;
ret = led_classdev_register(&pdev->dev, &micro_led); ret = devm_led_classdev_register(&pdev->dev, &micro_led);
if (ret) { if (ret) {
dev_err(&pdev->dev, "registering led failed: %d\n", ret); dev_err(&pdev->dev, "registering led failed: %d\n", ret);
return ret; return ret;
...@@ -121,18 +121,11 @@ static int micro_leds_probe(struct platform_device *pdev) ...@@ -121,18 +121,11 @@ static int micro_leds_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int micro_leds_remove(struct platform_device *pdev)
{
led_classdev_unregister(&micro_led);
return 0;
}
static struct platform_driver micro_leds_device_driver = { static struct platform_driver micro_leds_device_driver = {
.driver = { .driver = {
.name = "ipaq-micro-leds", .name = "ipaq-micro-leds",
}, },
.probe = micro_leds_probe, .probe = micro_leds_probe,
.remove = micro_leds_remove,
}; };
module_platform_driver(micro_leds_device_driver); module_platform_driver(micro_leds_device_driver);
......
...@@ -59,23 +59,13 @@ static int locomoled_probe(struct locomo_dev *ldev) ...@@ -59,23 +59,13 @@ static int locomoled_probe(struct locomo_dev *ldev)
{ {
int ret; int ret;
ret = led_classdev_register(&ldev->dev, &locomo_led0); ret = devm_led_classdev_register(&ldev->dev, &locomo_led0);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = led_classdev_register(&ldev->dev, &locomo_led1); return devm_led_classdev_register(&ldev->dev, &locomo_led1);
if (ret < 0)
led_classdev_unregister(&locomo_led0);
return ret;
} }
static int locomoled_remove(struct locomo_dev *dev)
{
led_classdev_unregister(&locomo_led0);
led_classdev_unregister(&locomo_led1);
return 0;
}
static struct locomo_driver locomoled_driver = { static struct locomo_driver locomoled_driver = {
.drv = { .drv = {
...@@ -83,7 +73,6 @@ static struct locomo_driver locomoled_driver = { ...@@ -83,7 +73,6 @@ static struct locomo_driver locomoled_driver = {
}, },
.devid = LOCOMO_DEVID_LED, .devid = LOCOMO_DEVID_LED,
.probe = locomoled_probe, .probe = locomoled_probe,
.remove = locomoled_remove,
}; };
static int __init locomoled_init(void) static int __init locomoled_init(void)
......
...@@ -87,36 +87,20 @@ static int menf21bmc_led_probe(struct platform_device *pdev) ...@@ -87,36 +87,20 @@ static int menf21bmc_led_probe(struct platform_device *pdev)
leds[i].cdev.name = leds[i].name; leds[i].cdev.name = leds[i].name;
leds[i].cdev.brightness_set = menf21bmc_led_set; leds[i].cdev.brightness_set = menf21bmc_led_set;
leds[i].i2c_client = i2c_client; leds[i].i2c_client = i2c_client;
ret = led_classdev_register(&pdev->dev, &leds[i].cdev); ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
if (ret < 0) if (ret < 0) {
goto err_free_leds; dev_err(&pdev->dev, "failed to register LED device\n");
return ret;
}
} }
dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n"); dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n");
return 0; return 0;
err_free_leds:
dev_err(&pdev->dev, "failed to register LED device\n");
for (i = i - 1; i >= 0; i--)
led_classdev_unregister(&leds[i].cdev);
return ret;
}
static int menf21bmc_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(leds); i++)
led_classdev_unregister(&leds[i].cdev);
return 0;
} }
static struct platform_driver menf21bmc_led = { static struct platform_driver menf21bmc_led = {
.probe = menf21bmc_led_probe, .probe = menf21bmc_led_probe,
.remove = menf21bmc_led_remove,
.driver = { .driver = {
.name = "menf21bmc_led", .name = "menf21bmc_led",
}, },
......
...@@ -39,18 +39,11 @@ static struct led_classdev net48xx_error_led = { ...@@ -39,18 +39,11 @@ static struct led_classdev net48xx_error_led = {
static int net48xx_led_probe(struct platform_device *pdev) static int net48xx_led_probe(struct platform_device *pdev)
{ {
return led_classdev_register(&pdev->dev, &net48xx_error_led); return devm_led_classdev_register(&pdev->dev, &net48xx_error_led);
}
static int net48xx_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&net48xx_error_led);
return 0;
} }
static struct platform_driver net48xx_led_driver = { static struct platform_driver net48xx_led_driver = {
.probe = net48xx_led_probe, .probe = net48xx_led_probe,
.remove = net48xx_led_remove,
.driver = { .driver = {
.name = DRVNAME, .name = DRVNAME,
}, },
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/platform_data/leds-kirkwood-netxbig.h> #include <linux/platform_data/leds-kirkwood-netxbig.h>
...@@ -70,7 +71,8 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, ...@@ -70,7 +71,8 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
spin_unlock_irqrestore(&gpio_ext_lock, flags); spin_unlock_irqrestore(&gpio_ext_lock, flags);
} }
static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) static int gpio_ext_init(struct platform_device *pdev,
struct netxbig_gpio_ext *gpio_ext)
{ {
int err; int err;
int i; int i;
...@@ -80,46 +82,28 @@ static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) ...@@ -80,46 +82,28 @@ static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
/* Configure address GPIOs. */ /* Configure address GPIOs. */
for (i = 0; i < gpio_ext->num_addr; i++) { for (i = 0; i < gpio_ext->num_addr; i++) {
err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW, err = devm_gpio_request_one(&pdev->dev, gpio_ext->addr[i],
"GPIO extension addr"); GPIOF_OUT_INIT_LOW,
"GPIO extension addr");
if (err) if (err)
goto err_free_addr; return err;
} }
/* Configure data GPIOs. */ /* Configure data GPIOs. */
for (i = 0; i < gpio_ext->num_data; i++) { for (i = 0; i < gpio_ext->num_data; i++) {
err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW, err = devm_gpio_request_one(&pdev->dev, gpio_ext->data[i],
"GPIO extension data"); GPIOF_OUT_INIT_LOW,
"GPIO extension data");
if (err) if (err)
goto err_free_data; return err;
} }
/* Configure "enable select" GPIO. */ /* Configure "enable select" GPIO. */
err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW, err = devm_gpio_request_one(&pdev->dev, gpio_ext->enable,
"GPIO extension enable"); GPIOF_OUT_INIT_LOW,
"GPIO extension enable");
if (err) if (err)
goto err_free_data; return err;
return 0; return 0;
err_free_data:
for (i = i - 1; i >= 0; i--)
gpio_free(gpio_ext->data[i]);
i = gpio_ext->num_addr;
err_free_addr:
for (i = i - 1; i >= 0; i--)
gpio_free(gpio_ext->addr[i]);
return err;
}
static void gpio_ext_free(struct netxbig_gpio_ext *gpio_ext)
{
int i;
gpio_free(gpio_ext->enable);
for (i = gpio_ext->num_addr - 1; i >= 0; i--)
gpio_free(gpio_ext->addr[i]);
for (i = gpio_ext->num_data - 1; i >= 0; i--)
gpio_free(gpio_ext->data[i]);
} }
/* /*
...@@ -132,7 +116,6 @@ struct netxbig_led_data { ...@@ -132,7 +116,6 @@ struct netxbig_led_data {
int mode_addr; int mode_addr;
int *mode_val; int *mode_val;
int bright_addr; int bright_addr;
int bright_max;
struct netxbig_led_timer *timer; struct netxbig_led_timer *timer;
int num_timer; int num_timer;
enum netxbig_led_mode mode; enum netxbig_led_mode mode;
...@@ -194,7 +177,7 @@ static void netxbig_led_set(struct led_classdev *led_cdev, ...@@ -194,7 +177,7 @@ static void netxbig_led_set(struct led_classdev *led_cdev,
struct netxbig_led_data *led_dat = struct netxbig_led_data *led_dat =
container_of(led_cdev, struct netxbig_led_data, cdev); container_of(led_cdev, struct netxbig_led_data, cdev);
enum netxbig_led_mode mode; enum netxbig_led_mode mode;
int mode_val, bright_val; int mode_val;
int set_brightness = 1; int set_brightness = 1;
unsigned long flags; unsigned long flags;
...@@ -220,12 +203,9 @@ static void netxbig_led_set(struct led_classdev *led_cdev, ...@@ -220,12 +203,9 @@ static void netxbig_led_set(struct led_classdev *led_cdev,
* SATA LEDs. So, change the brightness setting for a single * SATA LEDs. So, change the brightness setting for a single
* SATA LED will affect all the others. * SATA LED will affect all the others.
*/ */
if (set_brightness) { if (set_brightness)
bright_val = DIV_ROUND_UP(value * led_dat->bright_max,
LED_FULL);
gpio_ext_set_value(led_dat->gpio_ext, gpio_ext_set_value(led_dat->gpio_ext,
led_dat->bright_addr, bright_val); led_dat->bright_addr, value);
}
spin_unlock_irqrestore(&led_dat->lock, flags); spin_unlock_irqrestore(&led_dat->lock, flags);
} }
...@@ -299,18 +279,11 @@ static struct attribute *netxbig_led_attrs[] = { ...@@ -299,18 +279,11 @@ static struct attribute *netxbig_led_attrs[] = {
}; };
ATTRIBUTE_GROUPS(netxbig_led); ATTRIBUTE_GROUPS(netxbig_led);
static void delete_netxbig_led(struct netxbig_led_data *led_dat) static int create_netxbig_led(struct platform_device *pdev,
struct netxbig_led_platform_data *pdata,
struct netxbig_led_data *led_dat,
const struct netxbig_led *template)
{ {
led_classdev_unregister(&led_dat->cdev);
}
static int
create_netxbig_led(struct platform_device *pdev,
struct netxbig_led_data *led_dat,
const struct netxbig_led *template)
{
struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
spin_lock_init(&led_dat->lock); spin_lock_init(&led_dat->lock);
led_dat->gpio_ext = pdata->gpio_ext; led_dat->gpio_ext = pdata->gpio_ext;
led_dat->cdev.name = template->name; led_dat->cdev.name = template->name;
...@@ -329,11 +302,11 @@ create_netxbig_led(struct platform_device *pdev, ...@@ -329,11 +302,11 @@ create_netxbig_led(struct platform_device *pdev,
*/ */
led_dat->sata = 0; led_dat->sata = 0;
led_dat->cdev.brightness = LED_OFF; led_dat->cdev.brightness = LED_OFF;
led_dat->cdev.max_brightness = template->bright_max;
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
led_dat->mode_addr = template->mode_addr; led_dat->mode_addr = template->mode_addr;
led_dat->mode_val = template->mode_val; led_dat->mode_val = template->mode_val;
led_dat->bright_addr = template->bright_addr; led_dat->bright_addr = template->bright_addr;
led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1;
led_dat->timer = pdata->timer; led_dat->timer = pdata->timer;
led_dat->num_timer = pdata->num_timer; led_dat->num_timer = pdata->num_timer;
/* /*
...@@ -343,67 +316,274 @@ create_netxbig_led(struct platform_device *pdev, ...@@ -343,67 +316,274 @@ create_netxbig_led(struct platform_device *pdev,
if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
led_dat->cdev.groups = netxbig_led_groups; led_dat->cdev.groups = netxbig_led_groups;
return led_classdev_register(&pdev->dev, &led_dat->cdev); return devm_led_classdev_register(&pdev->dev, &led_dat->cdev);
} }
static int netxbig_led_probe(struct platform_device *pdev) #ifdef CONFIG_OF_GPIO
static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
struct netxbig_gpio_ext *gpio_ext)
{ {
struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); int *addr, *data;
struct netxbig_led_data *leds_data; int num_addr, num_data;
int i;
int ret; int ret;
int i;
if (!pdata) ret = of_gpio_named_count(np, "addr-gpios");
return -EINVAL; if (ret < 0) {
dev_err(dev,
leds_data = devm_kzalloc(&pdev->dev, "Failed to count GPIOs in DT property addr-gpios\n");
sizeof(struct netxbig_led_data) * pdata->num_leds, GFP_KERNEL); return ret;
if (!leds_data) }
num_addr = ret;
addr = devm_kzalloc(dev, num_addr * sizeof(*addr), GFP_KERNEL);
if (!addr)
return -ENOMEM; return -ENOMEM;
ret = gpio_ext_init(pdata->gpio_ext); for (i = 0; i < num_addr; i++) {
if (ret < 0) ret = of_get_named_gpio(np, "addr-gpios", i);
if (ret < 0)
return ret;
addr[i] = ret;
}
gpio_ext->addr = addr;
gpio_ext->num_addr = num_addr;
ret = of_gpio_named_count(np, "data-gpios");
if (ret < 0) {
dev_err(dev,
"Failed to count GPIOs in DT property data-gpios\n");
return ret; return ret;
}
num_data = ret;
data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
for (i = 0; i < pdata->num_leds; i++) { for (i = 0; i < num_data; i++) {
ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]); ret = of_get_named_gpio(np, "data-gpios", i);
if (ret < 0) if (ret < 0)
goto err_free_leds; return ret;
data[i] = ret;
} }
gpio_ext->data = data;
gpio_ext->num_data = num_data;
platform_set_drvdata(pdev, leds_data); ret = of_get_named_gpio(np, "enable-gpio", 0);
if (ret < 0) {
dev_err(dev,
"Failed to get GPIO from DT property enable-gpio\n");
return ret;
}
gpio_ext->enable = ret;
return 0; return 0;
}
static int netxbig_leds_get_of_pdata(struct device *dev,
struct netxbig_led_platform_data *pdata)
{
struct device_node *np = dev->of_node;
struct device_node *gpio_ext_np;
struct device_node *child;
struct netxbig_gpio_ext *gpio_ext;
struct netxbig_led_timer *timers;
struct netxbig_led *leds, *led;
int num_timers;
int num_leds = 0;
int ret;
int i;
err_free_leds: /* GPIO extension */
for (i = i - 1; i >= 0; i--) gpio_ext_np = of_parse_phandle(np, "gpio-ext", 0);
delete_netxbig_led(&leds_data[i]); if (!gpio_ext_np) {
dev_err(dev, "Failed to get DT handle gpio-ext\n");
return -EINVAL;
}
gpio_ext_free(pdata->gpio_ext); gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL);
if (!gpio_ext)
return -ENOMEM;
ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext);
if (ret)
return ret;
of_node_put(gpio_ext_np);
pdata->gpio_ext = gpio_ext;
/* Timers (optional) */
ret = of_property_count_u32_elems(np, "timers");
if (ret > 0) {
if (ret % 3)
return -EINVAL;
num_timers = ret / 3;
timers = devm_kzalloc(dev, num_timers * sizeof(*timers),
GFP_KERNEL);
if (!timers)
return -ENOMEM;
for (i = 0; i < num_timers; i++) {
u32 tmp;
of_property_read_u32_index(np, "timers", 3 * i,
&timers[i].mode);
if (timers[i].mode >= NETXBIG_LED_MODE_NUM)
return -EINVAL;
of_property_read_u32_index(np, "timers",
3 * i + 1, &tmp);
timers[i].delay_on = tmp;
of_property_read_u32_index(np, "timers",
3 * i + 2, &tmp);
timers[i].delay_off = tmp;
}
pdata->timer = timers;
pdata->num_timer = num_timers;
}
/* LEDs */
num_leds = of_get_child_count(np);
if (!num_leds) {
dev_err(dev, "No LED subnodes found in DT\n");
return -ENODEV;
}
leds = devm_kzalloc(dev, num_leds * sizeof(*leds), GFP_KERNEL);
if (!leds)
return -ENOMEM;
led = leds;
for_each_child_of_node(np, child) {
const char *string;
int *mode_val;
int num_modes;
ret = of_property_read_u32(child, "mode-addr",
&led->mode_addr);
if (ret)
goto err_node_put;
ret = of_property_read_u32(child, "bright-addr",
&led->bright_addr);
if (ret)
goto err_node_put;
ret = of_property_read_u32(child, "max-brightness",
&led->bright_max);
if (ret)
goto err_node_put;
mode_val =
devm_kzalloc(dev,
NETXBIG_LED_MODE_NUM * sizeof(*mode_val),
GFP_KERNEL);
if (!mode_val) {
ret = -ENOMEM;
goto err_node_put;
}
for (i = 0; i < NETXBIG_LED_MODE_NUM; i++)
mode_val[i] = NETXBIG_LED_INVALID_MODE;
ret = of_property_count_u32_elems(child, "mode-val");
if (ret < 0 || ret % 2) {
ret = -EINVAL;
goto err_node_put;
}
num_modes = ret / 2;
if (num_modes > NETXBIG_LED_MODE_NUM) {
ret = -EINVAL;
goto err_node_put;
}
for (i = 0; i < num_modes; i++) {
int mode;
int val;
of_property_read_u32_index(child,
"mode-val", 2 * i, &mode);
of_property_read_u32_index(child,
"mode-val", 2 * i + 1, &val);
if (mode >= NETXBIG_LED_MODE_NUM) {
ret = -EINVAL;
goto err_node_put;
}
mode_val[mode] = val;
}
led->mode_val = mode_val;
if (!of_property_read_string(child, "label", &string))
led->name = string;
else
led->name = child->name;
if (!of_property_read_string(child,
"linux,default-trigger", &string))
led->default_trigger = string;
led++;
}
pdata->leds = leds;
pdata->num_leds = num_leds;
return 0;
err_node_put:
of_node_put(child);
return ret; return ret;
} }
static int netxbig_led_remove(struct platform_device *pdev) static const struct of_device_id of_netxbig_leds_match[] = {
{ .compatible = "lacie,netxbig-leds", },
{},
};
#else
static inline int
netxbig_leds_get_of_pdata(struct device *dev,
struct netxbig_led_platform_data *pdata)
{
return -ENODEV;
}
#endif /* CONFIG_OF_GPIO */
static int netxbig_led_probe(struct platform_device *pdev)
{ {
struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct netxbig_led_data *leds_data; struct netxbig_led_data *leds_data;
int i; int i;
int ret;
leds_data = platform_get_drvdata(pdev); if (!pdata) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata);
if (ret)
return ret;
}
leds_data = devm_kzalloc(&pdev->dev,
pdata->num_leds * sizeof(*leds_data),
GFP_KERNEL);
if (!leds_data)
return -ENOMEM;
for (i = 0; i < pdata->num_leds; i++) ret = gpio_ext_init(pdev, pdata->gpio_ext);
delete_netxbig_led(&leds_data[i]); if (ret < 0)
return ret;
gpio_ext_free(pdata->gpio_ext); for (i = 0; i < pdata->num_leds; i++) {
ret = create_netxbig_led(pdev, pdata,
&leds_data[i], &pdata->leds[i]);
if (ret < 0)
return ret;
}
return 0; return 0;
} }
static struct platform_driver netxbig_led_driver = { static struct platform_driver netxbig_led_driver = {
.probe = netxbig_led_probe, .probe = netxbig_led_probe,
.remove = netxbig_led_remove,
.driver = { .driver = {
.name = "leds-netxbig", .name = "leds-netxbig",
.of_match_table = of_match_ptr(of_netxbig_leds_match),
}, },
}; };
......
...@@ -124,9 +124,9 @@ static int ot200_led_probe(struct platform_device *pdev) ...@@ -124,9 +124,9 @@ static int ot200_led_probe(struct platform_device *pdev)
leds[i].cdev.name = leds[i].name; leds[i].cdev.name = leds[i].name;
leds[i].cdev.brightness_set = ot200_led_brightness_set; leds[i].cdev.brightness_set = ot200_led_brightness_set;
ret = led_classdev_register(&pdev->dev, &leds[i].cdev); ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
if (ret < 0) if (ret < 0)
goto err; return ret;
} }
leds_front = 0; /* turn off all front leds */ leds_front = 0; /* turn off all front leds */
...@@ -135,27 +135,10 @@ static int ot200_led_probe(struct platform_device *pdev) ...@@ -135,27 +135,10 @@ static int ot200_led_probe(struct platform_device *pdev)
outb(leds_back, 0x5a); outb(leds_back, 0x5a);
return 0; return 0;
err:
for (i = i - 1; i >= 0; i--)
led_classdev_unregister(&leds[i].cdev);
return ret;
}
static int ot200_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(leds); i++)
led_classdev_unregister(&leds[i].cdev);
return 0;
} }
static struct platform_driver ot200_led_driver = { static struct platform_driver ot200_led_driver = {
.probe = ot200_led_probe, .probe = ot200_led_probe,
.remove = ot200_led_remove,
.driver = { .driver = {
.name = "leds-ot200", .name = "leds-ot200",
}, },
......
...@@ -262,15 +262,19 @@ static int powernv_led_classdev(struct platform_device *pdev, ...@@ -262,15 +262,19 @@ static int powernv_led_classdev(struct platform_device *pdev,
while ((cur = of_prop_next_string(p, cur)) != NULL) { while ((cur = of_prop_next_string(p, cur)) != NULL) {
powernv_led = devm_kzalloc(dev, sizeof(*powernv_led), powernv_led = devm_kzalloc(dev, sizeof(*powernv_led),
GFP_KERNEL); GFP_KERNEL);
if (!powernv_led) if (!powernv_led) {
of_node_put(np);
return -ENOMEM; return -ENOMEM;
}
powernv_led->common = powernv_led_common; powernv_led->common = powernv_led_common;
powernv_led->loc_code = (char *)np->name; powernv_led->loc_code = (char *)np->name;
rc = powernv_led_create(dev, powernv_led, cur); rc = powernv_led_create(dev, powernv_led, cur);
if (rc) if (rc) {
of_node_put(np);
return rc; return rc;
}
} /* while end */ } /* while end */
} }
......
...@@ -59,6 +59,7 @@ static int sead3_led_remove(struct platform_device *pdev) ...@@ -59,6 +59,7 @@ static int sead3_led_remove(struct platform_device *pdev)
{ {
led_classdev_unregister(&sead3_pled); led_classdev_unregister(&sead3_pled);
led_classdev_unregister(&sead3_fled); led_classdev_unregister(&sead3_fled);
return 0; return 0;
} }
......
...@@ -76,39 +76,19 @@ static int wrap_led_probe(struct platform_device *pdev) ...@@ -76,39 +76,19 @@ static int wrap_led_probe(struct platform_device *pdev)
{ {
int ret; int ret;
ret = led_classdev_register(&pdev->dev, &wrap_power_led); ret = devm_led_classdev_register(&pdev->dev, &wrap_power_led);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = led_classdev_register(&pdev->dev, &wrap_error_led); ret = devm_led_classdev_register(&pdev->dev, &wrap_error_led);
if (ret < 0) if (ret < 0)
goto err1; return ret;
ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
if (ret < 0)
goto err2;
return ret;
err2:
led_classdev_unregister(&wrap_error_led);
err1:
led_classdev_unregister(&wrap_power_led);
return ret;
}
static int wrap_led_remove(struct platform_device *pdev) return devm_led_classdev_register(&pdev->dev, &wrap_extra_led);
{
led_classdev_unregister(&wrap_power_led);
led_classdev_unregister(&wrap_error_led);
led_classdev_unregister(&wrap_extra_led);
return 0;
} }
static struct platform_driver wrap_led_driver = { static struct platform_driver wrap_led_driver = {
.probe = wrap_led_probe, .probe = wrap_led_probe,
.remove = wrap_led_remove,
.driver = { .driver = {
.name = DRVNAME, .name = DRVNAME,
}, },
......
...@@ -44,6 +44,7 @@ static inline int led_get_brightness(struct led_classdev *led_cdev) ...@@ -44,6 +44,7 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
return led_cdev->brightness; return led_cdev->brightness;
} }
void led_init_core(struct led_classdev *led_cdev);
void led_stop_software_blink(struct led_classdev *led_cdev); void led_stop_software_blink(struct led_classdev *led_cdev);
extern struct rw_semaphore leds_list_lock; extern struct rw_semaphore leds_list_lock;
......
...@@ -27,6 +27,7 @@ struct heartbeat_trig_data { ...@@ -27,6 +27,7 @@ struct heartbeat_trig_data {
unsigned int phase; unsigned int phase;
unsigned int period; unsigned int period;
struct timer_list timer; struct timer_list timer;
unsigned int invert;
}; };
static void led_heartbeat_function(unsigned long data) static void led_heartbeat_function(unsigned long data)
...@@ -56,21 +57,27 @@ static void led_heartbeat_function(unsigned long data) ...@@ -56,21 +57,27 @@ static void led_heartbeat_function(unsigned long data)
msecs_to_jiffies(heartbeat_data->period); msecs_to_jiffies(heartbeat_data->period);
delay = msecs_to_jiffies(70); delay = msecs_to_jiffies(70);
heartbeat_data->phase++; heartbeat_data->phase++;
brightness = led_cdev->max_brightness; if (!heartbeat_data->invert)
brightness = led_cdev->max_brightness;
break; break;
case 1: case 1:
delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
heartbeat_data->phase++; heartbeat_data->phase++;
if (heartbeat_data->invert)
brightness = led_cdev->max_brightness;
break; break;
case 2: case 2:
delay = msecs_to_jiffies(70); delay = msecs_to_jiffies(70);
heartbeat_data->phase++; heartbeat_data->phase++;
brightness = led_cdev->max_brightness; if (!heartbeat_data->invert)
brightness = led_cdev->max_brightness;
break; break;
default: default:
delay = heartbeat_data->period - heartbeat_data->period / 4 - delay = heartbeat_data->period - heartbeat_data->period / 4 -
msecs_to_jiffies(70); msecs_to_jiffies(70);
heartbeat_data->phase = 0; heartbeat_data->phase = 0;
if (heartbeat_data->invert)
brightness = led_cdev->max_brightness;
break; break;
} }
...@@ -78,15 +85,50 @@ static void led_heartbeat_function(unsigned long data) ...@@ -78,15 +85,50 @@ static void led_heartbeat_function(unsigned long data)
mod_timer(&heartbeat_data->timer, jiffies + delay); mod_timer(&heartbeat_data->timer, jiffies + delay);
} }
static ssize_t led_invert_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
return sprintf(buf, "%u\n", heartbeat_data->invert);
}
static ssize_t led_invert_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
unsigned long state;
int ret;
ret = kstrtoul(buf, 0, &state);
if (ret)
return ret;
heartbeat_data->invert = !!state;
return size;
}
static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
static void heartbeat_trig_activate(struct led_classdev *led_cdev) static void heartbeat_trig_activate(struct led_classdev *led_cdev)
{ {
struct heartbeat_trig_data *heartbeat_data; struct heartbeat_trig_data *heartbeat_data;
int rc;
heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
if (!heartbeat_data) if (!heartbeat_data)
return; return;
led_cdev->trigger_data = heartbeat_data; led_cdev->trigger_data = heartbeat_data;
rc = device_create_file(led_cdev->dev, &dev_attr_invert);
if (rc) {
kfree(led_cdev->trigger_data);
return;
}
setup_timer(&heartbeat_data->timer, setup_timer(&heartbeat_data->timer,
led_heartbeat_function, (unsigned long) led_cdev); led_heartbeat_function, (unsigned long) led_cdev);
heartbeat_data->phase = 0; heartbeat_data->phase = 0;
...@@ -100,6 +142,7 @@ static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) ...@@ -100,6 +142,7 @@ static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
if (led_cdev->activated) { if (led_cdev->activated) {
del_timer_sync(&heartbeat_data->timer); del_timer_sync(&heartbeat_data->timer);
device_remove_file(led_cdev->dev, &dev_attr_invert);
kfree(heartbeat_data); kfree(heartbeat_data);
led_cdev->activated = false; led_cdev->activated = false;
} }
......
/* /*
* Board functions for Marvell System On Chip * This header provides constants for netxbig LED bindings.
*
* Copyright (C) 2014
*
* Andrew Lunn <andrew@lunn.ch>
* *
* This file is licensed under the terms of the GNU General Public * This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any * License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#ifndef __ARCH_MVEBU_BOARD_H #ifndef _DT_BINDINGS_LEDS_NETXBIG_H
#define __ARCH_MVEBU_BOARD_H #define _DT_BINDINGS_LEDS_NETXBIG_H
#define NETXBIG_LED_OFF 0
#define NETXBIG_LED_ON 1
#define NETXBIG_LED_SATA 2
#define NETXBIG_LED_TIMER1 3
#define NETXBIG_LED_TIMER2 4
#ifdef CONFIG_MACH_NETXBIG #endif /* _DT_BINDINGS_LEDS_NETXBIG_H */
void netxbig_init(void);
#else
static inline void netxbig_init(void) {};
#endif
#endif
...@@ -40,6 +40,7 @@ struct netxbig_led { ...@@ -40,6 +40,7 @@ struct netxbig_led {
int mode_addr; int mode_addr;
int *mode_val; int *mode_val;
int bright_addr; int bright_addr;
int bright_max;
}; };
struct netxbig_led_platform_data { struct netxbig_led_platform_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment