Another thread reminds me that I should share my little work for ls-wvl. The full model string is "LS-WVL/E-AP", without pre-installed hard disks. I don't know whether the one with pre-installed hard disk has exactly the same hardware or not (especially regarding the 512MB nand flash). But normally those patches SHOULD be applicable. But still, use them at YOUR OWN RISK. The patches came from various souces including myself. I'm trying my best to list the corresponding credit below, forgive me if someone is missing or listed incorrectly. Thanks for all the original authors.
The patches are listed in the sequence of applying.
1. Module alloc size check. This patch came from openwrt project.
Pastebin Link:
http://pastebin.com/j71499jJCode:
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2322,12 +2322,15 @@ static void dynamic_debug_remove(struct
void * __weak module_alloc(unsigned long size)
{
- return size == 0 ? NULL : vmalloc_exec(size);
+ return vmalloc_exec(size);
}
static void *module_alloc_update_bounds(unsigned long size)
{
- void *ret = module_alloc(size);
+ void *ret = NULL;
+
+ if (size)
+ ret = module_alloc(size);
if (ret) {
mutex_lock(&module_mutex);
2. Fix section mismatch warning. From openwrt.
Pastebin Link:
http://pastebin.com/TGsgjSiyCode:
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -192,7 +192,7 @@ void __init orion5x_init_early(void)
int orion5x_tclk;
-int __init orion5x_find_tclk(void)
+static __init int orion5x_find_tclk(void)
{
u32 dev, rev;
@@ -204,7 +204,7 @@ int __init orion5x_find_tclk(void)
return 166666667;
}
-static void orion5x_timer_init(void)
+static __init void orion5x_timer_init(void)
{
orion5x_tclk = orion5x_find_tclk();
--- a/arch/arm/mach-orion5x/addr-map.c
+++ b/arch/arm/mach-orion5x/addr-map.c
@@ -76,7 +76,7 @@ static int __init cpu_win_can_remap(cons
/*
* Description of the windows needed by the platform code
*/
-static struct __initdata orion_addr_map_cfg addr_map_cfg = {
+static struct orion_addr_map_cfg addr_map_cfg __initdata = {
.num_wins = 8,
.cpu_win_can_remap = cpu_win_can_remap,
.bridge_virt_base = ORION5X_BRIDGE_VIRT_BASE,
3. Kirkwood jumbo frame fix. Refer to this address for the detail:
h==p://www.spinics.net/lists/arm-kernel/msg186135.html
Part of the patches mentioned there had already been in the mainline kernel, but I don't know why the limit still was not set for kirkwood.
Of course I need to made some modification. But the only modification I need to mention here is that I moved the error detect to the last descriptor and I removed the under run error warning since for jumbo frame, this error came out so frequently).
Pastebin link:
http://pastebin.com/w4kUTQX2Code:
diff -rupN linux-3.3.4-orig/arch/arm/mach-dove/common.c linux-3.3.4/arch/arm/mach-dove/common.c
--- linux-3.3.4-orig/arch/arm/mach-dove/common.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/mach-dove/common.c 2012-05-07 17:58:22.746247051 +0800
@@ -88,7 +88,7 @@ void __init dove_ehci1_init(void)
****************************************************************************/
void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
- orion_ge00_init(eth_data,
+ orion_ge00_init(eth_data, 1600,
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM,
0, get_tclk());
}
diff -rupN linux-3.3.4-orig/arch/arm/mach-kirkwood/common.c linux-3.3.4/arch/arm/mach-kirkwood/common.c
--- linux-3.3.4-orig/arch/arm/mach-kirkwood/common.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/mach-kirkwood/common.c 2012-05-07 17:58:22.750247010 +0800
@@ -85,7 +85,7 @@ void __init kirkwood_ge00_init(struct mv
{
kirkwood_clk_ctrl |= CGC_GE0;
- orion_ge00_init(eth_data,
+ orion_ge00_init(eth_data, 1600,
GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
IRQ_KIRKWOOD_GE00_ERR, kirkwood_tclk);
}
@@ -99,7 +99,7 @@ void __init kirkwood_ge01_init(struct mv
kirkwood_clk_ctrl |= CGC_GE1;
- orion_ge01_init(eth_data,
+ orion_ge01_init(eth_data, 1600,
GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
IRQ_KIRKWOOD_GE01_ERR, kirkwood_tclk);
}
diff -rupN linux-3.3.4-orig/arch/arm/mach-mv78xx0/common.c linux-3.3.4/arch/arm/mach-mv78xx0/common.c
--- linux-3.3.4-orig/arch/arm/mach-mv78xx0/common.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/mach-mv78xx0/common.c 2012-05-07 17:58:22.758246917 +0800
@@ -197,7 +197,7 @@ void __init mv78xx0_ehci2_init(void)
****************************************************************************/
void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
- orion_ge00_init(eth_data,
+ orion_ge00_init(eth_data, 0,
GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
IRQ_MV78XX0_GE_ERR, get_tclk());
}
@@ -208,7 +208,7 @@ void __init mv78xx0_ge00_init(struct mv6
****************************************************************************/
void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
{
- orion_ge01_init(eth_data,
+ orion_ge01_init(eth_data, 0,
GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
NO_IRQ, get_tclk());
}
diff -rupN linux-3.3.4-orig/arch/arm/mach-orion5x/common.c linux-3.3.4/arch/arm/mach-orion5x/common.c
--- linux-3.3.4-orig/arch/arm/mach-orion5x/common.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/mach-orion5x/common.c 2012-05-07 17:58:22.762246865 +0800
@@ -92,7 +92,7 @@ void __init orion5x_ehci1_init(void)
****************************************************************************/
void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
{
- orion_ge00_init(eth_data,
+ orion_ge00_init(eth_data, 0,
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
IRQ_ORION5X_ETH_ERR, orion5x_tclk);
}
diff -rupN linux-3.3.4-orig/arch/arm/plat-orion/common.c linux-3.3.4/arch/arm/plat-orion/common.c
--- linux-3.3.4-orig/arch/arm/plat-orion/common.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/plat-orion/common.c 2012-05-07 17:58:22.762246865 +0800
@@ -257,6 +257,7 @@ static struct platform_device orion_ge00
};
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
+ int tx_csum_limit,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
@@ -264,6 +265,8 @@ void __init orion_ge00_init(struct mv643
{
fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
+ if (tx_csum_limit > 0)
+ orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
ge_complete(&orion_ge00_shared_data, tclk,
orion_ge00_resources, irq, &orion_ge00_shared,
eth_data, &orion_ge00);
@@ -310,6 +313,7 @@ static struct platform_device orion_ge01
};
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
+ int tx_csum_limit,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
@@ -317,6 +321,8 @@ void __init orion_ge01_init(struct mv643
{
fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
+ if (tx_csum_limit > 0)
+ orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
ge_complete(&orion_ge01_shared_data, tclk,
orion_ge01_resources, irq, &orion_ge01_shared,
eth_data, &orion_ge01);
diff -rupN linux-3.3.4-orig/arch/arm/plat-orion/include/plat/common.h linux-3.3.4/arch/arm/plat-orion/include/plat/common.h
--- linux-3.3.4-orig/arch/arm/plat-orion/include/plat/common.h 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/plat-orion/include/plat/common.h 2012-05-07 17:58:22.778246655 +0800
@@ -37,12 +37,14 @@ void __init orion_rtc_init(unsigned long
unsigned long irq);
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
+ int tx_csum_limit,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
+ int tx_csum_limit,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
diff -rupN linux-3.3.4-orig/drivers/net/ethernet/marvell/mv643xx_eth.c linux-3.3.4/drivers/net/ethernet/marvell/mv643xx_eth.c
--- linux-3.3.4-orig/drivers/net/ethernet/marvell/mv643xx_eth.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/drivers/net/ethernet/marvell/mv643xx_eth.c 2012-05-07 17:58:22.794246454 +0800
@@ -965,12 +965,15 @@ static int txq_reclaim(struct tx_queue *
txq->tx_desc_count--;
skb = NULL;
- if (cmd_sts & TX_LAST_DESC)
+ if (cmd_sts & TX_LAST_DESC) {
skb = __skb_dequeue(&txq->tx_skb);
- if (cmd_sts & ERROR_SUMMARY) {
- netdev_info(mp->dev, "tx error\n");
- mp->dev->stats.tx_errors++;
+ /*Error status only valid for last descriptor*/
+ /*ignore under run error*/
+ if (unlikely(cmd_sts & ERROR_SUMMARY) && unlikely(!(cmd_sts & 0x00000002))) {
+ netdev_info(mp->dev, "tx error\n");
+ mp->dev->stats.tx_errors++;
+ }
}
if (cmd_sts & TX_FIRST_DESC) {
4. A patch to fix the hardware crypto for orion chip, not kirkwood. I wrote it. And very limited test was done against it. Let me know if you need this. But currently someone is working on the DMA support for the MV_CESA, so I think you should looking at that instead.
5. Here the LS-WVL support comes. The patch was based on the LS-VL patch found here, and modified by myself:
h==p://www.yamasita.jp/cgi-bin/BBS/eztree.cgi
Pastebin link:
http://pastebin.com/yDSBf7qYCode:
diff -rupN linux-3.3.4-orig/arch/arm/mach-kirkwood/Kconfig linux-3.3.4/arch/arm/mach-kirkwood/Kconfig
--- linux-3.3.4-orig/arch/arm/mach-kirkwood/Kconfig 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/mach-kirkwood/Kconfig 2012-05-07 17:58:22.750247010 +0800
@@ -130,6 +130,12 @@ config MACH_T5325
Say 'Y' here if you want your kernel to support the
HP t5325 Thin Client.
+config MACH_LSWVL
+ bool "Buffalo LS-WVL Series"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo LS-WVL/E-AP NAS
+
endmenu
endif
diff -rupN linux-3.3.4-orig/arch/arm/mach-kirkwood/lswvl-setup.c linux-3.3.4/arch/arm/mach-kirkwood/lswvl-setup.c
--- linux-3.3.4-orig/arch/arm/mach-kirkwood/lswvl-setup.c 1970-01-01 07:00:00.000000000 +0700
+++ linux-3.3.4/arch/arm/mach-kirkwood/lswvl-setup.c 2012-05-07 17:58:22.754246966 +0800
@@ -0,0 +1,366 @@
+/*
+ * arch/arm/mach-kirkwood/lswvl-setup.c
+ *
+ * Buffalo LS-WVL Series Setup
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/orion_nand.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+
+/*****************************************************************************
+ * 512MB NAND Flash on Device bus CS0
+ ****************************************************************************/
+static struct mtd_partition lswvl_nand_parts[] = {
+ {
+ .name = "boot",
+ .offset = 0,
+ .size = 16 * 1024 * 1024,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 488 * 1024 * 1024,
+ }, {
+ .name = "reserve",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+/*****************************************************************************
+ * 512KB NOR Flash on BOOT Device
+ ****************************************************************************/
+static struct mtd_partition lswvl_partitions[] = {
+ {
+ .name = "u-boot",
+ .size = 0x80000,
+ .offset = 0x00000,
+ //.mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+};
+
+static struct flash_platform_data lswvl_spi_slave_data = {
+ .parts = lswvl_partitions,
+ .nr_parts = ARRAY_SIZE(lswvl_partitions),
+};
+
+static struct spi_board_info __initdata lswvl_spi_slave_info[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &lswvl_spi_slave_data,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ },
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+static struct mv643xx_eth_platform_data lswvl_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lswvl_sata_data = {
+ .n_ports = 2,
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+#define LSWVL_GPIO_LED_HDDERR0 34
+#define LSWVL_GPIO_LED_HDDERR1 35
+#define LSWVL_GPIO_LED_ALARM 36
+#define LSWVL_GPIO_LED_FUNC_RED 37
+#define LSWVL_GPIO_LED_INFO 38
+#define LSWVL_GPIO_LED_FUNC_BLUE 39
+#define LSWVL_GPIO_LED_PWR 40
+
+static struct gpio_led lswvl_led_pins[] = {
+ {
+ .name = "lswvl:hdderr:0",
+ .gpio = LSWVL_GPIO_LED_HDDERR0,
+ }, {
+ .name = "lswvl:hdderr:1",
+ .gpio = LSWVL_GPIO_LED_HDDERR1,
+ }, {
+ .name = "lswvl:alarm:red",
+ .gpio = LSWVL_GPIO_LED_ALARM,
+ }, {
+ .name = "lswvl:func:red",
+ .gpio = LSWVL_GPIO_LED_FUNC_RED,
+ }, {
+ .name = "lswvl:info:amber",
+ .gpio = LSWVL_GPIO_LED_INFO,
+ }, {
+ .name = "lswvl:func:blue",
+ .gpio = LSWVL_GPIO_LED_FUNC_BLUE,
+ }, {
+ .name = "lswvl:power:blue",
+ .default_trigger = "default-on",
+ .gpio = LSWVL_GPIO_LED_PWR,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data lswvl_led_data = {
+ .leds = lswvl_led_pins,
+ .num_leds = ARRAY_SIZE(lswvl_led_pins),
+};
+
+static struct platform_device lswvl_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lswvl_led_data,
+ }
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSWVL_GPIO_HDD0_POWER 8
+#define LSWVL_GPIO_HDD1_POWER 9
+#define LSWVL_GPIO_USB_POWER 12
+
+/*****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#define LSWVL_GPIO_KEY_FUNC 45
+#define LSWVL_GPIO_KEY_POWER 46
+#define LSWVL_GPIO_KEY_AUTOPOWER 47
+#define LSWVL_SW_POWER 0x00
+#define LSWVL_SW_AUTOPOWER 0x01
+#define LSWVL_SW_FUNC 0x02
+
+static struct gpio_keys_button lswvl_buttons[] = {
+ {
+ .type = EV_KEY,
+ .code = BTN_1,
+ .gpio = LSWVL_GPIO_KEY_POWER,
+ .desc = "power-on",
+ .active_low = 1,
+ }, {
+ .type = EV_KEY,
+ .code = BTN_2,
+ .gpio = LSWVL_GPIO_KEY_AUTOPOWER,
+ .desc = "power-auto",
+ .active_low = 1,
+ }, {
+ .type = EV_KEY,
+ .code = BTN_0,
+ .gpio = LSWVL_GPIO_KEY_FUNC,
+ .desc = "function",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data lswvl_button_data = {
+ .buttons = lswvl_buttons,
+ .nbuttons = ARRAY_SIZE(lswvl_buttons),
+};
+
+static struct platform_device lswvl_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lswvl_button_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Fan
+ ****************************************************************************/
+#define LSWVL_GPIO_FAN_HIGH 16
+#define LSWVL_GPIO_FAN_LOW 17
+#define LSWVL_GPIO_FAN_LOCK 43
+
+static struct gpio_fan_alarm lswvl_alarm = {
+ .gpio = LSWVL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lswvl_speeds[] = {
+ {
+ .rpm = 0,
+ .ctrl_val = 3,
+ }, {
+ .rpm = 1500,
+ .ctrl_val = 1,
+ }, {
+ .rpm = 3250,
+ .ctrl_val = 2,
+ }, {
+ .rpm = 5000,
+ .ctrl_val = 0,
+ }
+};
+
+static int lswvl_gpio_list[] = {
+ LSWVL_GPIO_FAN_HIGH, LSWVL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lswvl_fan_data = {
+ .num_ctrl = ARRAY_SIZE(lswvl_gpio_list),
+ .ctrl = lswvl_gpio_list,
+ .alarm = &lswvl_alarm,
+ .num_speed = ARRAY_SIZE(lswvl_speeds),
+ .speed = lswvl_speeds,
+};
+
+static struct platform_device lswvl_fan_device = {
+ .name = "gpio-fan",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lswvl_fan_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Data
+ ****************************************************************************/
+
+static unsigned int lswvl_mpp_config[] __initdata = {
+ MPP0_NF_IO2,
+ MPP1_NF_IO3,
+ MPP2_NF_IO4,
+ MPP3_NF_IO5,
+ MPP4_NF_IO6,
+ MPP5_NF_IO7,
+ MPP6_SYSRST_OUTn,
+ MPP7_SPI_SCn,
+ MPP8_GPIO, /* HDD Power */
+ MPP9_GPIO, /* HDD Power */
+ MPP10_UART0_TXD,
+ MPP11_UART0_RXD,
+ MPP12_GPO, /* USB VBUS EN */
+ MPP13_GPIO,
+ MPP14_GPIO,
+ MPP15_GPIO,
+ MPP16_GPIO, /* FAN HIGH: on:0, off:1 */
+ MPP17_GPIO, /* FAN LOW: on:0, off:1 */
+ MPP18_NF_IO0,
+ MPP19_NF_IO1,
+ MPP20_GPIO,
+ MPP21_GPIO,
+ MPP22_GPIO,
+ MPP23_GPIO,
+ MPP24_GPIO,
+ MPP25_GPIO,
+ MPP26_GPIO,
+ MPP27_GPIO,
+ MPP28_GPIO,
+ MPP29_GPIO,
+ MPP30_GPIO,
+ MPP31_GPIO,
+ MPP32_GPIO,
+ MPP33_GPO,
+ MPP34_GPIO, /*HDD ERROR LED 0*/
+ MPP35_GPIO, /*HDD ERROR LED 1*/
+ MPP36_GPIO, /* ALARM LED */
+ MPP37_GPIO, /* FUNC RED LED */
+ MPP38_GPIO, /* INFO LED */
+ MPP39_GPIO, /* FUNC LED */
+ MPP40_GPIO, /* POWER LED */
+ MPP41_GPIO,
+ MPP42_GPIO,
+ MPP43_GPIO, /* FAN LOCK */
+ MPP44_GPIO,
+ MPP45_GPIO, /* FUNC SW */
+ MPP46_GPIO, /* POWER SW */
+ MPP47_GPIO, /* POWER AUTO SW */
+ MPP48_GPIO, /* UART EN */
+ MPP49_GPIO,
+ 0
+};
+
+/*****************************************************************************
+ * LS-WVL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the LS-WVL, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ * to move the switch to ON position
+ *
+ */
+
+static void lswvl_power_off(void)
+{
+ kirkwood_restart('h', NULL);
+}
+
+static void __init lswvl_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(lswvl_mpp_config);
+
+ /*
+ * Configure peripherals.
+ */
+ kirkwood_ge00_init(&lswvl_ge00_data);
+ kirkwood_uart0_init();
+ kirkwood_uart1_init();
+ kirkwood_ehci_init();
+ kirkwood_sata_init(&lswvl_sata_data);
+
+ spi_register_board_info(lswvl_spi_slave_info,
+ ARRAY_SIZE(lswvl_spi_slave_info));
+ kirkwood_spi_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(lswvl_nand_parts), 25);
+
+ platform_device_register(&lswvl_leds);
+ platform_device_register(&lswvl_button_device);
+ platform_device_register(&lswvl_fan_device);
+
+ /* usb power on */
+ gpio_set_value(LSWVL_GPIO_USB_POWER, 1);
+
+ /* register power-off method */
+ pm_power_off = lswvl_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LSWVL, "Buffalo LS-WVL/E-AP NAS")
+ .atag_offset = 0x100,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+ .init_machine = lswvl_init,
+ .restart = kirkwood_restart,
+MACHINE_END
+
diff -rupN linux-3.3.4-orig/arch/arm/mach-kirkwood/Makefile linux-3.3.4/arch/arm/mach-kirkwood/Makefile
--- linux-3.3.4-orig/arch/arm/mach-kirkwood/Makefile 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/mach-kirkwood/Makefile 2012-05-07 17:58:22.754246966 +0800
@@ -18,5 +18,6 @@ obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2
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_LSWVL) += lswvl-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
6. This patch is needed to support SPI and Nand Flash MPP mulitiplex. Otherwise you won't be able to use the nand flash. I wrote it based on buffalo's gpl source. But if you try to use the nor and nand flash at the same time, error may happen. Maybe not. I don't know. It's just the same way as buffalo's stock firmware.
Use it at your own risk!Pastebin link:
http://pastebin.com/KEp0bSp9Code:
diff -rupN linux-3.3.4-orig/arch/arm/plat-orion/mpp.c linux-3.3.4/arch/arm/plat-orion/mpp.c
--- linux-3.3.4-orig/arch/arm/plat-orion/mpp.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/plat-orion/mpp.c 2012-05-07 17:58:22.778246655 +0800
@@ -15,6 +15,7 @@
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <plat/mpp.h>
+#include <asm/mach-types.h>
/* Address of the ith MPP control register */
static __init unsigned long mpp_ctrl_addr(unsigned int i,
@@ -75,3 +76,37 @@ void __init orion_mpp_conf(unsigned int
}
printk("\n");
}
+
+#ifdef CONFIG_MACH_LSWVL
+
+static u32 boot_mpp_value = 0x21111111;
+/*
+ * change MPP[3:1] to SPI mode
+ */
+void lswvl_setup_spi_mpp(void)
+{
+ u32 spival = 0;
+ u32 bootval = 0;
+
+ spival = 0x00002220;
+ boot_mpp_value = bootval = readl(mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+ bootval &= 0xffff000f;
+ writel(spival | bootval, mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+}
+
+/*
+ * change back MPP[3:1] to default configuration
+ */
+void lswvl_reset_mpp(void)
+{
+ u32 spival = 0;
+ u32 bootval = 0;
+
+ spival = readl(mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+ spival &= 0xffff000f;
+ bootval = boot_mpp_value & ~0xffff000f;
+ writel(spival | bootval, mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+}
+
+#endif
+
diff -rupN linux-3.3.4-orig/drivers/spi/spi-orion.c linux-3.3.4/drivers/spi/spi-orion.c
--- linux-3.3.4-orig/drivers/spi/spi-orion.c 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/drivers/spi/spi-orion.c 2012-05-07 17:58:22.802246355 +0800
@@ -19,6 +19,12 @@
#include <linux/spi/orion_spi.h>
#include <linux/module.h>
#include <asm/unaligned.h>
+#include <asm/mach-types.h>
+
+#ifdef CONFIG_MACH_LSWVL
+void lswvl_setup_spi_mpp(void);
+void lswvl_reset_mpp(void);
+#endif
#define DRIVER_NAME "orion_spi"
@@ -141,6 +147,9 @@ orion_spi_setup_transfer(struct spi_devi
unsigned int bits_per_word = spi->bits_per_word;
int rc;
+#ifdef CONFIG_MACH_LSWVL
+ lswvl_setup_spi_mpp();
+#endif
orion_spi = spi_master_get_devdata(spi->master);
if ((t != NULL) && t->speed_hz)
@@ -152,16 +161,36 @@ orion_spi_setup_transfer(struct spi_devi
rc = orion_spi_baudrate_set(spi, speed);
if (rc)
return rc;
-
+#ifdef CONFIG_MACH_LSWVL
+ rc = orion_spi_set_transfer_size(orion_spi, bits_per_word);
+ lswvl_reset_mpp();
+ return rc;
+#else
return orion_spi_set_transfer_size(orion_spi, bits_per_word);
+#endif
}
static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
{
if (enable)
+#ifdef CONFIG_MACH_LSWVL
+ {
+ lswvl_setup_spi_mpp();
+ udelay(1);
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+ }
+#else
+ orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+#endif
else
+#ifdef CONFIG_MACH_LSWVL
+ {
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+ lswvl_reset_mpp();
+ }
+#else
+ orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+#endif
}
static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
@@ -361,8 +390,17 @@ static int orion_spi_setup(struct spi_de
/* Fix ac timing if required. */
if (orion_spi->spi_info->enable_clock_fix)
+#ifdef CONFIG_MACH_LSWVL
+ {
+ lswvl_setup_spi_mpp();
+ orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+ (1 << 14));
+ lswvl_reset_mpp();
+ }
+#else
orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
(1 << 14));
+#endif
if ((spi->max_speed_hz == 0)
|| (spi->max_speed_hz > orion_spi->max_speed))
7. This is a patch to let the compiler always cross compile the kernel for ARM, using ubuntu's ARM toolchain. Obviously not mandatory.
Pastebin link:
http://pastebin.com/Yme2xSiwCode:
--- linux-3.3.4-orig/Makefile 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/Makefile 2012-05-07 17:58:22.834245952 +0800
@@ -192,8 +192,8 @@
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
export KBUILD_BUILDHOST := $(SUBARCH)
-ARCH ?= $(SUBARCH)
-CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
+ARCH ?= arm
+CROSS_COMPILE ?= arm-linux-gnueabi-
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
8. Extra modification of the compiler parameters to further reduce the kernel size. From openwrt.
Pastebin link:
http://pastebin.com/A4atvVH5Code:
--- a/Makefile
+++ b/Makefile
@@ -559,9 +559,9 @@ endif # $(dot-config)
all: vmlinux
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS += -Os
+KBUILD_CFLAGS += -Os -fno-caller-saves
else
-KBUILD_CFLAGS += -O2
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch -fno-caller-saves
endif
include $(srctree)/arch/$(SRCARCH)/Makefile
@@ -620,6 +620,9 @@ endif
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
+# improve gcc optimization
+CFLAGS += $(call cc-option,-funit-at-a-time,)
+
# warn about C99 declaration after statement
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
9. Fix the mach-type for lspro and ls-wvl. So you don't need to modify the kernel image after it is generated. Don't use it if you don't know what it is. But if you want to support ls-wvl, you actually need the lswvl line. the linkstation_pro line was for my lspro.
Pastebin link:
http://pastebin.com/bjb2ghmbCode:
diff -rupN linux-3.3.4-orig/arch/arm/tools/mach-types linux-3.3.4/arch/arm/tools/mach-types
--- linux-3.3.4-orig/arch/arm/tools/mach-types 2012-04-28 01:17:35.000000000 +0800
+++ linux-3.3.4/arch/arm/tools/mach-types 2012-05-07 17:58:22.782246605 +0800
@@ -117,7 +117,9 @@ omap_h3 MACH_OMAP_H3 OMAP_H3 509
omap_h4 MACH_OMAP_H4 OMAP_H4 510
omap_osk MACH_OMAP_OSK OMAP_OSK 515
tosa MACH_TOSA TOSA 520
+linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 526
avila MACH_AVILA AVILA 526
+lswvl MACH_LSWVL LSWVL 527
edb9302 MACH_EDB9302 EDB9302 538
husky MACH_HUSKY HUSKY 543
shepherd MACH_SHEPHERD SHEPHERD 545
@@ -274,7 +276,6 @@ at91cap9adk MACH_AT91CAP9ADK AT91CAP9AD
mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574
vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578
terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584
-linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585
e350 MACH_E350 E350 1596
ts409 MACH_TS409 TS409 1601
rsi_ews MACH_RSI_EWS RSI_EWS 1609
After applying those patches, you should get a 3.3 kernel (3.4 kernel shall also be OK. I'm currently using 3.4.7 now) that can be used for ls-wvl. Then follow the normal kernel (cross-)compile and install instructions. I use debian for the user space. But you need something else to support the switch on the back of the machine and the fan. Instead of a shell script to poll the switch continuously, I used udev rule to do that (together with a script). But that need another patch. For the fan, a script is used as usual.
Hope this could be useful for other LS-WVL owners.
Be back soon for fan and switch topic. (I need to get the access to my ls-wvl for the script for the fan and switch).
Those patches actually had been available for months (the oldest version was based on the 2.6.38 kernel). But I didn't find time to share them (forgive my laziness. You must understand for me to write such a post in English is really hard).