LED updates for 4.13

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJZXUGpAAoJEL1qUBy3i3wmBdgP/jhpBsA9D+W4grLEzbTSTWSV
 GKm19egbgujyLWkTecs1ICtuPYQFI90xV2HqmoSsXa9BEZHErB7zbubBzPEqS4RW
 ghsqweaLllOe6LtHs/ZvgvTGILaivpvK1R9qawaqJi6Cmg0VZvG8ApQNNpQD6bnj
 YCknKetLK+pdcjVCTaG7hyf+Ess7ASrwiWwIBiU26K+X6p7YpilxT5AylYWH6erl
 s+Lr3U0As86Fj+/ELOgmYBMTO1phZ7r1FSR/sa7RTlfgEgJQxmgagCfAvPGH92K3
 gK0UKKKirzfU08nUliHeHqn1K9ZaTKS15bbRNHpzl3/be/oLCuN3kB/Y/ZWtPgOc
 pEaCkWn2+4TeChlznyEmmTAeJgKLOBlt8ffSlz+wWNNL9wjG/LVm0Gq/eO49rWsG
 fJVbAT/lnWQ5dVEXlzQbw4uKU8DZDpjChjkv7shLMcValUtysnJ/w3edl5Czyx0y
 s2ckFmWnmQwTd+//PoJYnfdywPc3NfpsJD2j2VrEc0unsodAszwrdHdFVmsSgAJY
 u6cbrrxWYakXUcV/6gKVybhdMpNsV4f2KDthxrZmN3JGetQU/zoNsMBrNJu30l3d
 Iifry+UlYNHoozITKyk1+J3atEF6YzMIhuJTP1ifN07tvo5WaSESPFuoJdxLFlyt
 4OZcjjWj+CGqZ6+RSUya
 =5JLc
 -----END PGP SIGNATURE-----

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

Pull LED updates from Jacek Anaszewski:
 "This time we're removing more than adding:

  Removed drivers:

    leds-versatile:
      - all users of the Versatile LED driver are deleted and replaced
        with the very generic leds-syscon

    leds-sead3:
      - SEAD3 is using the generic leds-syscon & regmap based
        register-bit-led driver

  LED class drivers improvements:

    ledtrig-gpio:
      - use threaded IRQ, which both simplifies the code because we can
        drop the workqueue indirection, and it enables using the trigger
        for GPIOs that work with threaded IRQs themselves
      - refresh LED state after GPIO change since the new GPIO may have
        a different state than the old one

    leds-lp55xx:
      - make various arrays static const

    leds-pca963x:
      - add bindings to invert polarity"

* tag 'leds_for_4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
  leds: lp55xx: make various arrays static const
  leds: Remove SEAD-3 driver
  leds: trigger: gpio: Use threaded IRQ
  leds: trigger: gpio: Refresh LED state after GPIO change
  leds: Delete obsolete Versatile driver
  leds: pca963x: Add bindings to invert polarity
This commit is contained in:
Linus Torvalds 2017-07-06 11:32:40 -07:00
commit 4f5dfdd290
9 changed files with 34 additions and 237 deletions

View File

