diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-04-13 13:38:49 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2012-04-13 13:38:49 +0000 |
commit | 99768ccb7c7593c36ebca250bd5cbe1d6b74d166 (patch) | |
tree | f818c307d0ecd73d24d27991e9f8f989ce8fe499 /target/linux/ixp4xx/patches-3.3 | |
parent | ec667208e67461068515f4502304f77dcd6803a4 (diff) | |
download | upstream-99768ccb7c7593c36ebca250bd5cbe1d6b74d166.tar.gz upstream-99768ccb7c7593c36ebca250bd5cbe1d6b74d166.tar.bz2 upstream-99768ccb7c7593c36ebca250bd5cbe1d6b74d166.zip |
ixp4xx: add support for linux 3.3.1
SVN-Revision: 31275
Diffstat (limited to 'target/linux/ixp4xx/patches-3.3')
40 files changed, 6273 insertions, 0 deletions
diff --git a/target/linux/ixp4xx/patches-3.3/010-backport_ixp4xx_mtd_fix.patch b/target/linux/ixp4xx/patches-3.3/010-backport_ixp4xx_mtd_fix.patch new file mode 100644 index 0000000000..426714f933 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/010-backport_ixp4xx_mtd_fix.patch @@ -0,0 +1,43 @@ +commit a3c1e3b732b3708a80e4035b9d845f3f7c7dd0c9 +Author: Marc Kleine-Budde <mkl@blackshift.org> +Date: Wed Feb 8 20:24:29 2012 +0100 + + mtd: ixp4xx: oops in ixp4xx_flash_probe + + In commit "c797533 mtd: abstract last MTD partition parser argument" the + third argument of "mtd_device_parse_register()" changed from start address + of the MTD device to a pointer to a struct. + + The "ixp4xx_flash_probe()" function was not converted properly, causing + an oops during boot. + + This patch fixes the problem by filling the needed information into a + "struct mtd_part_parser_data" and passing it to + "mtd_device_parse_register()". + + Signed-off-by: Marc Kleine-Budde <mkl@blackshift.org> + Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> + Cc: stable@kernel.org [3.2+] + Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> + +--- a/drivers/mtd/maps/ixp4xx.c ++++ b/drivers/mtd/maps/ixp4xx.c +@@ -182,6 +182,9 @@ static int ixp4xx_flash_probe(struct pla + { + struct flash_platform_data *plat = dev->dev.platform_data; + struct ixp4xx_flash_info *info; ++ struct mtd_part_parser_data ppdata = { ++ .origin = dev->resource->start, ++ }; + int err = -1; + + if (!plat) +@@ -247,7 +250,7 @@ static int ixp4xx_flash_probe(struct pla + /* Use the fast version */ + info->map.write = ixp4xx_write16; + +- err = mtd_device_parse_register(info->mtd, probes, dev->resource->start, ++ err = mtd_device_parse_register(info->mtd, probes, &ppdata, + plat->parts, plat->nr_parts); + if (err) { + printk(KERN_ERR "Could not parse partitions\n"); diff --git a/target/linux/ixp4xx/patches-3.3/020-gateworks_i2c_pld.patch b/target/linux/ixp4xx/patches-3.3/020-gateworks_i2c_pld.patch new file mode 100644 index 0000000000..652080b232 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/020-gateworks_i2c_pld.patch @@ -0,0 +1,423 @@ +--- /dev/null ++++ b/drivers/gpio/gw_i2c_pld.c +@@ -0,0 +1,373 @@ ++/* ++ * Gateworks I2C PLD GPIO expander ++ * ++ * Copyright (C) 2009 Gateworks Corporation ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/hardirq.h> ++#include <linux/i2c.h> ++#include <linux/i2c/gw_i2c_pld.h> ++#include <linux/module.h> ++#include <linux/export.h> ++#include <asm/gpio.h> ++ ++static const struct i2c_device_id gw_i2c_pld_id[] = { ++ { "gw_i2c_pld", 8 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, gw_i2c_pld_id); ++ ++/* ++ * The Gateworks I2C PLD chip only expose one read and one ++ * write register. Writing a "one" bit (to match the reset state) lets ++ * that pin be used as an input. It is an open-drain model. ++ */ ++ ++struct gw_i2c_pld { ++ struct gpio_chip chip; ++ struct i2c_client *client; ++ unsigned out; /* software latch */ ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * The Gateworks I2C PLD chip does not properly send the acknowledge bit ++ * thus we cannot use standard i2c_smbus functions. We have recreated ++ * our own here, but we still use the rt_mutex_lock to lock the i2c_bus ++ * as the device still exists on the I2C bus. ++*/ ++ ++#define PLD_SCL_GPIO 6 ++#define PLD_SDA_GPIO 7 ++ ++#define SCL_LO() gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_LOW) ++#define SCL_HI() gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_HIGH) ++#define SCL_EN() gpio_line_config(PLD_SCL_GPIO, IXP4XX_GPIO_OUT) ++#define SDA_LO() gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_LOW) ++#define SDA_HI() gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_HIGH) ++#define SDA_EN() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_OUT) ++#define SDA_DIS() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_IN) ++#define SDA_IN(x) gpio_line_get(PLD_SDA_GPIO, &x); ++ ++static int i2c_pld_write_byte(int address, int byte) ++{ ++ int i; ++ ++ address = (address << 1) & ~0x1; ++ ++ SDA_HI(); ++ SDA_EN(); ++ SCL_EN(); ++ SCL_HI(); ++ SDA_LO(); ++ SCL_LO(); ++ ++ for (i = 7; i >= 0; i--) ++ { ++ if (address & (1 << i)) ++ SDA_HI(); ++ else ++ SDA_LO(); ++ ++ SCL_HI(); ++ SCL_LO(); ++ } ++ ++ SDA_DIS(); ++ SCL_HI(); ++ SDA_IN(i); ++ SCL_LO(); ++ SDA_EN(); ++ ++ for (i = 7; i >= 0; i--) ++ { ++ if (byte & (1 << i)) ++ SDA_HI(); ++ else ++ SDA_LO(); ++ SCL_HI(); ++ SCL_LO(); ++ } ++ ++ SDA_DIS(); ++ SCL_HI(); ++ SDA_IN(i); ++ SCL_LO(); ++ ++ SDA_HI(); ++ SDA_EN(); ++ ++ SDA_LO(); ++ SCL_HI(); ++ SDA_HI(); ++ SCL_LO(); ++ SCL_HI(); ++ ++ return 0; ++} ++ ++static unsigned int i2c_pld_read_byte(int address) ++{ ++ int i = 0, byte = 0; ++ int bit; ++ ++ address = (address << 1) | 0x1; ++ ++ SDA_HI(); ++ SDA_EN(); ++ SCL_EN(); ++ SCL_HI(); ++ SDA_LO(); ++ SCL_LO(); ++ ++ for (i = 7; i >= 0; i--) ++ { ++ if (address & (1 << i)) ++ SDA_HI(); ++ else ++ SDA_LO(); ++ ++ SCL_HI(); ++ SCL_LO(); ++ } ++ ++ SDA_DIS(); ++ SCL_HI(); ++ SDA_IN(i); ++ SCL_LO(); ++ SDA_EN(); ++ ++ SDA_DIS(); ++ for (i = 7; i >= 0; i--) ++ { ++ SCL_HI(); ++ SDA_IN(bit); ++ byte |= bit << i; ++ SCL_LO(); ++ } ++ ++ SDA_LO(); ++ SCL_HI(); ++ SDA_HI(); ++ SCL_LO(); ++ SCL_HI(); ++ ++ return byte; ++} ++ ++ ++static int gw_i2c_pld_input8(struct gpio_chip *chip, unsigned offset) ++{ ++ int ret; ++ struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip); ++ struct i2c_adapter *adap = gpio->client->adapter; ++ ++ if (in_atomic() || irqs_disabled()) { ++ ret = rt_mutex_trylock(&adap->bus_lock); ++ if (!ret) ++ /* I2C activity is ongoing. */ ++ return -EAGAIN; ++ } else { ++ rt_mutex_lock(&adap->bus_lock); ++ } ++ ++ gpio->out |= (1 << offset); ++ ++ ret = i2c_pld_write_byte(gpio->client->addr, gpio->out); ++ ++ rt_mutex_unlock(&adap->bus_lock); ++ ++ return ret; ++} ++ ++static int gw_i2c_pld_get8(struct gpio_chip *chip, unsigned offset) ++{ ++ int ret; ++ s32 value; ++ struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip); ++ struct i2c_adapter *adap = gpio->client->adapter; ++ ++ if (in_atomic() || irqs_disabled()) { ++ ret = rt_mutex_trylock(&adap->bus_lock); ++ if (!ret) ++ /* I2C activity is ongoing. */ ++ return -EAGAIN; ++ } else { ++ rt_mutex_lock(&adap->bus_lock); ++ } ++ ++ value = i2c_pld_read_byte(gpio->client->addr); ++ ++ rt_mutex_unlock(&adap->bus_lock); ++ ++ return (value < 0) ? 0 : (value & (1 << offset)); ++} ++ ++static int gw_i2c_pld_output8(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ int ret; ++ ++ struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip); ++ struct i2c_adapter *adap = gpio->client->adapter; ++ ++ unsigned bit = 1 << offset; ++ ++ if (in_atomic() || irqs_disabled()) { ++ ret = rt_mutex_trylock(&adap->bus_lock); ++ if (!ret) ++ /* I2C activity is ongoing. */ ++ return -EAGAIN; ++ } else { ++ rt_mutex_lock(&adap->bus_lock); ++ } ++ ++ ++ if (value) ++ gpio->out |= bit; ++ else ++ gpio->out &= ~bit; ++ ++ ret = i2c_pld_write_byte(gpio->client->addr, gpio->out); ++ ++ rt_mutex_unlock(&adap->bus_lock); ++ ++ return ret; ++} ++ ++static void gw_i2c_pld_set8(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ gw_i2c_pld_output8(chip, offset, value); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int gw_i2c_pld_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct gw_i2c_pld_platform_data *pdata; ++ struct gw_i2c_pld *gpio; ++ int status; ++ ++ pdata = client->dev.platform_data; ++ if (!pdata) ++ return -ENODEV; ++ ++ /* Allocate, initialize, and register this gpio_chip. */ ++ gpio = kzalloc(sizeof *gpio, GFP_KERNEL); ++ if (!gpio) ++ return -ENOMEM; ++ ++ gpio->chip.base = pdata->gpio_base; ++ gpio->chip.can_sleep = 1; ++ gpio->chip.dev = &client->dev; ++ gpio->chip.owner = THIS_MODULE; ++ ++ gpio->chip.ngpio = pdata->nr_gpio; ++ gpio->chip.direction_input = gw_i2c_pld_input8; ++ gpio->chip.get = gw_i2c_pld_get8; ++ gpio->chip.direction_output = gw_i2c_pld_output8; ++ gpio->chip.set = gw_i2c_pld_set8; ++ ++ gpio->chip.label = client->name; ++ ++ gpio->client = client; ++ i2c_set_clientdata(client, gpio); ++ ++ gpio->out = 0xFF; ++ ++ status = gpiochip_add(&gpio->chip); ++ if (status < 0) ++ goto fail; ++ ++ dev_info(&client->dev, "gpios %d..%d on a %s%s\n", ++ gpio->chip.base, ++ gpio->chip.base + gpio->chip.ngpio - 1, ++ client->name, ++ client->irq ? " (irq ignored)" : ""); ++ ++ /* Let platform code set up the GPIOs and their users. ++ * Now is the first time anyone could use them. ++ */ ++ if (pdata->setup) { ++ status = pdata->setup(client, ++ gpio->chip.base, gpio->chip.ngpio, ++ pdata->context); ++ if (status < 0) ++ dev_warn(&client->dev, "setup --> %d\n", status); ++ } ++ ++ return 0; ++ ++fail: ++ dev_dbg(&client->dev, "probe error %d for '%s'\n", ++ status, client->name); ++ kfree(gpio); ++ return status; ++} ++ ++static int gw_i2c_pld_remove(struct i2c_client *client) ++{ ++ struct gw_i2c_pld_platform_data *pdata = client->dev.platform_data; ++ struct gw_i2c_pld *gpio = i2c_get_clientdata(client); ++ int status = 0; ++ ++ if (pdata->teardown) { ++ status = pdata->teardown(client, ++ gpio->chip.base, gpio->chip.ngpio, ++ pdata->context); ++ if (status < 0) { ++ dev_err(&client->dev, "%s --> %d\n", ++ "teardown", status); ++ return status; ++ } ++ } ++ ++ status = gpiochip_remove(&gpio->chip); ++ if (status == 0) ++ kfree(gpio); ++ else ++ dev_err(&client->dev, "%s --> %d\n", "remove", status); ++ return status; ++} ++ ++static struct i2c_driver gw_i2c_pld_driver = { ++ .driver = { ++ .name = "gw_i2c_pld", ++ .owner = THIS_MODULE, ++ }, ++ .probe = gw_i2c_pld_probe, ++ .remove = gw_i2c_pld_remove, ++ .id_table = gw_i2c_pld_id, ++}; ++ ++static int __init gw_i2c_pld_init(void) ++{ ++ return i2c_add_driver(&gw_i2c_pld_driver); ++} ++module_init(gw_i2c_pld_init); ++ ++static void __exit gw_i2c_pld_exit(void) ++{ ++ i2c_del_driver(&gw_i2c_pld_driver); ++} ++module_exit(gw_i2c_pld_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Chris Lang"); +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -426,6 +426,14 @@ config GPIO_RDC321X + Support for the RDC R321x SoC GPIOs over southbridge + PCI configuration space. + ++config GPIO_GW_I2C_PLD ++ tristate "Gateworks I2C PLD GPIO Expander" ++ depends on I2C ++ help ++ Say yes here to provide access to the Gateworks I2C PLD GPIO ++ Expander. This is used at least on the GW2358-4. ++ ++ + comment "SPI GPIO expanders:" + + config GPIO_MAX7301 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -61,3 +61,4 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x + obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o + obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o + obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o ++obj-$(CONFIG_GPIO_GW_I2C_PLD) += gw_i2c_pld.o +--- /dev/null ++++ b/include/linux/i2c/gw_i2c_pld.h +@@ -0,0 +1,20 @@ ++#ifndef __LINUX_GW_I2C_PLD_H ++#define __LINUX_GW_I2C_PLD_H ++ ++/** ++ * The Gateworks I2C PLD Implements an additional 8 bits of GPIO through the PLD ++ */ ++ ++struct gw_i2c_pld_platform_data { ++ unsigned gpio_base; ++ unsigned nr_gpio; ++ int (*setup)(struct i2c_client *client, ++ int gpio, unsigned ngpio, ++ void *context); ++ int (*teardown)(struct i2c_client *client, ++ int gpio, unsigned ngpio, ++ void *context); ++ void *context; ++}; ++ ++#endif /* __LINUX_GW_I2C_PLD_H */ diff --git a/target/linux/ixp4xx/patches-3.3/090-increase_entropy_pools.patch b/target/linux/ixp4xx/patches-3.3/090-increase_entropy_pools.patch new file mode 100644 index 0000000000..b5f3f1f2ac --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/090-increase_entropy_pools.patch @@ -0,0 +1,15 @@ +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -271,9 +271,9 @@ + /* + * Configuration information + */ +-#define INPUT_POOL_WORDS 128 +-#define OUTPUT_POOL_WORDS 32 +-#define SEC_XFER_SIZE 512 ++#define INPUT_POOL_WORDS 256 ++#define OUTPUT_POOL_WORDS 64 ++#define SEC_XFER_SIZE 1024 + #define EXTRACT_SIZE 10 + + /* diff --git a/target/linux/ixp4xx/patches-3.3/100-wg302v2_gateway7001_mac_plat_info.patch b/target/linux/ixp4xx/patches-3.3/100-wg302v2_gateway7001_mac_plat_info.patch new file mode 100644 index 0000000000..c664eda92e --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/100-wg302v2_gateway7001_mac_plat_info.patch @@ -0,0 +1,68 @@ +--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c ++++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c +@@ -75,9 +75,35 @@ static struct platform_device gateway700 + .resource = &gateway7001_uart_resource, + }; + ++static struct eth_plat_info gateway7001_plat_eth[] = { ++ { ++ .phy = 1, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 2, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device gateway7001_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = gateway7001_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = gateway7001_plat_eth + 1, ++ } ++}; ++ + static struct platform_device *gateway7001_devices[] __initdata = { + &gateway7001_flash, +- &gateway7001_uart ++ &gateway7001_uart, ++ &gateway7001_eth[0], ++ &gateway7001_eth[1], + }; + + static void __init gateway7001_init(void) +--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c ++++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c +@@ -76,9 +76,26 @@ static struct platform_device wg302v2_ua + .resource = &wg302v2_uart_resource, + }; + ++static struct eth_plat_info wg302v2_plat_eth[] = { ++ { ++ .phy = 8, ++ .rxq = 3, ++ .txreadyq = 20, ++ } ++}; ++ ++static struct platform_device wg302v2_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = wg302v2_plat_eth, ++ } ++}; ++ + static struct platform_device *wg302v2_devices[] __initdata = { + &wg302v2_flash, + &wg302v2_uart, ++ &wg302v2_eth[0], + }; + + static void __init wg302v2_init(void) diff --git a/target/linux/ixp4xx/patches-3.3/105-wg302v1_support.patch b/target/linux/ixp4xx/patches-3.3/105-wg302v1_support.patch new file mode 100644 index 0000000000..1e8fdaa513 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/105-wg302v1_support.patch @@ -0,0 +1,259 @@ +--- a/arch/arm/configs/ixp4xx_defconfig ++++ b/arch/arm/configs/ixp4xx_defconfig +@@ -13,6 +13,7 @@ CONFIG_MACH_AVILA=y + CONFIG_MACH_LOFT=y + CONFIG_ARCH_ADI_COYOTE=y + CONFIG_MACH_GATEWAY7001=y ++CONFIG_MACH_WG302V1=y + CONFIG_MACH_WG302V2=y + CONFIG_ARCH_IXDP425=y + CONFIG_MACH_IXDPG425=y +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -49,6 +49,14 @@ config MACH_GATEWAY7001 + 7001 Access Point. For more information on this platform, + see http://openwrt.org + ++config MACH_WG302V1 ++ bool "Netgear WG302 v1 / WAG302 v1" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support Netgear's ++ WG302 v1 or WAG302 v1 Access Points. For more information ++ on this platform, see http://openwrt.org ++ + config MACH_WG302V2 + bool "Netgear WG302 v2 / WAG302 v2" + select PCI +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -15,6 +15,7 @@ obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-p + obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o + obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o + obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o ++obj-pci-$(CONFIG_MACH_WG302V1) += wg302v1-pci.o + obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o + obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o + obj-pci-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-pci.o +@@ -33,6 +34,7 @@ obj-$(CONFIG_MACH_NSLU2) += nslu2-setup. + obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o + obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o + obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o ++obj-$(CONFIG_MACH_WG302V1) += wg302v1-setup.o + obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o + obj-$(CONFIG_MACH_FSG) += fsg-setup.o + obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_mlr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/wg302v1-pci.c +@@ -0,0 +1,64 @@ ++/* ++ * arch/arch/mach-ixp4xx/wg302v1-pci.c ++ * ++ * PCI setup routines for the Netgear WG302 v1 and WAG302 v1 ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Software, Inc. ++ * ++ * Maintainer: Imre Kaloz <kaloz@openwrt.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++ ++#include <asm/mach/pci.h> ++ ++void __init wg302v1_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init wg302v1_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 1) ++ return IRQ_IXP4XX_GPIO8; ++ else if (slot == 2) ++ return IRQ_IXP4XX_GPIO10; ++ else ++ return -1; ++} ++ ++struct hw_pci wg302v1_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = wg302v1_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = wg302v1_map_irq, ++}; ++ ++int __init wg302v1_pci_init(void) ++{ ++ if (machine_is_wg302v1()) ++ pci_common_init(&wg302v1_pci); ++ return 0; ++} ++ ++subsys_initcall(wg302v1_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/wg302v1-setup.c +@@ -0,0 +1,144 @@ ++/* ++ * arch/arm/mach-ixp4xx/wg302v1-setup.c ++ * ++ * Board setup for the Netgear WG302 v1 and WAG302 v1 ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <kaloz@openwrt.org> ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++#include <linux/memory.h> ++ ++#include <asm/setup.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data wg302v1_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource wg302v1_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device wg302v1_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &wg302v1_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &wg302v1_flash_resource, ++}; ++ ++static struct resource wg302v1_uart_resources[] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct plat_serial8250_port wg302v1_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device wg302v1_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = wg302v1_uart_data, ++ }, ++ .num_resources = 2, ++ .resource = wg302v1_uart_resources, ++}; ++ ++static struct eth_plat_info wg302v1_plat_eth[] = { ++ { ++ .phy = 30, ++ .rxq = 3, ++ .txreadyq = 20, ++ } ++}; ++ ++static struct platform_device wg302v1_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = wg302v1_plat_eth, ++ } ++}; ++ ++static struct platform_device *wg302v1_devices[] __initdata = { ++ &wg302v1_flash, ++ &wg302v1_uart, ++ &wg302v1_eth[0], ++}; ++ ++static void __init wg302v1_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ wg302v1_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ wg302v1_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; ++ ++ platform_add_devices(wg302v1_devices, ARRAY_SIZE(wg302v1_devices)); ++} ++ ++#ifdef CONFIG_MACH_WG302V1 ++MACHINE_START(WG302V1, "Netgear WG302 v1 / WAG302 v1") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .fixup = wg302v1_fixup, ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = wg302v1_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++#endif diff --git a/target/linux/ixp4xx/patches-3.3/110-pronghorn_series_support.patch b/target/linux/ixp4xx/patches-3.3/110-pronghorn_series_support.patch new file mode 100644 index 0000000000..529cddb436 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/110-pronghorn_series_support.patch @@ -0,0 +1,389 @@ +--- a/arch/arm/configs/ixp4xx_defconfig ++++ b/arch/arm/configs/ixp4xx_defconfig +@@ -15,6 +15,8 @@ CONFIG_ARCH_ADI_COYOTE=y + CONFIG_MACH_GATEWAY7001=y + CONFIG_MACH_WG302V1=y + CONFIG_MACH_WG302V2=y ++CONFIG_MACH_PRONGHORN=y ++CONFIG_MACH_PRONGHORNMETRO=y + CONFIG_ARCH_IXDP425=y + CONFIG_MACH_IXDPG425=y + CONFIG_MACH_IXDP465=y +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -65,6 +65,22 @@ config MACH_WG302V2 + WG302 v2 or WAG302 v2 Access Points. For more information + on this platform, see http://openwrt.org + ++config MACH_PRONGHORN ++ bool "ADI Pronghorn series" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support the ADI ++ Engineering Pronghorn series. For more ++ information on this platform, see http://www.adiengineering.com ++ ++# ++# There're only minimal differences kernel-wise between the Pronghorn and ++# Pronghorn Metro boards - they use different chip selects to drive the ++# CF slot connected to the expansion bus, so we just enable them together. ++# ++config MACH_PRONGHORNMETRO ++ def_bool MACH_PRONGHORN ++ + config ARCH_IXDP425 + bool "IXDP425" + help +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -19,6 +19,7 @@ obj-pci-$(CONFIG_MACH_WG302V1) += wg302 + obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o + obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o + obj-pci-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-pci.o ++obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o + + obj-y += common.o + +@@ -39,6 +40,7 @@ obj-$(CONFIG_MACH_WG302V2) += wg302v2-se + obj-$(CONFIG_MACH_FSG) += fsg-setup.o + obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_mlr.o + obj-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-setup.o ++obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/pronghorn-pci.c +@@ -0,0 +1,70 @@ ++/* ++ * arch/arch/mach-ixp4xx/pronghorn-pci.c ++ * ++ * PCI setup routines for ADI Engineering Pronghorn series ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Imre Kaloz <kaloz@openwrt.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++ ++#include <asm/mach/pci.h> ++ ++void __init pronghorn_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO1, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init pronghorn_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 13) ++ return IRQ_IXP4XX_GPIO4; ++ else if (slot == 14) ++ return IRQ_IXP4XX_GPIO6; ++ else if (slot == 15) ++ return IRQ_IXP4XX_GPIO11; ++ else if (slot == 16) ++ return IRQ_IXP4XX_GPIO1; ++ else ++ return -1; ++} ++ ++struct hw_pci pronghorn_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = pronghorn_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = pronghorn_map_irq, ++}; ++ ++int __init pronghorn_pci_init(void) ++{ ++ if (machine_is_pronghorn() || machine_is_pronghorn_metro()) ++ pci_common_init(&pronghorn_pci); ++ return 0; ++} ++ ++subsys_initcall(pronghorn_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/pronghorn-setup.c +@@ -0,0 +1,247 @@ ++/* ++ * arch/arm/mach-ixp4xx/pronghorn-setup.c ++ * ++ * Board setup for the ADI Engineering Pronghorn series ++ * ++ * Copyright (C) 2008 Imre Kaloz <Kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++#include <linux/memory.h> ++#include <linux/i2c-gpio.h> ++#include <linux/leds.h> ++ ++#include <asm/setup.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data pronghorn_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource pronghorn_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device pronghorn_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &pronghorn_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &pronghorn_flash_resource, ++}; ++ ++static struct resource pronghorn_uart_resources [] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ } ++}; ++ ++static struct plat_serial8250_port pronghorn_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device pronghorn_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = pronghorn_uart_data, ++ }, ++ .num_resources = 2, ++ .resource = pronghorn_uart_resources, ++}; ++ ++static struct i2c_gpio_platform_data pronghorn_i2c_gpio_data = { ++ .sda_pin = 9, ++ .scl_pin = 10, ++}; ++ ++static struct platform_device pronghorn_i2c_gpio = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &pronghorn_i2c_gpio_data, ++ }, ++}; ++ ++static struct gpio_led pronghorn_led_pin[] = { ++ { ++ .name = "pronghorn:green:status", ++ .gpio = 7, ++ } ++}; ++ ++static struct gpio_led_platform_data pronghorn_led_data = { ++ .num_leds = 1, ++ .leds = pronghorn_led_pin, ++}; ++ ++static struct platform_device pronghorn_led = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev.platform_data = &pronghorn_led_data, ++}; ++ ++static struct resource pronghorn_pata_resources[] = { ++ { ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "intrq", ++ .start = IRQ_IXP4XX_GPIO0, ++ .end = IRQ_IXP4XX_GPIO0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct ixp4xx_pata_data pronghorn_pata_data = { ++ .cs0_bits = 0xbfff0043, ++ .cs1_bits = 0xbfff0043, ++}; ++ ++static struct platform_device pronghorn_pata = { ++ .name = "pata_ixp4xx_cf", ++ .id = 0, ++ .dev.platform_data = &pronghorn_pata_data, ++ .num_resources = ARRAY_SIZE(pronghorn_pata_resources), ++ .resource = pronghorn_pata_resources, ++}; ++ ++static struct eth_plat_info pronghorn_plat_eth[] = { ++ { ++ .phy = 0, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 1, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device pronghorn_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = pronghorn_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = pronghorn_plat_eth + 1, ++ } ++}; ++ ++static struct platform_device *pronghorn_devices[] __initdata = { ++ &pronghorn_flash, ++ &pronghorn_uart, ++ &pronghorn_led, ++ &pronghorn_eth[0], ++ &pronghorn_eth[1], ++}; ++ ++static void __init pronghorn_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ pronghorn_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ pronghorn_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; ++ ++ platform_add_devices(pronghorn_devices, ARRAY_SIZE(pronghorn_devices)); ++ ++ if (machine_is_pronghorn()) { ++ pronghorn_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(2); ++ pronghorn_pata_resources[0].end = IXP4XX_EXP_BUS_END(2); ++ ++ pronghorn_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(3); ++ pronghorn_pata_resources[1].end = IXP4XX_EXP_BUS_END(3); ++ ++ pronghorn_pata_data.cs0_cfg = IXP4XX_EXP_CS2; ++ pronghorn_pata_data.cs1_cfg = IXP4XX_EXP_CS3; ++ } else { ++ pronghorn_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(3); ++ pronghorn_pata_resources[0].end = IXP4XX_EXP_BUS_END(3); ++ ++ pronghorn_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(4); ++ pronghorn_pata_resources[1].end = IXP4XX_EXP_BUS_END(4); ++ ++ pronghorn_pata_data.cs0_cfg = IXP4XX_EXP_CS3; ++ pronghorn_pata_data.cs1_cfg = IXP4XX_EXP_CS4; ++ ++ platform_device_register(&pronghorn_i2c_gpio); ++ } ++ ++ platform_device_register(&pronghorn_pata); ++} ++ ++MACHINE_START(PRONGHORN, "ADI Engineering Pronghorn") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = pronghorn_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++ ++MACHINE_START(PRONGHORNMETRO, "ADI Engineering Pronghorn Metro") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = pronghorn_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END +--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h ++++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h +@@ -42,7 +42,8 @@ static __inline__ void __arch_decomp_set + */ + if (machine_is_adi_coyote() || machine_is_gtwx5715() || + machine_is_gateway7001() || machine_is_wg302v2() || +- machine_is_devixp() || machine_is_miccpt() || machine_is_mic256()) ++ machine_is_devixp() || machine_is_miccpt() || machine_is_mic256() || ++ machine_is_pronghorn() || machine_is_pronghorn_metro()) + uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; + else + uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-3.3/111-pronghorn_swap_uarts.patch b/target/linux/ixp4xx/patches-3.3/111-pronghorn_swap_uarts.patch new file mode 100644 index 0000000000..b9fa507689 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/111-pronghorn_swap_uarts.patch @@ -0,0 +1,44 @@ +--- a/arch/arm/mach-ixp4xx/pronghorn-setup.c ++++ b/arch/arm/mach-ixp4xx/pronghorn-setup.c +@@ -51,31 +51,31 @@ static struct platform_device pronghorn_ + + static struct resource pronghorn_uart_resources [] = { + { +- .start = IXP4XX_UART1_BASE_PHYS, +- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, + .flags = IORESOURCE_MEM + }, + { +- .start = IXP4XX_UART2_BASE_PHYS, +- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, + .flags = IORESOURCE_MEM + } + }; + + static struct plat_serial8250_port pronghorn_uart_data[] = { + { +- .mapbase = IXP4XX_UART1_BASE_PHYS, +- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, +- .irq = IRQ_IXP4XX_UART1, ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = IXP4XX_UART_XTAL, + }, + { +- .mapbase = IXP4XX_UART2_BASE_PHYS, +- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, +- .irq = IRQ_IXP4XX_UART2, ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + .regshift = 2, diff --git a/target/linux/ixp4xx/patches-3.3/115-sidewinder_support.patch b/target/linux/ixp4xx/patches-3.3/115-sidewinder_support.patch new file mode 100644 index 0000000000..f2e626d16a --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/115-sidewinder_support.patch @@ -0,0 +1,283 @@ +From 60bdaaaf3446b4237566c6e04855186fc7bd766b Mon Sep 17 00:00:00 2001 +From: Imre Kaloz <kaloz@openwrt.org> +Date: Sun, 13 Jul 2008 22:46:45 +0200 +Subject: [PATCH] Add support for the ADI Sidewinder + +Signed-off-by: Imre Kaloz <kaloz@openwrt.org> +--- + arch/arm/mach-ixp4xx/Kconfig | 10 ++- + arch/arm/mach-ixp4xx/Makefile | 2 + + arch/arm/mach-ixp4xx/sidewinder-pci.c | 68 ++++++++++++++ + arch/arm/mach-ixp4xx/sidewinder-setup.c | 151 +++++++++++++++++++++++++++++++ + 4 files changed, 230 insertions(+), 1 deletions(-) + create mode 100644 arch/arm/mach-ixp4xx/sidewinder-pci.c + create mode 100644 arch/arm/mach-ixp4xx/sidewinder-setup.c + +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -81,6 +81,14 @@ config MACH_PRONGHORN + config MACH_PRONGHORNMETRO + def_bool MACH_PRONGHORN + ++config MACH_SIDEWINDER ++ bool "ADI Sidewinder" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support the ADI ++ Engineering Sidewinder board. For more information on this ++ platform, see http://www.adiengineering.com ++ + config ARCH_IXDP425 + bool "IXDP425" + help +@@ -177,7 +185,7 @@ config MACH_ARCOM_VULCAN + # + config CPU_IXP46X + bool +- depends on MACH_IXDP465 ++ depends on MACH_IXDP465 || MACH_SIDEWINDER + default y + + config CPU_IXP43X +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -20,6 +20,7 @@ obj-pci-$(CONFIG_MACH_WG302V2) += wg302 + obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o + obj-pci-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-pci.o + obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o ++obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o + + obj-y += common.o + +@@ -41,6 +42,7 @@ obj-$(CONFIG_MACH_FSG) += fsg-setup.o + obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_mlr.o + obj-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-setup.o + obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o ++obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/sidewinder-pci.c +@@ -0,0 +1,68 @@ ++/* ++ * arch/arch/mach-ixp4xx/pronghornmetro-pci.c ++ * ++ * PCI setup routines for ADI Engineering Sidewinder ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Imre Kaloz <kaloz@openwrt.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++ ++#include <asm/mach/pci.h> ++ ++void __init sidewinder_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init sidewinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 1) ++ return IRQ_IXP4XX_GPIO11; ++ else if (slot == 2) ++ return IRQ_IXP4XX_GPIO10; ++ else if (slot == 3) ++ return IRQ_IXP4XX_GPIO9; ++ else ++ return -1; ++} ++ ++struct hw_pci sidewinder_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = sidewinder_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = sidewinder_map_irq, ++}; ++ ++int __init sidewinder_pci_init(void) ++{ ++ if (machine_is_sidewinder()) ++ pci_common_init(&sidewinder_pci); ++ return 0; ++} ++ ++subsys_initcall(sidewinder_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/sidewinder-setup.c +@@ -0,0 +1,150 @@ ++/* ++ * arch/arm/mach-ixp4xx/sidewinder-setup.c ++ * ++ * Board setup for the ADI Engineering Sidewinder ++ * ++ * Copyright (C) 2008 Imre Kaloz <Kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/serial.h> ++#include <linux/serial_8250.h> ++ ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data sidewinder_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource sidewinder_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device sidewinder_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &sidewinder_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &sidewinder_flash_resource, ++}; ++ ++static struct resource sidewinder_uart_resources[] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct plat_serial8250_port sidewinder_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device sidewinder_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = sidewinder_uart_data, ++ }, ++ .num_resources = ARRAY_SIZE(sidewinder_uart_resources), ++ .resource = sidewinder_uart_resources, ++}; ++ ++static struct eth_plat_info sidewinder_plat_eth[] = { ++ { ++ .phy = 5, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0x1e, ++ .rxq = 4, ++ .txreadyq = 21, ++ }, { ++ .phy = 31, ++ .rxq = 2, ++ .txreadyq = 19, ++ } ++}; ++ ++static struct platform_device sidewinder_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = sidewinder_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = sidewinder_plat_eth + 1, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEA, ++ .dev.platform_data = sidewinder_plat_eth + 2, ++ } ++}; ++ ++static struct platform_device *sidewinder_devices[] __initdata = { ++ &sidewinder_flash, ++ &sidewinder_uart, ++ &sidewinder_eth[0], ++ &sidewinder_eth[1], ++ &sidewinder_eth[2], ++}; ++ ++static void __init sidewinder_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ sidewinder_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ sidewinder_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_64M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; ++ ++ platform_add_devices(sidewinder_devices, ARRAY_SIZE(sidewinder_devices)); ++} ++ ++MACHINE_START(SIDEWINDER, "ADI Engineering Sidewinder") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = sidewinder_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END diff --git a/target/linux/ixp4xx/patches-3.3/116-sidewinder_fis_location.patch b/target/linux/ixp4xx/patches-3.3/116-sidewinder_fis_location.patch new file mode 100644 index 0000000000..af65b74bf3 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/116-sidewinder_fis_location.patch @@ -0,0 +1,30 @@ +--- a/drivers/mtd/redboot.c ++++ b/drivers/mtd/redboot.c +@@ -32,6 +32,8 @@ + + #define BOARD_CONFIG_PART "boardconfig" + ++#include <asm/mach-types.h> ++ + struct fis_image_desc { + unsigned char name[16]; // Null terminated name + uint32_t flash_base; // Address within FLASH of image +@@ -49,7 +51,8 @@ struct fis_list { + struct fis_list *next; + }; + +-static int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK; ++int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK; ++ + module_param(directory, int, 0); + + static inline int redboot_checksum(struct fis_image_desc *img) +@@ -78,6 +81,8 @@ static int parse_redboot_partitions(stru + #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED + static char nullstring[] = "unallocated"; + #endif ++ if (machine_is_sidewinder()) ++ directory = -5; + + if ( directory < 0 ) { + offset = master->size + directory * master->erasesize; diff --git a/target/linux/ixp4xx/patches-3.3/120-compex_support.patch b/target/linux/ixp4xx/patches-3.3/120-compex_support.patch new file mode 100644 index 0000000000..da59f4c075 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/120-compex_support.patch @@ -0,0 +1,213 @@ +From 24025a2dcf1248079dd3019fac6ed955252d277f Mon Sep 17 00:00:00 2001 +From: Imre Kaloz <kaloz@openwrt.org> +Date: Mon, 14 Jul 2008 21:56:34 +0200 +Subject: [PATCH] Add support for the Compex WP18 / NP18A boards + +Signed-off-by: Imre Kaloz <kaloz@openwrt.org> +--- + arch/arm/mach-ixp4xx/Kconfig | 8 ++ + arch/arm/mach-ixp4xx/Makefile | 2 + + arch/arm/mach-ixp4xx/compex-setup.c | 136 +++++++++++++++++++++++++++++++++++ + arch/arm/mach-ixp4xx/ixdp425-pci.c | 3 +- + arch/arm/tools/mach-types | 2 +- + 5 files changed, 149 insertions(+), 2 deletions(-) + create mode 100644 arch/arm/mach-ixp4xx/compex-setup.c + +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -89,6 +89,14 @@ config MACH_SIDEWINDER + Engineering Sidewinder board. For more information on this + platform, see http://www.adiengineering.com + ++config MACH_COMPEX ++ bool "Compex WP18 / NP18A" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support Compex' ++ WP18 or NP18A boards. For more information on this ++ platform, see http://www.compex.com.sg/home/OEM/product_ap.htm ++ + config ARCH_IXDP425 + bool "IXDP425" + help +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -21,6 +21,7 @@ obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o + obj-pci-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-pci.o + obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o + obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o ++obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o + + obj-y += common.o + +@@ -43,6 +44,7 @@ obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_ + obj-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-setup.o + obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o + obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o ++obj-$(CONFIG_MACH_COMPEX) += compex-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/compex-setup.c +@@ -0,0 +1,137 @@ ++/* ++ * arch/arm/mach-ixp4xx/compex-setup.c ++ * ++ * Compex WP18 / NP18A board-setup ++ * ++ * Copyright (C) 2008 Imre Kaloz <Kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/serial.h> ++#include <linux/serial_8250.h> ++ ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data compex_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource compex_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device compex_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &compex_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &compex_flash_resource, ++}; ++ ++static struct resource compex_uart_resources[] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ } ++}; ++ ++static struct plat_serial8250_port compex_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device compex_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev.platform_data = compex_uart_data, ++ .num_resources = 2, ++ .resource = compex_uart_resources, ++}; ++ ++static struct eth_plat_info compex_plat_eth[] = { ++ { ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0xf0000, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 3, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device compex_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = compex_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = compex_plat_eth + 1, ++ } ++}; ++ ++static struct platform_device *compex_devices[] __initdata = { ++ &compex_flash, ++ &compex_uart, ++ &compex_eth[0], ++ &compex_eth[1], ++}; ++ ++static void __init compex_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ compex_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ compex_flash_resource.end = ++ IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; ++ ++ platform_add_devices(compex_devices, ARRAY_SIZE(compex_devices)); ++} ++ ++MACHINE_START(COMPEX, "Compex WP18 / NP18A") ++ /* Maintainer: Imre Kaloz <Kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = compex_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END +--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c ++++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c +@@ -70,7 +70,8 @@ struct hw_pci ixdp425_pci __initdata = { + int __init ixdp425_pci_init(void) + { + if (machine_is_ixdp425() || machine_is_ixcdp1100() || +- machine_is_ixdp465() || machine_is_kixrp435()) ++ machine_is_ixdp465() || machine_is_kixrp435() || ++ machine_is_compex()) + pci_common_init(&ixdp425_pci); + return 0; + } +--- a/arch/arm/tools/mach-types ++++ b/arch/arm/tools/mach-types +@@ -1273,7 +1273,7 @@ oiab MACH_OIAB OIAB 1269 + smdk6400 MACH_SMDK6400 SMDK6400 1270 + nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271 + greenphone MACH_GREENPHONE GREENPHONE 1272 +-compex42x MACH_COMPEXWP18 COMPEXWP18 1273 ++compex MACH_COMPEX COMPEX 1273 + xmate MACH_XMATE XMATE 1274 + energizer MACH_ENERGIZER ENERGIZER 1275 + ime1 MACH_IME1 IME1 1276 diff --git a/target/linux/ixp4xx/patches-3.3/130-wrt300nv2_support.patch b/target/linux/ixp4xx/patches-3.3/130-wrt300nv2_support.patch new file mode 100644 index 0000000000..caa2b3887e --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/130-wrt300nv2_support.patch @@ -0,0 +1,227 @@ +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -97,6 +97,14 @@ config MACH_COMPEX + WP18 or NP18A boards. For more information on this + platform, see http://www.compex.com.sg/home/OEM/product_ap.htm + ++config MACH_WRT300NV2 ++ bool "Linksys WRT300N v2" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support Linksys' ++ WRT300N v2 router. For more information on this ++ platform, see http://openwrt.org ++ + config ARCH_IXDP425 + bool "IXDP425" + help +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -22,6 +22,7 @@ obj-pci-$(CONFIG_MACH_ARCOM_VULCAN) += v + obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o + obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o + obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o ++obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o + + obj-y += common.o + +@@ -45,6 +46,7 @@ obj-$(CONFIG_MACH_ARCOM_VULCAN) += vulca + obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o + obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o + obj-$(CONFIG_MACH_COMPEX) += compex-setup.o ++obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/wrt300nv2-pci.c +@@ -0,0 +1,65 @@ ++/* ++ * arch/arch/mach-ixp4xx/wrt300nv2-pci.c ++ * ++ * PCI setup routines for Linksys WRT300N v2 ++ * ++ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Imre Kaloz <kaloz@openwrt.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++ ++#include <asm/mach/pci.h> ++ ++extern void ixp4xx_pci_preinit(void); ++extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); ++extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); ++ ++void __init wrt300nv2_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init wrt300nv2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 1) ++ return IRQ_IXP4XX_GPIO8; ++ else return -1; ++} ++ ++struct hw_pci wrt300nv2_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = wrt300nv2_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = wrt300nv2_map_irq, ++}; ++ ++int __init wrt300nv2_pci_init(void) ++{ ++ if (machine_is_wrt300nv2()) ++ pci_common_init(&wrt300nv2_pci); ++ return 0; ++} ++ ++subsys_initcall(wrt300nv2_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/wrt300nv2-setup.c +@@ -0,0 +1,109 @@ ++/* ++ * arch/arm/mach-ixp4xx/wrt300nv2-setup.c ++ * ++ * Board setup for the Linksys WRT300N v2 ++ * ++ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++ ++#include <asm/types.h> ++#include <asm/setup.h> ++#include <asm/memory.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data wrt300nv2_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource wrt300nv2_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device wrt300nv2_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &wrt300nv2_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &wrt300nv2_flash_resource, ++}; ++ ++static struct resource wrt300nv2_uart_resource = { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct plat_serial8250_port wrt300nv2_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device wrt300nv2_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = wrt300nv2_uart_data, ++ }, ++ .num_resources = 1, ++ .resource = &wrt300nv2_uart_resource, ++}; ++ ++static struct platform_device *wrt300nv2_devices[] __initdata = { ++ &wrt300nv2_flash, ++ &wrt300nv2_uart ++}; ++ ++static void __init wrt300nv2_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ wrt300nv2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ wrt300nv2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; ++ ++ platform_add_devices(wrt300nv2_devices, ARRAY_SIZE(wrt300nv2_devices)); ++} ++ ++#ifdef CONFIG_MACH_WRT300NV2 ++MACHINE_START(WRT300NV2, "Linksys WRT300N v2") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = wrt300nv2_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++#endif +--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h ++++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h +@@ -43,7 +43,8 @@ static __inline__ void __arch_decomp_set + if (machine_is_adi_coyote() || machine_is_gtwx5715() || + machine_is_gateway7001() || machine_is_wg302v2() || + machine_is_devixp() || machine_is_miccpt() || machine_is_mic256() || +- machine_is_pronghorn() || machine_is_pronghorn_metro()) ++ machine_is_pronghorn() || machine_is_pronghorn_metro() || ++ machine_is_wrt300nv2()) + uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; + else + uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-3.3/131-wrt300nv2_mac_plat_info.patch b/target/linux/ixp4xx/patches-3.3/131-wrt300nv2_mac_plat_info.patch new file mode 100644 index 0000000000..3ab68c4f3a --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/131-wrt300nv2_mac_plat_info.patch @@ -0,0 +1,40 @@ +--- a/arch/arm/mach-ixp4xx/wrt300nv2-setup.c ++++ b/arch/arm/mach-ixp4xx/wrt300nv2-setup.c +@@ -76,9 +76,36 @@ static struct platform_device wrt300nv2_ + .resource = &wrt300nv2_uart_resource, + }; + ++/* Built-in 10/100 Ethernet MAC interfaces */ ++static struct eth_plat_info wrt300nv2_plat_eth[] = { ++ { ++ .phy = -1, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 1, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device wrt300nv2_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = wrt300nv2_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = wrt300nv2_plat_eth + 1, ++ } ++}; ++ + static struct platform_device *wrt300nv2_devices[] __initdata = { + &wrt300nv2_flash, +- &wrt300nv2_uart ++ &wrt300nv2_uart, ++ &wrt300nv2_eth[0], ++ &wrt300nv2_eth[1], + }; + + static void __init wrt300nv2_init(void) diff --git a/target/linux/ixp4xx/patches-3.3/132-wrt300nv2_mac_fix.patch b/target/linux/ixp4xx/patches-3.3/132-wrt300nv2_mac_fix.patch new file mode 100644 index 0000000000..381cc5b757 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/132-wrt300nv2_mac_fix.patch @@ -0,0 +1,72 @@ +--- a/arch/arm/mach-ixp4xx/wrt300nv2-setup.c ++++ b/arch/arm/mach-ixp4xx/wrt300nv2-setup.c +@@ -3,6 +3,7 @@ + * + * Board setup for the Linksys WRT300N v2 + * ++ * Copyright (C) 2010 Alexandros C. Couloumbis <alex@ozo.com> + * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org> + * + * based on coyote-setup.c: +@@ -18,6 +19,7 @@ + #include <linux/tty.h> + #include <linux/serial_8250.h> + #include <linux/slab.h> ++#include <linux/etherdevice.h> + + #include <asm/types.h> + #include <asm/setup.h> +@@ -79,7 +81,8 @@ static struct platform_device wrt300nv2_ + /* Built-in 10/100 Ethernet MAC interfaces */ + static struct eth_plat_info wrt300nv2_plat_eth[] = { + { +- .phy = -1, ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0x0F0000, + .rxq = 3, + .txreadyq = 20, + }, { +@@ -110,6 +113,10 @@ static struct platform_device *wrt300nv2 + + static void __init wrt300nv2_init(void) + { ++ uint8_t __iomem *f; ++ int offset = 0; ++ int i; ++ + ixp4xx_sys_init(); + + wrt300nv2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); +@@ -119,6 +126,32 @@ static void __init wrt300nv2_init(void) + *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; + + platform_add_devices(wrt300nv2_devices, ARRAY_SIZE(wrt300nv2_devices)); ++ ++ f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x60000); ++ ++ if (f) { ++ for (i = 0; i < 6; i++) { ++#ifdef __ARMEB__ ++ wrt300nv2_plat_eth[0].hwaddr[i] = readb(f + 0x5FFA0 + i); ++ if (i == 5) ++ offset = 1; ++ wrt300nv2_plat_eth[1].hwaddr[i] = (wrt300nv2_plat_eth[0].hwaddr[i] + offset); ++#else ++ wrt300nv2_plat_eth[0].hwaddr[i] = readb(f + 0x5FFA0 + (i^3)); ++ if (i == 5) ++ offset = 1; ++ wrt300nv2_plat_eth[1].hwaddr[i] = (wrt300nv2_plat_eth[0].hwaddr[i] + offset); ++#endif ++ } ++ iounmap(f); ++ } ++ ++ if (!(is_valid_ether_addr(wrt300nv2_plat_eth[0].hwaddr))) ++ random_ether_addr(wrt300nv2_plat_eth[0].hwaddr); ++ if (!(is_valid_ether_addr(wrt300nv2_plat_eth[1].hwaddr))) { ++ memcpy(wrt300nv2_plat_eth[1].hwaddr, wrt300nv2_plat_eth[0].hwaddr, ETH_ALEN); ++ wrt300nv2_plat_eth[1].hwaddr[5] = (wrt300nv2_plat_eth[0].hwaddr[5] + 1); ++ } + } + + #ifdef CONFIG_MACH_WRT300NV2 diff --git a/target/linux/ixp4xx/patches-3.3/150-lanready_ap1000_support.patch b/target/linux/ixp4xx/patches-3.3/150-lanready_ap1000_support.patch new file mode 100644 index 0000000000..da3c1432f3 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/150-lanready_ap1000_support.patch @@ -0,0 +1,201 @@ +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/ap1000-setup.c +@@ -0,0 +1,152 @@ ++/* ++ * arch/arm/mach-ixp4xx/ap1000-setup.c ++ * ++ * Lanready AP-1000 ++ * ++ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org> ++ * ++ * based on ixdp425-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++ ++#include <asm/types.h> ++#include <asm/setup.h> ++#include <asm/memory.h> ++#include <mach/hardware.h> ++#include <asm/mach-types.h> ++#include <asm/irq.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data ap1000_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource ap1000_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device ap1000_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &ap1000_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &ap1000_flash_resource, ++}; ++ ++static struct resource ap1000_uart_resources[] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ } ++}; ++ ++static struct plat_serial8250_port ap1000_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device ap1000_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev.platform_data = ap1000_uart_data, ++ .num_resources = 2, ++ .resource = ap1000_uart_resources ++}; ++ ++static struct platform_device *ap1000_devices[] __initdata = { ++ &ap1000_flash, ++ &ap1000_uart ++}; ++ ++static char ap1000_mem_fixup[] __initdata = "mem=64M "; ++ ++static void __init ap1000_fixup(struct machine_desc *desc, ++ struct tag *tags, char **cmdline, struct meminfo *mi) ++ ++{ ++ struct tag *t = tags; ++ char *p = *cmdline; ++ ++ /* Find the end of the tags table, taking note of any cmdline tag. */ ++ for (; t->hdr.size; t = tag_next(t)) { ++ if (t->hdr.tag == ATAG_CMDLINE) { ++ p = t->u.cmdline.cmdline; ++ } ++ } ++ ++ /* Overwrite the end of the table with a new cmdline tag. */ ++ t->hdr.tag = ATAG_CMDLINE; ++ t->hdr.size = (sizeof (struct tag_header) + ++ strlen(ap1000_mem_fixup) + strlen(p) + 1 + 4) >> 2; ++ strlcpy(t->u.cmdline.cmdline, ap1000_mem_fixup, COMMAND_LINE_SIZE); ++ strlcpy(t->u.cmdline.cmdline + strlen(ap1000_mem_fixup), p, ++ COMMAND_LINE_SIZE - strlen(ap1000_mem_fixup)); ++ ++ /* Terminate the table. */ ++ t = tag_next(t); ++ t->hdr.tag = ATAG_NONE; ++ t->hdr.size = 0; ++} ++ ++static void __init ap1000_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ ap1000_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ ap1000_flash_resource.end = ++ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; ++ ++ platform_add_devices(ap1000_devices, ARRAY_SIZE(ap1000_devices)); ++} ++ ++#ifdef CONFIG_MACH_AP1000 ++MACHINE_START(AP1000, "Lanready AP-1000") ++ /* Maintainer: Imre Kaloz <Kaloz@openwrt.org> */ ++ .fixup = ap1000_fixup, ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = ap1000_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++#endif +--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c ++++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c +@@ -71,7 +71,7 @@ int __init ixdp425_pci_init(void) + { + if (machine_is_ixdp425() || machine_is_ixcdp1100() || + machine_is_ixdp465() || machine_is_kixrp435() || +- machine_is_compex()) ++ machine_is_compex() || machine_is_ap1000()) + pci_common_init(&ixdp425_pci); + return 0; + } +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -105,6 +105,14 @@ config MACH_WRT300NV2 + WRT300N v2 router. For more information on this + platform, see http://openwrt.org + ++config MACH_AP1000 ++ bool "Lanready AP-1000" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support Lanready's ++ AP1000 board. For more information on this ++ platform, see http://openwrt.org ++ + config ARCH_IXDP425 + bool "IXDP425" + help +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -23,6 +23,7 @@ obj-pci-$(CONFIG_MACH_PRONGHORN) += pron + obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o + obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o + obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o ++obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o + + obj-y += common.o + +@@ -47,6 +48,7 @@ obj-$(CONFIG_MACH_PRONGHORN) += pronghor + obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o + obj-$(CONFIG_MACH_COMPEX) += compex-setup.o + obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o ++obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o diff --git a/target/linux/ixp4xx/patches-3.3/151-lanready_ap1000_mac_plat_info.patch b/target/linux/ixp4xx/patches-3.3/151-lanready_ap1000_mac_plat_info.patch new file mode 100644 index 0000000000..38b026d76a --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/151-lanready_ap1000_mac_plat_info.patch @@ -0,0 +1,49 @@ +--- a/arch/arm/mach-ixp4xx/ap1000-setup.c ++++ b/arch/arm/mach-ixp4xx/ap1000-setup.c +@@ -90,15 +90,43 @@ static struct platform_device ap1000_uar + .resource = ap1000_uart_resources + }; + ++/* Built-in 10/100 Ethernet MAC interfaces */ ++static struct eth_plat_info ap1000_plat_eth[] = { ++ { ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0x1e, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 5, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device ap1000_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = ap1000_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = ap1000_plat_eth + 1, ++ } ++}; ++ + static struct platform_device *ap1000_devices[] __initdata = { + &ap1000_flash, +- &ap1000_uart ++ &ap1000_uart, ++ &ap1000_eth[0], ++ &ap1000_eth[1], + }; + + static char ap1000_mem_fixup[] __initdata = "mem=64M "; + +-static void __init ap1000_fixup(struct machine_desc *desc, +- struct tag *tags, char **cmdline, struct meminfo *mi) ++static void __init ap1000_fixup(struct tag *tags, char **cmdline, ++ struct meminfo *mi) + + { + struct tag *t = tags; diff --git a/target/linux/ixp4xx/patches-3.3/162-wg302v1_mem_fixup.patch b/target/linux/ixp4xx/patches-3.3/162-wg302v1_mem_fixup.patch new file mode 100644 index 0000000000..469593158d --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/162-wg302v1_mem_fixup.patch @@ -0,0 +1,38 @@ +--- a/arch/arm/mach-ixp4xx/wg302v1-setup.c ++++ b/arch/arm/mach-ixp4xx/wg302v1-setup.c +@@ -115,6 +115,35 @@ static struct platform_device *wg302v1_d + &wg302v1_eth[0], + }; + ++static char wg302v1_mem_fixup[] __initdata = "mem=32M "; ++ ++static void __init wg302v1_fixup(struct tag *tags, char **cmdline, ++ struct meminfo *mi) ++{ ++ struct tag *t = tags; ++ char *p = *cmdline; ++ ++ /* Find the end of the tags table, taking note of any cmdline tag. */ ++ for (; t->hdr.size; t = tag_next(t)) { ++ if (t->hdr.tag == ATAG_CMDLINE) { ++ p = t->u.cmdline.cmdline; ++ } ++ } ++ ++ /* Overwrite the end of the table with a new cmdline tag. */ ++ t->hdr.tag = ATAG_CMDLINE; ++ t->hdr.size = (sizeof (struct tag_header) + ++ strlen(wg302v1_mem_fixup) + strlen(p) + 1 + 4) >> 2; ++ strlcpy(t->u.cmdline.cmdline, wg302v1_mem_fixup, COMMAND_LINE_SIZE); ++ strlcpy(t->u.cmdline.cmdline + strlen(wg302v1_mem_fixup), p, ++ COMMAND_LINE_SIZE - strlen(wg302v1_mem_fixup)); ++ ++ /* Terminate the table. */ ++ t = tag_next(t); ++ t->hdr.tag = ATAG_NONE; ++ t->hdr.size = 0; ++} ++ + static void __init wg302v1_init(void) + { + ixp4xx_sys_init(); diff --git a/target/linux/ixp4xx/patches-3.3/170-ixdpg425_mac_plat_info.patch b/target/linux/ixp4xx/patches-3.3/170-ixdpg425_mac_plat_info.patch new file mode 100644 index 0000000000..5333532ff9 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/170-ixdpg425_mac_plat_info.patch @@ -0,0 +1,41 @@ +--- a/arch/arm/mach-ixp4xx/coyote-setup.c ++++ b/arch/arm/mach-ixp4xx/coyote-setup.c +@@ -81,9 +81,37 @@ static struct platform_device coyote_uar + .resource = &coyote_uart_resource, + }; + ++/* Built-in 10/100 Ethernet MAC interfaces */ ++static struct eth_plat_info ixdpg425_plat_eth[] = { ++ { ++ .phy = 5, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 4, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device ixdpg425_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = ixdpg425_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = ixdpg425_plat_eth + 1, ++ } ++}; ++ ++ + static struct platform_device *coyote_devices[] __initdata = { + &coyote_flash, +- &coyote_uart ++ &coyote_uart, ++ &ixdpg425_eth[0], ++ &ixdpg425_eth[1], + }; + + static void __init coyote_init(void) diff --git a/target/linux/ixp4xx/patches-3.3/180-tw5334_support.patch b/target/linux/ixp4xx/patches-3.3/180-tw5334_support.patch new file mode 100644 index 0000000000..2b6f0f0498 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/180-tw5334_support.patch @@ -0,0 +1,285 @@ +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -164,6 +164,14 @@ config ARCH_PRPMC1100 + PrPCM1100 Processor Mezanine Module. For more information on + this platform, see <file:Documentation/arm/IXP4xx>. + ++config MACH_TW5334 ++ bool "Titan Wireless TW-533-4" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support the Titan ++ Wireless TW533-4. For more information on this platform, ++ see http://openwrt.org ++ + config MACH_NAS100D + bool + prompt "NAS100D" +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -24,6 +24,7 @@ obj-pci-$(CONFIG_MACH_SIDEWINDER) += sid + obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o + obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o + obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o ++obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o + + obj-y += common.o + +@@ -49,6 +50,7 @@ obj-$(CONFIG_MACH_SIDEWINDER) += sidewin + obj-$(CONFIG_MACH_COMPEX) += compex-setup.o + obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o + obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o ++obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/tw5334-setup.c +@@ -0,0 +1,164 @@ ++/* ++ * arch/arm/mach-ixp4xx/tw5334-setup.c ++ * ++ * Board setup for the Titan Wireless TW-533-4 ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/if_ether.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++ ++#include <asm/types.h> ++#include <asm/setup.h> ++#include <asm/memory.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data tw5334_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource tw5334_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device tw5334_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &tw5334_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &tw5334_flash_resource, ++}; ++ ++static struct resource tw5334_uart_resource = { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct plat_serial8250_port tw5334_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device tw5334_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = tw5334_uart_data, ++ }, ++ .num_resources = 1, ++ .resource = &tw5334_uart_resource, ++}; ++ ++/* Built-in 10/100 Ethernet MAC interfaces */ ++static struct eth_plat_info tw5334_plat_eth[] = { ++ { ++ .phy = 0, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 1, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device tw5334_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = tw5334_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = tw5334_plat_eth + 1, ++ } ++}; ++ ++static struct platform_device *tw5334_devices[] __initdata = { ++ &tw5334_flash, ++ &tw5334_uart, ++ &tw5334_eth[0], ++ &tw5334_eth[1], ++}; ++ ++static void __init tw5334_init(void) ++{ ++ uint8_t __iomem *f; ++ int i; ++ ++ ixp4xx_sys_init(); ++ ++ tw5334_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ tw5334_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; ++ ++ platform_add_devices(tw5334_devices, ARRAY_SIZE(tw5334_devices)); ++ ++ /* ++ * Map in a portion of the flash and read the MAC addresses. ++ * Since it is stored in BE in the flash itself, we need to ++ * byteswap it if we're in LE mode. ++ */ ++ f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000); ++ if (f) { ++ for (i = 0; i < 6; i++) { ++#ifdef __ARMEB__ ++ tw5334_plat_eth[0].hwaddr[i] = readb(f + 0xFC0422 + i); ++ tw5334_plat_eth[1].hwaddr[i] = readb(f + 0xFC043B + i); ++#else ++ tw5334_plat_eth[0].hwaddr[i] = readb(f + 0xFC0422 + (i^3)); ++ tw5334_plat_eth[1].hwaddr[i] = readb(f + 0xFC043B + (i^3)); ++#endif ++ } ++ iounmap(f); ++ } ++ ++ printk(KERN_INFO "TW-533-4: Using MAC address %pM for port 0\n", ++ tw5334_plat_eth[0].hwaddr); ++ printk(KERN_INFO "TW-533-4: Using MAC address %pM for port 1\n", ++ tw5334_plat_eth[1].hwaddr); ++} ++ ++#ifdef CONFIG_MACH_TW5334 ++MACHINE_START(TW5334, "Titan Wireless TW-533-4") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = tw5334_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++#endif +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/tw5334-pci.c +@@ -0,0 +1,69 @@ ++/* ++ * arch/arch/mach-ixp4xx/tw5334-pci.c ++ * ++ * PCI setup routines for the Titan Wireless TW-533-4 ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Imre Kaloz <kaloz@openwrt.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++ ++#include <asm/mach/pci.h> ++ ++void __init tw5334_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO2, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO1, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO0, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init tw5334_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 12) ++ return IRQ_IXP4XX_GPIO6; ++ else if (slot == 13) ++ return IRQ_IXP4XX_GPIO2; ++ else if (slot == 14) ++ return IRQ_IXP4XX_GPIO1; ++ else if (slot == 15) ++ return IRQ_IXP4XX_GPIO0; ++ else return -1; ++} ++ ++struct hw_pci tw5334_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = tw5334_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = tw5334_map_irq, ++}; ++ ++int __init tw5334_pci_init(void) ++{ ++ if (machine_is_tw5334()) ++ pci_common_init(&tw5334_pci); ++ return 0; ++} ++ ++subsys_initcall(tw5334_pci_init); +--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h ++++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h +@@ -44,7 +44,7 @@ static __inline__ void __arch_decomp_set + machine_is_gateway7001() || machine_is_wg302v2() || + machine_is_devixp() || machine_is_miccpt() || machine_is_mic256() || + machine_is_pronghorn() || machine_is_pronghorn_metro() || +- machine_is_wrt300nv2()) ++ machine_is_wrt300nv2() || machine_is_tw5334()) + uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; + else + uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-3.3/185-mi424wr_support.patch b/target/linux/ixp4xx/patches-3.3/185-mi424wr_support.patch new file mode 100644 index 0000000000..7228860015 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/185-mi424wr_support.patch @@ -0,0 +1,466 @@ +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/mi424wr-pci.c +@@ -0,0 +1,71 @@ ++/* ++ * arch/arm/mach-ixp4xx/mi424wr-pci.c ++ * ++ * Actiontec MI424WR board-level PCI initialization ++ * ++ * Copyright (C) 2008 Jose Vasconcellos ++ * ++ * Maintainer: Jose Vasconcellos <jvasco@verizon.net> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <asm/mach/pci.h> ++ ++/* PCI controller GPIO to IRQ pin mappings ++ * This information was obtained from Actiontec's GPL release. ++ * ++ * INTA INTB ++ * SLOT 13 8 6 ++ * SLOT 14 7 8 ++ * SLOT 15 6 7 ++ */ ++ ++void __init mi424wr_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init mi424wr_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 13) ++ return IRQ_IXP4XX_GPIO8; ++ if (slot == 14) ++ return IRQ_IXP4XX_GPIO7; ++ if (slot == 15) ++ return IRQ_IXP4XX_GPIO6; ++ ++ return -1; ++} ++ ++struct hw_pci mi424wr_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = mi424wr_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = mi424wr_map_irq, ++}; ++ ++int __init mi424wr_pci_init(void) ++{ ++ if (machine_is_mi424wr()) ++ pci_common_init(&mi424wr_pci); ++ return 0; ++} ++ ++subsys_initcall(mi424wr_pci_init); ++ +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/mi424wr-setup.c +@@ -0,0 +1,345 @@ ++/* ++ * arch/arm/mach-ixp4xx/mi424wr-setup.c ++ * ++ * Actiontec MI424-WR board setup ++ * Copyright (c) 2008 Jose Vasconcellos ++ * ++ * Based on Gemtek GTWX5715 by ++ * Copyright (C) 2004 George T. Joseph ++ * Derived from Coyote ++ * ++ * 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; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/serial_8250.h> ++#include <linux/types.h> ++#include <linux/memory.h> ++#include <linux/leds.h> ++#include <linux/spi/spi_gpio_old.h> ++ ++#include <asm/setup.h> ++#include <asm/irq.h> ++#include <asm/io.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++/* ++ * GPIO 2,3,4 and 9 are hard wired to the Micrel/Kendin KS8995M Switch ++ * and operate as an SPI type interface. The details of the interface ++ * are available on Kendin/Micrel's web site. ++ */ ++ ++#define MI424WR_KSSPI_SELECT 9 ++#define MI424WR_KSSPI_TXD 4 ++#define MI424WR_KSSPI_CLOCK 2 ++#define MI424WR_KSSPI_RXD 3 ++ ++/* ++ * The "reset" button is wired to GPIO 10. ++ * The GPIO is brought "low" when the button is pushed. ++ */ ++ ++#define MI424WR_BUTTON_GPIO 10 ++#define MI424WR_BUTTON_IRQ IRQ_IXP4XX_GPIO10 ++ ++#define MI424WR_MOCA_WAN_LED 11 ++ ++/* Latch on CS1 - taken from Actiontec's 2.4 source code ++ * ++ * default latch value ++ * 0 - power alarm led (red) 0 (off) ++ * 1 - power led (green) 0 (off) ++ * 2 - wireless led (green) 1 (off) ++ * 3 - no internet led (red) 0 (off) ++ * 4 - internet ok led (green) 0 (off) ++ * 5 - moca LAN 0 (off) ++ * 6 - WAN alarm led (red) 0 (off) ++ * 7 - PCI reset 1 (not reset) ++ * 8 - IP phone 1 led (green) 1 (off) ++ * 9 - IP phone 2 led (green) 1 (off) ++ * 10 - VOIP ready led (green) 1 (off) ++ * 11 - PSTN relay 1 control 0 (PSTN) ++ * 12 - PSTN relay 1 control 0 (PSTN) ++ * 13 - N/A ++ * 14 - N/A ++ * 15 - N/A ++ */ ++ ++#define MI424WR_LATCH_MASK 0x04 ++#define MI424WR_LATCH_DEFAULT 0x1f86 ++ ++#define MI424WR_LATCH_ALARM_LED 0x00 ++#define MI424WR_LATCH_POWER_LED 0x01 ++#define MI424WR_LATCH_WIRELESS_LED 0x02 ++#define MI424WR_LATCH_INET_DOWN_LED 0x03 ++#define MI424WR_LATCH_INET_OK_LED 0x04 ++#define MI424WR_LATCH_MOCA_LAN_LED 0x05 ++#define MI424WR_LATCH_WAN_ALARM_LED 0x06 ++#define MI424WR_LATCH_PCI_RESET 0x07 ++#define MI424WR_LATCH_PHONE1_LED 0x08 ++#define MI424WR_LATCH_PHONE2_LED 0x09 ++#define MI424WR_LATCH_VOIP_LED 0x10 ++#define MI424WR_LATCH_PSTN_RELAY1 0x11 ++#define MI424WR_LATCH_PSTN_RELAY2 0x12 ++ ++/* initialize CS1 to default timings, Intel style, 16-bit bus */ ++#define MI424WR_CS1_CONFIG 0x80000002 ++ ++/* Define both UARTs but they are not easily accessible. ++ */ ++ ++static struct resource mi424wr_uart_resources[] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++ ++static struct plat_serial8250_port mi424wr_uart_platform_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device mi424wr_uart_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev.platform_data = mi424wr_uart_platform_data, ++ .num_resources = ARRAY_SIZE(mi424wr_uart_resources), ++ .resource = mi424wr_uart_resources, ++}; ++ ++static struct flash_platform_data mi424wr_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource mi424wr_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device mi424wr_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev.platform_data = &mi424wr_flash_data, ++ .num_resources = 1, ++ .resource = &mi424wr_flash_resource, ++}; ++ ++static int mi424wr_spi_boardinfo_setup(struct spi_board_info *bi, ++ struct spi_master *master, void *data) ++{ ++ ++ strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias)); ++ ++ bi->max_speed_hz = 5000000 /* Hz */; ++ bi->bus_num = master->bus_num; ++ bi->mode = SPI_MODE_0; ++ ++ return 0; ++} ++ ++static struct spi_gpio_platform_data mi424wr_spi_bus_data = { ++ .pin_cs = MI424WR_KSSPI_SELECT, ++ .pin_clk = MI424WR_KSSPI_CLOCK, ++ .pin_miso = MI424WR_KSSPI_RXD, ++ .pin_mosi = MI424WR_KSSPI_TXD, ++ .cs_activelow = 1, ++ .no_spi_delay = 1, ++ .boardinfo_setup = mi424wr_spi_boardinfo_setup, ++}; ++ ++static struct gpio_led mi424wr_gpio_led[] = { ++ { ++ .name = "moca-wan", /* green led */ ++ .gpio = MI424WR_MOCA_WAN_LED, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led_platform_data mi424wr_gpio_leds_data = { ++ .num_leds = 1, ++ .leds = mi424wr_gpio_led, ++}; ++ ++static struct platform_device mi424wr_gpio_leds = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev.platform_data = &mi424wr_gpio_leds_data, ++}; ++ ++static uint16_t latch_value = MI424WR_LATCH_DEFAULT; ++static uint16_t __iomem *iobase; ++ ++static void mi424wr_latch_set_led(u8 bit, enum led_brightness value) ++{ ++ ++ if (((MI424WR_LATCH_MASK >> bit) & 1) ^ (value == LED_OFF)) ++ latch_value &= ~(0x1 << bit); ++ else ++ latch_value |= (0x1 << bit); ++ ++ __raw_writew(latch_value, iobase); ++ ++} ++ ++static struct latch_led mi424wr_latch_led[] = { ++ { ++ .name = "power-alarm", ++ .bit = MI424WR_LATCH_ALARM_LED, ++ }, ++ { ++ .name = "power-ok", ++ .bit = MI424WR_LATCH_POWER_LED, ++ }, ++ { ++ .name = "wireless", /* green led */ ++ .bit = MI424WR_LATCH_WIRELESS_LED, ++ }, ++ { ++ .name = "inet-down", /* red led */ ++ .bit = MI424WR_LATCH_INET_DOWN_LED, ++ }, ++ { ++ .name = "inet-up", /* green led */ ++ .bit = MI424WR_LATCH_INET_OK_LED, ++ }, ++ { ++ .name = "moca-lan", /* green led */ ++ .bit = MI424WR_LATCH_MOCA_LAN_LED, ++ }, ++ { ++ .name = "wan-alarm", /* red led */ ++ .bit = MI424WR_LATCH_WAN_ALARM_LED, ++ } ++}; ++ ++static struct latch_led_platform_data mi424wr_latch_leds_data = { ++ .num_leds = ARRAY_SIZE(mi424wr_latch_led), ++ .mem = 0x51000000, ++ .leds = mi424wr_latch_led, ++ .set_led = mi424wr_latch_set_led, ++}; ++ ++static struct platform_device mi424wr_latch_leds = { ++ .name = "leds-latch", ++ .id = -1, ++ .dev.platform_data = &mi424wr_latch_leds_data, ++}; ++ ++static struct platform_device mi424wr_spi_bus = { ++ .name = "spi-gpio", ++ .id = 0, ++ .dev.platform_data = &mi424wr_spi_bus_data, ++}; ++ ++static struct eth_plat_info mi424wr_npeb_data = { ++ .phy = 17, /* KS8721 */ ++ .rxq = 3, ++ .txreadyq = 20, ++}; ++ ++static struct eth_plat_info mi424wr_npec_data = { ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0x1e, /* ports 1-4 of the KS8995 switch */ ++ .rxq = 4, ++ .txreadyq = 21, ++}; ++ ++static struct platform_device mi424wr_npe_devices[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = &mi424wr_npec_data, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = &mi424wr_npeb_data, ++ } ++}; ++ ++static struct platform_device *mi424wr_devices[] __initdata = { ++ &mi424wr_uart_device, ++ &mi424wr_flash, ++ &mi424wr_gpio_leds, ++ &mi424wr_latch_leds, ++ &mi424wr_spi_bus, ++ &mi424wr_npe_devices[0], ++ &mi424wr_npe_devices[1], ++}; ++ ++static void __init mi424wr_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ mi424wr_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ mi424wr_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = MI424WR_CS1_CONFIG; ++ ++ /* configure button as input ++ */ ++ gpio_line_config(MI424WR_BUTTON_GPIO, IXP4XX_GPIO_IN); ++ ++ /* Initialize LEDs and enables PCI bus. ++ */ ++ iobase = ioremap_nocache(IXP4XX_EXP_BUS_BASE(1), 0x1000); ++ __raw_writew(latch_value, iobase); ++ ++ platform_add_devices(mi424wr_devices, ARRAY_SIZE(mi424wr_devices)); ++} ++ ++ ++MACHINE_START(MI424WR, "Actiontec MI424WR") ++ /* Maintainer: Jose Vasconcellos */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = mi424wr_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++ +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -25,6 +25,7 @@ obj-pci-$(CONFIG_MACH_COMPEX) += ixdp42 + obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o + obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o + obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o ++obj-pci-$(CONFIG_MACH_MI424WR) += mi424wr-pci.o + + obj-y += common.o + +@@ -51,6 +52,7 @@ obj-$(CONFIG_MACH_COMPEX) += compex-setu + obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o + obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o + obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o ++obj-$(CONFIG_MACH_MI424WR) += mi424wr-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -262,6 +262,13 @@ config MACH_MIC256 + Say 'Y' here if you want your kernel to support the MIC256 + board from OMICRON electronics GmbH. + ++config MACH_MI424WR ++ bool "Actiontec MI424WR" ++ depends on ARCH_IXP4XX ++ select PCI ++ help ++ Add support for the Actiontec MI424-WR. ++ + comment "IXP4xx Options" + + config IXP4XX_INDIRECT_PCI +--- a/arch/arm/configs/ixp4xx_defconfig ++++ b/arch/arm/configs/ixp4xx_defconfig +@@ -26,6 +26,7 @@ CONFIG_MACH_NAS100D=y + CONFIG_MACH_DSMG600=y + CONFIG_MACH_FSG=y + CONFIG_MACH_GTWX5715=y ++CONFIG_MACH_MI424WR=y + CONFIG_IXP4XX_QMGR=y + CONFIG_IXP4XX_NPE=y + # CONFIG_ARM_THUMB is not set diff --git a/target/linux/ixp4xx/patches-3.3/190-cambria_support.patch b/target/linux/ixp4xx/patches-3.3/190-cambria_support.patch new file mode 100644 index 0000000000..3c6627cb35 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/190-cambria_support.patch @@ -0,0 +1,554 @@ +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/cambria-pci.c +@@ -0,0 +1,74 @@ ++/* ++ * arch/arch/mach-ixp4xx/cambria-pci.c ++ * ++ * PCI setup routines for Gateworks Cambria series ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Imre Kaloz <kaloz@openwrt.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++ ++#include <asm/mach/pci.h> ++ ++extern void ixp4xx_pci_preinit(void); ++extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); ++extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); ++ ++void __init cambria_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init cambria_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 1) ++ return IRQ_IXP4XX_GPIO11; ++ else if (slot == 2) ++ return IRQ_IXP4XX_GPIO10; ++ else if (slot == 3) ++ return IRQ_IXP4XX_GPIO9; ++ else if (slot == 4) ++ return IRQ_IXP4XX_GPIO8; ++ else return -1; ++} ++ ++struct hw_pci cambria_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = cambria_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = cambria_map_irq, ++}; ++ ++int __init cambria_pci_init(void) ++{ ++ if (machine_is_cambria()) ++ pci_common_init(&cambria_pci); ++ return 0; ++} ++ ++subsys_initcall(cambria_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/cambria-setup.c +@@ -0,0 +1,430 @@ ++/* ++ * arch/arm/mach-ixp4xx/cambria-setup.c ++ * ++ * Board setup for the Gateworks Cambria series ++ * ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Imre Kaloz <kaloz@openwrt.org> ++ */ ++ ++#include <linux/device.h> ++#include <linux/i2c.h> ++#include <linux/i2c-gpio.h> ++#include <linux/i2c/at24.h> ++#include <linux/if_ether.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/leds.h> ++#include <linux/memory.h> ++#include <linux/netdevice.h> ++#include <linux/serial.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++#include <linux/socket.h> ++#include <linux/types.h> ++#include <linux/tty.h> ++ ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/setup.h> ++ ++struct cambria_board_info { ++ unsigned char *model; ++ void (*setup)(void); ++}; ++ ++static struct cambria_board_info *cambria_info __initdata; ++ ++static struct flash_platform_data cambria_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource cambria_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cambria_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &cambria_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cambria_flash_resource, ++}; ++ ++static struct i2c_gpio_platform_data cambria_i2c_gpio_data = { ++ .sda_pin = 7, ++ .scl_pin = 6, ++}; ++ ++static struct platform_device cambria_i2c_gpio = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &cambria_i2c_gpio_data, ++ }, ++}; ++ ++static struct eth_plat_info cambria_npec_data = { ++ .phy = 1, ++ .rxq = 4, ++ .txreadyq = 21, ++}; ++ ++static struct eth_plat_info cambria_npea_data = { ++ .phy = 2, ++ .rxq = 2, ++ .txreadyq = 19, ++}; ++ ++static struct platform_device cambria_npec_device = { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = &cambria_npec_data, ++}; ++ ++static struct platform_device cambria_npea_device = { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEA, ++ .dev.platform_data = &cambria_npea_data, ++}; ++ ++static struct resource cambria_uart_resource = { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct plat_serial8250_port cambria_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device cambria_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = cambria_uart_data, ++ }, ++ .num_resources = 1, ++ .resource = &cambria_uart_resource, ++}; ++ ++static struct resource cambria_pata_resources[] = { ++ { ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "intrq", ++ .start = IRQ_IXP4XX_GPIO12, ++ .end = IRQ_IXP4XX_GPIO12, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct ixp4xx_pata_data cambria_pata_data = { ++ .cs0_bits = 0xbfff3c03, ++ .cs1_bits = 0xbfff3c03, ++}; ++ ++static struct platform_device cambria_pata = { ++ .name = "pata_ixp4xx_cf", ++ .id = 0, ++ .dev.platform_data = &cambria_pata_data, ++ .num_resources = ARRAY_SIZE(cambria_pata_resources), ++ .resource = cambria_pata_resources, ++}; ++ ++static struct gpio_led cambria_gpio_leds[] = { ++ { ++ .name = "user", /* green led */ ++ .gpio = 5, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led_platform_data cambria_gpio_leds_data = { ++ .num_leds = 1, ++ .leds = cambria_gpio_leds, ++}; ++ ++static struct platform_device cambria_gpio_leds_device = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev.platform_data = &cambria_gpio_leds_data, ++}; ++ ++static struct latch_led cambria_latch_leds[] = { ++ { ++ .name = "ledA", /* green led */ ++ .bit = 0, ++ }, ++ { ++ .name = "ledB", /* green led */ ++ .bit = 1, ++ }, ++ { ++ .name = "ledC", /* green led */ ++ .bit = 2, ++ }, ++ { ++ .name = "ledD", /* green led */ ++ .bit = 3, ++ }, ++ { ++ .name = "ledE", /* green led */ ++ .bit = 4, ++ }, ++ { ++ .name = "ledF", /* green led */ ++ .bit = 5, ++ }, ++ { ++ .name = "ledG", /* green led */ ++ .bit = 6, ++ }, ++ { ++ .name = "ledH", /* green led */ ++ .bit = 7, ++ } ++}; ++ ++static struct latch_led_platform_data cambria_latch_leds_data = { ++ .num_leds = 8, ++ .leds = cambria_latch_leds, ++ .mem = 0x53F40000, ++}; ++ ++static struct platform_device cambria_latch_leds_device = { ++ .name = "leds-latch", ++ .id = -1, ++ .dev.platform_data = &cambria_latch_leds_data, ++}; ++ ++static struct resource cambria_usb0_resources[] = { ++ { ++ .start = 0xCD000000, ++ .end = 0xCD000300, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = 32, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource cambria_usb1_resources[] = { ++ { ++ .start = 0xCE000000, ++ .end = 0xCE000300, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = 33, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 ehci_dma_mask = ~(u32)0; ++ ++static struct platform_device cambria_usb0_device = { ++ .name = "ixp4xx-ehci", ++ .id = 0, ++ .resource = cambria_usb0_resources, ++ .num_resources = ARRAY_SIZE(cambria_usb0_resources), ++ .dev = { ++ .dma_mask = &ehci_dma_mask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++}; ++ ++static struct platform_device cambria_usb1_device = { ++ .name = "ixp4xx-ehci", ++ .id = 1, ++ .resource = cambria_usb1_resources, ++ .num_resources = ARRAY_SIZE(cambria_usb1_resources), ++ .dev = { ++ .dma_mask = &ehci_dma_mask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++}; ++ ++static struct platform_device *cambria_devices[] __initdata = { ++ &cambria_i2c_gpio, ++ &cambria_flash, ++ &cambria_uart, ++}; ++ ++static void __init cambria_gw23xx_setup(void) ++{ ++ platform_device_register(&cambria_npec_device); ++ platform_device_register(&cambria_npea_device); ++} ++ ++static void __init cambria_gw2350_setup(void) ++{ ++ platform_device_register(&cambria_npec_device); ++ platform_device_register(&cambria_npea_device); ++ ++ platform_device_register(&cambria_usb0_device); ++ platform_device_register(&cambria_usb1_device); ++ ++ platform_device_register(&cambria_gpio_leds_device); ++} ++ ++static void __init cambria_gw2358_setup(void) ++{ ++ platform_device_register(&cambria_npec_device); ++ platform_device_register(&cambria_npea_device); ++ ++ platform_device_register(&cambria_usb0_device); ++ platform_device_register(&cambria_usb1_device); ++ ++ platform_device_register(&cambria_pata); ++ ++ platform_device_register(&cambria_latch_leds_device); ++} ++ ++static struct cambria_board_info cambria_boards[] __initdata = { ++ { ++ .model = "GW2350", ++ .setup = cambria_gw2350_setup, ++ }, { ++ .model = "GW2358", ++ .setup = cambria_gw2358_setup, ++ } ++}; ++ ++static struct cambria_board_info * __init cambria_find_board_info(char *model) ++{ ++ int i; ++ model[6] = '\0'; ++ ++ for (i = 0; i < ARRAY_SIZE(cambria_boards); i++) { ++ struct cambria_board_info *info = &cambria_boards[i]; ++ if (strcmp(info->model, model) == 0) ++ return info; ++ } ++ ++ return NULL; ++} ++ ++static struct memory_accessor *at24_mem_acc; ++ ++static void at24_setup(struct memory_accessor *mem_acc, void *context) ++{ ++ char mac_addr[ETH_ALEN]; ++ char model[7]; ++ ++ at24_mem_acc = mem_acc; ++ ++ /* Read MAC addresses */ ++ if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x0, 6) == 6) { ++ memcpy(&cambria_npec_data.hwaddr, mac_addr, ETH_ALEN); ++ } ++ if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x6, 6) == 6) { ++ memcpy(&cambria_npea_data.hwaddr, mac_addr, ETH_ALEN); ++ } ++ ++ /* Read the first 6 bytes of the model number */ ++ if (at24_mem_acc->read(at24_mem_acc, model, 0x20, 6) == 6) { ++ cambria_info = cambria_find_board_info(model); ++ } ++ ++} ++ ++static struct at24_platform_data cambria_eeprom_info = { ++ .byte_len = 1024, ++ .page_size = 16, ++ .flags = AT24_FLAG_READONLY, ++ .setup = at24_setup, ++}; ++ ++static struct i2c_board_info __initdata cambria_i2c_board_info[] = { ++ { ++ I2C_BOARD_INFO("ds1672", 0x68), ++ }, ++ { ++ I2C_BOARD_INFO("ad7418", 0x28), ++ }, ++ { ++ I2C_BOARD_INFO("24c08", 0x51), ++ .platform_data = &cambria_eeprom_info ++ }, ++}; ++ ++static void __init cambria_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ cambria_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ cambria_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; ++ ++ platform_add_devices(cambria_devices, ARRAY_SIZE(cambria_devices)); ++ ++ cambria_pata_resources[0].start = 0x53e00000; ++ cambria_pata_resources[0].end = 0x53e3ffff; ++ ++ cambria_pata_resources[1].start = 0x53e40000; ++ cambria_pata_resources[1].end = 0x53e7ffff; ++ ++ cambria_pata_data.cs0_cfg = IXP4XX_EXP_CS3; ++ cambria_pata_data.cs1_cfg = IXP4XX_EXP_CS3; ++ ++ i2c_register_board_info(0, cambria_i2c_board_info, ++ ARRAY_SIZE(cambria_i2c_board_info)); ++} ++ ++static int __init cambria_model_setup(void) ++{ ++ if (!machine_is_cambria()) ++ return 0; ++ ++ if (cambria_info) { ++ printk(KERN_DEBUG "Running on Gateworks Cambria %s\n", ++ cambria_info->model); ++ cambria_info->setup(); ++ } else { ++ printk(KERN_INFO "Unknown/missing Cambria model number" ++ " -- defaults will be used\n"); ++ cambria_gw23xx_setup(); ++ } ++ ++ return 0; ++} ++late_initcall(cambria_model_setup); ++ ++MACHINE_START(CAMBRIA, "Gateworks Cambria series") ++ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = cambria_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -25,6 +25,14 @@ config MACH_AVILA + Avila Network Platform. For more information on this platform, + see <file:Documentation/arm/IXP4xx>. + ++config MACH_CAMBRIA ++ bool "Cambria" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support the Gateworks ++ Cambria series. For more information on this platform, ++ see <file:Documentation/arm/IXP4xx>. ++ + config MACH_LOFT + bool "Loft" + depends on MACH_AVILA +@@ -222,7 +230,7 @@ config CPU_IXP46X + + config CPU_IXP43X + bool +- depends on MACH_KIXRP435 ++ depends on MACH_KIXRP435 || MACH_CAMBRIA + default y + + config MACH_GTWX5715 +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -7,6 +7,7 @@ obj-pci-n := + + obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o + obj-pci-$(CONFIG_MACH_AVILA) += avila-pci.o ++obj-pci-$(CONFIG_MACH_CAMBRIA) += cambria-pci.o + obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o + obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o + obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o +@@ -31,6 +32,7 @@ obj-y += common.o + + obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o + obj-$(CONFIG_MACH_AVILA) += avila-setup.o ++obj-$(CONFIG_MACH_CAMBRIA) += cambria-setup.o + obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o + obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o + obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o diff --git a/target/linux/ixp4xx/patches-3.3/191-cambria_optional_uart.patch b/target/linux/ixp4xx/patches-3.3/191-cambria_optional_uart.patch new file mode 100644 index 0000000000..636ebd715b --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/191-cambria_optional_uart.patch @@ -0,0 +1,217 @@ +--- a/arch/arm/mach-ixp4xx/cambria-setup.c ++++ b/arch/arm/mach-ixp4xx/cambria-setup.c +@@ -34,6 +34,7 @@ + #include <asm/mach/arch.h> + #include <asm/mach/flash.h> + #include <asm/setup.h> ++#include <linux/irq.h> + + struct cambria_board_info { + unsigned char *model; +@@ -127,6 +128,45 @@ static struct platform_device cambria_ua + .resource = &cambria_uart_resource, + }; + ++static struct resource cambria_optional_uart_resources[] = { ++ { ++ .start = 0x52000000, ++ .end = 0x52000fff, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = 0x53000000, ++ .end = 0x53000fff, ++ .flags = IORESOURCE_MEM ++ } ++}; ++ ++static struct plat_serial8250_port cambria_optional_uart_data[] = { ++ { ++ .flags = UPF_BOOT_AUTOCONF, ++ .iotype = UPIO_MEM_DELAY, ++ .regshift = 0, ++ .uartclk = 1843200, ++ .rw_delay = 2, ++ }, ++ { ++ .flags = UPF_BOOT_AUTOCONF, ++ .iotype = UPIO_MEM_DELAY, ++ .regshift = 0, ++ .uartclk = 1843200, ++ .rw_delay = 2, ++ }, ++ { }, ++}; ++ ++static struct platform_device cambria_optional_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev.platform_data = cambria_optional_uart_data, ++ .num_resources = 2, ++ .resource = cambria_optional_uart_resources, ++}; ++ + static struct resource cambria_pata_resources[] = { + { + .flags = IORESOURCE_MEM +@@ -283,6 +323,19 @@ static void __init cambria_gw23xx_setup( + + static void __init cambria_gw2350_setup(void) + { ++ *IXP4XX_EXP_CS2 = 0xBFFF3C43; ++ irq_set_irq_type(IRQ_IXP4XX_GPIO3, IRQ_TYPE_EDGE_RISING); ++ cambria_optional_uart_data[0].mapbase = 0x52FF0000; ++ cambria_optional_uart_data[0].membase = (void __iomem *)ioremap(0x52FF0000, 0x0fff); ++ cambria_optional_uart_data[0].irq = IRQ_IXP4XX_GPIO3; ++ ++ *IXP4XX_EXP_CS3 = 0xBFFF3C43; ++ irq_set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_EDGE_RISING); ++ cambria_optional_uart_data[1].mapbase = 0x53FF0000; ++ cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53FF0000, 0x0fff); ++ cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; ++ ++ platform_device_register(&cambria_optional_uart); + platform_device_register(&cambria_npec_device); + platform_device_register(&cambria_npea_device); + +@@ -294,6 +347,19 @@ static void __init cambria_gw2350_setup( + + static void __init cambria_gw2358_setup(void) + { ++ *IXP4XX_EXP_CS3 = 0xBFFF3C43; ++ irq_set_irq_type(IRQ_IXP4XX_GPIO3, IRQ_TYPE_EDGE_RISING); ++ cambria_optional_uart_data[0].mapbase = 0x53FC0000; ++ cambria_optional_uart_data[0].membase = (void __iomem *)ioremap(0x53FC0000, 0x0fff); ++ cambria_optional_uart_data[0].irq = IRQ_IXP4XX_GPIO3; ++ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_EDGE_RISING); ++ cambria_optional_uart_data[1].mapbase = 0x53F80000; ++ cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53F80000, 0x0fff); ++ cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; ++ ++ platform_device_register(&cambria_optional_uart); ++ + platform_device_register(&cambria_npec_device); + platform_device_register(&cambria_npea_device); + +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -27,6 +27,7 @@ struct plat_serial8250_port { + void *private_data; + unsigned char regshift; /* register shift */ + unsigned char iotype; /* UPIO_* */ ++ unsigned int rw_delay; /* udelay for slower busses IXP4XX Expansion Bus */ + unsigned char hub6; + upf_t flags; /* UPF_* flags */ + unsigned int type; /* If UPF_FIXED_TYPE */ +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -324,6 +324,7 @@ struct uart_port { + #define UPIO_AU (4) /* Au1x00 type IO */ + #define UPIO_TSI (5) /* Tsi108/109 type IO */ + #define UPIO_RM9000 (6) /* RM9000 type IO */ ++#define UPIO_MEM_DELAY (7) + + unsigned int read_status_mask; /* driver specific */ + unsigned int ignore_status_mask; /* driver specific */ +@@ -368,6 +369,7 @@ struct uart_port { + + unsigned int mctrl; /* current modem ctrl settings */ + unsigned int timeout; /* character-based timeout */ ++ unsigned int rw_delay; /* udelay for slow busses, IXP4XX Expansion Bus */ + unsigned int type; /* port type */ + const struct uart_ops *ops; + unsigned int custom_divisor; +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -400,6 +400,20 @@ static void mem_serial_out(struct uart_p + writeb(value, p->membase + offset); + } + ++static unsigned int memdelay_serial_in(struct uart_port *p, int offset) ++{ ++ struct uart_8250_port *up = (struct uart_8250_port *)p; ++ udelay(up->port.rw_delay); ++ return mem_serial_in(p, offset); ++} ++ ++static void memdelay_serial_out(struct uart_port *p, int offset, int value) ++{ ++ struct uart_8250_port *up = (struct uart_8250_port *)p; ++ udelay(up->port.rw_delay); ++ mem_serial_out(p, offset, value); ++} ++ + static void mem32_serial_out(struct uart_port *p, int offset, int value) + { + offset = map_8250_out_reg(p, offset) << p->regshift; +@@ -459,6 +473,11 @@ static void set_io_from_upio(struct uart + p->serial_out = mem32_serial_out; + break; + ++ case UPIO_MEM_DELAY: ++ p->serial_in = memdelay_serial_in; ++ p->serial_out = memdelay_serial_out; ++ break; ++ + case UPIO_AU: + p->serial_in = au_serial_in; + p->serial_out = au_serial_out; +@@ -481,6 +500,7 @@ serial_out_sync(struct uart_8250_port *u + switch (p->iotype) { + case UPIO_MEM: + case UPIO_MEM32: ++ case UPIO_MEM_DELAY: + case UPIO_AU: + p->serial_out(p, offset, value); + p->serial_in(p, UART_LCR); /* safe, no side-effects */ +@@ -2498,6 +2518,7 @@ static int serial8250_request_std_resour + case UPIO_TSI: + case UPIO_MEM32: + case UPIO_MEM: ++ case UPIO_MEM_DELAY: + if (!up->port.mapbase) + break; + +@@ -2534,6 +2555,7 @@ static void serial8250_release_std_resou + case UPIO_TSI: + case UPIO_MEM32: + case UPIO_MEM: ++ case UPIO_MEM_DELAY: + if (!up->port.mapbase) + break; + +@@ -3050,6 +3072,7 @@ static int __devinit serial8250_probe(st + port.set_termios = p->set_termios; + port.pm = p->pm; + port.dev = &dev->dev; ++ port.rw_delay = p->rw_delay; + port.irqflags |= irqflag; + ret = serial8250_register_port(&port); + if (ret < 0) { +@@ -3199,6 +3222,7 @@ int serial8250_register_port(struct uart + uart->port.iotype = port->iotype; + uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; + uart->port.mapbase = port->mapbase; ++ uart->port.rw_delay = port->rw_delay; + uart->port.private_data = port->private_data; + if (port->dev) + uart->port.dev = port->dev; +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -2021,6 +2021,7 @@ uart_report_port(struct uart_driver *drv + snprintf(address, sizeof(address), + "I/O 0x%lx offset 0x%x", port->iobase, port->hub6); + break; ++ case UPIO_MEM_DELAY: + case UPIO_MEM: + case UPIO_MEM32: + case UPIO_AU: +@@ -2435,6 +2436,7 @@ int uart_match_port(struct uart_port *po + case UPIO_HUB6: + return (port1->iobase == port2->iobase) && + (port1->hub6 == port2->hub6); ++ case UPIO_MEM_DELAY: + case UPIO_MEM: + case UPIO_MEM32: + case UPIO_AU: diff --git a/target/linux/ixp4xx/patches-3.3/192-cambria_gpio_device.patch b/target/linux/ixp4xx/patches-3.3/192-cambria_gpio_device.patch new file mode 100644 index 0000000000..d785c3a8ca --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/192-cambria_gpio_device.patch @@ -0,0 +1,46 @@ +--- a/arch/arm/mach-ixp4xx/cambria-setup.c ++++ b/arch/arm/mach-ixp4xx/cambria-setup.c +@@ -214,6 +214,20 @@ static struct platform_device cambria_gp + .dev.platform_data = &cambria_gpio_leds_data, + }; + ++static struct resource cambria_gpio_resources[] = { ++ { ++ .name = "gpio", ++ .flags = 0, ++ }, ++}; ++ ++static struct platform_device cambria_gpio = { ++ .name = "GPIODEV", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(cambria_gpio_resources), ++ .resource = cambria_gpio_resources, ++}; ++ + static struct latch_led cambria_latch_leds[] = { + { + .name = "ledA", /* green led */ +@@ -335,6 +349,11 @@ static void __init cambria_gw2350_setup( + cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53FF0000, 0x0fff); + cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; + ++ cambria_gpio_resources[0].start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) |\ ++ (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12); ++ cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; ++ ++ platform_device_register(&cambria_gpio); + platform_device_register(&cambria_optional_uart); + platform_device_register(&cambria_npec_device); + platform_device_register(&cambria_npea_device); +@@ -358,6 +377,10 @@ static void __init cambria_gw2358_setup( + cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53F80000, 0x0fff); + cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; + ++ cambria_gpio_resources[0].start = (1 << 14); ++ cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; ++ ++ platform_device_register(&cambria_gpio); + platform_device_register(&cambria_optional_uart); + + platform_device_register(&cambria_npec_device); diff --git a/target/linux/ixp4xx/patches-3.3/193-cambria_pld_gpio.patch b/target/linux/ixp4xx/patches-3.3/193-cambria_pld_gpio.patch new file mode 100644 index 0000000000..299630f171 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/193-cambria_pld_gpio.patch @@ -0,0 +1,107 @@ +--- a/arch/arm/mach-ixp4xx/cambria-setup.c ++++ b/arch/arm/mach-ixp4xx/cambria-setup.c +@@ -12,11 +12,14 @@ + */ + + #include <linux/device.h> ++#include <linux/gpio_buttons.h> + #include <linux/i2c.h> + #include <linux/i2c-gpio.h> + #include <linux/i2c/at24.h> ++#include <linux/i2c/gw_i2c_pld.h> + #include <linux/if_ether.h> + #include <linux/init.h> ++#include <linux/input.h> + #include <linux/kernel.h> + #include <linux/leds.h> + #include <linux/memory.h> +@@ -323,6 +326,39 @@ static struct platform_device cambria_us + }, + }; + ++static struct gw_i2c_pld_platform_data gw_i2c_pld_data0 = { ++ .gpio_base = 16, ++ .nr_gpio = 8, ++}; ++ ++static struct gw_i2c_pld_platform_data gw_i2c_pld_data1 = { ++ .gpio_base = 24, ++ .nr_gpio = 2, ++}; ++ ++ ++static struct gpio_button cambria_gpio_buttons[] = { ++ { ++ .desc = "user", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .threshold = 2, ++ .gpio = 25, ++ } ++}; ++ ++static struct gpio_buttons_platform_data cambria_gpio_buttons_data = { ++ .poll_interval = 500, ++ .nbuttons = 1, ++ .buttons = cambria_gpio_buttons, ++}; ++ ++static struct platform_device cambria_gpio_buttons_device = { ++ .name = "gpio-buttons", ++ .id = -1, ++ .dev.platform_data = &cambria_gpio_buttons_data, ++}; ++ + static struct platform_device *cambria_devices[] __initdata = { + &cambria_i2c_gpio, + &cambria_flash, +@@ -331,6 +367,11 @@ static struct platform_device *cambria_d + + static void __init cambria_gw23xx_setup(void) + { ++ cambria_gpio_resources[0].start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) |\ ++ (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12); ++ cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; ++ ++ platform_device_register(&cambria_gpio); + platform_device_register(&cambria_npec_device); + platform_device_register(&cambria_npea_device); + } +@@ -377,7 +418,8 @@ static void __init cambria_gw2358_setup( + cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53F80000, 0x0fff); + cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; + +- cambria_gpio_resources[0].start = (1 << 14); ++ cambria_gpio_resources[0].start = (1 << 14) | (1 << 16) | (1 << 17) | (1 << 18) |\ ++ (1 << 19) | (1 << 20) | (1 << 24) | (1 << 25); + cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; + + platform_device_register(&cambria_gpio); +@@ -391,7 +433,12 @@ static void __init cambria_gw2358_setup( + + platform_device_register(&cambria_pata); + ++ cambria_gpio_leds[0].gpio = 24; ++ platform_device_register(&cambria_gpio_leds_device); ++ + platform_device_register(&cambria_latch_leds_device); ++ ++ platform_device_register(&cambria_gpio_buttons_device); + } + + static struct cambria_board_info cambria_boards[] __initdata = { +@@ -460,6 +507,14 @@ static struct i2c_board_info __initdata + I2C_BOARD_INFO("24c08", 0x51), + .platform_data = &cambria_eeprom_info + }, ++ { ++ I2C_BOARD_INFO("gw_i2c_pld", 0x56), ++ .platform_data = &gw_i2c_pld_data0, ++ }, ++ { ++ I2C_BOARD_INFO("gw_i2c_pld", 0x57), ++ .platform_data = &gw_i2c_pld_data1, ++ }, + }; + + static void __init cambria_init(void) diff --git a/target/linux/ixp4xx/patches-3.3/201-npe_driver_print_license_location.patch b/target/linux/ixp4xx/patches-3.3/201-npe_driver_print_license_location.patch new file mode 100644 index 0000000000..e6bbbc382c --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/201-npe_driver_print_license_location.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c ++++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c +@@ -582,6 +582,8 @@ int npe_load_firmware(struct npe *npe, c + npe_reset(npe); + #endif + ++ print_npe(KERN_INFO, npe, "firmware's license can be found in /usr/share/doc/LICENSE.IPL\n"); ++ + print_npe(KERN_INFO, npe, "firmware functionality 0x%X, " + "revision 0x%X:%X\n", (image->id >> 16) & 0xFF, + (image->id >> 8) & 0xFF, image->id & 0xFF); diff --git a/target/linux/ixp4xx/patches-3.3/203-npe_driver_mask_phy_features.patch b/target/linux/ixp4xx/patches-3.3/203-npe_driver_mask_phy_features.patch new file mode 100644 index 0000000000..0892b96226 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/203-npe_driver_mask_phy_features.patch @@ -0,0 +1,13 @@ +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -1425,6 +1425,10 @@ static int __devinit eth_init_one(struct + goto err_free_mem; + } + ++ /* mask with MAC supported features */ ++ port->phydev->supported &= PHY_BASIC_FEATURES; ++ port->phydev->advertising = port->phydev->supported; ++ + port->phydev->irq = PHY_POLL; + + if ((err = register_netdev(dev))) diff --git a/target/linux/ixp4xx/patches-3.3/205-npe_driver_separate_phy_functions.patch b/target/linux/ixp4xx/patches-3.3/205-npe_driver_separate_phy_functions.patch new file mode 100644 index 0000000000..23b6338a89 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/205-npe_driver_separate_phy_functions.patch @@ -0,0 +1,122 @@ +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -573,6 +573,51 @@ static void ixp4xx_adjust_link(struct ne + dev->name, port->speed, port->duplex ? "full" : "half"); + } + ++static int ixp4xx_phy_connect(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ struct eth_plat_info *plat = port->plat; ++ char phy_id[MII_BUS_ID_SIZE + 3]; ++ ++ snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, ++ mdio_bus->id, plat->phy); ++ port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, ++ PHY_INTERFACE_MODE_MII); ++ if (IS_ERR(port->phydev)) { ++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); ++ return PTR_ERR(port->phydev); ++ } ++ ++ /* mask with MAC supported features */ ++ port->phydev->supported &= PHY_BASIC_FEATURES; ++ port->phydev->advertising = port->phydev->supported; ++ ++ port->phydev->irq = PHY_POLL; ++ ++ return 0; ++} ++ ++static void ixp4xx_phy_disconnect(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ ++ phy_disconnect(port->phydev); ++} ++ ++static void ixp4xx_phy_start(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ ++ port->speed = 0; /* force "link up" message */ ++ phy_start(port->phydev); ++} ++ ++static void ixp4xx_phy_stop(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ ++ phy_stop(port->phydev); ++} + + static inline void debug_pkt(struct net_device *dev, const char *func, + u8 *data, int len) +@@ -1205,8 +1250,7 @@ static int eth_open(struct net_device *d + return err; + } + +- port->speed = 0; /* force "link up" message */ +- phy_start(port->phydev); ++ ixp4xx_phy_start(dev); + + for (i = 0; i < ETH_ALEN; i++) + __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); +@@ -1327,7 +1371,7 @@ static int eth_close(struct net_device * + printk(KERN_CRIT "%s: unable to disable loopback\n", + dev->name); + +- phy_stop(port->phydev); ++ ixp4xx_phy_stop(dev); + + if (!ports_open) + qmgr_disable_irq(TXDONE_QUEUE); +@@ -1353,7 +1397,6 @@ static int __devinit eth_init_one(struct + struct net_device *dev; + struct eth_plat_info *plat = pdev->dev.platform_data; + u32 regs_phys; +- char phy_id[MII_BUS_ID_SIZE + 3]; + int err; + + if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { +@@ -1416,20 +1459,9 @@ static int __devinit eth_init_one(struct + __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); + udelay(50); + +- snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, +- mdio_bus->id, plat->phy); +- port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, +- PHY_INTERFACE_MODE_MII); +- if (IS_ERR(port->phydev)) { +- err = PTR_ERR(port->phydev); ++ err = ixp4xx_phy_connect(dev); ++ if (err) + goto err_free_mem; +- } +- +- /* mask with MAC supported features */ +- port->phydev->supported &= PHY_BASIC_FEATURES; +- port->phydev->advertising = port->phydev->supported; +- +- port->phydev->irq = PHY_POLL; + + if ((err = register_netdev(dev))) + goto err_phy_dis; +@@ -1440,7 +1472,7 @@ static int __devinit eth_init_one(struct + return 0; + + err_phy_dis: +- phy_disconnect(port->phydev); ++ ixp4xx_phy_disconnect(dev); + err_free_mem: + npe_port_tab[NPE_ID(port->id)] = NULL; + platform_set_drvdata(pdev, NULL); +@@ -1458,7 +1490,7 @@ static int __devexit eth_remove_one(stru + struct port *port = netdev_priv(dev); + + unregister_netdev(dev); +- phy_disconnect(port->phydev); ++ ixp4xx_phy_disconnect(dev); + npe_port_tab[NPE_ID(port->id)] = NULL; + platform_set_drvdata(pdev, NULL); + npe_release(port->npe); diff --git a/target/linux/ixp4xx/patches-3.3/206-npe_driver_add_update_link_function.patch b/target/linux/ixp4xx/patches-3.3/206-npe_driver_add_update_link_function.patch new file mode 100644 index 0000000000..9e1b07f92d --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/206-npe_driver_add_update_link_function.patch @@ -0,0 +1,98 @@ +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -177,7 +177,7 @@ struct port { + struct desc *desc_tab; /* coherent */ + u32 desc_tab_phys; + int id; /* logical port ID */ +- int speed, duplex; ++ int link, speed, duplex; + u8 firmware[4]; + int hwts_tx_en; + int hwts_rx_en; +@@ -542,37 +542,52 @@ static void ixp4xx_mdio_remove(void) + mdiobus_free(mdio_bus); + } + +- +-static void ixp4xx_adjust_link(struct net_device *dev) ++static void ixp4xx_update_link(struct net_device *dev) + { + struct port *port = netdev_priv(dev); +- struct phy_device *phydev = port->phydev; + +- if (!phydev->link) { +- if (port->speed) { +- port->speed = 0; +- printk(KERN_INFO "%s: link down\n", dev->name); +- } ++ if (!port->link) { ++ netif_carrier_off(dev); ++ printk(KERN_INFO "%s: link down\n", dev->name); + return; + } + +- if (port->speed == phydev->speed && port->duplex == phydev->duplex) +- return; +- +- port->speed = phydev->speed; +- port->duplex = phydev->duplex; +- +- if (port->duplex) ++ if (port->duplex == DUPLEX_FULL) + __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, + &port->regs->tx_control[0]); + else + __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, + &port->regs->tx_control[0]); + ++ netif_carrier_on(dev); + printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n", + dev->name, port->speed, port->duplex ? "full" : "half"); + } + ++static void ixp4xx_adjust_link(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ struct phy_device *phydev = port->phydev; ++ int status_change = 0; ++ ++ if (phydev->link) { ++ if (port->duplex != phydev->duplex ++ || port->speed != phydev->speed) { ++ status_change = 1; ++ } ++ } ++ ++ if (phydev->link != port->link) ++ status_change = 1; ++ ++ port->link = phydev->link; ++ port->speed = phydev->speed; ++ port->duplex = phydev->duplex; ++ ++ if (status_change) ++ ixp4xx_update_link(dev); ++} ++ + static int ixp4xx_phy_connect(struct net_device *dev) + { + struct port *port = netdev_priv(dev); +@@ -608,7 +623,6 @@ static void ixp4xx_phy_start(struct net_ + { + struct port *port = netdev_priv(dev); + +- port->speed = 0; /* force "link up" message */ + phy_start(port->phydev); + } + +@@ -1466,6 +1480,10 @@ static int __devinit eth_init_one(struct + if ((err = register_netdev(dev))) + goto err_phy_dis; + ++ port->link = 0; ++ port->speed = 0; ++ port->duplex = -1; ++ + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, + npe_name(port->npe)); + diff --git a/target/linux/ixp4xx/patches-3.3/207-npe_driver_multiphy_support.patch b/target/linux/ixp4xx/patches-3.3/207-npe_driver_multiphy_support.patch new file mode 100644 index 0000000000..d50c545cc1 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/207-npe_driver_multiphy_support.patch @@ -0,0 +1,154 @@ +TODO: take care of additional PHYs through the PHY abstraction layer + +--- a/arch/arm/mach-ixp4xx/include/mach/platform.h ++++ b/arch/arm/mach-ixp4xx/include/mach/platform.h +@@ -72,7 +72,7 @@ extern unsigned long ixp4xx_exp_bus_size + /* + * Clock Speed Definitions. + */ +-#define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66Mhzi APB BUS */ ++#define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66Mhzi APB BUS */ + #define IXP4XX_UART_XTAL 14745600 + + /* +@@ -95,12 +95,23 @@ struct sys_timer; + #define IXP4XX_ETH_NPEB 0x10 + #define IXP4XX_ETH_NPEC 0x20 + ++#define IXP4XX_ETH_PHY_MAX_ADDR 32 ++ + /* Information about built-in Ethernet MAC interfaces */ + struct eth_plat_info { + u8 phy; /* MII PHY ID, 0 - 31 */ + u8 rxq; /* configurable, currently 0 - 31 only */ + u8 txreadyq; + u8 hwaddr[6]; ++ ++ u32 phy_mask; ++#if 0 ++ int speed; ++ int duplex; ++#else ++ int speed_10; ++ int half_duplex; ++#endif + }; + + /* Information about built-in HSS (synchronous serial) interfaces */ +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -594,6 +594,37 @@ static int ixp4xx_phy_connect(struct net + struct eth_plat_info *plat = port->plat; + char phy_id[MII_BUS_ID_SIZE + 3]; + ++ if (plat->phy == IXP4XX_ETH_PHY_MAX_ADDR) { ++#if 0 ++ switch (plat->speed) { ++ case SPEED_10: ++ case SPEED_100: ++ break; ++ default: ++ printk(KERN_ERR "%s: invalid speed (%d)\n", ++ dev->name, plat->speed); ++ return -EINVAL; ++ } ++ ++ switch (plat->duplex) { ++ case DUPLEX_HALF: ++ case DUPLEX_FULL: ++ break; ++ default: ++ printk(KERN_ERR "%s: invalid duplex mode (%d)\n", ++ dev->name, plat->duplex); ++ return -EINVAL; ++ } ++ port->speed = plat->speed; ++ port->duplex = plat->duplex; ++#else ++ port->speed = plat->speed_10 ? SPEED_10 : SPEED_100; ++ port->duplex = plat->half_duplex ? DUPLEX_HALF : DUPLEX_FULL; ++#endif ++ ++ return 0; ++ } ++ + snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, + mdio_bus->id, plat->phy); + port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, +@@ -616,21 +647,32 @@ static void ixp4xx_phy_disconnect(struct + { + struct port *port = netdev_priv(dev); + +- phy_disconnect(port->phydev); ++ if (port->phydev) ++ phy_disconnect(port->phydev); + } + + static void ixp4xx_phy_start(struct net_device *dev) + { + struct port *port = netdev_priv(dev); + +- phy_start(port->phydev); ++ if (port->phydev) { ++ phy_start(port->phydev); ++ } else { ++ port->link = 1; ++ ixp4xx_update_link(dev); ++ } + } + + static void ixp4xx_phy_stop(struct net_device *dev) + { + struct port *port = netdev_priv(dev); + +- phy_stop(port->phydev); ++ if (port->phydev) { ++ phy_stop(port->phydev); ++ } else { ++ port->link = 0; ++ ixp4xx_update_link(dev); ++ } + } + + static inline void debug_pkt(struct net_device *dev, const char *func, +@@ -1027,6 +1069,9 @@ static int eth_ioctl(struct net_device * + if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP) + return hwtstamp_ioctl(dev, req, cmd); + ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_mii_ioctl(port->phydev, req, cmd); + } + +@@ -1046,18 +1091,30 @@ static void ixp4xx_get_drvinfo(struct ne + static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct port *port = netdev_priv(dev); ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_ethtool_gset(port->phydev, cmd); + } + + static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct port *port = netdev_priv(dev); ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_ethtool_sset(port->phydev, cmd); + } + + static int ixp4xx_nway_reset(struct net_device *dev) + { + struct port *port = netdev_priv(dev); ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_start_aneg(port->phydev); + } + diff --git a/target/linux/ixp4xx/patches-3.3/295-latch_led_driver.patch b/target/linux/ixp4xx/patches-3.3/295-latch_led_driver.patch new file mode 100644 index 0000000000..3ed6ec5164 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/295-latch_led_driver.patch @@ -0,0 +1,202 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -204,6 +204,13 @@ config LEDS_LP5523 + Driver provides direct control via LED class and interface for + programming the engines. + ++config LEDS_LATCH ++ tristate "LED Support for Memory Latched LEDs" ++ depends on LEDS_CLASS ++ help ++ -- To Do -- ++ ++ + config LEDS_CLEVO_MAIL + tristate "Mail LED on Clevo notebook" + depends on LEDS_CLASS +--- /dev/null ++++ b/drivers/leds/leds-latch.c +@@ -0,0 +1,152 @@ ++/* ++ * LEDs driver for Memory Latched Devices ++ * ++ * Copyright (C) 2008 Gateworks Corp. ++ * Chris Lang <clang@gateworks.com> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/leds.h> ++#include <linux/workqueue.h> ++#include <asm/io.h> ++#include <linux/spinlock.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++#include <linux/export.h> ++ ++static unsigned int mem_keep = 0xFF; ++static spinlock_t mem_lock; ++static unsigned char *iobase; ++ ++struct latch_led_data { ++ struct led_classdev cdev; ++ struct work_struct work; ++ u8 new_level; ++ u8 bit; ++ void (*set_led)(u8 bit, enum led_brightness value); ++}; ++ ++static void latch_set_led(u8 bit, enum led_brightness value) ++{ ++ if (value == LED_OFF) ++ mem_keep |= (0x1 << bit); ++ else ++ mem_keep &= ~(0x1 << bit); ++ ++ writeb(mem_keep, iobase); ++} ++ ++static void latch_led_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ struct latch_led_data *led_dat = ++ container_of(led_cdev, struct latch_led_data, cdev); ++ ++ raw_spin_lock(mem_lock); ++ ++ led_dat->set_led(led_dat->bit, value); ++ ++ raw_spin_unlock(mem_lock); ++} ++ ++static int latch_led_probe(struct platform_device *pdev) ++{ ++ struct latch_led_platform_data *pdata = pdev->dev.platform_data; ++ struct latch_led *cur_led; ++ struct latch_led_data *leds_data, *led_dat; ++ int i, ret = 0; ++ ++ if (!pdata) ++ return -EBUSY; ++ ++ leds_data = kzalloc(sizeof(struct latch_led_data) * pdata->num_leds, ++ GFP_KERNEL); ++ if (!leds_data) ++ return -ENOMEM; ++ ++ for (i = 0; i < pdata->num_leds; i++) { ++ cur_led = &pdata->leds[i]; ++ led_dat = &leds_data[i]; ++ ++ led_dat->cdev.name = cur_led->name; ++ led_dat->cdev.default_trigger = cur_led->default_trigger; ++ led_dat->cdev.brightness_set = latch_led_set; ++ led_dat->cdev.brightness = LED_OFF; ++ led_dat->bit = cur_led->bit; ++ led_dat->set_led = pdata->set_led ? pdata->set_led : latch_set_led; ++ ++ ret = led_classdev_register(&pdev->dev, &led_dat->cdev); ++ if (ret < 0) { ++ goto err; ++ } ++ } ++ ++ if (!pdata->set_led) { ++ iobase = ioremap_nocache(pdata->mem, 0x1000); ++ writeb(0xFF, iobase); ++ } ++ platform_set_drvdata(pdev, leds_data); ++ ++ return 0; ++ ++err: ++ if (i > 0) { ++ for (i = i - 1; i >= 0; i--) { ++ led_classdev_unregister(&leds_data[i].cdev); ++ } ++ } ++ ++ kfree(leds_data); ++ ++ return ret; ++} ++ ++static int __devexit latch_led_remove(struct platform_device *pdev) ++{ ++ int i; ++ struct latch_led_platform_data *pdata = pdev->dev.platform_data; ++ struct latch_led_data *leds_data; ++ ++ leds_data = platform_get_drvdata(pdev); ++ ++ for (i = 0; i < pdata->num_leds; i++) { ++ led_classdev_unregister(&leds_data[i].cdev); ++ cancel_work_sync(&leds_data[i].work); ++ } ++ ++ kfree(leds_data); ++ ++ return 0; ++} ++ ++static struct platform_driver latch_led_driver = { ++ .probe = latch_led_probe, ++ .remove = __devexit_p(latch_led_remove), ++ .driver = { ++ .name = "leds-latch", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init latch_led_init(void) ++{ ++ return platform_driver_register(&latch_led_driver); ++} ++ ++static void __exit latch_led_exit(void) ++{ ++ platform_driver_unregister(&latch_led_driver); ++} ++ ++module_init(latch_led_init); ++module_exit(latch_led_exit); ++ ++MODULE_AUTHOR("Chris Lang <clang@gateworks.com>"); ++MODULE_DESCRIPTION("Latch LED driver"); +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunf + obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o + obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o + obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o ++obj-$(CONFIG_LEDS_LATCH) += leds-latch.o + obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o + obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o + obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -210,4 +210,18 @@ struct gpio_led_platform_data { + struct platform_device *gpio_led_register_device( + int id, const struct gpio_led_platform_data *pdata); + ++/* For the leds-latch driver */ ++struct latch_led { ++ const char *name; ++ char *default_trigger; ++ unsigned bit; ++}; ++ ++struct latch_led_platform_data { ++ int num_leds; ++ u32 mem; ++ struct latch_led *leds; ++ void (*set_led)(u8 bit, enum led_brightness value); ++}; ++ + #endif /* __LINUX_LEDS_H_INCLUDED */ diff --git a/target/linux/ixp4xx/patches-3.3/300-avila_fetch_mac.patch b/target/linux/ixp4xx/patches-3.3/300-avila_fetch_mac.patch new file mode 100644 index 0000000000..8cbd38d4e7 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/300-avila_fetch_mac.patch @@ -0,0 +1,242 @@ +--- a/arch/arm/mach-ixp4xx/avila-setup.c ++++ b/arch/arm/mach-ixp4xx/avila-setup.c +@@ -14,9 +14,14 @@ + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/device.h> ++#include <linux/if_ether.h> ++#include <linux/socket.h> ++#include <linux/netdevice.h> + #include <linux/serial.h> + #include <linux/tty.h> + #include <linux/serial_8250.h> ++#include <linux/i2c.h> ++#include <linux/i2c/at24.h> + #include <linux/i2c-gpio.h> + #include <asm/types.h> + #include <asm/setup.h> +@@ -30,6 +35,13 @@ + #define AVILA_SDA_PIN 7 + #define AVILA_SCL_PIN 6 + ++struct avila_board_info { ++ unsigned char *model; ++ void (*setup)(void); ++}; ++ ++static struct avila_board_info *avila_info __initdata; ++ + static struct flash_platform_data avila_flash_data = { + .map_name = "cfi_probe", + .width = 2, +@@ -133,16 +145,181 @@ static struct platform_device avila_pata + .resource = avila_pata_resources, + }; + ++/* Built-in 10/100 Ethernet MAC interfaces */ ++static struct eth_plat_info avila_npeb_data = { ++ .phy = 0, ++ .rxq = 3, ++ .txreadyq = 20, ++}; ++ ++static struct eth_plat_info avila_npec_data = { ++ .phy = 1, ++ .rxq = 4, ++ .txreadyq = 21, ++}; ++ ++static struct platform_device avila_npeb_device = { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = &avila_npeb_data, ++}; ++ ++static struct platform_device avila_npec_device = { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = &avila_npec_data, ++}; ++ + static struct platform_device *avila_devices[] __initdata = { + &avila_i2c_gpio, + &avila_flash, + &avila_uart + }; + ++static void __init avila_gw23xx_setup(void) ++{ ++ platform_device_register(&avila_npeb_device); ++ platform_device_register(&avila_npec_device); ++} ++ ++static void __init avila_gw2342_setup(void) ++{ ++ platform_device_register(&avila_npeb_device); ++ platform_device_register(&avila_npec_device); ++} ++ ++static void __init avila_gw2345_setup(void) ++{ ++ avila_npeb_data.phy = IXP4XX_ETH_PHY_MAX_ADDR; ++ avila_npeb_data.phy_mask = 0x1e; /* ports 1-4 of the KS8995 switch */ ++ platform_device_register(&avila_npeb_device); ++ ++ avila_npec_data.phy = 5; /* port 5 of the KS8995 switch */ ++ platform_device_register(&avila_npec_device); ++} ++ ++static void __init avila_gw2347_setup(void) ++{ ++ platform_device_register(&avila_npeb_device); ++} ++ ++static void __init avila_gw2348_setup(void) ++{ ++ platform_device_register(&avila_npeb_device); ++ platform_device_register(&avila_npec_device); ++} ++ ++static void __init avila_gw2353_setup(void) ++{ ++ platform_device_register(&avila_npeb_device); ++} ++ ++static void __init avila_gw2355_setup(void) ++{ ++ avila_npeb_data.phy = IXP4XX_ETH_PHY_MAX_ADDR; ++ avila_npeb_data.phy_mask = 0x1e; /* ports 1-4 of the KS8995 switch */ ++ platform_device_register(&avila_npeb_device); ++ ++ avila_npec_data.phy = 16; ++ platform_device_register(&avila_npec_device); ++} ++ ++static void __init avila_gw2357_setup(void) ++{ ++ platform_device_register(&avila_npeb_device); ++} ++ ++static struct avila_board_info avila_boards[] __initdata = { ++ { ++ .model = "GW2342", ++ .setup = avila_gw2342_setup, ++ }, { ++ .model = "GW2345", ++ .setup = avila_gw2345_setup, ++ }, { ++ .model = "GW2347", ++ .setup = avila_gw2347_setup, ++ }, { ++ .model = "GW2348", ++ .setup = avila_gw2348_setup, ++ }, { ++ .model = "GW2353", ++ .setup = avila_gw2353_setup, ++ }, { ++ .model = "GW2355", ++ .setup = avila_gw2355_setup, ++ }, { ++ .model = "GW2357", ++ .setup = avila_gw2357_setup, ++ } ++}; ++ ++static struct avila_board_info * __init avila_find_board_info(char *model) ++{ ++ int i; ++ model[6] = '\0'; ++ ++ for (i = 0; i < ARRAY_SIZE(avila_boards); i++) { ++ struct avila_board_info *info = &avila_boards[i]; ++ if (strcmp(info->model, model) == 0) ++ return info; ++ } ++ ++ return NULL; ++} ++ ++static struct memory_accessor *at24_mem_acc; ++ ++static void at24_setup(struct memory_accessor *mem_acc, void *context) ++{ ++ char mac_addr[ETH_ALEN]; ++ char model[7]; ++ ++ at24_mem_acc = mem_acc; ++ ++ /* Read MAC addresses */ ++ if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x0, 6) == 6) { ++ memcpy(&avila_npeb_data.hwaddr, mac_addr, ETH_ALEN); ++ } ++ if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x6, 6) == 6) { ++ memcpy(&avila_npec_data.hwaddr, mac_addr, ETH_ALEN); ++ } ++ ++ /* Read the first 6 bytes of the model number */ ++ if (at24_mem_acc->read(at24_mem_acc, model, 0x20, 6) == 6) { ++ avila_info = avila_find_board_info(model); ++ } ++ ++} ++ ++static struct at24_platform_data avila_eeprom_info = { ++ .byte_len = 1024, ++ .page_size = 16, ++ .flags = AT24_FLAG_READONLY, ++ .setup = at24_setup, ++}; ++ ++static struct i2c_board_info __initdata avila_i2c_board_info[] = { ++ { ++ I2C_BOARD_INFO("ds1672", 0x68), ++ }, ++ { ++ I2C_BOARD_INFO("ad7418", 0x28), ++ }, ++ { ++ I2C_BOARD_INFO("24c08", 0x51), ++ .platform_data = &avila_eeprom_info ++ }, ++}; ++ + static void __init avila_init(void) + { + ixp4xx_sys_init(); + ++ /* ++ * These devices are present on all Avila models and don't need any ++ * model specific setup. ++ */ + avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); + avila_flash_resource.end = + IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; +@@ -160,7 +337,28 @@ static void __init avila_init(void) + + platform_device_register(&avila_pata); + ++ i2c_register_board_info(0, avila_i2c_board_info, ++ ARRAY_SIZE(avila_i2c_board_info)); ++} ++ ++static int __init avila_model_setup(void) ++{ ++ if (!machine_is_avila()) ++ return 0; ++ ++ if (avila_info) { ++ printk(KERN_DEBUG "Running on Gateworks Avila %s\n", ++ avila_info->model); ++ avila_info->setup(); ++ } else { ++ printk(KERN_INFO "Unknown/missing Avila model number" ++ " -- defaults will be used\n"); ++ avila_gw23xx_setup(); ++ } ++ ++ return 0; + } ++late_initcall(avila_model_setup); + + MACHINE_START(AVILA, "Gateworks Avila Network Platform") + /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */ diff --git a/target/linux/ixp4xx/patches-3.3/301-avila_led.patch b/target/linux/ixp4xx/patches-3.3/301-avila_led.patch new file mode 100644 index 0000000000..9acf3fda68 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/301-avila_led.patch @@ -0,0 +1,161 @@ +--- a/arch/arm/mach-ixp4xx/avila-setup.c ++++ b/arch/arm/mach-ixp4xx/avila-setup.c +@@ -22,6 +22,7 @@ + #include <linux/serial_8250.h> + #include <linux/i2c.h> + #include <linux/i2c/at24.h> ++#include <linux/leds.h> + #include <linux/i2c-gpio.h> + #include <asm/types.h> + #include <asm/setup.h> +@@ -170,6 +171,72 @@ static struct platform_device avila_npec + .dev.platform_data = &avila_npec_data, + }; + ++static struct gpio_led avila_gpio_leds[] = { ++ { ++ .name = "user", /* green led */ ++ .gpio = AVILA_GW23XX_LED_USER_GPIO, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led_platform_data avila_gpio_leds_data = { ++ .num_leds = 1, ++ .leds = avila_gpio_leds, ++}; ++ ++static struct platform_device avila_gpio_leds_device = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev.platform_data = &avila_gpio_leds_data, ++}; ++ ++static struct latch_led avila_latch_leds[] = { ++ { ++ .name = "led0", /* green led */ ++ .bit = 0, ++ }, ++ { ++ .name = "led1", /* green led */ ++ .bit = 1, ++ }, ++ { ++ .name = "led2", /* green led */ ++ .bit = 2, ++ }, ++ { ++ .name = "led3", /* green led */ ++ .bit = 3, ++ }, ++ { ++ .name = "led4", /* green led */ ++ .bit = 4, ++ }, ++ { ++ .name = "led5", /* green led */ ++ .bit = 5, ++ }, ++ { ++ .name = "led6", /* green led */ ++ .bit = 6, ++ }, ++ { ++ .name = "led7", /* green led */ ++ .bit = 7, ++ } ++}; ++ ++static struct latch_led_platform_data avila_latch_leds_data = { ++ .num_leds = 8, ++ .leds = avila_latch_leds, ++ .mem = 0x51000000, ++}; ++ ++static struct platform_device avila_latch_leds_device = { ++ .name = "leds-latch", ++ .id = -1, ++ .dev.platform_data = &avila_latch_leds_data, ++}; ++ + static struct platform_device *avila_devices[] __initdata = { + &avila_i2c_gpio, + &avila_flash, +@@ -180,12 +247,16 @@ static void __init avila_gw23xx_setup(vo + { + platform_device_register(&avila_npeb_device); + platform_device_register(&avila_npec_device); ++ ++ platform_device_register(&avila_gpio_leds_device); + } + + static void __init avila_gw2342_setup(void) + { + platform_device_register(&avila_npeb_device); + platform_device_register(&avila_npec_device); ++ ++ platform_device_register(&avila_gpio_leds_device); + } + + static void __init avila_gw2345_setup(void) +@@ -196,22 +267,30 @@ static void __init avila_gw2345_setup(vo + + avila_npec_data.phy = 5; /* port 5 of the KS8995 switch */ + platform_device_register(&avila_npec_device); ++ ++ platform_device_register(&avila_gpio_leds_device); + } + + static void __init avila_gw2347_setup(void) + { + platform_device_register(&avila_npeb_device); ++ ++ avila_gpio_leds[0].gpio = AVILA_GW23X7_LED_USER_GPIO; ++ platform_device_register(&avila_gpio_leds_device); + } + + static void __init avila_gw2348_setup(void) + { + platform_device_register(&avila_npeb_device); + platform_device_register(&avila_npec_device); ++ ++ platform_device_register(&avila_gpio_leds_device); + } + + static void __init avila_gw2353_setup(void) + { + platform_device_register(&avila_npeb_device); ++ platform_device_register(&avila_gpio_leds_device); + } + + static void __init avila_gw2355_setup(void) +@@ -222,11 +301,29 @@ static void __init avila_gw2355_setup(vo + + avila_npec_data.phy = 16; + platform_device_register(&avila_npec_device); ++ ++ platform_device_register(&avila_gpio_leds_device); ++ ++ *IXP4XX_EXP_CS4 |= 0xbfff3c03; ++ avila_latch_leds[0].name = "RXD"; ++ avila_latch_leds[1].name = "TXD"; ++ avila_latch_leds[2].name = "POL"; ++ avila_latch_leds[3].name = "LNK"; ++ avila_latch_leds[4].name = "ERR"; ++ avila_latch_leds_data.num_leds = 5; ++ avila_latch_leds_data.mem = 0x54000000; ++ platform_device_register(&avila_latch_leds_device); + } + + static void __init avila_gw2357_setup(void) + { + platform_device_register(&avila_npeb_device); ++ ++ avila_gpio_leds[0].gpio = AVILA_GW23X7_LED_USER_GPIO; ++ platform_device_register(&avila_gpio_leds_device); ++ ++ *IXP4XX_EXP_CS1 |= 0xbfff3c03; ++ platform_device_register(&avila_latch_leds_device); + } + + static struct avila_board_info avila_boards[] __initdata = { diff --git a/target/linux/ixp4xx/patches-3.3/302-avila_gpio_device.patch b/target/linux/ixp4xx/patches-3.3/302-avila_gpio_device.patch new file mode 100644 index 0000000000..a45d432efb --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/302-avila_gpio_device.patch @@ -0,0 +1,16 @@ +--- a/arch/arm/mach-ixp4xx/avila-setup.c ++++ b/arch/arm/mach-ixp4xx/avila-setup.c +@@ -36,6 +36,13 @@ + #define AVILA_SDA_PIN 7 + #define AVILA_SCL_PIN 6 + ++/* User LEDs */ ++#define AVILA_GW23XX_LED_USER_GPIO 3 ++#define AVILA_GW23X7_LED_USER_GPIO 4 ++ ++/* gpio mask used by platform device */ ++#define AVILA_GPIO_MASK (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9) ++ + struct avila_board_info { + unsigned char *model; + void (*setup)(void); diff --git a/target/linux/ixp4xx/patches-3.3/304-ixp4xx_eth_jumboframe.patch b/target/linux/ixp4xx/patches-3.3/304-ixp4xx_eth_jumboframe.patch new file mode 100644 index 0000000000..f215fc9628 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/304-ixp4xx_eth_jumboframe.patch @@ -0,0 +1,80 @@ +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -57,7 +57,7 @@ + + #define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS)) + #define REGS_SIZE 0x1000 +-#define MAX_MRU 1536 /* 0x600 */ ++#define MAX_MRU (14320 - ETH_HLEN - ETH_FCS_LEN) + #define RX_BUFF_SIZE ALIGN((NET_IP_ALIGN) + MAX_MRU, 4) + + #define NAPI_WEIGHT 16 +@@ -1261,6 +1261,32 @@ static void destroy_queues(struct port * + } + } + ++static int eth_do_change_mtu(struct net_device *dev, int mtu) ++{ ++ struct port *port; ++ struct msg msg; ++ /* adjust for ethernet headers */ ++ int framesize = mtu + ETH_HLEN + ETH_FCS_LEN; ++ ++ port = netdev_priv(dev); ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.cmd = NPE_SETMAXFRAMELENGTHS; ++ msg.eth_id = port->id; ++ ++ /* max rx/tx 64 byte blocks */ ++ msg.byte2 = ((framesize + 63) / 64) << 8; ++ msg.byte3 = ((framesize + 63) / 64) << 8; ++ ++ msg.byte4 = msg.byte6 = framesize >> 8; ++ msg.byte5 = msg.byte7 = framesize & 0xff; ++ ++ if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAX_FRAME_LENGTH")) ++ return -EIO; ++ ++ return 0; ++} ++ + static int eth_open(struct net_device *dev) + { + struct port *port = netdev_priv(dev); +@@ -1312,6 +1338,8 @@ static int eth_open(struct net_device *d + if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE")) + return -EIO; + ++ eth_do_change_mtu(dev, dev->mtu); ++ + if ((err = request_queues(port)) != 0) + return err; + +@@ -1451,7 +1479,26 @@ static int eth_close(struct net_device * + return 0; + } + ++static int ixp_eth_change_mtu(struct net_device *dev, int mtu) ++{ ++ int ret; ++ ++ if (mtu > MAX_MRU) ++ return -EINVAL; ++ ++ if (dev->flags & IFF_UP) { ++ ret = eth_do_change_mtu(dev, mtu); ++ if (ret < 0) ++ return ret; ++ } ++ ++ dev->mtu = mtu; ++ ++ return 0; ++} ++ + static const struct net_device_ops ixp4xx_netdev_ops = { ++ .ndo_change_mtu = ixp_eth_change_mtu, + .ndo_open = eth_open, + .ndo_stop = eth_close, + .ndo_start_xmit = eth_xmit, diff --git a/target/linux/ixp4xx/patches-3.3/310-gtwx5717_spi_bus.patch b/target/linux/ixp4xx/patches-3.3/310-gtwx5717_spi_bus.patch new file mode 100644 index 0000000000..080b96ac86 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/310-gtwx5717_spi_bus.patch @@ -0,0 +1,52 @@ +--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c ++++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c +@@ -27,6 +27,7 @@ + #include <linux/serial.h> + #include <linux/tty.h> + #include <linux/serial_8250.h> ++#include <linux/spi/spi_gpio_old.h> + #include <asm/types.h> + #include <asm/setup.h> + #include <asm/memory.h> +@@ -146,9 +147,41 @@ static struct platform_device gtwx5715_f + .resource = >wx5715_flash_resource, + }; + ++static int gtwx5715_spi_boardinfo_setup(struct spi_board_info *bi, ++ struct spi_master *master, void *data) ++{ ++ ++ strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias)); ++ ++ bi->max_speed_hz = 5000000 /* Hz */; ++ bi->bus_num = master->bus_num; ++ bi->mode = SPI_MODE_0; ++ ++ return 0; ++} ++ ++static struct spi_gpio_platform_data gtwx5715_spi_bus_data = { ++ .pin_cs = GTWX5715_KSSPI_SELECT, ++ .pin_clk = GTWX5715_KSSPI_CLOCK, ++ .pin_miso = GTWX5715_KSSPI_RXD, ++ .pin_mosi = GTWX5715_KSSPI_TXD, ++ .cs_activelow = 1, ++ .no_spi_delay = 1, ++ .boardinfo_setup = gtwx5715_spi_boardinfo_setup, ++}; ++ ++static struct platform_device gtwx5715_spi_bus = { ++ .name = "spi-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = >wx5715_spi_bus_data, ++ }, ++}; ++ + static struct platform_device *gtwx5715_devices[] __initdata = { + >wx5715_uart_device, + >wx5715_flash, ++ >wx5715_spi_bus, + }; + + static void __init gtwx5715_init(void) diff --git a/target/linux/ixp4xx/patches-3.3/311-gtwx5717_mac_plat_info.patch b/target/linux/ixp4xx/patches-3.3/311-gtwx5717_mac_plat_info.patch new file mode 100644 index 0000000000..706eed22ad --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/311-gtwx5717_mac_plat_info.patch @@ -0,0 +1,40 @@ +--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c ++++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c +@@ -178,10 +178,37 @@ static struct platform_device gtwx5715_s + }, + }; + ++static struct eth_plat_info gtwx5715_npeb_data = { ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0x1e, /* ports 1-4 of the KS8995 switch */ ++ .rxq = 3, ++ .txreadyq = 20, ++}; ++ ++static struct eth_plat_info gtwx5715_npec_data = { ++ .phy = 5, /* port 5 of the KS8995 switch */ ++ .rxq = 4, ++ .txreadyq = 21, ++}; ++ ++static struct platform_device gtwx5715_npeb_device = { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = >wx5715_npeb_data, ++}; ++ ++static struct platform_device gtwx5715_npec_device = { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = >wx5715_npec_data, ++}; ++ + static struct platform_device *gtwx5715_devices[] __initdata = { + >wx5715_uart_device, + >wx5715_flash, + >wx5715_spi_bus, ++ >wx5715_npeb_device, ++ >wx5715_npec_device, + }; + + static void __init gtwx5715_init(void) diff --git a/target/linux/ixp4xx/patches-3.3/312-ixp4xx_pata_optimization.patch b/target/linux/ixp4xx/patches-3.3/312-ixp4xx_pata_optimization.patch new file mode 100644 index 0000000000..2d3b6092cb --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/312-ixp4xx_pata_optimization.patch @@ -0,0 +1,137 @@ +--- a/drivers/ata/pata_ixp4xx_cf.c ++++ b/drivers/ata/pata_ixp4xx_cf.c +@@ -24,16 +24,58 @@ + #include <scsi/scsi_host.h> + + #define DRV_NAME "pata_ixp4xx_cf" +-#define DRV_VERSION "0.2" ++#define DRV_VERSION "0.3" + + static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) + { ++ struct ixp4xx_pata_data *data = link->ap->host->dev->platform_data; ++ unsigned int pio_mask; + struct ata_device *dev; + + ata_for_each_dev(dev, link, ENABLED) { +- ata_dev_info(dev, "configured for PIO0\n"); +- dev->pio_mode = XFER_PIO_0; +- dev->xfer_mode = XFER_PIO_0; ++ if (dev->id[ATA_ID_FIELD_VALID] & (1 << 1)) { ++ pio_mask = dev->id[ATA_ID_PIO_MODES] & 0x03; ++ if (pio_mask & (1 << 1)) { ++ pio_mask = 4; ++ } else { ++ pio_mask = 3; ++ } ++ } else { ++ pio_mask = (dev->id[ATA_ID_OLD_PIO_MODES] >> 8); ++ } ++ ++ switch (pio_mask){ ++ case 0: ++ ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); ++ dev->pio_mode = XFER_PIO_0; ++ dev->xfer_mode = XFER_PIO_0; ++ *data->cs0_cfg = 0x8a473c03; ++ break; ++ case 1: ++ ata_dev_printk(dev, KERN_INFO, "configured for PIO1\n"); ++ dev->pio_mode = XFER_PIO_1; ++ dev->xfer_mode = XFER_PIO_1; ++ *data->cs0_cfg = 0x86433c03; ++ break; ++ case 2: ++ ata_dev_printk(dev, KERN_INFO, "configured for PIO2\n"); ++ dev->pio_mode = XFER_PIO_2; ++ dev->xfer_mode = XFER_PIO_2; ++ *data->cs0_cfg = 0x82413c03; ++ break; ++ case 3: ++ ata_dev_printk(dev, KERN_INFO, "configured for PIO3\n"); ++ dev->pio_mode = XFER_PIO_3; ++ dev->xfer_mode = XFER_PIO_3; ++ *data->cs0_cfg = 0x80823c03; ++ break; ++ case 4: ++ ata_dev_printk(dev, KERN_INFO, "configured for PIO4\n"); ++ dev->pio_mode = XFER_PIO_4; ++ dev->xfer_mode = XFER_PIO_4; ++ *data->cs0_cfg = 0x80403c03; ++ break; ++ } + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + } +@@ -46,6 +88,7 @@ static unsigned int ixp4xx_mmio_data_xfe + unsigned int i; + unsigned int words = buflen >> 1; + u16 *buf16 = (u16 *) buf; ++ unsigned int pio_mask; + struct ata_port *ap = dev->link->ap; + void __iomem *mmio = ap->ioaddr.data_addr; + struct ixp4xx_pata_data *data = ap->host->dev->platform_data; +@@ -53,8 +96,34 @@ static unsigned int ixp4xx_mmio_data_xfe + /* set the expansion bus in 16bit mode and restore + * 8 bit mode after the transaction. + */ +- *data->cs0_cfg &= ~(0x01); +- udelay(100); ++ if (dev->id[ATA_ID_FIELD_VALID] & (1 << 1)){ ++ pio_mask = dev->id[ATA_ID_PIO_MODES] & 0x03; ++ if (pio_mask & (1 << 1)){ ++ pio_mask = 4; ++ }else{ ++ pio_mask = 3; ++ } ++ }else{ ++ pio_mask = (dev->id[ATA_ID_OLD_PIO_MODES] >> 8); ++ } ++ switch (pio_mask){ ++ case 0: ++ *data->cs0_cfg = 0xa9643c42; ++ break; ++ case 1: ++ *data->cs0_cfg = 0x85033c42; ++ break; ++ case 2: ++ *data->cs0_cfg = 0x80b23c42; ++ break; ++ case 3: ++ *data->cs0_cfg = 0x80823c42; ++ break; ++ case 4: ++ *data->cs0_cfg = 0x80403c42; ++ break; ++ } ++ udelay(5); + + /* Transfer multiple of 2 bytes */ + if (rw == READ) +@@ -79,8 +148,24 @@ static unsigned int ixp4xx_mmio_data_xfe + words++; + } + +- udelay(100); +- *data->cs0_cfg |= 0x01; ++ udelay(5); ++ switch (pio_mask){ ++ case 0: ++ *data->cs0_cfg = 0x8a473c03; ++ break; ++ case 1: ++ *data->cs0_cfg = 0x86433c03; ++ break; ++ case 2: ++ *data->cs0_cfg = 0x82413c03; ++ break; ++ case 3: ++ *data->cs0_cfg = 0x80823c03; ++ break; ++ case 4: ++ *data->cs0_cfg = 0x80403c03; ++ break; ++ } + + return words << 1; + } diff --git a/target/linux/ixp4xx/patches-3.3/402-ixp4xx_gpiolib.patch b/target/linux/ixp4xx/patches-3.3/402-ixp4xx_gpiolib.patch new file mode 100644 index 0000000000..449755d165 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/402-ixp4xx_gpiolib.patch @@ -0,0 +1,134 @@ +--- a/arch/arm/mach-ixp4xx/common.c ++++ b/arch/arm/mach-ixp4xx/common.c +@@ -36,6 +36,7 @@ + #include <asm/page.h> + #include <asm/irq.h> + #include <asm/sched_clock.h> ++#include <asm/gpio.h> + + #include <asm/mach/map.h> + #include <asm/mach/irq.h> +@@ -375,12 +376,50 @@ static struct platform_device *ixp46x_de + unsigned long ixp4xx_exp_bus_size; + EXPORT_SYMBOL(ixp4xx_exp_bus_size); + ++static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) ++{ ++ gpio_line_config(gpio, IXP4XX_GPIO_IN); ++ return 0; ++} ++ ++static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) ++{ ++ gpio_line_set(gpio, level); ++ gpio_line_config(gpio, IXP4XX_GPIO_OUT); ++ return 0; ++} ++ ++static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) ++{ ++ int value; ++ ++ gpio_line_get(gpio, &value); ++ return value; ++} ++ ++static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) ++{ ++ gpio_line_set(gpio, value); ++} ++ ++static struct gpio_chip ixp4xx_gpio_chip = { ++ .label = "IXP4XX_GPIO_CHIP", ++ .direction_input = ixp4xx_gpio_direction_input, ++ .direction_output = ixp4xx_gpio_direction_output, ++ .get = ixp4xx_gpio_get_value, ++ .set = ixp4xx_gpio_set_value, ++ .base = 0, ++ .ngpio = 16, ++}; ++ + void __init ixp4xx_sys_init(void) + { + ixp4xx_exp_bus_size = SZ_16M; + + platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); + ++ gpiochip_add(&ixp4xx_gpio_chip); ++ + if (cpu_is_ixp46x()) { + int region; + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -529,7 +529,7 @@ config ARCH_IXP4XX + depends on MMU + select CLKSRC_MMIO + select CPU_XSCALE +- select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB + select GENERIC_CLOCKEVENTS + select HAVE_SCHED_CLOCK + select MIGHT_HAVE_PCI +--- a/arch/arm/mach-ixp4xx/include/mach/gpio.h ++++ b/arch/arm/mach-ixp4xx/include/mach/gpio.h +@@ -27,38 +27,19 @@ + + #include <linux/kernel.h> + #include <mach/hardware.h> ++#include <asm-generic/gpio.h> /* cansleep wrappers */ + + #define __ARM_GPIOLIB_COMPLEX + +-static inline int gpio_request(unsigned gpio, const char *label) +-{ +- return 0; +-} +- +-static inline void gpio_free(unsigned gpio) +-{ +- might_sleep(); +- +- return; +-} +- +-static inline int gpio_direction_input(unsigned gpio) +-{ +- gpio_line_config(gpio, IXP4XX_GPIO_IN); +- return 0; +-} +- +-static inline int gpio_direction_output(unsigned gpio, int level) +-{ +- gpio_line_set(gpio, level); +- gpio_line_config(gpio, IXP4XX_GPIO_OUT); +- return 0; +-} ++#define NR_BUILTIN_GPIO 16 + + static inline int gpio_get_value(unsigned gpio) + { + int value; + ++ if (gpio >= NR_BUILTIN_GPIO) ++ return __gpio_get_value(gpio); ++ + gpio_line_get(gpio, &value); + + return value; +@@ -66,10 +47,13 @@ static inline int gpio_get_value(unsigne + + static inline void gpio_set_value(unsigned gpio, int value) + { +- gpio_line_set(gpio, value); ++ if (gpio >= NR_BUILTIN_GPIO) ++ __gpio_set_value(gpio, value); ++ else ++ gpio_line_set(gpio, value); + } + +-#include <asm-generic/gpio.h> /* cansleep wrappers */ ++#define gpio_cansleep __gpio_cansleep + + extern int gpio_to_irq(int gpio); + #define gpio_to_irq gpio_to_irq diff --git a/target/linux/ixp4xx/patches-3.3/500-usr8200_support.patch b/target/linux/ixp4xx/patches-3.3/500-usr8200_support.patch new file mode 100644 index 0000000000..8ce1b41293 --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/500-usr8200_support.patch @@ -0,0 +1,344 @@ +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -97,6 +97,14 @@ config MACH_SIDEWINDER + Engineering Sidewinder board. For more information on this + platform, see http://www.adiengineering.com + ++config MACH_USR8200 ++ bool "USRobotics USR8200" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support the USRobotics ++ USR8200 router board. For more information on this platform, see ++ http://openwrt.org ++ + config MACH_COMPEX + bool "Compex WP18 / NP18A" + select PCI +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -27,6 +27,7 @@ obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt + obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o + obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o + obj-pci-$(CONFIG_MACH_MI424WR) += mi424wr-pci.o ++obj-pci-$(CONFIG_MACH_USR8200) += usr8200-pci.o + + obj-y += common.o + +@@ -55,6 +56,7 @@ obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv + obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o + obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o + obj-$(CONFIG_MACH_MI424WR) += mi424wr-setup.o ++obj-$(CONFIG_MACH_USR8200) += usr8200-setup.o + + obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o + obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/usr8200-pci.c +@@ -0,0 +1,78 @@ ++/* ++ * arch/arch/mach-ixp4xx/usr8200-pci.c ++ * ++ * PCI setup routines for USRobotics USR8200 ++ * ++ * Copyright (C) 2008 Peter Denison <openwrt@marshadder.org> ++ * ++ * based on pronghorn-pci.c ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Peter Denison <openwrt@marshadder.org> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++ ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++ ++#include <asm/mach/pci.h> ++ ++void __init usr8200_pci_preinit(void) ++{ ++ irq_set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init usr8200_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 14) ++ return IRQ_IXP4XX_GPIO7; ++ else if (slot == 15) ++ return IRQ_IXP4XX_GPIO8; ++ else if (slot == 16) { ++ if (pin == 1) ++ return IRQ_IXP4XX_GPIO11; ++ else if (pin == 2) ++ return IRQ_IXP4XX_GPIO10; ++ else if (pin == 3) ++ return IRQ_IXP4XX_GPIO9; ++ else ++ return -1; ++ } else ++ return -1; ++} ++ ++struct hw_pci usr8200_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = usr8200_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = usr8200_map_irq, ++}; ++ ++int __init usr8200_pci_init(void) ++{ ++ if (machine_is_usr8200()) ++ pci_common_init(&usr8200_pci); ++ return 0; ++} ++ ++subsys_initcall(usr8200_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/usr8200-setup.c +@@ -0,0 +1,213 @@ ++/* ++ * arch/arm/mach-ixp4xx/usr8200-setup.c ++ * ++ * Board setup for the USRobotics USR8200 ++ * ++ * Copyright (C) 2008 Peter Denison <openwrt@marshadder.org> ++ * ++ * based on pronghorn-setup.c: ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * based on coyote-setup.c: ++ * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * ++ * Author: Peter Denison <openwrt@marshadder.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++#include <linux/memory.h> ++#include <linux/i2c-gpio.h> ++#include <linux/leds.h> ++ ++#include <asm/setup.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++static struct flash_platform_data usr8200_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource usr8200_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device usr8200_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &usr8200_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &usr8200_flash_resource, ++}; ++ ++static struct resource usr8200_uart_resources [] = { ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ } ++}; ++ ++static struct plat_serial8250_port usr8200_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device usr8200_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = usr8200_uart_data, ++ }, ++ .num_resources = 2, ++ .resource = usr8200_uart_resources, ++}; ++ ++static struct gpio_led usr8200_led_pin[] = { ++ { ++ .name = "usr8200:usb1", ++ .gpio = 0, ++ .active_low = 1, ++ }, ++ { ++ .name = "usr8200:usb2", ++ .gpio = 1, ++ .active_low = 1, ++ }, ++ { ++ .name = "usr8200:ieee1394", ++ .gpio = 2, ++ .active_low = 1, ++ }, ++ { ++ .name = "usr8200:internal", ++ .gpio = 3, ++ .active_low = 1, ++ }, ++ { ++ .name = "usr8200:power", ++ .gpio = 14, ++ } ++}; ++ ++static struct gpio_led_platform_data usr8200_led_data = { ++ .num_leds = ARRAY_SIZE(usr8200_led_pin), ++ .leds = usr8200_led_pin, ++}; ++ ++static struct platform_device usr8200_led = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev.platform_data = &usr8200_led_data, ++}; ++ ++static struct eth_plat_info usr8200_plat_eth[] = { ++ { /* NPEC - LAN with Marvell 88E6060 switch */ ++ .phy = IXP4XX_ETH_PHY_MAX_ADDR, ++ .phy_mask = 0x0F0000, ++ .rxq = 4, ++ .txreadyq = 21, ++ }, { /* NPEB - WAN */ ++ .phy = 9, ++ .rxq = 3, ++ .txreadyq = 20, ++ } ++}; ++ ++static struct platform_device usr8200_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = usr8200_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = usr8200_plat_eth + 1, ++ } ++}; ++ ++static struct resource usr8200_rtc_resources = { ++ .flags = IORESOURCE_MEM ++}; ++ ++static struct platform_device usr8200_rtc = { ++ .name = "rtc7301", ++ .id = 0, ++ .num_resources = 1, ++ .resource = &usr8200_rtc_resources, ++}; ++ ++static struct platform_device *usr8200_devices[] __initdata = { ++ &usr8200_flash, ++ &usr8200_uart, ++ &usr8200_led, ++ &usr8200_eth[0], ++ &usr8200_eth[1], ++ &usr8200_rtc, ++}; ++ ++static void __init usr8200_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ usr8200_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ usr8200_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_16M - 1; ++ ++ usr8200_rtc_resources.start = IXP4XX_EXP_BUS_BASE(2); ++ usr8200_rtc_resources.end = IXP4XX_EXP_BUS_BASE(2) + 0x01ff; ++ ++ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; ++ *IXP4XX_EXP_CS2 = 0x3fff000 | IXP4XX_EXP_BUS_SIZE(0) | IXP4XX_EXP_BUS_WR_EN | ++ IXP4XX_EXP_BUS_CS_EN | IXP4XX_EXP_BUS_BYTE_EN; ++ *IXP4XX_GPIO_GPCLKR = 0x01100000; ++ ++ /* configure button as input */ ++ gpio_line_config(12, IXP4XX_GPIO_IN); ++ ++ platform_add_devices(usr8200_devices, ARRAY_SIZE(usr8200_devices)); ++} ++ ++MACHINE_START(USR8200, "USRobotics USR8200") ++ /* Maintainer: Peter Denison <openwrt@marshadder.org> */ ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = usr8200_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END +--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h ++++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h +@@ -44,7 +44,8 @@ static __inline__ void __arch_decomp_set + machine_is_gateway7001() || machine_is_wg302v2() || + machine_is_devixp() || machine_is_miccpt() || machine_is_mic256() || + machine_is_pronghorn() || machine_is_pronghorn_metro() || +- machine_is_wrt300nv2() || machine_is_tw5334()) ++ machine_is_wrt300nv2() || machine_is_tw5334() || ++ machine_is_usr8200()) + uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; + else + uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-3.3/520-tw2662_support.patch b/target/linux/ixp4xx/patches-3.3/520-tw2662_support.patch new file mode 100644 index 0000000000..edce4771bf --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/520-tw2662_support.patch @@ -0,0 +1,333 @@ +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -180,6 +180,15 @@ config ARCH_PRPMC1100 + PrPCM1100 Processor Mezanine Module. For more information on + this platform, see <file:Documentation/arm/IXP4xx>. + ++config MACH_TW2662 ++ bool "Titan Wireless TW-266-2" ++ select PCI ++ help ++ Say 'Y' here if you want your kernel to support the Titan ++ Wireless TW266-2. For more information on this platform, ++ see http://openwrt.org ++ ++ + config MACH_TW5334 + bool "Titan Wireless TW-533-4" + select PCI +--- a/arch/arm/mach-ixp4xx/Makefile ++++ b/arch/arm/mach-ixp4xx/Makefile +@@ -25,6 +25,7 @@ obj-pci-$(CONFIG_MACH_SIDEWINDER) += sid + obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o + obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o + obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o ++obj-pci-$(CONFIG_MACH_TW2662) += tw2662-pci.o + obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o + obj-pci-$(CONFIG_MACH_MI424WR) += mi424wr-pci.o + obj-pci-$(CONFIG_MACH_USR8200) += usr8200-pci.o +@@ -54,6 +55,7 @@ obj-$(CONFIG_MACH_SIDEWINDER) += sidewin + obj-$(CONFIG_MACH_COMPEX) += compex-setup.o + obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o + obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o ++obj-$(CONFIG_MACH_TW2662) += tw2662-setup.o + obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o + obj-$(CONFIG_MACH_MI424WR) += mi424wr-setup.o + obj-$(CONFIG_MACH_USR8200) += usr8200-setup.o +--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h ++++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h +@@ -45,7 +45,7 @@ static __inline__ void __arch_decomp_set + machine_is_devixp() || machine_is_miccpt() || machine_is_mic256() || + machine_is_pronghorn() || machine_is_pronghorn_metro() || + machine_is_wrt300nv2() || machine_is_tw5334() || +- machine_is_usr8200()) ++ machine_is_usr8200() || machine_is_tw2662()) + uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; + else + uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/tw2662-pci.c +@@ -0,0 +1,68 @@ ++/* ++ * arch/arm/mach-ixp4xx/tw2662-pci.c ++ * ++ * PCI setup routines for Tiran Wireless TW-266-2 platform ++ * ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * Copyright (C) 2010 Alexandros C. Couloumbis <alex@ozo.com> ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * Maintainer: Deepak Saxena <dsaxena@mvista.com> ++ * Maintainer: Alexandros C. Couloumbis <alex@ozo.com> ++ * ++ * 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 <linux/kernel.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/irq.h> ++#include <asm/mach-types.h> ++#include <mach/hardware.h> ++#include <asm/irq.h> ++#include <asm/mach/pci.h> ++ ++#define SLOT0_DEVID 1 ++#define SLOT1_DEVID 3 ++ ++/* PCI controller GPIO to IRQ pin mappings */ ++#define SLOT0_INTA 11 ++#define SLOT1_INTA 9 ++ ++void __init tw2662_pci_preinit(void) ++{ ++ irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW); ++ irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW); ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init tw2662_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == SLOT0_DEVID) ++ return IXP4XX_GPIO_IRQ(SLOT0_INTA); ++ else if (slot == SLOT1_DEVID) ++ return IXP4XX_GPIO_IRQ(SLOT1_INTA); ++ else return -1; ++} ++ ++struct hw_pci tw2662_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = tw2662_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = tw2662_map_irq, ++}; ++ ++int __init tw2662_pci_init(void) ++{ ++ if (machine_is_tw2662()) ++ pci_common_init(&tw2662_pci); ++ return 0; ++} ++ ++subsys_initcall(tw2662_pci_init); +--- /dev/null ++++ b/arch/arm/mach-ixp4xx/tw2662-setup.c +@@ -0,0 +1,212 @@ ++/* ++ * arch/arm/mach-ixp4xx/tw2662-setup.c ++ * ++ * Titan Wireless TW-266-2 ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2010 Alexandros C. Couloumbis <alex@ozo.com> ++ * ++ * based on ap1000-setup.c: ++ * Author: Imre Kaloz <Kaloz@openwrt.org> ++ */ ++ ++#include <linux/if_ether.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/serial.h> ++#include <linux/tty.h> ++#include <linux/serial_8250.h> ++#include <linux/slab.h> ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/platform_device.h> ++ ++#include <asm/io.h> ++#include <asm/types.h> ++#include <asm/setup.h> ++#include <asm/memory.h> ++#include <mach/hardware.h> ++#include <asm/mach-types.h> ++#include <asm/irq.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++ ++/* gpio mask used by platform device */ ++#define TW2662_GPIO_MASK (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) ++ ++static struct flash_platform_data tw2662_flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++}; ++ ++static struct resource tw2662_flash_resource = { ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device tw2662_flash = { ++ .name = "IXP4XX-Flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &tw2662_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &tw2662_flash_resource, ++}; ++ ++static struct resource tw2662_gpio_resources[] = { ++ { ++ .name = "gpio", ++ /* FIXME: gpio mask should be model specific */ ++ .start = TW2662_GPIO_MASK, ++ .end = TW2662_GPIO_MASK, ++ .flags = 0, ++ }, ++}; ++ ++static struct platform_device tw2662_gpio = { ++ .name = "GPIODEV", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(tw2662_gpio_resources), ++ .resource = tw2662_gpio_resources, ++}; ++ ++static struct resource tw2662_uart_resources[] = { ++ { ++ .start = IXP4XX_UART1_BASE_PHYS, ++ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IXP4XX_UART2_BASE_PHYS, ++ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, ++ .flags = IORESOURCE_MEM ++ } ++}; ++ ++static struct plat_serial8250_port tw2662_uart_data[] = { ++ { ++ .mapbase = IXP4XX_UART1_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART1, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { ++ .mapbase = IXP4XX_UART2_BASE_PHYS, ++ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, ++ .irq = IRQ_IXP4XX_UART2, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ .iotype = UPIO_MEM, ++ .regshift = 2, ++ .uartclk = IXP4XX_UART_XTAL, ++ }, ++ { }, ++}; ++ ++static struct platform_device tw2662_uart = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev.platform_data = tw2662_uart_data, ++ .num_resources = 2, ++ .resource = tw2662_uart_resources ++}; ++ ++/* Built-in 10/100 Ethernet MAC interfaces */ ++static struct eth_plat_info tw2662_plat_eth[] = { ++ { ++ .phy = 3, ++ .rxq = 3, ++ .txreadyq = 20, ++ }, { ++ .phy = 1, ++ .rxq = 4, ++ .txreadyq = 21, ++ } ++}; ++ ++static struct platform_device tw2662_eth[] = { ++ { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEB, ++ .dev.platform_data = tw2662_plat_eth, ++ }, { ++ .name = "ixp4xx_eth", ++ .id = IXP4XX_ETH_NPEC, ++ .dev.platform_data = tw2662_plat_eth + 1, ++ } ++}; ++ ++ ++static struct platform_device *tw2662_devices[] __initdata = { ++ &tw2662_flash, ++ &tw2662_uart, ++ &tw2662_gpio, ++ &tw2662_eth[0], ++ &tw2662_eth[1], ++}; ++ ++static char tw2662_mem_fixup[] __initdata = "mem=64M "; ++ ++static void __init tw2662_fixup(struct tag *tags, char **cmdline, ++ struct meminfo *mi) ++{ ++ struct tag *t = tags; ++ char *p = *cmdline; ++ ++ /* Find the end of the tags table, taking note of any cmdline tag. */ ++ for (; t->hdr.size; t = tag_next(t)) { ++ if (t->hdr.tag == ATAG_CMDLINE) { ++ p = t->u.cmdline.cmdline; ++ } ++ } ++ ++ /* Overwrite the end of the table with a new cmdline tag. */ ++ t->hdr.tag = ATAG_CMDLINE; ++ t->hdr.size = (sizeof (struct tag_header) + ++ strlen(tw2662_mem_fixup) + strlen(p) + 1 + 4) >> 2; ++ strlcpy(t->u.cmdline.cmdline, tw2662_mem_fixup, COMMAND_LINE_SIZE); ++ strlcpy(t->u.cmdline.cmdline + strlen(tw2662_mem_fixup), p, ++ COMMAND_LINE_SIZE - strlen(tw2662_mem_fixup)); ++ ++ /* Terminate the table. */ ++ t = tag_next(t); ++ t->hdr.tag = ATAG_NONE; ++ t->hdr.size = 0; ++} ++ ++static void __init tw2662_init(void) ++{ ++ ixp4xx_sys_init(); ++ ++ tw2662_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ++ tw2662_flash_resource.end = ++ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; ++ ++ platform_add_devices(tw2662_devices, ARRAY_SIZE(tw2662_devices)); ++ ++ if (!(is_valid_ether_addr(tw2662_plat_eth[0].hwaddr))) ++ random_ether_addr(tw2662_plat_eth[0].hwaddr); ++ if (!(is_valid_ether_addr(tw2662_plat_eth[1].hwaddr))) { ++ memcpy(tw2662_plat_eth[1].hwaddr, tw2662_plat_eth[0].hwaddr, ETH_ALEN); ++ tw2662_plat_eth[1].hwaddr[5] = (tw2662_plat_eth[0].hwaddr[5] + 1); ++ } ++ ++} ++ ++#ifdef CONFIG_MACH_TW2662 ++MACHINE_START(TW2662, "Titan Wireless TW-266-2") ++ /* Maintainer: Alexandros C. Couloumbis <alex@ozo.com> */ ++ .fixup = tw2662_fixup, ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .atag_offset = 0x0100, ++ .init_machine = tw2662_init, ++#if defined(CONFIG_PCI) ++ .dma_zone_size = SZ_64M, ++#endif ++MACHINE_END ++#endif diff --git a/target/linux/ixp4xx/patches-3.3/600-skb_avoid_dmabounce.patch b/target/linux/ixp4xx/patches-3.3/600-skb_avoid_dmabounce.patch new file mode 100644 index 0000000000..f48c273b4a --- /dev/null +++ b/target/linux/ixp4xx/patches-3.3/600-skb_avoid_dmabounce.patch @@ -0,0 +1,24 @@ +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -176,6 +176,10 @@ struct sk_buff *__alloc_skb(unsigned int + struct sk_buff *skb; + u8 *data; + ++#ifdef CONFIG_ARCH_IXP4XX ++ gfp_mask |= GFP_DMA; ++#endif ++ + cache = fclone ? skbuff_fclone_cache : skbuff_head_cache; + + /* Get the HEAD */ +@@ -929,6 +933,10 @@ int pskb_expand_head(struct sk_buff *skb + if (skb_shared(skb)) + BUG(); + ++#ifdef CONFIG_ARCH_IXP4XX ++ gfp_mask |= GFP_DMA; ++#endif ++ + size = SKB_DATA_ALIGN(size); + + /* Check if we can avoid taking references on fragments if we own |