diff -uNr '--exclude=out' linux-3.6.9/arch/arm/Kconfig linux-3.6.9-my/arch/arm/Kconfig --- linux-3.6.9/arch/arm/Kconfig 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/arch/arm/Kconfig 2012-12-06 17:04:46.987415264 +0100 @@ -584,6 +584,7 @@ config ARCH_KIRKWOOD bool "Marvell Kirkwood" select CPU_FEROCEON + select ARCH_HAS_CPUFREQ select PCI select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS diff -uNr '--exclude=out' linux-3.6.9/arch/arm/mach-kirkwood/cpufreq.c linux-3.6.9-my/arch/arm/mach-kirkwood/cpufreq.c --- linux-3.6.9/arch/arm/mach-kirkwood/cpufreq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-3.6.9-my/arch/arm/mach-kirkwood/cpufreq.c 2012-12-06 17:04:46.987415264 +0100 @@ -0,0 +1,248 @@ +/* + * arch/arm/mach-kirkwood/cpufreq.c + * + * Clock scaling for Kirkwood SoC + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + + + +enum kw_cpufreq_range { + KW_CPUFREQ_LOW = 0, + KW_CPUFREQ_HIGH = 1 +}; + +static struct cpufreq_frequency_table kw_freqs[] = { + { KW_CPUFREQ_LOW, 0 }, + { KW_CPUFREQ_HIGH, 0 }, + { 0, CPUFREQ_TABLE_END } +}; + + +static inline void kw_set_powersave_on(void) +{ + unsigned long old,temp; + /* Disable int */ + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + + /* Set SoC in power save */ + writel(readl(CLOCK_GATING_CTRL) | (1 << 11), CLOCK_GATING_CTRL); + + /* Wait for int */ + __asm__ __volatile__("mcr p15, 0, r0, c7, c0, 4"); + + /* Enabled int */ + __asm__ __volatile__("msr cpsr_c, %0" + : + : "r" (old) + : "memory"); +} + +static inline void kw_set_powersave_off(void) +{ + unsigned long old,temp; + /* Disable int */ + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + + /* Set SoC in power save */ + writel(readl(CLOCK_GATING_CTRL) & (~(1 << 11)), CLOCK_GATING_CTRL); + + /* Wait for int */ + __asm__ __volatile__("mcr p15, 0, r0, c7, c0, 4"); + + /* Enabled int */ + __asm__ __volatile__("msr cpsr_c, %0" + : + : "r" (old) + : "memory"); +} + +/* + * Power management function: set or unset powersave mode + * FIXME: a better place ? + */ +static inline void kw_set_powersave(int on) +{ + if (on) + kw_set_powersave_on(); + else + kw_set_powersave_off(); +} + +static int kw_cpufreq_verify(struct cpufreq_policy *policy) +{ + if (unlikely(!cpu_online(policy->cpu))) + return -ENODEV; + + return cpufreq_frequency_table_verify(policy, kw_freqs); +} + +/* + * Get the current frequency for a given cpu. + */ +static unsigned int kw_cpufreq_get(unsigned int cpu) +{ + unsigned int freq; + u32 reg; + + if (unlikely(!cpu_online(cpu))) + return -ENODEV; + + /* To get the current frequency, we have to check if + * the powersave mode is set. */ + reg = readl(CLOCK_GATING_CTRL); + + if (reg & (1 << 11)) + freq = kw_freqs[KW_CPUFREQ_LOW].frequency; + else + freq = kw_freqs[KW_CPUFREQ_HIGH].frequency; + + return freq; +} + +/* + * Set the frequency for a given cpu. + */ +static int kw_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int index; + struct cpufreq_freqs freqs; + + if (unlikely(!cpu_online(policy->cpu))) + return -ENODEV; + + /* Lookup the next frequency */ + if (unlikely(cpufreq_frequency_table_target(policy, + kw_freqs, target_freq, relation, &index))) + return -EINVAL; + + + freqs.old = policy->cur; + freqs.new = kw_freqs[index].frequency; + freqs.cpu = policy->cpu; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* Interruptions will be disabled in the low level power mode + * functions. */ + if (index == KW_CPUFREQ_LOW) + kw_set_powersave(1); + else if (index == KW_CPUFREQ_HIGH) + kw_set_powersave(0); + else + return -EINVAL; + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; +} + +static int kw_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (unlikely(!cpu_online(policy->cpu))) + return -ENODEV; + +#if 0 + TODO: Read cpu frequencies from register + /* + * As 6180 board have different reset sample register values, + * the board type must be checked first. + */ + if (dev_id == MV_6180_DEV_ID) { + + kw_freqs[KW_CPUFREQ_HIGH].frequency = mvCpuPclkGet()/1000; + /* At the lowest frequency CPU goes to DDR data clock rate: + * (2 x DDR clock rate). */ + kw_freqs[KW_CPUFREQ_LOW].frequency = mvBoardSysClkGet()*2/1000; + + } else if ((dev_id == MV_6281_DEV_ID) || + (dev_id == MV_6192_DEV_ID)) { + + kw_freqs[KW_CPUFREQ_HIGH].frequency = mvCpuPclkGet()/1000; + /* CPU low frequency is the DDR frequency. */ + kw_freqs[KW_CPUFREQ_LOW].frequency = mvBoardSysClkGet()/1000; + + } else { + return -ENODEV; + } +#endif + /* God knows */ + kw_freqs[KW_CPUFREQ_HIGH].frequency = 1200000; + kw_freqs[KW_CPUFREQ_LOW].frequency = 400000; + + printk(KERN_INFO + "cpufreq: High frequency: %uKHz - Low frequency: %uKHz\n", + kw_freqs[KW_CPUFREQ_HIGH].frequency, + kw_freqs[KW_CPUFREQ_LOW].frequency); + + policy->cpuinfo.transition_latency = 1000000; + policy->cur = kw_cpufreq_get(0); + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + cpufreq_frequency_table_get_attr(kw_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, kw_freqs); +} + + +static int kw_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static struct freq_attr *kw_freq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + + +static struct cpufreq_driver kw_freq_driver = { + .name = "kw_cpufreq", + .owner = THIS_MODULE, + .init = kw_cpufreq_cpu_init, + .verify = kw_cpufreq_verify, + .exit = kw_cpufreq_cpu_exit, + .target = kw_cpufreq_target, + .get = kw_cpufreq_get, + .attr = kw_freq_attr, +}; + + +static int __init kw_cpufreq_init(void) +{ + printk(KERN_INFO "cpufreq: Init kirkwood cpufreq driver\n"); + + return cpufreq_register_driver(&kw_freq_driver); +} + +static void __exit kw_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&kw_freq_driver); +} + +module_init(kw_cpufreq_init); +module_exit(kw_cpufreq_exit); + diff -uNr '--exclude=out' linux-3.6.9/arch/arm/mach-kirkwood/Kconfig linux-3.6.9-my/arch/arm/mach-kirkwood/Kconfig --- linux-3.6.9/arch/arm/mach-kirkwood/Kconfig 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/arch/arm/mach-kirkwood/Kconfig 2012-12-06 17:04:46.991415300 +0100 @@ -195,6 +195,28 @@ Say 'Y' here if you want your kernel to support the HP t5325 Thin Client. +config ZYXEL_NAS + bool "Support for ZyXEL NAS devices" + help + Enable this to set more options for ZyXEL NAS. + +choice + prompt "ZyXEL NAS Model" + depends on ZYXEL_NAS + default MACH_NSA310 + +config MACH_NSA310 + bool "Zyxel NSA310 NAS" + help + Support for ZyXEL NSA310 board. + +config MACH_NSA320 + bool "Zyxel NSA320 NAS" + help + Support for ZyXEL NSA320 board. + +endchoice + endmenu endif diff -uNr '--exclude=out' linux-3.6.9/arch/arm/mach-kirkwood/Makefile linux-3.6.9-my/arch/arm/mach-kirkwood/Makefile --- linux-3.6.9/arch/arm/mach-kirkwood/Makefile 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/arch/arm/mach-kirkwood/Makefile 2012-12-06 17:04:46.991415300 +0100 @@ -18,8 +18,11 @@ obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_T5325) += t5325-setup.o +obj-$(CONFIG_MACH_NSA320) += nsa320-setup.o mcu.o +obj-$(CONFIG_MACH_NSA310) += nsa310-setup.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o +obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += cpufreq.o obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o obj-$(CONFIG_MACH_DREAMPLUG_DT) += board-dreamplug.o obj-$(CONFIG_MACH_ICONNECT_DT) += board-iconnect.o diff -uNr '--exclude=out' linux-3.6.9/arch/arm/mach-kirkwood/mcu.c linux-3.6.9-my/arch/arm/mach-kirkwood/mcu.c --- linux-3.6.9/arch/arm/mach-kirkwood/mcu.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-3.6.9-my/arch/arm/mach-kirkwood/mcu.c 2012-12-06 17:04:46.991415300 +0100 @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "common.h" +#include "mpp.h" + + + +#define MCU_DATA_PIN 14 +#define MCU_CLK_PIN 16 +#define MCU_ACT_PIN 17 + +MODULE_LICENSE("GPL v2"); +#define MODULE_NAME "mcu" + +unsigned long mcu_data = 0; +unsigned long mcu_counter = 0; + +static struct proc_dir_entry *mcu_proc; + +static int mcu_status_read_fn(char *buf, char **start, off_t offset, + int count, int *eof, void *data) +{ + unsigned long len, i; + + mcu_data = 0; + + gpio_request(14, "MCU_DATA"); + gpio_request(16, "MCU_CLK"); + gpio_request(17, "MCU_ACT"); + + gpio_direction_output(MCU_ACT_PIN, 0); + msleep(100); + gpio_direction_input(MCU_DATA_PIN); + gpio_direction_output(MCU_CLK_PIN, 0); + udelay(100); + + for(i = 0 ; i < 32 ; i++) + { + mcu_data <<= 1; + gpio_set_value(MCU_CLK_PIN,1); + + mcu_data |= gpio_get_value(MCU_DATA_PIN)?0x1:0; + + udelay(100); + + gpio_set_value(MCU_CLK_PIN,0); + + udelay(100); + } + + + gpio_set_value(MCU_CLK_PIN,1); + gpio_set_value(MCU_ACT_PIN,1); + + + gpio_free(14); + gpio_free(16); + gpio_free(17); + + len = sprintf(buf, "MagicNum:%u\nRpss:%u\nTemperature:%u\n",(unsigned int)((mcu_data & 0xff000000) >> 24), + (unsigned int)((mcu_data & 0xff0000) >> 16), + (unsigned int)((mcu_data & 0xffff))); + *eof = 1; + + return len; +} + +static int mcu_status_write_fn(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + return 0; +} + + +static int __init mcu_init(void) +{ + + mcu_proc = create_proc_entry("mcu", 0644, NULL); + if(mcu_proc != NULL) + { + mcu_proc->read_proc = mcu_status_read_fn; + mcu_proc->write_proc = mcu_status_write_fn; + } + + return 0; +} + +static void __exit mcu_exit(void) +{ + remove_proc_entry("mcu", NULL); + +} + +module_init(mcu_init); +module_exit(mcu_exit); + diff -uNr '--exclude=out' linux-3.6.9/arch/arm/mach-kirkwood/nsa310-setup.c linux-3.6.9-my/arch/arm/mach-kirkwood/nsa310-setup.c --- linux-3.6.9/arch/arm/mach-kirkwood/nsa310-setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-3.6.9-my/arch/arm/mach-kirkwood/nsa310-setup.c 2012-12-06 17:04:46.991415300 +0100 @@ -0,0 +1,330 @@ + /* + * Zyxel NSA-310 Setup, by AA666 and Peeter123 + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include +#include + +static void nsa310_timerfunc(unsigned long data); +static DEFINE_TIMER(timer, nsa310_timerfunc, 0, 0); + +static struct mtd_partition nsa310_nand_parts[] = { + { + .name = "uboot", + .offset = 0, + .size = 0x100000, + .mask_flags = MTD_WRITEABLE + }, { + .name = "uboot_env", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x80000 + }, { + .name = "key_store", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x80000 + }, { + .name = "info", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x80000 + }, { + .name = "etc", + .offset = MTDPART_OFS_NXTBLK, + .size = 0xA00000 + }, { + .name = "kernel_1", + .offset = MTDPART_OFS_NXTBLK, + .size = 0xA00000 + }, { + .name = "rootfs1", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x2FC0000 + }, { + .name = "kernel_2", + .offset = MTDPART_OFS_NXTBLK, + .size = 0xA00000 + }, { + .name = "rootfs2", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x2FC0000 + }, +}; + +static struct mv_sata_platform_data nsa310_sata_data = { + .n_ports = 2, +}; + +static unsigned int nsa310_mpp_config[] __initdata = { + MPP36_GPIO, // Reset button + MPP37_GPIO, // Copy button + MPP46_GPIO, // Power button + + MPP48_GPIO, // Power Off + MPP21_GPIO, // USB Power Off + + MPP28_GPIO, // Sys LED Green + MPP29_GPIO, // Sys LED Yellow + MPP41_GPIO, // SATA1 LED Green + MPP42_GPIO, // SATA1 LED Red + MPP12_GPIO, // SATA2 LED Green + MPP13_GPIO, // SATA2 LED Red + MPP39_GPIO, // Copy LED Green + MPP40_GPIO, // Copy LED Red + MPP15_GPIO, // USB LED Green + + MPP14_GPIO, // MCU Data + MPP16_GPIO, // MCU Clk + MPP17_GPIO, // MCU Act + + MPP38_GPIO, // VID B0 + MPP45_GPIO, // VID B1 + + MPP44_GPIO, // Buzzer + MPP43_GPIO, // HTP + + MPP47_GPIO, // Power Resume Data + MPP49_GPIO, // Power Resume Clock + + 0 +}; + +static struct gpio_led nsa310_gpio_led[] = { + { + .name = "nsa310:green:System", + .default_trigger = "timer", + .gpio = 28, + .active_low = 0, + + }, + { + .name = "nsa310:red:System", + .default_trigger = "none", + .gpio = 29, + .active_low = 0, + }, + { + .name = "nsa310:green:SATA1", + .default_trigger = "none", + .gpio = 41, + .active_low = 0, + }, + { + .name = "nsa310:red:SATA1", + .default_trigger = "sata-disk", + .gpio = 42, + .active_low = 0, + }, + { + .name = "nsa310:green:SATA2", + .default_trigger = "none", + .gpio = 12, + .active_low = 0, + }, + { + .name = "nsa310:red:SATA2", + .default_trigger = "none", + .gpio = 13, + .active_low = 0, + }, + { + .name = "nsa310:green:USB", + .default_trigger = "none", + .gpio = 15, + .active_low = 0, + }, + { + .name = "nsa310:green:Copy", + .default_trigger = "none", + .gpio = 39, + .active_low = 0, + }, + { + .name = "nsa310:red:Copy", + .default_trigger = "none", + .gpio = 40, + .active_low = 0, + }, +}; + + +static int nsa310_gpio_blink_set(unsigned gpio, int state, + unsigned long *delay_on, unsigned long *delay_off) +{ + switch(state) { + case GPIO_LED_NO_BLINK_LOW: + case GPIO_LED_NO_BLINK_HIGH: + orion_gpio_set_blink(gpio, 0); + gpio_set_value(gpio, state); + break; + case GPIO_LED_BLINK: + orion_gpio_set_blink(gpio, 1); + break; + } + return 0; +} + +static struct gpio_led_platform_data nsa310_led_data = { + .leds = nsa310_gpio_led, + .num_leds = ARRAY_SIZE(nsa310_gpio_led), + .gpio_blink_set = nsa310_gpio_blink_set, +}; + +static struct platform_device nsa310_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { .platform_data = &nsa310_led_data, } +}; + +static struct gpio_keys_button nsa310_gpio_keys_button[] = { + { + .code = KEY_POWER, + .type = EV_KEY, + .gpio = 46, + .desc = "Power Button", + .active_low = 0, + .debounce_interval = 100, + }, + { + .code = KEY_COPY, + .type = EV_KEY, + .gpio = 37, + .desc = "USB Copy", + .active_low = 1, + .debounce_interval = 100, + }, + { + .code = KEY_RESTART, + .type = EV_KEY, + .gpio = 36, + .desc = "Reset", + .active_low = 1, + .debounce_interval = 100, + }, +}; + +static struct gpio_keys_platform_data nsa310_keys_data = { + .buttons = nsa310_gpio_keys_button, + .nbuttons = ARRAY_SIZE(nsa310_gpio_keys_button), +}; + + +static struct platform_device nsa310_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { .platform_data = &nsa310_keys_data, } +}; + +static void nsa310_power_off(void) +{ + printk(KERN_INFO "NSA310: Activating power off GPIO pin...\n"); + gpio_set_value(48, 1); + +} + +static void nsa310_timerfunc(unsigned long data) +{ +// Activate USB Power + if (gpio_request(21, "USB Power") != 0 || gpio_direction_output(21, 1) != 0) + printk(KERN_ERR "NSA310: Failed to setup USB power GPIO\n"); + else + printk(KERN_INFO "NSA310: USB power enabled\n"); + gpio_free(21); +} + +static void __init nsa310_init(void) +{ + u32 dev, rev; + printk(KERN_INFO "NSA310: Init board\n"); + kirkwood_init(); + + kirkwood_mpp_conf(nsa310_mpp_config); + kirkwood_nand_init(ARRAY_AND_SIZE(nsa310_nand_parts), 40); + kirkwood_pcie_id(&dev, &rev); + + kirkwood_sata_init(&nsa310_sata_data); + kirkwood_uart0_init(); + kirkwood_i2c_init(); + + platform_device_register(&nsa310_leds); + platform_device_register(&nsa310_buttons); + + printk(KERN_INFO "NSA310: Start USB and 20 sec USB power delay\n"); + kirkwood_ehci_init(); + /* USB Power delay for 20 sec */ + timer.function = nsa310_timerfunc; + timer.data = 0; + timer.expires = jiffies + msecs_to_jiffies(20000); + add_timer(&timer); + + +/* Power resume control */ + + /* Request GPIO access */ + gpio_request(47, "Power-data"); + gpio_request(49, "Power-clk"); + + /* Set GPIO output */ + gpio_direction_output(49, 1); + gpio_direction_output(47, 1); + + udelay(1000); + gpio_set_value(49, 0); + + /* Free GPIO pins */ + gpio_free(47); + gpio_free(49); + + printk(KERN_INFO "NSA310: Power Resume Enabled\n"); + + /* Activate Power-off GPIO */ + if (gpio_request(48, "Power-off") == 0 && gpio_direction_output(48, 0) == 0) { + pm_power_off = nsa310_power_off; + printk(KERN_INFO "NSA310: Power-off GPIO enabled\n"); + } else + printk(KERN_ERR "NSA310: Failed to configure Power-off GPIO\n"); + +}; + +static int __init nsa310_pci_init(void) +{ + if (machine_is_nsa310()) + kirkwood_pcie_init(KW_PCIE0); + return 0; +} + +subsys_initcall(nsa310_pci_init); + +MACHINE_START(NSA310, "Zyxel NSA-310") + .atag_offset = 0x100, + .init_machine = nsa310_init, + .map_io = kirkwood_map_io, + .init_early = kirkwood_init_early, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, + .restart = kirkwood_restart, +MACHINE_END + diff -uNr '--exclude=out' linux-3.6.9/arch/arm/mach-kirkwood/nsa320-setup.c linux-3.6.9-my/arch/arm/mach-kirkwood/nsa320-setup.c --- linux-3.6.9/arch/arm/mach-kirkwood/nsa320-setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-3.6.9-my/arch/arm/mach-kirkwood/nsa320-setup.c 2012-12-06 17:04:46.991415300 +0100 @@ -0,0 +1,357 @@ +/* + * arch/arm/mach-kirkwood/nsa320-setup.c + * + * Zyxel NSA-320 Setup, by AA666 + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include +#include + +static void nsa320_timerfunc(unsigned long data); +static DEFINE_TIMER(timer, nsa320_timerfunc, 0, 0); + +static struct mtd_partition nsa320_nand_parts[] = { + { + .name = "uboot", + .offset = 0, + .size = 0x100000, + .mask_flags = MTD_WRITEABLE + }, { + .name = "uboot_env", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x80000 + }, { + .name = "key_store", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x80000 + }, { + .name = "info", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x80000 + }, { + .name = "etc", + .offset = MTDPART_OFS_NXTBLK, + .size = 0xA00000 + }, { + .name = "kernel_1", + .offset = MTDPART_OFS_NXTBLK, + .size = 0xA00000 + }, { + .name = "rootfs1", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x2FC0000 + }, { + .name = "kernel_2", + .offset = MTDPART_OFS_NXTBLK, + .size = 0xA00000 + }, { + .name = "rootfs2", + .offset = MTDPART_OFS_NXTBLK, + .size = 0x2FC0000 + }, +}; + +static struct i2c_board_info __initdata nsa320_i2c_rtc = { + I2C_BOARD_INFO("pcf8563", 0x51), +}; + +static struct mv643xx_eth_platform_data nsa320_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), + .speed = SPEED_1000, + .duplex = DUPLEX_FULL, +}; + +static struct mv_sata_platform_data nsa320_sata_data = { + .n_ports = 2, +}; + +static unsigned int nsa320_mpp_config[] __initdata = { + MPP36_GPIO, // Reset button + MPP37_GPIO, // Copy button + MPP46_GPIO, // Power button + + MPP48_GPIO, // Power Off + MPP21_GPIO, // USB Power Off + + MPP28_GPIO, // Sys LED Green + MPP29_GPIO, // Sys LED Yellow + MPP41_GPIO, // SATA1 LED Green + MPP42_GPIO, // SATA1 LED Red + MPP12_GPO, // SATA2 LED Green + MPP13_GPIO, // SATA2 LED Red + MPP39_GPIO, // Copy LED Green + MPP40_GPIO, // Copy LED Red + MPP15_GPIO, // USB LED Green + + MPP14_GPIO, // MCU Data + MPP16_GPIO, // MCU Clk + MPP17_GPIO, // MCU Act + + MPP38_GPIO, // VID B0 + MPP45_GPIO, // VID B1 + + MPP44_GPIO, // Buzzer + MPP43_GPIO, // HTP + + MPP47_GPIO, // Power Resume Data + MPP49_GPIO, // Power Resume Clock + + 0 +}; + +static struct gpio_led nsa320_gpio_led[] = { + { + .name = "nsa320:green:System", + .default_trigger = "timer", + .gpio = 28, + .active_low = 0, + + }, + { + .name = "nsa320:red:System", + .default_trigger = "none", + .gpio = 29, + .active_low = 0, + }, + { + .name = "nsa320:green:SATA1", + .default_trigger = "none", + .gpio = 41, + .active_low = 0, + }, + { + .name = "nsa320:red:SATA1", + .default_trigger = "sata-disk", + .gpio = 42, + .active_low = 0, + }, + { + .name = "nsa320:green:SATA2", + .default_trigger = "none", + .gpio = 12, + .active_low = 0, + }, + { + .name = "nsa320:red:SATA2", + .default_trigger = "none", + .gpio = 13, + .active_low = 0, + }, + { + .name = "nsa320:green:USB", + .default_trigger = "none", + .gpio = 15, + .active_low = 0, + }, + { + .name = "nsa320:green:Copy", + .default_trigger = "none", + .gpio = 39, + .active_low = 0, + }, + { + .name = "nsa320:red:Copy", + .default_trigger = "none", + .gpio = 40, + .active_low = 0, + }, +}; + + +static int nsa320_gpio_blink_set(unsigned gpio, int state, + unsigned long *delay_on, unsigned long *delay_off) +{ + +// Use hardware acceleration +// if (delay_on && delay_off && !*delay_on && !*delay_off) +// *delay_on = *delay_off = 100; + + switch(state) { + case GPIO_LED_NO_BLINK_LOW: + case GPIO_LED_NO_BLINK_HIGH: + orion_gpio_set_blink(gpio, 0); + gpio_set_value(gpio, state); + break; + case GPIO_LED_BLINK: + orion_gpio_set_blink(gpio, 1); + break; + } + return 0; +} + + +static struct gpio_led_platform_data nsa320_led_data = { + .leds = nsa320_gpio_led, + .num_leds = ARRAY_SIZE(nsa320_gpio_led), + .gpio_blink_set = nsa320_gpio_blink_set, +}; + +static struct platform_device nsa320_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { .platform_data = &nsa320_led_data, } +}; + +static struct gpio_keys_button nsa320_gpio_keys_button[] = { + { + .code = KEY_POWER, + .type = EV_KEY, + .gpio = 46, + .desc = "Power Button", + .active_low = 0, + .debounce_interval = 1000, + }, + { + .code = KEY_COPY, + .type = EV_KEY, + .gpio = 37, + .desc = "USB Copy", + .active_low = 1, + .debounce_interval = 1000, + }, + { + .code = KEY_OPTION, + .type = EV_KEY, + .gpio = 36, + .desc = "Reset", + .active_low = 1, + .debounce_interval = 1000, + }, +}; + +static struct gpio_keys_platform_data nsa320_keys_data = { + .buttons = nsa320_gpio_keys_button, + .nbuttons = ARRAY_SIZE(nsa320_gpio_keys_button), +}; + +static struct platform_device nsa320_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { .platform_data = &nsa320_keys_data, } +}; + +static void nsa320_power_off(void) +{ +// +//don't work with sysfs + printk(KERN_INFO "NSA320: Activating power off GPIO pin...\n"); + gpio_set_value(48, 1); + +// If machine goes to restart, uncomment next lines for infinite loop +/* printk(KERN_INFO "System halted, please turn off power manually\n"); + gpio_set_value(28, 0); + do { + mdelay(1000); + } while(1); +*/ +} + +static void nsa320_timerfunc(unsigned long data) +{ +// Activate USB Power + if (gpio_request(21, "USB Power") != 0 || gpio_direction_output(21, 1) != 0) + printk(KERN_ERR "NSA320: Failed to setup USB power GPIO\n"); + else + printk(KERN_INFO "NSA320: USB power enabled\n"); + gpio_free(21); +} + +static void __init nsa320_init(void) +{ + u32 dev, rev; + + kirkwood_init(); + + kirkwood_mpp_conf(nsa320_mpp_config); + kirkwood_nand_init(ARRAY_AND_SIZE(nsa320_nand_parts), 40); + kirkwood_ge00_init(&nsa320_ge00_data); + kirkwood_pcie_id(&dev, &rev); + + kirkwood_sata_init(&nsa320_sata_data); + kirkwood_uart0_init(); + kirkwood_i2c_init(); + i2c_register_board_info(0, &nsa320_i2c_rtc, 1); + + platform_device_register(&nsa320_leds); + platform_device_register(&nsa320_buttons); + + kirkwood_ehci_init(); +// USB Power delay for 20 sec + timer.function = nsa320_timerfunc; + timer.data = 0; + timer.expires = jiffies + msecs_to_jiffies(20000); + add_timer(&timer); + + +/* Power resume control */ + gpio_request(49, "Power-clk"); + gpio_direction_output(49, 1); + gpio_request(47, "Power-data"); +// Clear power resume +// gpio_direction_output(47, 0); +// Set power resume + gpio_direction_output(47, 1); + udelay(1000); +// gpio_direction_output(49, 0); + gpio_set_value(49, 0); +// release GPIO? +//test + gpio_free(47); + gpio_free(49); + printk(KERN_INFO "NSA320: Power resume enabled\n"); + + +// Activate Power-off GPIO + if (gpio_request(48, "Power-off") == 0 && gpio_direction_output(48, 0) == 0) { +// gpio_free(48); + pm_power_off = nsa320_power_off; + printk(KERN_INFO "NSA320: Power-off GPIO enabled\n"); + } else + printk(KERN_ERR "failed to configure Power-off GPIO\n"); + +}; + +static int __init nsa320_pci_init(void) +{ + if (machine_is_nsa320()) + kirkwood_pcie_init(KW_PCIE0); + return 0; +} + +subsys_initcall(nsa320_pci_init); + +MACHINE_START(NSA320, "Zyxel NSA-320") + .atag_offset = 0x100, + .init_machine = nsa320_init, + .map_io = kirkwood_map_io, + .init_early = kirkwood_init_early, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, + .restart = kirkwood_restart, +MACHINE_END diff -uNr '--exclude=out' linux-3.6.9/drivers/ata/sata_mv.c linux-3.6.9-my/drivers/ata/sata_mv.c --- linux-3.6.9/drivers/ata/sata_mv.c 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/drivers/ata/sata_mv.c 2012-12-06 17:04:46.991415300 +0100 @@ -71,6 +71,7 @@ #include #include #include +#include #define DRV_NAME "sata_mv" #define DRV_VERSION "1.28" @@ -1155,6 +1156,8 @@ { int want_ncq = (protocol == ATA_PROT_NCQ); + ledtrig_sata_activity(); + if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0); if (want_ncq != using_ncq) diff -uNr '--exclude=out' linux-3.6.9/drivers/cpufreq/Kconfig.arm linux-3.6.9-my/drivers/cpufreq/Kconfig.arm --- linux-3.6.9/drivers/cpufreq/Kconfig.arm 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/drivers/cpufreq/Kconfig.arm 2012-12-06 17:04:46.991415300 +0100 @@ -2,6 +2,12 @@ # ARM CPU Frequency scaling drivers # +config ARM_KIRKWOOD_CPUFREQ + bool "KIRKWOOD CPU Frequency scaling support" + depends on ARCH_KIRKWOOD + help + This adds the CPUFreq driver for the Kirkwood SoC. + config ARM_OMAP2PLUS_CPUFREQ bool "TI OMAP2+" depends on ARCH_OMAP2PLUS diff -uNr '--exclude=out' linux-3.6.9/drivers/i2c/busses/i2c-mv64xxx.c linux-3.6.9-my/drivers/i2c/busses/i2c-mv64xxx.c --- linux-3.6.9/drivers/i2c/busses/i2c-mv64xxx.c 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/drivers/i2c/busses/i2c-mv64xxx.c 2012-12-06 17:04:46.995415336 +0100 @@ -64,7 +64,6 @@ MV64XXX_I2C_STATE_INVALID, MV64XXX_I2C_STATE_IDLE, MV64XXX_I2C_STATE_WAITING_FOR_START_COND, - MV64XXX_I2C_STATE_WAITING_FOR_RESTART, MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, @@ -76,7 +75,6 @@ MV64XXX_I2C_ACTION_INVALID, MV64XXX_I2C_ACTION_CONTINUE, MV64XXX_I2C_ACTION_SEND_START, - MV64XXX_I2C_ACTION_SEND_RESTART, MV64XXX_I2C_ACTION_SEND_ADDR_1, MV64XXX_I2C_ACTION_SEND_ADDR_2, MV64XXX_I2C_ACTION_SEND_DATA, @@ -98,7 +96,6 @@ u32 addr2; u32 bytes_left; u32 byte_posn; - u32 send_stop; u32 block; int rc; u32 freq_m; @@ -170,15 +167,8 @@ if ((drv_data->bytes_left == 0) || (drv_data->aborting && (drv_data->byte_posn != 0))) { - if (drv_data->send_stop) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - drv_data->state = MV64XXX_I2C_STATE_IDLE; - } else { - drv_data->action = - MV64XXX_I2C_ACTION_SEND_RESTART; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_RESTART; - } + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; } else { drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; drv_data->state = @@ -246,15 +236,6 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) { switch(drv_data->action) { - case MV64XXX_I2C_ACTION_SEND_RESTART: - drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - drv_data->block = 0; - wake_up_interruptible(&drv_data->waitq); - break; - case MV64XXX_I2C_ACTION_CONTINUE: writel(drv_data->cntl_bits, drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); @@ -413,8 +394,7 @@ } static int -mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, - int is_first, int is_last) +mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) { unsigned long flags; @@ -434,18 +414,10 @@ drv_data->bytes_left--; } } else { - if (is_first) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_START_COND; - } else { - drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; - } + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; } - drv_data->send_stop = is_last; drv_data->block = 1; mv64xxx_i2c_do_action(drv_data); spin_unlock_irqrestore(&drv_data->lock, flags); @@ -473,12 +445,9 @@ struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); int i, rc; - for (i = 0; i < num; i++) { - rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i], - i == 0, i + 1 == num); - if (rc < 0) + for (i=0; i + * + * Derived from ledtrig-timer.c which is: + * Copyright 2005-2006 Openedhand Ltd. + * Author: Richard Purdie + * + * 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 +#include +#include + +#include "leds.h" + +/* + * Configurable sysfs attributes: + * + * device_name - network device name to monitor + * + * interval - duration of LED blink, in milliseconds + * + * mode - either "none" (LED is off) or a space separated list + * of one or more of: + * link: LED's normal state reflects whether the link is up (has carrier) + * or not + * tx: LED blinks on transmitted data + * rx: LED blinks on receive data + * + * Some suggestions: + * + * Simple link status LED: + * $ echo netdev >someled/trigger + * $ echo eth0 >someled/device_name + * $ echo link >someled/mode + * + * Ethernet-style link/activity LED: + * $ echo netdev >someled/trigger + * $ echo eth0 >someled/device_name + * $ echo "link tx rx" >someled/mode + * + * Modem-style tx/rx LEDs: + * $ echo netdev >led1/trigger + * $ echo ppp0 >led1/device_name + * $ echo tx >led1/mode + * $ echo netdev >led2/trigger + * $ echo ppp0 >led2/device_name + * $ echo rx >led2/mode + * + */ + +#define MODE_LINK 1 +#define MODE_TX 2 +#define MODE_RX 4 + +struct led_netdev_data { + rwlock_t lock; + + struct timer_list timer; + struct notifier_block notifier; + + struct led_classdev *led_cdev; + struct net_device *net_dev; + + char device_name[IFNAMSIZ]; + unsigned interval; + unsigned mode; + unsigned link_up; + unsigned last_activity; +}; + +static void set_baseline_state(struct led_netdev_data *trigger_data) +{ + if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) + led_set_brightness(trigger_data->led_cdev, LED_FULL); + else + led_set_brightness(trigger_data->led_cdev, LED_OFF); + + if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && + trigger_data->link_up) + mod_timer(&trigger_data->timer, + jiffies + trigger_data->interval); + else + del_timer(&trigger_data->timer); +} + +static ssize_t led_device_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + + read_lock(&trigger_data->lock); + sprintf(buf, "%s\n", trigger_data->device_name); + read_unlock(&trigger_data->lock); + + return strlen(buf) + 1; +} + +static ssize_t led_device_name_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + + if (size < 0 || size >= IFNAMSIZ) + return -EINVAL; + + write_lock(&trigger_data->lock); + + strcpy(trigger_data->device_name, buf); + if (size > 0 && trigger_data->device_name[size-1] == '\n') + trigger_data->device_name[size-1] = 0; + + if (trigger_data->device_name[0] != 0) { + /* check for existing device to update from */ + struct net_device *dev = + dev_get_by_name(&init_net, trigger_data->device_name); + if (dev != NULL) { + unsigned int flags = dev_get_flags(dev); + trigger_data->net_dev = dev; + trigger_data->link_up = (flags & IFF_LOWER_UP) != 0; + } + /* updates LEDs, may start timers */ + set_baseline_state(trigger_data); + } + + write_unlock(&trigger_data->lock); + return size; +} + +static DEVICE_ATTR(device_name, 0644, + led_device_name_show, led_device_name_store); + +static ssize_t led_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + + read_lock(&trigger_data->lock); + + if (trigger_data->mode == 0) { + strcpy(buf, "none\n"); + } else { + if (trigger_data->mode & MODE_LINK) + strcat(buf, "link "); + if (trigger_data->mode & MODE_TX) + strcat(buf, "tx "); + if (trigger_data->mode & MODE_RX) + strcat(buf, "rx "); + strcat(buf, "\n"); + } + + read_unlock(&trigger_data->lock); + + return strlen(buf)+1; +} + +static ssize_t led_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + char copybuf[32]; + int new_mode = -1; + char *p, *token; + + /* take a copy since we don't want to trash the inbound buffer + when using strsep */ + strncpy(copybuf, buf, sizeof(copybuf)); + copybuf[sizeof(copybuf) - 1] = '\0'; + p = copybuf; + + while ((token = strsep(&p, " \t\n")) != NULL) { + if (!*token) + continue; + + if (new_mode == -1) + new_mode = 0; + + if (!strcmp(token, "none")) + new_mode = 0; + else if (!strcmp(token, "tx")) + new_mode |= MODE_TX; + else if (!strcmp(token, "rx")) + new_mode |= MODE_RX; + else if (!strcmp(token, "link")) + new_mode |= MODE_LINK; + else + return -EINVAL; + } + + if (new_mode == -1) + return -EINVAL; + + write_lock(&trigger_data->lock); + trigger_data->mode = new_mode; + set_baseline_state(trigger_data); + write_unlock(&trigger_data->lock); + + return size; +} + +static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store); + +static ssize_t led_interval_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + + read_lock(&trigger_data->lock); + sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval)); + read_unlock(&trigger_data->lock); + + return strlen(buf) + 1; +} + +static ssize_t led_interval_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + int ret = -EINVAL; + char *after; + unsigned long value = simple_strtoul(buf, &after, 10); + size_t count = after - buf; + + if (*after && isspace(*after)) + count++; + + /* impose some basic bounds on the timer interval */ + if (count == size && value >= 5 && value <= 10000) { + write_lock(&trigger_data->lock); + trigger_data->interval = msecs_to_jiffies(value); + set_baseline_state(trigger_data); /* resets timer */ + write_unlock(&trigger_data->lock); + ret = count; + } + + return ret; +} + +static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store); + +static int netdev_trig_notify(struct notifier_block *nb, + unsigned long evt, + void *dv) +{ + struct net_device *dev = dv; + struct led_netdev_data *trigger_data = + container_of(nb, struct led_netdev_data, notifier); + + if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && + evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) + return NOTIFY_DONE; + + write_lock(&trigger_data->lock); + + if (strcmp(dev->name, trigger_data->device_name)) + goto done; + + if (evt == NETDEV_REGISTER) { + if (trigger_data->net_dev != NULL) + dev_put(trigger_data->net_dev); + dev_hold(dev); + trigger_data->net_dev = dev; + trigger_data->link_up = 0; + goto done; + } + + if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) { + dev_put(trigger_data->net_dev); + trigger_data->net_dev = NULL; + goto done; + } + + /* UP / DOWN / CHANGE */ + + trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev)); + set_baseline_state(trigger_data); + +done: + write_unlock(&trigger_data->lock); + return NOTIFY_DONE; +} + +/* here's the real work! */ +static void netdev_trig_timer(unsigned long arg) +{ + struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg; + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *dev_stats; + unsigned new_activity; + + write_lock(&trigger_data->lock); + + if (!trigger_data->link_up || !trigger_data->net_dev || + (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) { + /* we don't need to do timer work, just reflect link state. */ + int on = (trigger_data->mode & MODE_LINK) != 0 && + trigger_data->link_up; + led_set_brightness(trigger_data->led_cdev, + on ? LED_FULL : LED_OFF); + goto no_restart; + } + + dev_stats = dev_get_stats(trigger_data->net_dev, &temp); + + new_activity = + ((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) + + ((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0); + + if (trigger_data->mode & MODE_LINK) { + /* base state is ON (link present) */ + /* if there's no link, we don't get this far + and the LED is off */ + + /* OFF -> ON always */ + /* ON -> OFF on activity */ + if (trigger_data->led_cdev->brightness == LED_OFF) + led_set_brightness(trigger_data->led_cdev, LED_FULL); + else if (trigger_data->last_activity != new_activity) + led_set_brightness(trigger_data->led_cdev, LED_OFF); + } else { + /* base state is OFF */ + /* ON -> OFF always */ + /* OFF -> ON on activity */ + if (trigger_data->led_cdev->brightness == LED_FULL) + led_set_brightness(trigger_data->led_cdev, LED_OFF); + else if (trigger_data->last_activity != new_activity) + led_set_brightness(trigger_data->led_cdev, LED_FULL); + } + + trigger_data->last_activity = new_activity; + mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); + +no_restart: + write_unlock(&trigger_data->lock); +} + +static void netdev_trig_activate(struct led_classdev *led_cdev) +{ + struct led_netdev_data *trigger_data; + int rc; + + trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); + if (!trigger_data) + return; + + rwlock_init(&trigger_data->lock); + + trigger_data->notifier.notifier_call = netdev_trig_notify; + trigger_data->notifier.priority = 10; + + setup_timer(&trigger_data->timer, netdev_trig_timer, + (unsigned long) trigger_data); + + trigger_data->led_cdev = led_cdev; + trigger_data->net_dev = NULL; + trigger_data->device_name[0] = 0; + + trigger_data->mode = 0; + trigger_data->interval = msecs_to_jiffies(50); + trigger_data->link_up = 0; + trigger_data->last_activity = 0; + + led_cdev->trigger_data = trigger_data; + + rc = device_create_file(led_cdev->dev, &dev_attr_device_name); + if (rc) + goto err_out; + rc = device_create_file(led_cdev->dev, &dev_attr_mode); + if (rc) + goto err_out_device_name; + rc = device_create_file(led_cdev->dev, &dev_attr_interval); + if (rc) + goto err_out_mode; + + register_netdevice_notifier(&trigger_data->notifier); + return; + +err_out_mode: + device_remove_file(led_cdev->dev, &dev_attr_mode); +err_out_device_name: + device_remove_file(led_cdev->dev, &dev_attr_device_name); +err_out: + led_cdev->trigger_data = NULL; + kfree(trigger_data); +} + +static void netdev_trig_deactivate(struct led_classdev *led_cdev) +{ + struct led_netdev_data *trigger_data = led_cdev->trigger_data; + + if (trigger_data) { + unregister_netdevice_notifier(&trigger_data->notifier); + + device_remove_file(led_cdev->dev, &dev_attr_device_name); + device_remove_file(led_cdev->dev, &dev_attr_mode); + device_remove_file(led_cdev->dev, &dev_attr_interval); + + write_lock(&trigger_data->lock); + + if (trigger_data->net_dev) { + dev_put(trigger_data->net_dev); + trigger_data->net_dev = NULL; + } + + write_unlock(&trigger_data->lock); + + del_timer_sync(&trigger_data->timer); + + kfree(trigger_data); + } +} + +static struct led_trigger netdev_led_trigger = { + .name = "netdev", + .activate = netdev_trig_activate, + .deactivate = netdev_trig_deactivate, +}; + +static int __init netdev_trig_init(void) +{ + return led_trigger_register(&netdev_led_trigger); +} + +static void __exit netdev_trig_exit(void) +{ + led_trigger_unregister(&netdev_led_trigger); +} + +module_init(netdev_trig_init); +module_exit(netdev_trig_exit); + +MODULE_AUTHOR("Oliver Jowett "); +MODULE_DESCRIPTION("Netdev LED trigger"); +MODULE_LICENSE("GPL"); diff -uNr '--exclude=out' linux-3.6.9/drivers/leds/ledtrig-sata-disk.c linux-3.6.9-my/drivers/leds/ledtrig-sata-disk.c --- linux-3.6.9/drivers/leds/ledtrig-sata-disk.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-3.6.9-my/drivers/leds/ledtrig-sata-disk.c 2012-12-06 17:04:46.995415336 +0100 @@ -0,0 +1,64 @@ +/* + * LED SATA-Disk Activity Trigger + * + * Copyright 2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 + +static void ledtrig_sata_timerfunc(unsigned long data); + +DEFINE_LED_TRIGGER(ledtrig_sata); +static DEFINE_TIMER(ledtrig_sata_timer, ledtrig_sata_timerfunc, 0, 0); +static int sata_activity; +static int sata_lastactivity; + +void ledtrig_sata_activity(void) +{ + sata_activity++; + if (!timer_pending(&ledtrig_sata_timer)) + mod_timer(&ledtrig_sata_timer, jiffies + msecs_to_jiffies(10)); +} +EXPORT_SYMBOL(ledtrig_sata_activity); + +static void ledtrig_sata_timerfunc(unsigned long data) +{ + if (sata_lastactivity != sata_activity) { + sata_lastactivity = sata_activity; + /* INT_MAX will set each LED to its maximum brightness */ + led_trigger_event(ledtrig_sata, INT_MAX); + mod_timer(&ledtrig_sata_timer, jiffies + msecs_to_jiffies(10)); + } else { + led_trigger_event(ledtrig_sata, LED_OFF); + } +} + +static int __init ledtrig_sata_init(void) +{ + led_trigger_register_simple("sata-disk", &ledtrig_sata); + return 0; +} + +static void __exit ledtrig_sata_exit(void) +{ + led_trigger_unregister_simple(ledtrig_sata); +} + +module_init(ledtrig_sata_init); +module_exit(ledtrig_sata_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("LED IDE Disk Activity Trigger"); +MODULE_LICENSE("GPL"); diff -uNr '--exclude=out' linux-3.6.9/drivers/leds/Makefile linux-3.6.9-my/drivers/leds/Makefile --- linux-3.6.9/drivers/leds/Makefile 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/drivers/leds/Makefile 2012-12-06 17:04:46.995415336 +0100 @@ -58,6 +58,8 @@ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o +obj-$(CONFIG_LEDS_TRIGGER_SATA_DISK) += ledtrig-sata-disk.o +obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o diff -uNr '--exclude=out' linux-3.6.9/include/linux/leds.h linux-3.6.9-my/include/linux/leds.h --- linux-3.6.9/include/linux/leds.h 2012-12-03 20:39:49.000000000 +0100 +++ linux-3.6.9-my/include/linux/leds.h 2012-12-06 17:04:46.995415336 +0100 @@ -194,6 +194,12 @@ #define ledtrig_ide_activity() do {} while(0) #endif +#ifdef CONFIG_LEDS_TRIGGER_SATA_DISK +extern void ledtrig_sata_activity(void); +#else +#define ledtrig_sata_activity() do {} while(0) +#endif + /* * Generic LED platform data for describing LED names and default triggers. */ diff -uNr '--exclude=out' linux-3.6.9/include/linux/nsa3xx-hwmon.h linux-3.6.9-my/include/linux/nsa3xx-hwmon.h --- linux-3.6.9/include/linux/nsa3xx-hwmon.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-3.6.9-my/include/linux/nsa3xx-hwmon.h 2012-12-06 17:04:46.995415336 +0100 @@ -0,0 +1,21 @@ +/* + * include/linux/nsa3xx.hwmon.h + * + * Platform data structure for ZyXEL NSA3xx hwmon driver + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __LINUX_NSA3XX_HWMON_H +#define __LINUX_NSA3XX_HWMON_H + +struct nsa3xx_hwmon_platform_data { + /* GPIO pins */ + unsigned act_pin; + unsigned clk_pin; + unsigned data_pin; +}; + +#endif /* __LINUX_NSA3XX_HWMON_H */