From cc910c6802f8fe8041d4d2b13531e5c50c6ee239 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 2 Aug 2009 13:01:18 +0000 Subject: [PATCH] [ar7] add experimental support for 2.6.30 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17097 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ar7/files/arch/mips/include/asm/ar7 | 1 + .../ar7/patches-2.6.30/100-board_support.patch | 86 ++++ target/linux/ar7/patches-2.6.30/110-flash.patch | 11 + .../linux/ar7/patches-2.6.30/120-gpio_chrdev.patch | 28 ++ target/linux/ar7/patches-2.6.30/130-vlynq.patch | 20 + .../linux/ar7/patches-2.6.30/131-vlynq_fixes.patch | 548 +++++++++++++++++++++ .../ar7/patches-2.6.30/150-cpmac_not_broken.patch | 11 + .../ar7/patches-2.6.30/500-serial_kludge.patch | 38 ++ .../ar7/patches-2.6.30/900-cpmac_multiqueue.patch | 70 +++ 9 files changed, 813 insertions(+) create mode 120000 target/linux/ar7/files/arch/mips/include/asm/ar7 create mode 100644 target/linux/ar7/patches-2.6.30/100-board_support.patch create mode 100644 target/linux/ar7/patches-2.6.30/110-flash.patch create mode 100644 target/linux/ar7/patches-2.6.30/120-gpio_chrdev.patch create mode 100644 target/linux/ar7/patches-2.6.30/130-vlynq.patch create mode 100644 target/linux/ar7/patches-2.6.30/131-vlynq_fixes.patch create mode 100644 target/linux/ar7/patches-2.6.30/150-cpmac_not_broken.patch create mode 100644 target/linux/ar7/patches-2.6.30/500-serial_kludge.patch create mode 100644 target/linux/ar7/patches-2.6.30/900-cpmac_multiqueue.patch diff --git a/target/linux/ar7/files/arch/mips/include/asm/ar7 b/target/linux/ar7/files/arch/mips/include/asm/ar7 new file mode 120000 index 0000000000..4de8fbc8bc --- /dev/null +++ b/target/linux/ar7/files/arch/mips/include/asm/ar7 @@ -0,0 +1 @@ +../../../../include/asm-mips/ar7 \ No newline at end of file diff --git a/target/linux/ar7/patches-2.6.30/100-board_support.patch b/target/linux/ar7/patches-2.6.30/100-board_support.patch new file mode 100644 index 0000000000..c3fad1653a --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/100-board_support.patch @@ -0,0 +1,86 @@ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -19,6 +19,24 @@ choice + prompt "System type" + default SGI_IP22 + ++config AR7 ++ bool "Texas Instruments AR7" ++ select BOOT_ELF32 ++ select DMA_NONCOHERENT ++ select CEVT_R4K ++ select CSRC_R4K ++ select IRQ_CPU ++ select NO_EXCEPT_FILL ++ select SWAP_IO_SPACE ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_KGDB ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select GENERIC_GPIO ++ select GENERIC_HARDIRQS_NO__DO_IRQ ++ + config MACH_ALCHEMY + bool "Alchemy processor based machines" + +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -1203,9 +1203,22 @@ void *set_except_vector(int n, void *add + + exception_handlers[n] = handler; + if (n == 0 && cpu_has_divec) { +- *(u32 *)(ebase + 0x200) = 0x08000000 | +- (0x03ffffff & (handler >> 2)); +- local_flush_icache_range(ebase + 0x200, ebase + 0x204); ++ if ((handler ^ (ebase + 4)) & 0xfc000000) { ++ /* lui k0, 0x0000 */ ++ *(u32 *)(ebase + 0x200) = 0x3c1a0000 | (handler >> 16); ++ /* ori k0, 0x0000 */ ++ *(u32 *)(ebase + 0x204) = ++ 0x375a0000 | (handler & 0xffff); ++ /* jr k0 */ ++ *(u32 *)(ebase + 0x208) = 0x03400008; ++ /* nop */ ++ *(u32 *)(ebase + 0x20C) = 0x00000000; ++ flush_icache_range(ebase + 0x200, ebase + 0x210); ++ } else { ++ *(u32 *)(ebase + 0x200) = ++ 0x08000000 | (0x03ffffff & (handler >> 2)); ++ flush_icache_range(ebase + 0x200, ebase + 0x204); ++ } + } + return (void *)old_handler; + } +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -167,6 +167,13 @@ libs-$(CONFIG_SIBYTE_CFE) += arch/mips/s + # + + # ++# Texas Instruments AR7 ++# ++core-$(CONFIG_AR7) += arch/mips/ar7/ ++cflags-$(CONFIG_AR7) += -Iinclude/asm-mips/ar7 ++load-$(CONFIG_AR7) += 0xffffffff94100000 ++ ++# + # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. + # + core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ +--- a/arch/mips/include/asm/page.h ++++ b/arch/mips/include/asm/page.h +@@ -182,8 +182,10 @@ typedef struct { unsigned long pgprot; } + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) +-#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) ++#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \ ++ PHYS_OFFSET) ++#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \ ++ PHYS_OFFSET) + + #include + #include diff --git a/target/linux/ar7/patches-2.6.30/110-flash.patch b/target/linux/ar7/patches-2.6.30/110-flash.patch new file mode 100644 index 0000000000..7311a67349 --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/110-flash.patch @@ -0,0 +1,11 @@ +--- a/drivers/mtd/maps/physmap.c ++++ b/drivers/mtd/maps/physmap.c +@@ -80,7 +80,7 @@ static const char *rom_probe_types[] = { + "map_rom", + NULL }; + #ifdef CONFIG_MTD_PARTITIONS +-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; ++static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "ar7part", NULL }; + #endif + + static int physmap_flash_probe(struct platform_device *dev) diff --git a/target/linux/ar7/patches-2.6.30/120-gpio_chrdev.patch b/target/linux/ar7/patches-2.6.30/120-gpio_chrdev.patch new file mode 100644 index 0000000000..fa61e5ccf5 --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/120-gpio_chrdev.patch @@ -0,0 +1,28 @@ +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -974,6 +974,15 @@ config MWAVE + To compile this driver as a module, choose M here: the + module will be called mwave. + ++config AR7_GPIO ++ tristate "TI AR7 GPIO Support" ++ depends on AR7 ++ help ++ Give userspace access to the GPIO pins on the Texas Instruments AR7 ++ processors. ++ ++ If compiled as a module, it will be called ar7_gpio. ++ + config SCx200_GPIO + tristate "NatSemi SCx200 GPIO Support" + depends on SCx200 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -90,6 +90,7 @@ obj-$(CONFIG_HW_RANDOM) += hw_random/ + obj-$(CONFIG_PPDEV) += ppdev.o + obj-$(CONFIG_NWBUTTON) += nwbutton.o + obj-$(CONFIG_NWFLASH) += nwflash.o ++obj-$(CONFIG_AR7_GPIO) += ar7_gpio.o + obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o + obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o + obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o diff --git a/target/linux/ar7/patches-2.6.30/130-vlynq.patch b/target/linux/ar7/patches-2.6.30/130-vlynq.patch new file mode 100644 index 0000000000..9ab3638eaa --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/130-vlynq.patch @@ -0,0 +1,20 @@ +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -100,5 +100,7 @@ source "drivers/auxdisplay/Kconfig" + + source "drivers/uio/Kconfig" + ++source "drivers/vlynq/Kconfig" ++ + source "drivers/xen/Kconfig" + endmenu +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -96,6 +96,7 @@ obj-$(CONFIG_DCA) += dca/ + obj-$(CONFIG_HID) += hid/ + obj-$(CONFIG_PPC_PS3) += ps3/ + obj-$(CONFIG_OF) += of/ ++obj-$(CONFIG_VLYNQ) += vlynq/ + obj-$(CONFIG_SSB) += ssb/ + obj-$(CONFIG_VIRTIO) += virtio/ + obj-$(CONFIG_REGULATOR) += regulator/ diff --git a/target/linux/ar7/patches-2.6.30/131-vlynq_fixes.patch b/target/linux/ar7/patches-2.6.30/131-vlynq_fixes.patch new file mode 100644 index 0000000000..f68ae4c70e --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/131-vlynq_fixes.patch @@ -0,0 +1,548 @@ +--- a/drivers/vlynq/vlynq.c 2009-05-31 20:41:57.000000000 +0200 ++++ b/drivers/vlynq/vlynq.c 2009-07-28 21:27:52.000000000 +0200 +@@ -14,6 +14,9 @@ + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ * Parts of the VLYNQ specification can be found here: ++ * http://www.ti.com/litv/pdf/sprue36a + */ + + #include +@@ -25,7 +28,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -73,15 +75,11 @@ + u32 int_device[8]; + }; + +-#define vlynq_reg_read(reg) readl(&(reg)) +-#define vlynq_reg_write(reg, val) writel(val, &(reg)) +- +-static int __vlynq_enable_device(struct vlynq_device *dev); +- +-#ifdef VLYNQ_DEBUG ++#ifdef CONFIG_VLYNQ_DEBUG + static void vlynq_dump_regs(struct vlynq_device *dev) + { + int i; ++ + printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n", + dev->local, dev->remote); + for (i = 0; i < 32; i++) { +@@ -95,20 +93,23 @@ + static void vlynq_dump_mem(u32 *base, int count) + { + int i; ++ + for (i = 0; i < (count + 3) / 4; i++) { +- if (i % 4 == 0) printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4); ++ if (i % 4 == 0) ++ printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4); + printk(KERN_DEBUG " 0x%08x", *(base + i)); + } + printk(KERN_DEBUG "\n"); + } + #endif + +-int vlynq_linked(struct vlynq_device *dev) ++/* Check the VLYNQ link status with a given device */ ++static int vlynq_linked(struct vlynq_device *dev) + { + int i; + + for (i = 0; i < 100; i++) +- if (vlynq_reg_read(dev->local->status) & VLYNQ_STATUS_LINK) ++ if (readl(&dev->local->status) & VLYNQ_STATUS_LINK) + return 1; + else + cpu_relax(); +@@ -118,17 +119,15 @@ + + static void vlynq_reset(struct vlynq_device *dev) + { +- vlynq_reg_write(dev->local->control, +- vlynq_reg_read(dev->local->control) | +- VLYNQ_CTRL_RESET); ++ writel(readl(&dev->local->control) | VLYNQ_CTRL_RESET, ++ &dev->local->control); + + /* Wait for the devices to finish resetting */ + msleep(5); + + /* Remove reset bit */ +- vlynq_reg_write(dev->local->control, +- vlynq_reg_read(dev->local->control) & +- ~VLYNQ_CTRL_RESET); ++ writel(readl(&dev->local->control) & ~VLYNQ_CTRL_RESET, ++ &dev->local->control); + + /* Give some time for the devices to settle */ + msleep(5); +@@ -142,9 +141,9 @@ + + BUG_ON(!dev); + virq = irq - dev->irq_start; +- val = vlynq_reg_read(dev->remote->int_device[virq >> 2]); ++ val = readl(&dev->remote->int_device[virq >> 2]); + val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq); +- vlynq_reg_write(dev->remote->int_device[virq >> 2], val); ++ writel(val, &dev->remote->int_device[virq >> 2]); + } + + static void vlynq_irq_mask(unsigned int irq) +@@ -155,9 +154,9 @@ + + BUG_ON(!dev); + virq = irq - dev->irq_start; +- val = vlynq_reg_read(dev->remote->int_device[virq >> 2]); ++ val = readl(&dev->remote->int_device[virq >> 2]); + val &= ~(VINT_ENABLE << VINT_OFFSET(virq)); +- vlynq_reg_write(dev->remote->int_device[virq >> 2], val); ++ writel(val, &dev->remote->int_device[virq >> 2]); + } + + static int vlynq_irq_type(unsigned int irq, unsigned int flow_type) +@@ -168,7 +167,7 @@ + + BUG_ON(!dev); + virq = irq - dev->irq_start; +- val = vlynq_reg_read(dev->remote->int_device[virq >> 2]); ++ val = readl(&dev->remote->int_device[virq >> 2]); + switch (flow_type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: +@@ -187,28 +186,30 @@ + default: + return -EINVAL; + } +- vlynq_reg_write(dev->remote->int_device[virq >> 2], val); ++ writel(val, &dev->remote->int_device[virq >> 2]); + return 0; + } + + static void vlynq_local_ack(unsigned int irq) + { + struct vlynq_device *dev = get_irq_chip_data(irq); +- u32 status = vlynq_reg_read(dev->local->status); +- if (printk_ratelimit()) +- printk(KERN_DEBUG "%s: local status: 0x%08x\n", +- dev->dev.bus_id, status); +- vlynq_reg_write(dev->local->status, status); ++ ++ u32 status = readl(&dev->local->status); ++ ++ pr_debug("%s: local status: 0x%08x\n", ++ dev_name(&dev->dev), status); ++ writel(status, &dev->local->status); + } + + static void vlynq_remote_ack(unsigned int irq) + { + struct vlynq_device *dev = get_irq_chip_data(irq); +- u32 status = vlynq_reg_read(dev->remote->status); +- if (printk_ratelimit()) +- printk(KERN_DEBUG "%s: remote status: 0x%08x\n", +- dev->dev.bus_id, status); +- vlynq_reg_write(dev->remote->status, status); ++ ++ u32 status = readl(&dev->remote->status); ++ ++ pr_debug("%s: remote status: 0x%08x\n", ++ dev_name(&dev->dev), status); ++ writel(status, &dev->remote->status); + } + + static irqreturn_t vlynq_irq(int irq, void *dev_id) +@@ -217,8 +218,8 @@ + u32 status; + int virq = 0; + +- status = vlynq_reg_read(dev->local->int_status); +- vlynq_reg_write(dev->local->int_status, status); ++ status = readl(&dev->local->int_status); ++ writel(status, &dev->local->int_status); + + if (unlikely(!status)) + spurious_interrupt(); +@@ -262,28 +263,28 @@ + if (dev->local_irq == dev->remote_irq) { + printk(KERN_ERR + "%s: local vlynq irq should be different from remote\n", +- dev->dev.bus_id); ++ dev_name(&dev->dev)); + return -EINVAL; + } + + /* Clear local and remote error bits */ +- vlynq_reg_write(dev->local->status, vlynq_reg_read(dev->local->status)); +- vlynq_reg_write(dev->remote->status, +- vlynq_reg_read(dev->remote->status)); ++ writel(readl(&dev->local->status), &dev->local->status); ++ writel(readl(&dev->remote->status), &dev->remote->status); + + /* Now setup interrupts */ + val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq); + val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL | + VLYNQ_CTRL_INT2CFG; +- val |= vlynq_reg_read(dev->local->control); +- vlynq_reg_write(dev->local->int_ptr, VLYNQ_INT_OFFSET); +- vlynq_reg_write(dev->local->control, val); ++ val |= readl(&dev->local->control); ++ writel(VLYNQ_INT_OFFSET, &dev->local->int_ptr); ++ writel(val, &dev->local->control); + + val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq); + val |= VLYNQ_CTRL_INT_ENABLE; +- val |= vlynq_reg_read(dev->remote->control); +- vlynq_reg_write(dev->remote->int_ptr, VLYNQ_INT_OFFSET); +- vlynq_reg_write(dev->remote->control, val); ++ val |= readl(&dev->remote->control); ++ writel(VLYNQ_INT_OFFSET, &dev->remote->int_ptr); ++ writel(val, &dev->remote->int_ptr); ++ writel(val, &dev->remote->control); + + for (i = dev->irq_start; i <= dev->irq_end; i++) { + virq = i - dev->irq_start; +@@ -299,12 +300,13 @@ + set_irq_chip_and_handler(i, &vlynq_irq_chip, + handle_simple_irq); + set_irq_chip_data(i, dev); +- vlynq_reg_write(dev->remote->int_device[virq >> 2], 0); ++ writel(0, &dev->remote->int_device[virq >> 2]); + } + } + + if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) { +- printk(KERN_ERR "%s: request_irq failed\n", dev->dev.bus_id); ++ printk(KERN_ERR "%s: request_irq failed\n", ++ dev_name(&dev->dev)); + return -EAGAIN; + } + +@@ -328,11 +330,11 @@ + if (ids->id == vdev->dev_id) { + vdev->divisor = ids->divisor; + vlynq_set_drvdata(vdev, ids); +- printk(KERN_INFO "Driver found for VLYNQ " \ ++ printk(KERN_INFO "Driver found for VLYNQ " + "device: %08x\n", vdev->dev_id); + return 1; + } +- printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver" \ ++ printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver" + " for VLYNQ device: %08x\n", ids->id, vdev->dev_id); + ids++; + } +@@ -346,8 +348,7 @@ + struct vlynq_device_id *id = vlynq_get_drvdata(vdev); + int result = -ENODEV; + +- get_device(dev); +- if (drv && drv->probe) ++ if (drv->probe) + result = drv->probe(vdev, id); + if (result) + put_device(dev); +@@ -357,9 +358,10 @@ + static int vlynq_device_remove(struct device *dev) + { + struct vlynq_driver *drv = to_vlynq_driver(dev->driver); +- if (drv && drv->remove) ++ ++ if (drv->remove) + drv->remove(to_vlynq_device(dev)); +- put_device(dev); ++ + return 0; + } + +@@ -377,6 +379,14 @@ + } + EXPORT_SYMBOL(vlynq_unregister_driver); + ++/* ++ * A VLYNQ remote device can clock the VLYNQ bus master ++ * using a dedicated clock line. In that case, both the ++ * remove device and the bus master should have the same ++ * serial clock dividers configured. Iterate through the ++ * 8 possible dividers until we actually link with the ++ * device. ++ */ + static int __vlynq_try_remote(struct vlynq_device *dev) + { + int i; +@@ -389,21 +399,21 @@ + if (!vlynq_linked(dev)) + break; + +- vlynq_reg_write(dev->remote->control, +- (vlynq_reg_read(dev->remote->control) & ++ writel((readl(&dev->remote->control) & + ~VLYNQ_CTRL_CLOCK_MASK) | + VLYNQ_CTRL_CLOCK_INT | +- VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1)); +- vlynq_reg_write(dev->local->control, +- ((vlynq_reg_read(dev->local->control) ++ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), ++ &dev->remote->control); ++ writel((readl(&dev->local->control) + & ~(VLYNQ_CTRL_CLOCK_INT | + VLYNQ_CTRL_CLOCK_MASK)) | +- VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1))); ++ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), ++ &dev->local->control); + + if (vlynq_linked(dev)) { + printk(KERN_DEBUG + "%s: using remote clock divisor %d\n", +- dev->dev.bus_id, i - vlynq_rdiv1 + 1); ++ dev_name(&dev->dev), i - vlynq_rdiv1 + 1); + dev->divisor = i; + return 0; + } else { +@@ -414,26 +424,33 @@ + return -ENODEV; + } + ++/* ++ * A VLYNQ remote device can be clocked by the VLYNQ bus ++ * master using a dedicated clock line. In that case, only ++ * the bus master configures the serial clock divider. ++ * Iterate through the 8 possible dividers until we ++ * actually get a link with the device. ++ */ + static int __vlynq_try_local(struct vlynq_device *dev) + { + int i; +- ++ + vlynq_reset(dev); + + for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ? + i <= vlynq_ldiv8 : i >= vlynq_ldiv2; + dev->dev_id ? i++ : i--) { + +- vlynq_reg_write(dev->local->control, +- (vlynq_reg_read(dev->local->control) & ++ writel((readl(&dev->local->control) & + ~VLYNQ_CTRL_CLOCK_MASK) | + VLYNQ_CTRL_CLOCK_INT | +- VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1)); ++ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1), ++ &dev->local->control); + + if (vlynq_linked(dev)) { + printk(KERN_DEBUG + "%s: using local clock divisor %d\n", +- dev->dev.bus_id, i - vlynq_ldiv1 + 1); ++ dev_name(&dev->dev), i - vlynq_ldiv1 + 1); + dev->divisor = i; + return 0; + } else { +@@ -444,27 +461,33 @@ + return -ENODEV; + } + ++/* ++ * When using external clocking method, serial clock ++ * is supplied by an external oscillator, therefore we ++ * should mask the local clock bit in the clock control ++ * register for both the bus master and the remote device. ++ */ + static int __vlynq_try_external(struct vlynq_device *dev) + { + vlynq_reset(dev); + if (!vlynq_linked(dev)) + return -ENODEV; + +- vlynq_reg_write(dev->remote->control, +- (vlynq_reg_read(dev->remote->control) & +- ~VLYNQ_CTRL_CLOCK_INT)); +- +- vlynq_reg_write(dev->local->control, +- (vlynq_reg_read(dev->local->control) & +- ~VLYNQ_CTRL_CLOCK_INT)); ++ writel((readl(&dev->remote->control) & ++ ~VLYNQ_CTRL_CLOCK_INT), ++ &dev->remote->control); ++ ++ writel((readl(&dev->local->control) & ++ ~VLYNQ_CTRL_CLOCK_INT), ++ &dev->local->control); + + if (vlynq_linked(dev)) { + printk(KERN_DEBUG "%s: using external clock\n", +- dev->dev.bus_id); ++ dev_name(&dev->dev)); + dev->divisor = vlynq_div_external; + return 0; + } +- ++ + return -ENODEV; + } + +@@ -481,10 +504,10 @@ + case vlynq_div_external: + case vlynq_div_auto: + /* When the device is brought from reset it should have clock +- generation negotiated by hardware. +- Check which device is generating clocks and perform setup +- accordingly */ +- if (vlynq_linked(dev) && vlynq_reg_read(dev->remote->control) & ++ * generation negotiated by hardware. ++ * Check which device is generating clocks and perform setup ++ * accordingly */ ++ if (vlynq_linked(dev) && readl(&dev->remote->control) & + VLYNQ_CTRL_CLOCK_INT) { + if (!__vlynq_try_remote(dev) || + !__vlynq_try_local(dev) || +@@ -497,31 +520,43 @@ + return 0; + } + break; +- case vlynq_ldiv1: case vlynq_ldiv2: case vlynq_ldiv3: case vlynq_ldiv4: +- case vlynq_ldiv5: case vlynq_ldiv6: case vlynq_ldiv7: case vlynq_ldiv8: +- vlynq_reg_write(dev->local->control, +- VLYNQ_CTRL_CLOCK_INT | +- VLYNQ_CTRL_CLOCK_DIV(dev->divisor - +- vlynq_ldiv1)); +- vlynq_reg_write(dev->remote->control, 0); ++ case vlynq_ldiv1: ++ case vlynq_ldiv2: ++ case vlynq_ldiv3: ++ case vlynq_ldiv4: ++ case vlynq_ldiv5: ++ case vlynq_ldiv6: ++ case vlynq_ldiv7: ++ case vlynq_ldiv8: ++ writel(VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_DIV(dev->divisor - ++ vlynq_ldiv1), &dev->local->control); ++ writel(0, &dev->remote->control); + if (vlynq_linked(dev)) { + printk(KERN_DEBUG +- "%s: using local clock divisor %d\n", +- dev->dev.bus_id, dev->divisor - vlynq_ldiv1 + 1); ++ "%s: using local clock divisor %d\n", ++ dev_name(&dev->dev), ++ dev->divisor - vlynq_ldiv1 + 1); + return 0; + } + break; +- case vlynq_rdiv1: case vlynq_rdiv2: case vlynq_rdiv3: case vlynq_rdiv4: +- case vlynq_rdiv5: case vlynq_rdiv6: case vlynq_rdiv7: case vlynq_rdiv8: +- vlynq_reg_write(dev->local->control, 0); +- vlynq_reg_write(dev->remote->control, +- VLYNQ_CTRL_CLOCK_INT | +- VLYNQ_CTRL_CLOCK_DIV(dev->divisor - +- vlynq_rdiv1)); ++ case vlynq_rdiv1: ++ case vlynq_rdiv2: ++ case vlynq_rdiv3: ++ case vlynq_rdiv4: ++ case vlynq_rdiv5: ++ case vlynq_rdiv6: ++ case vlynq_rdiv7: ++ case vlynq_rdiv8: ++ writel(0, &dev->local->control); ++ writel(VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_DIV(dev->divisor - ++ vlynq_rdiv1), &dev->remote->control); + if (vlynq_linked(dev)) { + printk(KERN_DEBUG +- "%s: using remote clock divisor %d\n", +- dev->dev.bus_id, dev->divisor - vlynq_rdiv1 + 1); ++ "%s: using remote clock divisor %d\n", ++ dev_name(&dev->dev), ++ dev->divisor - vlynq_rdiv1 + 1); + return 0; + } + break; +@@ -568,12 +603,10 @@ + if (!dev->enabled) + return -ENXIO; + +- vlynq_reg_write(dev->local->tx_offset, tx_offset); ++ writel(tx_offset, &dev->local->tx_offset); + for (i = 0; i < 4; i++) { +- vlynq_reg_write(dev->local->rx_mapping[i].offset, +- mapping[i].offset); +- vlynq_reg_write(dev->local->rx_mapping[i].size, +- mapping[i].size); ++ writel(mapping[i].offset, &dev->local->rx_mapping[i].offset); ++ writel(mapping[i].size, &dev->local->rx_mapping[i].size); + } + return 0; + } +@@ -587,12 +620,10 @@ + if (!dev->enabled) + return -ENXIO; + +- vlynq_reg_write(dev->remote->tx_offset, tx_offset); ++ writel(tx_offset, &dev->remote->tx_offset); + for (i = 0; i < 4; i++) { +- vlynq_reg_write(dev->remote->rx_mapping[i].offset, +- mapping[i].offset); +- vlynq_reg_write(dev->remote->rx_mapping[i].size, +- mapping[i].size); ++ writel(mapping[i].offset, &dev->remote->rx_mapping[i].offset); ++ writel(mapping[i].size, &dev->remote->rx_mapping[i].size); + } + return 0; + } +@@ -662,8 +693,7 @@ + dev->id = pdev->id; + dev->dev.bus = &vlynq_bus_type; + dev->dev.parent = &pdev->dev; +- snprintf(dev->dev.bus_id, BUS_ID_SIZE, "vlynq%d", dev->id); +- dev->dev.bus_id[BUS_ID_SIZE - 1] = 0; ++ dev_set_name(&dev->dev, "vlynq%d", dev->id); + dev->dev.platform_data = pdev->dev.platform_data; + dev->dev.release = vlynq_device_release; + +@@ -673,9 +703,9 @@ + dev->mem_end = mem_res->end; + + len = regs_res->end - regs_res->start; +- if (!request_mem_region(regs_res->start, len, dev->dev.bus_id)) { ++ if (!request_mem_region(regs_res->start, len, dev_name(&dev->dev))) { + printk(KERN_ERR "%s: Can't request vlynq registers\n", +- dev->dev.bus_id); ++ dev_name(&dev->dev)); + result = -ENXIO; + goto fail_request; + } +@@ -683,7 +713,7 @@ + dev->local = ioremap(regs_res->start, len); + if (!dev->local) { + printk(KERN_ERR "%s: Can't remap vlynq registers\n", +- dev->dev.bus_id); ++ dev_name(&dev->dev)); + result = -ENXIO; + goto fail_remap; + } +@@ -702,14 +732,14 @@ + platform_set_drvdata(pdev, dev); + + printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n", +- dev->dev.bus_id, (void *)dev->regs_start, dev->irq, ++ dev_name(&dev->dev), (void *)dev->regs_start, dev->irq, + (void *)dev->mem_start); + + dev->dev_id = 0; + dev->divisor = vlynq_div_auto; + result = __vlynq_enable_device(dev); + if (result == 0) { +- dev->dev_id = vlynq_reg_read(dev->remote->chip); ++ dev->dev_id = readl(&dev->remote->chip); + ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev); + } + if (dev->dev_id) diff --git a/target/linux/ar7/patches-2.6.30/150-cpmac_not_broken.patch b/target/linux/ar7/patches-2.6.30/150-cpmac_not_broken.patch new file mode 100644 index 0000000000..0c8a20d459 --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/150-cpmac_not_broken.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -1883,7 +1883,7 @@ config SC92031 + + config CPMAC + tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" +- depends on NET_ETHERNET && EXPERIMENTAL && AR7 && BROKEN ++ depends on NET_ETHERNET && EXPERIMENTAL && AR7 + select PHYLIB + help + TI AR7 CPMAC Ethernet support diff --git a/target/linux/ar7/patches-2.6.30/500-serial_kludge.patch b/target/linux/ar7/patches-2.6.30/500-serial_kludge.patch new file mode 100644 index 0000000000..d4b02bc913 --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/500-serial_kludge.patch @@ -0,0 +1,38 @@ +--- a/drivers/serial/8250.c ++++ b/drivers/serial/8250.c +@@ -287,6 +287,13 @@ static const struct serial8250_config ua + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, ++ [PORT_AR7] = { ++ .name = "TI-AR7", ++ .fifo_size = 16, ++ .tx_loadsz = 16, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, ++ .flags = UART_CAP_FIFO | UART_CAP_AFE, ++ }, + }; + + #if defined (CONFIG_SERIAL_8250_AU1X00) +@@ -2702,7 +2709,11 @@ static void serial8250_console_putchar(s + { + struct uart_8250_port *up = (struct uart_8250_port *)port; + ++#ifdef CONFIG_AR7 ++ wait_for_xmitr(up, BOTH_EMPTY); ++#else + wait_for_xmitr(up, UART_LSR_THRE); ++#endif + serial_out(up, UART_TX, ch); + } + +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -41,6 +41,7 @@ + #define PORT_XSCALE 15 + #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ + #define PORT_OCTEON 17 /* Cavium OCTEON internal UART */ ++#define PORT_AR7 18 /* TI AR7 internal UART */ + #define PORT_MAX_8250 17 /* max port ID */ + + /* diff --git a/target/linux/ar7/patches-2.6.30/900-cpmac_multiqueue.patch b/target/linux/ar7/patches-2.6.30/900-cpmac_multiqueue.patch new file mode 100644 index 0000000000..3df3d68324 --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/900-cpmac_multiqueue.patch @@ -0,0 +1,70 @@ +This patch fixes the network driver cpmac.c for compilation with +configuration option CONFIG_NETDEVICES_MULTIQUEUE. + +These compiler warnings are fixed by the patch: +drivers/net/cpmac.c: In function 'cpmac_end_xmit': +drivers/net/cpmac.c:630: warning: passing argument 2 of 'netif_subqueue_stopped' makes pointer from integer without a cast +drivers/net/cpmac.c:641: warning: passing argument 2 of 'netif_subqueue_stopped' makes pointer from integer without a cast +drivers/net/cpmac.c: In function 'cpmac_probe': +drivers/net/cpmac.c:1128: warning: unused variable 'i' + +During runtime, the unpatched driver raises a fatal runtime exception. +This is fixed by calling __netif_subqueue_stopped instead +of netif_subqueue_stopped, too. + +Two additional code parts were modified for CONFIG_NETDEVICES_MULTIQUEUE +because other drivers do it in the same way. + + Signed-off-by: Stefan Weil + +--- a/drivers/net/cpmac.c ++++ b/drivers/net/cpmac.c +@@ -615,13 +615,13 @@ static void cpmac_end_xmit(struct net_de + + dev_kfree_skb_irq(desc->skb); + desc->skb = NULL; +- if (netif_subqueue_stopped(dev, queue)) ++ if (__netif_subqueue_stopped(dev, queue)) + netif_wake_subqueue(dev, queue); + } else { + if (netif_msg_tx_err(priv) && net_ratelimit()) + printk(KERN_WARNING + "%s: end_xmit: spurious interrupt\n", dev->name); +- if (netif_subqueue_stopped(dev, queue)) ++ if (__netif_subqueue_stopped(dev, queue)) + netif_wake_subqueue(dev, queue); + } + } +@@ -731,7 +731,6 @@ static void cpmac_clear_tx(struct net_de + + static void cpmac_hw_error(struct work_struct *work) + { +- int i; + struct cpmac_priv *priv = + container_of(work, struct cpmac_priv, reset_work); + +@@ -818,7 +817,6 @@ static irqreturn_t cpmac_irq(int irq, vo + + static void cpmac_tx_timeout(struct net_device *dev) + { +- int i; + struct cpmac_priv *priv = netdev_priv(dev); + + spin_lock(&priv->lock); +@@ -1097,7 +1095,7 @@ static int external_switch; + + static int __devinit cpmac_probe(struct platform_device *pdev) + { +- int rc, phy_id, i; ++ int rc, phy_id; + char *mdio_bus_id = "0"; + struct resource *mem; + struct cpmac_priv *priv; +@@ -1125,6 +1123,7 @@ static int __devinit cpmac_probe(struct + } + + dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); ++ //~ dev = alloc_etherdev(sizeof(*priv)); + + if (!dev) { + printk(KERN_ERR "cpmac: Unable to allocate net_device\n"); -- 2.11.0