>From e63c88dee53094f07dd547ad46f44d8bd6a2e7fe Mon Sep 17 00:00:00 2001
From: Matthew Fatheree <matthew.fathe...@belkin.com>
Date: Sun, 4 May 2014 20:30:17 +0700
Subject: [PATCH 20/30] mamba mvebu: LED control support

 - Mamba LED driver controls SOC leds.
 - ledctrl script controls TLC & SOC leds from user space.

Signed-off-by: Matthew Fatheree <matthew.fathe...@belkin.com>
---
 package/linksys-base-files/files/usr/sbin/ledctrl  |  164 +++++++++++
 target/linux/mvebu/config-3.10                     |    1 +
 .../0310-ARM-mvebu-power-led-driver.patch          |  294 ++++++++++++++++++++
 3 files changed, 459 insertions(+)
 create mode 100755 package/linksys-base-files/files/usr/sbin/ledctrl
 create mode 100644 
target/linux/mvebu/patches-3.10/0310-ARM-mvebu-power-led-driver.patch

diff --git a/package/linksys-base-files/files/usr/sbin/ledctrl 
b/package/linksys-base-files/files/usr/sbin/ledctrl
new file mode 100755
index 0000000..4cc2465
--- /dev/null
+++ b/package/linksys-base-files/files/usr/sbin/ledctrl
@@ -0,0 +1,164 @@
+#!/bin/sh
+
+EXPECTED_ARGS=2
+E_BADARGS=65
+
+usage() {
+       echo "Usage: `basename $0` <led_name> <on|off|brightness_value> 
[delay_on] [delay_off]"
+       echo "       `basename $0` <led_2g> 100 500 500"
+       echo "       `basename $0` all on|off"
+       echo "          led name: led_2g | led_5g | led_esata | led_usb2"
+       echo "                    led_usb31 | led_usb32 | wan_amber | wan_white"
+       echo "                    wps_amber | wps_white | power"
+       echo "          brightness_value: 0..255"
+       echo "          delay_on/delay_off: 0..5000"
+
+       exit $E_BADARGS
+}
+
+if [ $# -lt $EXPECTED_ARGS ]
+then
+       usage
+fi
+
+led_name=$1
+value=$2
+blink="na"
+led_gpio=20
+
+if [ $# -ge 4 ]
+then
+       blink="ok"
+       delay_on=$3
+       delay_off=$4
+fi
+
+check_number() {
+       case $1 in
+       *[!0-9]* )
+               usage
+               ;;
+       esac
+}
+
+led_name_to_gpio() {
+       case $1 in
+               wan_amber )
+                       led_gpio=0 ;;
+               wan_white )
+                       led_gpio=1 ;;
+               led_2g )
+                       led_gpio=2 ;;
+               led_5g )
+                       led_gpio=3 ;;
+               led_esata )
+                       led_gpio=4 ;;
+               led_usb2 )
+                       led_gpio=5 ;;
+               led_usb31 )
+                       led_gpio=6 ;;
+               led_usb32 )
+                       led_gpio=7 ;;
+               wps_white )
+                       led_gpio=8 ;;
+               wps_amber )
+                       led_gpio=9 ;;
+               *)
+                       usage
+       esac
+}
+
+do_power() {
+       sval=$1
+       sblink=$2
+       sdelay_on=$3
+       sdelay_off=$4
+
+       if [ $sblink = "ok" ]
+       then
+               echo power $sval $delay_on $delay_off > /proc/mamba_led
+       else
+               echo power $sval > /proc/mamba_led
+       fi
+}
+
+led_list="led_2g led_5g led_esata led_usb2 led_usb31 led_usb32 wan_amber 
wan_white wps_amber wps_white power"
+led_gpio="0 1 2 3 4 5 6 7 8 9"
+
+led_perf() {
+
+       # Check if the led_name is valid
+       found=0
+       for x in $led_list
+       do
+               if [ $led_name = $x ]
+               then
+                       found=1
+               fi
+       done
+
+       if [ $found -eq 0 ]
+       then
+               if [ $led_name != "all" ]
+               then
+                       usage
+               fi
+       fi
+
+       # Check if the value is valid
+       case $value in
+       "on")
+               value=255
+               ;;
+       "off")
+               value=0
+               ;;
+       *)
+               check_number $value
+               if [ $value -gt 255 ]
+               then
+                       value=255
+               elif [ $value -lt 0 ]
+               then
+                       value=0
+               fi
+
+               ;;
+       esac
+
+       if [ $led_name = "all" ]
+       then
+               for x in $led_gpio
+               do
+                       path_led=/sys/class/leds/tlc59116:$x
+                       echo $value > $path_led/brightness
+                       if [ $blink = "ok" ]
+                       then
+                               echo timer > $path_led/trigger
+                               echo $value > $path_led/brightness
+                               echo $delay_on > $path_led/delay_on
+                               echo $delay_off > $path_led/delay_off
+                       fi
+                       sleep 1
+               done
+               do_power $value $blink $delay_on $delay_off
+       elif [ $led_name = "power" ]
+       then
+               #echo "Do Led Power"
+               do_power $value $blink $delay_on $delay_off
+       else
+               led_name_to_gpio $led_name
+               path_led=/sys/class/leds/tlc59116:$led_gpio
+               echo $value > $path_led/brightness
+
+               if [ $blink = "ok" ]
+               then
+                       echo timer > $path_led/trigger
+                       echo $value > $path_led/brightness
+                       echo $delay_on > $path_led/delay_on
+                       echo $delay_off > $path_led/delay_off
+               fi
+       fi
+}
+
+led_perf
diff --git a/target/linux/mvebu/config-3.10 b/target/linux/mvebu/config-3.10
index 8c67450..d5f944b 100644
--- a/target/linux/mvebu/config-3.10
+++ b/target/linux/mvebu/config-3.10
@@ -171,6 +171,7 @@ CONFIG_MACH_ARMADA_370_XP=y
 CONFIG_MACH_ARMADA_MAMBA=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAMBA_LED=y
 CONFIG_MARVELL_PHY=y
 CONFIG_MDIO_BOARDINFO=y
 CONFIG_MEMORY=y
