>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