mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-26 02:38:59 +02:00
preliminary 2.6.30 support
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@15468 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
0c04ef4bee
commit
27c303501e
2207
target/linux/generic-2.6/config-2.6.30
Normal file
2207
target/linux/generic-2.6/config-2.6.30
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@
|
|||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -561,6 +561,9 @@ endif
|
||||||
|
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
|
||||||
|
CHECKFLAGS += $(NOSTDINC_FLAGS)
|
||||||
|
|
||||||
|
+# improve gcc optimization
|
||||||
|
+CFLAGS += $(call cc-option,-funit-at-a-time,)
|
||||||
|
+
|
||||||
|
# warn about C99 declaration after statement
|
||||||
|
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/arch/mips/include/asm/system.h
|
||||||
|
+++ b/arch/mips/include/asm/system.h
|
||||||
|
@@ -187,7 +187,7 @@ extern __u64 __xchg_u64_unsupported_on_3
|
||||||
|
if something tries to do an invalid xchg(). */
|
||||||
|
extern void __xchg_called_with_bad_pointer(void);
|
||||||
|
|
||||||
|
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||||
|
+static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 4:
|
@ -0,0 +1,36 @@
|
|||||||
|
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||||
|
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||||
|
@@ -51,6 +51,7 @@
|
||||||
|
#define SST49LF040B 0x0050
|
||||||
|
#define SST49LF008A 0x005a
|
||||||
|
#define AT49BV6416 0x00d6
|
||||||
|
+#define MANUFACTURER_SAMSUNG 0x00ec
|
||||||
|
|
||||||
|
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||||
|
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
||||||
|
@@ -386,12 +387,19 @@ struct mtd_info *cfi_cmdset_0002(struct
|
||||||
|
|
||||||
|
if (extp->MajorVersion != '1' ||
|
||||||
|
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
|
||||||
|
- printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||||
|
- "version %c.%c.\n", extp->MajorVersion,
|
||||||
|
- extp->MinorVersion);
|
||||||
|
- kfree(extp);
|
||||||
|
- kfree(mtd);
|
||||||
|
- return NULL;
|
||||||
|
+ if (cfi->mfr == MANUFACTURER_SAMSUNG &&
|
||||||
|
+ (extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
|
||||||
|
+ printk(KERN_NOTICE " Newer Samsung flash detected, "
|
||||||
|
+ "should be compatibile with Amd/Fujitsu.\n");
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||||
|
+ "version %c.%c.\n", extp->MajorVersion,
|
||||||
|
+ extp->MinorVersion);
|
||||||
|
+ kfree(extp);
|
||||||
|
+ kfree(mtd);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install our own private info structure */
|
11
target/linux/generic-2.6/patches-2.6.30/011-mips_boot.patch
Normal file
11
target/linux/generic-2.6/patches-2.6.30/011-mips_boot.patch
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--- a/arch/mips/kernel/head.S
|
||||||
|
+++ b/arch/mips/kernel/head.S
|
||||||
|
@@ -121,6 +121,8 @@
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
+ j kernel_entry
|
||||||
|
+ nop
|
||||||
|
#ifndef CONFIG_NO_EXCEPT_FILL
|
||||||
|
/*
|
||||||
|
* Reserved space for exception handlers.
|
@ -0,0 +1,157 @@
|
|||||||
|
--- /dev/null
|
||||||
|
+++ b/include/asm-mips/mips_machine.h
|
||||||
|
@@ -0,0 +1,47 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2008 Gabor Juhos <juhosg@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.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef __ASM_MIPS_MACHINE_H
|
||||||
|
+#define __ASM_MIPS_MACHINE_H
|
||||||
|
+
|
||||||
|
+#include <linux/init.h>
|
||||||
|
+#include <linux/list.h>
|
||||||
|
+
|
||||||
|
+#define MIPS_MACHINE_NAME_LEN 64
|
||||||
|
+
|
||||||
|
+struct mips_machine {
|
||||||
|
+ unsigned long mach_type;
|
||||||
|
+ void (*mach_setup)(void);
|
||||||
|
+ unsigned char mach_name[MIPS_MACHINE_NAME_LEN];
|
||||||
|
+ struct list_head list;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+void mips_machine_register(struct mips_machine *) __init;
|
||||||
|
+void mips_machine_setup(unsigned long machtype) __init;
|
||||||
|
+
|
||||||
|
+extern unsigned char mips_machine_name[MIPS_MACHINE_NAME_LEN];
|
||||||
|
+
|
||||||
|
+#define MIPS_MACHINE(_type, _name, _setup) \
|
||||||
|
+static struct mips_machine machine_##_type __initdata = \
|
||||||
|
+{ \
|
||||||
|
+ .mach_type = _type, \
|
||||||
|
+ .mach_name = _name, \
|
||||||
|
+ .mach_setup = _setup, \
|
||||||
|
+}; \
|
||||||
|
+ \
|
||||||
|
+static int __init register_machine_##_type(void) \
|
||||||
|
+{ \
|
||||||
|
+ mips_machine_register(&machine_##_type); \
|
||||||
|
+ return 0; \
|
||||||
|
+} \
|
||||||
|
+ \
|
||||||
|
+pure_initcall(register_machine_##_type)
|
||||||
|
+
|
||||||
|
+#endif /* __ASM_MIPS_MACHINE_H */
|
||||||
|
+
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/mips/kernel/mips_machine.c
|
||||||
|
@@ -0,0 +1,58 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2008 Gabor Juhos <juhosg@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 <asm/mips_machine.h>
|
||||||
|
+#include <asm/bootinfo.h>
|
||||||
|
+
|
||||||
|
+static struct list_head mips_machines __initdata =
|
||||||
|
+ LIST_HEAD_INIT(mips_machines);
|
||||||
|
+
|
||||||
|
+unsigned char mips_machine_name[MIPS_MACHINE_NAME_LEN] = "Unknown";
|
||||||
|
+
|
||||||
|
+static struct mips_machine * __init mips_machine_find(unsigned long machtype)
|
||||||
|
+{
|
||||||
|
+ struct list_head *this;
|
||||||
|
+
|
||||||
|
+ list_for_each(this, &mips_machines) {
|
||||||
|
+ struct mips_machine *mach;
|
||||||
|
+
|
||||||
|
+ mach = list_entry(this, struct mips_machine, list);
|
||||||
|
+ if (mach->mach_type == machtype)
|
||||||
|
+ return mach;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void __init mips_machine_register(struct mips_machine *mach)
|
||||||
|
+{
|
||||||
|
+ list_add_tail(&mach->list, &mips_machines);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void __init mips_machine_setup(unsigned long machtype)
|
||||||
|
+{
|
||||||
|
+ struct mips_machine *mach;
|
||||||
|
+
|
||||||
|
+ mach = mips_machine_find(machtype);
|
||||||
|
+ if (!mach) {
|
||||||
|
+ printk(KERN_ALERT "MIPS: no machine registered for "
|
||||||
|
+ "machtype %lu\n", machtype);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (mach->mach_name[0])
|
||||||
|
+ strncpy(mips_machine_name, mach->mach_name,
|
||||||
|
+ MIPS_MACHINE_NAME_LEN);
|
||||||
|
+
|
||||||
|
+ printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name);
|
||||||
|
+
|
||||||
|
+ if (mach->mach_setup)
|
||||||
|
+ mach->mach_setup();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
--- a/arch/mips/kernel/Makefile
|
||||||
|
+++ b/arch/mips/kernel/Makefile
|
||||||
|
@@ -85,6 +85,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||||
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
|
+obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
|
||||||
|
|
||||||
|
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
|
||||||
|
|
||||||
|
--- a/arch/mips/Kconfig
|
||||||
|
+++ b/arch/mips/Kconfig
|
||||||
|
@@ -802,6 +802,9 @@ config MIPS_DISABLE_OBSOLETE_IDE
|
||||||
|
config SYNC_R4K
|
||||||
|
bool
|
||||||
|
|
||||||
|
+config MIPS_MACHINE
|
||||||
|
+ def_bool n
|
||||||
|
+
|
||||||
|
config NO_IOPORT
|
||||||
|
def_bool n
|
||||||
|
|
||||||
|
--- a/arch/mips/kernel/proc.c
|
||||||
|
+++ b/arch/mips/kernel/proc.c
|
||||||
|
@@ -14,6 +14,7 @@
|
||||||
|
#include <asm/cpu-features.h>
|
||||||
|
#include <asm/mipsregs.h>
|
||||||
|
#include <asm/processor.h>
|
||||||
|
+#include <asm/mips_machine.h>
|
||||||
|
|
||||||
|
unsigned int vced_count, vcei_count;
|
||||||
|
|
||||||
|
@@ -33,8 +34,12 @@ static int show_cpuinfo(struct seq_file
|
||||||
|
/*
|
||||||
|
* For the first processor also print the system type
|
||||||
|
*/
|
||||||
|
- if (n == 0)
|
||||||
|
+ if (n == 0) {
|
||||||
|
seq_printf(m, "system type\t\t: %s\n", get_system_type());
|
||||||
|
+#ifdef CONFIG_MIPS_MACHINE
|
||||||
|
+ seq_printf(m, "machine\t\t\t: %s\n", mips_machine_name);
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
|
||||||
|
seq_printf(m, "processor\t\t: %ld\n", n);
|
||||||
|
sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
|
@ -0,0 +1,50 @@
|
|||||||
|
--- a/arch/mips/Kconfig
|
||||||
|
+++ b/arch/mips/Kconfig
|
||||||
|
@@ -804,6 +804,9 @@ config SYNC_R4K
|
||||||
|
|
||||||
|
config MIPS_MACHINE
|
||||||
|
def_bool n
|
||||||
|
+
|
||||||
|
+config PROM_EMU
|
||||||
|
+ def_bool n
|
||||||
|
|
||||||
|
config NO_IOPORT
|
||||||
|
def_bool n
|
||||||
|
--- a/arch/mips/kernel/head.S
|
||||||
|
+++ b/arch/mips/kernel/head.S
|
||||||
|
@@ -143,6 +143,15 @@ FEXPORT(__kernel_entry)
|
||||||
|
j kernel_entry
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifdef CONFIG_PROM_EMU
|
||||||
|
+EXPORT(prom_emu_argv)
|
||||||
|
+ .word 0
|
||||||
|
+ .word prom_emu_cmdline
|
||||||
|
+ .ascii "CMDLINE:"
|
||||||
|
+EXPORT(prom_emu_cmdline)
|
||||||
|
+ .fill 0x400
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
__REF
|
||||||
|
|
||||||
|
NESTED(kernel_entry, 16, sp) # kernel entry point
|
||||||
|
@@ -183,6 +192,19 @@ NESTED(kernel_entry, 16, sp) # kernel
|
||||||
|
LONG_S zero, (t0)
|
||||||
|
bne t0, t1, 1b
|
||||||
|
|
||||||
|
+#ifdef CONFIG_PROM_EMU
|
||||||
|
+ PTR_LA t0, prom_emu_cmdline
|
||||||
|
+ LONG_L t1, 0(t0)
|
||||||
|
+ beqz t1, 1f
|
||||||
|
+
|
||||||
|
+ li a0, 2
|
||||||
|
+ PTR_LA a1, prom_emu_argv
|
||||||
|
+ move a2, zero
|
||||||
|
+ move a3, zero
|
||||||
|
+
|
||||||
|
+1:
|
||||||
|
+#endif /* CONFIG_PROM_EMU */
|
||||||
|
+
|
||||||
|
LONG_S a0, fw_arg0 # firmware arguments
|
||||||
|
LONG_S a1, fw_arg1
|
||||||
|
LONG_S a2, fw_arg2
|
110
target/linux/generic-2.6/patches-2.6.30/060-block2mtd_init.patch
Normal file
110
target/linux/generic-2.6/patches-2.6.30/060-block2mtd_init.patch
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
--- a/drivers/mtd/devices/block2mtd.c
|
||||||
|
+++ b/drivers/mtd/devices/block2mtd.c
|
||||||
|
@@ -14,6 +14,7 @@
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
+#include <linux/mtd/partitions.h>
|
||||||
|
#include <linux/buffer_head.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
|
@@ -232,10 +233,11 @@ static void block2mtd_free_device(struct
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||||
|
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
|
||||||
|
+static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
|
||||||
|
{
|
||||||
|
struct block_device *bdev;
|
||||||
|
struct block2mtd_dev *dev;
|
||||||
|
+ struct mtd_partition *part;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if (!devname)
|
||||||
|
@@ -273,17 +275,17 @@ static struct block2mtd_dev *add_device(
|
||||||
|
|
||||||
|
mutex_init(&dev->write_mutex);
|
||||||
|
|
||||||
|
- /* Setup the MTD structure */
|
||||||
|
- /* make the name contain the block device in */
|
||||||
|
- name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1,
|
||||||
|
- GFP_KERNEL);
|
||||||
|
+ if (!mtdname)
|
||||||
|
+ mtdname = devname;
|
||||||
|
+
|
||||||
|
+ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
|
||||||
|
if (!name)
|
||||||
|
goto devinit_err;
|
||||||
|
|
||||||
|
- sprintf(name, "block2mtd: %s", devname);
|
||||||
|
+ strcpy(name, mtdname);
|
||||||
|
dev->mtd.name = name;
|
||||||
|
|
||||||
|
- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
|
||||||
|
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
|
||||||
|
dev->mtd.erasesize = erase_size;
|
||||||
|
dev->mtd.writesize = 1;
|
||||||
|
dev->mtd.type = MTD_RAM;
|
||||||
|
@@ -296,14 +298,17 @@ static struct block2mtd_dev *add_device(
|
||||||
|
dev->mtd.priv = dev;
|
||||||
|
dev->mtd.owner = THIS_MODULE;
|
||||||
|
|
||||||
|
- if (add_mtd_device(&dev->mtd)) {
|
||||||
|
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
||||||
|
+ part->name = dev->mtd.name;
|
||||||
|
+ part->offset = 0;
|
||||||
|
+ part->size = dev->mtd.size;
|
||||||
|
+ if (add_mtd_partitions(&dev->mtd, part, 1)) {
|
||||||
|
/* Device didnt get added, so free the entry */
|
||||||
|
goto devinit_err;
|
||||||
|
}
|
||||||
|
list_add(&dev->list, &blkmtd_device_list);
|
||||||
|
INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
|
||||||
|
- dev->mtd.name + strlen("block2mtd: "),
|
||||||
|
- dev->mtd.erasesize >> 10, dev->mtd.erasesize);
|
||||||
|
+ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
|
||||||
|
return dev;
|
||||||
|
|
||||||
|
devinit_err:
|
||||||
|
@@ -376,9 +381,9 @@ static char block2mtd_paramline[80 + 12]
|
||||||
|
|
||||||
|
static int block2mtd_setup2(const char *val)
|
||||||
|
{
|
||||||
|
- char buf[80 + 12]; /* 80 for device, 12 for erase size */
|
||||||
|
+ char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
|
||||||
|
char *str = buf;
|
||||||
|
- char *token[2];
|
||||||
|
+ char *token[3];
|
||||||
|
char *name;
|
||||||
|
size_t erase_size = PAGE_SIZE;
|
||||||
|
int i, ret;
|
||||||
|
@@ -389,7 +394,7 @@ static int block2mtd_setup2(const char *
|
||||||
|
strcpy(str, val);
|
||||||
|
kill_final_newline(str);
|
||||||
|
|
||||||
|
- for (i = 0; i < 2; i++)
|
||||||
|
+ for (i = 0; i < 3; i++)
|
||||||
|
token[i] = strsep(&str, ",");
|
||||||
|
|
||||||
|
if (str)
|
||||||
|
@@ -408,8 +413,10 @@ static int block2mtd_setup2(const char *
|
||||||
|
parse_err("illegal erase size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (token[2] && (strlen(token[2]) + 1 > 80))
|
||||||
|
+ parse_err("mtd device name too long");
|
||||||
|
|
||||||
|
- add_device(name, erase_size);
|
||||||
|
+ add_device(name, erase_size, token[2]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -443,7 +450,7 @@ static int block2mtd_setup(const char *v
|
||||||
|
|
||||||
|
|
||||||
|
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
|
||||||
|
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
|
||||||
|
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
|
||||||
|
|
||||||
|
static int __init block2mtd_init(void)
|
||||||
|
{
|
633
target/linux/generic-2.6/patches-2.6.30/065-rootfs_split.patch
Normal file
633
target/linux/generic-2.6/patches-2.6.30/065-rootfs_split.patch
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
--- a/drivers/mtd/Kconfig
|
||||||
|
+++ b/drivers/mtd/Kconfig
|
||||||
|
@@ -53,6 +53,16 @@ config MTD_TESTS
|
||||||
|
should normally be compiled as kernel modules. The modules perform
|
||||||
|
various checks and verifications when loaded.
|
||||||
|
|
||||||
|
+config MTD_ROOTFS_ROOT_DEV
|
||||||
|
+ bool "Automatically set 'rootfs' partition to be root filesystem"
|
||||||
|
+ depends on MTD_PARTITIONS
|
||||||
|
+ default y
|
||||||
|
+
|
||||||
|
+config MTD_ROOTFS_SPLIT
|
||||||
|
+ bool "Automatically split 'rootfs' partition for squashfs"
|
||||||
|
+ depends on MTD_PARTITIONS
|
||||||
|
+ default y
|
||||||
|
+
|
||||||
|
config MTD_REDBOOT_PARTS
|
||||||
|
tristate "RedBoot partition table parsing"
|
||||||
|
depends on MTD_PARTITIONS
|
||||||
|
--- a/drivers/mtd/mtdpart.c
|
||||||
|
+++ b/drivers/mtd/mtdpart.c
|
||||||
|
@@ -18,6 +18,8 @@
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
#include <linux/mtd/partitions.h>
|
||||||
|
#include <linux/mtd/compatmac.h>
|
||||||
|
+#include <linux/root_dev.h>
|
||||||
|
+#include <linux/magic.h>
|
||||||
|
|
||||||
|
/* Our partition linked list */
|
||||||
|
static LIST_HEAD(mtd_partitions);
|
||||||
|
@@ -37,7 +39,7 @@ struct mtd_part {
|
||||||
|
* the pointer to that structure with this macro.
|
||||||
|
*/
|
||||||
|
#define PART(x) ((struct mtd_part *)(x))
|
||||||
|
-
|
||||||
|
+#define IS_PART(mtd) (mtd->read == part_read)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MTD methods which simply translate the effective address and pass through
|
||||||
|
@@ -512,6 +514,156 @@ out_register:
|
||||||
|
return slave;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
||||||
|
+#define ROOTFS_SPLIT_NAME "rootfs_data"
|
||||||
|
+#define ROOTFS_REMOVED_NAME "<removed>"
|
||||||
|
+
|
||||||
|
+struct squashfs_super_block {
|
||||||
|
+ __le32 s_magic;
|
||||||
|
+ __le32 pad0[9];
|
||||||
|
+ __le64 bytes_used;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
|
||||||
|
+{
|
||||||
|
+ char buf[512];
|
||||||
|
+ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
|
||||||
|
+ int len, ret;
|
||||||
|
+
|
||||||
|
+ ret = master->read(master, offset, sizeof(*sb), &len, buf);
|
||||||
|
+ if (ret || (len != sizeof(*sb))) {
|
||||||
|
+ printk(KERN_ALERT "split_squashfs: error occured while reading "
|
||||||
|
+ "from \"%s\"\n", master->name);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (*((u32 *) buf) != SQUASHFS_MAGIC) {
|
||||||
|
+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
|
||||||
|
+ master->name);
|
||||||
|
+ *split_offset = 0;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (sb->bytes_used <= 0) {
|
||||||
|
+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
|
||||||
|
+ master->name);
|
||||||
|
+ *split_offset = 0;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ len = (u32) sb->bytes_used;
|
||||||
|
+ len += (offset & 0x000fffff);
|
||||||
|
+ len += (master->erasesize - 1);
|
||||||
|
+ len &= ~(master->erasesize - 1);
|
||||||
|
+ len -= (offset & 0x000fffff);
|
||||||
|
+ *split_offset = offset + len;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part,
|
||||||
|
+ int index)
|
||||||
|
+{
|
||||||
|
+ struct mtd_partition *dpart;
|
||||||
|
+ struct mtd_part *slave = NULL;
|
||||||
|
+ int split_offset = 0;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = split_squashfs(master, part->offset, &split_offset);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (split_offset <= 0)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
|
||||||
|
+ if (dpart == NULL) {
|
||||||
|
+ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
|
||||||
|
+ ROOTFS_SPLIT_NAME);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(dpart, part, sizeof(*part));
|
||||||
|
+ dpart->name = (unsigned char *)&dpart[1];
|
||||||
|
+ strcpy(dpart->name, ROOTFS_SPLIT_NAME);
|
||||||
|
+
|
||||||
|
+ dpart->size -= split_offset - dpart->offset;
|
||||||
|
+ dpart->offset = split_offset;
|
||||||
|
+
|
||||||
|
+ if (dpart == NULL)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n",
|
||||||
|
+ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
|
||||||
|
+
|
||||||
|
+ slave = add_one_partition(master, dpart, index, split_offset);
|
||||||
|
+ if (!slave) {
|
||||||
|
+ kfree(dpart);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
+ rpart->split = &slave->mtd;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int refresh_rootfs_split(struct mtd_info *mtd)
|
||||||
|
+{
|
||||||
|
+ struct mtd_partition tpart;
|
||||||
|
+ struct mtd_part *part;
|
||||||
|
+ char *name;
|
||||||
|
+ int index = 0;
|
||||||
|
+ int offset, size;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ part = PART(mtd);
|
||||||
|
+
|
||||||
|
+ /* check for the new squashfs offset first */
|
||||||
|
+ ret = split_squashfs(part->master, part->offset, &offset);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if ((offset > 0) && !mtd->split) {
|
||||||
|
+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
|
||||||
|
+ /* if we don't have a rootfs split partition, create a new one */
|
||||||
|
+ tpart.name = (char *) mtd->name;
|
||||||
|
+ tpart.size = mtd->size;
|
||||||
|
+ tpart.offset = part->offset;
|
||||||
|
+
|
||||||
|
+ /* find the index of the last partition */
|
||||||
|
+ if (!list_empty(&mtd_partitions))
|
||||||
|
+ index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1;
|
||||||
|
+
|
||||||
|
+ return split_rootfs_data(part->master, &part->mtd, &tpart, index);
|
||||||
|
+ } else if ((offset > 0) && mtd->split) {
|
||||||
|
+ /* update the offsets of the existing partition */
|
||||||
|
+ size = mtd->size + part->offset - offset;
|
||||||
|
+
|
||||||
|
+ part = PART(mtd->split);
|
||||||
|
+ part->offset = offset;
|
||||||
|
+ part->mtd.size = size;
|
||||||
|
+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
|
||||||
|
+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
|
||||||
|
+ (u32) part->offset, (u32) part->mtd.size);
|
||||||
|
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
|
||||||
|
+ strcpy(name, ROOTFS_SPLIT_NAME);
|
||||||
|
+ part->mtd.name = name;
|
||||||
|
+ } else if ((offset <= 0) && mtd->split) {
|
||||||
|
+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
|
||||||
|
+
|
||||||
|
+ /* mark existing partition as removed */
|
||||||
|
+ part = PART(mtd->split);
|
||||||
|
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
|
||||||
|
+ strcpy(name, ROOTFS_REMOVED_NAME);
|
||||||
|
+ part->mtd.name = name;
|
||||||
|
+ part->offset = 0;
|
||||||
|
+ part->mtd.size = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* This function, given a master MTD object and a partition table, creates
|
||||||
|
* and registers slave MTD objects which are bound to the master according to
|
||||||
|
@@ -527,14 +679,29 @@ int add_mtd_partitions(struct mtd_info *
|
||||||
|
{
|
||||||
|
struct mtd_part *slave;
|
||||||
|
uint64_t cur_offset = 0;
|
||||||
|
- int i;
|
||||||
|
+ int i, j, ret;
|
||||||
|
|
||||||
|
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
|
||||||
|
|
||||||
|
- for (i = 0; i < nbparts; i++) {
|
||||||
|
- slave = add_one_partition(master, parts + i, i, cur_offset);
|
||||||
|
+ for (i = 0, j = 0; i < nbparts; i++) {
|
||||||
|
+ slave = add_one_partition(master, parts + i, j++, cur_offset);
|
||||||
|
if (!slave)
|
||||||
|
return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ if (!strcmp(parts[i].name, "rootfs") && slave->registered) {
|
||||||
|
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
|
||||||
|
+ if (ROOT_DEV == 0) {
|
||||||
|
+ printk(KERN_NOTICE "mtd: partition \"rootfs\" "
|
||||||
|
+ "set to be root filesystem\n");
|
||||||
|
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
||||||
|
+ ret = split_rootfs_data(master, &slave->mtd, &parts[i], j);
|
||||||
|
+ if (ret == 0)
|
||||||
|
+ j++;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
cur_offset = slave->offset + slave->mtd.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -542,6 +709,32 @@ int add_mtd_partitions(struct mtd_info *
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(add_mtd_partitions);
|
||||||
|
|
||||||
|
+int refresh_mtd_partitions(struct mtd_info *mtd)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ if (IS_PART(mtd)) {
|
||||||
|
+ struct mtd_part *part;
|
||||||
|
+ struct mtd_info *master;
|
||||||
|
+
|
||||||
|
+ part = PART(mtd);
|
||||||
|
+ master = part->master;
|
||||||
|
+ if (master->refresh_device)
|
||||||
|
+ ret = master->refresh_device(master);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!ret && mtd->refresh_device)
|
||||||
|
+ ret = mtd->refresh_device(mtd);
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
||||||
|
+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
|
||||||
|
+ refresh_rootfs_split(mtd);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(refresh_mtd_partitions);
|
||||||
|
+
|
||||||
|
static DEFINE_SPINLOCK(part_parser_lock);
|
||||||
|
static LIST_HEAD(part_parsers);
|
||||||
|
|
||||||
|
--- a/drivers/mtd/devices/block2mtd.c
|
||||||
|
+++ b/drivers/mtd/devices/block2mtd.c
|
||||||
|
@@ -29,6 +29,8 @@ struct block2mtd_dev {
|
||||||
|
struct block_device *blkdev;
|
||||||
|
struct mtd_info mtd;
|
||||||
|
struct mutex write_mutex;
|
||||||
|
+ rwlock_t bdev_mutex;
|
||||||
|
+ char devname[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -81,6 +83,12 @@ static int block2mtd_erase(struct mtd_in
|
||||||
|
size_t len = instr->len;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
+ read_lock(&dev->bdev_mutex);
|
||||||
|
+ if (!dev->blkdev) {
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
instr->state = MTD_ERASING;
|
||||||
|
mutex_lock(&dev->write_mutex);
|
||||||
|
err = _block2mtd_erase(dev, from, len);
|
||||||
|
@@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in
|
||||||
|
|
||||||
|
instr->state = MTD_ERASE_DONE;
|
||||||
|
mtd_erase_callback(instr);
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+ read_unlock(&dev->bdev_mutex);
|
||||||
|
+
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf
|
||||||
|
struct page *page;
|
||||||
|
int index = from >> PAGE_SHIFT;
|
||||||
|
int offset = from & (PAGE_SIZE-1);
|
||||||
|
- int cpylen;
|
||||||
|
+ int cpylen, err = 0;
|
||||||
|
+
|
||||||
|
+ read_lock(&dev->bdev_mutex);
|
||||||
|
+ if (!dev->blkdev || (from > mtd->size)) {
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (from > mtd->size)
|
||||||
|
- return -EINVAL;
|
||||||
|
if (from + len > mtd->size)
|
||||||
|
len = mtd->size - from;
|
||||||
|
|
||||||
|
@@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf
|
||||||
|
len = len - cpylen;
|
||||||
|
|
||||||
|
page = page_read(dev->blkdev->bd_inode->i_mapping, index);
|
||||||
|
- if (!page)
|
||||||
|
- return -ENOMEM;
|
||||||
|
- if (IS_ERR(page))
|
||||||
|
- return PTR_ERR(page);
|
||||||
|
+ if (!page) {
|
||||||
|
+ err = -ENOMEM;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+ if (IS_ERR(page)) {
|
||||||
|
+ err = PTR_ERR(page);
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
memcpy(buf, page_address(page) + offset, cpylen);
|
||||||
|
page_cache_release(page);
|
||||||
|
@@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf
|
||||||
|
offset = 0;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
- return 0;
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+ read_unlock(&dev->bdev_mutex);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in
|
||||||
|
size_t *retlen, const u_char *buf)
|
||||||
|
{
|
||||||
|
struct block2mtd_dev *dev = mtd->priv;
|
||||||
|
- int err;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ read_lock(&dev->bdev_mutex);
|
||||||
|
+ if (!dev->blkdev) {
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
- return 0;
|
||||||
|
- if (to >= mtd->size)
|
||||||
|
- return -ENOSPC;
|
||||||
|
+ goto done;
|
||||||
|
+
|
||||||
|
+ if (to >= mtd->size) {
|
||||||
|
+ err = -ENOSPC;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (to + len > mtd->size)
|
||||||
|
len = mtd->size - to;
|
||||||
|
|
||||||
|
@@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in
|
||||||
|
mutex_unlock(&dev->write_mutex);
|
||||||
|
if (err > 0)
|
||||||
|
err = 0;
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+ read_unlock(&dev->bdev_mutex);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -210,52 +246,29 @@ static int block2mtd_write(struct mtd_in
|
||||||
|
static void block2mtd_sync(struct mtd_info *mtd)
|
||||||
|
{
|
||||||
|
struct block2mtd_dev *dev = mtd->priv;
|
||||||
|
- sync_blockdev(dev->blkdev);
|
||||||
|
- return;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static void block2mtd_free_device(struct block2mtd_dev *dev)
|
||||||
|
-{
|
||||||
|
- if (!dev)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- kfree(dev->mtd.name);
|
||||||
|
|
||||||
|
- if (dev->blkdev) {
|
||||||
|
- invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
|
||||||
|
- 0, -1);
|
||||||
|
- close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
|
||||||
|
- }
|
||||||
|
+ read_lock(&dev->bdev_mutex);
|
||||||
|
+ if (dev->blkdev)
|
||||||
|
+ sync_blockdev(dev->blkdev);
|
||||||
|
+ read_unlock(&dev->bdev_mutex);
|
||||||
|
|
||||||
|
- kfree(dev);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||||
|
-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
|
||||||
|
+static int _open_bdev(struct block2mtd_dev *dev)
|
||||||
|
{
|
||||||
|
struct block_device *bdev;
|
||||||
|
- struct block2mtd_dev *dev;
|
||||||
|
- struct mtd_partition *part;
|
||||||
|
- char *name;
|
||||||
|
-
|
||||||
|
- if (!devname)
|
||||||
|
- return NULL;
|
||||||
|
-
|
||||||
|
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
|
||||||
|
- if (!dev)
|
||||||
|
- return NULL;
|
||||||
|
|
||||||
|
/* Get a handle on the device */
|
||||||
|
- bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
|
||||||
|
+ bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL);
|
||||||
|
#ifndef MODULE
|
||||||
|
if (IS_ERR(bdev)) {
|
||||||
|
|
||||||
|
/* We might not have rootfs mounted at this point. Try
|
||||||
|
to resolve the device name by other means. */
|
||||||
|
|
||||||
|
- dev_t devt = name_to_dev_t(devname);
|
||||||
|
+ dev_t devt = name_to_dev_t(dev->devname);
|
||||||
|
if (devt) {
|
||||||
|
bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
||||||
|
}
|
||||||
|
@@ -263,17 +276,97 @@ static struct block2mtd_dev *add_device(
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (IS_ERR(bdev)) {
|
||||||
|
- ERROR("error: cannot open device %s", devname);
|
||||||
|
- goto devinit_err;
|
||||||
|
+ ERROR("error: cannot open device %s", dev->devname);
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
dev->blkdev = bdev;
|
||||||
|
|
||||||
|
if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
|
||||||
|
ERROR("attempting to use an MTD device as a block device");
|
||||||
|
- goto devinit_err;
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _close_bdev(struct block2mtd_dev *dev)
|
||||||
|
+{
|
||||||
|
+ struct block_device *bdev;
|
||||||
|
+
|
||||||
|
+ if (!dev->blkdev)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ bdev = dev->blkdev;
|
||||||
|
+ invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
|
||||||
|
+ close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
|
||||||
|
+ dev->blkdev = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void block2mtd_free_device(struct block2mtd_dev *dev)
|
||||||
|
+{
|
||||||
|
+ if (!dev)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ kfree(dev->mtd.name);
|
||||||
|
+ _close_bdev(dev);
|
||||||
|
+ kfree(dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int block2mtd_refresh(struct mtd_info *mtd)
|
||||||
|
+{
|
||||||
|
+ struct block2mtd_dev *dev = mtd->priv;
|
||||||
|
+ struct block_device *bdev;
|
||||||
|
+ dev_t devt;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ /* no other mtd function can run at this point */
|
||||||
|
+ write_lock(&dev->bdev_mutex);
|
||||||
|
+
|
||||||
|
+ /* get the device number for the whole disk */
|
||||||
|
+ devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
|
||||||
|
+
|
||||||
|
+ /* close the old block device */
|
||||||
|
+ _close_bdev(dev);
|
||||||
|
+
|
||||||
|
+ /* open the whole disk, issue a partition rescan, then */
|
||||||
|
+ bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
||||||
|
+ if (!bdev || !bdev->bd_disk)
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ else {
|
||||||
|
+ err = rescan_partitions(bdev->bd_disk, bdev);
|
||||||
|
+ }
|
||||||
|
+ if (bdev)
|
||||||
|
+ close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
|
||||||
|
+
|
||||||
|
+ /* try to open the partition block device again */
|
||||||
|
+ _open_bdev(dev);
|
||||||
|
+ write_unlock(&dev->bdev_mutex);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||||
|
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
|
||||||
|
+{
|
||||||
|
+ struct block2mtd_dev *dev;
|
||||||
|
+ struct mtd_partition *part;
|
||||||
|
+ char *name;
|
||||||
|
+
|
||||||
|
+ if (!devname)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
|
||||||
|
+ if (!dev)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ strcpy(dev->devname, devname);
|
||||||
|
+
|
||||||
|
+ if (_open_bdev(dev))
|
||||||
|
+ goto devinit_err;
|
||||||
|
+
|
||||||
|
mutex_init(&dev->write_mutex);
|
||||||
|
+ rwlock_init(&dev->bdev_mutex);
|
||||||
|
|
||||||
|
if (!mtdname)
|
||||||
|
mtdname = devname;
|
||||||
|
@@ -297,6 +390,7 @@ static struct block2mtd_dev *add_device(
|
||||||
|
dev->mtd.read = block2mtd_read;
|
||||||
|
dev->mtd.priv = dev;
|
||||||
|
dev->mtd.owner = THIS_MODULE;
|
||||||
|
+ dev->mtd.refresh_device = block2mtd_refresh;
|
||||||
|
|
||||||
|
part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
||||||
|
part->name = dev->mtd.name;
|
||||||
|
--- a/drivers/mtd/mtdchar.c
|
||||||
|
+++ b/drivers/mtd/mtdchar.c
|
||||||
|
@@ -17,6 +17,7 @@
|
||||||
|
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
#include <linux/mtd/compatmac.h>
|
||||||
|
+#include <linux/mtd/partitions.h>
|
||||||
|
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
@@ -750,6 +751,13 @@ static int mtd_ioctl(struct inode *inode
|
||||||
|
file->f_pos = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+#ifdef CONFIG_MTD_PARTITIONS
|
||||||
|
+ case MTDREFRESH:
|
||||||
|
+ {
|
||||||
|
+ ret = refresh_mtd_partitions(mtd);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = -ENOTTY;
|
||||||
|
--- a/include/linux/mtd/mtd.h
|
||||||
|
+++ b/include/linux/mtd/mtd.h
|
||||||
|
@@ -101,6 +101,7 @@ struct mtd_oob_ops {
|
||||||
|
uint8_t *oobbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct mtd_info;
|
||||||
|
struct mtd_info {
|
||||||
|
u_char type;
|
||||||
|
uint32_t flags;
|
||||||
|
@@ -241,6 +242,9 @@ struct mtd_info {
|
||||||
|
struct device dev;
|
||||||
|
int usecount;
|
||||||
|
|
||||||
|
+ int (*refresh_device)(struct mtd_info *mtd);
|
||||||
|
+ struct mtd_info *split;
|
||||||
|
+
|
||||||
|
/* If the driver is something smart, like UBI, it may need to maintain
|
||||||
|
* its own reference counting. The below functions are only for driver.
|
||||||
|
* The driver may register its callbacks. These callbacks are not
|
||||||
|
--- a/include/linux/mtd/partitions.h
|
||||||
|
+++ b/include/linux/mtd/partitions.h
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
||||||
|
*/
|
||||||
|
|
||||||
|
+struct mtd_partition;
|
||||||
|
struct mtd_partition {
|
||||||
|
char *name; /* identifier string */
|
||||||
|
uint64_t size; /* partition size */
|
||||||
|
@@ -41,6 +42,7 @@ struct mtd_partition {
|
||||||
|
uint32_t mask_flags; /* master MTD flags to mask out for this partition */
|
||||||
|
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
|
||||||
|
struct mtd_info **mtdp; /* pointer to store the MTD object */
|
||||||
|
+ int (*refresh_partition)(struct mtd_info *);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MTDPART_OFS_NXTBLK (-2)
|
||||||
|
@@ -50,6 +52,7 @@ struct mtd_partition {
|
||||||
|
|
||||||
|
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
|
||||||
|
int del_mtd_partitions(struct mtd_info *);
|
||||||
|
+int refresh_mtd_partitions(struct mtd_info *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions dealing with the various ways of partitioning the space
|
||||||
|
--- a/include/mtd/mtd-abi.h
|
||||||
|
+++ b/include/mtd/mtd-abi.h
|
||||||
|
@@ -95,6 +95,7 @@ struct otp_info {
|
||||||
|
#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
|
||||||
|
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
|
||||||
|
#define MTDFILEMODE _IO('M', 19)
|
||||||
|
+#define MTDREFRESH _IO('M', 23)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obsolete legacy interface. Keep it in order not to break userspace
|
@ -0,0 +1,30 @@
|
|||||||
|
--- a/drivers/mtd/redboot.c
|
||||||
|
+++ b/drivers/mtd/redboot.c
|
||||||
|
@@ -249,14 +249,21 @@ static int parse_redboot_partitions(stru
|
||||||
|
#endif
|
||||||
|
names += strlen(names)+1;
|
||||||
|
|
||||||
|
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||||
|
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
|
||||||
|
- i++;
|
||||||
|
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||||
|
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||||
|
- parts[i].name = nullname;
|
||||||
|
- }
|
||||||
|
+ if (!strcmp(parts[i].name, "rootfs")) {
|
||||||
|
+ parts[i].size = fl->next->img->flash_base;
|
||||||
|
+ parts[i].size &= ~(master->erasesize - 1);
|
||||||
|
+ parts[i].size -= parts[i].offset;
|
||||||
|
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||||
|
+ nrparts--;
|
||||||
|
+ } else {
|
||||||
|
+ i++;
|
||||||
|
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||||
|
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||||
|
+ parts[i].name = nullname;
|
||||||
|
#endif
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
tmp_fl = fl;
|
||||||
|
fl = fl->next;
|
||||||
|
kfree(tmp_fl);
|
@ -0,0 +1,60 @@
|
|||||||
|
--- a/drivers/mtd/redboot.c
|
||||||
|
+++ b/drivers/mtd/redboot.c
|
||||||
|
@@ -11,6 +11,8 @@
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
#include <linux/mtd/partitions.h>
|
||||||
|
|
||||||
|
+#define BOARD_CONFIG_PART "boardconfig"
|
||||||
|
+
|
||||||
|
struct fis_image_desc {
|
||||||
|
unsigned char name[16]; // Null terminated name
|
||||||
|
uint32_t flash_base; // Address within FLASH of image
|
||||||
|
@@ -41,6 +43,7 @@ static int parse_redboot_partitions(stru
|
||||||
|
struct mtd_partition **pparts,
|
||||||
|
unsigned long fis_origin)
|
||||||
|
{
|
||||||
|
+ unsigned long max_offset = 0;
|
||||||
|
int nrparts = 0;
|
||||||
|
struct fis_image_desc *buf;
|
||||||
|
struct mtd_partition *parts;
|
||||||
|
@@ -209,14 +212,14 @@ static int parse_redboot_partitions(stru
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
- parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
|
||||||
|
+ parts = kzalloc(sizeof(*parts) * (nrparts + 1) + nulllen + namelen + sizeof(BOARD_CONFIG_PART), GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!parts) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- nullname = (char *)&parts[nrparts];
|
||||||
|
+ nullname = (char *)&parts[nrparts + 1];
|
||||||
|
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||||
|
if (nulllen > 0) {
|
||||||
|
strcpy(nullname, nullstring);
|
||||||
|
@@ -235,6 +238,8 @@ static int parse_redboot_partitions(stru
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for ( ; i<nrparts; i++) {
|
||||||
|
+ if(max_offset < buf[i].flash_base + buf[i].size)
|
||||||
|
+ max_offset = buf[i].flash_base + buf[i].size;
|
||||||
|
parts[i].size = fl->img->size;
|
||||||
|
parts[i].offset = fl->img->flash_base;
|
||||||
|
parts[i].name = names;
|
||||||
|
@@ -268,6 +273,14 @@ static int parse_redboot_partitions(stru
|
||||||
|
fl = fl->next;
|
||||||
|
kfree(tmp_fl);
|
||||||
|
}
|
||||||
|
+ if(master->size - max_offset >= master->erasesize)
|
||||||
|
+ {
|
||||||
|
+ parts[nrparts].size = master->size - max_offset;
|
||||||
|
+ parts[nrparts].offset = max_offset;
|
||||||
|
+ parts[nrparts].name = names;
|
||||||
|
+ strcpy(names, BOARD_CONFIG_PART);
|
||||||
|
+ nrparts++;
|
||||||
|
+ }
|
||||||
|
ret = nrparts;
|
||||||
|
*pparts = parts;
|
||||||
|
out:
|
@ -0,0 +1,32 @@
|
|||||||
|
--- a/include/linux/mtd/nand.h
|
||||||
|
+++ b/include/linux/mtd/nand.h
|
||||||
|
@@ -574,6 +574,7 @@ struct platform_nand_chip {
|
||||||
|
int chip_delay;
|
||||||
|
unsigned int options;
|
||||||
|
const char **part_probe_types;
|
||||||
|
+ int (*chip_fixup)(struct mtd_info *mtd);
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
--- a/drivers/mtd/nand/plat_nand.c
|
||||||
|
+++ b/drivers/mtd/nand/plat_nand.c
|
||||||
|
@@ -71,7 +71,18 @@ static int __devinit plat_nand_probe(str
|
||||||
|
platform_set_drvdata(pdev, data);
|
||||||
|
|
||||||
|
/* Scan to find existance of the device */
|
||||||
|
- if (nand_scan(&data->mtd, 1)) {
|
||||||
|
+ if (nand_scan_ident(&data->mtd, 1)) {
|
||||||
|
+ res = -ENXIO;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pdata->chip.chip_fixup) {
|
||||||
|
+ res = pdata->chip.chip_fixup(&data->mtd);
|
||||||
|
+ if (res)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (nand_scan_tail(&data->mtd)) {
|
||||||
|
res = -ENXIO;
|
||||||
|
goto out;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
--- a/drivers/mtd/Kconfig
|
||||||
|
+++ b/drivers/mtd/Kconfig
|
||||||
|
@@ -180,6 +180,22 @@ config MTD_AR7_PARTS
|
||||||
|
---help---
|
||||||
|
TI AR7 partitioning support
|
||||||
|
|
||||||
|
+config MTD_MYLOADER_PARTS
|
||||||
|
+ tristate "MyLoader partition parsing"
|
||||||
|
+ depends on MTD_PARTITIONS && (ADM5120 || ATHEROS || ATHEROS_AR71XX)
|
||||||
|
+ ---help---
|
||||||
|
+ MyLoader is a bootloader which allows the user to define partitions
|
||||||
|
+ in flash devices, by putting a table in the second erase block
|
||||||
|
+ on the device, similar to a partition table. This table gives the
|
||||||
|
+ offsets and lengths of the user defined partitions.
|
||||||
|
+
|
||||||
|
+ If you need code which can detect and parse these tables, and
|
||||||
|
+ register MTD 'partitions' corresponding to each image detected,
|
||||||
|
+ enable this option.
|
||||||
|
+
|
||||||
|
+ You will still need the parsing functions to be called by the driver
|
||||||
|
+ for your particular device. It won't happen automatically.
|
||||||
|
+
|
||||||
|
comment "User Modules And Translation Layers"
|
||||||
|
|
||||||
|
config MTD_CHAR
|
||||||
|
--- a/drivers/mtd/Makefile
|
||||||
|
+++ b/drivers/mtd/Makefile
|
||||||
|
@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli
|
||||||
|
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||||
|
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
||||||
|
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||||
|
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
||||||
|
|
||||||
|
# 'Users' - code which presents functionality to userspace.
|
||||||
|
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/drivers/mtd/myloader.c
|
||||||
|
+++ b/drivers/mtd/myloader.c
|
||||||
|
@@ -19,7 +19,7 @@
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
#include <linux/mtd/partitions.h>
|
||||||
|
-#include <linux/byteorder/generic.h>
|
||||||
|
+#include <linux/byteorder.h>
|
||||||
|
#include <linux/myloader.h>
|
||||||
|
|
||||||
|
#define BLOCK_LEN_MIN 0x10000
|
@ -0,0 +1,12 @@
|
|||||||
|
--- a/drivers/mtd/nand/nand_ecc.c
|
||||||
|
+++ b/drivers/mtd/nand/nand_ecc.c
|
||||||
|
@@ -492,8 +492,7 @@ int nand_correct_data(struct mtd_info *m
|
||||||
|
if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
|
||||||
|
return 1; /* error in ecc data; no action needed */
|
||||||
|
|
||||||
|
- printk(KERN_ERR "uncorrectable error : ");
|
||||||
|
- return -1;
|
||||||
|
+ return -EBADMSG;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(nand_correct_data);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,108 @@
|
|||||||
|
--- a/include/linux/netfilter/xt_layer7.h
|
||||||
|
+++ b/include/linux/netfilter/xt_layer7.h
|
||||||
|
@@ -8,6 +8,7 @@ struct xt_layer7_info {
|
||||||
|
char protocol[MAX_PROTOCOL_LEN];
|
||||||
|
char pattern[MAX_PATTERN_LEN];
|
||||||
|
u_int8_t invert;
|
||||||
|
+ u_int8_t pkt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _XT_LAYER7_H */
|
||||||
|
--- a/net/netfilter/xt_layer7.c
|
||||||
|
+++ b/net/netfilter/xt_layer7.c
|
||||||
|
@@ -314,33 +314,35 @@ static int match_no_append(struct nf_con
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the new app data to the conntrack. Return number of bytes added. */
|
||||||
|
-static int add_data(struct nf_conn * master_conntrack,
|
||||||
|
- char * app_data, int appdatalen)
|
||||||
|
+static int add_datastr(char *target, int offset, char *app_data, int len)
|
||||||
|
{
|
||||||
|
int length = 0, i;
|
||||||
|
- int oldlength = master_conntrack->layer7.app_data_len;
|
||||||
|
-
|
||||||
|
- /* This is a fix for a race condition by Deti Fliegl. However, I'm not
|
||||||
|
- clear on whether the race condition exists or whether this really
|
||||||
|
- fixes it. I might just be being dense... Anyway, if it's not really
|
||||||
|
- a fix, all it does is waste a very small amount of time. */
|
||||||
|
- if(!master_conntrack->layer7.app_data) return 0;
|
||||||
|
+ if (!target) return 0;
|
||||||
|
|
||||||
|
/* Strip nulls. Make everything lower case (our regex lib doesn't
|
||||||
|
do case insensitivity). Add it to the end of the current data. */
|
||||||
|
- for(i = 0; i < maxdatalen-oldlength-1 &&
|
||||||
|
- i < appdatalen; i++) {
|
||||||
|
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
|
||||||
|
if(app_data[i] != '\0') {
|
||||||
|
/* the kernel version of tolower mungs 'upper ascii' */
|
||||||
|
- master_conntrack->layer7.app_data[length+oldlength] =
|
||||||
|
+ target[length+offset] =
|
||||||
|
isascii(app_data[i])?
|
||||||
|
tolower(app_data[i]) : app_data[i];
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ target[length+offset] = '\0';
|
||||||
|
+
|
||||||
|
+ return length;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* add the new app data to the conntrack. Return number of bytes added. */
|
||||||
|
+static int add_data(struct nf_conn * master_conntrack,
|
||||||
|
+ char * app_data, int appdatalen)
|
||||||
|
+{
|
||||||
|
+ int length;
|
||||||
|
|
||||||
|
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
|
||||||
|
- master_conntrack->layer7.app_data_len = length + oldlength;
|
||||||
|
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
|
||||||
|
+ master_conntrack->layer7.app_data_len += length;
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
@@ -428,7 +430,7 @@ match(const struct sk_buff *skbin,
|
||||||
|
const struct xt_layer7_info * info = matchinfo;
|
||||||
|
enum ip_conntrack_info master_ctinfo, ctinfo;
|
||||||
|
struct nf_conn *master_conntrack, *conntrack;
|
||||||
|
- unsigned char * app_data;
|
||||||
|
+ unsigned char *app_data, *tmp_data;
|
||||||
|
unsigned int pattern_result, appdatalen;
|
||||||
|
regexp * comppattern;
|
||||||
|
|
||||||
|
@@ -456,8 +458,8 @@ match(const struct sk_buff *skbin,
|
||||||
|
master_conntrack = master_ct(master_conntrack);
|
||||||
|
|
||||||
|
/* if we've classified it or seen too many packets */
|
||||||
|
- if(total_acct_packets(master_conntrack) > num_packets ||
|
||||||
|
- master_conntrack->layer7.app_proto) {
|
||||||
|
+ if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
|
||||||
|
+ master_conntrack->layer7.app_proto)) {
|
||||||
|
|
||||||
|
pattern_result = match_no_append(conntrack, master_conntrack,
|
||||||
|
ctinfo, master_ctinfo, info);
|
||||||
|
@@ -490,6 +492,25 @@ match(const struct sk_buff *skbin,
|
||||||
|
/* the return value gets checked later, when we're ready to use it */
|
||||||
|
comppattern = compile_and_cache(info->pattern, info->protocol);
|
||||||
|
|
||||||
|
+ if (info->pkt) {
|
||||||
|
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
|
||||||
|
+ if(!tmp_data){
|
||||||
|
+ if (net_ratelimit())
|
||||||
|
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
|
||||||
|
+ return info->invert;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ tmp_data[0] = '\0';
|
||||||
|
+ add_datastr(tmp_data, 0, app_data, appdatalen);
|
||||||
|
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
|
||||||
|
+
|
||||||
|
+ kfree(tmp_data);
|
||||||
|
+ tmp_data = NULL;
|
||||||
|
+ spin_unlock_bh(&l7_lock);
|
||||||
|
+
|
||||||
|
+ return (pattern_result ^ info->invert);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* On the first packet of a connection, allocate space for app data */
|
||||||
|
if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
|
||||||
|
!master_conntrack->layer7.app_data){
|
@ -0,0 +1,74 @@
|
|||||||
|
--- a/include/linux/netfilter_ipv4/ip_tables.h
|
||||||
|
+++ b/include/linux/netfilter_ipv4/ip_tables.h
|
||||||
|
@@ -62,6 +62,7 @@ struct ipt_ip {
|
||||||
|
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
|
||||||
|
#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
|
||||||
|
#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
|
||||||
|
+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
|
||||||
|
|
||||||
|
/* Values for "inv" field in struct ipt_ip. */
|
||||||
|
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
|
||||||
|
--- a/net/ipv4/netfilter/ip_tables.c
|
||||||
|
+++ b/net/ipv4/netfilter/ip_tables.c
|
||||||
|
@@ -87,6 +87,9 @@ ip_packet_match(const struct iphdr *ip,
|
||||||
|
|
||||||
|
#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
|
||||||
|
|
||||||
|
+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
|
||||||
|
IPT_INV_SRCIP)
|
||||||
|
|| FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
|
||||||
|
@@ -137,13 +140,32 @@ ip_packet_match(const struct iphdr *ip,
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#undef FWINV
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
-ip_checkentry(const struct ipt_ip *ip)
|
||||||
|
+ip_checkentry(struct ipt_ip *ip)
|
||||||
|
{
|
||||||
|
- if (ip->flags & ~IPT_F_MASK) {
|
||||||
|
+#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg)))
|
||||||
|
+
|
||||||
|
+ if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) ||
|
||||||
|
+ FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP))
|
||||||
|
+ goto has_match_rules;
|
||||||
|
+
|
||||||
|
+ if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0],
|
||||||
|
+ IPT_INV_VIA_IN) ||
|
||||||
|
+ FWINV(!!((const unsigned long *)ip->outiface_mask)[0],
|
||||||
|
+ IPT_INV_VIA_OUT))
|
||||||
|
+ goto has_match_rules;
|
||||||
|
+
|
||||||
|
+ if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG))
|
||||||
|
+ goto has_match_rules;
|
||||||
|
+
|
||||||
|
+ ip->flags |= IPT_F_NO_DEF_MATCH;
|
||||||
|
+
|
||||||
|
+has_match_rules:
|
||||||
|
+ if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) {
|
||||||
|
duprintf("Unknown flag bits set: %08X\n",
|
||||||
|
ip->flags & ~IPT_F_MASK);
|
||||||
|
return false;
|
||||||
|
@@ -153,6 +175,8 @@ ip_checkentry(const struct ipt_ip *ip)
|
||||||
|
ip->invflags & ~IPT_INV_MASK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#undef FWINV
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -200,7 +224,6 @@ unconditional(const struct ipt_ip *ip)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
-#undef FWINV
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
7688
target/linux/generic-2.6/patches-2.6.30/130-netfilter_ipset.patch
Normal file
7688
target/linux/generic-2.6/patches-2.6.30/130-netfilter_ipset.patch
Normal file
File diff suppressed because it is too large
Load Diff
914
target/linux/generic-2.6/patches-2.6.30/150-netfilter_imq.patch
Normal file
914
target/linux/generic-2.6/patches-2.6.30/150-netfilter_imq.patch
Normal file
@ -0,0 +1,914 @@
|
|||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/imq.c
|
||||||
|
@@ -0,0 +1,474 @@
|
||||||
|
+/*
|
||||||
|
+ * Pseudo-driver for the intermediate queue device.
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ *
|
||||||
|
+ * Authors: Patrick McHardy, <kaber@trash.net>
|
||||||
|
+ *
|
||||||
|
+ * The first version was written by Martin Devera, <devik@cdi.cz>
|
||||||
|
+ *
|
||||||
|
+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
|
||||||
|
+ * - Update patch to 2.4.21
|
||||||
|
+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
|
||||||
|
+ * - Fix "Dead-loop on netdevice imq"-issue
|
||||||
|
+ * Marcel Sebek <sebek64@post.cz>
|
||||||
|
+ * - Update to 2.6.2-rc1
|
||||||
|
+ *
|
||||||
|
+ * After some time of inactivity there is a group taking care
|
||||||
|
+ * of IMQ again: http://www.linuximq.net
|
||||||
|
+ *
|
||||||
|
+ *
|
||||||
|
+ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7
|
||||||
|
+ * including the following changes:
|
||||||
|
+ *
|
||||||
|
+ * - Correction of ipv6 support "+"s issue (Hasso Tepper)
|
||||||
|
+ * - Correction of imq_init_devs() issue that resulted in
|
||||||
|
+ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
|
||||||
|
+ * - Addition of functionality to choose number of IMQ devices
|
||||||
|
+ * during kernel config (Andre Correa)
|
||||||
|
+ * - Addition of functionality to choose how IMQ hooks on
|
||||||
|
+ * PRE and POSTROUTING (after or before NAT) (Andre Correa)
|
||||||
|
+ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
|
||||||
|
+ *
|
||||||
|
+ *
|
||||||
|
+ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
|
||||||
|
+ * released with almost no problems. 2.6.14-x was released
|
||||||
|
+ * with some important changes: nfcache was removed; After
|
||||||
|
+ * some weeks of trouble we figured out that some IMQ fields
|
||||||
|
+ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
|
||||||
|
+ * These functions are correctly patched by this new patch version.
|
||||||
|
+ *
|
||||||
|
+ * Thanks for all who helped to figure out all the problems with
|
||||||
|
+ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
|
||||||
|
+ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
|
||||||
|
+ * I didn't forget anybody). I apologize again for my lack of time.
|
||||||
|
+ *
|
||||||
|
+ *
|
||||||
|
+ * 2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead
|
||||||
|
+ * of qdisc_restart() and moved qdisc_run() to tasklet to avoid
|
||||||
|
+ * recursive locking. New initialization routines to fix 'rmmod' not
|
||||||
|
+ * working anymore. Used code from ifb.c. (Jussi Kivilinna)
|
||||||
|
+ *
|
||||||
|
+ * Also, many thanks to pablo Sebastian Greco for making the initial
|
||||||
|
+ * patch and to those who helped the testing.
|
||||||
|
+ *
|
||||||
|
+ * More info at: http://www.linuximq.net/ (Andre Correa)
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/moduleparam.h>
|
||||||
|
+#include <linux/skbuff.h>
|
||||||
|
+#include <linux/netdevice.h>
|
||||||
|
+#include <linux/rtnetlink.h>
|
||||||
|
+#include <linux/if_arp.h>
|
||||||
|
+#include <linux/netfilter.h>
|
||||||
|
+#include <linux/netfilter_ipv4.h>
|
||||||
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
+ #include <linux/netfilter_ipv6.h>
|
||||||
|
+#endif
|
||||||
|
+#include <linux/imq.h>
|
||||||
|
+#include <net/pkt_sched.h>
|
||||||
|
+#include <net/netfilter/nf_queue.h>
|
||||||
|
+
|
||||||
|
+struct imq_private {
|
||||||
|
+ struct tasklet_struct tasklet;
|
||||||
|
+ unsigned long tasklet_pending;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static nf_hookfn imq_nf_hook;
|
||||||
|
+
|
||||||
|
+static struct nf_hook_ops imq_ingress_ipv4 = {
|
||||||
|
+ .hook = imq_nf_hook,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .pf = PF_INET,
|
||||||
|
+ .hooknum = NF_INET_PRE_ROUTING,
|
||||||
|
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||||
|
+ .priority = NF_IP_PRI_MANGLE + 1
|
||||||
|
+#else
|
||||||
|
+ .priority = NF_IP_PRI_NAT_DST + 1
|
||||||
|
+#endif
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct nf_hook_ops imq_egress_ipv4 = {
|
||||||
|
+ .hook = imq_nf_hook,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .pf = PF_INET,
|
||||||
|
+ .hooknum = NF_INET_POST_ROUTING,
|
||||||
|
+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
|
||||||
|
+ .priority = NF_IP_PRI_LAST
|
||||||
|
+#else
|
||||||
|
+ .priority = NF_IP_PRI_NAT_SRC - 1
|
||||||
|
+#endif
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
+static struct nf_hook_ops imq_ingress_ipv6 = {
|
||||||
|
+ .hook = imq_nf_hook,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .pf = PF_INET6,
|
||||||
|
+ .hooknum = NF_INET_PRE_ROUTING,
|
||||||
|
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||||
|
+ .priority = NF_IP6_PRI_MANGLE + 1
|
||||||
|
+#else
|
||||||
|
+ .priority = NF_IP6_PRI_NAT_DST + 1
|
||||||
|
+#endif
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct nf_hook_ops imq_egress_ipv6 = {
|
||||||
|
+ .hook = imq_nf_hook,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .pf = PF_INET6,
|
||||||
|
+ .hooknum = NF_INET_POST_ROUTING,
|
||||||
|
+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
|
||||||
|
+ .priority = NF_IP6_PRI_LAST
|
||||||
|
+#else
|
||||||
|
+ .priority = NF_IP6_PRI_NAT_SRC - 1
|
||||||
|
+#endif
|
||||||
|
+};
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_IMQ_NUM_DEVS)
|
||||||
|
+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
|
||||||
|
+#else
|
||||||
|
+static unsigned int numdevs = IMQ_MAX_DEVS;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
|
||||||
|
+
|
||||||
|
+static struct net_device_stats *imq_get_stats(struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ return &dev->stats;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* called for packets kfree'd in qdiscs at places other than enqueue */
|
||||||
|
+static void imq_skb_destructor(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ struct nf_queue_entry *entry = skb->nf_queue_entry;
|
||||||
|
+
|
||||||
|
+ if (entry) {
|
||||||
|
+ if (entry->indev)
|
||||||
|
+ dev_put(entry->indev);
|
||||||
|
+ if (entry->outdev)
|
||||||
|
+ dev_put(entry->outdev);
|
||||||
|
+ kfree(entry);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ dev->stats.tx_bytes += skb->len;
|
||||||
|
+ dev->stats.tx_packets++;
|
||||||
|
+
|
||||||
|
+ skb->imq_flags = 0;
|
||||||
|
+ skb->destructor = NULL;
|
||||||
|
+
|
||||||
|
+ dev->trans_start = jiffies;
|
||||||
|
+ nf_reinject(skb->nf_queue_entry, NF_ACCEPT);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
|
||||||
|
+{
|
||||||
|
+ struct net_device *dev;
|
||||||
|
+ struct imq_private *priv;
|
||||||
|
+ struct sk_buff *skb2 = NULL;
|
||||||
|
+ struct Qdisc *q;
|
||||||
|
+ unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK;
|
||||||
|
+ int ret = -1;
|
||||||
|
+
|
||||||
|
+ if (index > numdevs)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ /* check for imq device by index from cache */
|
||||||
|
+ dev = imq_devs_cache[index];
|
||||||
|
+ if (!dev) {
|
||||||
|
+ char buf[8];
|
||||||
|
+
|
||||||
|
+ /* get device by name and cache result */
|
||||||
|
+ snprintf(buf, sizeof(buf), "imq%d", index);
|
||||||
|
+ dev = dev_get_by_name(&init_net, buf);
|
||||||
|
+ if (!dev) {
|
||||||
|
+ /* not found ?!*/
|
||||||
|
+ BUG();
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ imq_devs_cache[index] = dev;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ priv = netdev_priv(dev);
|
||||||
|
+ if (!(dev->flags & IFF_UP)) {
|
||||||
|
+ entry->skb->imq_flags = 0;
|
||||||
|
+ nf_reinject(entry, NF_ACCEPT);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ dev->last_rx = jiffies;
|
||||||
|
+
|
||||||
|
+ if (entry->skb->destructor) {
|
||||||
|
+ skb2 = entry->skb;
|
||||||
|
+ entry->skb = skb_clone(entry->skb, GFP_ATOMIC);
|
||||||
|
+ if (!entry->skb)
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ entry->skb->nf_queue_entry = entry;
|
||||||
|
+
|
||||||
|
+ dev->stats.rx_bytes += entry->skb->len;
|
||||||
|
+ dev->stats.rx_packets++;
|
||||||
|
+
|
||||||
|
+ spin_lock_bh(&dev->queue_lock);
|
||||||
|
+ q = dev->qdisc;
|
||||||
|
+ if (q->enqueue) {
|
||||||
|
+ q->enqueue(skb_get(entry->skb), q);
|
||||||
|
+ if (skb_shared(entry->skb)) {
|
||||||
|
+ entry->skb->destructor = imq_skb_destructor;
|
||||||
|
+ kfree_skb(entry->skb);
|
||||||
|
+ ret = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (!test_and_set_bit(1, &priv->tasklet_pending))
|
||||||
|
+ tasklet_schedule(&priv->tasklet);
|
||||||
|
+ spin_unlock_bh(&dev->queue_lock);
|
||||||
|
+
|
||||||
|
+ if (skb2)
|
||||||
|
+ kfree_skb(ret ? entry->skb : skb2);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct nf_queue_handler nfqh = {
|
||||||
|
+ .name = "imq",
|
||||||
|
+ .outfn = imq_nf_queue,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static void qdisc_run_tasklet(unsigned long arg)
|
||||||
|
+{
|
||||||
|
+ struct net_device *dev = (struct net_device *)arg;
|
||||||
|
+ struct imq_private *priv = netdev_priv(dev);
|
||||||
|
+
|
||||||
|
+ spin_lock(&dev->queue_lock);
|
||||||
|
+ qdisc_run(dev);
|
||||||
|
+ clear_bit(1, &priv->tasklet_pending);
|
||||||
|
+ spin_unlock(&dev->queue_lock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
|
||||||
|
+ const struct net_device *indev,
|
||||||
|
+ const struct net_device *outdev,
|
||||||
|
+ int (*okfn)(struct sk_buff *))
|
||||||
|
+{
|
||||||
|
+ if (pskb->imq_flags & IMQ_F_ENQUEUE)
|
||||||
|
+ return NF_QUEUE;
|
||||||
|
+
|
||||||
|
+ return NF_ACCEPT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int imq_close(struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct imq_private *priv = netdev_priv(dev);
|
||||||
|
+
|
||||||
|
+ tasklet_kill(&priv->tasklet);
|
||||||
|
+ netif_stop_queue(dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int imq_open(struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct imq_private *priv = netdev_priv(dev);
|
||||||
|
+
|
||||||
|
+ tasklet_init(&priv->tasklet, qdisc_run_tasklet, (unsigned long)dev);
|
||||||
|
+ netif_start_queue(dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void imq_setup(struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ dev->hard_start_xmit = imq_dev_xmit;
|
||||||
|
+ dev->open = imq_open;
|
||||||
|
+ dev->get_stats = imq_get_stats;
|
||||||
|
+ dev->stop = imq_close;
|
||||||
|
+ dev->type = ARPHRD_VOID;
|
||||||
|
+ dev->mtu = 16000;
|
||||||
|
+ dev->tx_queue_len = 11000;
|
||||||
|
+ dev->flags = IFF_NOARP;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct rtnl_link_ops imq_link_ops __read_mostly = {
|
||||||
|
+ .kind = "imq",
|
||||||
|
+ .priv_size = sizeof(struct imq_private),
|
||||||
|
+ .setup = imq_setup,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init imq_init_hooks(void)
|
||||||
|
+{
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = nf_register_queue_handler(PF_INET, &nfqh);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err1;
|
||||||
|
+
|
||||||
|
+ err = nf_register_hook(&imq_ingress_ipv4);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err2;
|
||||||
|
+
|
||||||
|
+ err = nf_register_hook(&imq_egress_ipv4);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err3;
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
+ err = nf_register_queue_handler(PF_INET6, &nfqh);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err4;
|
||||||
|
+
|
||||||
|
+ err = nf_register_hook(&imq_ingress_ipv6);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err5;
|
||||||
|
+
|
||||||
|
+ err = nf_register_hook(&imq_egress_ipv6);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err6;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
+err6:
|
||||||
|
+ nf_unregister_hook(&imq_ingress_ipv6);
|
||||||
|
+err5:
|
||||||
|
+ nf_unregister_queue_handler(PF_INET6, &nfqh);
|
||||||
|
+err4:
|
||||||
|
+ nf_unregister_hook(&imq_egress_ipv4);
|
||||||
|
+#endif
|
||||||
|
+err3:
|
||||||
|
+ nf_unregister_hook(&imq_ingress_ipv4);
|
||||||
|
+err2:
|
||||||
|
+ nf_unregister_queue_handler(PF_INET, &nfqh);
|
||||||
|
+err1:
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init imq_init_one(int index)
|
||||||
|
+{
|
||||||
|
+ struct net_device *dev;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ dev = alloc_netdev(sizeof(struct imq_private), "imq%d", imq_setup);
|
||||||
|
+ if (!dev)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ ret = dev_alloc_name(dev, dev->name);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ dev->rtnl_link_ops = &imq_link_ops;
|
||||||
|
+ ret = register_netdevice(dev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+fail:
|
||||||
|
+ free_netdev(dev);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init imq_init_devs(void)
|
||||||
|
+{
|
||||||
|
+ int err, i;
|
||||||
|
+
|
||||||
|
+ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
|
||||||
|
+ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
|
||||||
|
+ IMQ_MAX_DEVS);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rtnl_lock();
|
||||||
|
+ err = __rtnl_link_register(&imq_link_ops);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < numdevs && !err; i++)
|
||||||
|
+ err = imq_init_one(i);
|
||||||
|
+
|
||||||
|
+ if (err) {
|
||||||
|
+ __rtnl_link_unregister(&imq_link_ops);
|
||||||
|
+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
|
||||||
|
+ }
|
||||||
|
+ rtnl_unlock();
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init imq_init_module(void)
|
||||||
|
+{
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = imq_init_devs();
|
||||||
|
+ if (err) {
|
||||||
|
+ printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ err = imq_init_hooks();
|
||||||
|
+ if (err) {
|
||||||
|
+ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
|
||||||
|
+ rtnl_link_unregister(&imq_link_ops);
|
||||||
|
+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printk(KERN_INFO "IMQ driver loaded successfully.\n");
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||||
|
+ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
|
||||||
|
+#else
|
||||||
|
+ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
|
||||||
|
+#endif
|
||||||
|
+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||||
|
+ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
|
||||||
|
+#else
|
||||||
|
+ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit imq_unhook(void)
|
||||||
|
+{
|
||||||
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
+ nf_unregister_hook(&imq_ingress_ipv6);
|
||||||
|
+ nf_unregister_hook(&imq_egress_ipv6);
|
||||||
|
+ nf_unregister_queue_handler(PF_INET6, &nfqh);
|
||||||
|
+#endif
|
||||||
|
+ nf_unregister_hook(&imq_ingress_ipv4);
|
||||||
|
+ nf_unregister_hook(&imq_egress_ipv4);
|
||||||
|
+ nf_unregister_queue_handler(PF_INET, &nfqh);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit imq_cleanup_devs(void)
|
||||||
|
+{
|
||||||
|
+ rtnl_link_unregister(&imq_link_ops);
|
||||||
|
+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit imq_exit_module(void)
|
||||||
|
+{
|
||||||
|
+ imq_unhook();
|
||||||
|
+ imq_cleanup_devs();
|
||||||
|
+ printk(KERN_INFO "IMQ driver unloaded successfully.\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+module_init(imq_init_module);
|
||||||
|
+module_exit(imq_exit_module);
|
||||||
|
+
|
||||||
|
+module_param(numdevs, int, 0);
|
||||||
|
+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
|
||||||
|
+ "be created)");
|
||||||
|
+MODULE_AUTHOR("http://www.linuximq.net");
|
||||||
|
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
|
||||||
|
+ "http://www.linuximq.net/ for more information.");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+MODULE_ALIAS_RTNL_LINK("imq");
|
||||||
|
+
|
||||||
|
--- a/drivers/net/Kconfig
|
||||||
|
+++ b/drivers/net/Kconfig
|
||||||
|
@@ -119,6 +119,129 @@ config EQUALIZER
|
||||||
|
To compile this driver as a module, choose M here: the module
|
||||||
|
will be called eql. If unsure, say N.
|
||||||
|
|
||||||
|
+config IMQ
|
||||||
|
+ tristate "IMQ (intermediate queueing device) support"
|
||||||
|
+ depends on NETDEVICES && NETFILTER
|
||||||
|
+ ---help---
|
||||||
|
+ The IMQ device(s) is used as placeholder for QoS queueing
|
||||||
|
+ disciplines. Every packet entering/leaving the IP stack can be
|
||||||
|
+ directed through the IMQ device where it's enqueued/dequeued to the
|
||||||
|
+ attached qdisc. This allows you to treat network devices as classes
|
||||||
|
+ and distribute bandwidth among them. Iptables is used to specify
|
||||||
|
+ through which IMQ device, if any, packets travel.
|
||||||
|
+
|
||||||
|
+ More information at: http://www.linuximq.net/
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the module
|
||||||
|
+ will be called imq. If unsure, say N.
|
||||||
|
+
|
||||||
|
+choice
|
||||||
|
+ prompt "IMQ behavior (PRE/POSTROUTING)"
|
||||||
|
+ depends on IMQ
|
||||||
|
+ default IMQ_BEHAVIOR_AB
|
||||||
|
+ help
|
||||||
|
+
|
||||||
|
+ This settings defines how IMQ behaves in respect to its
|
||||||
|
+ hooking in PREROUTING and POSTROUTING.
|
||||||
|
+
|
||||||
|
+ IMQ can work in any of the following ways:
|
||||||
|
+
|
||||||
|
+ PREROUTING | POSTROUTING
|
||||||
|
+ -----------------|-------------------
|
||||||
|
+ #1 After NAT | After NAT
|
||||||
|
+ #2 After NAT | Before NAT
|
||||||
|
+ #3 Before NAT | After NAT
|
||||||
|
+ #4 Before NAT | Before NAT
|
||||||
|
+
|
||||||
|
+ The default behavior is to hook before NAT on PREROUTING
|
||||||
|
+ and after NAT on POSTROUTING (#3).
|
||||||
|
+
|
||||||
|
+ This settings are specially usefull when trying to use IMQ
|
||||||
|
+ to shape NATed clients.
|
||||||
|
+
|
||||||
|
+ More information can be found at: www.linuximq.net
|
||||||
|
+
|
||||||
|
+ If not sure leave the default settings alone.
|
||||||
|
+
|
||||||
|
+config IMQ_BEHAVIOR_AA
|
||||||
|
+ bool "IMQ AA"
|
||||||
|
+ help
|
||||||
|
+ This settings defines how IMQ behaves in respect to its
|
||||||
|
+ hooking in PREROUTING and POSTROUTING.
|
||||||
|
+
|
||||||
|
+ Choosing this option will make IMQ hook like this:
|
||||||
|
+
|
||||||
|
+ PREROUTING: After NAT
|
||||||
|
+ POSTROUTING: After NAT
|
||||||
|
+
|
||||||
|
+ More information can be found at: www.linuximq.net
|
||||||
|
+
|
||||||
|
+ If not sure leave the default settings alone.
|
||||||
|
+
|
||||||
|
+config IMQ_BEHAVIOR_AB
|
||||||
|
+ bool "IMQ AB"
|
||||||
|
+ help
|
||||||
|
+ This settings defines how IMQ behaves in respect to its
|
||||||
|
+ hooking in PREROUTING and POSTROUTING.
|
||||||
|
+
|
||||||
|
+ Choosing this option will make IMQ hook like this:
|
||||||
|
+
|
||||||
|
+ PREROUTING: After NAT
|
||||||
|
+ POSTROUTING: Before NAT
|
||||||
|
+
|
||||||
|
+ More information can be found at: www.linuximq.net
|
||||||
|
+
|
||||||
|
+ If not sure leave the default settings alone.
|
||||||
|
+
|
||||||
|
+config IMQ_BEHAVIOR_BA
|
||||||
|
+ bool "IMQ BA"
|
||||||
|
+ help
|
||||||
|
+ This settings defines how IMQ behaves in respect to its
|
||||||
|
+ hooking in PREROUTING and POSTROUTING.
|
||||||
|
+
|
||||||
|
+ Choosing this option will make IMQ hook like this:
|
||||||
|
+
|
||||||
|
+ PREROUTING: Before NAT
|
||||||
|
+ POSTROUTING: After NAT
|
||||||
|
+
|
||||||
|
+ More information can be found at: www.linuximq.net
|
||||||
|
+
|
||||||
|
+ If not sure leave the default settings alone.
|
||||||
|
+
|
||||||
|
+config IMQ_BEHAVIOR_BB
|
||||||
|
+ bool "IMQ BB"
|
||||||
|
+ help
|
||||||
|
+ This settings defines how IMQ behaves in respect to its
|
||||||
|
+ hooking in PREROUTING and POSTROUTING.
|
||||||
|
+
|
||||||
|
+ Choosing this option will make IMQ hook like this:
|
||||||
|
+
|
||||||
|
+ PREROUTING: Before NAT
|
||||||
|
+ POSTROUTING: Before NAT
|
||||||
|
+
|
||||||
|
+ More information can be found at: www.linuximq.net
|
||||||
|
+
|
||||||
|
+ If not sure leave the default settings alone.
|
||||||
|
+
|
||||||
|
+endchoice
|
||||||
|
+
|
||||||
|
+config IMQ_NUM_DEVS
|
||||||
|
+
|
||||||
|
+ int "Number of IMQ devices"
|
||||||
|
+ range 2 16
|
||||||
|
+ depends on IMQ
|
||||||
|
+ default "16"
|
||||||
|
+ help
|
||||||
|
+
|
||||||
|
+ This settings defines how many IMQ devices will be
|
||||||
|
+ created.
|
||||||
|
+
|
||||||
|
+ The default value is 16.
|
||||||
|
+
|
||||||
|
+ More information can be found at: www.linuximq.net
|
||||||
|
+
|
||||||
|
+ If not sure leave the default settings alone.
|
||||||
|
+
|
||||||
|
config TUN
|
||||||
|
tristate "Universal TUN/TAP device driver support"
|
||||||
|
select CRC32
|
||||||
|
--- a/drivers/net/Makefile
|
||||||
|
+++ b/drivers/net/Makefile
|
||||||
|
@@ -151,6 +151,7 @@ obj-$(CONFIG_SLHC) += slhc.o
|
||||||
|
obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_DUMMY) += dummy.o
|
||||||
|
+obj-$(CONFIG_IMQ) += imq.o
|
||||||
|
obj-$(CONFIG_IFB) += ifb.o
|
||||||
|
obj-$(CONFIG_MACVLAN) += macvlan.o
|
||||||
|
obj-$(CONFIG_DE600) += de600.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/linux/imq.h
|
||||||
|
@@ -0,0 +1,9 @@
|
||||||
|
+#ifndef _IMQ_H
|
||||||
|
+#define _IMQ_H
|
||||||
|
+
|
||||||
|
+#define IMQ_MAX_DEVS 16
|
||||||
|
+
|
||||||
|
+#define IMQ_F_IFMASK 0x7f
|
||||||
|
+#define IMQ_F_ENQUEUE 0x80
|
||||||
|
+
|
||||||
|
+#endif /* _IMQ_H */
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
|
||||||
|
@@ -0,0 +1,8 @@
|
||||||
|
+#ifndef _IPT_IMQ_H
|
||||||
|
+#define _IPT_IMQ_H
|
||||||
|
+
|
||||||
|
+struct ipt_imq_info {
|
||||||
|
+ unsigned int todev; /* target imq device */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#endif /* _IPT_IMQ_H */
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
|
||||||
|
@@ -0,0 +1,8 @@
|
||||||
|
+#ifndef _IP6T_IMQ_H
|
||||||
|
+#define _IP6T_IMQ_H
|
||||||
|
+
|
||||||
|
+struct ip6t_imq_info {
|
||||||
|
+ unsigned int todev; /* target imq device */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#endif /* _IP6T_IMQ_H */
|
||||||
|
--- a/include/linux/skbuff.h
|
||||||
|
+++ b/include/linux/skbuff.h
|
||||||
|
@@ -363,6 +363,10 @@ struct sk_buff {
|
||||||
|
struct nf_conntrack *nfct;
|
||||||
|
struct sk_buff *nfct_reasm;
|
||||||
|
#endif
|
||||||
|
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||||
|
+ unsigned char imq_flags;
|
||||||
|
+ struct nf_queue_entry *nf_queue_entry;
|
||||||
|
+#endif
|
||||||
|
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||||
|
struct nf_bridge_info *nf_bridge;
|
||||||
|
#endif
|
||||||
|
@@ -1931,6 +1935,10 @@ static inline void __nf_copy(struct sk_b
|
||||||
|
dst->nfct_reasm = src->nfct_reasm;
|
||||||
|
nf_conntrack_get_reasm(src->nfct_reasm);
|
||||||
|
#endif
|
||||||
|
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||||
|
+ dst->imq_flags = src->imq_flags;
|
||||||
|
+ dst->nf_queue_entry = src->nf_queue_entry;
|
||||||
|
+#endif
|
||||||
|
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||||
|
dst->nf_bridge = src->nf_bridge;
|
||||||
|
nf_bridge_get(src->nf_bridge);
|
||||||
|
--- a/net/core/dev.c
|
||||||
|
+++ b/net/core/dev.c
|
||||||
|
@@ -96,6 +96,9 @@
|
||||||
|
#include <net/net_namespace.h>
|
||||||
|
#include <net/sock.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||||
|
+#include <linux/imq.h>
|
||||||
|
+#endif
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/stat.h>
|
||||||
|
@@ -1673,7 +1676,11 @@ int dev_hard_start_xmit(struct sk_buff *
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (likely(!skb->next)) {
|
||||||
|
- if (!list_empty(&ptype_all))
|
||||||
|
+ if (!list_empty(&ptype_all)
|
||||||
|
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||||
|
+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
|
||||||
|
+#endif
|
||||||
|
+ )
|
||||||
|
dev_queue_xmit_nit(skb, dev);
|
||||||
|
|
||||||
|
if (netif_needs_gso(dev, skb)) {
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/net/ipv4/netfilter/ipt_IMQ.c
|
||||||
|
@@ -0,0 +1,69 @@
|
||||||
|
+/*
|
||||||
|
+ * This target marks packets to be enqueued to an imq device
|
||||||
|
+ */
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/skbuff.h>
|
||||||
|
+#include <linux/netfilter_ipv4/ip_tables.h>
|
||||||
|
+#include <linux/netfilter_ipv4/ipt_IMQ.h>
|
||||||
|
+#include <linux/imq.h>
|
||||||
|
+
|
||||||
|
+static unsigned int imq_target(struct sk_buff *pskb,
|
||||||
|
+ const struct net_device *in,
|
||||||
|
+ const struct net_device *out,
|
||||||
|
+ unsigned int hooknum,
|
||||||
|
+ const struct xt_target *target,
|
||||||
|
+ const void *targinfo)
|
||||||
|
+{
|
||||||
|
+ struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo;
|
||||||
|
+
|
||||||
|
+ pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE;
|
||||||
|
+
|
||||||
|
+ return XT_CONTINUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imq_checkentry(const char *tablename,
|
||||||
|
+ const void *e,
|
||||||
|
+ const struct xt_target *target,
|
||||||
|
+ void *targinfo,
|
||||||
|
+ unsigned int hook_mask)
|
||||||
|
+{
|
||||||
|
+ struct ipt_imq_info *mr;
|
||||||
|
+
|
||||||
|
+ mr = (struct ipt_imq_info *)targinfo;
|
||||||
|
+
|
||||||
|
+ if (mr->todev > IMQ_MAX_DEVS) {
|
||||||
|
+ printk(KERN_WARNING
|
||||||
|
+ "IMQ: invalid device specified, highest is %u\n",
|
||||||
|
+ IMQ_MAX_DEVS);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct xt_target ipt_imq_reg = {
|
||||||
|
+ .name = "IMQ",
|
||||||
|
+ .family = AF_INET,
|
||||||
|
+ .target = imq_target,
|
||||||
|
+ .targetsize = sizeof(struct ipt_imq_info),
|
||||||
|
+ .checkentry = imq_checkentry,
|
||||||
|
+ .me = THIS_MODULE,
|
||||||
|
+ .table = "mangle"
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init init(void)
|
||||||
|
+{
|
||||||
|
+ return xt_register_target(&ipt_imq_reg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit fini(void)
|
||||||
|
+{
|
||||||
|
+ xt_unregister_target(&ipt_imq_reg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+module_init(init);
|
||||||
|
+module_exit(fini);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("http://www.linuximq.net");
|
||||||
|
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
--- a/net/ipv4/netfilter/Kconfig
|
||||||
|
+++ b/net/ipv4/netfilter/Kconfig
|
||||||
|
@@ -112,6 +112,17 @@ config IP_NF_FILTER
|
||||||
|
|
||||||
|
To compile it as a module, choose M here. If unsure, say N.
|
||||||
|
|
||||||
|
+config IP_NF_TARGET_IMQ
|
||||||
|
+ tristate "IMQ target support"
|
||||||
|
+ depends on IP_NF_MANGLE && IMQ
|
||||||
|
+ help
|
||||||
|
+ This option adds a `IMQ' target which is used to specify if and
|
||||||
|
+ to which IMQ device packets should get enqueued/dequeued.
|
||||||
|
+
|
||||||
|
+ For more information visit: http://www.linuximq.net/
|
||||||
|
+
|
||||||
|
+ To compile it as a module, choose M here. If unsure, say N.
|
||||||
|
+
|
||||||
|
config IP_NF_TARGET_REJECT
|
||||||
|
tristate "REJECT target support"
|
||||||
|
depends on IP_NF_FILTER
|
||||||
|
--- a/net/ipv4/netfilter/Makefile
|
||||||
|
+++ b/net/ipv4/netfilter/Makefile
|
||||||
|
@@ -57,6 +57,7 @@ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set
|
||||||
|
obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
|
||||||
|
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
|
||||||
|
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
|
||||||
|
+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
|
||||||
|
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
|
||||||
|
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
|
||||||
|
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/net/ipv6/netfilter/ip6t_IMQ.c
|
||||||
|
@@ -0,0 +1,69 @@
|
||||||
|
+/*
|
||||||
|
+ * This target marks packets to be enqueued to an imq device
|
||||||
|
+ */
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/skbuff.h>
|
||||||
|
+#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||||
|
+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
|
||||||
|
+#include <linux/imq.h>
|
||||||
|
+
|
||||||
|
+static unsigned int imq_target(struct sk_buff *pskb,
|
||||||
|
+ const struct net_device *in,
|
||||||
|
+ const struct net_device *out,
|
||||||
|
+ unsigned int hooknum,
|
||||||
|
+ const struct xt_target *target,
|
||||||
|
+ const void *targinfo)
|
||||||
|
+{
|
||||||
|
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info *)targinfo;
|
||||||
|
+
|
||||||
|
+ pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE;
|
||||||
|
+
|
||||||
|
+ return XT_CONTINUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool imq_checkentry(const char *tablename,
|
||||||
|
+ const void *entry,
|
||||||
|
+ const struct xt_target *target,
|
||||||
|
+ void *targinfo,
|
||||||
|
+ unsigned int hook_mask)
|
||||||
|
+{
|
||||||
|
+ struct ip6t_imq_info *mr;
|
||||||
|
+
|
||||||
|
+ mr = (struct ip6t_imq_info *)targinfo;
|
||||||
|
+
|
||||||
|
+ if (mr->todev > IMQ_MAX_DEVS) {
|
||||||
|
+ printk(KERN_WARNING
|
||||||
|
+ "IMQ: invalid device specified, highest is %u\n",
|
||||||
|
+ IMQ_MAX_DEVS);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct xt_target ip6t_imq_reg = {
|
||||||
|
+ .name = "IMQ",
|
||||||
|
+ .family = AF_INET6,
|
||||||
|
+ .target = imq_target,
|
||||||
|
+ .targetsize = sizeof(struct ip6t_imq_info),
|
||||||
|
+ .table = "mangle",
|
||||||
|
+ .checkentry = imq_checkentry,
|
||||||
|
+ .me = THIS_MODULE
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init init(void)
|
||||||
|
+{
|
||||||
|
+ return xt_register_target(&ip6t_imq_reg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit fini(void)
|
||||||
|
+{
|
||||||
|
+ xt_unregister_target(&ip6t_imq_reg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+module_init(init);
|
||||||
|
+module_exit(fini);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("http://www.linuximq.net");
|
||||||
|
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
--- a/net/ipv6/netfilter/Kconfig
|
||||||
|
+++ b/net/ipv6/netfilter/Kconfig
|
||||||
|
@@ -129,6 +129,15 @@ config IP6_NF_MATCH_RT
|
||||||
|
|
||||||
|
To compile it as a module, choose M here. If unsure, say N.
|
||||||
|
|
||||||
|
+config IP6_NF_TARGET_IMQ
|
||||||
|
+ tristate "IMQ target support"
|
||||||
|
+ depends on IP6_NF_MANGLE && IMQ
|
||||||
|
+ help
|
||||||
|
+ This option adds a `IMQ' target which is used to specify if and
|
||||||
|
+ to which imq device packets should get enqueued/dequeued.
|
||||||
|
+
|
||||||
|
+ To compile it as a module, choose M here. If unsure, say N.
|
||||||
|
+
|
||||||
|
# The targets
|
||||||
|
config IP6_NF_TARGET_HL
|
||||||
|
tristate '"HL" hoplimit target support'
|
||||||
|
--- a/net/ipv6/netfilter/Makefile
|
||||||
|
+++ b/net/ipv6/netfilter/Makefile
|
||||||
|
@@ -6,6 +6,7 @@
|
||||||
|
obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
|
||||||
|
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
|
||||||
|
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
|
||||||
|
+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
|
||||||
|
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
|
||||||
|
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
|
||||||
|
obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
|
||||||
|
--- a/net/sched/sch_generic.c
|
||||||
|
+++ b/net/sched/sch_generic.c
|
||||||
|
@@ -195,6 +195,7 @@ void __qdisc_run(struct Qdisc *q)
|
||||||
|
|
||||||
|
clear_bit(__QDISC_STATE_RUNNING, &q->state);
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL(__qdisc_run);
|
||||||
|
|
||||||
|
static void dev_watchdog(unsigned long arg)
|
||||||
|
{
|
@ -0,0 +1,114 @@
|
|||||||
|
--- a/drivers/net/imq.c
|
||||||
|
+++ b/drivers/net/imq.c
|
||||||
|
@@ -178,10 +178,11 @@ static int imq_nf_queue(struct nf_queue_
|
||||||
|
struct sk_buff *skb2 = NULL;
|
||||||
|
struct Qdisc *q;
|
||||||
|
unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK;
|
||||||
|
- int ret = -1;
|
||||||
|
+ struct netdev_queue *txq;
|
||||||
|
+ int ret = -EINVAL;
|
||||||
|
|
||||||
|
if (index > numdevs)
|
||||||
|
- return -1;
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
/* check for imq device by index from cache */
|
||||||
|
dev = imq_devs_cache[index];
|
||||||
|
@@ -194,7 +195,7 @@ static int imq_nf_queue(struct nf_queue_
|
||||||
|
if (!dev) {
|
||||||
|
/* not found ?!*/
|
||||||
|
BUG();
|
||||||
|
- return -1;
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
imq_devs_cache[index] = dev;
|
||||||
|
@@ -212,17 +213,19 @@ static int imq_nf_queue(struct nf_queue_
|
||||||
|
skb2 = entry->skb;
|
||||||
|
entry->skb = skb_clone(entry->skb, GFP_ATOMIC);
|
||||||
|
if (!entry->skb)
|
||||||
|
- return -1;
|
||||||
|
+ return -ENOMEM;
|
||||||
|
}
|
||||||
|
entry->skb->nf_queue_entry = entry;
|
||||||
|
|
||||||
|
dev->stats.rx_bytes += entry->skb->len;
|
||||||
|
dev->stats.rx_packets++;
|
||||||
|
|
||||||
|
- spin_lock_bh(&dev->queue_lock);
|
||||||
|
- q = dev->qdisc;
|
||||||
|
+ txq = netdev_get_tx_queue(dev, 0);
|
||||||
|
+ __netif_tx_lock_bh(txq);
|
||||||
|
+ q = txq->qdisc;
|
||||||
|
+
|
||||||
|
if (q->enqueue) {
|
||||||
|
- q->enqueue(skb_get(entry->skb), q);
|
||||||
|
+ qdisc_enqueue_root(skb_get(entry->skb), q);
|
||||||
|
if (skb_shared(entry->skb)) {
|
||||||
|
entry->skb->destructor = imq_skb_destructor;
|
||||||
|
kfree_skb(entry->skb);
|
||||||
|
@@ -231,7 +234,7 @@ static int imq_nf_queue(struct nf_queue_
|
||||||
|
}
|
||||||
|
if (!test_and_set_bit(1, &priv->tasklet_pending))
|
||||||
|
tasklet_schedule(&priv->tasklet);
|
||||||
|
- spin_unlock_bh(&dev->queue_lock);
|
||||||
|
+ __netif_tx_unlock_bh(txq);
|
||||||
|
|
||||||
|
if (skb2)
|
||||||
|
kfree_skb(ret ? entry->skb : skb2);
|
||||||
|
@@ -248,11 +251,13 @@ static void qdisc_run_tasklet(unsigned l
|
||||||
|
{
|
||||||
|
struct net_device *dev = (struct net_device *)arg;
|
||||||
|
struct imq_private *priv = netdev_priv(dev);
|
||||||
|
+ struct netdev_queue *txq;
|
||||||
|
|
||||||
|
- spin_lock(&dev->queue_lock);
|
||||||
|
- qdisc_run(dev);
|
||||||
|
+ netif_tx_lock(dev);
|
||||||
|
+ txq = netdev_get_tx_queue(dev, 0);
|
||||||
|
+ qdisc_run(txq->qdisc);
|
||||||
|
clear_bit(1, &priv->tasklet_pending);
|
||||||
|
- spin_unlock(&dev->queue_lock);
|
||||||
|
+ netif_tx_unlock(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
|
||||||
|
--- a/net/ipv4/netfilter/ipt_IMQ.c
|
||||||
|
+++ b/net/ipv4/netfilter/ipt_IMQ.c
|
||||||
|
@@ -7,29 +7,23 @@
|
||||||
|
#include <linux/netfilter_ipv4/ipt_IMQ.h>
|
||||||
|
#include <linux/imq.h>
|
||||||
|
|
||||||
|
-static unsigned int imq_target(struct sk_buff *pskb,
|
||||||
|
- const struct net_device *in,
|
||||||
|
- const struct net_device *out,
|
||||||
|
- unsigned int hooknum,
|
||||||
|
- const struct xt_target *target,
|
||||||
|
- const void *targinfo)
|
||||||
|
+static unsigned int
|
||||||
|
+imq_target(struct sk_buff *pskb,
|
||||||
|
+ const struct xt_target_param *par)
|
||||||
|
{
|
||||||
|
- struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo;
|
||||||
|
+ struct ipt_imq_info *mr = (struct ipt_imq_info *)par->targinfo;
|
||||||
|
|
||||||
|
pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE;
|
||||||
|
|
||||||
|
return XT_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool imq_checkentry(const char *tablename,
|
||||||
|
- const void *e,
|
||||||
|
- const struct xt_target *target,
|
||||||
|
- void *targinfo,
|
||||||
|
- unsigned int hook_mask)
|
||||||
|
+static bool
|
||||||
|
+imq_checkentry(const struct xt_tgchk_param *par)
|
||||||
|
{
|
||||||
|
struct ipt_imq_info *mr;
|
||||||
|
|
||||||
|
- mr = (struct ipt_imq_info *)targinfo;
|
||||||
|
+ mr = (struct ipt_imq_info *)par->targinfo;
|
||||||
|
|
||||||
|
if (mr->todev > IMQ_MAX_DEVS) {
|
||||||
|
printk(KERN_WARNING
|
@ -0,0 +1,18 @@
|
|||||||
|
--- a/net/netfilter/Kconfig
|
||||||
|
+++ b/net/netfilter/Kconfig
|
||||||
|
@@ -160,7 +160,6 @@ config NF_CONNTRACK_FTP
|
||||||
|
|
||||||
|
config NF_CONNTRACK_H323
|
||||||
|
tristate "H.323 protocol support"
|
||||||
|
- depends on (IPV6 || IPV6=n)
|
||||||
|
depends on NETFILTER_ADVANCED
|
||||||
|
help
|
||||||
|
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
|
||||||
|
@@ -493,7 +492,6 @@ config NETFILTER_XT_TARGET_SECMARK
|
||||||
|
|
||||||
|
config NETFILTER_XT_TARGET_TCPMSS
|
||||||
|
tristate '"TCPMSS" target support'
|
||||||
|
- depends on (IPV6 || IPV6=n)
|
||||||
|
default m if NETFILTER_ADVANCED=n
|
||||||
|
---help---
|
||||||
|
This option adds a `TCPMSS' target, which allows you to alter the
|
1366
target/linux/generic-2.6/patches-2.6.30/190-netfilter_rtsp.patch
Normal file
1366
target/linux/generic-2.6/patches-2.6.30/190-netfilter_rtsp.patch
Normal file
File diff suppressed because it is too large
Load Diff
795
target/linux/generic-2.6/patches-2.6.30/200-sched_esfq.patch
Normal file
795
target/linux/generic-2.6/patches-2.6.30/200-sched_esfq.patch
Normal file
@ -0,0 +1,795 @@
|
|||||||
|
--- a/include/linux/pkt_sched.h
|
||||||
|
+++ b/include/linux/pkt_sched.h
|
||||||
|
@@ -182,8 +182,37 @@ struct tc_sfq_xstats
|
||||||
|
*
|
||||||
|
* The only reason for this is efficiency, it is possible
|
||||||
|
* to change these parameters in compile time.
|
||||||
|
+ *
|
||||||
|
+ * If you need to play with these values, use esfq instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+/* ESFQ section */
|
||||||
|
+
|
||||||
|
+enum
|
||||||
|
+{
|
||||||
|
+ /* traditional */
|
||||||
|
+ TCA_SFQ_HASH_CLASSIC,
|
||||||
|
+ TCA_SFQ_HASH_DST,
|
||||||
|
+ TCA_SFQ_HASH_SRC,
|
||||||
|
+ TCA_SFQ_HASH_FWMARK,
|
||||||
|
+ /* conntrack */
|
||||||
|
+ TCA_SFQ_HASH_CTORIGDST,
|
||||||
|
+ TCA_SFQ_HASH_CTORIGSRC,
|
||||||
|
+ TCA_SFQ_HASH_CTREPLDST,
|
||||||
|
+ TCA_SFQ_HASH_CTREPLSRC,
|
||||||
|
+ TCA_SFQ_HASH_CTNATCHG,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct tc_esfq_qopt
|
||||||
|
+{
|
||||||
|
+ unsigned quantum; /* Bytes per round allocated to flow */
|
||||||
|
+ int perturb_period; /* Period of hash perturbation */
|
||||||
|
+ __u32 limit; /* Maximal packets in queue */
|
||||||
|
+ unsigned divisor; /* Hash divisor */
|
||||||
|
+ unsigned flows; /* Maximal number of flows */
|
||||||
|
+ unsigned hash_kind; /* Hash function to use for flow identification */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* RED section */
|
||||||
|
|
||||||
|
enum
|
||||||
|
--- a/net/sched/Kconfig
|
||||||
|
+++ b/net/sched/Kconfig
|
||||||
|
@@ -137,6 +137,37 @@ config NET_SCH_SFQ
|
||||||
|
To compile this code as a module, choose M here: the
|
||||||
|
module will be called sch_sfq.
|
||||||
|
|
||||||
|
+config NET_SCH_ESFQ
|
||||||
|
+ tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
|
||||||
|
+ ---help---
|
||||||
|
+ Say Y here if you want to use the Enhanced Stochastic Fairness
|
||||||
|
+ Queueing (ESFQ) packet scheduling algorithm for some of your network
|
||||||
|
+ devices or as a leaf discipline for a classful qdisc such as HTB or
|
||||||
|
+ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
|
||||||
|
+ references to the SFQ algorithm).
|
||||||
|
+
|
||||||
|
+ This is an enchanced SFQ version which allows you to control some
|
||||||
|
+ hardcoded values in the SFQ scheduler.
|
||||||
|
+
|
||||||
|
+ ESFQ also adds control of the hash function used to identify packet
|
||||||
|
+ flows. The original SFQ discipline hashes by connection; ESFQ add
|
||||||
|
+ several other hashing methods, such as by src IP or by dst IP, which
|
||||||
|
+ can be more fair to users in some networking situations.
|
||||||
|
+
|
||||||
|
+ To compile this code as a module, choose M here: the
|
||||||
|
+ module will be called sch_esfq.
|
||||||
|
+
|
||||||
|
+config NET_SCH_ESFQ_NFCT
|
||||||
|
+ bool "Connection Tracking Hash Types"
|
||||||
|
+ depends on NET_SCH_ESFQ && NF_CONNTRACK
|
||||||
|
+ ---help---
|
||||||
|
+ Say Y here to enable support for hashing based on netfilter connection
|
||||||
|
+ tracking information. This is useful for a router that is also using
|
||||||
|
+ NAT to connect privately-addressed hosts to the Internet. If you want
|
||||||
|
+ to provide fair distribution of upstream bandwidth, ESFQ must use
|
||||||
|
+ connection tracking information, since all outgoing packets will share
|
||||||
|
+ the same source address.
|
||||||
|
+
|
||||||
|
config NET_SCH_TEQL
|
||||||
|
tristate "True Link Equalizer (TEQL)"
|
||||||
|
---help---
|
||||||
|
--- a/net/sched/Makefile
|
||||||
|
+++ b/net/sched/Makefile
|
||||||
|
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
|
||||||
|
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
|
||||||
|
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
|
||||||
|
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
|
||||||
|
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
|
||||||
|
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
|
||||||
|
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
|
||||||
|
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/net/sched/sch_esfq.c
|
||||||
|
@@ -0,0 +1,702 @@
|
||||||
|
+/*
|
||||||
|
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ *
|
||||||
|
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
||||||
|
+ *
|
||||||
|
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
|
||||||
|
+ * Added dynamic depth,limit,divisor,hash_kind options.
|
||||||
|
+ * Added dst and src hashes.
|
||||||
|
+ *
|
||||||
|
+ * Alexander Clouter, <alex@digriz.org.uk>
|
||||||
|
+ * Ported ESFQ to Linux 2.6.
|
||||||
|
+ *
|
||||||
|
+ * Corey Hickey, <bugfood-c@fatooh.org>
|
||||||
|
+ * Maintenance of the Linux 2.6 port.
|
||||||
|
+ * Added fwmark hash (thanks to Robert Kurjata).
|
||||||
|
+ * Added usage of jhash.
|
||||||
|
+ * Added conntrack support.
|
||||||
|
+ * Added ctnatchg hash (thanks to Ben Pfountz).
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <asm/uaccess.h>
|
||||||
|
+#include <asm/system.h>
|
||||||
|
+#include <linux/bitops.h>
|
||||||
|
+#include <linux/types.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/jiffies.h>
|
||||||
|
+#include <linux/string.h>
|
||||||
|
+#include <linux/mm.h>
|
||||||
|
+#include <linux/socket.h>
|
||||||
|
+#include <linux/sockios.h>
|
||||||
|
+#include <linux/in.h>
|
||||||
|
+#include <linux/errno.h>
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
+#include <linux/if_ether.h>
|
||||||
|
+#include <linux/inet.h>
|
||||||
|
+#include <linux/netdevice.h>
|
||||||
|
+#include <linux/etherdevice.h>
|
||||||
|
+#include <linux/notifier.h>
|
||||||
|
+#include <linux/init.h>
|
||||||
|
+#include <net/ip.h>
|
||||||
|
+#include <linux/ipv6.h>
|
||||||
|
+#include <net/route.h>
|
||||||
|
+#include <linux/skbuff.h>
|
||||||
|
+#include <net/sock.h>
|
||||||
|
+#include <net/pkt_sched.h>
|
||||||
|
+#include <linux/jhash.h>
|
||||||
|
+#include <net/netfilter/nf_conntrack.h>
|
||||||
|
+
|
||||||
|
+/* Stochastic Fairness Queuing algorithm.
|
||||||
|
+ For more comments look at sch_sfq.c.
|
||||||
|
+ The difference is that you can change limit, depth,
|
||||||
|
+ hash table size and choose alternate hash types.
|
||||||
|
+
|
||||||
|
+ classic: same as in sch_sfq.c
|
||||||
|
+ dst: destination IP address
|
||||||
|
+ src: source IP address
|
||||||
|
+ fwmark: netfilter mark value
|
||||||
|
+ ctorigdst: original destination IP address
|
||||||
|
+ ctorigsrc: original source IP address
|
||||||
|
+ ctrepldst: reply destination IP address
|
||||||
|
+ ctreplsrc: reply source IP
|
||||||
|
+
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#define ESFQ_HEAD 0
|
||||||
|
+#define ESFQ_TAIL 1
|
||||||
|
+
|
||||||
|
+/* This type should contain at least SFQ_DEPTH*2 values */
|
||||||
|
+typedef unsigned int esfq_index;
|
||||||
|
+
|
||||||
|
+struct esfq_head
|
||||||
|
+{
|
||||||
|
+ esfq_index next;
|
||||||
|
+ esfq_index prev;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct esfq_sched_data
|
||||||
|
+{
|
||||||
|
+/* Parameters */
|
||||||
|
+ int perturb_period;
|
||||||
|
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
|
||||||
|
+ int limit;
|
||||||
|
+ unsigned depth;
|
||||||
|
+ unsigned hash_divisor;
|
||||||
|
+ unsigned hash_kind;
|
||||||
|
+/* Variables */
|
||||||
|
+ struct timer_list perturb_timer;
|
||||||
|
+ int perturbation;
|
||||||
|
+ esfq_index tail; /* Index of current slot in round */
|
||||||
|
+ esfq_index max_depth; /* Maximal depth */
|
||||||
|
+
|
||||||
|
+ esfq_index *ht; /* Hash table */
|
||||||
|
+ esfq_index *next; /* Active slots link */
|
||||||
|
+ short *allot; /* Current allotment per slot */
|
||||||
|
+ unsigned short *hash; /* Hash value indexed by slots */
|
||||||
|
+ struct sk_buff_head *qs; /* Slot queue */
|
||||||
|
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* This contains the info we will hash. */
|
||||||
|
+struct esfq_packet_info
|
||||||
|
+{
|
||||||
|
+ u32 proto; /* protocol or port */
|
||||||
|
+ u32 src; /* source from packet header */
|
||||||
|
+ u32 dst; /* destination from packet header */
|
||||||
|
+ u32 ctorigsrc; /* original source from conntrack */
|
||||||
|
+ u32 ctorigdst; /* original destination from conntrack */
|
||||||
|
+ u32 ctreplsrc; /* reply source from conntrack */
|
||||||
|
+ u32 ctrepldst; /* reply destination from conntrack */
|
||||||
|
+ u32 mark; /* netfilter mark (fwmark) */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
|
||||||
|
+{
|
||||||
|
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
|
||||||
|
+{
|
||||||
|
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
|
||||||
|
+{
|
||||||
|
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ struct esfq_packet_info info;
|
||||||
|
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||||
|
+ enum ip_conntrack_info ctinfo;
|
||||||
|
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ switch (skb->protocol) {
|
||||||
|
+ case __constant_htons(ETH_P_IP):
|
||||||
|
+ {
|
||||||
|
+ struct iphdr *iph = ip_hdr(skb);
|
||||||
|
+ info.dst = iph->daddr;
|
||||||
|
+ info.src = iph->saddr;
|
||||||
|
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
|
||||||
|
+ (iph->protocol == IPPROTO_TCP ||
|
||||||
|
+ iph->protocol == IPPROTO_UDP ||
|
||||||
|
+ iph->protocol == IPPROTO_SCTP ||
|
||||||
|
+ iph->protocol == IPPROTO_DCCP ||
|
||||||
|
+ iph->protocol == IPPROTO_ESP))
|
||||||
|
+ info.proto = *(((u32*)iph) + iph->ihl);
|
||||||
|
+ else
|
||||||
|
+ info.proto = iph->protocol;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ case __constant_htons(ETH_P_IPV6):
|
||||||
|
+ {
|
||||||
|
+ struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||||
|
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
|
||||||
|
+ * but the code is simple. */
|
||||||
|
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
|
||||||
|
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
|
||||||
|
+ if (iph->nexthdr == IPPROTO_TCP ||
|
||||||
|
+ iph->nexthdr == IPPROTO_UDP ||
|
||||||
|
+ iph->nexthdr == IPPROTO_SCTP ||
|
||||||
|
+ iph->nexthdr == IPPROTO_DCCP ||
|
||||||
|
+ iph->nexthdr == IPPROTO_ESP)
|
||||||
|
+ info.proto = *(u32*)&iph[1];
|
||||||
|
+ else
|
||||||
|
+ info.proto = iph->nexthdr;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ default:
|
||||||
|
+ info.dst = (u32)(unsigned long)skb->dst;
|
||||||
|
+ info.src = (u32)(unsigned long)skb->sk;
|
||||||
|
+ info.proto = skb->protocol;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ info.mark = skb->mark;
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||||
|
+ /* defaults if there is no conntrack info */
|
||||||
|
+ info.ctorigsrc = info.src;
|
||||||
|
+ info.ctorigdst = info.dst;
|
||||||
|
+ info.ctreplsrc = info.dst;
|
||||||
|
+ info.ctrepldst = info.src;
|
||||||
|
+ /* collect conntrack info */
|
||||||
|
+ if (ct && ct != &nf_conntrack_untracked) {
|
||||||
|
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
|
||||||
|
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
||||||
|
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
|
||||||
|
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
|
||||||
|
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
|
||||||
|
+ }
|
||||||
|
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
|
||||||
|
+ /* Again, hash ipv6 addresses into a single u32. */
|
||||||
|
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
|
||||||
|
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
|
||||||
|
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
|
||||||
|
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ switch(q->hash_kind) {
|
||||||
|
+ case TCA_SFQ_HASH_CLASSIC:
|
||||||
|
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
||||||
|
+ case TCA_SFQ_HASH_DST:
|
||||||
|
+ return esfq_jhash_1word(q, info.dst);
|
||||||
|
+ case TCA_SFQ_HASH_SRC:
|
||||||
|
+ return esfq_jhash_1word(q, info.src);
|
||||||
|
+ case TCA_SFQ_HASH_FWMARK:
|
||||||
|
+ return esfq_jhash_1word(q, info.mark);
|
||||||
|
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||||
|
+ case TCA_SFQ_HASH_CTORIGDST:
|
||||||
|
+ return esfq_jhash_1word(q, info.ctorigdst);
|
||||||
|
+ case TCA_SFQ_HASH_CTORIGSRC:
|
||||||
|
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
||||||
|
+ case TCA_SFQ_HASH_CTREPLDST:
|
||||||
|
+ return esfq_jhash_1word(q, info.ctrepldst);
|
||||||
|
+ case TCA_SFQ_HASH_CTREPLSRC:
|
||||||
|
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
||||||
|
+ case TCA_SFQ_HASH_CTNATCHG:
|
||||||
|
+ {
|
||||||
|
+ if (info.ctorigdst == info.ctreplsrc)
|
||||||
|
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
||||||
|
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ default:
|
||||||
|
+ if (net_ratelimit())
|
||||||
|
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
|
||||||
|
+ }
|
||||||
|
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
|
||||||
|
+{
|
||||||
|
+ esfq_index p, n;
|
||||||
|
+ int d = q->qs[x].qlen + q->depth;
|
||||||
|
+
|
||||||
|
+ p = d;
|
||||||
|
+ n = q->dep[d].next;
|
||||||
|
+ q->dep[x].next = n;
|
||||||
|
+ q->dep[x].prev = p;
|
||||||
|
+ q->dep[p].next = q->dep[n].prev = x;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
|
||||||
|
+{
|
||||||
|
+ esfq_index p, n;
|
||||||
|
+
|
||||||
|
+ n = q->dep[x].next;
|
||||||
|
+ p = q->dep[x].prev;
|
||||||
|
+ q->dep[p].next = n;
|
||||||
|
+ q->dep[n].prev = p;
|
||||||
|
+
|
||||||
|
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
|
||||||
|
+ q->max_depth--;
|
||||||
|
+
|
||||||
|
+ esfq_link(q, x);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
|
||||||
|
+{
|
||||||
|
+ esfq_index p, n;
|
||||||
|
+ int d;
|
||||||
|
+
|
||||||
|
+ n = q->dep[x].next;
|
||||||
|
+ p = q->dep[x].prev;
|
||||||
|
+ q->dep[p].next = n;
|
||||||
|
+ q->dep[n].prev = p;
|
||||||
|
+ d = q->qs[x].qlen;
|
||||||
|
+ if (q->max_depth < d)
|
||||||
|
+ q->max_depth = d;
|
||||||
|
+
|
||||||
|
+ esfq_link(q, x);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static unsigned int esfq_drop(struct Qdisc *sch)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ esfq_index d = q->max_depth;
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+ unsigned int len;
|
||||||
|
+
|
||||||
|
+ /* Queue is full! Find the longest slot and
|
||||||
|
+ drop a packet from it */
|
||||||
|
+
|
||||||
|
+ if (d > 1) {
|
||||||
|
+ esfq_index x = q->dep[d+q->depth].next;
|
||||||
|
+ skb = q->qs[x].prev;
|
||||||
|
+ len = skb->len;
|
||||||
|
+ __skb_unlink(skb, &q->qs[x]);
|
||||||
|
+ kfree_skb(skb);
|
||||||
|
+ esfq_dec(q, x);
|
||||||
|
+ sch->q.qlen--;
|
||||||
|
+ sch->qstats.drops++;
|
||||||
|
+ sch->qstats.backlog -= len;
|
||||||
|
+ return len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (d == 1) {
|
||||||
|
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
|
||||||
|
+ d = q->next[q->tail];
|
||||||
|
+ q->next[q->tail] = q->next[d];
|
||||||
|
+ q->allot[q->next[d]] += q->quantum;
|
||||||
|
+ skb = q->qs[d].prev;
|
||||||
|
+ len = skb->len;
|
||||||
|
+ __skb_unlink(skb, &q->qs[d]);
|
||||||
|
+ kfree_skb(skb);
|
||||||
|
+ esfq_dec(q, d);
|
||||||
|
+ sch->q.qlen--;
|
||||||
|
+ q->ht[q->hash[d]] = q->depth;
|
||||||
|
+ sch->qstats.drops++;
|
||||||
|
+ sch->qstats.backlog -= len;
|
||||||
|
+ return len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
|
||||||
|
+{
|
||||||
|
+ unsigned hash = esfq_hash(q, skb);
|
||||||
|
+ unsigned depth = q->depth;
|
||||||
|
+ esfq_index x;
|
||||||
|
+
|
||||||
|
+ x = q->ht[hash];
|
||||||
|
+ if (x == depth) {
|
||||||
|
+ q->ht[hash] = x = q->dep[depth].next;
|
||||||
|
+ q->hash[x] = hash;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (end == ESFQ_TAIL)
|
||||||
|
+ __skb_queue_tail(&q->qs[x], skb);
|
||||||
|
+ else
|
||||||
|
+ __skb_queue_head(&q->qs[x], skb);
|
||||||
|
+
|
||||||
|
+ esfq_inc(q, x);
|
||||||
|
+ if (q->qs[x].qlen == 1) { /* The flow is new */
|
||||||
|
+ if (q->tail == depth) { /* It is the first flow */
|
||||||
|
+ q->tail = x;
|
||||||
|
+ q->next[x] = x;
|
||||||
|
+ q->allot[x] = q->quantum;
|
||||||
|
+ } else {
|
||||||
|
+ q->next[x] = q->next[q->tail];
|
||||||
|
+ q->next[q->tail] = x;
|
||||||
|
+ q->tail = x;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ esfq_q_enqueue(skb, q, ESFQ_TAIL);
|
||||||
|
+ sch->qstats.backlog += skb->len;
|
||||||
|
+ if (++sch->q.qlen < q->limit-1) {
|
||||||
|
+ sch->bstats.bytes += skb->len;
|
||||||
|
+ sch->bstats.packets++;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sch->qstats.drops++;
|
||||||
|
+ esfq_drop(sch);
|
||||||
|
+ return NET_XMIT_CN;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ esfq_q_enqueue(skb, q, ESFQ_HEAD);
|
||||||
|
+ sch->qstats.backlog += skb->len;
|
||||||
|
+ if (++sch->q.qlen < q->limit - 1) {
|
||||||
|
+ sch->qstats.requeues++;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sch->qstats.drops++;
|
||||||
|
+ esfq_drop(sch);
|
||||||
|
+ return NET_XMIT_CN;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
|
||||||
|
+{
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+ unsigned depth = q->depth;
|
||||||
|
+ esfq_index a, old_a;
|
||||||
|
+
|
||||||
|
+ /* No active slots */
|
||||||
|
+ if (q->tail == depth)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ a = old_a = q->next[q->tail];
|
||||||
|
+
|
||||||
|
+ /* Grab packet */
|
||||||
|
+ skb = __skb_dequeue(&q->qs[a]);
|
||||||
|
+ esfq_dec(q, a);
|
||||||
|
+
|
||||||
|
+ /* Is the slot empty? */
|
||||||
|
+ if (q->qs[a].qlen == 0) {
|
||||||
|
+ q->ht[q->hash[a]] = depth;
|
||||||
|
+ a = q->next[a];
|
||||||
|
+ if (a == old_a) {
|
||||||
|
+ q->tail = depth;
|
||||||
|
+ return skb;
|
||||||
|
+ }
|
||||||
|
+ q->next[q->tail] = a;
|
||||||
|
+ q->allot[a] += q->quantum;
|
||||||
|
+ } else if ((q->allot[a] -= skb->len) <= 0) {
|
||||||
|
+ q->tail = a;
|
||||||
|
+ a = q->next[a];
|
||||||
|
+ q->allot[a] += q->quantum;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return skb;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+
|
||||||
|
+ skb = esfq_q_dequeue(q);
|
||||||
|
+ if (skb == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+ sch->q.qlen--;
|
||||||
|
+ sch->qstats.backlog -= skb->len;
|
||||||
|
+ return skb;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void esfq_q_destroy(struct esfq_sched_data *q)
|
||||||
|
+{
|
||||||
|
+ del_timer(&q->perturb_timer);
|
||||||
|
+ if(q->ht)
|
||||||
|
+ kfree(q->ht);
|
||||||
|
+ if(q->dep)
|
||||||
|
+ kfree(q->dep);
|
||||||
|
+ if(q->next)
|
||||||
|
+ kfree(q->next);
|
||||||
|
+ if(q->allot)
|
||||||
|
+ kfree(q->allot);
|
||||||
|
+ if(q->hash)
|
||||||
|
+ kfree(q->hash);
|
||||||
|
+ if(q->qs)
|
||||||
|
+ kfree(q->qs);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void esfq_destroy(struct Qdisc *sch)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ esfq_q_destroy(q);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void esfq_reset(struct Qdisc* sch)
|
||||||
|
+{
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+
|
||||||
|
+ while ((skb = esfq_dequeue(sch)) != NULL)
|
||||||
|
+ kfree_skb(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void esfq_perturbation(unsigned long arg)
|
||||||
|
+{
|
||||||
|
+ struct Qdisc *sch = (struct Qdisc*)arg;
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+
|
||||||
|
+ q->perturbation = net_random()&0x1F;
|
||||||
|
+
|
||||||
|
+ if (q->perturb_period) {
|
||||||
|
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||||
|
+ add_timer(&q->perturb_timer);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static unsigned int esfq_check_hash(unsigned int kind)
|
||||||
|
+{
|
||||||
|
+ switch (kind) {
|
||||||
|
+ case TCA_SFQ_HASH_CTORIGDST:
|
||||||
|
+ case TCA_SFQ_HASH_CTORIGSRC:
|
||||||
|
+ case TCA_SFQ_HASH_CTREPLDST:
|
||||||
|
+ case TCA_SFQ_HASH_CTREPLSRC:
|
||||||
|
+ case TCA_SFQ_HASH_CTNATCHG:
|
||||||
|
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
|
||||||
|
+ {
|
||||||
|
+ if (net_ratelimit())
|
||||||
|
+ printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
|
||||||
|
+ return TCA_SFQ_HASH_CLASSIC;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ case TCA_SFQ_HASH_CLASSIC:
|
||||||
|
+ case TCA_SFQ_HASH_DST:
|
||||||
|
+ case TCA_SFQ_HASH_SRC:
|
||||||
|
+ case TCA_SFQ_HASH_FWMARK:
|
||||||
|
+ return kind;
|
||||||
|
+ default:
|
||||||
|
+ {
|
||||||
|
+ if (net_ratelimit())
|
||||||
|
+ printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
|
||||||
|
+ return TCA_SFQ_HASH_CLASSIC;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int esfq_q_init(struct esfq_sched_data *q, struct rtattr *opt)
|
||||||
|
+{
|
||||||
|
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
|
||||||
|
+ esfq_index p = ~0U/2;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ q->perturbation = 0;
|
||||||
|
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
|
||||||
|
+ q->max_depth = 0;
|
||||||
|
+ if (opt == NULL) {
|
||||||
|
+ q->perturb_period = 0;
|
||||||
|
+ q->hash_divisor = 1024;
|
||||||
|
+ q->tail = q->limit = q->depth = 128;
|
||||||
|
+
|
||||||
|
+ } else {
|
||||||
|
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
|
||||||
|
+ if (ctl->quantum)
|
||||||
|
+ q->quantum = ctl->quantum;
|
||||||
|
+ q->perturb_period = ctl->perturb_period*HZ;
|
||||||
|
+ q->hash_divisor = ctl->divisor ? : 1024;
|
||||||
|
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
|
||||||
|
+
|
||||||
|
+ if ( q->depth > p - 1 )
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ if (ctl->limit)
|
||||||
|
+ q->limit = min_t(u32, ctl->limit, q->depth);
|
||||||
|
+
|
||||||
|
+ if (ctl->hash_kind) {
|
||||||
|
+ q->hash_kind = esfq_check_hash(ctl->hash_kind);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
|
||||||
|
+ if (!q->ht)
|
||||||
|
+ goto err_case;
|
||||||
|
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
|
||||||
|
+ if (!q->dep)
|
||||||
|
+ goto err_case;
|
||||||
|
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
|
||||||
|
+ if (!q->next)
|
||||||
|
+ goto err_case;
|
||||||
|
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
|
||||||
|
+ if (!q->allot)
|
||||||
|
+ goto err_case;
|
||||||
|
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
|
||||||
|
+ if (!q->hash)
|
||||||
|
+ goto err_case;
|
||||||
|
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
|
||||||
|
+ if (!q->qs)
|
||||||
|
+ goto err_case;
|
||||||
|
+
|
||||||
|
+ for (i=0; i< q->hash_divisor; i++)
|
||||||
|
+ q->ht[i] = q->depth;
|
||||||
|
+ for (i=0; i<q->depth; i++) {
|
||||||
|
+ skb_queue_head_init(&q->qs[i]);
|
||||||
|
+ q->dep[i+q->depth].next = i+q->depth;
|
||||||
|
+ q->dep[i+q->depth].prev = i+q->depth;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i=0; i<q->depth; i++)
|
||||||
|
+ esfq_link(q, i);
|
||||||
|
+ return 0;
|
||||||
|
+err_case:
|
||||||
|
+ esfq_q_destroy(q);
|
||||||
|
+ return -ENOBUFS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int esfq_init(struct Qdisc *sch, struct rtattr *opt)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
||||||
|
+ if ((err = esfq_q_init(q, opt)))
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ init_timer(&q->perturb_timer);
|
||||||
|
+ q->perturb_timer.data = (unsigned long)sch;
|
||||||
|
+ q->perturb_timer.function = esfq_perturbation;
|
||||||
|
+ if (q->perturb_period) {
|
||||||
|
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||||
|
+ add_timer(&q->perturb_timer);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int esfq_change(struct Qdisc *sch, struct rtattr *opt)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ struct esfq_sched_data new;
|
||||||
|
+ struct sk_buff *skb;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ /* set up new queue */
|
||||||
|
+ memset(&new, 0, sizeof(struct esfq_sched_data));
|
||||||
|
+ new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
||||||
|
+ if ((err = esfq_q_init(&new, opt)))
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ /* copy all packets from the old queue to the new queue */
|
||||||
|
+ sch_tree_lock(sch);
|
||||||
|
+ while ((skb = esfq_q_dequeue(q)) != NULL)
|
||||||
|
+ esfq_q_enqueue(skb, &new, ESFQ_TAIL);
|
||||||
|
+
|
||||||
|
+ /* clean up the old queue */
|
||||||
|
+ esfq_q_destroy(q);
|
||||||
|
+
|
||||||
|
+ /* copy elements of the new queue into the old queue */
|
||||||
|
+ q->perturb_period = new.perturb_period;
|
||||||
|
+ q->quantum = new.quantum;
|
||||||
|
+ q->limit = new.limit;
|
||||||
|
+ q->depth = new.depth;
|
||||||
|
+ q->hash_divisor = new.hash_divisor;
|
||||||
|
+ q->hash_kind = new.hash_kind;
|
||||||
|
+ q->tail = new.tail;
|
||||||
|
+ q->max_depth = new.max_depth;
|
||||||
|
+ q->ht = new.ht;
|
||||||
|
+ q->dep = new.dep;
|
||||||
|
+ q->next = new.next;
|
||||||
|
+ q->allot = new.allot;
|
||||||
|
+ q->hash = new.hash;
|
||||||
|
+ q->qs = new.qs;
|
||||||
|
+
|
||||||
|
+ /* finish up */
|
||||||
|
+ if (q->perturb_period) {
|
||||||
|
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||||
|
+ add_timer(&q->perturb_timer);
|
||||||
|
+ } else {
|
||||||
|
+ q->perturbation = 0;
|
||||||
|
+ }
|
||||||
|
+ sch_tree_unlock(sch);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||||
|
+ unsigned char *b = skb->tail;
|
||||||
|
+ struct tc_esfq_qopt opt;
|
||||||
|
+
|
||||||
|
+ opt.quantum = q->quantum;
|
||||||
|
+ opt.perturb_period = q->perturb_period/HZ;
|
||||||
|
+
|
||||||
|
+ opt.limit = q->limit;
|
||||||
|
+ opt.divisor = q->hash_divisor;
|
||||||
|
+ opt.flows = q->depth;
|
||||||
|
+ opt.hash_kind = q->hash_kind;
|
||||||
|
+
|
||||||
|
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
|
||||||
|
+
|
||||||
|
+ return skb->len;
|
||||||
|
+
|
||||||
|
+rtattr_failure:
|
||||||
|
+ skb_trim(skb, b - skb->data);
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct Qdisc_ops esfq_qdisc_ops =
|
||||||
|
+{
|
||||||
|
+ .next = NULL,
|
||||||
|
+ .cl_ops = NULL,
|
||||||
|
+ .id = "esfq",
|
||||||
|
+ .priv_size = sizeof(struct esfq_sched_data),
|
||||||
|
+ .enqueue = esfq_enqueue,
|
||||||
|
+ .dequeue = esfq_dequeue,
|
||||||
|
+ .requeue = esfq_requeue,
|
||||||
|
+ .drop = esfq_drop,
|
||||||
|
+ .init = esfq_init,
|
||||||
|
+ .reset = esfq_reset,
|
||||||
|
+ .destroy = esfq_destroy,
|
||||||
|
+ .change = esfq_change,
|
||||||
|
+ .dump = esfq_dump,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init esfq_module_init(void)
|
||||||
|
+{
|
||||||
|
+ return register_qdisc(&esfq_qdisc_ops);
|
||||||
|
+}
|
||||||
|
+static void __exit esfq_module_exit(void)
|
||||||
|
+{
|
||||||
|
+ unregister_qdisc(&esfq_qdisc_ops);
|
||||||
|
+}
|
||||||
|
+module_init(esfq_module_init)
|
||||||
|
+module_exit(esfq_module_exit)
|
||||||
|
+MODULE_LICENSE("GPL");
|
227
target/linux/generic-2.6/patches-2.6.30/201-jhash3.patch
Normal file
227
target/linux/generic-2.6/patches-2.6.30/201-jhash3.patch
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
--- a/include/linux/jhash.h
|
||||||
|
+++ b/include/linux/jhash.h
|
||||||
|
@@ -3,80 +3,95 @@
|
||||||
|
|
||||||
|
/* jhash.h: Jenkins hash support.
|
||||||
|
*
|
||||||
|
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||||
|
+ * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||||
|
*
|
||||||
|
* http://burtleburtle.net/bob/hash/
|
||||||
|
*
|
||||||
|
* These are the credits from Bob's sources:
|
||||||
|
*
|
||||||
|
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
|
||||||
|
- * hash(), hash2(), hash3, and mix() are externally useful functions.
|
||||||
|
- * Routines to test the hash are included if SELF_TEST is defined.
|
||||||
|
- * You can use this free for any purpose. It has no warranty.
|
||||||
|
+ * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||||
|
*
|
||||||
|
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
|
||||||
|
+ * These are functions for producing 32-bit hashes for hash table lookup.
|
||||||
|
+ * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||||
|
+ * are externally useful functions. Routines to test the hash are included
|
||||||
|
+ * if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||||
|
+ * the public domain. It has no warranty.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2009 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||||
|
*
|
||||||
|
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||||
|
- * any bugs present are surely my fault. -DaveM
|
||||||
|
+ * any bugs present are my fault. Jozsef
|
||||||
|
*/
|
||||||
|
|
||||||
|
-/* NOTE: Arguments are modified. */
|
||||||
|
-#define __jhash_mix(a, b, c) \
|
||||||
|
+#define __rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||||
|
+
|
||||||
|
+/* __jhash_mix - mix 3 32-bit values reversibly. */
|
||||||
|
+#define __jhash_mix(a,b,c) \
|
||||||
|
+{ \
|
||||||
|
+ a -= c; a ^= __rot(c, 4); c += b; \
|
||||||
|
+ b -= a; b ^= __rot(a, 6); a += c; \
|
||||||
|
+ c -= b; c ^= __rot(b, 8); b += a; \
|
||||||
|
+ a -= c; a ^= __rot(c,16); c += b; \
|
||||||
|
+ b -= a; b ^= __rot(a,19); a += c; \
|
||||||
|
+ c -= b; c ^= __rot(b, 4); b += a; \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
||||||
|
+#define __jhash_final(a,b,c) \
|
||||||
|
{ \
|
||||||
|
- a -= b; a -= c; a ^= (c>>13); \
|
||||||
|
- b -= c; b -= a; b ^= (a<<8); \
|
||||||
|
- c -= a; c -= b; c ^= (b>>13); \
|
||||||
|
- a -= b; a -= c; a ^= (c>>12); \
|
||||||
|
- b -= c; b -= a; b ^= (a<<16); \
|
||||||
|
- c -= a; c -= b; c ^= (b>>5); \
|
||||||
|
- a -= b; a -= c; a ^= (c>>3); \
|
||||||
|
- b -= c; b -= a; b ^= (a<<10); \
|
||||||
|
- c -= a; c -= b; c ^= (b>>15); \
|
||||||
|
+ c ^= b; c -= __rot(b,14); \
|
||||||
|
+ a ^= c; a -= __rot(c,11); \
|
||||||
|
+ b ^= a; b -= __rot(a,25); \
|
||||||
|
+ c ^= b; c -= __rot(b,16); \
|
||||||
|
+ a ^= c; a -= __rot(c,4); \
|
||||||
|
+ b ^= a; b -= __rot(a,14); \
|
||||||
|
+ c ^= b; c -= __rot(b,24); \
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* The golden ration: an arbitrary value */
|
||||||
|
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
|
||||||
|
+/* An arbitrary initial parameter */
|
||||||
|
+#define JHASH_GOLDEN_RATIO 0xdeadbeef
|
||||||
|
|
||||||
|
/* The most generic version, hashes an arbitrary sequence
|
||||||
|
* of bytes. No alignment or length assumptions are made about
|
||||||
|
- * the input key.
|
||||||
|
+ * the input key. The result depends on endianness.
|
||||||
|
*/
|
||||||
|
static inline u32 jhash(const void *key, u32 length, u32 initval)
|
||||||
|
{
|
||||||
|
- u32 a, b, c, len;
|
||||||
|
+ u32 a,b,c;
|
||||||
|
const u8 *k = key;
|
||||||
|
|
||||||
|
- len = length;
|
||||||
|
- a = b = JHASH_GOLDEN_RATIO;
|
||||||
|
- c = initval;
|
||||||
|
-
|
||||||
|
- while (len >= 12) {
|
||||||
|
- a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
|
||||||
|
- b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
|
||||||
|
- c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
|
||||||
|
-
|
||||||
|
- __jhash_mix(a,b,c);
|
||||||
|
+ /* Set up the internal state */
|
||||||
|
+ a = b = c = JHASH_GOLDEN_RATIO + length + initval;
|
||||||
|
|
||||||
|
+ /* all but the last block: affect some 32 bits of (a,b,c) */
|
||||||
|
+ while (length > 12) {
|
||||||
|
+ a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24));
|
||||||
|
+ b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24));
|
||||||
|
+ c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24));
|
||||||
|
+ __jhash_mix(a, b, c);
|
||||||
|
+ length -= 12;
|
||||||
|
k += 12;
|
||||||
|
- len -= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
- c += length;
|
||||||
|
- switch (len) {
|
||||||
|
- case 11: c += ((u32)k[10]<<24);
|
||||||
|
- case 10: c += ((u32)k[9]<<16);
|
||||||
|
- case 9 : c += ((u32)k[8]<<8);
|
||||||
|
- case 8 : b += ((u32)k[7]<<24);
|
||||||
|
- case 7 : b += ((u32)k[6]<<16);
|
||||||
|
- case 6 : b += ((u32)k[5]<<8);
|
||||||
|
+ /* last block: affect all 32 bits of (c) */
|
||||||
|
+ /* all the case statements fall through */
|
||||||
|
+ switch (length) {
|
||||||
|
+ case 12: c += (u32)k[11]<<24;
|
||||||
|
+ case 11: c += (u32)k[10]<<16;
|
||||||
|
+ case 10: c += (u32)k[9]<<8;
|
||||||
|
+ case 9 : c += k[8];
|
||||||
|
+ case 8 : b += (u32)k[7]<<24;
|
||||||
|
+ case 7 : b += (u32)k[6]<<16;
|
||||||
|
+ case 6 : b += (u32)k[5]<<8;
|
||||||
|
case 5 : b += k[4];
|
||||||
|
- case 4 : a += ((u32)k[3]<<24);
|
||||||
|
- case 3 : a += ((u32)k[2]<<16);
|
||||||
|
- case 2 : a += ((u32)k[1]<<8);
|
||||||
|
+ case 4 : a += (u32)k[3]<<24;
|
||||||
|
+ case 3 : a += (u32)k[2]<<16;
|
||||||
|
+ case 2 : a += (u32)k[1]<<8;
|
||||||
|
case 1 : a += k[0];
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
- __jhash_mix(a,b,c);
|
||||||
|
+ __jhash_final(a, b, c);
|
||||||
|
+ case 0 :
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
@@ -86,58 +101,57 @@ static inline u32 jhash(const void *key,
|
||||||
|
*/
|
||||||
|
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
||||||
|
{
|
||||||
|
- u32 a, b, c, len;
|
||||||
|
+ u32 a, b, c;
|
||||||
|
|
||||||
|
- a = b = JHASH_GOLDEN_RATIO;
|
||||||
|
- c = initval;
|
||||||
|
- len = length;
|
||||||
|
+ /* Set up the internal state */
|
||||||
|
+ a = b = c = JHASH_GOLDEN_RATIO + (length<<2) + initval;
|
||||||
|
|
||||||
|
- while (len >= 3) {
|
||||||
|
+ /* handle most of the key */
|
||||||
|
+ while (length > 3) {
|
||||||
|
a += k[0];
|
||||||
|
b += k[1];
|
||||||
|
c += k[2];
|
||||||
|
__jhash_mix(a, b, c);
|
||||||
|
- k += 3; len -= 3;
|
||||||
|
+ length -= 3;
|
||||||
|
+ k += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
- c += length * 4;
|
||||||
|
-
|
||||||
|
- switch (len) {
|
||||||
|
- case 2 : b += k[1];
|
||||||
|
- case 1 : a += k[0];
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
- __jhash_mix(a,b,c);
|
||||||
|
+ /* handle the last 3 u32's */
|
||||||
|
+ /* all the case statements fall through */
|
||||||
|
+ switch (length) {
|
||||||
|
+ case 3: c += k[2];
|
||||||
|
+ case 2: b += k[1];
|
||||||
|
+ case 1: a += k[0];
|
||||||
|
+ __jhash_final(a, b, c);
|
||||||
|
+ case 0: /* case 0: nothing left to add */
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
/* A special ultra-optimized versions that knows they are hashing exactly
|
||||||
|
* 3, 2 or 1 word(s).
|
||||||
|
- *
|
||||||
|
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
|
||||||
|
- * done at the end is not done here.
|
||||||
|
*/
|
||||||
|
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
|
||||||
|
{
|
||||||
|
- a += JHASH_GOLDEN_RATIO;
|
||||||
|
- b += JHASH_GOLDEN_RATIO;
|
||||||
|
- c += initval;
|
||||||
|
+ a += JHASH_GOLDEN_RATIO + initval;
|
||||||
|
+ b += JHASH_GOLDEN_RATIO + initval;
|
||||||
|
+ c += JHASH_GOLDEN_RATIO + initval;
|
||||||
|
|
||||||
|
- __jhash_mix(a, b, c);
|
||||||
|
+ __jhash_final(a, b, c);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
|
||||||
|
{
|
||||||
|
- return jhash_3words(a, b, 0, initval);
|
||||||
|
+ return jhash_3words(0, a, b, initval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 jhash_1word(u32 a, u32 initval)
|
||||||
|
{
|
||||||
|
- return jhash_3words(a, 0, 0, initval);
|
||||||
|
+ return jhash_3words(0, 0, a, initval);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _LINUX_JHASH_H */
|
@ -0,0 +1,12 @@
|
|||||||
|
--- a/arch/mips/Makefile
|
||||||
|
+++ b/arch/mips/Makefile
|
||||||
|
@@ -602,6 +602,9 @@ else
|
||||||
|
load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000
|
||||||
|
endif
|
||||||
|
|
||||||
|
+# temporary until string.h is fixed
|
||||||
|
+cflags-y += -ffreestanding
|
||||||
|
+
|
||||||
|
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
|
||||||
|
drivers-$(CONFIG_PCI) += arch/mips/pci/
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
--- a/include/linux/slab.h
|
||||||
|
+++ b/include/linux/slab.h
|
||||||
|
@@ -115,8 +115,8 @@ int kmem_ptr_validate(struct kmem_cache
|
||||||
|
* to do various tricks to work around compiler limitations in order to
|
||||||
|
* ensure proper constant folding.
|
||||||
|
*/
|
||||||
|
-#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
|
||||||
|
- (MAX_ORDER + PAGE_SHIFT - 1) : 25)
|
||||||
|
+#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 17 ? \
|
||||||
|
+ (MAX_ORDER + PAGE_SHIFT - 1) : 17)
|
||||||
|
|
||||||
|
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_HIGH)
|
||||||
|
#define KMALLOC_MAX_ORDER (KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
|
@ -0,0 +1,132 @@
|
|||||||
|
--- a/fs/jffs2/build.c
|
||||||
|
+++ b/fs/jffs2/build.c
|
||||||
|
@@ -111,6 +111,17 @@ static int jffs2_build_filesystem(struct
|
||||||
|
dbg_fsbuild("scanned flash completely\n");
|
||||||
|
jffs2_dbg_dump_block_lists_nolock(c);
|
||||||
|
|
||||||
|
+ if (c->flags & (1 << 7)) {
|
||||||
|
+ printk("%s(): unlocking the mtd device... ", __func__);
|
||||||
|
+ if (c->mtd->unlock)
|
||||||
|
+ c->mtd->unlock(c->mtd, 0, c->mtd->size);
|
||||||
|
+ printk("done.\n");
|
||||||
|
+
|
||||||
|
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
|
||||||
|
+ jffs2_erase_pending_blocks(c, -1);
|
||||||
|
+ printk("done.\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
dbg_fsbuild("pass 1 starting\n");
|
||||||
|
c->flags |= JFFS2_SB_FLAG_BUILDING;
|
||||||
|
/* Now scan the directory tree, increasing nlink according to every dirent found. */
|
||||||
|
--- a/fs/jffs2/scan.c
|
||||||
|
+++ b/fs/jffs2/scan.c
|
||||||
|
@@ -72,7 +72,7 @@ static int file_dirty(struct jffs2_sb_in
|
||||||
|
return ret;
|
||||||
|
if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
|
||||||
|
return ret;
|
||||||
|
- /* Turned wasted size into dirty, since we apparently
|
||||||
|
+ /* Turned wasted size into dirty, since we apparently
|
||||||
|
think it's recoverable now. */
|
||||||
|
jeb->dirty_size += jeb->wasted_size;
|
||||||
|
c->dirty_size += jeb->wasted_size;
|
||||||
|
@@ -144,8 +144,11 @@ int jffs2_scan_medium(struct jffs2_sb_in
|
||||||
|
/* reset summary info for next eraseblock scan */
|
||||||
|
jffs2_sum_reset_collected(s);
|
||||||
|
|
||||||
|
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
||||||
|
- buf_size, s);
|
||||||
|
+ if (c->flags & (1 << 7))
|
||||||
|
+ ret = BLK_STATE_ALLFF;
|
||||||
|
+ else
|
||||||
|
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
||||||
|
+ buf_size, s);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
@@ -400,7 +403,7 @@ static int jffs2_scan_xref_node(struct j
|
||||||
|
if (!ref)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
- /* BEFORE jffs2_build_xattr_subsystem() called,
|
||||||
|
+ /* BEFORE jffs2_build_xattr_subsystem() called,
|
||||||
|
* and AFTER xattr_ref is marked as a dead xref,
|
||||||
|
* ref->xid is used to store 32bit xid, xd is not used
|
||||||
|
* ref->ino is used to store 32bit inode-number, ic is not used
|
||||||
|
@@ -473,7 +476,7 @@ static int jffs2_scan_eraseblock (struct
|
||||||
|
struct jffs2_sum_marker *sm;
|
||||||
|
void *sumptr = NULL;
|
||||||
|
uint32_t sumlen;
|
||||||
|
-
|
||||||
|
+
|
||||||
|
if (!buf_size) {
|
||||||
|
/* XIP case. Just look, point at the summary if it's there */
|
||||||
|
sm = (void *)buf + c->sector_size - sizeof(*sm);
|
||||||
|
@@ -489,9 +492,9 @@ static int jffs2_scan_eraseblock (struct
|
||||||
|
buf_len = sizeof(*sm);
|
||||||
|
|
||||||
|
/* Read as much as we want into the _end_ of the preallocated buffer */
|
||||||
|
- err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
|
||||||
|
+ err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
|
||||||
|
jeb->offset + c->sector_size - buf_len,
|
||||||
|
- buf_len);
|
||||||
|
+ buf_len);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
@@ -510,9 +513,9 @@ static int jffs2_scan_eraseblock (struct
|
||||||
|
}
|
||||||
|
if (buf_len < sumlen) {
|
||||||
|
/* Need to read more so that the entire summary node is present */
|
||||||
|
- err = jffs2_fill_scan_buf(c, sumptr,
|
||||||
|
+ err = jffs2_fill_scan_buf(c, sumptr,
|
||||||
|
jeb->offset + c->sector_size - sumlen,
|
||||||
|
- sumlen - buf_len);
|
||||||
|
+ sumlen - buf_len);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@@ -525,7 +528,7 @@ static int jffs2_scan_eraseblock (struct
|
||||||
|
|
||||||
|
if (buf_size && sumlen > buf_size)
|
||||||
|
kfree(sumptr);
|
||||||
|
- /* If it returns with a real error, bail.
|
||||||
|
+ /* If it returns with a real error, bail.
|
||||||
|
If it returns positive, that's a block classification
|
||||||
|
(i.e. BLK_STATE_xxx) so return that too.
|
||||||
|
If it returns zero, fall through to full scan. */
|
||||||
|
@@ -546,6 +549,17 @@ static int jffs2_scan_eraseblock (struct
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if ((buf[0] == 0xde) &&
|
||||||
|
+ (buf[1] == 0xad) &&
|
||||||
|
+ (buf[2] == 0xc0) &&
|
||||||
|
+ (buf[3] == 0xde)) {
|
||||||
|
+ /* end of filesystem. erase everything after this point */
|
||||||
|
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
|
||||||
|
+ c->flags |= (1 << 7);
|
||||||
|
+
|
||||||
|
+ return BLK_STATE_ALLFF;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
|
||||||
|
ofs = 0;
|
||||||
|
|
||||||
|
@@ -671,7 +685,7 @@ scan_more:
|
||||||
|
scan_end = buf_len;
|
||||||
|
goto more_empty;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+
|
||||||
|
/* See how much more there is to read in this eraseblock... */
|
||||||
|
buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
|
||||||
|
if (!buf_len) {
|
||||||
|
@@ -907,7 +921,7 @@ scan_more:
|
||||||
|
|
||||||
|
D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
|
||||||
|
jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
|
||||||
|
-
|
||||||
|
+
|
||||||
|
/* mark_node_obsolete can add to wasted !! */
|
||||||
|
if (jeb->wasted_size) {
|
||||||
|
jeb->dirty_size += jeb->wasted_size;
|
@ -0,0 +1,16 @@
|
|||||||
|
--- a/include/linux/skbuff.h
|
||||||
|
+++ b/include/linux/skbuff.h
|
||||||
|
@@ -1355,9 +1355,12 @@ static inline int skb_network_offset(con
|
||||||
|
*
|
||||||
|
* Various parts of the networking layer expect at least 32 bytes of
|
||||||
|
* headroom, you should not reduce this.
|
||||||
|
+ *
|
||||||
|
+ * This has been changed to 64 to acommodate for routing between ethernet
|
||||||
|
+ * and wireless
|
||||||
|
*/
|
||||||
|
#ifndef NET_SKB_PAD
|
||||||
|
-#define NET_SKB_PAD 32
|
||||||
|
+#define NET_SKB_PAD 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
|
@ -0,0 +1,9 @@
|
|||||||
|
--- /dev/null
|
||||||
|
+++ b/include/asm-powerpc/segment.h
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+#ifndef _ASM_SEGMENT_H
|
||||||
|
+#define _ASM_SEGMENT_H
|
||||||
|
+
|
||||||
|
+/* Only here because we have some old header files that expect it.. */
|
||||||
|
+
|
||||||
|
+#endif /* _ASM_SEGMENT_H */
|
@ -0,0 +1,42 @@
|
|||||||
|
--- a/drivers/net/r8169.c
|
||||||
|
+++ b/drivers/net/r8169.c
|
||||||
|
@@ -1890,7 +1890,7 @@ static const struct rtl_cfg_info {
|
||||||
|
.hw_start = rtl_hw_start_8169,
|
||||||
|
.region = 1,
|
||||||
|
.align = 0,
|
||||||
|
- .intr_event = SYSErr | LinkChg | RxOverflow |
|
||||||
|
+ .intr_event = LinkChg | RxOverflow |
|
||||||
|
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
||||||
|
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
|
||||||
|
.features = RTL_FEATURE_GMII
|
||||||
|
@@ -1899,7 +1899,7 @@ static const struct rtl_cfg_info {
|
||||||
|
.hw_start = rtl_hw_start_8168,
|
||||||
|
.region = 2,
|
||||||
|
.align = 8,
|
||||||
|
- .intr_event = SYSErr | LinkChg | RxOverflow |
|
||||||
|
+ .intr_event = LinkChg | RxOverflow |
|
||||||
|
TxErr | TxOK | RxOK | RxErr,
|
||||||
|
.napi_event = TxErr | TxOK | RxOK | RxOverflow,
|
||||||
|
.features = RTL_FEATURE_GMII | RTL_FEATURE_MSI
|
||||||
|
@@ -1908,7 +1908,7 @@ static const struct rtl_cfg_info {
|
||||||
|
.hw_start = rtl_hw_start_8101,
|
||||||
|
.region = 2,
|
||||||
|
.align = 8,
|
||||||
|
- .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
|
||||||
|
+ .intr_event = LinkChg | RxOverflow | PCSTimeout |
|
||||||
|
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
||||||
|
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
|
||||||
|
.features = RTL_FEATURE_MSI
|
||||||
|
@@ -3582,10 +3582,12 @@ static irqreturn_t rtl8169_interrupt(int
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if 0
|
||||||
|
if (unlikely(status & SYSErr)) {
|
||||||
|
rtl8169_pcierr_interrupt(dev);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
if (status & LinkChg)
|
||||||
|
rtl8169_check_link_status(dev, tp, ioaddr);
|
7780
target/linux/generic-2.6/patches-2.6.30/209-mini_fo.patch
Normal file
7780
target/linux/generic-2.6/patches-2.6.30/209-mini_fo.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,143 @@
|
|||||||
|
--- a/fs/mini_fo/main.c
|
||||||
|
+++ b/fs/mini_fo/main.c
|
||||||
|
@@ -79,6 +79,7 @@ mini_fo_tri_interpose(dentry_t *hidden_d
|
||||||
|
* of the new inode's fields
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
|
||||||
|
/*
|
||||||
|
* original: inode = iget(sb, hidden_inode->i_ino);
|
||||||
|
*/
|
||||||
|
@@ -87,6 +88,13 @@ mini_fo_tri_interpose(dentry_t *hidden_d
|
||||||
|
err = -EACCES; /* should be impossible??? */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+#else
|
||||||
|
+ inode = mini_fo_iget(sb, iunique(sb, 25));
|
||||||
|
+ if (IS_ERR(inode)) {
|
||||||
|
+ err = PTR_ERR(inode);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* interpose the inode if not already interposed
|
||||||
|
@@ -184,9 +192,9 @@ mini_fo_parse_options(super_block_t *sb,
|
||||||
|
hidden_root = ERR_PTR(err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- hidden_root = nd.dentry;
|
||||||
|
- stopd(sb)->base_dir_dentry = nd.dentry;
|
||||||
|
- stopd(sb)->hidden_mnt = nd.mnt;
|
||||||
|
+ hidden_root = nd_get_dentry(&nd);
|
||||||
|
+ stopd(sb)->base_dir_dentry = nd_get_dentry(&nd);
|
||||||
|
+ stopd(sb)->hidden_mnt = nd_get_mnt(&nd);
|
||||||
|
|
||||||
|
} else if(!strncmp("sto=", options, 4)) {
|
||||||
|
/* parse the storage dir */
|
||||||
|
@@ -204,9 +212,9 @@ mini_fo_parse_options(super_block_t *sb,
|
||||||
|
hidden_root2 = ERR_PTR(err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- hidden_root2 = nd2.dentry;
|
||||||
|
- stopd(sb)->storage_dir_dentry = nd2.dentry;
|
||||||
|
- stopd(sb)->hidden_mnt2 = nd2.mnt;
|
||||||
|
+ hidden_root2 = nd_get_dentry(&nd2);
|
||||||
|
+ stopd(sb)->storage_dir_dentry = nd_get_dentry(&nd2);
|
||||||
|
+ stopd(sb)->hidden_mnt2 = nd_get_mnt(&nd2);
|
||||||
|
stohs2(sb) = hidden_root2->d_sb;
|
||||||
|
|
||||||
|
/* validate storage dir, this is done in
|
||||||
|
--- a/fs/mini_fo/mini_fo.h
|
||||||
|
+++ b/fs/mini_fo/mini_fo.h
|
||||||
|
@@ -302,6 +302,10 @@ extern int mini_fo_tri_interpose(dentry_
|
||||||
|
extern int mini_fo_cp_cont(dentry_t *tgt_dentry, struct vfsmount *tgt_mnt,
|
||||||
|
dentry_t *src_dentry, struct vfsmount *src_mnt);
|
||||||
|
|
||||||
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
||||||
|
+extern struct inode *mini_fo_iget(struct super_block *sb, unsigned long ino);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||||
|
extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
|
||||||
|
|
||||||
|
@@ -501,6 +505,29 @@ static inline void double_unlock(struct
|
||||||
|
#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
|
||||||
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
+
|
||||||
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
||||||
|
+static inline dentry_t *nd_get_dentry(struct nameidata *nd)
|
||||||
|
+{
|
||||||
|
+ return (nd->path.dentry);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline struct vfsmount *nd_get_mnt(struct nameidata *nd)
|
||||||
|
+{
|
||||||
|
+ return (nd->path.mnt);
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+static inline dentry_t *nd_get_dentry(struct nameidata *nd)
|
||||||
|
+{
|
||||||
|
+ return (nd->dentry);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline struct vfsmount *nd_get_mnt(struct nameidata *nd)
|
||||||
|
+{
|
||||||
|
+ return (nd->mnt);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Definitions for user and kernel code
|
||||||
|
*/
|
||||||
|
--- a/fs/mini_fo/super.c
|
||||||
|
+++ b/fs/mini_fo/super.c
|
||||||
|
@@ -262,10 +262,31 @@ mini_fo_umount_begin(super_block_t *sb)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
||||||
|
+struct inode *
|
||||||
|
+mini_fo_iget(struct super_block *sb, unsigned long ino)
|
||||||
|
+{
|
||||||
|
+ struct inode *inode;
|
||||||
|
+
|
||||||
|
+ inode = iget_locked(sb, ino);
|
||||||
|
+ if (!inode)
|
||||||
|
+ return ERR_PTR(-ENOMEM);
|
||||||
|
+
|
||||||
|
+ if (!(inode->i_state & I_NEW))
|
||||||
|
+ return inode;
|
||||||
|
+
|
||||||
|
+ mini_fo_read_inode(inode);
|
||||||
|
+
|
||||||
|
+ unlock_new_inode(inode);
|
||||||
|
+ return inode;
|
||||||
|
+}
|
||||||
|
+#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) */
|
||||||
|
|
||||||
|
struct super_operations mini_fo_sops =
|
||||||
|
{
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
|
||||||
|
read_inode: mini_fo_read_inode,
|
||||||
|
+#endif
|
||||||
|
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||||
|
write_inode: mini_fo_write_inode,
|
||||||
|
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
||||||
|
--- a/fs/mini_fo/aux.c
|
||||||
|
+++ b/fs/mini_fo/aux.c
|
||||||
|
@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
|
||||||
|
err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
|
||||||
|
|
||||||
|
/* validate */
|
||||||
|
- if (err || !nd.dentry || !nd.dentry->d_inode) {
|
||||||
|
+ if (err || !nd_get_dentry(&nd) || !nd_get_dentry(&nd)->d_inode) {
|
||||||
|
printk(KERN_CRIT "mini_fo: bpath_walk: path_walk failed.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
- return nd.dentry;
|
||||||
|
+ return nd_get_dentry(&nd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
--- a/fs/mini_fo/meta.c
|
||||||
|
+++ b/fs/mini_fo/meta.c
|
||||||
|
@@ -442,6 +442,11 @@ int meta_write_d_entry(dentry_t *dentry,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* $%& err, is this correct? */
|
||||||
|
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||||
|
+ mntget(meta_mnt);
|
||||||
|
+
|
||||||
|
/* open META-file for writing */
|
||||||
|
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
@@ -535,6 +540,11 @@ int meta_write_r_entry(dentry_t *dentry,
|
||||||
|
meta_dentry, S_IRUSR | S_IWUSR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* $%& err, is this correct? */
|
||||||
|
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||||
|
+ mntget(meta_mnt);
|
||||||
|
+
|
||||||
|
/* open META-file for writing */
|
||||||
|
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
@@ -671,14 +681,16 @@ int meta_sync_d_list(dentry_t *dentry, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* $%& err, is this correct? */
|
||||||
|
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||||
|
+ mntget(meta_mnt);
|
||||||
|
+
|
||||||
|
/* open META-file for writing */
|
||||||
|
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_sync_d_list: \
|
||||||
|
ERROR opening meta file.\n");
|
||||||
|
- /* we don't mntget so we dont't mntput (for now)
|
||||||
|
- * mntput(meta_mnt);
|
||||||
|
- */
|
||||||
|
+ mntput(meta_mnt);
|
||||||
|
dput(meta_dentry);
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
@@ -811,14 +823,16 @@ int meta_sync_r_list(dentry_t *dentry, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* $%& err, is this correct? */
|
||||||
|
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||||
|
+ mntget(meta_mnt);
|
||||||
|
+
|
||||||
|
/* open META-file for writing */
|
||||||
|
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_sync_r_list: \
|
||||||
|
ERROR opening meta file.\n");
|
||||||
|
- /* we don't mntget so we dont't mntput (for now)
|
||||||
|
- * mntput(meta_mnt);
|
||||||
|
- */
|
||||||
|
+ mntput(meta_mnt);
|
||||||
|
dput(meta_dentry);
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
@ -0,0 +1,37 @@
|
|||||||
|
--- a/fs/mini_fo/super.c
|
||||||
|
+++ b/fs/mini_fo/super.c
|
||||||
|
@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
|
||||||
|
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
||||||
|
|
||||||
|
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
|
||||||
|
STATIC void
|
||||||
|
mini_fo_put_inode(inode_t *inode)
|
||||||
|
{
|
||||||
|
@@ -99,6 +100,7 @@ mini_fo_put_inode(inode_t *inode)
|
||||||
|
if (atomic_read(&inode->i_count) == 1)
|
||||||
|
inode->i_nlink = 0;
|
||||||
|
}
|
||||||
|
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||||
|
@@ -238,7 +240,7 @@ mini_fo_clear_inode(inode_t *inode)
|
||||||
|
* dies.
|
||||||
|
*/
|
||||||
|
STATIC void
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
|
||||||
|
mini_fo_umount_begin(struct vfsmount *mnt, int flags)
|
||||||
|
{
|
||||||
|
struct vfsmount *hidden_mnt;
|
||||||
|
@@ -290,7 +292,9 @@ struct super_operations mini_fo_sops =
|
||||||
|
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||||
|
write_inode: mini_fo_write_inode,
|
||||||
|
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
|
||||||
|
put_inode: mini_fo_put_inode,
|
||||||
|
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */
|
||||||
|
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||||
|
delete_inode: mini_fo_delete_inode,
|
||||||
|
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
@ -0,0 +1,41 @@
|
|||||||
|
--- a/fs/mini_fo/inode.c
|
||||||
|
+++ b/fs/mini_fo/inode.c
|
||||||
|
@@ -439,7 +439,7 @@ mini_fo_symlink(inode_t *dir, dentry_t *
|
||||||
|
int err=0;
|
||||||
|
dentry_t *hidden_sto_dentry;
|
||||||
|
dentry_t *hidden_sto_dir_dentry;
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
|
||||||
|
umode_t mode;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -466,7 +466,7 @@ mini_fo_symlink(inode_t *dir, dentry_t *
|
||||||
|
down(&hidden_sto_dir_dentry->d_inode->i_sem);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
|
||||||
|
mode = S_IALLUGO;
|
||||||
|
err = vfs_symlink(hidden_sto_dir_dentry->d_inode,
|
||||||
|
hidden_sto_dentry, symname, mode);
|
||||||
|
@@ -1128,7 +1128,7 @@ void mini_fo_put_link(struct dentry *den
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
|
||||||
|
mini_fo_permission(inode_t *inode, int mask, struct nameidata *nd)
|
||||||
|
#else
|
||||||
|
mini_fo_permission(inode_t *inode, int mask)
|
||||||
|
@@ -1150,8 +1150,9 @@ mini_fo_permission(inode_t *inode, int m
|
||||||
|
* if (err)
|
||||||
|
* goto out;
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||||
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
|
||||||
|
+ err = inode_permission(hidden_inode, mask);
|
||||||
|
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||||
|
err = permission(hidden_inode, mask, nd);
|
||||||
|
#else
|
||||||
|
err = permission(hidden_inode, mask);
|
@ -0,0 +1,96 @@
|
|||||||
|
--- a/fs/mini_fo/aux.c
|
||||||
|
+++ b/fs/mini_fo/aux.c
|
||||||
|
@@ -236,7 +236,7 @@ int mini_fo_cp_cont(dentry_t *tgt_dentry
|
||||||
|
mntget(src_mnt);
|
||||||
|
|
||||||
|
/* open file write only */
|
||||||
|
- tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1);
|
||||||
|
+ tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1, current_cred());
|
||||||
|
if(!tgt_file || IS_ERR(tgt_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening target file.\n");
|
||||||
|
err = PTR_ERR(tgt_file);
|
||||||
|
@@ -244,7 +244,7 @@ int mini_fo_cp_cont(dentry_t *tgt_dentry
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open file read only */
|
||||||
|
- src_file = dentry_open(src_dentry, src_mnt, 0x0);
|
||||||
|
+ src_file = dentry_open(src_dentry, src_mnt, 0x0, current_cred());
|
||||||
|
if(!src_file || IS_ERR(src_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening source file.\n");
|
||||||
|
err = PTR_ERR(src_file);
|
||||||
|
--- a/fs/mini_fo/file.c
|
||||||
|
+++ b/fs/mini_fo/file.c
|
||||||
|
@@ -437,7 +437,7 @@ mini_fo_open(inode_t *inode, file_t *fil
|
||||||
|
mntget(stopd(inode->i_sb)->hidden_mnt);
|
||||||
|
hidden_file = dentry_open(hidden_dentry,
|
||||||
|
stopd(inode->i_sb)->hidden_mnt,
|
||||||
|
- hidden_flags);
|
||||||
|
+ hidden_flags, file->f_cred);
|
||||||
|
if (IS_ERR(hidden_file)) {
|
||||||
|
err = PTR_ERR(hidden_file);
|
||||||
|
dput(hidden_dentry);
|
||||||
|
@@ -479,7 +479,7 @@ mini_fo_open(inode_t *inode, file_t *fil
|
||||||
|
mntget(stopd(inode->i_sb)->hidden_mnt);
|
||||||
|
hidden_file = dentry_open(hidden_dentry,
|
||||||
|
stopd(inode->i_sb)->hidden_mnt,
|
||||||
|
- hidden_flags);
|
||||||
|
+ hidden_flags, file->f_cred);
|
||||||
|
if (IS_ERR(hidden_file)) {
|
||||||
|
err = PTR_ERR(hidden_file);
|
||||||
|
dput(hidden_dentry);
|
||||||
|
@@ -512,7 +512,7 @@ mini_fo_open(inode_t *inode, file_t *fil
|
||||||
|
mntget(stopd(inode->i_sb)->hidden_mnt2);
|
||||||
|
hidden_sto_file = dentry_open(hidden_sto_dentry,
|
||||||
|
stopd(inode->i_sb)->hidden_mnt2,
|
||||||
|
- hidden_flags);
|
||||||
|
+ hidden_flags, file->f_cred);
|
||||||
|
|
||||||
|
/* dentry_open dputs the dentry if it fails */
|
||||||
|
if (IS_ERR(hidden_sto_file)) {
|
||||||
|
--- a/fs/mini_fo/meta.c
|
||||||
|
+++ b/fs/mini_fo/meta.c
|
||||||
|
@@ -56,7 +56,7 @@ int meta_build_lists(dentry_t *dentry)
|
||||||
|
|
||||||
|
|
||||||
|
/* open META-file for reading */
|
||||||
|
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x0);
|
||||||
|
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x0, current_cred());
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_build_lists: \
|
||||||
|
ERROR opening META file.\n");
|
||||||
|
@@ -448,7 +448,7 @@ int meta_write_d_entry(dentry_t *dentry,
|
||||||
|
mntget(meta_mnt);
|
||||||
|
|
||||||
|
/* open META-file for writing */
|
||||||
|
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_write_d_entry: \
|
||||||
|
ERROR opening meta file.\n");
|
||||||
|
@@ -546,7 +546,7 @@ int meta_write_r_entry(dentry_t *dentry,
|
||||||
|
mntget(meta_mnt);
|
||||||
|
|
||||||
|
/* open META-file for writing */
|
||||||
|
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_write_r_entry: \
|
||||||
|
ERROR opening meta file.\n");
|
||||||
|
@@ -686,7 +686,7 @@ int meta_sync_d_list(dentry_t *dentry, i
|
||||||
|
mntget(meta_mnt);
|
||||||
|
|
||||||
|
/* open META-file for writing */
|
||||||
|
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_sync_d_list: \
|
||||||
|
ERROR opening meta file.\n");
|
||||||
|
@@ -828,7 +828,7 @@ int meta_sync_r_list(dentry_t *dentry, i
|
||||||
|
mntget(meta_mnt);
|
||||||
|
|
||||||
|
/* open META-file for writing */
|
||||||
|
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||||
|
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||||
|
if(!meta_file || IS_ERR(meta_file)) {
|
||||||
|
printk(KERN_CRIT "mini_fo: meta_sync_r_list: \
|
||||||
|
ERROR opening meta file.\n");
|
@ -0,0 +1,42 @@
|
|||||||
|
--- a/lib/kobject_uevent.c
|
||||||
|
+++ b/lib/kobject_uevent.c
|
||||||
|
@@ -29,7 +29,8 @@ u64 uevent_seqnum;
|
||||||
|
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
||||||
|
static DEFINE_SPINLOCK(sequence_lock);
|
||||||
|
#if defined(CONFIG_NET)
|
||||||
|
-static struct sock *uevent_sock;
|
||||||
|
+struct sock *uevent_sock = NULL;
|
||||||
|
+EXPORT_SYMBOL_GPL(uevent_sock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the strings here must match the enum in include/linux/kobject.h */
|
||||||
|
@@ -42,6 +43,18 @@ static const char *kobject_actions[] = {
|
||||||
|
[KOBJ_OFFLINE] = "offline",
|
||||||
|
};
|
||||||
|
|
||||||
|
+u64 uevent_next_seqnum(void)
|
||||||
|
+{
|
||||||
|
+ u64 seq;
|
||||||
|
+
|
||||||
|
+ spin_lock(&sequence_lock);
|
||||||
|
+ seq = ++uevent_seqnum;
|
||||||
|
+ spin_unlock(&sequence_lock);
|
||||||
|
+
|
||||||
|
+ return seq;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(uevent_next_seqnum);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* kobject_action_type - translate action string to numeric type
|
||||||
|
*
|
||||||
|
@@ -201,9 +214,7 @@ int kobject_uevent_env(struct kobject *k
|
||||||
|
kobj->state_remove_uevent_sent = 1;
|
||||||
|
|
||||||
|
/* we will send an event, so request a new sequence number */
|
||||||
|
- spin_lock(&sequence_lock);
|
||||||
|
- seq = ++uevent_seqnum;
|
||||||
|
- spin_unlock(&sequence_lock);
|
||||||
|
+ seq = uevent_next_seqnum();
|
||||||
|
retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
|
||||||
|
if (retval)
|
||||||
|
goto exit;
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/sound/core/Kconfig
|
||||||
|
+++ b/sound/core/Kconfig
|
||||||
|
@@ -7,7 +7,7 @@ config SND_PCM
|
||||||
|
select SND_TIMER
|
||||||
|
|
||||||
|
config SND_HWDEP
|
||||||
|
- tristate
|
||||||
|
+ tristate "Sound hardware support"
|
||||||
|
|
||||||
|
config SND_RAWMIDI
|
||||||
|
tristate
|
@ -0,0 +1,132 @@
|
|||||||
|
This patch allows the user to specify desired packet types (outgoing,
|
||||||
|
broadcast, unicast, etc.) on packet sockets via setsockopt.
|
||||||
|
This can reduce the load in situations where only a limited number
|
||||||
|
of packet types are necessary
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
|
||||||
|
--- a/include/linux/if_packet.h
|
||||||
|
+++ b/include/linux/if_packet.h
|
||||||
|
@@ -31,6 +31,8 @@ struct sockaddr_ll
|
||||||
|
/* These ones are invisible by user level */
|
||||||
|
#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
|
||||||
|
#define PACKET_FASTROUTE 6 /* Fastrouted frame */
|
||||||
|
+#define PACKET_ANY 0xffffffff
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Packet socket options */
|
||||||
|
|
||||||
|
@@ -46,6 +48,7 @@ struct sockaddr_ll
|
||||||
|
#define PACKET_VERSION 10
|
||||||
|
#define PACKET_HDRLEN 11
|
||||||
|
#define PACKET_RESERVE 12
|
||||||
|
+#define PACKET_RECV_TYPE 13
|
||||||
|
|
||||||
|
struct tpacket_stats
|
||||||
|
{
|
||||||
|
--- a/net/packet/af_packet.c
|
||||||
|
+++ b/net/packet/af_packet.c
|
||||||
|
@@ -192,6 +192,7 @@ struct packet_sock {
|
||||||
|
unsigned int tp_hdrlen;
|
||||||
|
unsigned int tp_reserve;
|
||||||
|
#endif
|
||||||
|
+ int pkt_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct packet_skb_cb {
|
||||||
|
@@ -282,6 +283,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||||
|
{
|
||||||
|
struct sock *sk;
|
||||||
|
struct sockaddr_pkt *spkt;
|
||||||
|
+ struct packet_sock *po;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we registered the protocol we saved the socket in the data
|
||||||
|
@@ -289,6 +291,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||||
|
*/
|
||||||
|
|
||||||
|
sk = pt->af_packet_priv;
|
||||||
|
+ po = pkt_sk(sk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Yank back the headers [hope the device set this
|
||||||
|
@@ -301,7 +304,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||||
|
* so that this procedure is noop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- if (skb->pkt_type == PACKET_LOOPBACK)
|
||||||
|
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (dev_net(dev) != sock_net(sk))
|
||||||
|
@@ -486,12 +489,12 @@ static int packet_rcv(struct sk_buff *sk
|
||||||
|
int skb_len = skb->len;
|
||||||
|
unsigned int snaplen, res;
|
||||||
|
|
||||||
|
- if (skb->pkt_type == PACKET_LOOPBACK)
|
||||||
|
- goto drop;
|
||||||
|
-
|
||||||
|
sk = pt->af_packet_priv;
|
||||||
|
po = pkt_sk(sk);
|
||||||
|
|
||||||
|
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
|
||||||
|
+ goto drop;
|
||||||
|
+
|
||||||
|
if (dev_net(dev) != sock_net(sk))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
|
@@ -608,12 +611,12 @@ static int tpacket_rcv(struct sk_buff *s
|
||||||
|
struct timeval tv;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
- if (skb->pkt_type == PACKET_LOOPBACK)
|
||||||
|
- goto drop;
|
||||||
|
-
|
||||||
|
sk = pt->af_packet_priv;
|
||||||
|
po = pkt_sk(sk);
|
||||||
|
|
||||||
|
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
|
||||||
|
+ goto drop;
|
||||||
|
+
|
||||||
|
if (dev_net(dev) != sock_net(sk))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
|
@@ -1072,6 +1075,7 @@ static int packet_create(struct net *net
|
||||||
|
spin_lock_init(&po->bind_lock);
|
||||||
|
mutex_init(&po->pg_vec_lock);
|
||||||
|
po->prot_hook.func = packet_rcv;
|
||||||
|
+ po->pkt_type = PACKET_ANY & ~PACKET_LOOPBACK;
|
||||||
|
|
||||||
|
if (sock->type == SOCK_PACKET)
|
||||||
|
po->prot_hook.func = packet_rcv_spkt;
|
||||||
|
@@ -1412,6 +1416,16 @@ packet_setsockopt(struct socket *sock, i
|
||||||
|
ret = packet_mc_drop(sk, &mreq);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
+ case PACKET_RECV_TYPE:
|
||||||
|
+ {
|
||||||
|
+ int val;
|
||||||
|
+ if (optlen != sizeof(val))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ if (copy_from_user(&val, optval, sizeof(val)))
|
||||||
|
+ return -EFAULT;
|
||||||
|
+ po->pkt_type = val & ~PACKET_LOOPBACK;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
#ifdef CONFIG_PACKET_MMAP
|
||||||
|
case PACKET_RX_RING:
|
||||||
|
@@ -1543,6 +1557,13 @@ static int packet_getsockopt(struct sock
|
||||||
|
|
||||||
|
data = &val;
|
||||||
|
break;
|
||||||
|
+ case PACKET_RECV_TYPE:
|
||||||
|
+ if (len > sizeof(int))
|
||||||
|
+ len = sizeof(int);
|
||||||
|
+ val = po->pkt_type;
|
||||||
|
+
|
||||||
|
+ data = &val;
|
||||||
|
+ break;
|
||||||
|
#ifdef CONFIG_PACKET_MMAP
|
||||||
|
case PACKET_VERSION:
|
||||||
|
if (len > sizeof(int))
|
@ -0,0 +1,18 @@
|
|||||||
|
--- a/drivers/leds/Kconfig
|
||||||
|
+++ b/drivers/leds/Kconfig
|
||||||
|
@@ -295,4 +295,8 @@ config LEDS_TRIGGER_DEFAULT_ON
|
||||||
|
comment "iptables trigger is under Netfilter config (LED target)"
|
||||||
|
depends on LEDS_TRIGGERS
|
||||||
|
|
||||||
|
+config LEDS_TRIGGER_MORSE
|
||||||
|
+ tristate "LED Morse Trigger"
|
||||||
|
+ depends on LEDS_TRIGGERS
|
||||||
|
+
|
||||||
|
endif # NEW_LEDS
|
||||||
|
--- a/drivers/leds/Makefile
|
||||||
|
+++ b/drivers/leds/Makefile
|
||||||
|
@@ -38,3 +38,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=
|
||||||
|
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
|
||||||
|
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
|
||||||
|
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
|
||||||
|
+obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
@ -0,0 +1,21 @@
|
|||||||
|
--- a/drivers/leds/Kconfig
|
||||||
|
+++ b/drivers/leds/Kconfig
|
||||||
|
@@ -299,4 +299,11 @@ config LEDS_TRIGGER_MORSE
|
||||||
|
tristate "LED Morse Trigger"
|
||||||
|
depends on LEDS_TRIGGERS
|
||||||
|
|
||||||
|
+config LEDS_TRIGGER_NETDEV
|
||||||
|
+ tristate "LED Netdev Trigger"
|
||||||
|
+ depends on LEDS_TRIGGERS
|
||||||
|
+ help
|
||||||
|
+ This allows LEDs to be controlled by network device activity.
|
||||||
|
+ If unsure, say Y.
|
||||||
|
+
|
||||||
|
endif # NEW_LEDS
|
||||||
|
--- a/drivers/leds/Makefile
|
||||||
|
+++ b/drivers/leds/Makefile
|
||||||
|
@@ -39,3 +39,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
|
||||||
|
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
|
||||||
|
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
|
||||||
|
obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
||||||
|
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
|
@ -0,0 +1,30 @@
|
|||||||
|
--- a/drivers/input/misc/Kconfig
|
||||||
|
+++ b/drivers/input/misc/Kconfig
|
||||||
|
@@ -227,4 +227,20 @@ config INPUT_PCF50633_PMU
|
||||||
|
Say Y to include support for delivering PMU events via input
|
||||||
|
layer on NXP PCF50633.
|
||||||
|
|
||||||
|
+config INPUT_GPIO_BUTTONS
|
||||||
|
+ tristate "Polled GPIO buttons interface"
|
||||||
|
+ depends on GENERIC_GPIO
|
||||||
|
+ select INPUT_POLLDEV
|
||||||
|
+ help
|
||||||
|
+ This driver implements support for buttons connected
|
||||||
|
+ to GPIO pins of various CPUs (and some other chips).
|
||||||
|
+
|
||||||
|
+ Say Y here if your device has buttons connected
|
||||||
|
+ directly to such GPIO pins. Your board-specific
|
||||||
|
+ setup logic must also provide a platform device,
|
||||||
|
+ with configuration data saying which GPIOs are used.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the
|
||||||
|
+ module will be called gpio-buttons.
|
||||||
|
+
|
||||||
|
endif
|
||||||
|
--- a/drivers/input/misc/Makefile
|
||||||
|
+++ b/drivers/input/misc/Makefile
|
||||||
|
@@ -22,3 +22,4 @@ obj-$(CONFIG_INPUT_UINPUT) += uinput.o
|
||||||
|
obj-$(CONFIG_INPUT_APANEL) += apanel.o
|
||||||
|
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
|
||||||
|
obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
|
||||||
|
+obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o
|
26
target/linux/generic-2.6/patches-2.6.30/420-gpiodev.patch
Normal file
26
target/linux/generic-2.6/patches-2.6.30/420-gpiodev.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
--- a/drivers/char/Kconfig
|
||||||
|
+++ b/drivers/char/Kconfig
|
||||||
|
@@ -1016,6 +1016,13 @@ config CS5535_GPIO
|
||||||
|
|
||||||
|
If compiled as a module, it will be called cs5535_gpio.
|
||||||
|
|
||||||
|
+config GPIO_DEVICE
|
||||||
|
+ tristate "GPIO device support"
|
||||||
|
+ depends on GENERIC_GPIO
|
||||||
|
+ help
|
||||||
|
+ Say Y to enable Linux GPIO device support. This allows control of
|
||||||
|
+ GPIO pins using a character device
|
||||||
|
+
|
||||||
|
config GPIO_VR41XX
|
||||||
|
tristate "NEC VR4100 series General-purpose I/O Unit support"
|
||||||
|
depends on CPU_VR41XX
|
||||||
|
--- a/drivers/char/Makefile
|
||||||
|
+++ b/drivers/char/Makefile
|
||||||
|
@@ -94,6 +94,7 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio
|
||||||
|
obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
|
||||||
|
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
|
||||||
|
obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
|
||||||
|
+obj-$(CONFIG_GPIO_DEVICE) += gpio_dev.o
|
||||||
|
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
|
||||||
|
obj-$(CONFIG_GPIO_TB0219) += tb0219.o
|
||||||
|
obj-$(CONFIG_TELCLOCK) += tlclk.o
|
@ -0,0 +1,17 @@
|
|||||||
|
--- a/fs/Kconfig
|
||||||
|
+++ b/fs/Kconfig
|
||||||
|
@@ -177,6 +177,7 @@ source "fs/romfs/Kconfig"
|
||||||
|
source "fs/sysv/Kconfig"
|
||||||
|
source "fs/ufs/Kconfig"
|
||||||
|
source "fs/exofs/Kconfig"
|
||||||
|
+source "fs/yaffs2/Kconfig"
|
||||||
|
|
||||||
|
config NILFS2_FS
|
||||||
|
tristate "NILFS2 file system support (EXPERIMENTAL)"
|
||||||
|
--- a/fs/Makefile
|
||||||
|
+++ b/fs/Makefile
|
||||||
|
@@ -125,3 +125,4 @@ obj-$(CONFIG_OCFS2_FS) += ocfs2/
|
||||||
|
obj-$(CONFIG_BTRFS_FS) += btrfs/
|
||||||
|
obj-$(CONFIG_GFS2_FS) += gfs2/
|
||||||
|
obj-$(CONFIG_EXOFS_FS) += exofs/
|
||||||
|
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
|
12344
target/linux/generic-2.6/patches-2.6.30/511-yaffs-cvs-2009-04-24.patch
Normal file
12344
target/linux/generic-2.6/patches-2.6.30/511-yaffs-cvs-2009-04-24.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,83 @@
|
|||||||
|
--- a/drivers/net/phy/phy.c
|
||||||
|
+++ b/drivers/net/phy/phy.c
|
||||||
|
@@ -299,6 +299,50 @@ int phy_ethtool_gset(struct phy_device *
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(phy_ethtool_gset);
|
||||||
|
|
||||||
|
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
|
||||||
|
+{
|
||||||
|
+ u32 cmd;
|
||||||
|
+ int tmp;
|
||||||
|
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
|
||||||
|
+ struct ethtool_value edata = { ETHTOOL_GLINK };
|
||||||
|
+
|
||||||
|
+ if (get_user(cmd, (u32 *) useraddr))
|
||||||
|
+ return -EFAULT;
|
||||||
|
+
|
||||||
|
+ switch (cmd) {
|
||||||
|
+ case ETHTOOL_GSET:
|
||||||
|
+ phy_ethtool_gset(phydev, &ecmd);
|
||||||
|
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
|
||||||
|
+ return -EFAULT;
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ case ETHTOOL_SSET:
|
||||||
|
+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
|
||||||
|
+ return -EFAULT;
|
||||||
|
+ return phy_ethtool_sset(phydev, &ecmd);
|
||||||
|
+
|
||||||
|
+ case ETHTOOL_NWAY_RST:
|
||||||
|
+ /* if autoneg is off, it's an error */
|
||||||
|
+ tmp = phy_read(phydev, MII_BMCR);
|
||||||
|
+ if (tmp & BMCR_ANENABLE) {
|
||||||
|
+ tmp |= (BMCR_ANRESTART);
|
||||||
|
+ phy_write(phydev, MII_BMCR, tmp);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ case ETHTOOL_GLINK:
|
||||||
|
+ edata.data = (phy_read(phydev,
|
||||||
|
+ MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
|
||||||
|
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
|
||||||
|
+ return -EFAULT;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(phy_ethtool_ioctl);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* phy_mii_ioctl - generic PHY MII ioctl interface
|
||||||
|
* @phydev: the phy_device struct
|
||||||
|
@@ -355,8 +399,8 @@ int phy_mii_ioctl(struct phy_device *phy
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_write(phydev, mii_data->reg_num, val);
|
||||||
|
-
|
||||||
|
- if (mii_data->reg_num == MII_BMCR
|
||||||
|
+
|
||||||
|
+ if (mii_data->reg_num == MII_BMCR
|
||||||
|
&& val & BMCR_RESET
|
||||||
|
&& phydev->drv->config_init) {
|
||||||
|
phy_scan_fixups(phydev);
|
||||||
|
@@ -471,7 +515,7 @@ static void phy_force_reduction(struct p
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = phy_find_setting(phydev->speed, phydev->duplex);
|
||||||
|
-
|
||||||
|
+
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
idx = phy_find_valid(idx, phydev->supported);
|
||||||
|
--- a/include/linux/phy.h
|
||||||
|
+++ b/include/linux/phy.h
|
||||||
|
@@ -477,6 +477,7 @@ void phy_start_machine(struct phy_device
|
||||||
|
void phy_stop_machine(struct phy_device *phydev);
|
||||||
|
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||||
|
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||||
|
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
|
||||||
|
int phy_mii_ioctl(struct phy_device *phydev,
|
||||||
|
struct mii_ioctl_data *mii_data, int cmd);
|
||||||
|
int phy_start_interrupts(struct phy_device *phydev);
|
@ -0,0 +1,24 @@
|
|||||||
|
--- a/drivers/net/phy/Kconfig
|
||||||
|
+++ b/drivers/net/phy/Kconfig
|
||||||
|
@@ -82,6 +82,11 @@ config LSI_ET1011C_PHY
|
||||||
|
---help---
|
||||||
|
Supports the LSI ET1011C PHY.
|
||||||
|
|
||||||
|
+config ADM6996_PHY
|
||||||
|
+ tristate "Driver for ADM6996 switches"
|
||||||
|
+ ---help---
|
||||||
|
+ Currently supports the ADM6996F switch
|
||||||
|
+
|
||||||
|
config FIXED_PHY
|
||||||
|
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
||||||
|
depends on PHYLIB=y
|
||||||
|
--- a/drivers/net/phy/Makefile
|
||||||
|
+++ b/drivers/net/phy/Makefile
|
||||||
|
@@ -12,6 +12,7 @@ obj-$(CONFIG_SMSC_PHY) += smsc.o
|
||||||
|
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||||
|
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
||||||
|
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
||||||
|
+obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
||||||
|
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||||
|
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||||
|
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
@ -0,0 +1,63 @@
|
|||||||
|
--- a/drivers/net/phy/phy_device.c
|
||||||
|
+++ b/drivers/net/phy/phy_device.c
|
||||||
|
@@ -143,6 +143,18 @@ int phy_scan_fixups(struct phy_device *p
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(phy_scan_fixups);
|
||||||
|
|
||||||
|
+static int generic_receive_skb(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ skb->protocol = eth_type_trans(skb, skb->dev);
|
||||||
|
+ return netif_receive_skb(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int generic_rx(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ skb->protocol = eth_type_trans(skb, skb->dev);
|
||||||
|
+ return netif_rx(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
|
||||||
|
{
|
||||||
|
struct phy_device *dev;
|
||||||
|
@@ -168,6 +180,8 @@ struct phy_device* phy_device_create(str
|
||||||
|
dev->bus = bus;
|
||||||
|
|
||||||
|
dev->state = PHY_DOWN;
|
||||||
|
+ dev->netif_receive_skb = &generic_receive_skb;
|
||||||
|
+ dev->netif_rx = &generic_rx;
|
||||||
|
|
||||||
|
mutex_init(&dev->lock);
|
||||||
|
|
||||||
|
--- a/include/linux/phy.h
|
||||||
|
+++ b/include/linux/phy.h
|
||||||
|
@@ -325,6 +325,20 @@ struct phy_device {
|
||||||
|
void (*adjust_link)(struct net_device *dev);
|
||||||
|
|
||||||
|
void (*adjust_state)(struct net_device *dev);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * By default these point to the original functions
|
||||||
|
+ * with the same name. adding them to the phy_device
|
||||||
|
+ * allows the phy driver to override them for packet
|
||||||
|
+ * mangling if the ethernet driver supports it
|
||||||
|
+ * This is required to support some really horrible
|
||||||
|
+ * switches such as the Marvell 88E6060
|
||||||
|
+ */
|
||||||
|
+ int (*netif_receive_skb)(struct sk_buff *skb);
|
||||||
|
+ int (*netif_rx)(struct sk_buff *skb);
|
||||||
|
+
|
||||||
|
+ /* alignment offset for packets */
|
||||||
|
+ int pkt_align;
|
||||||
|
};
|
||||||
|
#define to_phy_device(d) container_of(d, struct phy_device, dev)
|
||||||
|
|
||||||
|
--- a/include/linux/netdevice.h
|
||||||
|
+++ b/include/linux/netdevice.h
|
||||||
|
@@ -770,6 +770,7 @@ struct net_device
|
||||||
|
void *ax25_ptr; /* AX.25 specific data */
|
||||||
|
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
|
||||||
|
assign before registering */
|
||||||
|
+ void *phy_ptr; /* PHY device specific data */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache line mostly used on receive path (including eth_type_trans())
|
25
target/linux/generic-2.6/patches-2.6.30/650-swconfig.patch
Normal file
25
target/linux/generic-2.6/patches-2.6.30/650-swconfig.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
--- a/drivers/net/phy/Kconfig
|
||||||
|
+++ b/drivers/net/phy/Kconfig
|
||||||
|
@@ -13,6 +13,12 @@ menuconfig PHYLIB
|
||||||
|
|
||||||
|
if PHYLIB
|
||||||
|
|
||||||
|
+config SWCONFIG
|
||||||
|
+ tristate "Switch configuration API"
|
||||||
|
+ ---help---
|
||||||
|
+ Switch configuration API using netlink. This allows
|
||||||
|
+ you to configure the VLAN features of certain switches.
|
||||||
|
+
|
||||||
|
comment "MII PHY device drivers"
|
||||||
|
|
||||||
|
config MARVELL_PHY
|
||||||
|
--- a/drivers/net/phy/Makefile
|
||||||
|
+++ b/drivers/net/phy/Makefile
|
||||||
|
@@ -3,6 +3,7 @@
|
||||||
|
libphy-objs := phy.o phy_device.o mdio_bus.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_PHYLIB) += libphy.o
|
||||||
|
+obj-$(CONFIG_SWCONFIG) += swconfig.o
|
||||||
|
obj-$(CONFIG_MARVELL_PHY) += marvell.o
|
||||||
|
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
|
||||||
|
obj-$(CONFIG_CICADA_PHY) += cicada.o
|
@ -0,0 +1,22 @@
|
|||||||
|
--- a/drivers/net/phy/Kconfig
|
||||||
|
+++ b/drivers/net/phy/Kconfig
|
||||||
|
@@ -93,6 +93,9 @@ config ADM6996_PHY
|
||||||
|
---help---
|
||||||
|
Currently supports the ADM6996F switch
|
||||||
|
|
||||||
|
+config MVSWITCH_PHY
|
||||||
|
+ tristate "Driver for Marvell 88E6060 switches"
|
||||||
|
+
|
||||||
|
config FIXED_PHY
|
||||||
|
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
||||||
|
depends on PHYLIB=y
|
||||||
|
--- a/drivers/net/phy/Makefile
|
||||||
|
+++ b/drivers/net/phy/Makefile
|
||||||
|
@@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||||
|
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
||||||
|
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
||||||
|
obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
||||||
|
+obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
||||||
|
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||||
|
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||||
|
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
250
target/linux/generic-2.6/patches-2.6.30/700-rtc7301.patch
Normal file
250
target/linux/generic-2.6/patches-2.6.30/700-rtc7301.patch
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
--- a/drivers/rtc/Kconfig
|
||||||
|
+++ b/drivers/rtc/Kconfig
|
||||||
|
@@ -526,6 +526,15 @@ config RTC_DRV_PCF50633
|
||||||
|
If you say yes here you get support for the RTC subsystem of the
|
||||||
|
NXP PCF50633 used in embedded systems.
|
||||||
|
|
||||||
|
+config RTC_DRV_RTC7301
|
||||||
|
+ tristate "Epson RTC-7301 SF/DG"
|
||||||
|
+ help
|
||||||
|
+ If you say Y here you will get support for the
|
||||||
|
+ Epson RTC-7301 SF/DG RTC chips.
|
||||||
|
+
|
||||||
|
+ This driver can also be built as a module. If so, the module
|
||||||
|
+ will be called rtc-7301.
|
||||||
|
+
|
||||||
|
comment "on-CPU RTC drivers"
|
||||||
|
|
||||||
|
config RTC_DRV_OMAP
|
||||||
|
--- a/drivers/rtc/Makefile
|
||||||
|
+++ b/drivers/rtc/Makefile
|
||||||
|
@@ -62,6 +62,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701
|
||||||
|
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
|
||||||
|
+obj-$(CONFIG_RTC_DRV_RTC7301) += rtc-rtc7301.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/rtc/rtc-rtc7301.c
|
||||||
|
@@ -0,0 +1,219 @@
|
||||||
|
+/*
|
||||||
|
+ * Driver for Epson RTC-7301SF/DG
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2009 Jose Vasconcellos
|
||||||
|
+ *
|
||||||
|
+ * 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/module.h>
|
||||||
|
+#include <linux/rtc.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
+#include <linux/bcd.h>
|
||||||
|
+
|
||||||
|
+#define RTC_NAME "rtc7301"
|
||||||
|
+#define RTC_VERSION "0.1"
|
||||||
|
+
|
||||||
|
+/* Epson RTC-7301 register addresses */
|
||||||
|
+#define RTC7301_SEC 0x00
|
||||||
|
+#define RTC7301_SEC10 0x01
|
||||||
|
+#define RTC7301_MIN 0x02
|
||||||
|
+#define RTC7301_MIN10 0x03
|
||||||
|
+#define RTC7301_HOUR 0x04
|
||||||
|
+#define RTC7301_HOUR10 0x05
|
||||||
|
+#define RTC7301_WEEKDAY 0x06
|
||||||
|
+#define RTC7301_DAY 0x07
|
||||||
|
+#define RTC7301_DAY10 0x08
|
||||||
|
+#define RTC7301_MON 0x09
|
||||||
|
+#define RTC7301_MON10 0x0A
|
||||||
|
+#define RTC7301_YEAR 0x0B
|
||||||
|
+#define RTC7301_YEAR10 0x0C
|
||||||
|
+#define RTC7301_YEAR100 0x0D
|
||||||
|
+#define RTC7301_YEAR1000 0x0E
|
||||||
|
+#define RTC7301_CTRLREG 0x0F
|
||||||
|
+
|
||||||
|
+static uint8_t __iomem *rtc7301_base;
|
||||||
|
+
|
||||||
|
+#define read_reg(offset) (readb(rtc7301_base + offset) & 0xf)
|
||||||
|
+#define write_reg(offset, data) writeb(data, rtc7301_base + (offset))
|
||||||
|
+
|
||||||
|
+#define rtc7301_isbusy() (read_reg(RTC7301_CTRLREG) & 1)
|
||||||
|
+
|
||||||
|
+static void rtc7301_init_settings(void)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ write_reg(RTC7301_CTRLREG, 2);
|
||||||
|
+ write_reg(RTC7301_YEAR1000, 2);
|
||||||
|
+ udelay(122);
|
||||||
|
+
|
||||||
|
+ /* bank 1 */
|
||||||
|
+ write_reg(RTC7301_CTRLREG, 6);
|
||||||
|
+ for (i=0; i<15; i++)
|
||||||
|
+ write_reg(i, 0);
|
||||||
|
+
|
||||||
|
+ /* bank 2 */
|
||||||
|
+ write_reg(RTC7301_CTRLREG, 14);
|
||||||
|
+ for (i=0; i<15; i++)
|
||||||
|
+ write_reg(i, 0);
|
||||||
|
+ write_reg(RTC7301_CTRLREG, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int rtc7301_get_datetime(struct device *dev, struct rtc_time *dt)
|
||||||
|
+{
|
||||||
|
+ int cnt;
|
||||||
|
+ uint8_t buf[16];
|
||||||
|
+
|
||||||
|
+ cnt = 0;
|
||||||
|
+ while (rtc7301_isbusy()) {
|
||||||
|
+ udelay(244);
|
||||||
|
+ if (cnt++ > 100) {
|
||||||
|
+ dev_err(dev, "%s: timeout error %x\n", __func__, rtc7301_base[RTC7301_CTRLREG]);
|
||||||
|
+ return -EIO;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (cnt=0; cnt<16; cnt++)
|
||||||
|
+ buf[cnt] = read_reg(cnt);
|
||||||
|
+
|
||||||
|
+ if (buf[RTC7301_SEC10] & 8) {
|
||||||
|
+ dev_err(dev, "%s: RTC not set\n", __func__);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memset(dt, 0, sizeof(*dt));
|
||||||
|
+
|
||||||
|
+ dt->tm_sec = buf[RTC7301_SEC] + buf[RTC7301_SEC10]*10;
|
||||||
|
+ dt->tm_min = buf[RTC7301_MIN] + buf[RTC7301_MIN10]*10;
|
||||||
|
+ dt->tm_hour = buf[RTC7301_HOUR] + buf[RTC7301_HOUR10]*10;
|
||||||
|
+
|
||||||
|
+ dt->tm_mday = buf[RTC7301_DAY] + buf[RTC7301_DAY10]*10;
|
||||||
|
+ dt->tm_mon = buf[RTC7301_MON] + buf[RTC7301_MON10]*10 - 1;
|
||||||
|
+ dt->tm_year = buf[RTC7301_YEAR] + buf[RTC7301_YEAR10]*10 +
|
||||||
|
+ buf[RTC7301_YEAR100]*100 +
|
||||||
|
+ ((buf[RTC7301_YEAR1000] & 3)*1000) - 1900;
|
||||||
|
+
|
||||||
|
+ /* the rtc device may contain illegal values on power up
|
||||||
|
+ * according to the data sheet. make sure they are valid.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ return rtc_valid_tm(dt);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int rtc7301_set_datetime(struct device *dev, struct rtc_time *dt)
|
||||||
|
+{
|
||||||
|
+ int data;
|
||||||
|
+
|
||||||
|
+ data = dt->tm_year + 1900;
|
||||||
|
+ if (data >= 2100 || data < 1900)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ write_reg(RTC7301_CTRLREG, 2);
|
||||||
|
+ udelay(122);
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_sec);
|
||||||
|
+ write_reg(RTC7301_SEC, data);
|
||||||
|
+ write_reg(RTC7301_SEC10, (data >> 4));
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_min);
|
||||||
|
+ write_reg(RTC7301_MIN, data );
|
||||||
|
+ write_reg(RTC7301_MIN10, (data >> 4));
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_hour);
|
||||||
|
+ write_reg(RTC7301_HOUR, data);
|
||||||
|
+ write_reg(RTC7301_HOUR10, (data >> 4));
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_mday);
|
||||||
|
+ write_reg(RTC7301_DAY, data);
|
||||||
|
+ write_reg(RTC7301_DAY10, (data>> 4));
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_mon + 1);
|
||||||
|
+ write_reg(RTC7301_MON, data);
|
||||||
|
+ write_reg(RTC7301_MON10, (data >> 4));
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_year % 100);
|
||||||
|
+ write_reg(RTC7301_YEAR, data);
|
||||||
|
+ write_reg(RTC7301_YEAR10, (data >> 4));
|
||||||
|
+ data = bin2bcd((1900 + dt->tm_year) / 100);
|
||||||
|
+ write_reg(RTC7301_YEAR100, data);
|
||||||
|
+
|
||||||
|
+ data = bin2bcd(dt->tm_wday);
|
||||||
|
+ write_reg(RTC7301_WEEKDAY, data);
|
||||||
|
+
|
||||||
|
+ write_reg(RTC7301_CTRLREG, 0);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct rtc_class_ops rtc7301_rtc_ops = {
|
||||||
|
+ .read_time = rtc7301_get_datetime,
|
||||||
|
+ .set_time = rtc7301_set_datetime,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __devinit rtc7301_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct rtc_device *rtc;
|
||||||
|
+ struct resource *res;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ if (!res)
|
||||||
|
+ return -ENOENT;
|
||||||
|
+
|
||||||
|
+ rtc7301_base = ioremap_nocache(res->start, 0x1000 /*res->end - res->start + 1*/);
|
||||||
|
+ if (!rtc7301_base)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ rtc = rtc_device_register(RTC_NAME, &pdev->dev,
|
||||||
|
+ &rtc7301_rtc_ops, THIS_MODULE);
|
||||||
|
+ if (IS_ERR(rtc)) {
|
||||||
|
+ iounmap(rtc7301_base);
|
||||||
|
+ return PTR_ERR(rtc);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ platform_set_drvdata(pdev, rtc);
|
||||||
|
+
|
||||||
|
+ rtc7301_init_settings();
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __devexit rtc7301_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ if (rtc)
|
||||||
|
+ rtc_device_unregister(rtc);
|
||||||
|
+ if (rtc7301_base)
|
||||||
|
+ iounmap(rtc7301_base);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct platform_driver rtc7301_driver = {
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = RTC_NAME,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ },
|
||||||
|
+ .probe = rtc7301_probe,
|
||||||
|
+ .remove = __devexit_p(rtc7301_remove),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static __init int rtc7301_init(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_register(&rtc7301_driver);
|
||||||
|
+}
|
||||||
|
+module_init(rtc7301_init);
|
||||||
|
+
|
||||||
|
+static __exit void rtc7301_exit(void)
|
||||||
|
+{
|
||||||
|
+ platform_driver_unregister(&rtc7301_driver);
|
||||||
|
+}
|
||||||
|
+module_exit(rtc7301_exit);
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("Epson 7301 RTC driver");
|
||||||
|
+MODULE_AUTHOR("Jose Vasconcellos <jvasco@verizon.net>");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+MODULE_ALIAS("platform:" RTC_NAME);
|
||||||
|
+MODULE_VERSION(RTC_VERSION);
|
@ -0,0 +1,25 @@
|
|||||||
|
--- a/drivers/usb/serial/usb-serial.c
|
||||||
|
+++ b/drivers/usb/serial/usb-serial.c
|
||||||
|
@@ -60,6 +60,7 @@ static struct usb_driver usb_serial_driv
|
||||||
|
drivers depend on it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+static ushort maxSize = 0;
|
||||||
|
static int debug;
|
||||||
|
/* initially all NULL */
|
||||||
|
static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
|
||||||
|
@@ -841,7 +842,7 @@ int usb_serial_probe(struct usb_interfac
|
||||||
|
dev_err(&interface->dev, "No free urbs available\n");
|
||||||
|
goto probe_error;
|
||||||
|
}
|
||||||
|
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||||
|
+ buffer_size = (endpoint->wMaxPacketSize > maxSize) ? endpoint->wMaxPacketSize : maxSize;
|
||||||
|
port->bulk_in_size = buffer_size;
|
||||||
|
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
|
||||||
|
port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||||
|
@@ -1279,3 +1280,5 @@ MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||||
|
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||||
|
+module_param(maxSize, ushort,0);
|
||||||
|
+MODULE_PARM_DESC(maxSize,"User specified USB endpoint size");
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/init/main.c
|
||||||
|
+++ b/init/main.c
|
||||||
|
@@ -807,7 +807,7 @@ static noinline int init_post(void)
|
||||||
|
numa_default_policy();
|
||||||
|
|
||||||
|
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
|
||||||
|
- printk(KERN_WARNING "Warning: unable to open an initial console.\n");
|
||||||
|
+ printk(KERN_WARNING "Please be patient, while OpenWrt loads ...\n");
|
||||||
|
|
||||||
|
(void) sys_dup(0);
|
||||||
|
(void) sys_dup(0);
|
@ -0,0 +1,102 @@
|
|||||||
|
--- a/scripts/genksyms/parse.c_shipped
|
||||||
|
+++ b/scripts/genksyms/parse.c_shipped
|
||||||
|
@@ -160,7 +160,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
+#ifndef __APPLE__
|
||||||
|
#include <malloc.h>
|
||||||
|
+#endif
|
||||||
|
#include "genksyms.h"
|
||||||
|
|
||||||
|
static int is_typedef;
|
||||||
|
--- a/scripts/genksyms/parse.y
|
||||||
|
+++ b/scripts/genksyms/parse.y
|
||||||
|
@@ -24,7 +24,9 @@
|
||||||
|
%{
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
+#ifndef __APPLE__
|
||||||
|
#include <malloc.h>
|
||||||
|
+#endif
|
||||||
|
#include "genksyms.h"
|
||||||
|
|
||||||
|
static int is_typedef;
|
||||||
|
--- a/scripts/kallsyms.c
|
||||||
|
+++ b/scripts/kallsyms.c
|
||||||
|
@@ -22,6 +22,35 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
+#ifdef __APPLE__
|
||||||
|
+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */
|
||||||
|
+void *memmem (const void *haystack, size_t haystack_len,
|
||||||
|
+ const void *needle, size_t needle_len)
|
||||||
|
+{
|
||||||
|
+ const char *begin;
|
||||||
|
+ const char *const last_possible
|
||||||
|
+ = (const char *) haystack + haystack_len - needle_len;
|
||||||
|
+
|
||||||
|
+ if (needle_len == 0)
|
||||||
|
+ /* The first occurrence of the empty string is deemed to occur at
|
||||||
|
+ the beginning of the string. */
|
||||||
|
+ return (void *) haystack;
|
||||||
|
+
|
||||||
|
+ /* Sanity check, otherwise the loop might search through the whole
|
||||||
|
+ memory. */
|
||||||
|
+ if (__builtin_expect (haystack_len < needle_len, 0))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ for (begin = (const char *) haystack; begin <= last_possible; ++begin)
|
||||||
|
+ if (begin[0] == ((const char *) needle)[0] &&
|
||||||
|
+ !memcmp ((const void *) &begin[1],
|
||||||
|
+ (const void *) ((const char *) needle + 1),
|
||||||
|
+ needle_len - 1))
|
||||||
|
+ return (void *) begin;
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
#define KSYM_NAME_LEN 128
|
||||||
|
|
||||||
|
--- a/scripts/kconfig/Makefile
|
||||||
|
+++ b/scripts/kconfig/Makefile
|
||||||
|
@@ -97,6 +97,9 @@ check-lxdialog := $(srctree)/$(src)/lxd
|
||||||
|
# we really need to do so. (Do not call gcc as part of make mrproper)
|
||||||
|
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
|
||||||
|
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
|
||||||
|
+ifeq ($(shell uname -s),Darwin)
|
||||||
|
+HOST_LOADLIBES += -lncurses
|
||||||
|
+endif
|
||||||
|
|
||||||
|
HOST_EXTRACFLAGS += -DLOCALE
|
||||||
|
|
||||||
|
--- a/scripts/mod/mk_elfconfig.c
|
||||||
|
+++ b/scripts/mod/mk_elfconfig.c
|
||||||
|
@@ -1,7 +1,11 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
+#ifndef __APPLE__
|
||||||
|
#include <elf.h>
|
||||||
|
+#else
|
||||||
|
+#include "../../../../../tools/sstrip/include/elf.h"
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
--- a/scripts/mod/modpost.h
|
||||||
|
+++ b/scripts/mod/modpost.h
|
||||||
|
@@ -7,7 +7,11 @@
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
+#ifndef __APPLE__
|
||||||
|
#include <elf.h>
|
||||||
|
+#else
|
||||||
|
+#include "../../../../../tools/sstrip/include/elf.h"
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
#include "elfconfig.h"
|
||||||
|
|
154
target/linux/generic-2.6/patches-2.6.30/903-hostap_txpower.patch
Normal file
154
target/linux/generic-2.6/patches-2.6.30/903-hostap_txpower.patch
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
--- a/drivers/net/wireless/hostap/hostap_ap.c
|
||||||
|
+++ b/drivers/net/wireless/hostap/hostap_ap.c
|
||||||
|
@@ -2335,13 +2335,13 @@ int prism2_ap_get_sta_qual(local_info_t
|
||||||
|
addr[count].sa_family = ARPHRD_ETHER;
|
||||||
|
memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
|
||||||
|
if (sta->last_rx_silence == 0)
|
||||||
|
- qual[count].qual = sta->last_rx_signal < 27 ?
|
||||||
|
- 0 : (sta->last_rx_signal - 27) * 92 / 127;
|
||||||
|
+ qual[count].qual = (sta->last_rx_signal - 156) == 0 ?
|
||||||
|
+ 0 : (sta->last_rx_signal - 156) * 92 / 64;
|
||||||
|
else
|
||||||
|
- qual[count].qual = sta->last_rx_signal -
|
||||||
|
- sta->last_rx_silence - 35;
|
||||||
|
- qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
|
||||||
|
- qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
|
||||||
|
+ qual[count].qual = (sta->last_rx_signal -
|
||||||
|
+ sta->last_rx_silence) * 92 / 64;
|
||||||
|
+ qual[count].level = sta->last_rx_signal;
|
||||||
|
+ qual[count].noise = sta->last_rx_silence;
|
||||||
|
qual[count].updated = sta->last_rx_updated;
|
||||||
|
|
||||||
|
sta->last_rx_updated = IW_QUAL_DBM;
|
||||||
|
@@ -2407,13 +2407,13 @@ int prism2_ap_translate_scan(struct net_
|
||||||
|
memset(&iwe, 0, sizeof(iwe));
|
||||||
|
iwe.cmd = IWEVQUAL;
|
||||||
|
if (sta->last_rx_silence == 0)
|
||||||
|
- iwe.u.qual.qual = sta->last_rx_signal < 27 ?
|
||||||
|
- 0 : (sta->last_rx_signal - 27) * 92 / 127;
|
||||||
|
+ iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ?
|
||||||
|
+ 0 : (sta->last_rx_signal - 156) * 92 / 64;
|
||||||
|
else
|
||||||
|
- iwe.u.qual.qual = sta->last_rx_signal -
|
||||||
|
- sta->last_rx_silence - 35;
|
||||||
|
- iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
|
||||||
|
- iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
|
||||||
|
+ iwe.u.qual.qual = (sta->last_rx_signal -
|
||||||
|
+ sta->last_rx_silence) * 92 / 64;
|
||||||
|
+ iwe.u.qual.level = sta->last_rx_signal;
|
||||||
|
+ iwe.u.qual.noise = sta->last_rx_silence;
|
||||||
|
iwe.u.qual.updated = sta->last_rx_updated;
|
||||||
|
iwe.len = IW_EV_QUAL_LEN;
|
||||||
|
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
||||||
|
--- a/drivers/net/wireless/hostap/hostap_config.h
|
||||||
|
+++ b/drivers/net/wireless/hostap/hostap_config.h
|
||||||
|
@@ -45,4 +45,9 @@
|
||||||
|
*/
|
||||||
|
/* #define PRISM2_NO_STATION_MODES */
|
||||||
|
|
||||||
|
+/* Enable TX power Setting functions
|
||||||
|
+ * (min att = -128 , max att = 127)
|
||||||
|
+ */
|
||||||
|
+#define RAW_TXPOWER_SETTING
|
||||||
|
+
|
||||||
|
#endif /* HOSTAP_CONFIG_H */
|
||||||
|
--- a/drivers/net/wireless/hostap/hostap.h
|
||||||
|
+++ b/drivers/net/wireless/hostap/hostap.h
|
||||||
|
@@ -90,6 +90,7 @@ extern const struct iw_handler_def hosta
|
||||||
|
extern const struct ethtool_ops prism2_ethtool_ops;
|
||||||
|
|
||||||
|
int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||||
|
+int hostap_restore_power(struct net_device *dev);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HOSTAP_H */
|
||||||
|
--- a/drivers/net/wireless/hostap/hostap_hw.c
|
||||||
|
+++ b/drivers/net/wireless/hostap/hostap_hw.c
|
||||||
|
@@ -932,6 +932,7 @@ static int hfa384x_set_rid(struct net_de
|
||||||
|
prism2_hw_reset(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ hostap_restore_power(dev);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/drivers/net/wireless/hostap/hostap_info.c
|
||||||
|
+++ b/drivers/net/wireless/hostap/hostap_info.c
|
||||||
|
@@ -431,6 +431,11 @@ static void handle_info_queue_linkstatus
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get BSSID if we have a valid AP address */
|
||||||
|
+
|
||||||
|
+ if ( val == HFA384X_LINKSTATUS_CONNECTED ||
|
||||||
|
+ val == HFA384X_LINKSTATUS_DISCONNECTED )
|
||||||
|
+ hostap_restore_power(local->dev);
|
||||||
|
+
|
||||||
|
if (connected) {
|
||||||
|
netif_carrier_on(local->dev);
|
||||||
|
netif_carrier_on(local->ddev);
|
||||||
|
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
|
||||||
|
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
|
||||||
|
@@ -1475,23 +1475,20 @@ static int prism2_txpower_hfa386x_to_dBm
|
||||||
|
val = 255;
|
||||||
|
|
||||||
|
tmp = val;
|
||||||
|
- tmp >>= 2;
|
||||||
|
|
||||||
|
- return -12 - tmp;
|
||||||
|
+ return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16 prism2_txpower_dBm_to_hfa386x(int val)
|
||||||
|
{
|
||||||
|
signed char tmp;
|
||||||
|
|
||||||
|
- if (val > 20)
|
||||||
|
- return 128;
|
||||||
|
- else if (val < -43)
|
||||||
|
+ if (val > 127)
|
||||||
|
return 127;
|
||||||
|
+ else if (val < -128)
|
||||||
|
+ return 128;
|
||||||
|
|
||||||
|
tmp = val;
|
||||||
|
- tmp = -12 - tmp;
|
||||||
|
- tmp <<= 2;
|
||||||
|
|
||||||
|
return (unsigned char) tmp;
|
||||||
|
}
|
||||||
|
@@ -4055,3 +4052,35 @@ int hostap_ioctl(struct net_device *dev,
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/* BUG FIX: Restore power setting value when lost due to F/W bug */
|
||||||
|
+
|
||||||
|
+int hostap_restore_power(struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct hostap_interface *iface = dev->priv;
|
||||||
|
+ local_info_t *local = iface->local;
|
||||||
|
+
|
||||||
|
+ u16 val;
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ if (local->txpower_type == PRISM2_TXPOWER_OFF) {
|
||||||
|
+ val = 0xff; /* use all standby and sleep modes */
|
||||||
|
+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
|
||||||
|
+ HFA386X_CR_A_D_TEST_MODES2,
|
||||||
|
+ &val, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#ifdef RAW_TXPOWER_SETTING
|
||||||
|
+ if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
|
||||||
|
+ val = HFA384X_TEST_CFG_BIT_ALC;
|
||||||
|
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
|
||||||
|
+ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
|
||||||
|
+ val = prism2_txpower_dBm_to_hfa386x(local->txpower);
|
||||||
|
+ ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
|
||||||
|
+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL));
|
||||||
|
+ }
|
||||||
|
+#endif /* RAW_TXPOWER_SETTING */
|
||||||
|
+ return (ret ? -EOPNOTSUPP : 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+EXPORT_SYMBOL(hostap_restore_power);
|
@ -0,0 +1,17 @@
|
|||||||
|
--- a/include/linux/stddef.h
|
||||||
|
+++ b/include/linux/stddef.h
|
||||||
|
@@ -16,6 +16,7 @@ enum {
|
||||||
|
false = 0,
|
||||||
|
true = 1
|
||||||
|
};
|
||||||
|
+#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
#undef offsetof
|
||||||
|
#ifdef __compiler_offsetof
|
||||||
|
@@ -23,6 +24,5 @@ enum {
|
||||||
|
#else
|
||||||
|
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||||
|
#endif
|
||||||
|
-#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
#endif
|
10
target/linux/generic-2.6/patches-2.6.30/905-i386_build.patch
Normal file
10
target/linux/generic-2.6/patches-2.6.30/905-i386_build.patch
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
--- a/arch/x86/boot/tools/build.c
|
||||||
|
+++ b/arch/x86/boot/tools/build.c
|
||||||
|
@@ -29,7 +29,6 @@
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
-#include <sys/sysmacros.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
@ -0,0 +1,60 @@
|
|||||||
|
Fix spi-gpio for hotplug.
|
||||||
|
|
||||||
|
--mb
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi_gpio.c
|
||||||
|
+++ b/drivers/spi/spi_gpio.c
|
||||||
|
@@ -218,7 +218,7 @@ static void spi_gpio_cleanup(struct spi_
|
||||||
|
spi_bitbang_cleanup(spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
|
||||||
|
+static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
|
||||||
|
@@ -232,7 +232,7 @@ static int __init spi_gpio_alloc(unsigne
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __init
|
||||||
|
+static int __devinit
|
||||||
|
spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
@@ -261,7 +261,7 @@ done:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __init spi_gpio_probe(struct platform_device *pdev)
|
||||||
|
+static int __devinit spi_gpio_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct spi_master *master;
|
||||||
|
@@ -317,7 +317,7 @@ gpio_free:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __exit spi_gpio_remove(struct platform_device *pdev)
|
||||||
|
+static int __devexit spi_gpio_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct spi_gpio *spi_gpio;
|
||||||
|
struct spi_gpio_platform_data *pdata;
|
||||||
|
@@ -344,12 +344,13 @@ MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||||
|
static struct platform_driver spi_gpio_driver = {
|
||||||
|
.driver.name = DRIVER_NAME,
|
||||||
|
.driver.owner = THIS_MODULE,
|
||||||
|
- .remove = __exit_p(spi_gpio_remove),
|
||||||
|
+ .probe = spi_gpio_probe,
|
||||||
|
+ .remove = __devexit_p(spi_gpio_remove),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init spi_gpio_init(void)
|
||||||
|
{
|
||||||
|
- return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
|
||||||
|
+ return platform_driver_register(&spi_gpio_driver);
|
||||||
|
}
|
||||||
|
module_init(spi_gpio_init);
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
Implement the SPI-GPIO delay function for busses that need speed limitation.
|
||||||
|
|
||||||
|
--mb
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi_gpio.c
|
||||||
|
+++ b/drivers/spi/spi_gpio.c
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
#include <linux/spi/spi_bitbang.h>
|
||||||
|
@@ -69,6 +70,7 @@ struct spi_gpio {
|
||||||
|
* #define SPI_MOSI_GPIO 120
|
||||||
|
* #define SPI_SCK_GPIO 121
|
||||||
|
* #define SPI_N_CHIPSEL 4
|
||||||
|
+ * #undef NEED_SPIDELAY
|
||||||
|
* #include "spi_gpio.c"
|
||||||
|
*/
|
||||||
|
|
||||||
|
@@ -76,6 +78,7 @@ struct spi_gpio {
|
||||||
|
#define DRIVER_NAME "spi_gpio"
|
||||||
|
|
||||||
|
#define GENERIC_BITBANG /* vs tight inlines */
|
||||||
|
+#define NEED_SPIDELAY 1
|
||||||
|
|
||||||
|
/* all functions referencing these symbols must define pdata */
|
||||||
|
#define SPI_MISO_GPIO ((pdata)->miso)
|
||||||
|
@@ -120,12 +123,20 @@ static inline int getmiso(const struct s
|
||||||
|
#undef pdata
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * NOTE: this clocks "as fast as we can". It "should" be a function of the
|
||||||
|
- * requested device clock. Software overhead means we usually have trouble
|
||||||
|
- * reaching even one Mbit/sec (except when we can inline bitops), so for now
|
||||||
|
- * we'll just assume we never need additional per-bit slowdowns.
|
||||||
|
+ * NOTE: to clock "as fast as we can", set spi_device.max_speed_hz
|
||||||
|
+ * and spi_transfer.speed_hz to 0.
|
||||||
|
+ * Otherwise this is a function of the requested device clock.
|
||||||
|
+ * Software overhead means we usually have trouble
|
||||||
|
+ * reaching even one Mbit/sec (except when we can inline bitops). So on small
|
||||||
|
+ * embedded devices with fast SPI slaves you usually don't need a delay.
|
||||||
|
*/
|
||||||
|
-#define spidelay(nsecs) do {} while (0)
|
||||||
|
+static inline void spidelay(unsigned nsecs)
|
||||||
|
+{
|
||||||
|
+#ifdef NEED_SPIDELAY
|
||||||
|
+ if (unlikely(nsecs))
|
||||||
|
+ ndelay(nsecs);
|
||||||
|
+#endif /* NEED_SPIDELAY */
|
||||||
|
+}
|
||||||
|
|
||||||
|
#define EXPAND_BITBANG_TXRX
|
||||||
|
#include <linux/spi/spi_bitbang.h>
|
@ -0,0 +1,366 @@
|
|||||||
|
THIS CODE IS DEPRECATED.
|
||||||
|
|
||||||
|
Please use the new mainline SPI-GPIO driver, as of 2.6.29.
|
||||||
|
|
||||||
|
--mb
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/linux/spi/spi_gpio_old.h
|
||||||
|
@@ -0,0 +1,73 @@
|
||||||
|
+/*
|
||||||
|
+ * spi_gpio interface to platform code
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2008 Piotr Skamruk
|
||||||
|
+ * Copyright (c) 2008 Michael Buesch
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ */
|
||||||
|
+#ifndef _LINUX_SPI_SPI_GPIO
|
||||||
|
+#define _LINUX_SPI_SPI_GPIO
|
||||||
|
+
|
||||||
|
+#include <linux/types.h>
|
||||||
|
+#include <linux/spi/spi.h>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * struct spi_gpio_platform_data - Data definitions for a SPI-GPIO device.
|
||||||
|
+ *
|
||||||
|
+ * This structure holds information about a GPIO-based SPI device.
|
||||||
|
+ *
|
||||||
|
+ * @pin_clk: The GPIO pin number of the CLOCK pin.
|
||||||
|
+ *
|
||||||
|
+ * @pin_miso: The GPIO pin number of the MISO pin.
|
||||||
|
+ *
|
||||||
|
+ * @pin_mosi: The GPIO pin number of the MOSI pin.
|
||||||
|
+ *
|
||||||
|
+ * @pin_cs: The GPIO pin number of the CHIPSELECT pin.
|
||||||
|
+ *
|
||||||
|
+ * @cs_activelow: If true, the chip is selected when the CS line is low.
|
||||||
|
+ *
|
||||||
|
+ * @no_spi_delay: If true, no delay is done in the lowlevel bitbanging.
|
||||||
|
+ * Note that doing no delay is not standards compliant,
|
||||||
|
+ * but it might be needed to speed up transfers on some
|
||||||
|
+ * slow embedded machines.
|
||||||
|
+ *
|
||||||
|
+ * @boardinfo_setup: This callback is called after the
|
||||||
|
+ * SPI master device was registered, but before the
|
||||||
|
+ * device is registered.
|
||||||
|
+ * @boardinfo_setup_data: Data argument passed to boardinfo_setup().
|
||||||
|
+ */
|
||||||
|
+struct spi_gpio_platform_data {
|
||||||
|
+ unsigned int pin_clk;
|
||||||
|
+ unsigned int pin_miso;
|
||||||
|
+ unsigned int pin_mosi;
|
||||||
|
+ unsigned int pin_cs;
|
||||||
|
+ bool cs_activelow;
|
||||||
|
+ bool no_spi_delay;
|
||||||
|
+ int (*boardinfo_setup)(struct spi_board_info *bi,
|
||||||
|
+ struct spi_master *master,
|
||||||
|
+ void *data);
|
||||||
|
+ void *boardinfo_setup_data;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * SPI_GPIO_PLATDEV_NAME - The platform device name string.
|
||||||
|
+ *
|
||||||
|
+ * The name string that has to be used for platform_device_alloc
|
||||||
|
+ * when allocating a spi-gpio device.
|
||||||
|
+ */
|
||||||
|
+#define SPI_GPIO_PLATDEV_NAME "spi-gpio"
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * spi_gpio_next_id - Get another platform device ID number.
|
||||||
|
+ *
|
||||||
|
+ * This returns the next platform device ID number that has to be used
|
||||||
|
+ * for platform_device_alloc. The ID is opaque and should not be used for
|
||||||
|
+ * anything else.
|
||||||
|
+ */
|
||||||
|
+int spi_gpio_next_id(void);
|
||||||
|
+
|
||||||
|
+#endif /* _LINUX_SPI_SPI_GPIO */
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/spi/spi_gpio_old.c
|
||||||
|
@@ -0,0 +1,251 @@
|
||||||
|
+/*
|
||||||
|
+ * Bitbanging SPI bus driver using GPIO API
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2008 Piotr Skamruk
|
||||||
|
+ * Copyright (c) 2008 Michael Buesch
|
||||||
|
+ *
|
||||||
|
+ * based on spi_s3c2410_gpio.c
|
||||||
|
+ * Copyright (c) 2006 Ben Dooks
|
||||||
|
+ * Copyright (c) 2006 Simtec Electronics
|
||||||
|
+ * and on i2c-gpio.c
|
||||||
|
+ * Copyright (C) 2007 Atmel Corporation
|
||||||
|
+ *
|
||||||
|
+ * 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/init.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
+#include <linux/spinlock.h>
|
||||||
|
+#include <linux/workqueue.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/spi/spi.h>
|
||||||
|
+#include <linux/spi/spi_bitbang.h>
|
||||||
|
+#include <linux/spi/spi_gpio_old.h>
|
||||||
|
+#include <linux/gpio.h>
|
||||||
|
+#include <asm/atomic.h>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+struct spi_gpio {
|
||||||
|
+ struct spi_bitbang bitbang;
|
||||||
|
+ struct spi_gpio_platform_data *info;
|
||||||
|
+ struct platform_device *pdev;
|
||||||
|
+ struct spi_board_info bi;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev)
|
||||||
|
+{
|
||||||
|
+ return dev->controller_data;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void setsck(struct spi_device *dev, int val)
|
||||||
|
+{
|
||||||
|
+ struct spi_gpio *sp = spidev_to_sg(dev);
|
||||||
|
+ gpio_set_value(sp->info->pin_clk, val ? 1 : 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void setmosi(struct spi_device *dev, int val)
|
||||||
|
+{
|
||||||
|
+ struct spi_gpio *sp = spidev_to_sg(dev);
|
||||||
|
+ gpio_set_value(sp->info->pin_mosi, val ? 1 : 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline u32 getmiso(struct spi_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct spi_gpio *sp = spidev_to_sg(dev);
|
||||||
|
+ return gpio_get_value(sp->info->pin_miso) ? 1 : 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void do_spidelay(struct spi_device *dev, unsigned nsecs)
|
||||||
|
+{
|
||||||
|
+ struct spi_gpio *sp = spidev_to_sg(dev);
|
||||||
|
+
|
||||||
|
+ if (!sp->info->no_spi_delay)
|
||||||
|
+ ndelay(nsecs);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define spidelay(nsecs) do { \
|
||||||
|
+ /* Steal the spi_device pointer from our caller. \
|
||||||
|
+ * The bitbang-API should probably get fixed here... */ \
|
||||||
|
+ do_spidelay(spi, nsecs); \
|
||||||
|
+ } while (0)
|
||||||
|
+
|
||||||
|
+#define EXPAND_BITBANG_TXRX
|
||||||
|
+#include <linux/spi/spi_bitbang.h>
|
||||||
|
+
|
||||||
|
+static u32 spi_gpio_txrx_mode0(struct spi_device *spi,
|
||||||
|
+ unsigned nsecs, u32 word, u8 bits)
|
||||||
|
+{
|
||||||
|
+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static u32 spi_gpio_txrx_mode1(struct spi_device *spi,
|
||||||
|
+ unsigned nsecs, u32 word, u8 bits)
|
||||||
|
+{
|
||||||
|
+ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static u32 spi_gpio_txrx_mode2(struct spi_device *spi,
|
||||||
|
+ unsigned nsecs, u32 word, u8 bits)
|
||||||
|
+{
|
||||||
|
+ return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static u32 spi_gpio_txrx_mode3(struct spi_device *spi,
|
||||||
|
+ unsigned nsecs, u32 word, u8 bits)
|
||||||
|
+{
|
||||||
|
+ return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void spi_gpio_chipselect(struct spi_device *dev, int on)
|
||||||
|
+{
|
||||||
|
+ struct spi_gpio *sp = spidev_to_sg(dev);
|
||||||
|
+
|
||||||
|
+ if (sp->info->cs_activelow)
|
||||||
|
+ on = !on;
|
||||||
|
+ gpio_set_value(sp->info->pin_cs, on ? 1 : 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int spi_gpio_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct spi_master *master;
|
||||||
|
+ struct spi_gpio_platform_data *pdata;
|
||||||
|
+ struct spi_gpio *sp;
|
||||||
|
+ struct spi_device *spidev;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ pdata = pdev->dev.platform_data;
|
||||||
|
+ if (!pdata)
|
||||||
|
+ return -ENXIO;
|
||||||
|
+
|
||||||
|
+ err = -ENOMEM;
|
||||||
|
+ master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio));
|
||||||
|
+ if (!master)
|
||||||
|
+ goto err_alloc_master;
|
||||||
|
+
|
||||||
|
+ sp = spi_master_get_devdata(master);
|
||||||
|
+ platform_set_drvdata(pdev, sp);
|
||||||
|
+ sp->info = pdata;
|
||||||
|
+
|
||||||
|
+ err = gpio_request(pdata->pin_clk, "spi_clock");
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_request_clk;
|
||||||
|
+ err = gpio_request(pdata->pin_mosi, "spi_mosi");
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_request_mosi;
|
||||||
|
+ err = gpio_request(pdata->pin_miso, "spi_miso");
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_request_miso;
|
||||||
|
+ err = gpio_request(pdata->pin_cs, "spi_cs");
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_request_cs;
|
||||||
|
+
|
||||||
|
+ sp->bitbang.master = spi_master_get(master);
|
||||||
|
+ sp->bitbang.master->bus_num = -1;
|
||||||
|
+ sp->bitbang.master->num_chipselect = 1;
|
||||||
|
+ sp->bitbang.chipselect = spi_gpio_chipselect;
|
||||||
|
+ sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0;
|
||||||
|
+ sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1;
|
||||||
|
+ sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2;
|
||||||
|
+ sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3;
|
||||||
|
+
|
||||||
|
+ gpio_direction_output(pdata->pin_clk, 0);
|
||||||
|
+ gpio_direction_output(pdata->pin_mosi, 0);
|
||||||
|
+ gpio_direction_output(pdata->pin_cs,
|
||||||
|
+ pdata->cs_activelow ? 1 : 0);
|
||||||
|
+ gpio_direction_input(pdata->pin_miso);
|
||||||
|
+
|
||||||
|
+ err = spi_bitbang_start(&sp->bitbang);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_no_bitbang;
|
||||||
|
+ err = pdata->boardinfo_setup(&sp->bi, master,
|
||||||
|
+ pdata->boardinfo_setup_data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_bi_setup;
|
||||||
|
+ sp->bi.controller_data = sp;
|
||||||
|
+ spidev = spi_new_device(master, &sp->bi);
|
||||||
|
+ if (!spidev)
|
||||||
|
+ goto err_new_dev;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_new_dev:
|
||||||
|
+err_bi_setup:
|
||||||
|
+ spi_bitbang_stop(&sp->bitbang);
|
||||||
|
+err_no_bitbang:
|
||||||
|
+ spi_master_put(sp->bitbang.master);
|
||||||
|
+ gpio_free(pdata->pin_cs);
|
||||||
|
+err_request_cs:
|
||||||
|
+ gpio_free(pdata->pin_miso);
|
||||||
|
+err_request_miso:
|
||||||
|
+ gpio_free(pdata->pin_mosi);
|
||||||
|
+err_request_mosi:
|
||||||
|
+ gpio_free(pdata->pin_clk);
|
||||||
|
+err_request_clk:
|
||||||
|
+ kfree(master);
|
||||||
|
+
|
||||||
|
+err_alloc_master:
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __devexit spi_gpio_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct spi_gpio *sp;
|
||||||
|
+ struct spi_gpio_platform_data *pdata;
|
||||||
|
+
|
||||||
|
+ pdata = pdev->dev.platform_data;
|
||||||
|
+ sp = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ gpio_free(pdata->pin_clk);
|
||||||
|
+ gpio_free(pdata->pin_mosi);
|
||||||
|
+ gpio_free(pdata->pin_miso);
|
||||||
|
+ gpio_free(pdata->pin_cs);
|
||||||
|
+ spi_bitbang_stop(&sp->bitbang);
|
||||||
|
+ spi_master_put(sp->bitbang.master);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct platform_driver spi_gpio_driver = {
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = SPI_GPIO_PLATDEV_NAME,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ },
|
||||||
|
+ .probe = spi_gpio_probe,
|
||||||
|
+ .remove = __devexit_p(spi_gpio_remove),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int spi_gpio_next_id(void)
|
||||||
|
+{
|
||||||
|
+ static atomic_t counter = ATOMIC_INIT(-1);
|
||||||
|
+
|
||||||
|
+ return atomic_inc_return(&counter);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(spi_gpio_next_id);
|
||||||
|
+
|
||||||
|
+static int __init spi_gpio_init(void)
|
||||||
|
+{
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = platform_driver_register(&spi_gpio_driver);
|
||||||
|
+ if (err)
|
||||||
|
+ printk(KERN_ERR "spi-gpio: register failed: %d\n", err);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+module_init(spi_gpio_init);
|
||||||
|
+
|
||||||
|
+static void __exit spi_gpio_exit(void)
|
||||||
|
+{
|
||||||
|
+ platform_driver_unregister(&spi_gpio_driver);
|
||||||
|
+}
|
||||||
|
+module_exit(spi_gpio_exit);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>");
|
||||||
|
+MODULE_AUTHOR("Michael Buesch");
|
||||||
|
+MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
--- a/drivers/spi/Kconfig
|
||||||
|
+++ b/drivers/spi/Kconfig
|
||||||
|
@@ -116,6 +116,15 @@ config SPI_GPIO
|
||||||
|
GPIO operations, you should be able to leverage that for better
|
||||||
|
speed with a custom version of this driver; see the source code.
|
||||||
|
|
||||||
|
+config SPI_GPIO_OLD
|
||||||
|
+ tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)"
|
||||||
|
+ depends on SPI_MASTER && GENERIC_GPIO
|
||||||
|
+ select SPI_BITBANG
|
||||||
|
+ help
|
||||||
|
+ This code is deprecated. Please use the new mainline SPI-GPIO driver.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
config SPI_IMX
|
||||||
|
tristate "Freescale iMX SPI controller"
|
||||||
|
depends on ARCH_IMX && EXPERIMENTAL
|
||||||
|
--- a/drivers/spi/Makefile
|
||||||
|
+++ b/drivers/spi/Makefile
|
||||||
|
@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitban
|
||||||
|
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
|
||||||
|
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
|
||||||
|
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
|
||||||
|
+obj-$(CONFIG_SPI_GPIO_OLD) += spi_gpio_old.o
|
||||||
|
obj-$(CONFIG_SPI_IMX) += spi_imx.o
|
||||||
|
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
|
||||||
|
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
|
838
target/linux/generic-2.6/patches-2.6.30/922-gpiommc.patch
Normal file
838
target/linux/generic-2.6/patches-2.6.30/922-gpiommc.patch
Normal file
@ -0,0 +1,838 @@
|
|||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/mmc/host/gpiommc.c
|
||||||
|
@@ -0,0 +1,608 @@
|
||||||
|
+/*
|
||||||
|
+ * Driver an MMC/SD card on a bitbanging GPIO SPI bus.
|
||||||
|
+ * This module hooks up the mmc_spi and spi_gpio modules and also
|
||||||
|
+ * provides a configfs interface.
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2008 Michael Buesch <mb@bu3sch.de>
|
||||||
|
+ *
|
||||||
|
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/mmc/gpiommc.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/list.h>
|
||||||
|
+#include <linux/mutex.h>
|
||||||
|
+#include <linux/spi/spi_gpio_old.h>
|
||||||
|
+#include <linux/configfs.h>
|
||||||
|
+#include <linux/gpio.h>
|
||||||
|
+#include <asm/atomic.h>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#define PFX "gpio-mmc: "
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+struct gpiommc_device {
|
||||||
|
+ struct platform_device *pdev;
|
||||||
|
+ struct platform_device *spi_pdev;
|
||||||
|
+ struct spi_board_info boardinfo;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("GPIO based MMC driver");
|
||||||
|
+MODULE_AUTHOR("Michael Buesch");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int gpiommc_boardinfo_setup(struct spi_board_info *bi,
|
||||||
|
+ struct spi_master *master,
|
||||||
|
+ void *data)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_device *d = data;
|
||||||
|
+ struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data;
|
||||||
|
+
|
||||||
|
+ /* Bind the SPI master to the MMC-SPI host driver. */
|
||||||
|
+ strlcpy(bi->modalias, "mmc_spi", sizeof(bi->modalias));
|
||||||
|
+
|
||||||
|
+ bi->max_speed_hz = pdata->max_bus_speed;
|
||||||
|
+ bi->bus_num = master->bus_num;
|
||||||
|
+ bi->mode = pdata->mode;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int gpiommc_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_platform_data *mmc_pdata = pdev->dev.platform_data;
|
||||||
|
+ struct spi_gpio_platform_data spi_pdata;
|
||||||
|
+ struct gpiommc_device *d;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = -ENXIO;
|
||||||
|
+ if (!mmc_pdata)
|
||||||
|
+ goto error;
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MMC_SPI_MODULE
|
||||||
|
+ err = request_module("mmc_spi");
|
||||||
|
+ if (err) {
|
||||||
|
+ printk(KERN_WARNING PFX
|
||||||
|
+ "Failed to request mmc_spi module.\n");
|
||||||
|
+ }
|
||||||
|
+#endif /* CONFIG_MMC_SPI_MODULE */
|
||||||
|
+
|
||||||
|
+ /* Allocate the GPIO-MMC device */
|
||||||
|
+ err = -ENOMEM;
|
||||||
|
+ d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||||
|
+ if (!d)
|
||||||
|
+ goto error;
|
||||||
|
+ d->pdev = pdev;
|
||||||
|
+
|
||||||
|
+ /* Create the SPI-GPIO device */
|
||||||
|
+ d->spi_pdev = platform_device_alloc(SPI_GPIO_PLATDEV_NAME,
|
||||||
|
+ spi_gpio_next_id());
|
||||||
|
+ if (!d->spi_pdev)
|
||||||
|
+ goto err_free_d;
|
||||||
|
+
|
||||||
|
+ memset(&spi_pdata, 0, sizeof(spi_pdata));
|
||||||
|
+ spi_pdata.pin_clk = mmc_pdata->pins.gpio_clk;
|
||||||
|
+ spi_pdata.pin_miso = mmc_pdata->pins.gpio_do;
|
||||||
|
+ spi_pdata.pin_mosi = mmc_pdata->pins.gpio_di;
|
||||||
|
+ spi_pdata.pin_cs = mmc_pdata->pins.gpio_cs;
|
||||||
|
+ spi_pdata.cs_activelow = mmc_pdata->pins.cs_activelow;
|
||||||
|
+ spi_pdata.no_spi_delay = mmc_pdata->no_spi_delay;
|
||||||
|
+ spi_pdata.boardinfo_setup = gpiommc_boardinfo_setup;
|
||||||
|
+ spi_pdata.boardinfo_setup_data = d;
|
||||||
|
+
|
||||||
|
+ err = platform_device_add_data(d->spi_pdev, &spi_pdata,
|
||||||
|
+ sizeof(spi_pdata));
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_free_pdev;
|
||||||
|
+ err = platform_device_add(d->spi_pdev);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_free_pdata;
|
||||||
|
+ platform_set_drvdata(pdev, d);
|
||||||
|
+
|
||||||
|
+ printk(KERN_INFO PFX "MMC-Card \"%s\" "
|
||||||
|
+ "attached to GPIO pins di=%u, do=%u, clk=%u, cs=%u\n",
|
||||||
|
+ mmc_pdata->name, mmc_pdata->pins.gpio_di,
|
||||||
|
+ mmc_pdata->pins.gpio_do,
|
||||||
|
+ mmc_pdata->pins.gpio_clk,
|
||||||
|
+ mmc_pdata->pins.gpio_cs);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_free_pdata:
|
||||||
|
+ kfree(d->spi_pdev->dev.platform_data);
|
||||||
|
+ d->spi_pdev->dev.platform_data = NULL;
|
||||||
|
+err_free_pdev:
|
||||||
|
+ platform_device_put(d->spi_pdev);
|
||||||
|
+err_free_d:
|
||||||
|
+ kfree(d);
|
||||||
|
+error:
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int gpiommc_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_device *d = platform_get_drvdata(pdev);
|
||||||
|
+ struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data;
|
||||||
|
+
|
||||||
|
+ platform_device_unregister(d->spi_pdev);
|
||||||
|
+ printk(KERN_INFO PFX "GPIO based MMC-Card \"%s\" removed\n",
|
||||||
|
+ pdata->name);
|
||||||
|
+ platform_device_put(d->spi_pdev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_GPIOMMC_CONFIGFS
|
||||||
|
+
|
||||||
|
+/* A device that was created through configfs */
|
||||||
|
+struct gpiommc_configfs_device {
|
||||||
|
+ struct config_item item;
|
||||||
|
+ /* The platform device, after registration. */
|
||||||
|
+ struct platform_device *pdev;
|
||||||
|
+ /* The configuration */
|
||||||
|
+ struct gpiommc_platform_data pdata;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define GPIO_INVALID -1
|
||||||
|
+
|
||||||
|
+static inline bool gpiommc_is_registered(struct gpiommc_configfs_device *dev)
|
||||||
|
+{
|
||||||
|
+ return (dev->pdev != NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline struct gpiommc_configfs_device *ci_to_gpiommc(struct config_item *item)
|
||||||
|
+{
|
||||||
|
+ return item ? container_of(item, struct gpiommc_configfs_device, item) : NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_DI = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "gpio_data_in",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_DO = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "gpio_data_out",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_CLK = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "gpio_clock",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_CS = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "gpio_chipselect",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_CS_activelow = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "gpio_chipselect_activelow",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_spimode = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "spi_mode",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_spidelay = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "spi_delay",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_max_bus_speed = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "max_bus_speed",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute gpiommc_attr_register = {
|
||||||
|
+ .ca_owner = THIS_MODULE,
|
||||||
|
+ .ca_name = "register",
|
||||||
|
+ .ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_attribute *gpiommc_config_attrs[] = {
|
||||||
|
+ &gpiommc_attr_DI,
|
||||||
|
+ &gpiommc_attr_DO,
|
||||||
|
+ &gpiommc_attr_CLK,
|
||||||
|
+ &gpiommc_attr_CS,
|
||||||
|
+ &gpiommc_attr_CS_activelow,
|
||||||
|
+ &gpiommc_attr_spimode,
|
||||||
|
+ &gpiommc_attr_spidelay,
|
||||||
|
+ &gpiommc_attr_max_bus_speed,
|
||||||
|
+ &gpiommc_attr_register,
|
||||||
|
+ NULL,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static ssize_t gpiommc_config_attr_show(struct config_item *item,
|
||||||
|
+ struct configfs_attribute *attr,
|
||||||
|
+ char *page)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
|
||||||
|
+ ssize_t count = 0;
|
||||||
|
+ unsigned int gpio;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ if (attr == &gpiommc_attr_DI) {
|
||||||
|
+ gpio = dev->pdata.pins.gpio_di;
|
||||||
|
+ if (gpio == GPIO_INVALID)
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "not configured\n");
|
||||||
|
+ else
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_DO) {
|
||||||
|
+ gpio = dev->pdata.pins.gpio_do;
|
||||||
|
+ if (gpio == GPIO_INVALID)
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "not configured\n");
|
||||||
|
+ else
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_CLK) {
|
||||||
|
+ gpio = dev->pdata.pins.gpio_clk;
|
||||||
|
+ if (gpio == GPIO_INVALID)
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "not configured\n");
|
||||||
|
+ else
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_CS) {
|
||||||
|
+ gpio = dev->pdata.pins.gpio_cs;
|
||||||
|
+ if (gpio == GPIO_INVALID)
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "not configured\n");
|
||||||
|
+ else
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_CS_activelow) {
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n",
|
||||||
|
+ dev->pdata.pins.cs_activelow);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_spimode) {
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n",
|
||||||
|
+ dev->pdata.mode);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_spidelay) {
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n",
|
||||||
|
+ !dev->pdata.no_spi_delay);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_max_bus_speed) {
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n",
|
||||||
|
+ dev->pdata.max_bus_speed);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_register) {
|
||||||
|
+ count = snprintf(page, PAGE_SIZE, "%u\n",
|
||||||
|
+ gpiommc_is_registered(dev));
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ WARN_ON(1);
|
||||||
|
+ err = -ENOSYS;
|
||||||
|
+out:
|
||||||
|
+ return err ? err : count;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int gpiommc_do_register(struct gpiommc_configfs_device *dev,
|
||||||
|
+ const char *name)
|
||||||
|
+{
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ if (gpiommc_is_registered(dev))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (!gpio_is_valid(dev->pdata.pins.gpio_di) ||
|
||||||
|
+ !gpio_is_valid(dev->pdata.pins.gpio_do) ||
|
||||||
|
+ !gpio_is_valid(dev->pdata.pins.gpio_clk) ||
|
||||||
|
+ !gpio_is_valid(dev->pdata.pins.gpio_cs)) {
|
||||||
|
+ printk(KERN_ERR PFX
|
||||||
|
+ "configfs: Invalid GPIO pin number(s)\n");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ strlcpy(dev->pdata.name, name,
|
||||||
|
+ sizeof(dev->pdata.name));
|
||||||
|
+
|
||||||
|
+ dev->pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME,
|
||||||
|
+ gpiommc_next_id());
|
||||||
|
+ if (!dev->pdev)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ err = platform_device_add_data(dev->pdev, &dev->pdata,
|
||||||
|
+ sizeof(dev->pdata));
|
||||||
|
+ if (err) {
|
||||||
|
+ platform_device_put(dev->pdev);
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+ err = platform_device_add(dev->pdev);
|
||||||
|
+ if (err) {
|
||||||
|
+ platform_device_put(dev->pdev);
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void gpiommc_do_unregister(struct gpiommc_configfs_device *dev)
|
||||||
|
+{
|
||||||
|
+ if (!gpiommc_is_registered(dev))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ platform_device_unregister(dev->pdev);
|
||||||
|
+ dev->pdev = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static ssize_t gpiommc_config_attr_store(struct config_item *item,
|
||||||
|
+ struct configfs_attribute *attr,
|
||||||
|
+ const char *page, size_t count)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
|
||||||
|
+ int err = -EINVAL;
|
||||||
|
+ unsigned long data;
|
||||||
|
+
|
||||||
|
+ if (attr == &gpiommc_attr_register) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (data == 1)
|
||||||
|
+ err = gpiommc_do_register(dev, item->ci_name);
|
||||||
|
+ if (data == 0) {
|
||||||
|
+ gpiommc_do_unregister(dev);
|
||||||
|
+ err = 0;
|
||||||
|
+ }
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (gpiommc_is_registered(dev)) {
|
||||||
|
+ /* The rest of the config parameters can only be set
|
||||||
|
+ * as long as the device is not registered, yet. */
|
||||||
|
+ err = -EBUSY;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (attr == &gpiommc_attr_DI) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (!gpio_is_valid(data))
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.pins.gpio_di = data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_DO) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (!gpio_is_valid(data))
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.pins.gpio_do = data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_CLK) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (!gpio_is_valid(data))
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.pins.gpio_clk = data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_CS) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (!gpio_is_valid(data))
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.pins.gpio_cs = data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_CS_activelow) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (data != 0 && data != 1)
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.pins.cs_activelow = data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_spimode) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ switch (data) {
|
||||||
|
+ case 0:
|
||||||
|
+ dev->pdata.mode = SPI_MODE_0;
|
||||||
|
+ break;
|
||||||
|
+ case 1:
|
||||||
|
+ dev->pdata.mode = SPI_MODE_1;
|
||||||
|
+ break;
|
||||||
|
+ case 2:
|
||||||
|
+ dev->pdata.mode = SPI_MODE_2;
|
||||||
|
+ break;
|
||||||
|
+ case 3:
|
||||||
|
+ dev->pdata.mode = SPI_MODE_3;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_spidelay) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (data != 0 && data != 1)
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.no_spi_delay = !data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (attr == &gpiommc_attr_max_bus_speed) {
|
||||||
|
+ err = strict_strtoul(page, 10, &data);
|
||||||
|
+ if (err)
|
||||||
|
+ goto out;
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (data > UINT_MAX)
|
||||||
|
+ goto out;
|
||||||
|
+ dev->pdata.max_bus_speed = data;
|
||||||
|
+ err = 0;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ WARN_ON(1);
|
||||||
|
+ err = -ENOSYS;
|
||||||
|
+out:
|
||||||
|
+ return err ? err : count;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void gpiommc_config_item_release(struct config_item *item)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
|
||||||
|
+
|
||||||
|
+ kfree(dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct configfs_item_operations gpiommc_config_item_ops = {
|
||||||
|
+ .release = gpiommc_config_item_release,
|
||||||
|
+ .show_attribute = gpiommc_config_attr_show,
|
||||||
|
+ .store_attribute = gpiommc_config_attr_store,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct config_item_type gpiommc_dev_ci_type = {
|
||||||
|
+ .ct_item_ops = &gpiommc_config_item_ops,
|
||||||
|
+ .ct_attrs = gpiommc_config_attrs,
|
||||||
|
+ .ct_owner = THIS_MODULE,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct config_item *gpiommc_make_item(struct config_group *group,
|
||||||
|
+ const char *name)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_configfs_device *dev;
|
||||||
|
+
|
||||||
|
+ if (strlen(name) > GPIOMMC_MAX_NAMELEN) {
|
||||||
|
+ printk(KERN_ERR PFX "configfs: device name too long\n");
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
|
+ if (!dev)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ config_item_init_type_name(&dev->item, name,
|
||||||
|
+ &gpiommc_dev_ci_type);
|
||||||
|
+
|
||||||
|
+ /* Assign default configuration */
|
||||||
|
+ dev->pdata.pins.gpio_di = GPIO_INVALID;
|
||||||
|
+ dev->pdata.pins.gpio_do = GPIO_INVALID;
|
||||||
|
+ dev->pdata.pins.gpio_clk = GPIO_INVALID;
|
||||||
|
+ dev->pdata.pins.gpio_cs = GPIO_INVALID;
|
||||||
|
+ dev->pdata.pins.cs_activelow = 1;
|
||||||
|
+ dev->pdata.mode = SPI_MODE_0;
|
||||||
|
+ dev->pdata.no_spi_delay = 0;
|
||||||
|
+ dev->pdata.max_bus_speed = 5000000; /* 5 MHz */
|
||||||
|
+
|
||||||
|
+ return &(dev->item);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void gpiommc_drop_item(struct config_group *group,
|
||||||
|
+ struct config_item *item)
|
||||||
|
+{
|
||||||
|
+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
|
||||||
|
+
|
||||||
|
+ gpiommc_do_unregister(dev);
|
||||||
|
+ kfree(dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct configfs_group_operations gpiommc_ct_group_ops = {
|
||||||
|
+ .make_item = gpiommc_make_item,
|
||||||
|
+ .drop_item = gpiommc_drop_item,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct config_item_type gpiommc_ci_type = {
|
||||||
|
+ .ct_group_ops = &gpiommc_ct_group_ops,
|
||||||
|
+ .ct_owner = THIS_MODULE,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct configfs_subsystem gpiommc_subsys = {
|
||||||
|
+ .su_group = {
|
||||||
|
+ .cg_item = {
|
||||||
|
+ .ci_namebuf = GPIOMMC_PLATDEV_NAME,
|
||||||
|
+ .ci_type = &gpiommc_ci_type,
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
+ .su_mutex = __MUTEX_INITIALIZER(gpiommc_subsys.su_mutex),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#endif /* CONFIG_GPIOMMC_CONFIGFS */
|
||||||
|
+
|
||||||
|
+static struct platform_driver gpiommc_plat_driver = {
|
||||||
|
+ .probe = gpiommc_probe,
|
||||||
|
+ .remove = gpiommc_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = GPIOMMC_PLATDEV_NAME,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int gpiommc_next_id(void)
|
||||||
|
+{
|
||||||
|
+ static atomic_t counter = ATOMIC_INIT(-1);
|
||||||
|
+
|
||||||
|
+ return atomic_inc_return(&counter);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(gpiommc_next_id);
|
||||||
|
+
|
||||||
|
+static int __init gpiommc_modinit(void)
|
||||||
|
+{
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = platform_driver_register(&gpiommc_plat_driver);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_GPIOMMC_CONFIGFS
|
||||||
|
+ config_group_init(&gpiommc_subsys.su_group);
|
||||||
|
+ err = configfs_register_subsystem(&gpiommc_subsys);
|
||||||
|
+ if (err) {
|
||||||
|
+ platform_driver_unregister(&gpiommc_plat_driver);
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+#endif /* CONFIG_GPIOMMC_CONFIGFS */
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+module_init(gpiommc_modinit);
|
||||||
|
+
|
||||||
|
+static void __exit gpiommc_modexit(void)
|
||||||
|
+{
|
||||||
|
+#ifdef CONFIG_GPIOMMC_CONFIGFS
|
||||||
|
+ configfs_unregister_subsystem(&gpiommc_subsys);
|
||||||
|
+#endif
|
||||||
|
+ platform_driver_unregister(&gpiommc_plat_driver);
|
||||||
|
+}
|
||||||
|
+module_exit(gpiommc_modexit);
|
||||||
|
--- a/drivers/mmc/host/Kconfig
|
||||||
|
+++ b/drivers/mmc/host/Kconfig
|
||||||
|
@@ -241,3 +241,28 @@ config MMC_TMIO
|
||||||
|
help
|
||||||
|
This provides support for the SD/MMC cell found in TC6393XB,
|
||||||
|
T7L66XB and also ipaq ASIC3
|
||||||
|
+
|
||||||
|
+config GPIOMMC
|
||||||
|
+ tristate "MMC/SD over GPIO-based SPI"
|
||||||
|
+ depends on MMC && MMC_SPI && SPI_GPIO
|
||||||
|
+ help
|
||||||
|
+ This driver hooks up the mmc_spi and spi_gpio modules so that
|
||||||
|
+ MMC/SD cards can be used on a GPIO based bus by bitbanging
|
||||||
|
+ the SPI protocol in software.
|
||||||
|
+
|
||||||
|
+ This driver provides a configfs interface to dynamically create
|
||||||
|
+ and destroy GPIO-based MMC/SD card devices. It also provides
|
||||||
|
+ a platform device interface API.
|
||||||
|
+ See Documentation/gpiommc.txt for details.
|
||||||
|
+
|
||||||
|
+ The module will be called gpiommc.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
+config GPIOMMC_CONFIGFS
|
||||||
|
+ bool
|
||||||
|
+ depends on GPIOMMC && CONFIGFS_FS
|
||||||
|
+ default y
|
||||||
|
+ help
|
||||||
|
+ This option automatically enables configfs support for gpiommc
|
||||||
|
+ if configfs is available.
|
||||||
|
--- a/drivers/mmc/host/Makefile
|
||||||
|
+++ b/drivers/mmc/host/Makefile
|
||||||
|
@@ -29,4 +29,5 @@ endif
|
||||||
|
obj-$(CONFIG_MMC_S3C) += s3cmci.o
|
||||||
|
obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
|
||||||
|
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
|
||||||
|
+obj-$(CONFIG_GPIOMMC) += gpiommc.o
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/linux/mmc/gpiommc.h
|
||||||
|
@@ -0,0 +1,71 @@
|
||||||
|
+/*
|
||||||
|
+ * Device driver for MMC/SD cards driven over a GPIO bus.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2008 Michael Buesch
|
||||||
|
+ *
|
||||||
|
+ * Licensed under the GNU/GPL version 2.
|
||||||
|
+ */
|
||||||
|
+#ifndef LINUX_GPIOMMC_H_
|
||||||
|
+#define LINUX_GPIOMMC_H_
|
||||||
|
+
|
||||||
|
+#include <linux/types.h>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#define GPIOMMC_MAX_NAMELEN 15
|
||||||
|
+#define GPIOMMC_MAX_NAMELEN_STR __stringify(GPIOMMC_MAX_NAMELEN)
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * struct gpiommc_pins - Hardware pin assignments
|
||||||
|
+ *
|
||||||
|
+ * @gpio_di: The GPIO number of the DATA IN pin
|
||||||
|
+ * @gpio_do: The GPIO number of the DATA OUT pin
|
||||||
|
+ * @gpio_clk: The GPIO number of the CLOCK pin
|
||||||
|
+ * @gpio_cs: The GPIO number of the CHIPSELECT pin
|
||||||
|
+ * @cs_activelow: If true, the chip is considered selected if @gpio_cs is low.
|
||||||
|
+ */
|
||||||
|
+struct gpiommc_pins {
|
||||||
|
+ unsigned int gpio_di;
|
||||||
|
+ unsigned int gpio_do;
|
||||||
|
+ unsigned int gpio_clk;
|
||||||
|
+ unsigned int gpio_cs;
|
||||||
|
+ bool cs_activelow;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * struct gpiommc_platform_data - Platform data for a MMC-over-SPI-GPIO device.
|
||||||
|
+ *
|
||||||
|
+ * @name: The unique name string of the device.
|
||||||
|
+ * @pins: The hardware pin assignments.
|
||||||
|
+ * @mode: The hardware mode. This is either SPI_MODE_0,
|
||||||
|
+ * SPI_MODE_1, SPI_MODE_2 or SPI_MODE_3. See the SPI documentation.
|
||||||
|
+ * @no_spi_delay: Do not use delays in the lowlevel SPI bitbanging code.
|
||||||
|
+ * This is not standards compliant, but may be required for some
|
||||||
|
+ * embedded machines to gain reasonable speed.
|
||||||
|
+ * @max_bus_speed: The maximum speed of the SPI bus, in Hertz.
|
||||||
|
+ */
|
||||||
|
+struct gpiommc_platform_data {
|
||||||
|
+ char name[GPIOMMC_MAX_NAMELEN + 1];
|
||||||
|
+ struct gpiommc_pins pins;
|
||||||
|
+ u8 mode;
|
||||||
|
+ bool no_spi_delay;
|
||||||
|
+ unsigned int max_bus_speed;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * GPIOMMC_PLATDEV_NAME - The platform device name string.
|
||||||
|
+ *
|
||||||
|
+ * The name string that has to be used for platform_device_alloc
|
||||||
|
+ * when allocating a gpiommc device.
|
||||||
|
+ */
|
||||||
|
+#define GPIOMMC_PLATDEV_NAME "gpiommc"
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * gpiommc_next_id - Get another platform device ID number.
|
||||||
|
+ *
|
||||||
|
+ * This returns the next platform device ID number that has to be used
|
||||||
|
+ * for platform_device_alloc. The ID is opaque and should not be used for
|
||||||
|
+ * anything else.
|
||||||
|
+ */
|
||||||
|
+int gpiommc_next_id(void);
|
||||||
|
+
|
||||||
|
+#endif /* LINUX_GPIOMMC_H_ */
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/gpiommc.txt
|
||||||
|
@@ -0,0 +1,97 @@
|
||||||
|
+GPIOMMC - Driver for an MMC/SD card on a bitbanging GPIO SPI bus
|
||||||
|
+================================================================
|
||||||
|
+
|
||||||
|
+The gpiommc module hooks up the mmc_spi and spi_gpio modules for running an
|
||||||
|
+MMC or SD card on GPIO pins.
|
||||||
|
+
|
||||||
|
+Two interfaces for registering a new MMC/SD card device are provided:
|
||||||
|
+A static platform-device based mechanism and a dynamic configfs based interface.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+Registering devices via platform-device
|
||||||
|
+=======================================
|
||||||
|
+
|
||||||
|
+The platform-device interface is used for registering MMC/SD devices that are
|
||||||
|
+part of the hardware platform. This is most useful only for embedded machines
|
||||||
|
+with MMC/SD devices statically connected to the platform GPIO bus.
|
||||||
|
+
|
||||||
|
+The data structures are declared in <linux/mmc/gpiommc.h>.
|
||||||
|
+
|
||||||
|
+To register a new device, define an instance of struct gpiommc_platform_data.
|
||||||
|
+This structure holds any information about how the device is hooked up to the
|
||||||
|
+GPIO pins and what hardware modes the device supports. See the docbook-style
|
||||||
|
+documentation in the header file for more information on the struct fields.
|
||||||
|
+
|
||||||
|
+Then allocate a new instance of a platform device by doing:
|
||||||
|
+
|
||||||
|
+ pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME, gpiommc_next_id());
|
||||||
|
+
|
||||||
|
+This will allocate the platform device data structures and hook it up to the
|
||||||
|
+gpiommc driver.
|
||||||
|
+Then add the gpiommc_platform_data to the platform device.
|
||||||
|
+
|
||||||
|
+ err = platform_device_add_data(pdev, pdata, sizeof(struct gpiommc_platform_data));
|
||||||
|
+
|
||||||
|
+You may free the local instance of struct gpiommc_platform_data now. (So the
|
||||||
|
+struct may be allocated on the stack, too).
|
||||||
|
+Now simply register the platform device.
|
||||||
|
+
|
||||||
|
+ err = platform_device_add(pdev);
|
||||||
|
+
|
||||||
|
+Done. The gpiommc probe routine will be invoked now and you should see a kernel
|
||||||
|
+log message for the added device.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+Registering devices via configfs
|
||||||
|
+================================
|
||||||
|
+
|
||||||
|
+MMC/SD cards connected via GPIO often are a pretty dynamic thing, as for example
|
||||||
|
+selfmade hacks for soldering an MMC/SD card to standard GPIO pins on embedded
|
||||||
|
+hardware are a common situation.
|
||||||
|
+So we provide a dynamic interface to conveniently handle adding and removing
|
||||||
|
+devices from userspace, without the need to recompile the kernel.
|
||||||
|
+
|
||||||
|
+The "gpiommc" subdirectory at the configfs mountpoint is used for handling
|
||||||
|
+the dynamic configuration.
|
||||||
|
+
|
||||||
|
+To create a new device, it must first be allocated with mkdir.
|
||||||
|
+The following command will allocate a device named "my_mmc":
|
||||||
|
+ mkdir /config/gpiommc/my_mmc
|
||||||
|
+
|
||||||
|
+There are several configuration files available in the new
|
||||||
|
+/config/gpiommc/my_mmc/ directory:
|
||||||
|
+
|
||||||
|
+gpio_data_in = The SPI data-IN GPIO pin number.
|
||||||
|
+gpio_data_out = The SPI data-OUT GPIO pin number.
|
||||||
|
+gpio_clock = The SPI Clock GPIO pin number.
|
||||||
|
+gpio_chipselect = The SPI Chipselect GPIO pin number.
|
||||||
|
+gpio_chipselect_activelow = Boolean. If 0, Chipselect is active-HIGH.
|
||||||
|
+ If 1, Chipselect is active-LOW.
|
||||||
|
+spi_mode = The SPI data mode. Can be 0-3.
|
||||||
|
+spi_delay = Enable all delays in the lowlevel bitbanging.
|
||||||
|
+max_bus_speed = The maximum SPI bus speed. In Hertz.
|
||||||
|
+
|
||||||
|
+register = Not a configuration parameter.
|
||||||
|
+ Used to register the configured card
|
||||||
|
+ with the kernel.
|
||||||
|
+
|
||||||
|
+The device must first get configured and then registered by writing "1" to
|
||||||
|
+the "register" file.
|
||||||
|
+The configuration parameters "gpio_data_in", "gpio_data_out", "gpio_clock"
|
||||||
|
+and "gpio_chipselect" are essential and _must_ be configured before writing
|
||||||
|
+"1" to the "register" file. The registration will fail, otherwise.
|
||||||
|
+
|
||||||
|
+The default values for the other parameters are:
|
||||||
|
+gpio_chipselect_activelow = 1 (CS active-LOW)
|
||||||
|
+spi_mode = 0 (SPI_MODE_0)
|
||||||
|
+spi_delay = 1 (enabled)
|
||||||
|
+max_bus_speed = 5000000 (5 Mhz)
|
||||||
|
+
|
||||||
|
+Configuration values can not be changed after registration. To unregister
|
||||||
|
+the device, write a "0" to the "register" file. The configuration can be
|
||||||
|
+changed again after unregistering.
|
||||||
|
+
|
||||||
|
+To completely remove the device, simply rmdir the directory
|
||||||
|
+(/config/gpiommc/my_mmc in this example).
|
||||||
|
+There's no need to first unregister the device before removing it. That will
|
||||||
|
+be done automatically.
|
||||||
|
--- a/MAINTAINERS
|
||||||
|
+++ b/MAINTAINERS
|
||||||
|
@@ -1997,6 +1997,11 @@ L: linux-media@vger.kernel.org
|
||||||
|
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
|
+GPIOMMC DRIVER
|
||||||
|
+P: Michael Buesch
|
||||||
|
+M: mb@bu3sch.de
|
||||||
|
+S: Maintained
|
||||||
|
+
|
||||||
|
HARDWARE MONITORING
|
||||||
|
L: lm-sensors@lm-sensors.org
|
||||||
|
W: http://www.lm-sensors.org/
|
@ -0,0 +1,58 @@
|
|||||||
|
The gpiommc configfs context structure needs locking, as configfs
|
||||||
|
does not lock access between files.
|
||||||
|
|
||||||
|
--- a/drivers/mmc/host/gpiommc.c
|
||||||
|
+++ b/drivers/mmc/host/gpiommc.c
|
||||||
|
@@ -143,6 +143,8 @@ struct gpiommc_configfs_device {
|
||||||
|
struct platform_device *pdev;
|
||||||
|
/* The configuration */
|
||||||
|
struct gpiommc_platform_data pdata;
|
||||||
|
+ /* Mutex to protect this structure */
|
||||||
|
+ struct mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GPIO_INVALID -1
|
||||||
|
@@ -233,6 +235,8 @@ static ssize_t gpiommc_config_attr_show(
|
||||||
|
unsigned int gpio;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
+ mutex_lock(&dev->mutex);
|
||||||
|
+
|
||||||
|
if (attr == &gpiommc_attr_DI) {
|
||||||
|
gpio = dev->pdata.pins.gpio_di;
|
||||||
|
if (gpio == GPIO_INVALID)
|
||||||
|
@@ -293,6 +297,8 @@ static ssize_t gpiommc_config_attr_show(
|
||||||
|
WARN_ON(1);
|
||||||
|
err = -ENOSYS;
|
||||||
|
out:
|
||||||
|
+ mutex_unlock(&dev->mutex);
|
||||||
|
+
|
||||||
|
return err ? err : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -352,6 +358,8 @@ static ssize_t gpiommc_config_attr_store
|
||||||
|
int err = -EINVAL;
|
||||||
|
unsigned long data;
|
||||||
|
|
||||||
|
+ mutex_lock(&dev->mutex);
|
||||||
|
+
|
||||||
|
if (attr == &gpiommc_attr_register) {
|
||||||
|
err = strict_strtoul(page, 10, &data);
|
||||||
|
if (err)
|
||||||
|
@@ -477,6 +485,8 @@ static ssize_t gpiommc_config_attr_store
|
||||||
|
WARN_ON(1);
|
||||||
|
err = -ENOSYS;
|
||||||
|
out:
|
||||||
|
+ mutex_unlock(&dev->mutex);
|
||||||
|
+
|
||||||
|
return err ? err : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -513,6 +523,7 @@ static struct config_item *gpiommc_make_
|
||||||
|
if (!dev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
+ mutex_init(&dev->mutex);
|
||||||
|
config_item_init_type_name(&dev->item, name,
|
||||||
|
&gpiommc_dev_ci_type);
|
||||||
|
|
102
target/linux/generic-2.6/patches-2.6.30/924-cs5535_gpio.patch
Normal file
102
target/linux/generic-2.6/patches-2.6.30/924-cs5535_gpio.patch
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
--- a/drivers/char/cs5535_gpio.c
|
||||||
|
+++ b/drivers/char/cs5535_gpio.c
|
||||||
|
@@ -15,6 +15,7 @@
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/cdev.h>
|
||||||
|
+#include <linux/device.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/smp_lock.h>
|
||||||
|
@@ -48,6 +49,7 @@ static struct pci_device_id divil_pci[]
|
||||||
|
MODULE_DEVICE_TABLE(pci, divil_pci);
|
||||||
|
|
||||||
|
static struct cdev cs5535_gpio_cdev;
|
||||||
|
+static struct class *cs5535_gpio_class;
|
||||||
|
|
||||||
|
/* reserve 32 entries even though some aren't usable */
|
||||||
|
#define CS5535_GPIO_COUNT 32
|
||||||
|
@@ -66,9 +68,14 @@ static struct gpio_regmap rm[] =
|
||||||
|
{ 0x30, 0x00, '1', '0' }, /* GPIOx_READ_BACK / GPIOx_OUT_VAL */
|
||||||
|
{ 0x20, 0x20, 'I', 'i' }, /* GPIOx_IN_EN */
|
||||||
|
{ 0x04, 0x04, 'O', 'o' }, /* GPIOx_OUT_EN */
|
||||||
|
+ { 0x10, 0x10, 'A', 'a' }, /* GPIOx_OUT_AUX1_SEL */
|
||||||
|
+ { 0x14, 0x14, 'B', 'b' }, /* GPIOx_OUT_AUX2_SEL */
|
||||||
|
{ 0x08, 0x08, 't', 'T' }, /* GPIOx_OUT_OD_EN */
|
||||||
|
{ 0x18, 0x18, 'P', 'p' }, /* GPIOx_OUT_PU_EN */
|
||||||
|
{ 0x1c, 0x1c, 'D', 'd' }, /* GPIOx_OUT_PD_EN */
|
||||||
|
+ { 0x24, 0x24, 'N', 'n' }, /* GPIOx_IN_INV_EN */
|
||||||
|
+ { 0x0c, 0x0c, 'X', 'x' }, /* GPIOx_OUT_INV_EN */
|
||||||
|
+ { 0x00, 0x00, 'H', 'L' }, /* GPIOx_OUT_VAL */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -177,7 +184,7 @@ static int __init cs5535_gpio_init(void)
|
||||||
|
{
|
||||||
|
dev_t dev_id;
|
||||||
|
u32 low, hi;
|
||||||
|
- int retval;
|
||||||
|
+ int retval, i;
|
||||||
|
|
||||||
|
if (pci_dev_present(divil_pci) == 0) {
|
||||||
|
printk(KERN_WARNING NAME ": DIVIL not found\n");
|
||||||
|
@@ -232,23 +239,54 @@ static int __init cs5535_gpio_init(void)
|
||||||
|
major = MAJOR(dev_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (retval) {
|
||||||
|
- release_region(gpio_base, CS5535_GPIO_SIZE);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
+ if (retval)
|
||||||
|
+ goto error;
|
||||||
|
|
||||||
|
printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
|
||||||
|
gpio_base, mask, major);
|
||||||
|
|
||||||
|
cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
|
||||||
|
- cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
|
||||||
|
+ retval = cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
|
||||||
|
+ if (retval) {
|
||||||
|
+ kobject_put(&cs5535_gpio_cdev.kobj);
|
||||||
|
+ goto error_region;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cs5535_gpio_class = class_create(THIS_MODULE, "cs5535_gpio");
|
||||||
|
+ if (IS_ERR(cs5535_gpio_class)) {
|
||||||
|
+ printk(KERN_ERR "Error creating cs5535_gpio class\n");
|
||||||
|
+ cdev_del(&cs5535_gpio_cdev);
|
||||||
|
+ retval = PTR_ERR(cs5535_gpio_class);
|
||||||
|
+ goto error_region;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < CS5535_GPIO_COUNT; i++) {
|
||||||
|
+ if (mask & (1<<i)) {
|
||||||
|
+ device_create(cs5535_gpio_class, NULL, MKDEV(major, i), NULL, "cs5535_gpio%d", i);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+error_region:
|
||||||
|
+ unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
|
||||||
|
+error:
|
||||||
|
+ release_region(gpio_base, CS5535_GPIO_SIZE);
|
||||||
|
+ return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit cs5535_gpio_cleanup(void)
|
||||||
|
{
|
||||||
|
dev_t dev_id = MKDEV(major, 0);
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < CS5535_GPIO_COUNT; i++) {
|
||||||
|
+ if (mask & (1<<i)) {
|
||||||
|
+ device_destroy(cs5535_gpio_class, MKDEV(major, i));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ class_destroy(cs5535_gpio_class);
|
||||||
|
|
||||||
|
cdev_del(&cs5535_gpio_cdev);
|
||||||
|
unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
|
@ -0,0 +1,524 @@
|
|||||||
|
--- a/arch/powerpc/boot/crtsavres.S
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,233 +0,0 @@
|
||||||
|
-/*
|
||||||
|
- * Special support for eabi and SVR4
|
||||||
|
- *
|
||||||
|
- * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
- * Copyright 2008 Freescale Semiconductor, Inc.
|
||||||
|
- * Written By Michael Meissner
|
||||||
|
- *
|
||||||
|
- * Based on gcc/config/rs6000/crtsavres.asm from gcc
|
||||||
|
- *
|
||||||
|
- * This file 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, or (at your option) any
|
||||||
|
- * later version.
|
||||||
|
- *
|
||||||
|
- * In addition to the permissions in the GNU General Public License, the
|
||||||
|
- * Free Software Foundation gives you unlimited permission to link the
|
||||||
|
- * compiled version of this file with other programs, and to distribute
|
||||||
|
- * those programs without any restriction coming from the use of this
|
||||||
|
- * file. (The General Public License restrictions do apply in other
|
||||||
|
- * respects; for example, they cover modification of the file, and
|
||||||
|
- * distribution when not linked into another program.)
|
||||||
|
- *
|
||||||
|
- * This file 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; see the file COPYING. If not, write to
|
||||||
|
- * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
- * Boston, MA 02110-1301, USA.
|
||||||
|
- *
|
||||||
|
- * As a special exception, if you link this library with files
|
||||||
|
- * compiled with GCC to produce an executable, this does not cause
|
||||||
|
- * the resulting executable to be covered by the GNU General Public License.
|
||||||
|
- * This exception does not however invalidate any other reasons why
|
||||||
|
- * the executable file might be covered by the GNU General Public License.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- .file "crtsavres.S"
|
||||||
|
- .section ".text"
|
||||||
|
-
|
||||||
|
-/* On PowerPC64 Linux, these functions are provided by the linker. */
|
||||||
|
-#ifndef __powerpc64__
|
||||||
|
-
|
||||||
|
-#define _GLOBAL(name) \
|
||||||
|
- .type name,@function; \
|
||||||
|
- .globl name; \
|
||||||
|
-name:
|
||||||
|
-
|
||||||
|
-/* Routines for saving integer registers, called by the compiler. */
|
||||||
|
-/* Called with r11 pointing to the stack header word of the caller of the */
|
||||||
|
-/* function, just beyond the end of the integer save area. */
|
||||||
|
-
|
||||||
|
-_GLOBAL(_savegpr_14)
|
||||||
|
-_GLOBAL(_save32gpr_14)
|
||||||
|
- stw 14,-72(11) /* save gp registers */
|
||||||
|
-_GLOBAL(_savegpr_15)
|
||||||
|
-_GLOBAL(_save32gpr_15)
|
||||||
|
- stw 15,-68(11)
|
||||||
|
-_GLOBAL(_savegpr_16)
|
||||||
|
-_GLOBAL(_save32gpr_16)
|
||||||
|
- stw 16,-64(11)
|
||||||
|
-_GLOBAL(_savegpr_17)
|
||||||
|
-_GLOBAL(_save32gpr_17)
|
||||||
|
- stw 17,-60(11)
|
||||||
|
-_GLOBAL(_savegpr_18)
|
||||||
|
-_GLOBAL(_save32gpr_18)
|
||||||
|
- stw 18,-56(11)
|
||||||
|
-_GLOBAL(_savegpr_19)
|
||||||
|
-_GLOBAL(_save32gpr_19)
|
||||||
|
- stw 19,-52(11)
|
||||||
|
-_GLOBAL(_savegpr_20)
|
||||||
|
-_GLOBAL(_save32gpr_20)
|
||||||
|
- stw 20,-48(11)
|
||||||
|
-_GLOBAL(_savegpr_21)
|
||||||
|
-_GLOBAL(_save32gpr_21)
|
||||||
|
- stw 21,-44(11)
|
||||||
|
-_GLOBAL(_savegpr_22)
|
||||||
|
-_GLOBAL(_save32gpr_22)
|
||||||
|
- stw 22,-40(11)
|
||||||
|
-_GLOBAL(_savegpr_23)
|
||||||
|
-_GLOBAL(_save32gpr_23)
|
||||||
|
- stw 23,-36(11)
|
||||||
|
-_GLOBAL(_savegpr_24)
|
||||||
|
-_GLOBAL(_save32gpr_24)
|
||||||
|
- stw 24,-32(11)
|
||||||
|
-_GLOBAL(_savegpr_25)
|
||||||
|
-_GLOBAL(_save32gpr_25)
|
||||||
|
- stw 25,-28(11)
|
||||||
|
-_GLOBAL(_savegpr_26)
|
||||||
|
-_GLOBAL(_save32gpr_26)
|
||||||
|
- stw 26,-24(11)
|
||||||
|
-_GLOBAL(_savegpr_27)
|
||||||
|
-_GLOBAL(_save32gpr_27)
|
||||||
|
- stw 27,-20(11)
|
||||||
|
-_GLOBAL(_savegpr_28)
|
||||||
|
-_GLOBAL(_save32gpr_28)
|
||||||
|
- stw 28,-16(11)
|
||||||
|
-_GLOBAL(_savegpr_29)
|
||||||
|
-_GLOBAL(_save32gpr_29)
|
||||||
|
- stw 29,-12(11)
|
||||||
|
-_GLOBAL(_savegpr_30)
|
||||||
|
-_GLOBAL(_save32gpr_30)
|
||||||
|
- stw 30,-8(11)
|
||||||
|
-_GLOBAL(_savegpr_31)
|
||||||
|
-_GLOBAL(_save32gpr_31)
|
||||||
|
- stw 31,-4(11)
|
||||||
|
- blr
|
||||||
|
-
|
||||||
|
-/* Routines for restoring integer registers, called by the compiler. */
|
||||||
|
-/* Called with r11 pointing to the stack header word of the caller of the */
|
||||||
|
-/* function, just beyond the end of the integer restore area. */
|
||||||
|
-
|
||||||
|
-_GLOBAL(_restgpr_14)
|
||||||
|
-_GLOBAL(_rest32gpr_14)
|
||||||
|
- lwz 14,-72(11) /* restore gp registers */
|
||||||
|
-_GLOBAL(_restgpr_15)
|
||||||
|
-_GLOBAL(_rest32gpr_15)
|
||||||
|
- lwz 15,-68(11)
|
||||||
|
-_GLOBAL(_restgpr_16)
|
||||||
|
-_GLOBAL(_rest32gpr_16)
|
||||||
|
- lwz 16,-64(11)
|
||||||
|
-_GLOBAL(_restgpr_17)
|
||||||
|
-_GLOBAL(_rest32gpr_17)
|
||||||
|
- lwz 17,-60(11)
|
||||||
|
-_GLOBAL(_restgpr_18)
|
||||||
|
-_GLOBAL(_rest32gpr_18)
|
||||||
|
- lwz 18,-56(11)
|
||||||
|
-_GLOBAL(_restgpr_19)
|
||||||
|
-_GLOBAL(_rest32gpr_19)
|
||||||
|
- lwz 19,-52(11)
|
||||||
|
-_GLOBAL(_restgpr_20)
|
||||||
|
-_GLOBAL(_rest32gpr_20)
|
||||||
|
- lwz 20,-48(11)
|
||||||
|
-_GLOBAL(_restgpr_21)
|
||||||
|
-_GLOBAL(_rest32gpr_21)
|
||||||
|
- lwz 21,-44(11)
|
||||||
|
-_GLOBAL(_restgpr_22)
|
||||||
|
-_GLOBAL(_rest32gpr_22)
|
||||||
|
- lwz 22,-40(11)
|
||||||
|
-_GLOBAL(_restgpr_23)
|
||||||
|
-_GLOBAL(_rest32gpr_23)
|
||||||
|
- lwz 23,-36(11)
|
||||||
|
-_GLOBAL(_restgpr_24)
|
||||||
|
-_GLOBAL(_rest32gpr_24)
|
||||||
|
- lwz 24,-32(11)
|
||||||
|
-_GLOBAL(_restgpr_25)
|
||||||
|
-_GLOBAL(_rest32gpr_25)
|
||||||
|
- lwz 25,-28(11)
|
||||||
|
-_GLOBAL(_restgpr_26)
|
||||||
|
-_GLOBAL(_rest32gpr_26)
|
||||||
|
- lwz 26,-24(11)
|
||||||
|
-_GLOBAL(_restgpr_27)
|
||||||
|
-_GLOBAL(_rest32gpr_27)
|
||||||
|
- lwz 27,-20(11)
|
||||||
|
-_GLOBAL(_restgpr_28)
|
||||||
|
-_GLOBAL(_rest32gpr_28)
|
||||||
|
- lwz 28,-16(11)
|
||||||
|
-_GLOBAL(_restgpr_29)
|
||||||
|
-_GLOBAL(_rest32gpr_29)
|
||||||
|
- lwz 29,-12(11)
|
||||||
|
-_GLOBAL(_restgpr_30)
|
||||||
|
-_GLOBAL(_rest32gpr_30)
|
||||||
|
- lwz 30,-8(11)
|
||||||
|
-_GLOBAL(_restgpr_31)
|
||||||
|
-_GLOBAL(_rest32gpr_31)
|
||||||
|
- lwz 31,-4(11)
|
||||||
|
- blr
|
||||||
|
-
|
||||||
|
-/* Routines for restoring integer registers, called by the compiler. */
|
||||||
|
-/* Called with r11 pointing to the stack header word of the caller of the */
|
||||||
|
-/* function, just beyond the end of the integer restore area. */
|
||||||
|
-
|
||||||
|
-_GLOBAL(_restgpr_14_x)
|
||||||
|
-_GLOBAL(_rest32gpr_14_x)
|
||||||
|
- lwz 14,-72(11) /* restore gp registers */
|
||||||
|
-_GLOBAL(_restgpr_15_x)
|
||||||
|
-_GLOBAL(_rest32gpr_15_x)
|
||||||
|
- lwz 15,-68(11)
|
||||||
|
-_GLOBAL(_restgpr_16_x)
|
||||||
|
-_GLOBAL(_rest32gpr_16_x)
|
||||||
|
- lwz 16,-64(11)
|
||||||
|
-_GLOBAL(_restgpr_17_x)
|
||||||
|
-_GLOBAL(_rest32gpr_17_x)
|
||||||
|
- lwz 17,-60(11)
|
||||||
|
-_GLOBAL(_restgpr_18_x)
|
||||||
|
-_GLOBAL(_rest32gpr_18_x)
|
||||||
|
- lwz 18,-56(11)
|
||||||
|
-_GLOBAL(_restgpr_19_x)
|
||||||
|
-_GLOBAL(_rest32gpr_19_x)
|
||||||
|
- lwz 19,-52(11)
|
||||||
|
-_GLOBAL(_restgpr_20_x)
|
||||||
|
-_GLOBAL(_rest32gpr_20_x)
|
||||||
|
- lwz 20,-48(11)
|
||||||
|
-_GLOBAL(_restgpr_21_x)
|
||||||
|
-_GLOBAL(_rest32gpr_21_x)
|
||||||
|
- lwz 21,-44(11)
|
||||||
|
-_GLOBAL(_restgpr_22_x)
|
||||||
|
-_GLOBAL(_rest32gpr_22_x)
|
||||||
|
- lwz 22,-40(11)
|
||||||
|
-_GLOBAL(_restgpr_23_x)
|
||||||
|
-_GLOBAL(_rest32gpr_23_x)
|
||||||
|
- lwz 23,-36(11)
|
||||||
|
-_GLOBAL(_restgpr_24_x)
|
||||||
|
-_GLOBAL(_rest32gpr_24_x)
|
||||||
|
- lwz 24,-32(11)
|
||||||
|
-_GLOBAL(_restgpr_25_x)
|
||||||
|
-_GLOBAL(_rest32gpr_25_x)
|
||||||
|
- lwz 25,-28(11)
|
||||||
|
-_GLOBAL(_restgpr_26_x)
|
||||||
|
-_GLOBAL(_rest32gpr_26_x)
|
||||||
|
- lwz 26,-24(11)
|
||||||
|
-_GLOBAL(_restgpr_27_x)
|
||||||
|
-_GLOBAL(_rest32gpr_27_x)
|
||||||
|
- lwz 27,-20(11)
|
||||||
|
-_GLOBAL(_restgpr_28_x)
|
||||||
|
-_GLOBAL(_rest32gpr_28_x)
|
||||||
|
- lwz 28,-16(11)
|
||||||
|
-_GLOBAL(_restgpr_29_x)
|
||||||
|
-_GLOBAL(_rest32gpr_29_x)
|
||||||
|
- lwz 29,-12(11)
|
||||||
|
-_GLOBAL(_restgpr_30_x)
|
||||||
|
-_GLOBAL(_rest32gpr_30_x)
|
||||||
|
- lwz 30,-8(11)
|
||||||
|
-_GLOBAL(_restgpr_31_x)
|
||||||
|
-_GLOBAL(_rest32gpr_31_x)
|
||||||
|
- lwz 0,4(11)
|
||||||
|
- lwz 31,-4(11)
|
||||||
|
- mtlr 0
|
||||||
|
- mr 1,11
|
||||||
|
- blr
|
||||||
|
-#endif
|
||||||
|
--- a/arch/powerpc/boot/Makefile
|
||||||
|
+++ b/arch/powerpc/boot/Makefile
|
||||||
|
@@ -54,7 +54,7 @@ $(addprefix $(obj)/,$(zlib) cuboot-c2k.o
|
||||||
|
$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
|
||||||
|
|
||||||
|
src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
|
||||||
|
-src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
|
||||||
|
+src-wlib := string.S crt0.S stdio.c main.c \
|
||||||
|
$(addprefix libfdt/,$(src-libfdt)) libfdt-wrapper.c \
|
||||||
|
ns16550.c serial.c simple_alloc.c div64.S util.S \
|
||||||
|
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
|
||||||
|
--- a/arch/powerpc/kernel/prom_init_check.sh
|
||||||
|
+++ b/arch/powerpc/kernel/prom_init_check.sh
|
||||||
|
@@ -48,20 +48,6 @@ do
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- # ignore register save/restore funcitons
|
||||||
|
- if [ "${UNDEF:0:9}" = "_restgpr_" ]; then
|
||||||
|
- OK=1
|
||||||
|
- fi
|
||||||
|
- if [ "${UNDEF:0:11}" = "_rest32gpr_" ]; then
|
||||||
|
- OK=1
|
||||||
|
- fi
|
||||||
|
- if [ "${UNDEF:0:9}" = "_savegpr_" ]; then
|
||||||
|
- OK=1
|
||||||
|
- fi
|
||||||
|
- if [ "${UNDEF:0:11}" = "_save32gpr_" ]; then
|
||||||
|
- OK=1
|
||||||
|
- fi
|
||||||
|
-
|
||||||
|
if [ $OK -eq 0 ]; then
|
||||||
|
ERROR=1
|
||||||
|
echo "Error: External symbol '$UNDEF' referenced" \
|
||||||
|
--- a/arch/powerpc/lib/crtsavres.S
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,229 +0,0 @@
|
||||||
|
-/*
|
||||||
|
- * Special support for eabi and SVR4
|
||||||
|
- *
|
||||||
|
- * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
- * Copyright 2008 Freescale Semiconductor, Inc.
|
||||||
|
- * Written By Michael Meissner
|
||||||
|
- *
|
||||||
|
- * Based on gcc/config/rs6000/crtsavres.asm from gcc
|
||||||
|
- *
|
||||||
|
- * This file 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, or (at your option) any
|
||||||
|
- * later version.
|
||||||
|
- *
|
||||||
|
- * In addition to the permissions in the GNU General Public License, the
|
||||||
|
- * Free Software Foundation gives you unlimited permission to link the
|
||||||
|
- * compiled version of this file with other programs, and to distribute
|
||||||
|
- * those programs without any restriction coming from the use of this
|
||||||
|
- * file. (The General Public License restrictions do apply in other
|
||||||
|
- * respects; for example, they cover modification of the file, and
|
||||||
|
- * distribution when not linked into another program.)
|
||||||
|
- *
|
||||||
|
- * This file 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; see the file COPYING. If not, write to
|
||||||
|
- * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
- * Boston, MA 02110-1301, USA.
|
||||||
|
- *
|
||||||
|
- * As a special exception, if you link this library with files
|
||||||
|
- * compiled with GCC to produce an executable, this does not cause
|
||||||
|
- * the resulting executable to be covered by the GNU General Public License.
|
||||||
|
- * This exception does not however invalidate any other reasons why
|
||||||
|
- * the executable file might be covered by the GNU General Public License.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
-#include <asm/ppc_asm.h>
|
||||||
|
-
|
||||||
|
- .file "crtsavres.S"
|
||||||
|
- .section ".text"
|
||||||
|
-
|
||||||
|
-#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||||
|
-
|
||||||
|
-/* Routines for saving integer registers, called by the compiler. */
|
||||||
|
-/* Called with r11 pointing to the stack header word of the caller of the */
|
||||||
|
-/* function, just beyond the end of the integer save area. */
|
||||||
|
-
|
||||||
|
-_GLOBAL(_savegpr_14)
|
||||||
|
-_GLOBAL(_save32gpr_14)
|
||||||
|
- stw 14,-72(11) /* save gp registers */
|
||||||
|
-_GLOBAL(_savegpr_15)
|
||||||
|
-_GLOBAL(_save32gpr_15)
|
||||||
|
- stw 15,-68(11)
|
||||||
|
-_GLOBAL(_savegpr_16)
|
||||||
|
-_GLOBAL(_save32gpr_16)
|
||||||
|
- stw 16,-64(11)
|
||||||
|
-_GLOBAL(_savegpr_17)
|
||||||
|
-_GLOBAL(_save32gpr_17)
|
||||||
|
- stw 17,-60(11)
|
||||||
|
-_GLOBAL(_savegpr_18)
|
||||||
|
-_GLOBAL(_save32gpr_18)
|
||||||
|
- stw 18,-56(11)
|
||||||
|
-_GLOBAL(_savegpr_19)
|
||||||
|
-_GLOBAL(_save32gpr_19)
|
||||||
|
- stw 19,-52(11)
|
||||||
|
-_GLOBAL(_savegpr_20)
|
||||||
|
-_GLOBAL(_save32gpr_20)
|
||||||
|
- stw 20,-48(11)
|
||||||
|
-_GLOBAL(_savegpr_21)
|
||||||
|
-_GLOBAL(_save32gpr_21)
|
||||||
|
- stw 21,-44(11)
|
||||||
|
-_GLOBAL(_savegpr_22)
|
||||||
|
-_GLOBAL(_save32gpr_22)
|
||||||
|
- stw 22,-40(11)
|
||||||
|
-_GLOBAL(_savegpr_23)
|
||||||
|
-_GLOBAL(_save32gpr_23)
|
||||||
|
- stw 23,-36(11)
|
||||||
|
-_GLOBAL(_savegpr_24)
|
||||||
|
-_GLOBAL(_save32gpr_24)
|
||||||
|
- stw 24,-32(11)
|
||||||
|
-_GLOBAL(_savegpr_25)
|
||||||
|
-_GLOBAL(_save32gpr_25)
|
||||||
|
- stw 25,-28(11)
|
||||||
|
-_GLOBAL(_savegpr_26)
|
||||||
|
-_GLOBAL(_save32gpr_26)
|
||||||
|
- stw 26,-24(11)
|
||||||
|
-_GLOBAL(_savegpr_27)
|
||||||
|
-_GLOBAL(_save32gpr_27)
|
||||||
|
- stw 27,-20(11)
|
||||||
|
-_GLOBAL(_savegpr_28)
|
||||||
|
-_GLOBAL(_save32gpr_28)
|
||||||
|
- stw 28,-16(11)
|
||||||
|
-_GLOBAL(_savegpr_29)
|
||||||
|
-_GLOBAL(_save32gpr_29)
|
||||||
|
- stw 29,-12(11)
|
||||||
|
-_GLOBAL(_savegpr_30)
|
||||||
|
-_GLOBAL(_save32gpr_30)
|
||||||
|
- stw 30,-8(11)
|
||||||
|
-_GLOBAL(_savegpr_31)
|
||||||
|
-_GLOBAL(_save32gpr_31)
|
||||||
|
- stw 31,-4(11)
|
||||||
|
- blr
|
||||||
|
-
|
||||||
|
-/* Routines for restoring integer registers, called by the compiler. */
|
||||||
|
-/* Called with r11 pointing to the stack header word of the caller of the */
|
||||||
|
-/* function, just beyond the end of the integer restore area. */
|
||||||
|
-
|
||||||
|
-_GLOBAL(_restgpr_14)
|
||||||
|
-_GLOBAL(_rest32gpr_14)
|
||||||
|
- lwz 14,-72(11) /* restore gp registers */
|
||||||
|
-_GLOBAL(_restgpr_15)
|
||||||
|
-_GLOBAL(_rest32gpr_15)
|
||||||
|
- lwz 15,-68(11)
|
||||||
|
-_GLOBAL(_restgpr_16)
|
||||||
|
-_GLOBAL(_rest32gpr_16)
|
||||||
|
- lwz 16,-64(11)
|
||||||
|
-_GLOBAL(_restgpr_17)
|
||||||
|
-_GLOBAL(_rest32gpr_17)
|
||||||
|
- lwz 17,-60(11)
|
||||||
|
-_GLOBAL(_restgpr_18)
|
||||||
|
-_GLOBAL(_rest32gpr_18)
|
||||||
|
- lwz 18,-56(11)
|
||||||
|
-_GLOBAL(_restgpr_19)
|
||||||
|
-_GLOBAL(_rest32gpr_19)
|
||||||
|
- lwz 19,-52(11)
|
||||||
|
-_GLOBAL(_restgpr_20)
|
||||||
|
-_GLOBAL(_rest32gpr_20)
|
||||||
|
- lwz 20,-48(11)
|
||||||
|
-_GLOBAL(_restgpr_21)
|
||||||
|
-_GLOBAL(_rest32gpr_21)
|
||||||
|
- lwz 21,-44(11)
|
||||||
|
-_GLOBAL(_restgpr_22)
|
||||||
|
-_GLOBAL(_rest32gpr_22)
|
||||||
|
- lwz 22,-40(11)
|
||||||
|
-_GLOBAL(_restgpr_23)
|
||||||
|
-_GLOBAL(_rest32gpr_23)
|
||||||
|
- lwz 23,-36(11)
|
||||||
|
-_GLOBAL(_restgpr_24)
|
||||||
|
-_GLOBAL(_rest32gpr_24)
|
||||||
|
- lwz 24,-32(11)
|
||||||
|
-_GLOBAL(_restgpr_25)
|
||||||
|
-_GLOBAL(_rest32gpr_25)
|
||||||
|
- lwz 25,-28(11)
|
||||||
|
-_GLOBAL(_restgpr_26)
|
||||||
|
-_GLOBAL(_rest32gpr_26)
|
||||||
|
- lwz 26,-24(11)
|
||||||
|
-_GLOBAL(_restgpr_27)
|
||||||
|
-_GLOBAL(_rest32gpr_27)
|
||||||
|
- lwz 27,-20(11)
|
||||||
|
-_GLOBAL(_restgpr_28)
|
||||||
|
-_GLOBAL(_rest32gpr_28)
|
||||||
|
- lwz 28,-16(11)
|
||||||
|
-_GLOBAL(_restgpr_29)
|
||||||
|
-_GLOBAL(_rest32gpr_29)
|
||||||
|
- lwz 29,-12(11)
|
||||||
|
-_GLOBAL(_restgpr_30)
|
||||||
|
-_GLOBAL(_rest32gpr_30)
|
||||||
|
- lwz 30,-8(11)
|
||||||
|
-_GLOBAL(_restgpr_31)
|
||||||
|
-_GLOBAL(_rest32gpr_31)
|
||||||
|
- lwz 31,-4(11)
|
||||||
|
- blr
|
||||||
|
-
|
||||||
|
-/* Routines for restoring integer registers, called by the compiler. */
|
||||||
|
-/* Called with r11 pointing to the stack header word of the caller of the */
|
||||||
|
-/* function, just beyond the end of the integer restore area. */
|
||||||
|
-
|
||||||
|
-_GLOBAL(_restgpr_14_x)
|
||||||
|
-_GLOBAL(_rest32gpr_14_x)
|
||||||
|
- lwz 14,-72(11) /* restore gp registers */
|
||||||
|
-_GLOBAL(_restgpr_15_x)
|
||||||
|
-_GLOBAL(_rest32gpr_15_x)
|
||||||
|
- lwz 15,-68(11)
|
||||||
|
-_GLOBAL(_restgpr_16_x)
|
||||||
|
-_GLOBAL(_rest32gpr_16_x)
|
||||||
|
- lwz 16,-64(11)
|
||||||
|
-_GLOBAL(_restgpr_17_x)
|
||||||
|
-_GLOBAL(_rest32gpr_17_x)
|
||||||
|
- lwz 17,-60(11)
|
||||||
|
-_GLOBAL(_restgpr_18_x)
|
||||||
|
-_GLOBAL(_rest32gpr_18_x)
|
||||||
|
- lwz 18,-56(11)
|
||||||
|
-_GLOBAL(_restgpr_19_x)
|
||||||
|
-_GLOBAL(_rest32gpr_19_x)
|
||||||
|
- lwz 19,-52(11)
|
||||||
|
-_GLOBAL(_restgpr_20_x)
|
||||||
|
-_GLOBAL(_rest32gpr_20_x)
|
||||||
|
- lwz 20,-48(11)
|
||||||
|
-_GLOBAL(_restgpr_21_x)
|
||||||
|
-_GLOBAL(_rest32gpr_21_x)
|
||||||
|
- lwz 21,-44(11)
|
||||||
|
-_GLOBAL(_restgpr_22_x)
|
||||||
|
-_GLOBAL(_rest32gpr_22_x)
|
||||||
|
- lwz 22,-40(11)
|
||||||
|
-_GLOBAL(_restgpr_23_x)
|
||||||
|
-_GLOBAL(_rest32gpr_23_x)
|
||||||
|
- lwz 23,-36(11)
|
||||||
|
-_GLOBAL(_restgpr_24_x)
|
||||||
|
-_GLOBAL(_rest32gpr_24_x)
|
||||||
|
- lwz 24,-32(11)
|
||||||
|
-_GLOBAL(_restgpr_25_x)
|
||||||
|
-_GLOBAL(_rest32gpr_25_x)
|
||||||
|
- lwz 25,-28(11)
|
||||||
|
-_GLOBAL(_restgpr_26_x)
|
||||||
|
-_GLOBAL(_rest32gpr_26_x)
|
||||||
|
- lwz 26,-24(11)
|
||||||
|
-_GLOBAL(_restgpr_27_x)
|
||||||
|
-_GLOBAL(_rest32gpr_27_x)
|
||||||
|
- lwz 27,-20(11)
|
||||||
|
-_GLOBAL(_restgpr_28_x)
|
||||||
|
-_GLOBAL(_rest32gpr_28_x)
|
||||||
|
- lwz 28,-16(11)
|
||||||
|
-_GLOBAL(_restgpr_29_x)
|
||||||
|
-_GLOBAL(_rest32gpr_29_x)
|
||||||
|
- lwz 29,-12(11)
|
||||||
|
-_GLOBAL(_restgpr_30_x)
|
||||||
|
-_GLOBAL(_rest32gpr_30_x)
|
||||||
|
- lwz 30,-8(11)
|
||||||
|
-_GLOBAL(_restgpr_31_x)
|
||||||
|
-_GLOBAL(_rest32gpr_31_x)
|
||||||
|
- lwz 0,4(11)
|
||||||
|
- lwz 31,-4(11)
|
||||||
|
- mtlr 0
|
||||||
|
- mr 1,11
|
||||||
|
- blr
|
||||||
|
-#endif
|
||||||
|
--- a/arch/powerpc/lib/Makefile
|
||||||
|
+++ b/arch/powerpc/lib/Makefile
|
||||||
|
@@ -11,7 +11,7 @@ CFLAGS_REMOVE_feature-fixups.o = -pg
|
||||||
|
|
||||||
|
obj-y := string.o alloc.o \
|
||||||
|
checksum_$(CONFIG_WORD_SIZE).o
|
||||||
|
-obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o
|
||||||
|
+obj-$(CONFIG_PPC32) += div64.o copy_32.o
|
||||||
|
obj-$(CONFIG_HAS_IOMEM) += devres.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \
|
||||||
|
--- a/arch/powerpc/Makefile
|
||||||
|
+++ b/arch/powerpc/Makefile
|
||||||
|
@@ -92,8 +92,6 @@ endif
|
||||||
|
else
|
||||||
|
KBUILD_CFLAGS += $(call cc-option,-mtune=power4)
|
||||||
|
endif
|
||||||
|
-else
|
||||||
|
-LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_TUNE_CELL),y)
|
@ -0,0 +1,25 @@
|
|||||||
|
--- a/crypto/Kconfig
|
||||||
|
+++ b/crypto/Kconfig
|
||||||
|
@@ -778,6 +778,8 @@ config CRYPTO_ANSI_CPRNG
|
||||||
|
for cryptographic modules. Uses the Algorithm specified in
|
||||||
|
ANSI X9.31 A.2.4
|
||||||
|
|
||||||
|
+source "crypto/ocf/Kconfig"
|
||||||
|
+
|
||||||
|
source "drivers/crypto/Kconfig"
|
||||||
|
|
||||||
|
endif # if CRYPTO
|
||||||
|
--- a/crypto/Makefile
|
||||||
|
+++ b/crypto/Makefile
|
||||||
|
@@ -85,6 +85,11 @@ obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_
|
||||||
|
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
|
||||||
|
|
||||||
|
#
|
||||||
|
+# OCF
|
||||||
|
+#
|
||||||
|
+obj-$(CONFIG_OCF_OCF) += ocf/
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
# generic algorithms and the async_tx api
|
||||||
|
#
|
||||||
|
obj-$(CONFIG_XOR_BLOCKS) += xor.o
|
152
target/linux/generic-2.6/patches-2.6.30/971-ocf_20080917.patch
Normal file
152
target/linux/generic-2.6/patches-2.6.30/971-ocf_20080917.patch
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
--- a/drivers/char/random.c
|
||||||
|
+++ b/drivers/char/random.c
|
||||||
|
@@ -129,6 +129,9 @@
|
||||||
|
* unsigned int value);
|
||||||
|
* void add_interrupt_randomness(int irq);
|
||||||
|
*
|
||||||
|
+ * void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
|
||||||
|
+ * int random_input_wait(void);
|
||||||
|
+ *
|
||||||
|
* add_input_randomness() uses the input layer interrupt timing, as well as
|
||||||
|
* the event type information from the hardware.
|
||||||
|
*
|
||||||
|
@@ -140,6 +143,13 @@
|
||||||
|
* a better measure, since the timing of the disk interrupts are more
|
||||||
|
* unpredictable.
|
||||||
|
*
|
||||||
|
+ * random_input_words() just provides a raw block of entropy to the input
|
||||||
|
+ * pool, such as from a hardware entropy generator.
|
||||||
|
+ *
|
||||||
|
+ * random_input_wait() suspends the caller until such time as the
|
||||||
|
+ * entropy pool falls below the write threshold, and returns a count of how
|
||||||
|
+ * much entropy (in bits) is needed to sustain the pool.
|
||||||
|
+ *
|
||||||
|
* All of these routines try to estimate how many bits of randomness a
|
||||||
|
* particular randomness source. They do this by keeping track of the
|
||||||
|
* first and second order deltas of the event timings.
|
||||||
|
@@ -712,6 +722,61 @@ void add_disk_randomness(struct gendisk
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * random_input_words - add bulk entropy to pool
|
||||||
|
+ *
|
||||||
|
+ * @buf: buffer to add
|
||||||
|
+ * @wordcount: number of __u32 words to add
|
||||||
|
+ * @ent_count: total amount of entropy (in bits) to credit
|
||||||
|
+ *
|
||||||
|
+ * this provides bulk input of entropy to the input pool
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
|
||||||
|
+{
|
||||||
|
+ mix_pool_bytes(&input_pool, buf, wordcount*4);
|
||||||
|
+
|
||||||
|
+ credit_entropy_bits(&input_pool, ent_count);
|
||||||
|
+
|
||||||
|
+ DEBUG_ENT("crediting %d bits => %d\n",
|
||||||
|
+ ent_count, input_pool.entropy_count);
|
||||||
|
+ /*
|
||||||
|
+ * Wake up waiting processes if we have enough
|
||||||
|
+ * entropy.
|
||||||
|
+ */
|
||||||
|
+ if (input_pool.entropy_count >= random_read_wakeup_thresh)
|
||||||
|
+ wake_up_interruptible(&random_read_wait);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(random_input_words);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * random_input_wait - wait until random needs entropy
|
||||||
|
+ *
|
||||||
|
+ * this function sleeps until the /dev/random subsystem actually
|
||||||
|
+ * needs more entropy, and then return the amount of entropy
|
||||||
|
+ * that it would be nice to have added to the system.
|
||||||
|
+ */
|
||||||
|
+int random_input_wait(void)
|
||||||
|
+{
|
||||||
|
+ int count;
|
||||||
|
+
|
||||||
|
+ wait_event_interruptible(random_write_wait,
|
||||||
|
+ input_pool.entropy_count < random_write_wakeup_thresh);
|
||||||
|
+
|
||||||
|
+ count = random_write_wakeup_thresh - input_pool.entropy_count;
|
||||||
|
+
|
||||||
|
+ /* likely we got woken up due to a signal */
|
||||||
|
+ if (count <= 0) count = random_read_wakeup_thresh;
|
||||||
|
+
|
||||||
|
+ DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n",
|
||||||
|
+ count,
|
||||||
|
+ input_pool.entropy_count, random_write_wakeup_thresh);
|
||||||
|
+
|
||||||
|
+ return count;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(random_input_wait);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
#define EXTRACT_SIZE 10
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
--- a/fs/fcntl.c
|
||||||
|
+++ b/fs/fcntl.c
|
||||||
|
@@ -140,6 +140,7 @@ SYSCALL_DEFINE1(dup, unsigned int, filde
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL(sys_dup);
|
||||||
|
|
||||||
|
#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
|
||||||
|
|
||||||
|
--- a/include/linux/miscdevice.h
|
||||||
|
+++ b/include/linux/miscdevice.h
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#define APOLLO_MOUSE_MINOR 7
|
||||||
|
#define PC110PAD_MINOR 9
|
||||||
|
/*#define ADB_MOUSE_MINOR 10 FIXME OBSOLETE */
|
||||||
|
+#define CRYPTODEV_MINOR 70 /* /dev/crypto */
|
||||||
|
#define WATCHDOG_MINOR 130 /* Watchdog timer */
|
||||||
|
#define TEMP_MINOR 131 /* Temperature Sensor */
|
||||||
|
#define RTC_MINOR 135
|
||||||
|
--- a/include/linux/random.h
|
||||||
|
+++ b/include/linux/random.h
|
||||||
|
@@ -34,6 +34,30 @@
|
||||||
|
/* Clear the entropy pool and associated counters. (Superuser only.) */
|
||||||
|
#define RNDCLEARPOOL _IO( 'R', 0x06 )
|
||||||
|
|
||||||
|
+#ifdef CONFIG_FIPS_RNG
|
||||||
|
+
|
||||||
|
+/* Size of seed value - equal to AES blocksize */
|
||||||
|
+#define AES_BLOCK_SIZE_BYTES 16
|
||||||
|
+#define SEED_SIZE_BYTES AES_BLOCK_SIZE_BYTES
|
||||||
|
+/* Size of AES key */
|
||||||
|
+#define KEY_SIZE_BYTES 16
|
||||||
|
+
|
||||||
|
+/* ioctl() structure used by FIPS 140-2 Tests */
|
||||||
|
+struct rand_fips_test {
|
||||||
|
+ unsigned char key[KEY_SIZE_BYTES]; /* Input */
|
||||||
|
+ unsigned char datetime[SEED_SIZE_BYTES]; /* Input */
|
||||||
|
+ unsigned char seed[SEED_SIZE_BYTES]; /* Input */
|
||||||
|
+ unsigned char result[SEED_SIZE_BYTES]; /* Output */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */
|
||||||
|
+#define RNDFIPSVST _IOWR('R', 0x10, struct rand_fips_test)
|
||||||
|
+
|
||||||
|
+/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */
|
||||||
|
+#define RNDFIPSMCT _IOWR('R', 0x11, struct rand_fips_test)
|
||||||
|
+
|
||||||
|
+#endif /* #ifdef CONFIG_FIPS_RNG */
|
||||||
|
+
|
||||||
|
struct rand_pool_info {
|
||||||
|
int entropy_count;
|
||||||
|
int buf_size;
|
||||||
|
@@ -50,6 +74,10 @@ extern void add_input_randomness(unsigne
|
||||||
|
unsigned int value);
|
||||||
|
extern void add_interrupt_randomness(int irq);
|
||||||
|
|
||||||
|
+extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count);
|
||||||
|
+extern int random_input_wait(void);
|
||||||
|
+#define HAS_RANDOM_INPUT_WAIT 1
|
||||||
|
+
|
||||||
|
extern void get_random_bytes(void *buf, int nbytes);
|
||||||
|
void generate_random_uuid(unsigned char uuid_out[16]);
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/crypto/ocf/cryptosoft.c
|
||||||
|
+++ b/crypto/ocf/cryptosoft.c
|
||||||
|
@@ -47,7 +47,7 @@
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
-#include <asm/scatterlist.h>
|
||||||
|
+#include <linux/scatterlist.h>
|
||||||
|
|
||||||
|
#include <cryptodev.h>
|
||||||
|
#include <uio.h>
|
197
target/linux/generic-2.6/patches-2.6.30/973-ocf_2.6.27_fix.patch
Normal file
197
target/linux/generic-2.6/patches-2.6.30/973-ocf_2.6.27_fix.patch
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
--- a/crypto/ocf/random.c
|
||||||
|
+++ b/crypto/ocf/random.c
|
||||||
|
@@ -49,6 +49,7 @@
|
||||||
|
#include <linux/unistd.h>
|
||||||
|
#include <linux/poll.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
+#include <linux/kthread.h>
|
||||||
|
#include <cryptodev.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_OCF_FIPS
|
||||||
|
@@ -81,7 +82,7 @@ struct random_op {
|
||||||
|
|
||||||
|
static int random_proc(void *arg);
|
||||||
|
|
||||||
|
-static pid_t randomproc = (pid_t) -1;
|
||||||
|
+static struct task_struct *random_task;
|
||||||
|
static spinlock_t random_lock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -141,13 +142,18 @@ crypto_rregister(
|
||||||
|
spin_lock_irqsave(&random_lock, flags);
|
||||||
|
list_add_tail(&rops->random_list, &random_ops);
|
||||||
|
if (!started) {
|
||||||
|
- randomproc = kernel_thread(random_proc, NULL, CLONE_FS|CLONE_FILES);
|
||||||
|
- if (randomproc < 0) {
|
||||||
|
- ret = randomproc;
|
||||||
|
+ struct task_struct *t;
|
||||||
|
+
|
||||||
|
+ t = kthread_create(random_proc, NULL, "ocf-random");
|
||||||
|
+ if (IS_ERR(t)) {
|
||||||
|
printk("crypto: crypto_rregister cannot start random thread; "
|
||||||
|
"error %d", ret);
|
||||||
|
- } else
|
||||||
|
+ ret = PTR_ERR(t);
|
||||||
|
+ } else {
|
||||||
|
+ random_task = t;
|
||||||
|
+ wake_up_process(t);
|
||||||
|
started = 1;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&random_lock, flags);
|
||||||
|
|
||||||
|
@@ -172,7 +178,7 @@ crypto_runregister_all(u_int32_t driveri
|
||||||
|
|
||||||
|
spin_lock_irqsave(&random_lock, flags);
|
||||||
|
if (list_empty(&random_ops) && started)
|
||||||
|
- kill_proc(randomproc, SIGKILL, 1);
|
||||||
|
+ send_sig(SIGKILL, random_task, 1);
|
||||||
|
spin_unlock_irqrestore(&random_lock, flags);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
@@ -308,7 +314,7 @@ random_proc(void *arg)
|
||||||
|
|
||||||
|
bad_alloc:
|
||||||
|
spin_lock_irq(&random_lock);
|
||||||
|
- randomproc = (pid_t) -1;
|
||||||
|
+ random_task = NULL;
|
||||||
|
started = 0;
|
||||||
|
spin_unlock_irq(&random_lock);
|
||||||
|
|
||||||
|
--- a/crypto/ocf/crypto.c
|
||||||
|
+++ b/crypto/ocf/crypto.c
|
||||||
|
@@ -74,6 +74,7 @@ __FBSDID("$FreeBSD: src/sys/opencrypto/c
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
+#include <linux/kthread.h>
|
||||||
|
#include <cryptodev.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -255,10 +256,10 @@ module_param(crypto_devallowsoft, int, 0
|
||||||
|
MODULE_PARM_DESC(crypto_devallowsoft,
|
||||||
|
"Enable/disable use of software crypto support");
|
||||||
|
|
||||||
|
-static pid_t cryptoproc = (pid_t) -1;
|
||||||
|
+static struct task_struct *crypto_task;
|
||||||
|
static struct completion cryptoproc_exited;
|
||||||
|
static DECLARE_WAIT_QUEUE_HEAD(cryptoproc_wait);
|
||||||
|
-static pid_t cryptoretproc = (pid_t) -1;
|
||||||
|
+static struct task_struct *cryptoret_task;
|
||||||
|
static struct completion cryptoretproc_exited;
|
||||||
|
static DECLARE_WAIT_QUEUE_HEAD(cryptoretproc_wait);
|
||||||
|
|
||||||
|
@@ -1401,7 +1402,7 @@ crypto_proc(void *arg)
|
||||||
|
wait_event_interruptible(cryptoproc_wait,
|
||||||
|
!(list_empty(&crp_q) || crypto_all_qblocked) ||
|
||||||
|
!(list_empty(&crp_kq) || crypto_all_kqblocked) ||
|
||||||
|
- cryptoproc == (pid_t) -1);
|
||||||
|
+ crypto_task == NULL);
|
||||||
|
crp_sleep = 0;
|
||||||
|
if (signal_pending (current)) {
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||||
|
@@ -1414,7 +1415,7 @@ crypto_proc(void *arg)
|
||||||
|
}
|
||||||
|
CRYPTO_Q_LOCK();
|
||||||
|
dprintk("%s - awake\n", __FUNCTION__);
|
||||||
|
- if (cryptoproc == (pid_t) -1)
|
||||||
|
+ if (crypto_task == NULL)
|
||||||
|
break;
|
||||||
|
cryptostats.cs_intrs++;
|
||||||
|
}
|
||||||
|
@@ -1470,7 +1471,7 @@ crypto_ret_proc(void *arg)
|
||||||
|
dprintk("%s - sleeping\n", __FUNCTION__);
|
||||||
|
CRYPTO_RETQ_UNLOCK();
|
||||||
|
wait_event_interruptible(cryptoretproc_wait,
|
||||||
|
- cryptoretproc == (pid_t) -1 ||
|
||||||
|
+ cryptoret_task == NULL ||
|
||||||
|
!list_empty(&crp_ret_q) ||
|
||||||
|
!list_empty(&crp_ret_kq));
|
||||||
|
if (signal_pending (current)) {
|
||||||
|
@@ -1484,7 +1485,7 @@ crypto_ret_proc(void *arg)
|
||||||
|
}
|
||||||
|
CRYPTO_RETQ_LOCK();
|
||||||
|
dprintk("%s - awake\n", __FUNCTION__);
|
||||||
|
- if (cryptoretproc == (pid_t) -1) {
|
||||||
|
+ if (cryptoret_task == NULL) {
|
||||||
|
dprintk("%s - EXITING!\n", __FUNCTION__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -1597,6 +1598,7 @@ DB_SHOW_COMMAND(kcrypto, db_show_kcrypto
|
||||||
|
static int
|
||||||
|
crypto_init(void)
|
||||||
|
{
|
||||||
|
+ struct task_struct *t;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init);
|
||||||
|
@@ -1643,23 +1645,27 @@ crypto_init(void)
|
||||||
|
init_completion(&cryptoproc_exited);
|
||||||
|
init_completion(&cryptoretproc_exited);
|
||||||
|
|
||||||
|
- cryptoproc = 0; /* to avoid race condition where proc runs first */
|
||||||
|
- cryptoproc = kernel_thread(crypto_proc, NULL, CLONE_FS|CLONE_FILES);
|
||||||
|
- if (cryptoproc < 0) {
|
||||||
|
- error = cryptoproc;
|
||||||
|
+ crypto_task = NULL; /* to avoid race condition where proc runs first */
|
||||||
|
+ t = kthread_create(crypto_proc, NULL, "ocf-crypto");
|
||||||
|
+ if (IS_ERR(t)) {
|
||||||
|
+ error = PTR_ERR(t);
|
||||||
|
printk("crypto: crypto_init cannot start crypto thread; error %d",
|
||||||
|
error);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
+ wake_up_process(t);
|
||||||
|
+ crypto_task = t;
|
||||||
|
|
||||||
|
- cryptoretproc = 0; /* to avoid race condition where proc runs first */
|
||||||
|
- cryptoretproc = kernel_thread(crypto_ret_proc, NULL, CLONE_FS|CLONE_FILES);
|
||||||
|
- if (cryptoretproc < 0) {
|
||||||
|
- error = cryptoretproc;
|
||||||
|
+ cryptoret_task = NULL; /* to avoid race condition where proc runs first */
|
||||||
|
+ t = kthread_create(crypto_ret_proc, NULL, "ocf-cryptoret");
|
||||||
|
+ if (IS_ERR(t)) {
|
||||||
|
+ error = PTR_ERR(t);
|
||||||
|
printk("crypto: crypto_init cannot start cryptoret thread; error %d",
|
||||||
|
error);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
+ wake_up_process(t);
|
||||||
|
+ cryptoret_task = t;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
bad:
|
||||||
|
@@ -1671,7 +1677,7 @@ bad:
|
||||||
|
static void
|
||||||
|
crypto_exit(void)
|
||||||
|
{
|
||||||
|
- pid_t p;
|
||||||
|
+ struct task_struct *t;
|
||||||
|
unsigned long d_flags;
|
||||||
|
|
||||||
|
dprintk("%s()\n", __FUNCTION__);
|
||||||
|
@@ -1681,18 +1687,18 @@ crypto_exit(void)
|
||||||
|
*/
|
||||||
|
|
||||||
|
CRYPTO_DRIVER_LOCK();
|
||||||
|
- p = cryptoproc;
|
||||||
|
- cryptoproc = (pid_t) -1;
|
||||||
|
- kill_proc(p, SIGTERM, 1);
|
||||||
|
+ t = crypto_task;
|
||||||
|
+ crypto_task = NULL;
|
||||||
|
+ send_sig(SIGTERM, t, 1);
|
||||||
|
wake_up_interruptible(&cryptoproc_wait);
|
||||||
|
CRYPTO_DRIVER_UNLOCK();
|
||||||
|
|
||||||
|
wait_for_completion(&cryptoproc_exited);
|
||||||
|
|
||||||
|
CRYPTO_DRIVER_LOCK();
|
||||||
|
- p = cryptoretproc;
|
||||||
|
- cryptoretproc = (pid_t) -1;
|
||||||
|
- kill_proc(p, SIGTERM, 1);
|
||||||
|
+ t = cryptoret_task;
|
||||||
|
+ cryptoret_task = NULL;
|
||||||
|
+ send_sig(SIGTERM, t, 1);
|
||||||
|
wake_up_interruptible(&cryptoretproc_wait);
|
||||||
|
CRYPTO_DRIVER_UNLOCK();
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/drivers/ssb/Kconfig
|
||||||
|
+++ b/drivers/ssb/Kconfig
|
||||||
|
@@ -49,7 +49,7 @@ config SSB_PCIHOST
|
||||||
|
config SSB_B43_PCI_BRIDGE
|
||||||
|
bool
|
||||||
|
depends on SSB_PCIHOST
|
||||||
|
- default n
|
||||||
|
+ default y
|
||||||
|
|
||||||
|
config SSB_PCMCIAHOST_POSSIBLE
|
||||||
|
bool
|
@ -0,0 +1,23 @@
|
|||||||
|
--- a/lib/Kconfig
|
||||||
|
+++ b/lib/Kconfig
|
||||||
|
@@ -142,16 +142,16 @@ config REED_SOLOMON_DEC16
|
||||||
|
# Textsearch support is select'ed if needed
|
||||||
|
#
|
||||||
|
config TEXTSEARCH
|
||||||
|
- boolean
|
||||||
|
+ boolean "Textsearch support"
|
||||||
|
|
||||||
|
config TEXTSEARCH_KMP
|
||||||
|
- tristate
|
||||||
|
+ tristate "Textsearch KMP"
|
||||||
|
|
||||||
|
config TEXTSEARCH_BM
|
||||||
|
- tristate
|
||||||
|
+ tristate "Textsearch BM"
|
||||||
|
|
||||||
|
config TEXTSEARCH_FSM
|
||||||
|
- tristate
|
||||||
|
+ tristate "Textsearch FSM"
|
||||||
|
|
||||||
|
config HAS_IOMEM
|
||||||
|
boolean
|
@ -0,0 +1,47 @@
|
|||||||
|
--- a/crypto/Kconfig
|
||||||
|
+++ b/crypto/Kconfig
|
||||||
|
@@ -30,7 +30,7 @@ config CRYPTO_FIPS
|
||||||
|
this is.
|
||||||
|
|
||||||
|
config CRYPTO_ALGAPI
|
||||||
|
- tristate
|
||||||
|
+ tristate "ALGAPI"
|
||||||
|
select CRYPTO_ALGAPI2
|
||||||
|
help
|
||||||
|
This option provides the API for cryptographic algorithms.
|
||||||
|
@@ -39,7 +39,7 @@ config CRYPTO_ALGAPI2
|
||||||
|
tristate
|
||||||
|
|
||||||
|
config CRYPTO_AEAD
|
||||||
|
- tristate
|
||||||
|
+ tristate "AEAD"
|
||||||
|
select CRYPTO_AEAD2
|
||||||
|
select CRYPTO_ALGAPI
|
||||||
|
|
||||||
|
@@ -48,7 +48,7 @@ config CRYPTO_AEAD2
|
||||||
|
select CRYPTO_ALGAPI2
|
||||||
|
|
||||||
|
config CRYPTO_BLKCIPHER
|
||||||
|
- tristate
|
||||||
|
+ tristate "BLKCIPHER"
|
||||||
|
select CRYPTO_BLKCIPHER2
|
||||||
|
select CRYPTO_ALGAPI
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ config CRYPTO_BLKCIPHER2
|
||||||
|
select CRYPTO_WORKQUEUE
|
||||||
|
|
||||||
|
config CRYPTO_HASH
|
||||||
|
- tristate
|
||||||
|
+ tristate "HASH"
|
||||||
|
select CRYPTO_HASH2
|
||||||
|
select CRYPTO_ALGAPI
|
||||||
|
|
||||||
|
@@ -68,7 +68,7 @@ config CRYPTO_HASH2
|
||||||
|
select CRYPTO_ALGAPI2
|
||||||
|
|
||||||
|
config CRYPTO_RNG
|
||||||
|
- tristate
|
||||||
|
+ tristate "RNG"
|
||||||
|
select CRYPTO_RNG2
|
||||||
|
select CRYPTO_ALGAPI
|
||||||
|
|
116
target/linux/generic-2.6/patches-2.6.30/980-vm_exports.patch
Normal file
116
target/linux/generic-2.6/patches-2.6.30/980-vm_exports.patch
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
--- a/mm/shmem.c
|
||||||
|
+++ b/mm/shmem.c
|
||||||
|
@@ -2587,6 +2587,16 @@ int shmem_unuse(swp_entry_t entry, struc
|
||||||
|
|
||||||
|
/* common code */
|
||||||
|
|
||||||
|
+void shmem_set_file(struct vm_area_struct *vma, struct file *file)
|
||||||
|
+{
|
||||||
|
+ ima_shm_check(file);
|
||||||
|
+ if (vma->vm_file)
|
||||||
|
+ fput(vma->vm_file);
|
||||||
|
+ vma->vm_file = file;
|
||||||
|
+ vma->vm_ops = &shmem_vm_ops;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(shmem_set_file);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* shmem_file_setup - get an unlinked file living in tmpfs
|
||||||
|
* @name: name for dentry (to be seen in /proc/<pid>/maps
|
||||||
|
@@ -2665,11 +2675,7 @@ int shmem_zero_setup(struct vm_area_stru
|
||||||
|
if (IS_ERR(file))
|
||||||
|
return PTR_ERR(file);
|
||||||
|
|
||||||
|
- ima_shm_check(file);
|
||||||
|
- if (vma->vm_file)
|
||||||
|
- fput(vma->vm_file);
|
||||||
|
- vma->vm_file = file;
|
||||||
|
- vma->vm_ops = &shmem_vm_ops;
|
||||||
|
+ shmem_set_file(vma, file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/fs/file.c
|
||||||
|
+++ b/fs/file.c
|
||||||
|
@@ -270,6 +270,7 @@ int expand_files(struct files_struct *fi
|
||||||
|
/* All good, so we try */
|
||||||
|
return expand_fdtable(files, nr);
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(expand_files);
|
||||||
|
|
||||||
|
static int count_open_files(struct fdtable *fdt)
|
||||||
|
{
|
||||||
|
--- a/kernel/exit.c
|
||||||
|
+++ b/kernel/exit.c
|
||||||
|
@@ -508,6 +508,7 @@ struct files_struct *get_files_struct(st
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(get_files_struct);
|
||||||
|
|
||||||
|
void put_files_struct(struct files_struct *files)
|
||||||
|
{
|
||||||
|
@@ -527,6 +528,7 @@ void put_files_struct(struct files_struc
|
||||||
|
free_fdtable(fdt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(put_files_struct);
|
||||||
|
|
||||||
|
void reset_files_struct(struct files_struct *files)
|
||||||
|
{
|
||||||
|
--- a/kernel/fork.c
|
||||||
|
+++ b/kernel/fork.c
|
||||||
|
@@ -160,6 +160,7 @@ void __put_task_struct(struct task_struc
|
||||||
|
if (!profile_handoff_task(tsk))
|
||||||
|
free_task(tsk);
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(__put_task_struct);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* macro override instead of weak attribute alias, to workaround
|
||||||
|
--- a/kernel/sched.c
|
||||||
|
+++ b/kernel/sched.c
|
||||||
|
@@ -5600,6 +5600,7 @@ int can_nice(const struct task_struct *p
|
||||||
|
return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur ||
|
||||||
|
capable(CAP_SYS_NICE));
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(can_nice);
|
||||||
|
|
||||||
|
#ifdef __ARCH_WANT_SYS_NICE
|
||||||
|
|
||||||
|
--- a/mm/memory.c
|
||||||
|
+++ b/mm/memory.c
|
||||||
|
@@ -1063,6 +1063,7 @@ unsigned long zap_page_range(struct vm_a
|
||||||
|
tlb_finish_mmu(tlb, address, end);
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(zap_page_range);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zap_vma_ptes - remove ptes mapping the vma
|
||||||
|
@@ -2405,6 +2406,7 @@ int vmtruncate_range(struct inode *inode
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(vmtruncate_range);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We enter with non-exclusive mmap_sem (to exclude vma changes,
|
||||||
|
--- a/mm/vmalloc.c
|
||||||
|
+++ b/mm/vmalloc.c
|
||||||
|
@@ -1100,6 +1100,7 @@ void unmap_kernel_range(unsigned long ad
|
||||||
|
vunmap_page_range(addr, end);
|
||||||
|
flush_tlb_kernel_range(addr, end);
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(unmap_kernel_range);
|
||||||
|
|
||||||
|
int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
|
||||||
|
{
|
||||||
|
@@ -1213,6 +1214,7 @@ struct vm_struct *get_vm_area(unsigned l
|
||||||
|
return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
|
||||||
|
-1, GFP_KERNEL, __builtin_return_address(0));
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL_GPL(get_vm_area);
|
||||||
|
|
||||||
|
struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
|
||||||
|
void *caller)
|
@ -0,0 +1,27 @@
|
|||||||
|
--- a/arch/cris/include/arch-v10/arch/Kbuild
|
||||||
|
+++ b/arch/cris/include/arch-v10/arch/Kbuild
|
||||||
|
@@ -1,3 +1,5 @@
|
||||||
|
+header-y += elf.h
|
||||||
|
+header-y += ptrace.h
|
||||||
|
header-y += user.h
|
||||||
|
header-y += svinto.h
|
||||||
|
header-y += sv_addr_ag.h
|
||||||
|
--- a/arch/cris/include/asm/Kbuild
|
||||||
|
+++ b/arch/cris/include/asm/Kbuild
|
||||||
|
@@ -1,11 +1,14 @@
|
||||||
|
include include/asm-generic/Kbuild.asm
|
||||||
|
|
||||||
|
-header-y += arch-v10/
|
||||||
|
-header-y += arch-v32/
|
||||||
|
+header-y += ../arch-v10/arch/
|
||||||
|
+header-y += ../arch-v32/arch/
|
||||||
|
|
||||||
|
+header-y += elf.h
|
||||||
|
header-y += ethernet.h
|
||||||
|
+header-y += page.h
|
||||||
|
header-y += rtc.h
|
||||||
|
header-y += sync_serial.h
|
||||||
|
+header-y += user.h
|
||||||
|
|
||||||
|
unifdef-y += etraxgpio.h
|
||||||
|
unifdef-y += rs485.h
|
271
target/linux/ixp4xx/config-2.6.30
Normal file
271
target/linux/ixp4xx/config-2.6.30
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
# CONFIG_AEABI is not set
|
||||||
|
CONFIG_ALIGNMENT_TRAP=y
|
||||||
|
# CONFIG_ARCH_AAEC2000 is not set
|
||||||
|
# CONFIG_ARCH_ADI_COYOTE is not set
|
||||||
|
# CONFIG_ARCH_AT91 is not set
|
||||||
|
# CONFIG_ARCH_CLPS711X is not set
|
||||||
|
# CONFIG_ARCH_DAVINCI is not set
|
||||||
|
# CONFIG_ARCH_EBSA110 is not set
|
||||||
|
# CONFIG_ARCH_EP93XX is not set
|
||||||
|
CONFIG_ARCH_FLATMEM_HAS_HOLES=y
|
||||||
|
# CONFIG_ARCH_FOOTBRIDGE is not set
|
||||||
|
# CONFIG_ARCH_H720X is not set
|
||||||
|
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||||
|
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||||
|
# CONFIG_ARCH_IMX is not set
|
||||||
|
# CONFIG_ARCH_INTEGRATOR is not set
|
||||||
|
# CONFIG_ARCH_IOP13XX is not set
|
||||||
|
# CONFIG_ARCH_IOP32X is not set
|
||||||
|
# CONFIG_ARCH_IOP33X is not set
|
||||||
|
CONFIG_ARCH_IXCDP1100=y
|
||||||
|
CONFIG_ARCH_IXDP425=y
|
||||||
|
CONFIG_ARCH_IXDP4XX=y
|
||||||
|
# CONFIG_ARCH_IXP2000 is not set
|
||||||
|
# CONFIG_ARCH_IXP23XX is not set
|
||||||
|
CONFIG_ARCH_IXP4XX=y
|
||||||
|
# CONFIG_ARCH_KIRKWOOD is not set
|
||||||
|
# CONFIG_ARCH_KS8695 is not set
|
||||||
|
# CONFIG_ARCH_L7200 is not set
|
||||||
|
# CONFIG_ARCH_LH7A40X is not set
|
||||||
|
# CONFIG_ARCH_LOKI is not set
|
||||||
|
# CONFIG_ARCH_MMP is not set
|
||||||
|
# CONFIG_ARCH_MSM is not set
|
||||||
|
# CONFIG_ARCH_MV78XX0 is not set
|
||||||
|
# CONFIG_ARCH_MXC is not set
|
||||||
|
# CONFIG_ARCH_NETX is not set
|
||||||
|
# CONFIG_ARCH_NS9XXX is not set
|
||||||
|
# CONFIG_ARCH_OMAP is not set
|
||||||
|
# CONFIG_ARCH_ORION5X is not set
|
||||||
|
# CONFIG_ARCH_PNX4008 is not set
|
||||||
|
# CONFIG_ARCH_PRPMC1100 is not set
|
||||||
|
# CONFIG_ARCH_PXA is not set
|
||||||
|
# CONFIG_ARCH_REALVIEW is not set
|
||||||
|
CONFIG_ARCH_REQUIRE_GPIOLIB=y
|
||||||
|
# CONFIG_ARCH_RPC is not set
|
||||||
|
# CONFIG_ARCH_S3C2410 is not set
|
||||||
|
# CONFIG_ARCH_S3C64XX is not set
|
||||||
|
# CONFIG_ARCH_SA1100 is not set
|
||||||
|
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
|
||||||
|
# CONFIG_ARCH_SHARK is not set
|
||||||
|
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
|
||||||
|
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
|
||||||
|
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||||
|
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||||
|
# CONFIG_ARCH_VERSATILE is not set
|
||||||
|
# CONFIG_ARCH_W90X900 is not set
|
||||||
|
CONFIG_ARM=y
|
||||||
|
# CONFIG_ARM_THUMB is not set
|
||||||
|
# CONFIG_ARPD is not set
|
||||||
|
CONFIG_BASE_SMALL=0
|
||||||
|
CONFIG_BITREVERSE=y
|
||||||
|
CONFIG_BOUNCE=y
|
||||||
|
CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200 init=/etc/preinit"
|
||||||
|
CONFIG_COMPAT_NET_DEV_OPS=y
|
||||||
|
# CONFIG_CONFIGFS_FS is not set
|
||||||
|
CONFIG_CPU_32=y
|
||||||
|
CONFIG_CPU_32v5=y
|
||||||
|
CONFIG_CPU_ABRT_EV5T=y
|
||||||
|
CONFIG_CPU_BIG_ENDIAN=y
|
||||||
|
CONFIG_CPU_CACHE_VIVT=y
|
||||||
|
CONFIG_CPU_CP15=y
|
||||||
|
CONFIG_CPU_CP15_MMU=y
|
||||||
|
CONFIG_CPU_IXP43X=y
|
||||||
|
CONFIG_CPU_IXP46X=y
|
||||||
|
CONFIG_CPU_PABRT_NOIFAR=y
|
||||||
|
CONFIG_CPU_TLB_V4WBI=y
|
||||||
|
CONFIG_CPU_XSCALE=y
|
||||||
|
CONFIG_CRC16=y
|
||||||
|
# CONFIG_DCB is not set
|
||||||
|
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||||
|
# CONFIG_DEBUG_USER is not set
|
||||||
|
CONFIG_DEFAULT_VEGAS=y
|
||||||
|
# CONFIG_DEFAULT_WESTWOOD is not set
|
||||||
|
CONFIG_DEVPORT=y
|
||||||
|
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
|
||||||
|
# CONFIG_DM9000 is not set
|
||||||
|
CONFIG_DMABOUNCE=y
|
||||||
|
CONFIG_DMABOUNCE_DEBUG=y
|
||||||
|
CONFIG_DNOTIFY=y
|
||||||
|
CONFIG_EEPROM_AT24=y
|
||||||
|
# CONFIG_EEPROM_LEGACY is not set
|
||||||
|
# CONFIG_FIXED_PHY is not set
|
||||||
|
# CONFIG_FPE_FASTFPE is not set
|
||||||
|
# CONFIG_FPE_NWFPE is not set
|
||||||
|
CONFIG_FRAME_POINTER=y
|
||||||
|
# CONFIG_FREEZER is not set
|
||||||
|
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||||
|
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||||
|
CONFIG_GENERIC_FIND_LAST_BIT=y
|
||||||
|
CONFIG_GENERIC_GPIO=y
|
||||||
|
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||||
|
CONFIG_GPIOLIB=y
|
||||||
|
CONFIG_GPIO_DEVICE=y
|
||||||
|
CONFIG_GPIO_GW_I2C_PLD=y
|
||||||
|
CONFIG_GPIO_SYSFS=y
|
||||||
|
# CONFIG_HAMRADIO is not set
|
||||||
|
CONFIG_HARDIRQS_SW_RESEND=y
|
||||||
|
CONFIG_HAS_DMA=y
|
||||||
|
CONFIG_HAS_IOMEM=y
|
||||||
|
CONFIG_HAS_IOPORT=y
|
||||||
|
CONFIG_HAVE_AOUT=y
|
||||||
|
CONFIG_HAVE_ARCH_KGDB=y
|
||||||
|
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||||
|
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||||
|
CONFIG_HAVE_IDE=y
|
||||||
|
CONFIG_HAVE_KPROBES=y
|
||||||
|
CONFIG_HAVE_KRETPROBES=y
|
||||||
|
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
||||||
|
CONFIG_HAVE_MTD_OTP=y
|
||||||
|
CONFIG_HAVE_OPROFILE=y
|
||||||
|
# CONFIG_HTC_EGPIO is not set
|
||||||
|
CONFIG_HWMON=y
|
||||||
|
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||||
|
CONFIG_HWMON_VID=y
|
||||||
|
CONFIG_HW_RANDOM=y
|
||||||
|
CONFIG_HW_RANDOM_IXP4XX=y
|
||||||
|
CONFIG_I2C=y
|
||||||
|
CONFIG_I2C_ALGOBIT=y
|
||||||
|
CONFIG_I2C_BOARDINFO=y
|
||||||
|
CONFIG_I2C_CHARDEV=y
|
||||||
|
CONFIG_I2C_GPIO=y
|
||||||
|
# CONFIG_I2C_IOP3XX is not set
|
||||||
|
CONFIG_INITRAMFS_SOURCE=""
|
||||||
|
CONFIG_IP_MROUTE=y
|
||||||
|
CONFIG_IP_PIMSM_V1=y
|
||||||
|
CONFIG_IP_PIMSM_V2=y
|
||||||
|
# CONFIG_ISDN is not set
|
||||||
|
# CONFIG_IWMMXT is not set
|
||||||
|
CONFIG_IXP4XX_ETH=y
|
||||||
|
# CONFIG_IXP4XX_INDIRECT_PCI is not set
|
||||||
|
CONFIG_IXP4XX_NPE=y
|
||||||
|
CONFIG_IXP4XX_QMGR=y
|
||||||
|
CONFIG_IXP4XX_WATCHDOG=y
|
||||||
|
CONFIG_LEDS_FSG=y
|
||||||
|
CONFIG_LEDS_GPIO=y
|
||||||
|
CONFIG_LEDS_LATCH=y
|
||||||
|
CONFIG_LEGACY_PTYS=y
|
||||||
|
CONFIG_LEGACY_PTY_COUNT=256
|
||||||
|
# CONFIG_LIB80211 is not set
|
||||||
|
# CONFIG_LSI_ET1011C_PHY is not set
|
||||||
|
CONFIG_MACH_AP1000=y
|
||||||
|
CONFIG_MACH_AVILA=y
|
||||||
|
CONFIG_MACH_CAMBRIA=y
|
||||||
|
CONFIG_MACH_COMPEX=y
|
||||||
|
CONFIG_MACH_DSMG600=y
|
||||||
|
CONFIG_MACH_FSG=y
|
||||||
|
CONFIG_MACH_GATEWAY7001=y
|
||||||
|
# CONFIG_MACH_GTWX5715 is not set
|
||||||
|
# CONFIG_MACH_IXDP465 is not set
|
||||||
|
CONFIG_MACH_IXDPG425=y
|
||||||
|
# CONFIG_MACH_KIXRP435 is not set
|
||||||
|
CONFIG_MACH_LOFT=y
|
||||||
|
CONFIG_MACH_MI424WR=y
|
||||||
|
CONFIG_MACH_NAS100D=y
|
||||||
|
CONFIG_MACH_NSLU2=y
|
||||||
|
CONFIG_MACH_PRONGHORN=y
|
||||||
|
CONFIG_MACH_PRONGHORNMETRO=y
|
||||||
|
CONFIG_MACH_SIDEWINDER=y
|
||||||
|
CONFIG_MACH_TW5334=y
|
||||||
|
CONFIG_MACH_USR8200=y
|
||||||
|
CONFIG_MACH_WG302V1=y
|
||||||
|
CONFIG_MACH_WG302V2=y
|
||||||
|
CONFIG_MACH_WRT300NV2=y
|
||||||
|
# CONFIG_MAC_PARTITION is not set
|
||||||
|
CONFIG_MISC_FILESYSTEMS=y
|
||||||
|
CONFIG_MTD=y
|
||||||
|
# CONFIG_MTD_ABSENT is not set
|
||||||
|
# CONFIG_MTD_AFS_PARTS is not set
|
||||||
|
# CONFIG_MTD_ARM_INTEGRATOR is not set
|
||||||
|
CONFIG_MTD_BLKDEVS=y
|
||||||
|
CONFIG_MTD_BLOCK=y
|
||||||
|
# CONFIG_MTD_BLOCK2MTD is not set
|
||||||
|
CONFIG_MTD_CFI=y
|
||||||
|
CONFIG_MTD_CFI_ADV_OPTIONS=y
|
||||||
|
CONFIG_MTD_CFI_AMDSTD=y
|
||||||
|
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
|
||||||
|
# CONFIG_MTD_CFI_GEOMETRY is not set
|
||||||
|
CONFIG_MTD_CFI_I1=y
|
||||||
|
CONFIG_MTD_CFI_I2=y
|
||||||
|
# CONFIG_MTD_CFI_I4 is not set
|
||||||
|
# CONFIG_MTD_CFI_I8 is not set
|
||||||
|
CONFIG_MTD_CFI_INTELEXT=y
|
||||||
|
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
|
||||||
|
CONFIG_MTD_CFI_NOSWAP=y
|
||||||
|
# CONFIG_MTD_CFI_STAA is not set
|
||||||
|
CONFIG_MTD_CFI_UTIL=y
|
||||||
|
CONFIG_MTD_CHAR=y
|
||||||
|
# CONFIG_MTD_CMDLINE_PARTS is not set
|
||||||
|
CONFIG_MTD_COMPLEX_MAPPINGS=y
|
||||||
|
# CONFIG_MTD_CONCAT is not set
|
||||||
|
CONFIG_MTD_GEN_PROBE=y
|
||||||
|
CONFIG_MTD_IXP4XX=y
|
||||||
|
# CONFIG_MTD_JEDECPROBE is not set
|
||||||
|
# CONFIG_MTD_LPDDR is not set
|
||||||
|
CONFIG_MTD_MAP_BANK_WIDTH_1=y
|
||||||
|
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
|
||||||
|
CONFIG_MTD_MAP_BANK_WIDTH_2=y
|
||||||
|
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
|
||||||
|
CONFIG_MTD_MAP_BANK_WIDTH_4=y
|
||||||
|
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
|
||||||
|
# CONFIG_MTD_MTDRAM is not set
|
||||||
|
# CONFIG_MTD_ONENAND is not set
|
||||||
|
CONFIG_MTD_OTP=y
|
||||||
|
CONFIG_MTD_PARTITIONS=y
|
||||||
|
# CONFIG_MTD_PCI is not set
|
||||||
|
# CONFIG_MTD_PHRAM is not set
|
||||||
|
# CONFIG_MTD_PHYSMAP is not set
|
||||||
|
# CONFIG_MTD_PLATRAM is not set
|
||||||
|
# CONFIG_MTD_PMC551 is not set
|
||||||
|
# CONFIG_MTD_RAM is not set
|
||||||
|
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
|
||||||
|
CONFIG_MTD_REDBOOT_PARTS=y
|
||||||
|
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
|
||||||
|
# CONFIG_MTD_ROM is not set
|
||||||
|
# CONFIG_MTD_SLRAM is not set
|
||||||
|
# CONFIG_MTD_TESTS is not set
|
||||||
|
# CONFIG_NATIONAL_PHY is not set
|
||||||
|
# CONFIG_NATSEMI is not set
|
||||||
|
# CONFIG_NET_SCH_DRR is not set
|
||||||
|
# CONFIG_NF_DEFRAG_IPV4 is not set
|
||||||
|
# CONFIG_NO_IOPORT is not set
|
||||||
|
# CONFIG_NVRAM is not set
|
||||||
|
# CONFIG_OUTER_CACHE is not set
|
||||||
|
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||||
|
CONFIG_PAGE_OFFSET=0xC0000000
|
||||||
|
CONFIG_PCI=y
|
||||||
|
# CONFIG_PCI_STUB is not set
|
||||||
|
CONFIG_PCI_SYSCALL=y
|
||||||
|
CONFIG_PHYLIB=y
|
||||||
|
# CONFIG_PHYS_ADDR_T_64BIT is not set
|
||||||
|
CONFIG_RTC_CLASS=y
|
||||||
|
CONFIG_RTC_DRV_DS1672=y
|
||||||
|
CONFIG_RTC_DRV_ISL1208=y
|
||||||
|
CONFIG_RTC_DRV_PCF8563=y
|
||||||
|
CONFIG_RTC_DRV_X1205=y
|
||||||
|
CONFIG_RTC_HCTOSYS=y
|
||||||
|
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
|
||||||
|
CONFIG_RTC_INTF_DEV=y
|
||||||
|
CONFIG_RTC_INTF_PROC=y
|
||||||
|
CONFIG_RTC_INTF_SYSFS=y
|
||||||
|
CONFIG_RTC_LIB=y
|
||||||
|
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||||
|
# CONFIG_SCSI_DMA is not set
|
||||||
|
CONFIG_SENSORS_AD7418=y
|
||||||
|
CONFIG_SENSORS_MAX6650=y
|
||||||
|
CONFIG_SENSORS_W83781D=y
|
||||||
|
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||||
|
CONFIG_SERIAL_8250_NR_UARTS=4
|
||||||
|
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
|
||||||
|
CONFIG_SPLIT_PTLOCK_CPUS=4096
|
||||||
|
CONFIG_SSB_POSSIBLE=y
|
||||||
|
CONFIG_SYSVIPC_SYSCTL=y
|
||||||
|
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||||
|
CONFIG_TICK_ONESHOT=y
|
||||||
|
CONFIG_UID16=y
|
||||||
|
CONFIG_USB_SUPPORT=y
|
||||||
|
CONFIG_VECTORS_BASE=0xffff0000
|
||||||
|
CONFIG_VM_EVENT_COUNTERS=y
|
||||||
|
CONFIG_WATCHDOG_NOWAYOUT=y
|
||||||
|
CONFIG_XSCALE_PMU=y
|
||||||
|
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||||
|
CONFIG_ZBOOT_ROM_TEXT=0x0
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/include/mach/hardware.h
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h
|
||||||
|
@@ -18,7 +18,7 @@
|
||||||
|
#define __ASM_ARCH_HARDWARE_H__
|
||||||
|
|
||||||
|
#define PCIBIOS_MIN_IO 0x00001000
|
||||||
|
-#define PCIBIOS_MIN_MEM (cpu_is_ixp43x() ? 0x40000000 : 0x48000000)
|
||||||
|
+#define PCIBIOS_MIN_MEM 0x48000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We override the standard dma-mask routines for bouncing.
|
421
target/linux/ixp4xx/patches-2.6.30/020-gateworks_i2c_pld.patch
Normal file
421
target/linux/ixp4xx/patches-2.6.30/020-gateworks_i2c_pld.patch
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/gpio/gw_i2c_pld.c
|
||||||
|
@@ -0,0 +1,371 @@
|
||||||
|
+/*
|
||||||
|
+ * 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 <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 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 = mutex_trylock(&adap->bus_lock);
|
||||||
|
+ if (!ret)
|
||||||
|
+ /* I2C activity is ongoing. */
|
||||||
|
+ return -EAGAIN;
|
||||||
|
+ } else {
|
||||||
|
+ mutex_lock_nested(&adap->bus_lock, adap->level);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ gpio->out |= (1 << offset);
|
||||||
|
+
|
||||||
|
+ ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
|
||||||
|
+
|
||||||
|
+ 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 = mutex_trylock(&adap->bus_lock);
|
||||||
|
+ if (!ret)
|
||||||
|
+ /* I2C activity is ongoing. */
|
||||||
|
+ return -EAGAIN;
|
||||||
|
+ } else {
|
||||||
|
+ mutex_lock_nested(&adap->bus_lock, adap->level);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ value = i2c_pld_read_byte(gpio->client->addr);
|
||||||
|
+
|
||||||
|
+ 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 = mutex_trylock(&adap->bus_lock);
|
||||||
|
+ if (!ret)
|
||||||
|
+ /* I2C activity is ongoing. */
|
||||||
|
+ return -EAGAIN;
|
||||||
|
+ } else {
|
||||||
|
+ mutex_lock_nested(&adap->bus_lock, adap->level);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ if (value)
|
||||||
|
+ gpio->out |= bit;
|
||||||
|
+ else
|
||||||
|
+ gpio->out &= ~bit;
|
||||||
|
+
|
||||||
|
+ ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
|
||||||
|
+
|
||||||
|
+ 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
|
||||||
|
@@ -161,6 +161,14 @@ config GPIO_BT8XX
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+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
|
||||||
|
@@ -12,3 +12,4 @@ obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
|
||||||
|
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
|
||||||
|
obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
|
||||||
|
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.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 */
|
@ -0,0 +1,15 @@
|
|||||||
|
--- a/drivers/char/random.c
|
||||||
|
+++ b/drivers/char/random.c
|
||||||
|
@@ -259,9 +259,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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The minimum number of bits of entropy before we wake up a read on
|
@ -0,0 +1,68 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
|
||||||
|
@@ -76,9 +76,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
|
||||||
|
@@ -77,9 +77,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)
|
257
target/linux/ixp4xx/patches-2.6.30/105-wg302v1_support.patch
Normal file
257
target/linux/ixp4xx/patches-2.6.30/105-wg302v1_support.patch
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
--- a/arch/arm/configs/ixp4xx_defconfig
|
||||||
|
+++ b/arch/arm/configs/ixp4xx_defconfig
|
||||||
|
@@ -155,6 +155,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
|
||||||
|
@@ -14,6 +14,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
|
||||||
|
|
||||||
|
@@ -28,6 +29,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
|
||||||
|
|
||||||
|
--- /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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init wg302v1_map_irq(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,142 @@
|
||||||
|
+/*
|
||||||
|
+ * 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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = wg302v1_init,
|
||||||
|
+MACHINE_END
|
||||||
|
+#endif
|
@ -0,0 +1,387 @@
|
|||||||
|
--- a/arch/arm/configs/ixp4xx_defconfig
|
||||||
|
+++ b/arch/arm/configs/ixp4xx_defconfig
|
||||||
|
@@ -157,6 +157,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
|
||||||
|
@@ -17,6 +17,7 @@ obj-pci-$(CONFIG_MACH_GATEWAY7001) += ga
|
||||||
|
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_PRONGHORN) += pronghorn-pci.o
|
||||||
|
|
||||||
|
obj-y += common.o
|
||||||
|
|
||||||
|
@@ -32,6 +33,7 @@ obj-$(CONFIG_MACH_GATEWAY7001) += gatewa
|
||||||
|
obj-$(CONFIG_MACH_WG302V1) += wg302v1-setup.o
|
||||||
|
obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o
|
||||||
|
obj-$(CONFIG_MACH_FSG) += fsg-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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO1, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init pronghorn_map_irq(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,245 @@
|
||||||
|
+/*
|
||||||
|
+ * 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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = pronghorn_init,
|
||||||
|
+MACHINE_END
|
||||||
|
+
|
||||||
|
+MACHINE_START(PRONGHORNMETRO, "ADI Engineering Pronghorn Metro")
|
||||||
|
+ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = pronghorn_init,
|
||||||
|
+MACHINE_END
|
||||||
|
--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h
|
||||||
|
@@ -41,7 +41,8 @@ static __inline__ void __arch_decomp_set
|
||||||
|
* Some boards are using UART2 as console
|
||||||
|
*/
|
||||||
|
if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
|
||||||
|
- machine_is_gateway7001() || machine_is_wg302v2())
|
||||||
|
+ machine_is_gateway7001() || machine_is_wg302v2() ||
|
||||||
|
+ machine_is_pronghorn() || machine_is_pronghorn_metro())
|
||||||
|
uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
|
||||||
|
else
|
||||||
|
uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
|
@ -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,
|
282
target/linux/ixp4xx/patches-2.6.30/115-sidewinder_support.patch
Normal file
282
target/linux/ixp4xx/patches-2.6.30/115-sidewinder_support.patch
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
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
|
||||||
|
@@ -163,7 +171,7 @@ config MACH_FSG
|
||||||
|
#
|
||||||
|
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
|
||||||
|
@@ -18,6 +18,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_PRONGHORN) += pronghorn-pci.o
|
||||||
|
+obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o
|
||||||
|
|
||||||
|
obj-y += common.o
|
||||||
|
|
||||||
|
@@ -34,6 +35,7 @@ obj-$(CONFIG_MACH_WG302V1) += wg302v1-se
|
||||||
|
obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o
|
||||||
|
obj-$(CONFIG_MACH_FSG) += fsg-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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init sidewinder_map_irq(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,149 @@
|
||||||
|
+/*
|
||||||
|
+ * 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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = sidewinder_init,
|
||||||
|
+MACHINE_END
|
@ -0,0 +1,30 @@
|
|||||||
|
--- a/drivers/mtd/redboot.c
|
||||||
|
+++ b/drivers/mtd/redboot.c
|
||||||
|
@@ -13,6 +13,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
|
||||||
|
@@ -30,7 +32,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)
|
||||||
|
@@ -59,6 +62,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;
|
212
target/linux/ixp4xx/patches-2.6.30/120-compex_support.patch
Normal file
212
target/linux/ixp4xx/patches-2.6.30/120-compex_support.patch
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
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
|
||||||
|
@@ -19,6 +19,7 @@ obj-pci-$(CONFIG_MACH_WG302V2) += wg302
|
||||||
|
obj-pci-$(CONFIG_MACH_FSG) += fsg-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
|
||||||
|
|
||||||
|
@@ -36,6 +37,7 @@ obj-$(CONFIG_MACH_WG302V2) += wg302v2-se
|
||||||
|
obj-$(CONFIG_MACH_FSG) += fsg-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,136 @@
|
||||||
|
+/*
|
||||||
|
+ * 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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = compex_init,
|
||||||
|
+MACHINE_END
|
||||||
|
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
|
||||||
|
@@ -66,7 +66,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
|
225
target/linux/ixp4xx/patches-2.6.30/130-wrt300nv2_support.patch
Normal file
225
target/linux/ixp4xx/patches-2.6.30/130-wrt300nv2_support.patch
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
--- 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
|
||||||
|
@@ -20,6 +20,7 @@ obj-pci-$(CONFIG_MACH_FSG) += fsg-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-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o
|
||||||
|
|
||||||
|
obj-y += common.o
|
||||||
|
|
||||||
|
@@ -38,6 +39,7 @@ obj-$(CONFIG_MACH_FSG) += fsg-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_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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init wrt300nv2_map_irq(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,108 @@
|
||||||
|
+/*
|
||||||
|
+ * 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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = wrt300nv2_init,
|
||||||
|
+MACHINE_END
|
||||||
|
+#endif
|
||||||
|
--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h
|
||||||
|
@@ -42,7 +42,7 @@ static __inline__ void __arch_decomp_set
|
||||||
|
*/
|
||||||
|
if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
|
||||||
|
machine_is_gateway7001() || machine_is_wg302v2() ||
|
||||||
|
- 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;
|
@ -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)
|
@ -0,0 +1,200 @@
|
|||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/ap1000-setup.c
|
||||||
|
@@ -0,0 +1,151 @@
|
||||||
|
+/*
|
||||||
|
+ * 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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .fixup = ap1000_fixup,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = ap1000_init,
|
||||||
|
+MACHINE_END
|
||||||
|
+#endif
|
||||||
|
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
|
||||||
|
@@ -67,7 +67,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
|
||||||
|
@@ -21,6 +21,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
|
||||||
|
|
||||||
|
@@ -40,6 +41,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
|
@ -0,0 +1,41 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/ap1000-setup.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/ap1000-setup.c
|
||||||
|
@@ -90,9 +90,37 @@ 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 ";
|
@ -0,0 +1,47 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/wg302v1-setup.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/wg302v1-setup.c
|
||||||
|
@@ -115,6 +115,36 @@ static struct platform_device *wg302v1_d
|
||||||
|
&wg302v1_eth[0],
|
||||||
|
};
|
||||||
|
|
||||||
|
+static char wg302v1_mem_fixup[] __initdata = "mem=32M ";
|
||||||
|
+
|
||||||
|
+static void __init wg302v1_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(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();
|
||||||
|
@@ -133,6 +163,7 @@ MACHINE_START(WG302V1, "Netgear WG302 v1
|
||||||
|
/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
|
||||||
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .fixup = wg302v1_fixup,
|
||||||
|
.map_io = ixp4xx_map_io,
|
||||||
|
.init_irq = ixp4xx_init_irq,
|
||||||
|
.timer = &ixp4xx_timer,
|
@ -0,0 +1,41 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
|
||||||
|
@@ -73,9 +73,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)
|
284
target/linux/ixp4xx/patches-2.6.30/180-tw5334_support.patch
Normal file
284
target/linux/ixp4xx/patches-2.6.30/180-tw5334_support.patch
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/Kconfig
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/Kconfig
|
||||||
|
@@ -158,6 +158,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
|
||||||
|
@@ -22,6 +22,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
|
||||||
|
|
||||||
|
@@ -42,6 +43,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,162 @@
|
||||||
|
+/*
|
||||||
|
+ * 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)
|
||||||
|
+{
|
||||||
|
+ DECLARE_MAC_BUF(mac_buf);
|
||||||
|
+ 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 %s for port 0\n",
|
||||||
|
+ print_mac(mac_buf, tw5334_plat_eth[0].hwaddr));
|
||||||
|
+ printk(KERN_INFO "TW-533-4: Using MAC address %s for port 1\n",
|
||||||
|
+ print_mac(mac_buf, tw5334_plat_eth[1].hwaddr));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MACH_TW5334
|
||||||
|
+MACHINE_START(TW5334, "Titan Wireless TW-533-4")
|
||||||
|
+ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = tw5334_init,
|
||||||
|
+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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO2, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO1, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO0, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init tw5334_map_irq(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
|
||||||
|
@@ -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_pronghorn() || machine_is_pronghorn_metro() || machine_is_wrt300nv2())
|
||||||
|
+ machine_is_pronghorn() || machine_is_pronghorn_metro() || machine_is_wrt300nv2() ||
|
||||||
|
+ machine_is_tw5334())
|
||||||
|
uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
|
||||||
|
else
|
||||||
|
uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
|
465
target/linux/ixp4xx/patches-2.6.30/185-mi424wr_support.patch
Normal file
465
target/linux/ixp4xx/patches-2.6.30/185-mi424wr_support.patch
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
--- /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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init mi424wr_map_irq(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,344 @@
|
||||||
|
+/*
|
||||||
|
+ * 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 */
|
||||||
|
+ .phys_io = IXP4XX_UART2_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = mi424wr_init,
|
||||||
|
+MACHINE_END
|
||||||
|
+
|
||||||
|
--- a/arch/arm/mach-ixp4xx/Makefile
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/Makefile
|
||||||
|
@@ -23,6 +23,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
|
||||||
|
|
||||||
|
@@ -44,6 +45,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
|
||||||
|
@@ -229,6 +229,13 @@ config MACH_GTWX5715
|
||||||
|
"High Speed" UART is n/c (as far as I can tell)
|
||||||
|
20 Pin ARM/Xscale JTAG interface on J2
|
||||||
|
|
||||||
|
+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
|
||||||
|
@@ -172,6 +172,7 @@ CONFIG_MACH_FSG=y
|
||||||
|
CONFIG_CPU_IXP46X=y
|
||||||
|
CONFIG_CPU_IXP43X=y
|
||||||
|
CONFIG_MACH_GTWX5715=y
|
||||||
|
+CONFIG_MACH_MI424WR=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# IXP4xx Options
|
553
target/linux/ixp4xx/patches-2.6.30/190-cambria_support.patch
Normal file
553
target/linux/ixp4xx/patches-2.6.30/190-cambria_support.patch
Normal file
@ -0,0 +1,553 @@
|
|||||||
|
--- /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)
|
||||||
|
+{
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
+
|
||||||
|
+ ixp4xx_pci_preinit();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init cambria_map_irq(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,429 @@
|
||||||
|
+/*
|
||||||
|
+ * 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;
|
||||||
|
+
|
||||||
|
+ 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 int at24_setup(struct memory_accessor *mem_acc, void *context)
|
||||||
|
+{
|
||||||
|
+ char mac_addr[ETH_ALEN];
|
||||||
|
+ char model[6];
|
||||||
|
+
|
||||||
|
+ 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);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+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> */
|
||||||
|
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
|
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
|
+ .map_io = ixp4xx_map_io,
|
||||||
|
+ .init_irq = ixp4xx_init_irq,
|
||||||
|
+ .timer = &ixp4xx_timer,
|
||||||
|
+ .boot_params = 0x0100,
|
||||||
|
+ .init_machine = cambria_init,
|
||||||
|
+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
|
||||||
|
@@ -208,7 +216,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
|
||||||
|
@@ -29,6 +30,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
|
@ -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;
|
||||||
|
+ 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;
|
||||||
|
+ 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;
|
||||||
|
+ 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;
|
||||||
|
+
|
||||||
|
+ 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
|
||||||
|
@@ -26,6 +26,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
|
||||||
|
@@ -270,6 +270,7 @@ struct uart_port {
|
||||||
|
#define UPIO_TSI (5) /* Tsi108/109 type IO */
|
||||||
|
#define UPIO_DWAPB (6) /* DesignWare APB UART */
|
||||||
|
#define UPIO_RM9000 (7) /* RM9000 type IO */
|
||||||
|
+#define UPIO_MEM_DELAY (8)
|
||||||
|
|
||||||
|
unsigned int read_status_mask; /* driver specific */
|
||||||
|
unsigned int ignore_status_mask; /* driver specific */
|
||||||
|
@@ -312,6 +313,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/serial/8250.c
|
||||||
|
+++ b/drivers/serial/8250.c
|
||||||
|
@@ -396,6 +396,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;
|
||||||
|
@@ -488,6 +502,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;
|
||||||
|
+
|
||||||
|
#ifdef CONFIG_SERIAL_8250_AU1X00
|
||||||
|
case UPIO_AU:
|
||||||
|
p->serial_in = au_serial_in;
|
||||||
|
@@ -518,6 +537,7 @@ serial_out_sync(struct uart_8250_port *u
|
||||||
|
switch (p->iotype) {
|
||||||
|
case UPIO_MEM:
|
||||||
|
case UPIO_MEM32:
|
||||||
|
+ case UPIO_MEM_DELAY:
|
||||||
|
#ifdef CONFIG_SERIAL_8250_AU1X00
|
||||||
|
case UPIO_AU:
|
||||||
|
#endif
|
||||||
|
@@ -2433,6 +2453,7 @@ static int serial8250_request_std_resour
|
||||||
|
case UPIO_MEM32:
|
||||||
|
case UPIO_MEM:
|
||||||
|
case UPIO_DWAPB:
|
||||||
|
+ case UPIO_MEM_DELAY:
|
||||||
|
if (!up->port.mapbase)
|
||||||
|
break;
|
||||||
|
|
||||||
|
@@ -2470,6 +2491,7 @@ static void serial8250_release_std_resou
|
||||||
|
case UPIO_MEM32:
|
||||||
|
case UPIO_MEM:
|
||||||
|
case UPIO_DWAPB:
|
||||||
|
+ case UPIO_MEM_DELAY:
|
||||||
|
if (!up->port.mapbase)
|
||||||
|
break;
|
||||||
|
|
||||||
|
@@ -2931,6 +2953,7 @@ static int __devinit serial8250_probe(st
|
||||||
|
port.serial_in = p->serial_in;
|
||||||
|
port.serial_out = p->serial_out;
|
||||||
|
port.dev = &dev->dev;
|
||||||
|
+ port.rw_delay = p->rw_delay;
|
||||||
|
if (share_irqs)
|
||||||
|
port.flags |= UPF_SHARE_IRQ;
|
||||||
|
ret = serial8250_register_port(&port);
|
||||||
|
@@ -3080,6 +3103,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/serial/serial_core.c
|
||||||
|
+++ b/drivers/serial/serial_core.c
|
||||||
|
@@ -2142,6 +2142,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:
|
||||||
|
@@ -2556,6 +2557,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:
|
@ -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);
|
107
target/linux/ixp4xx/patches-2.6.30/193-cambria_pld_gpio.patch
Normal file
107
target/linux/ixp4xx/patches-2.6.30/193-cambria_pld_gpio.patch
Normal file
@ -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)
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
|
||||||
|
@@ -592,6 +592,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);
|
@ -0,0 +1,20 @@
|
|||||||
|
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
|
||||||
|
@@ -95,12 +95,15 @@ 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Information about built-in HSS (synchronous serial) interfaces */
|
@ -0,0 +1,88 @@
|
|||||||
|
From cba5c286f3ea34ea4767fc00c705434a00fe2c37 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Imre Kaloz <kaloz@openwrt.org>
|
||||||
|
Date: Thu, 26 Jun 2008 01:58:02 +0200
|
||||||
|
Subject: [PATCH] Add support for the ethernet ports on IXP43x
|
||||||
|
|
||||||
|
---
|
||||||
|
arch/arm/mach-ixp4xx/ixp4xx_npe.c | 6 +++---
|
||||||
|
drivers/net/arm/ixp4xx_eth.c | 13 +++++++++----
|
||||||
|
include/asm-arm/arch-ixp4xx/cpu.h | 2 ++
|
||||||
|
include/asm-arm/arch-ixp4xx/ixp4xx-regs.h | 7 ++++---
|
||||||
|
4 files changed, 18 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
|
||||||
|
@@ -575,8 +575,8 @@ int npe_load_firmware(struct npe *npe, c
|
||||||
|
for (i = 0; i < image->size; i++)
|
||||||
|
image->data[i] = swab32(image->data[i]);
|
||||||
|
|
||||||
|
- if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) {
|
||||||
|
- print_npe(KERN_INFO, npe, "IXP46x firmware ignored on "
|
||||||
|
+ if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) {
|
||||||
|
+ print_npe(KERN_INFO, npe, "IXP46x/IXP43x firmware ignored on "
|
||||||
|
"IXP42x\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
@@ -598,7 +598,7 @@ int npe_load_firmware(struct npe *npe, c
|
||||||
|
"revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
|
||||||
|
(image->id >> 8) & 0xFF, image->id & 0xFF);
|
||||||
|
|
||||||
|
- if (!cpu_is_ixp46x()) {
|
||||||
|
+ if (cpu_is_ixp42x()) {
|
||||||
|
if (!npe->id)
|
||||||
|
instr_size = NPE_A_42X_INSTR_SIZE;
|
||||||
|
else
|
||||||
|
--- a/drivers/net/arm/ixp4xx_eth.c
|
||||||
|
+++ b/drivers/net/arm/ixp4xx_eth.c
|
||||||
|
@@ -32,6 +32,7 @@
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
+#include <mach/cpu.h>
|
||||||
|
#include <mach/npe.h>
|
||||||
|
#include <mach/qmgr.h>
|
||||||
|
|
||||||
|
@@ -337,7 +338,13 @@ static int ixp4xx_mdio_register(void)
|
||||||
|
|
||||||
|
/* All MII PHY accesses use NPE-B Ethernet registers */
|
||||||
|
spin_lock_init(&mdio_lock);
|
||||||
|
- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
|
||||||
|
+ if (!cpu_is_ixp43x())
|
||||||
|
+ /* All MII PHY accesses use NPE-B Ethernet registers */
|
||||||
|
+ mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
|
||||||
|
+ else
|
||||||
|
+ /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
|
||||||
|
+ mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
|
||||||
|
+
|
||||||
|
__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
|
||||||
|
|
||||||
|
mdio_bus->name = "IXP4xx MII Bus";
|
||||||
|
--- a/arch/arm/mach-ixp4xx/include/mach/cpu.h
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/include/mach/cpu.h
|
||||||
|
@@ -35,6 +35,8 @@ static inline u32 ixp4xx_read_feature_bi
|
||||||
|
val &= ~IXP4XX_FEATURE_RESERVED;
|
||||||
|
if (!cpu_is_ixp46x())
|
||||||
|
val &= ~IXP4XX_FEATURE_IXP46X_ONLY;
|
||||||
|
+ if (cpu_is_ixp42x())
|
||||||
|
+ val &= ~IXP4XX_FEATURE_IXP43X_46X;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
--- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
|
||||||
|
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
|
||||||
|
@@ -628,11 +628,12 @@
|
||||||
|
#define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22)
|
||||||
|
#define IXP4XX_FEATURE_RESERVED (0xFF << 24)
|
||||||
|
|
||||||
|
-#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_ECC_TIMESYNC | \
|
||||||
|
+#define IXP4XX_FEATURE_IXP43X_46X (IXP4XX_FEATURE_ECC_TIMESYNC | \
|
||||||
|
IXP4XX_FEATURE_USB_HOST | \
|
||||||
|
IXP4XX_FEATURE_NPEA_ETH | \
|
||||||
|
- IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \
|
||||||
|
- IXP4XX_FEATURE_RSA | \
|
||||||
|
IXP4XX_FEATURE_XSCALE_MAX_FREQ)
|
||||||
|
|
||||||
|
+#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \
|
||||||
|
+ IXP4XX_FEATURE_RSA)
|
||||||
|
+
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user