diff --git 
a/target/linux/mvebu/patches-3.10/0310-ARM-mvebu-power-led-driver.patch 
b/target/linux/mvebu/patches-3.10/0310-ARM-mvebu-power-led-driver.patch
new file mode 100644
index 0000000..d910bfe
--- /dev/null
+++ b/target/linux/mvebu/patches-3.10/0310-ARM-mvebu-power-led-driver.patch
@@ -0,0 +1,294 @@
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -527,6 +527,12 @@ config SRAM
+         the genalloc API. It is supposed to be used for small on-chip SRAM
+         areas found on many SoCs.
+
++config MAMBA_LED
++      tristate "Mamba LED Module"
++      depends on MACH_ARMADA_MAMBA
++      help
++        This driver control the LED on Mamba board
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI)              += mei/
+ obj-$(CONFIG_VMWARE_VMCI)     += vmw_vmci/
+ obj-$(CONFIG_LATTICE_ECP3_CONFIG)     += lattice-ecp3-config.o
+ obj-$(CONFIG_SRAM)            += sram.o
++obj-$(CONFIG_MAMBA_LED)               += mamba_led.o
+--- /dev/null
++++ b/drivers/misc/mamba_led.c
+@@ -0,0 +1,269 @@
++
++/*
++ * mamba_led.c - Utility driver to control Mamba LEDs
++ *
++ * Copyright (C) 2013 Belkin Inc.
++ *
++ * 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; version 2 of the License.
++ *
++ *
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <asm/uaccess.h>
++#include <linux/cdev.h>
++#include <linux/proc_fs.h>
++#include <linux/mutex.h>
++#include <linux/sched.h>
++#include <linux/kthread.h>
++#include <linux/time.h>   // for using jiffies
++#include <linux/delay.h>
++#include <linux/kmod.h>
++#include <linux/gpio.h>
++#include <asm/io.h>
++
++#define MAX_PROC_SIZE 100
++#define MAX_LED_NAME_LEN 20
++#define LED_ON 255
++#define LED_OFF 0
++#define GPIO_OUT_DIR 0
++#define GPIO_IN_DIR 1
++
++struct mamba_led_t {
++      char name[MAX_LED_NAME_LEN];
++      unsigned int brightness;
++      unsigned char blink;
++      int delay_on;
++      int delay_off;
++      int gpio;
++      unsigned char default_gpio_dir;
++      int (*led_handler)(struct mamba_led_t *led);
++};
++
++#define MAMBA_LED_BASE_ADDR 0xf1018000
++#define MAMBA_LED_MAP_SIZE 0x1000
++#define MAMBA_POWER_LED_ENABLE_BLINK_ADDR     0x148
++#define MAMBA_POWER_LED_COUNTER_A_ADDR                0x160
++#define MAMBA_POWER_LED_ON_DURATION_ADDR      0x1c0
++#define MAMBA_POWER_LED_OFF_DURATION_ADDR     0x1c4
++#define MAMBA_POWER_LED_CTRL_GPIO 40
++
++int power_led_handler(struct mamba_led_t *led);
++
++static struct mamba_led_t mamba_leds[] = {
++      {"power", 0, 0, 0, 0, 40, GPIO_IN_DIR, power_led_handler}
++};
++
++static DEFINE_MUTEX(mutex);
++static char proc_data[MAX_PROC_SIZE];
++static struct proc_dir_entry *mamba_led_proc_entry;
++
++void __iomem *base_reg = NULL;
++
++int power_led_handler(struct mamba_led_t *led)
++{
++      if (base_reg == NULL)
++              return -1;
++
++      if (led->brightness == 0) {
++              gpio_direction_input(led->gpio);
++      }
++      else {
++              gpio_direction_output(led->gpio, led->brightness ? 1 : 0);
++              if (led->blink) {
++                      // Enable blink register
++                      writel(0x00000100,
++                              base_reg + MAMBA_POWER_LED_ENABLE_BLINK_ADDR);
++                      // Set blink counter A for GPIO40
++                      writel(0x00000000,
++                              base_reg + MAMBA_POWER_LED_COUNTER_A_ADDR);
++                      // On durration
++                      writel(led->delay_on*250*1000,
++                              base_reg + MAMBA_POWER_LED_ON_DURATION_ADDR);
++                      // Off duration
++                      writel(led->delay_off*250*1000,
++                              base_reg + MAMBA_POWER_LED_OFF_DURATION_ADDR);
++              }
++              else {
++                      // Disable blink register
++                      writel(0x00000000,
++                              base_reg + MAMBA_POWER_LED_ENABLE_BLINK_ADDR);
++              }
++      }
++      return 0;
++}
++
++static int mamba_led_proc_show(struct seq_file *m, void *v)
++{
++      int i = 0;
++      struct mamba_led_t *led = NULL;
++
++      seq_printf(m, "%12s%12s%7s%10s%11s%6s\n", "led_name", 
"brightness","blink",
++              "delay_on", "delay_off","gpio");
++      for (i = 0; i < sizeof(mamba_leds)/sizeof(struct mamba_led_t); i++) {
++              led = &mamba_leds[i];
++              seq_printf(m, "%12s", led->name);
++              seq_printf(m, "%12d", led->brightness);
++              seq_printf(m, "%7d", led->blink);
++              seq_printf(m, "%10d", led->delay_on);
++              seq_printf(m, "%11d", led->delay_off);
++              seq_printf(m, "%6d\n", led->gpio);
++      }
++      seq_printf(m, "echo <led_name> <on|off|brightness_value> [<delay_on>"
++              " <delay_off>] > /proc/mamba_led\n");
++
++      return 0;
++}
++
++static struct mamba_led_t *check_led_valid(char *led_name) {
++      int i = 0;
++      struct mamba_led_t *led = NULL;
++      for (i = 0; i < sizeof(mamba_leds)/sizeof(struct mamba_led_t); i++) {
++              led = &mamba_leds[i];
++              if(!strncmp(led_name, led->name, strlen(led->name))) {
++                      return led;
++              }
++      }
++      return NULL;
++}
++
++static int check_brightness_valid(char *brightness_s,
++              unsigned char *brightness) {
++      int ret = 0;
++      int tmp = 0;
++      if (!strncmp(brightness_s, "on", 2)) {
++              *brightness = 255;
++      }
++      else if (!strncmp(brightness_s, "off", 3)) {
++              *brightness = 0;
++      }
++      else {
++              ret = sscanf(brightness_s, "%d\n", &tmp);
++              if (ret == 1) {
++                      *brightness = tmp & 0xff;
++              }
++              else {
++                      return -1;
++              }
++      }
++      return 0;
++}
++
++static int mamba_led_write_proc(struct file *filp, const char *buf,
++              size_t count, loff_t *offp)
++{
++      int ret = 0;
++      char led_name[32];
++      char brightness_s[32];
++      struct mamba_led_t *target_led = NULL;
++      unsigned char brightness = 0;
++      int delay_on, delay_off;
++
++      if (!count) {
++              printk("echo <led_name> <on|off|brightness_value> [<delay_on>"
++                              " <delay_off>] > /proc/mamba_led\n");
++              goto err;
++      }
++      if(count > MAX_PROC_SIZE)
++              count = MAX_PROC_SIZE;
++
++      memset(proc_data, 0, sizeof(proc_data));
++      if(copy_from_user(proc_data, buf, count)) {
++              goto err;
++      }
++
++      ret = sscanf(proc_data, "%s %s %d %d\n",
++                      led_name, brightness_s, &delay_on, &delay_off);
++      if (ret < 2 || (ret > 2 && ret != 4)
++              || (target_led = check_led_valid(led_name)) == NULL
++              || check_brightness_valid(brightness_s, &brightness) != 0) {
++              goto err;
++      }
++
++      mutex_lock(&mutex);
++      target_led->brightness = brightness;
++      if (ret > 2) {
++              target_led->blink = 1;
++              target_led->delay_on = delay_on;
++              target_led->delay_off = delay_off;
++      }
++      else {
++              target_led->blink = 0;
++      }
++
++      if (target_led->led_handler)
++              target_led->led_handler(target_led);
++
++      mutex_unlock(&mutex);
++
++      return count;
++err:
++      return -EFAULT;
++}
++
++static int mamba_led_proc_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, mamba_led_proc_show, PDE_DATA(inode));
++}
++
++static struct file_operations proc_fops = {
++      .owner          = THIS_MODULE,
++      .open           = mamba_led_proc_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release,
++      .write          = mamba_led_write_proc,
++};
++
++int mamba_led_init (void) {
++      int i = 0;
++      struct mamba_led_t *led = NULL;
++
++      mamba_led_proc_entry = proc_create("mamba_led", 0, NULL, &proc_fops);
++      if(!mamba_led_proc_entry)
++      {
++              printk("%s: Error creating proc entry\n", __FUNCTION__);
++              return -ENOMEM;
++      }
++
++      base_reg = ioremap(MAMBA_LED_BASE_ADDR, MAMBA_LED_MAP_SIZE);
++      if (base_reg == NULL)
++              goto ioremap_failed;
++
++      for (i = 0; i < sizeof(mamba_leds)/sizeof(struct mamba_led_t); i++) {
++              led = &mamba_leds[i];
++              if(gpio_request(led->gpio, led->name) != 0) {
++                      printk("failed to request gpio for %s led\n",
++                              led->name);
++                      goto gpio_request_failed;
++              }
++              if (led->default_gpio_dir == GPIO_OUT_DIR)
++                      gpio_direction_output(led->gpio, 0);
++              else
++                      gpio_direction_input(led->gpio);
++      }
++
++      printk("Mamba LED init done\n");
++      return 0;
++
++gpio_request_failed:
++      if (base_reg)
++              iounmap(base_reg);
++ioremap_failed:
++      remove_proc_entry("mamba_led",NULL);
++      return -1;
++}
++
++void mamba_led_cleanup(void) {
++      if (base_reg)
++              iounmap(base_reg);
++      remove_proc_entry("mamba_led",NULL);
++}
++MODULE_AUTHOR("Belkin Inc.");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("mamba led driver");
++
++module_init(mamba_led_init);
++module_exit(mamba_led_cleanup);
--
1.7.9.5



__________________________________________________________________ Confidential 
This e-mail and any files transmitted with it are the property of Belkin 
International, Inc. and/or its affiliates, are confidential, and are intended 
solely for the use of the individual or entity to whom this e-mail is 
addressed. If you are not one of the named recipients or otherwise have reason 
to believe that you have received this e-mail in error, please notify the 
sender and delete this message immediately from your computer. Any other use, 
retention, dissemination, forwarding, printing or copying of this e-mail is 
strictly prohibited. Pour la version française: 
http://www.belkin.com/email-notice/French.html Für die deutsche Übersetzung: 
http://www.belkin.com/email-notice/German.html 
__________________________________________________________________
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to