Re: [OpenWrt-Devel] [PATCH v5 4/5] ar71xx: add LED driver NU801

2015-11-21 Thread John Crispin
Hi,

1 comment inline

On 22/09/2015 19:07, Chris R Blake wrote:
> From: Chris R Blake 
> 
> The MR18 uses a 3-channel 16-bit PWM Constant Current Driver
> for its status LED.
> 
> Signed-off-by: Chris R Blake 
> ---
>  package/base-files/files/etc/init.d/led|   2 +-
>  .../linux/ar71xx/files/drivers/leds/leds-nu801.c   | 396 
> +
>  .../linux/ar71xx/files/include/linux/leds-nu801.h  |  38 ++
>  target/linux/ar71xx/modules.mk |  16 +
>  .../818-MIPS-ath79-add-nu801-led-driver.patch  |  26 ++
>  5 files changed, 477 insertions(+), 1 deletion(-)
>  create mode 100644 target/linux/ar71xx/files/drivers/leds/leds-nu801.c
>  create mode 100644 target/linux/ar71xx/files/include/linux/leds-nu801.h
>  create mode 100644 
> target/linux/ar71xx/patches-4.1/818-MIPS-ath79-add-nu801-led-driver.patch
> 
> diff --git a/package/base-files/files/etc/init.d/led 
> b/package/base-files/files/etc/init.d/led
> index 3f45732..84cd028 100755
> --- a/package/base-files/files/etc/init.d/led
> +++ b/package/base-files/files/etc/init.d/led
> @@ -44,7 +44,7 @@ load_led() {
>   ret="$?"
>  
>   [ $default = 1 ] &&
> - echo 1 >/sys/class/leds/${sysfs}/brightness
> + cat /sys/class/leds/${sysfs}/max_brightness > 
> /sys/class/leds/${sysfs}/brightness
>  
>   [ $ret = 0 ] || {
>   echo >&2 "Skipping trigger '$trigger' for led '$name' 
> due to missing kernel module"

this is a nice corner case i never considered before. however this part
of the patch need to go into its own patch file as it modifies a
different part of openwrt.

John


> diff --git a/target/linux/ar71xx/files/drivers/leds/leds-nu801.c 
> b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c
> new file mode 100644
> index 000..0dfc015
> --- /dev/null
> +++ b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c
> @@ -0,0 +1,396 @@
> +/*
> + * LED driver for NU801
> + *
> + * Kevin Paul Herbert
> + * Copyright (c) 2012, Meraki, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#define MAX_NAME_LENGTH 24
> +#define NUM_COLORS 3
> +
> +static const char * const led_nu801_colors[] = { "blue", "green", "red" };
> +
> +struct led_nu801_led_data {
> + struct led_classdev cdev;
> + struct led_nu801_data *controller;
> + enum led_brightness level;
> + char name[MAX_NAME_LENGTH];
> +};
> +
> +struct led_nu801_data {
> + unsigned cki;
> + unsigned sdi;
> + int lei;
> + struct delayed_work work;
> + struct led_nu801_led_data *led_chain;
> + int num_leds;
> + const char *device_name;
> + const char *name;
> + u32 ndelay;
> + atomic_t pending;
> +};
> +
> +static void led_nu801_work(struct work_struct *work)
> +{
> + struct led_nu801_data   *controller =
> + container_of(work, struct led_nu801_data, work.work);
> + struct led_nu801_led_data *led;
> + u16 bit;
> + u16 brightness;
> + int index;
> +
> + for (index = 0; index < controller->num_leds; index++) {
> + led = &controller->led_chain[index];
> + brightness = led->level << 8; /* To do: gamma correction */
> + for (bit = 0x8000; bit; bit = bit >> 1) {
> + gpio_set_value(controller->sdi,
> +(brightness & bit) != 0);
> + gpio_set_value(controller->cki, 1);
> + if (unlikely(((index == (controller->num_leds - 1)) &&
> +   (bit == 1) &&
> +   (controller->lei < 0 {
> + udelay(600);
> + } else {
> + ndelay(controller->ndelay);
> + }
> + gpio_set_value(controller->cki, 0);
> + ndelay(controller->ndelay);
> + }
> + }
> + if (controller->lei >= 0) {
> + gpio_set_value(controller->lei, 1);
> + ndelay(controller->ndelay);
> + gpio_set_value(controller->lei, 0);
> + }
> + atomic_set(&controller->pending, 1);
> +}
> +
> +static void led_nu801_set(struct led_classdev *led_cdev,
> +   enum led_brightness value)
> +{
> + struct led_nu801_led_data *led_dat =
> + container_of(led_cdev, struct led_nu801_led_data, cdev);
> + struct led_nu801_data *controller = led_dat->controller;
> +
> + if (led_dat->level != value) {
> + led_dat->level = value;
> + if (atomic_dec_and_test(&controller->pending))
> + s

[OpenWrt-Devel] [PATCH v5 4/5] ar71xx: add LED driver NU801

2015-09-22 Thread Chris R Blake
From: Chris R Blake 

The MR18 uses a 3-channel 16-bit PWM Constant Current Driver
for its status LED.

Signed-off-by: Chris R Blake 
---
 package/base-files/files/etc/init.d/led|   2 +-
 .../linux/ar71xx/files/drivers/leds/leds-nu801.c   | 396 +
 .../linux/ar71xx/files/include/linux/leds-nu801.h  |  38 ++
 target/linux/ar71xx/modules.mk |  16 +
 .../818-MIPS-ath79-add-nu801-led-driver.patch  |  26 ++
 5 files changed, 477 insertions(+), 1 deletion(-)
 create mode 100644 target/linux/ar71xx/files/drivers/leds/leds-nu801.c
 create mode 100644 target/linux/ar71xx/files/include/linux/leds-nu801.h
 create mode 100644 
target/linux/ar71xx/patches-4.1/818-MIPS-ath79-add-nu801-led-driver.patch

diff --git a/package/base-files/files/etc/init.d/led 
b/package/base-files/files/etc/init.d/led
index 3f45732..84cd028 100755
--- a/package/base-files/files/etc/init.d/led
+++ b/package/base-files/files/etc/init.d/led
@@ -44,7 +44,7 @@ load_led() {
ret="$?"
 
[ $default = 1 ] &&
-   echo 1 >/sys/class/leds/${sysfs}/brightness
+   cat /sys/class/leds/${sysfs}/max_brightness > 
/sys/class/leds/${sysfs}/brightness
 
[ $ret = 0 ] || {
echo >&2 "Skipping trigger '$trigger' for led '$name' 
due to missing kernel module"
diff --git a/target/linux/ar71xx/files/drivers/leds/leds-nu801.c 
b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c
new file mode 100644
index 000..0dfc015
--- /dev/null
+++ b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c
@@ -0,0 +1,396 @@
+/*
+ * LED driver for NU801
+ *
+ * Kevin Paul Herbert
+ * Copyright (c) 2012, Meraki, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define MAX_NAME_LENGTH 24
+#define NUM_COLORS 3
+
+static const char * const led_nu801_colors[] = { "blue", "green", "red" };
+
+struct led_nu801_led_data {
+   struct led_classdev cdev;
+   struct led_nu801_data *controller;
+   enum led_brightness level;
+   char name[MAX_NAME_LENGTH];
+};
+
+struct led_nu801_data {
+   unsigned cki;
+   unsigned sdi;
+   int lei;
+   struct delayed_work work;
+   struct led_nu801_led_data *led_chain;
+   int num_leds;
+   const char *device_name;
+   const char *name;
+   u32 ndelay;
+   atomic_t pending;
+};
+
+static void led_nu801_work(struct work_struct *work)
+{
+   struct led_nu801_data   *controller =
+   container_of(work, struct led_nu801_data, work.work);
+   struct led_nu801_led_data *led;
+   u16 bit;
+   u16 brightness;
+   int index;
+
+   for (index = 0; index < controller->num_leds; index++) {
+   led = &controller->led_chain[index];
+   brightness = led->level << 8; /* To do: gamma correction */
+   for (bit = 0x8000; bit; bit = bit >> 1) {
+   gpio_set_value(controller->sdi,
+  (brightness & bit) != 0);
+   gpio_set_value(controller->cki, 1);
+   if (unlikely(((index == (controller->num_leds - 1)) &&
+ (bit == 1) &&
+ (controller->lei < 0 {
+   udelay(600);
+   } else {
+   ndelay(controller->ndelay);
+   }
+   gpio_set_value(controller->cki, 0);
+   ndelay(controller->ndelay);
+   }
+   }
+   if (controller->lei >= 0) {
+   gpio_set_value(controller->lei, 1);
+   ndelay(controller->ndelay);
+   gpio_set_value(controller->lei, 0);
+   }
+   atomic_set(&controller->pending, 1);
+}
+
+static void led_nu801_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+   struct led_nu801_led_data *led_dat =
+   container_of(led_cdev, struct led_nu801_led_data, cdev);
+   struct led_nu801_data *controller = led_dat->controller;
+
+   if (led_dat->level != value) {
+   led_dat->level = value;
+   if (atomic_dec_and_test(&controller->pending))
+   schedule_delayed_work(&led_dat->controller->work,
+ (HZ/1000) + 1);
+   }
+}
+
+static int __init led_nu801_create(struct led_nu801_data *controller,
+   struct device *parent,
+   int index,
+   enum led_brightness brightness,
+#ifdef CONFIG_LEDS_TRIGGERS
+