@ -10,6 +10,7 @@ Optional properties:
- nxp,period-scale : In some configurations, the chip blinks faster than expected. - nxp,period-scale : In some configurations, the chip blinks faster than expected.
This parameter provides a scaling ratio (fixed point, decimal divided This parameter provides a scaling ratio (fixed point, decimal divided
by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x. by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x.
- nxp,inverted-out: invert the polarity of the generated PWM
Each led is represented as a sub-node of the nxp,pca963x device. Each led is represented as a sub-node of the nxp,pca963x device.

View File

@ -590,16 +590,6 @@ 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.
config LEDS_IS31FL319X config LEDS_IS31FL319X
tristate "LED Support for ISSI IS31FL319x I2C LED controller family" tristate "LED Support for ISSI IS31FL319x I2C LED controller family"
depends on LEDS_CLASS && I2C && OF depends on LEDS_CLASS && I2C && OF
@ -651,14 +641,6 @@ config LEDS_SYSCON
devices. This will only work with device tree enabled devices. This will only work with device tree enabled
devices. devices.
config LEDS_VERSATILE
tristate "LED support for the ARM Versatile and RealView"
depends on ARCH_REALVIEW || ARCH_VERSATILE
depends on LEDS_CLASS
help
This option enabled support for the LEDs on the ARM Versatile
and RealView boards. Say Y to enabled these.
config LEDS_PM8058 config LEDS_PM8058
tristate "LED Support for the Qualcomm PM8058 PMIC" tristate "LED Support for the Qualcomm PM8058 PMIC"
depends on MFD_PM8XXX depends on MFD_PM8XXX

View File

@ -62,11 +62,9 @@ obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o
obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o
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
obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o
obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o
obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o

View File

@ -168,13 +168,13 @@ static int lp5523_post_init_device(struct lp55xx_chip *chip)
static void lp5523_load_engine(struct lp55xx_chip *chip) static void lp5523_load_engine(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 mask[] = { static const u8 mask[] = {
[LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M, [LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M,
[LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M, [LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M,
[LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M, [LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M,
}; };
u8 val[] = { static const u8 val[] = {
[LP55XX_ENGINE_1] = LP5523_LOAD_ENG1, [LP55XX_ENGINE_1] = LP5523_LOAD_ENG1,
[LP55XX_ENGINE_2] = LP5523_LOAD_ENG2, [LP55XX_ENGINE_2] = LP5523_LOAD_ENG2,
[LP55XX_ENGINE_3] = LP5523_LOAD_ENG3, [LP55XX_ENGINE_3] = LP5523_LOAD_ENG3,
@ -188,7 +188,7 @@ static void lp5523_load_engine(struct lp55xx_chip *chip)
static void lp5523_load_engine_and_select_page(struct lp55xx_chip *chip) static void lp5523_load_engine_and_select_page(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 page_sel[] = { static const u8 page_sel[] = {
[LP55XX_ENGINE_1] = LP5523_PAGE_ENG1, [LP55XX_ENGINE_1] = LP5523_PAGE_ENG1,
[LP55XX_ENGINE_2] = LP5523_PAGE_ENG2, [LP55XX_ENGINE_2] = LP5523_PAGE_ENG2,
[LP55XX_ENGINE_3] = LP5523_PAGE_ENG3, [LP55XX_ENGINE_3] = LP5523_PAGE_ENG3,
@ -208,7 +208,7 @@ static void lp5523_stop_all_engines(struct lp55xx_chip *chip)
static void lp5523_stop_engine(struct lp55xx_chip *chip) static void lp5523_stop_engine(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 mask[] = { static const u8 mask[] = {
[LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M, [LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M,
[LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M, [LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M,
[LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M, [LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M,
@ -505,7 +505,7 @@ static int lp5523_load_mux(struct lp55xx_chip *chip, u16 mux, int nr)
{ {
struct lp55xx_engine *engine = &chip->engines[nr - 1]; struct lp55xx_engine *engine = &chip->engines[nr - 1];
int ret; int ret;
u8 mux_page[] = { static const u8 mux_page[] = {
[LP55XX_ENGINE_1] = LP5523_PAGE_MUX1, [LP55XX_ENGINE_1] = LP5523_PAGE_MUX1,
[LP55XX_ENGINE_2] = LP5523_PAGE_MUX2, [LP55XX_ENGINE_2] = LP5523_PAGE_MUX2,
[LP55XX_ENGINE_3] = LP5523_PAGE_MUX3, [LP55XX_ENGINE_3] = LP5523_PAGE_MUX3,

View File

@ -342,6 +342,12 @@ pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
if (of_property_read_u32(np, "nxp,period-scale", &chip->scaling)) if (of_property_read_u32(np, "nxp,period-scale", &chip->scaling))
chip->scaling = 1000; chip->scaling = 1000;
/* default to non-inverted output, unless inverted is specified */
if (of_property_read_bool(np, "nxp,inverted-out"))
pdata->dir = PCA963X_INVERTED;
else
pdata->dir = PCA963X_NORMAL;
return pdata; return pdata;
} }
@ -452,11 +458,18 @@ static int pca963x_probe(struct i2c_client *client,
i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4)); i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4));
if (pdata) { if (pdata) {
u8 mode2 = i2c_smbus_read_byte_data(pca963x->chip->client,
PCA963X_MODE2);
/* Configure output: open-drain or totem pole (push-pull) */ /* Configure output: open-drain or totem pole (push-pull) */
if (pdata->outdrv == PCA963X_OPEN_DRAIN) if (pdata->outdrv == PCA963X_OPEN_DRAIN)
i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01); mode2 |= 0x01;
else else
i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x05); mode2 |= 0x05;
/* Configure direction: normal or inverted */
if (pdata->dir == PCA963X_INVERTED)
mode2 |= 0x10;
i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2,
mode2);
} }
return 0; return 0;

View File

@ -1,78 +0,0 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
* Copyright (C) 2015 Imagination Technologies, Inc.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/err.h>
#include <linux/io.h>
#include <asm/mips-boards/sead3-addr.h>
static void sead3_pled_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
writel(value, (void __iomem *)SEAD3_CPLD_P_LED);
}
static void sead3_fled_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
writel(value, (void __iomem *)SEAD3_CPLD_F_LED);
}
static struct led_classdev sead3_pled = {
.name = "sead3::pled",
.brightness_set = sead3_pled_set,
.flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev sead3_fled = {
.name = "sead3::fled",
.brightness_set = sead3_fled_set,
.flags = LED_CORE_SUSPENDRESUME,
};
static int sead3_led_probe(struct platform_device *pdev)
{
int ret;
ret = led_classdev_register(&pdev->dev, &sead3_pled);
if (ret < 0)
return ret;
ret = led_classdev_register(&pdev->dev, &sead3_fled);
if (ret < 0)
led_classdev_unregister(&sead3_pled);
return ret;
}
static int sead3_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&sead3_pled);
led_classdev_unregister(&sead3_fled);
return 0;
}
static struct platform_driver sead3_led_driver = {
.probe = sead3_led_probe,
.remove = sead3_led_remove,
.driver = {
.name = "sead3-led",
},
};
module_platform_driver(sead3_led_driver);
MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
MODULE_DESCRIPTION("SEAD3 LED driver");
MODULE_LICENSE("GPL");

View File

@ -1,110 +0,0 @@
/*
* Driver for the 8 user LEDs found on the RealViews and Versatiles
* Based on DaVinci's DM365 board code
*
* License terms: GNU General Public License (GPL) version 2
* Author: Linus Walleij <triad@df.lth.se>
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
struct versatile_led {
void __iomem *base;
struct led_classdev cdev;
u8 mask;
};
/*
* The triggers lines up below will only be used if the
* LED triggers are compiled in.
*/
static const struct {
const char *name;
const char *trigger;
} versatile_leds[] = {
{ "versatile:0", "heartbeat", },
{ "versatile:1", "mmc0", },
{ "versatile:2", "cpu0" },
{ "versatile:3", "cpu1" },
{ "versatile:4", "cpu2" },
{ "versatile:5", "cpu3" },
{ "versatile:6", },
{ "versatile:7", },
};
static void versatile_led_set(struct led_classdev *cdev,
enum led_brightness b)
{
struct versatile_led *led = container_of(cdev,
struct versatile_led, cdev);
u32 reg = readl(led->base);
if (b != LED_OFF)
reg |= led->mask;
else
reg &= ~led->mask;
writel(reg, led->base);
}
static enum led_brightness versatile_led_get(struct led_classdev *cdev)
{
struct versatile_led *led = container_of(cdev,
struct versatile_led, cdev);
u32 reg = readl(led->base);
return (reg & led->mask) ? LED_FULL : LED_OFF;
}
static int versatile_leds_probe(struct platform_device *dev)
{
int i;
struct resource *res;
void __iomem *base;
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&dev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
/* All off */
writel(0, base);
for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) {
struct versatile_led *led;
led = kzalloc(sizeof(*led), GFP_KERNEL);
if (!led)
break;
led->base = base;
led->cdev.name = versatile_leds[i].name;
led->cdev.brightness_set = versatile_led_set;
led->cdev.brightness_get = versatile_led_get;
led->cdev.default_trigger = versatile_leds[i].trigger;
led->mask = BIT(i);
if (led_classdev_register(NULL, &led->cdev) < 0) {
kfree(led);
break;
}
}
return 0;
}
static struct platform_driver versatile_leds_driver = {
.driver = {
.name = "versatile-leds",
},
.probe = versatile_leds_probe,
};
module_platform_driver(versatile_leds_driver);
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("ARM Versatile LED driver");
MODULE_LICENSE("GPL v2");

View File

@ -14,14 +14,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "../leds.h" #include "../leds.h"
struct gpio_trig_data { struct gpio_trig_data {
struct led_classdev *led; struct led_classdev *led;
struct work_struct work;
unsigned desired_brightness; /* desired brightness when led is on */ unsigned desired_brightness; /* desired brightness when led is on */
unsigned inverted; /* true when gpio is inverted */ unsigned inverted; /* true when gpio is inverted */
@ -32,22 +30,8 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led)
{ {
struct led_classdev *led = _led; struct led_classdev *led = _led;
struct gpio_trig_data *gpio_data = led->trigger_data; struct gpio_trig_data *gpio_data = led->trigger_data;
/* just schedule_work since gpio_get_value can sleep */
schedule_work(&gpio_data->work);
return IRQ_HANDLED;
};
static void gpio_trig_work(struct work_struct *work)
{
struct gpio_trig_data *gpio_data = container_of(work,
struct gpio_trig_data, work);
int tmp; int tmp;
if (!gpio_data->gpio)
return;
tmp = gpio_get_value_cansleep(gpio_data->gpio); tmp = gpio_get_value_cansleep(gpio_data->gpio);
if (gpio_data->inverted) if (gpio_data->inverted)
tmp = !tmp; tmp = !tmp;
@ -61,6 +45,8 @@ static void gpio_trig_work(struct work_struct *work)
} else { } else {
led_set_brightness_nosleep(gpio_data->led, LED_OFF); led_set_brightness_nosleep(gpio_data->led, LED_OFF);
} }
return IRQ_HANDLED;
} }
static ssize_t gpio_trig_brightness_show(struct device *dev, static ssize_t gpio_trig_brightness_show(struct device *dev,
@ -120,7 +106,7 @@ static ssize_t gpio_trig_inverted_store(struct device *dev,
gpio_data->inverted = inverted; gpio_data->inverted = inverted;
/* After inverting, we need to update the LED. */ /* After inverting, we need to update the LED. */
schedule_work(&gpio_data->work); gpio_trig_irq(0, led);
return n; return n;
} }
@ -147,7 +133,6 @@ static ssize_t gpio_trig_gpio_store(struct device *dev,
ret = sscanf(buf, "%u", &gpio); ret = sscanf(buf, "%u", &gpio);
if (ret < 1) { if (ret < 1) {
dev_err(dev, "couldn't read gpio number\n"); dev_err(dev, "couldn't read gpio number\n");
flush_work(&gpio_data->work);
return -EINVAL; return -EINVAL;
} }
@ -161,8 +146,8 @@ static ssize_t gpio_trig_gpio_store(struct device *dev,
return n; return n;
} }
ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq, ret = request_threaded_irq(gpio_to_irq(gpio), NULL, gpio_trig_irq,
IRQF_SHARED | IRQF_TRIGGER_RISING IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led); | IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
if (ret) { if (ret) {
dev_err(dev, "request_irq failed with error %d\n", ret); dev_err(dev, "request_irq failed with error %d\n", ret);
@ -170,6 +155,8 @@ static ssize_t gpio_trig_gpio_store(struct device *dev,
if (gpio_data->gpio != 0) if (gpio_data->gpio != 0)
free_irq(gpio_to_irq(gpio_data->gpio), led); free_irq(gpio_to_irq(gpio_data->gpio), led);
gpio_data->gpio = gpio; gpio_data->gpio = gpio;
/* After changing the GPIO, we need to update the LED. */
gpio_trig_irq(0, led);
} }
return ret ? ret : n; return ret ? ret : n;
@ -199,7 +186,6 @@ static void gpio_trig_activate(struct led_classdev *led)
gpio_data->led = led; gpio_data->led = led;
led->trigger_data = gpio_data; led->trigger_data = gpio_data;
INIT_WORK(&gpio_data->work, gpio_trig_work);
led->activated = true; led->activated = true;
return; return;
@ -222,7 +208,6 @@ static void gpio_trig_deactivate(struct led_classdev *led)
device_remove_file(led->dev, &dev_attr_gpio); device_remove_file(led->dev, &dev_attr_gpio);
device_remove_file(led->dev, &dev_attr_inverted); device_remove_file(led->dev, &dev_attr_inverted);
device_remove_file(led->dev, &dev_attr_desired_brightness); device_remove_file(led->dev, &dev_attr_desired_brightness);
flush_work(&gpio_data->work);
if (gpio_data->gpio != 0) if (gpio_data->gpio != 0)
free_irq(gpio_to_irq(gpio_data->gpio), led); free_irq(gpio_to_irq(gpio_data->gpio), led);
kfree(gpio_data); kfree(gpio_data);

View File

@ -33,10 +33,16 @@ enum pca963x_blink_type {
PCA963X_HW_BLINK, PCA963X_HW_BLINK,
}; };
enum pca963x_direction {
PCA963X_NORMAL,
PCA963X_INVERTED,
};
struct pca963x_platform_data { struct pca963x_platform_data {
struct led_platform_data leds; struct led_platform_data leds;
enum pca963x_outdrv outdrv; enum pca963x_outdrv outdrv;
enum pca963x_blink_type blink_type; enum pca963x_blink_type blink_type;
enum pca963x_direction dir;
}; };
#endif /* __LINUX_PCA963X_H*/ #endif /* __LINUX_PCA963X_H*/