* Re: [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
@ 2008-06-11 10:53 Daniel Laird
2008-06-11 11:01 ` Ralf Baechle
0 siblings, 1 reply; 6+ messages in thread
From: Daniel Laird @ 2008-06-11 10:53 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Florian Fainelli, linux-mips
On the second patch I submitted I changed platform.c as requested so
it registers all resources without the #ifdefs.
I also found that cpu_relax was not quite what i wanted so left the
while(1) loop for halt.
I have left printk kernel messages in as well (can remove if preferred).
If you require me to re-submit this second patch let me know (either
as attachment or inline).
I also split the ip3902, ip0105 and submitted to the i2c, netdev
mailing list and am awaiting feedback.
Daniel Laird
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
2008-06-11 10:53 [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel Daniel Laird
@ 2008-06-11 11:01 ` Ralf Baechle
0 siblings, 0 replies; 6+ messages in thread
From: Ralf Baechle @ 2008-06-11 11:01 UTC (permalink / raw)
To: Daniel Laird; +Cc: Florian Fainelli, linux-mips
On Wed, Jun 11, 2008 at 11:53:24AM +0100, Daniel Laird wrote:
> On the second patch I submitted I changed platform.c as requested so
> it registers all resources without the #ifdefs.
> I also found that cpu_relax was not quite what i wanted so left the
> while(1) loop for halt.
>
> I have left printk kernel messages in as well (can remove if preferred).
>
> If you require me to re-submit this second patch let me know (either
> as attachment or inline).
>
> I also split the ip3902, ip0105 and submitted to the i2c, netdev
> mailing list and am awaiting feedback.
I'm replying to things in not quite chronological order, just looking at
your patch in the other window.
Ralf
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
@ 2008-06-06 8:32 Daniel Laird
2008-06-11 10:43 ` Ralf Baechle
0 siblings, 1 reply; 6+ messages in thread
From: Daniel Laird @ 2008-06-06 8:32 UTC (permalink / raw)
To: Florian Fainelli, Daniel Laird; +Cc: linux-mips
> From: florian.fainelli@telecomint.eu
> To: daniel.j.laird@nxp.com
> Subject: Re: [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
> Date: Thu, 5 Jun 2008 22:43:18 +0200
> CC: linux-mips@linux-mips.org; ralf@linux-mips.org
>
> Hello Daniel,
>
> Le Thursday 05 June 2008 21:45:13 Daniel Laird, vous avez écrit :
> > The following patch add support for the NXP PNX833x SOC. More
> > specifically it adds support for
> > the STB222/5 variant. This has I2C support, NAND and onboard ethernet
> > support.
>
> You should send the i2c parts to Jean Delvare and Ben Dooks, the I2C
> maintainers. Ethernet part should be sent to the netdev mailing-list.
>
> You can send the other pending parts to their respective maintainers, since
> your drivers will be either platform drivers, and/or they depend on
> CONFIG_NXP_STB225, they can be merged now, and get active when MIPS code is
> merged as well.
>
> I have posted some comments below in the body of your email, code looks
> overall very good.
>
> > +/***********************************************
> > +* INCLUDE FILES *
> > +************************************************/
> > +
> > +#include <asm/mach-pnx833x/pnx833x.h>
> > +#include <linux/serial_pnx8xxx.h>
>
> You might want to get rid of such comments with lines of *, and probably
> reorder the inclusion to include first linux then asm headers.
Agreed.
>
> > +#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE)
> > +static struct resource pnx833x_sata_resources[] = {
> > + [0] = {
> > + .start = PNX8335_SATA_PORTS_START,
> > + .end = PNX8335_SATA_PORTS_END,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [1] = {
> > + .start = PNX8335_PIC_SATA_INT,
> > + .end = PNX8335_PIC_SATA_INT,
> > + .flags = IORESOURCE_IRQ,
> > + },
> > +};
> > +
> > +static struct platform_device pnx833x_sata_device = {
> > + .name = "pnx833x-sata",
> > + .id = -1,
> > + .num_resources = ARRAY_SIZE(pnx833x_sata_resources),
> > + .resource = pnx833x_sata_resources,
> > +};
> > +#endif
>
> What about defining those resources anyway ?
> > +
> > +#if defined(CONFIG_MTD_NAND_PLATFORM) ||
> > defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
>
> Same here and others below too.
>
Is there any harm in having them always defined even if not
implemented? I was playing safe.
> > +
> > +#define STB225_NAND_BASE 0x18000000 /* I/O location(gets
> > remapped)*/ +#define STB225_NAND_CLE_MASK 0x00100000 /* I/O location
> > with CLE high */ +#define STB225_NAND_ALE_MASK 0x00010000 /* I/O
> > location with ALE high */ +
>
> You might want to put this in an header file instead.
Agreed will do this.
>
> > +void pnx833x_machine_halt(void)
> > +{
> > + printk(KERN_ALERT "\n\nSystem halted.\n\n");
> > +
> > + while (1)
> > + __asm__ __volatile__ ("wait");
> > +}
>
> You might want to use cpu_relax(); instead of the assembly wait instruction.
>
Sounds good.
> > +
> > +void pnx833x_machine_power_off(void)
> > +{
> > + printk(KERN_ALERT "\n\nPower off not implemented.");
> > + pnx833x_machine_halt();
> > +}
>
> And put some less alarming message here, like "*** You can safely turn off the
> board".
>
Agreed.
> > +int __init plat_mem_setup(void)
> > +{
> > + /* fake pci bus to avoid bounce buffers */
> > + PCI_DMA_BUS_IS_PHYS = 1;
> > +
> > + /* set mips clock to 320MHz */
> > +#if defined(CONFIG_SOC_PNX8335)
> > + PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ);
> > +#endif
> > + gpio_init(); /* so it will be ready in board_setup() */
>
> You can move the GPIO code into its own C file, and use arch_initcall to
> initialise it. Prefixing gpio_init with pnx83xx is better to be consistent
> with other functions. See below for more comments about the GPIO code.
>
I will prefix all gpio functions for safety. I will look into gpio
library and submit a later patch
for that. I would quite like to get this in and then optimise or I
will take to long and miss the window
again :-(
> > +static inline unsigned long ip3902_read_reg(struct net_device *ndev, int
> > reg) +{
> > + unsigned long value = readl((void * __iomem)(ndev->base_addr +
> > reg)); + return value;
>
> Useless cast to void * __iomem in general, did your compiler produced a
> warning on this ?
>
> Netdev people will probably ask you to use NAPI unconditionnaly for new
> drivers.
>
Will do.
> > +#ifdef IP3902_NAPI
> > +static int ip3902_poll(struct napi_struct *napi, int budget)
> > +{
> > + struct ip3902_private *ip3902_priv = container_of(napi, struct
> > ip3902_private, napi);
> > + struct net_device *ndev = ip3902_priv->ndev;
> > + int work_done;
> > +
> > + work_done = ip3902_eth_receive_queue(ndev, ip3902_priv, budget);
> > +
> > + if (work_done < budget) {
> > + ip3902_write_reg(ndev, INT_CLEAR_REG, RX_DONE_INT);
> > + ip3902_write_reg(ndev, INT_CLEAR_REG, 0);
> > + netif_rx_complete(ndev, napi);
> > + ip3902_write_reg(ndev, INT_ENABLE_REG, (TX_UNDERRUN_INT |
> > RX_DONE_INT | RX_OVERRUN_INT));
> > + }
> > +
> > + return work_done;
> > +}
> > +#endif
>
>
>
> > +/* BIG FAT WARNING: races danger!
> > + No protections exist here. Current users are only early init code,
> > + when locking is not needed because no cuncurency yet exists there,
> > + and GPIO IRQ dispatcher, which does locking.
> > + However, if many uses will ever happen, proper locking will be needed
> > + - including locking between different uses
>
> You should consider using the GPIO library, or read what is done for BCM47xx,
> AU1000 and TX4938. This should be easy since you comply with most of your
> functions to this GPIO API. Providing your board specific gpio functions, the
> rest of the API will handle locking and interrupt context for you.
>
> Also, prefix your functions so that they will not collide with the other
> implementations naming scheme.
>
> Such functions might be provided by the C file instead, in the archicture
> code. Remapping GPIO registers or things like that can be done there as well
> at board boot time.
> --
> Cordialement, Florian Fainelli
> ------------------------------
>
Many thanks for all comments, will do gpio library in a later patch.
Will split i2c and ip3902 off into patches to the i2c and netdev mailing lists.
Hopefully update the linux-mips patch today.
Daniel
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
2008-06-06 8:32 Daniel Laird
@ 2008-06-11 10:43 ` Ralf Baechle
0 siblings, 0 replies; 6+ messages in thread
From: Ralf Baechle @ 2008-06-11 10:43 UTC (permalink / raw)
To: Daniel Laird; +Cc: Florian Fainelli, linux-mips
On Fri, Jun 06, 2008 at 09:32:15AM +0100, Daniel Laird wrote:
> > > +#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE)
> > > +static struct resource pnx833x_sata_resources[] = {
> > > + [0] = {
> > > + .start = PNX8335_SATA_PORTS_START,
> > > + .end = PNX8335_SATA_PORTS_END,
> > > + .flags = IORESOURCE_MEM,
> > > + },
> > > + [1] = {
> > > + .start = PNX8335_PIC_SATA_INT,
> > > + .end = PNX8335_PIC_SATA_INT,
> > > + .flags = IORESOURCE_IRQ,
> > > + },
> > > +};
> > > +
> > > +static struct platform_device pnx833x_sata_device = {
> > > + .name = "pnx833x-sata",
> > > + .id = -1,
> > > + .num_resources = ARRAY_SIZE(pnx833x_sata_resources),
> > > + .resource = pnx833x_sata_resources,
> > > +};
> > > +#endif
> >
> > What about defining those resources anyway ?
> > > +
> > > +#if defined(CONFIG_MTD_NAND_PLATFORM) ||
> > > defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
> >
> > Same here and others below too.
> >
> Is there any harm in having them always defined even if not
> implemented? I was playing safe.
You normally should register all platform devices based on their presence
on the platform without consideration of the drivers actually being enabled.
The Linux driver philosophy is that a driver can be enabled, compiled as
a module and loaded separately from the kernel build and the driver should
still be working. That will only work if the driver and its resources are
always in - even at the (low!) price of being unused on a particular
platform. It also helps tools that use sysfs to query hardware
configuration.
> > > +{
> > > + printk(KERN_ALERT "\n\nSystem halted.\n\n");
> > > +
> > > + while (1)
> > > + __asm__ __volatile__ ("wait");
> > > +}
> >
> > You might want to use cpu_relax(); instead of the assembly wait instruction.
> >
> Sounds good.
Almost. cpu_relax() is defined to just barrier() on MIPS since there
isn't really very much we could or need to do in tight loop - unlike the
infamous Pentium 4 netburst architecture which burns serious amounts of
power in such a loop.
So best keep it as it is for now. The issue deserves a better solution
though but that's beyond the scope of your patch.
> > > +void pnx833x_machine_power_off(void)
> > > +{
> > > + printk(KERN_ALERT "\n\nPower off not implemented.");
> > > + pnx833x_machine_halt();
> > > +}
> >
> > And put some less alarming message here, like "*** You can safely turn off the
> > board".
No message at all. It's userspace which is supposed to communicate with the
user not the kernel.
Ralf
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
@ 2008-06-05 19:45 Daniel Laird
2008-06-05 20:43 ` Florian Fainelli
0 siblings, 1 reply; 6+ messages in thread
From: Daniel Laird @ 2008-06-05 19:45 UTC (permalink / raw)
To: linux-mips; +Cc: ralf
Tried to post earlier and did not get through, can send patch file
separately if mail server wont accept it.
Daniel Laird
------------------------------------------------------
The following patch add support for the NXP PNX833x SOC. More
specifically it adds support for
the STB222/5 variant. This has I2C support, NAND and onboard ethernet
support.
SATA, USB, NOR flash, WATCHDOG are all pending patches after I get this in :-).
arch/mips/Kconfig | 33
arch/mips/Makefile | 8
arch/mips/configs/pnx8335-stb225_defconfig | 1150 +++++++++++++++++++++
arch/mips/nxp/pnx833x/common/Makefile | 1
arch/mips/nxp/pnx833x/common/gdb_hook.c | 162 +++
arch/mips/nxp/pnx833x/common/interrupts.c | 363 ++++++
arch/mips/nxp/pnx833x/common/platform.c | 337 ++++++
arch/mips/nxp/pnx833x/common/prom.c | 69 +
arch/mips/nxp/pnx833x/common/reset.c | 48
arch/mips/nxp/pnx833x/common/setup.c | 63 +
arch/mips/nxp/pnx833x/stb22x/Makefile | 1
arch/mips/nxp/pnx833x/stb22x/board.c | 138 ++
drivers/i2c/busses/Kconfig | 12
drivers/i2c/busses/Makefile | 1
drivers/i2c/busses/i2c-pnx0105.c | 328 ++++++
drivers/net/Kconfig | 9
drivers/net/Makefile | 1
drivers/net/ip3902.c | 1534 +++++++++++++++++++++++++++++
include/asm-mips/mach-pnx833x/gpio.h | 171 +++
include/asm-mips/mach-pnx833x/irq.h | 138 ++
include/asm-mips/mach-pnx833x/pnx833x.h | 194 +++
include/asm-mips/mach-pnx833x/war.h | 25
include/linux/i2c-id.h | 1
include/linux/i2c-pnx0105.h | 58 +
24 files changed, 4845 insertions(+)
Signed-off-by: daniel.j.laird <daniel.j.laird@nxp.com>
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/configs/pnx8335-stb225_defconfig
linux-2.6.26-rc4/arch/mips/configs/pnx8335-stb225_defconfig
--- linux-2.6.26-rc4.orig/arch/mips/configs/pnx8335-stb225_defconfig
1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/configs/pnx8335-stb225_defconfig 2008-06-04
15:58:03.000000000 +0100
@@ -0,0 +1,1150 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc4
+# Wed Jun 4 15:57:17 2008
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+CONFIG_NXP_STB225=y
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_WR_PPMC is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_SOC_PNX833X=y
+CONFIG_SOC_PNX8335=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_128=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=128
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=y
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+# CONFIG_MTD_CFI_NOSWAP is not set
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 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_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x18000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_IP3902 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_ALGOPCA=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+CONFIG_I2C_PNX0105=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_DVB_CORE=y
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+# CONFIG_DVB_CX24110 is not set
+# CONFIG_DVB_CX24123 is not set
+# CONFIG_DVB_MT312 is not set
+# CONFIG_DVB_S5H1420 is not set
+# CONFIG_DVB_STV0299 is not set
+# CONFIG_DVB_TDA8083 is not set
+# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_VES1X93 is not set
+# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TDA826X is not set
+# CONFIG_DVB_TUA6100 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+# CONFIG_DVB_SP8870 is not set
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_CX22700 is not set
+# CONFIG_DVB_CX22702 is not set
+# CONFIG_DVB_L64781 is not set
+CONFIG_DVB_TDA1004X=y
+# CONFIG_DVB_NXT6000 is not set
+# CONFIG_DVB_MT352 is not set
+# CONFIG_DVB_ZL10353 is not set
+# CONFIG_DVB_DIB3000MB is not set
+# CONFIG_DVB_DIB3000MC is not set
+# CONFIG_DVB_DIB7000M is not set
+# CONFIG_DVB_DIB7000P is not set
+# CONFIG_DVB_TDA10048 is not set
+
+#
+# DVB-C (cable) frontends
+#
+# CONFIG_DVB_VES1820 is not set
+# CONFIG_DVB_TDA10021 is not set
+# CONFIG_DVB_TDA10023 is not set
+# CONFIG_DVB_STV0297 is not set
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_S5H1409 is not set
+# CONFIG_DVB_AU8522 is not set
+# CONFIG_DVB_S5H1411 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+# CONFIG_DVB_PLL is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
+
+#
+# SEC control devices for DVB-S
+#
+# CONFIG_DVB_LNBP21 is not set
+# CONFIG_DVB_ISL6405 is not set
+# CONFIG_DVB_ISL6421 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_DETECT=y
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
+# SoC Audio for the Texas Instruments OMAP
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SAMPLES is not set
+CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/Kconfig
linux-2.6.26-rc4/arch/mips/Kconfig
--- linux-2.6.26-rc4.orig/arch/mips/Kconfig 2008-06-03
10:56:51.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/Kconfig 2008-06-03 17:12:19.000000000 +0100
@@ -311,6 +311,19 @@
select SYS_HAS_CPU_VR41XX
select GENERIC_HARDIRQS_NO__DO_IRQ
+config NXP_STB220
+ bool "NXP STB220 board"
+ select SOC_PNX833X
+ help
+ Support for NXP Semiconductors STB220 Development Board.
+
+config NXP_STB225
+ bool "NXP 225 board"
+ select SOC_PNX833X
+ select SOC_PNX8335
+ help
+ Support for NXP Semiconductors STB225 Development Board.
+
config PNX8550_JBS
bool "NXP PNX8550 based JBS board"
select PNX8550
@@ -947,6 +960,26 @@
bool
select SERIAL_RM9000
+config SOC_PNX833X
+ bool
+ select CEVT_R4K
+ select CSRC_R4K
+ select IRQ_CPU
+ select DMA_NONCOHERENT
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+ select SYS_SUPPORTS_KGDB
+ select GENERIC_GPIO
+ select CPU_MIPSR2_IRQ_VI
+
+config SOC_PNX8335
+ bool
+ select SOC_PNX833X
+
config PNX8550
bool
select SOC_PNX8550
diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/Makefile
linux-2.6.26-rc4/arch/mips/Makefile
--- linux-2.6.26-rc4.orig/arch/mips/Makefile 2008-06-03
10:56:51.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/Makefile 2008-06-03 17:13:03.000000000 +0100
@@ -409,6 +409,14 @@
#
load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000
+# NXP STB225
+core-$(CONFIG_SOC_PNX833X) += arch/mips/nxp/pnx833x/common/
+cflags-$(CONFIG_SOC_PNX833X) += -Iinclude/asm-mips/mach-pnx833x
+libs-$(CONFIG_NXP_STB220) += arch/mips/nxp/pnx833x/stb22x/
+load-$(CONFIG_NXP_STB220) += 0xffffffff80001000
+libs-$(CONFIG_NXP_STB225) += arch/mips/nxp/pnx833x/stb22x/
+load-$(CONFIG_NXP_STB225) += 0xffffffff80001000
+
#
# Common NXP PNX8550
#
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/gdb_hook.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/gdb_hook.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/gdb_hook.c
1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/gdb_hook.c 2008-06-05
11:16:42.000000000 +0100
@@ -0,0 +1,162 @@
+/*
+ * gdb_hook.c: gdb hook for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on PNX8550.
+ *
+ * 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 FILES *
+************************************************/
+
+#include <asm/mach-pnx833x/pnx833x.h>
+#include <linux/serial_pnx8xxx.h>
+
+/***********************************************
+* LOCAL MACROS *
+************************************************/
+
+#define UART0 (unsigned char *)PNX833X_UART0_PORTS_START
+#define UART1 (unsigned char *)PNX833X_UART1_PORTS_START
+
+/***********************************************
+* LOCAL TYPEDEFS *
+************************************************/
+
+/***********************************************
+* STATIC FUNCTION PROTOTYPES *
+************************************************/
+
+/***********************************************
+* STATIC DATA *
+************************************************/
+
+static unsigned char *kgdb_uart = UART1;
+static unsigned char *console_uart = UART0;
+static volatile int delay_count;
+
+/***********************************************
+* EXPORTED DATA *
+************************************************/
+
+/***********************************************
+* FUNCTION IMPLEMENTATION *
+************************************************/
+
+static unsigned int serial_in(unsigned char *base_address, int offset)
+{
+ return *((unsigned int volatile *)(base_address + offset));
+}
+
+static void serial_out(unsigned char *base_address, int offset, int value)
+{
+ *((unsigned int volatile *)(base_address + offset)) = value;
+}
+
+static void do_delay(void)
+{
+ int i;
+ for (i = 0; i < 10000; i++)
+ delay_count++;
+}
+
+static int put_char(unsigned char *base_address, char c)
+{
+ /* Wait for TX to be ready */
+ while (((serial_in(base_address, PNX8XXX_FIFO) &
PNX8XXX_UART_FIFO_TXFIFO) >> 16) > 15)
+ do_delay();
+
+ /* Send the next character */
+ serial_out(base_address, PNX8XXX_FIFO, c);
+ serial_out(base_address, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX);
+
+ return 1;
+}
+
+static char get_char(unsigned char *base_address)
+{
+ char output;
+
+ /* Wait for RX to be ready */
+ while ((serial_in(base_address, PNX8XXX_FIFO) &
PNX8XXX_UART_FIFO_RXFIFO) == 0)
+ do_delay();
+
+ /* Get the character */
+ output = serial_in(base_address, PNX8XXX_FIFO) & 0xFF;
+
+ /* Move onto the next character in the buffer */
+ serial_out(base_address, PNX8XXX_LCR, serial_in(base_address,
PNX8XXX_LCR) | PNX8XXX_UART_LCR_RX_NEXT);
+ serial_out(base_address, PNX8XXX_ICLR, PNX8XXX_UART_INT_RX);
+
+ return output;
+}
+
+static void serial_init(unsigned char *base_address)
+{
+ serial_out(base_address, PNX8XXX_LCR, PNX8XXX_UART_LCR_8BIT |
PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST);
+ serial_out(base_address, PNX8XXX_MCR, PNX8XXX_UART_MCR_DTR |
PNX8XXX_UART_MCR_RTS);
+ serial_out(base_address, PNX8XXX_BAUD, 1); /* 115200 Baud */
+ serial_out(base_address, PNX8XXX_CFG, 0x00060030);
+ serial_out(base_address, PNX8XXX_ICLR, -1);
+ serial_out(base_address, PNX8XXX_IEN, 0);
+}
+
+static void setup_serial_output(void)
+{
+ static bool initialised;
+ if (!initialised) {
+ serial_init(kgdb_uart);
+ serial_init(console_uart);
+ initialised = true;
+ }
+}
+
+int rs_kgdb_hook(int tty_no, int speed)
+{
+ kgdb_uart = tty_no ? UART1 : UART0;
+ console_uart = tty_no ? UART0 : UART1;
+
+ setup_serial_output();
+
+ return speed;
+}
+
+int prom_putchar(char c)
+{
+ setup_serial_output();
+ return put_char(console_uart, c);
+}
+
+char prom_getchar(void)
+{
+ setup_serial_output();
+ return get_char(console_uart);
+}
+
+int put_debug_char(char c)
+{
+ setup_serial_output();
+ return put_char(kgdb_uart, c);
+}
+
+char get_debug_char(void)
+{
+ setup_serial_output();
+ return get_char(kgdb_uart);
+}
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/interrupts.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/interrupts.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/interrupts.c
1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/interrupts.c 2008-06-05
11:44:06.000000000 +0100
@@ -0,0 +1,363 @@
+/*
+ * interrupts.c: Interrupt mappings for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * 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/irq.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <asm/mipsregs.h>
+#include <asm/irq_cpu.h>
+#include <irq.h>
+#include <gpio.h>
+
+static const unsigned int irq_prio[PNX833X_PIC_NUM_IRQ] =
+{
+ 0, /* unused */
+ 4, /* PNX833X_PIC_I2C0_INT 1 */
+ 4, /* PNX833X_PIC_I2C1_INT 2 */
+ 1, /* PNX833X_PIC_UART0_INT 3 */
+ 1, /* PNX833X_PIC_UART1_INT 4 */
+ 6, /* PNX833X_PIC_TS_IN0_DV_INT 5 */
+ 6, /* PNX833X_PIC_TS_IN0_DMA_INT 6 */
+ 7, /* PNX833X_PIC_GPIO_INT 7 */
+ 4, /* PNX833X_PIC_AUDIO_DEC_INT 8 */
+ 5, /* PNX833X_PIC_VIDEO_DEC_INT 9 */
+ 4, /* PNX833X_PIC_CONFIG_INT 10 */
+ 4, /* PNX833X_PIC_AOI_INT 11 */
+ 9, /* PNX833X_PIC_SYNC_INT 12 */
+ 9, /* PNX8335_PIC_SATA_INT 13 */
+ 4, /* PNX833X_PIC_OSD_INT 14 */
+ 9, /* PNX833X_PIC_DISP1_INT 15 */
+ 4, /* PNX833X_PIC_DEINTERLACER_INT 16 */
+ 9, /* PNX833X_PIC_DISPLAY2_INT 17 */
+ 4, /* PNX833X_PIC_VC_INT 18 */
+ 4, /* PNX833X_PIC_SC_INT 19 */
+ 9, /* PNX833X_PIC_IDE_INT 20 */
+ 9, /* PNX833X_PIC_IDE_DMA_INT 21 */
+ 6, /* PNX833X_PIC_TS_IN1_DV_INT 22 */
+ 6, /* PNX833X_PIC_TS_IN1_DMA_INT 23 */
+ 4, /* PNX833X_PIC_SGDX_DMA_INT 24 */
+ 4, /* PNX833X_PIC_TS_OUT_INT 25 */
+ 4, /* PNX833X_PIC_IR_INT 26 */
+ 3, /* PNX833X_PIC_VMSP1_INT 27 */
+ 3, /* PNX833X_PIC_VMSP2_INT 28 */
+ 4, /* PNX833X_PIC_PIBC_INT 29 */
+ 4, /* PNX833X_PIC_TS_IN0_TRD_INT 30 */
+ 4, /* PNX833X_PIC_SGDX_TPD_INT 31 */
+ 5, /* PNX833X_PIC_USB_INT 32 */
+ 4, /* PNX833X_PIC_TS_IN1_TRD_INT 33 */
+ 4, /* PNX833X_PIC_CLOCK_INT 34 */
+ 4, /* PNX833X_PIC_SGDX_PARSER_INT 35 */
+ 4, /* PNX833X_PIC_VMSP_DMA_INT 36 */
+#if defined(CONFIG_SOC_PNX8335)
+ 4, /* PNX8335_PIC_MIU_INT 37 */
+ 4, /* PNX8335_PIC_AVCHIP_IRQ_INT 38 */
+ 9, /* PNX8335_PIC_SYNC_HD_INT 39 */
+ 9, /* PNX8335_PIC_DISP_HD_INT 40 */
+ 9, /* PNX8335_PIC_DISP_SCALER_INT 41 */
+ 4, /* PNX8335_PIC_OSD_HD1_INT 42 */
+ 4, /* PNX8335_PIC_DTL_WRITER_Y_INT 43 */
+ 4, /* PNX8335_PIC_DTL_WRITER_C_INT 44 */
+ 4, /* PNX8335_PIC_DTL_EMULATOR_Y_IR_INT 45 */
+ 4, /* PNX8335_PIC_DTL_EMULATOR_C_IR_INT 46 */
+ 4, /* PNX8335_PIC_DENC_TTX_INT 47 */
+ 4, /* PNX8335_PIC_MMI_SIF0_INT 48 */
+ 4, /* PNX8335_PIC_MMI_SIF1_INT 49 */
+ 4, /* PNX8335_PIC_MMI_CDMMU_INT 50 */
+ 4, /* PNX8335_PIC_PIBCS_INT 51 */
+ 12, /* PNX8335_PIC_ETHERNET_INT 52 */
+ 3, /* PNX8335_PIC_VMSP1_0_INT 53 */
+ 3, /* PNX8335_PIC_VMSP1_1_INT 54 */
+ 4, /* PNX8335_PIC_VMSP1_DMA_INT 55 */
+ 4, /* PNX8335_PIC_TDGR_DE_INT 56 */
+ 4, /* PNX8335_PIC_IR1_IRQ_INT 57 */
+#endif
+};
+
+static void pic_dispatch(void)
+{
+ unsigned int irq = PNX833X_REGFIELD(PIC_INT_SRC, INT_SRC);
+
+ if ((irq >= 1) && (irq < (PNX833X_PIC_NUM_IRQ))) {
+ unsigned long priority = PNX833X_PIC_INT_PRIORITY;
+ PNX833X_PIC_INT_PRIORITY = irq_prio[irq];
+
+ if (irq == PNX833X_PIC_GPIO_INT) {
+ unsigned long mask = PNX833X_PIO_INT_STATUS &
PNX833X_PIO_INT_ENABLE;
+ int pin;
+ while ((pin = ffs(mask & 0xffff))) {
+ pin -= 1;
+ do_IRQ(PNX833X_GPIO_IRQ_BASE + pin);
+ mask &= ~(1 << pin);
+ }
+ } else {
+ do_IRQ(irq + PNX833X_PIC_IRQ_BASE);
+ }
+
+ PNX833X_PIC_INT_PRIORITY = priority;
+ } else {
+ printk(KERN_ERR "plat_irq_dispatch: unexpected irq %u\n", irq);
+ }
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP4)
+ pic_dispatch();
+ else if (pending & STATUSF_IP7)
+ do_IRQ(PNX833X_TIMER_IRQ);
+ else
+ spurious_interrupt();
+}
+
+static inline void pnx833x_hard_enable_pic_irq(unsigned int irq)
+{
+ /* Currently we do this by setting IRQ priority to 1.
+ If priority support is being implemented, 1 should be repalced
+ by a better value. */
+ PNX833X_PIC_INT_REG(irq) = irq_prio[irq];
+}
+
+static inline void pnx833x_hard_disable_pic_irq(unsigned int irq)
+{
+ /* Disable IRQ by writing setting it's priority to 0 */
+ PNX833X_PIC_INT_REG(irq) = 0;
+}
+
+static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */
+#define IRQFLAG_STARTED 1
+#define IRQFLAG_DISABLED 2
+
+static DEFINE_SPINLOCK(irq_lock);
+
+static unsigned int pnx833x_startup_pic_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
+
+ spin_lock_irqsave(&irq_lock, flags);
+
+ irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */
+ pnx833x_hard_enable_pic_irq(pic_irq);
+
+ spin_unlock_irqrestore(&irq_lock, flags);
+ return 0;
+}
+
+static void pnx833x_shutdown_pic_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
+
+ spin_lock_irqsave(&irq_lock, flags);
+
+ irqflags[pic_irq] = 0; /* not started */
+ pnx833x_hard_disable_pic_irq(pic_irq);
+
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static void pnx833x_enable_pic_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
+
+ spin_lock_irqsave(&irq_lock, flags);
+
+ irqflags[pic_irq] &= ~IRQFLAG_DISABLED;
+ if (irqflags[pic_irq] == IRQFLAG_STARTED)
+ pnx833x_hard_enable_pic_irq(pic_irq);
+
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static void pnx833x_disable_pic_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
+
+ spin_lock_irqsave(&irq_lock, flags);
+
+ irqflags[pic_irq] |= IRQFLAG_DISABLED;
+ pnx833x_hard_disable_pic_irq(pic_irq);
+
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static void pnx833x_ack_pic_irq(unsigned int irq)
+{
+}
+
+static void pnx833x_end_pic_irq(unsigned int irq)
+{
+}
+
+static DEFINE_SPINLOCK(gpio_irq_lock);
+
+static unsigned int pnx833x_startup_gpio_irq(unsigned int irq)
+{
+ int pin = irq - PNX833X_GPIO_IRQ_BASE;
+ unsigned long flags;
+ spin_lock_irqsave(&gpio_irq_lock, flags);
+ gpio_enable_irq(pin);
+ spin_unlock_irqrestore(&gpio_irq_lock, flags);
+ return 0;
+}
+
+static void pnx833x_enable_gpio_irq(unsigned int irq)
+{
+ int pin = irq - PNX833X_GPIO_IRQ_BASE;
+ unsigned long flags;
+ spin_lock_irqsave(&gpio_irq_lock, flags);
+ gpio_enable_irq(pin);
+ spin_unlock_irqrestore(&gpio_irq_lock, flags);
+}
+
+static void pnx833x_disable_gpio_irq(unsigned int irq)
+{
+ int pin = irq - PNX833X_GPIO_IRQ_BASE;
+ unsigned long flags;
+ spin_lock_irqsave(&gpio_irq_lock, flags);
+ gpio_disable_irq(pin);
+ spin_unlock_irqrestore(&gpio_irq_lock, flags);
+}
+
+static void pnx833x_ack_gpio_irq(unsigned int irq)
+{
+}
+
+static void pnx833x_end_gpio_irq(unsigned int irq)
+{
+ int pin = irq - PNX833X_GPIO_IRQ_BASE;
+ unsigned long flags;
+ spin_lock_irqsave(&gpio_irq_lock, flags);
+ gpio_clear_irq(pin);
+ spin_unlock_irqrestore(&gpio_irq_lock, flags);
+}
+
+static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type)
+{
+ int pin = irq - PNX833X_GPIO_IRQ_BASE;
+ int gpio_mode;
+
+ switch (flow_type) {
+ case IRQ_TYPE_EDGE_RISING:
+ gpio_mode = GPIO_INT_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ gpio_mode = GPIO_INT_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ gpio_mode = GPIO_INT_EDGE_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ gpio_mode = GPIO_INT_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ gpio_mode = GPIO_INT_LEVEL_LOW;
+ break;
+ default:
+ gpio_mode = GPIO_INT_NONE;
+ break;
+ }
+
+ gpio_setup_irq(gpio_mode, pin);
+
+ return 0;
+}
+
+static struct irq_chip pnx833x_pic_irq_type = {
+ .typename = "PNX-PIC",
+ .startup = pnx833x_startup_pic_irq,
+ .shutdown = pnx833x_shutdown_pic_irq,
+ .enable = pnx833x_enable_pic_irq,
+ .disable = pnx833x_disable_pic_irq,
+ .ack = pnx833x_ack_pic_irq,
+ .end = pnx833x_end_pic_irq
+};
+
+static struct irq_chip pnx833x_gpio_irq_type = {
+ .typename = "PNX-GPIO",
+ .startup = pnx833x_startup_gpio_irq,
+ .shutdown = pnx833x_disable_gpio_irq,
+ .enable = pnx833x_enable_gpio_irq,
+ .disable = pnx833x_disable_gpio_irq,
+ .ack = pnx833x_ack_gpio_irq,
+ .end = pnx833x_end_gpio_irq,
+ .set_type = pnx833x_set_type_gpio_irq
+};
+
+void __init arch_init_irq(void)
+{
+ unsigned int irq;
+
+ /* setup standard internal cpu irqs */
+ mips_cpu_irq_init();
+
+ /* Set IRQ information in irq_desc */
+ for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE +
PNX833X_PIC_NUM_IRQ); irq++) {
+ pnx833x_hard_disable_pic_irq(irq);
+ set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type,
handle_simple_irq);
+ }
+
+ for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE +
PNX833X_GPIO_NUM_IRQ); irq++)
+ set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type,
handle_simple_irq);
+
+ /* Set PIC priority limiter register to 0 */
+ PNX833X_PIC_INT_PRIORITY = 0;
+
+ /* Setup GPIO IRQ dispatching */
+ pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT);
+
+ /* Enable PIC IRQs (HWIRQ2) */
+ if (cpu_has_vint)
+ set_vi_handler(4, pic_dispatch);
+
+ write_c0_status(read_c0_status() | IE_IRQ2);
+}
+
+
+void __init plat_time_init(void)
+{
+ /* calculate mips_hpt_frequency based on PNX833X_CLOCK_CPUCP_CTL reg */
+
+ extern unsigned long mips_hpt_frequency;
+ unsigned long reg = PNX833X_CLOCK_CPUCP_CTL;
+
+ if (!(PNX833X_BIT(reg, CLOCK_CPUCP_CTL, EXIT_RESET))) {
+ /* Functional clock is disabled so use crystal frequency */
+ mips_hpt_frequency = 25;
+ } else {
+#if defined(CONFIG_SOC_PNX8335)
+ /* Functional clock is enabled, so get clock multiplier */
+ mips_hpt_frequency = 90 + (10 *
PNX8335_REGFIELD(CLOCK_PLL_CPU_CTL, FREQ));
+#else
+ static const unsigned long int freq[4] = {240, 160, 120, 80};
+ mips_hpt_frequency = freq[PNX833X_FIELD(reg,
CLOCK_CPUCP_CTL, DIV_CLOCK)];
+#endif
+ }
+
+ printk(KERN_INFO "CPU clock is %ld MHz\n", mips_hpt_frequency);
+
+ mips_hpt_frequency *= 500000;
+}
+
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/Makefile
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/Makefile
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/Makefile 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/Makefile 2008-03-03
13:09:30.000000000 +0000
@@ -0,0 +1 @@
+obj-y := interrupts.o platform.o prom.o setup.o reset.o gdb_hook.o
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/platform.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/platform.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/platform.c
1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/platform.c 2008-06-05
11:09:06.000000000 +0100
@@ -0,0 +1,337 @@
+/*
+ * platform.c: platform support for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on software written by:
+ * Nikita Youshchenko <yoush@debian.org>, based on PNX8550 code.
+ *
+ * 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/device.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+#include <linux/serial.h>
+#include <linux/serial_pnx8xxx.h>
+#include <linux/i2c-pnx0105.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <irq.h>
+#include <pnx833x.h>
+
+#if defined(CONFIG_SERIAL_PNX8XXX) || defined(CONFIG_SERIAL_PNX8XXX_MODULE)
+static u64 uart_dmamask = ~(u32)0;
+
+static struct resource pnx833x_uart_resources[] = {
+ [0] = {
+ .start = PNX833X_UART0_PORTS_START,
+ .end = PNX833X_UART0_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PNX833X_PIC_UART0_INT,
+ .end = PNX833X_PIC_UART0_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = PNX833X_UART1_PORTS_START,
+ .end = PNX833X_UART1_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ .start = PNX833X_PIC_UART1_INT,
+ .end = PNX833X_PIC_UART1_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct pnx8xxx_port pnx8xxx_ports[] = {
+ [0] = {
+ .port = {
+ .type = PORT_PNX8XXX,
+ .iotype = UPIO_MEM,
+ .membase = (void __iomem
*)PNX833X_UART0_PORTS_START,
+ .mapbase = PNX833X_UART0_PORTS_START,
+ .irq = PNX833X_PIC_UART0_INT,
+ .uartclk = 3692300,
+ .fifosize = 16,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ },
+ [1] = {
+ .port = {
+ .type = PORT_PNX8XXX,
+ .iotype = UPIO_MEM,
+ .membase = (void __iomem
*)PNX833X_UART1_PORTS_START,
+ .mapbase = PNX833X_UART1_PORTS_START,
+ .irq = PNX833X_PIC_UART1_INT,
+ .uartclk = 3692300,
+ .fifosize = 16,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 1,
+ },
+ },
+};
+
+static struct platform_device pnx833x_uart_device = {
+ .name = "pnx8xxx-uart",
+ .id = -1,
+ .dev = {
+ .dma_mask = &uart_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = pnx8xxx_ports,
+ },
+ .num_resources = ARRAY_SIZE(pnx833x_uart_resources),
+ .resource = pnx833x_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+static u64 ehci_dmamask = ~(u32)0;
+
+static struct resource pnx833x_usb_ehci_resources[] = {
+ [0] = {
+ .start = PNX833X_USB_PORTS_START,
+ .end = PNX833X_USB_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PNX833X_PIC_USB_INT,
+ .end = PNX833X_PIC_USB_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pnx833x_usb_ehci_device = {
+ .name = "pnx833x-ehci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ehci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(pnx833x_usb_ehci_resources),
+ .resource = pnx833x_usb_ehci_resources,
+};
+#endif
+
+#if defined(CONFIG_I2C_PNX0105) || defined(CONFIG_I2C_PNX0105_MODULE)
+static struct resource pnx833x_i2c0_resources[] = {
+ {
+ .start = PNX833X_I2C0_PORTS_START,
+ .end = PNX833X_I2C0_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PNX833X_PIC_I2C0_INT,
+ .end = PNX833X_PIC_I2C0_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource pnx833x_i2c1_resources[] = {
+ {
+ .start = PNX833X_I2C1_PORTS_START,
+ .end = PNX833X_I2C1_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PNX833X_PIC_I2C1_INT,
+ .end = PNX833X_PIC_I2C1_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = {
+ {
+ .base = PNX833X_I2C0_PORTS_START,
+ .irq = -1, /* should be PNX833X_PIC_I2C0_INT but
polling is faster */
+ .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 =
50kHz(Prefered HDCP) */
+ .bus_addr = 0, /* no slave support */
+ },
+ {
+ .base = PNX833X_I2C1_PORTS_START,
+ .irq = -1, /* on high freq, polling is faster */
+ /*.irq = PNX833X_PIC_I2C1_INT,*/
+ .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz
seems a safe
default for now */
+ .bus_addr = 0, /* no slave support */
+ },
+};
+
+static struct platform_device pnx833x_i2c0_device = {
+ .name = "i2c-pnx0105",
+ .id = 0,
+ .dev = {
+ .platform_data = &pnx833x_i2c_dev[0],
+ },
+ .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources),
+ .resource = pnx833x_i2c0_resources,
+};
+
+static struct platform_device pnx833x_i2c1_device = {
+ .name = "i2c-pnx0105",
+ .id = 1,
+ .dev = {
+ .platform_data = &pnx833x_i2c_dev[1],
+ },
+ .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources),
+ .resource = pnx833x_i2c1_resources,
+};
+#endif
+
+#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE)
+static u64 ethernet_dmamask = ~(u32)0;
+
+static struct resource pnx833x_ethernet_resources[] = {
+ [0] = {
+ .start = PNX8335_IP3902_PORTS_START,
+ .end = PNX8335_IP3902_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PNX8335_PIC_ETHERNET_INT,
+ .end = PNX8335_PIC_ETHERNET_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pnx833x_ethernet_device = {
+ .name = "ip3902-eth",
+ .id = -1,
+ .dev = {
+ .dma_mask = ðernet_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(pnx833x_ethernet_resources),
+ .resource = pnx833x_ethernet_resources,
+};
+#endif
+
+#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE)
+static struct resource pnx833x_sata_resources[] = {
+ [0] = {
+ .start = PNX8335_SATA_PORTS_START,
+ .end = PNX8335_SATA_PORTS_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PNX8335_PIC_SATA_INT,
+ .end = PNX8335_PIC_SATA_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pnx833x_sata_device = {
+ .name = "pnx833x-sata",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pnx833x_sata_resources),
+ .resource = pnx833x_sata_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_PLATFORM) ||
defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#define STB225_NAND_BASE 0x18000000 /* I/O location(gets remapped)*/
+#define STB225_NAND_CLE_MASK 0x00100000 /* I/O location with CLE high */
+#define STB225_NAND_ALE_MASK 0x00010000 /* I/O location with ALE high */
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", 0 };
+#endif
+
+static void
+pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (ctrl & NAND_CLE)
+ writeb(cmd, (void __iomem *)(nandaddr + STB225_NAND_CLE_MASK));
+ else
+ writeb(cmd, (void __iomem *) (nandaddr + STB225_NAND_ALE_MASK));
+}
+
+static struct platform_nand_data pnx833x_flash_nand_data = {
+ .chip = {
+ .chip_delay = 25,
+#ifdef CONFIG_MTD_PARTITIONS
+ .part_probe_types = part_probes,
+#endif
+ },
+ .ctrl = {
+ .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl
+ }
+};
+
+/* Set start to be the correct address (STB225_NAND_BASE with no 0xb!!),
+ 12 bytes more seems to be the standard that allows for NAND access.*/
+static struct resource pnx833x_flash_nand_resource = {
+ .start = STB225_NAND_BASE,
+ .end = STB225_NAND_BASE + 12,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device pnx833x_flash_nand = {
+ .name = "gen_nand",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &pnx833x_flash_nand_resource,
+ .dev = {
+ .platform_data = &pnx833x_flash_nand_data,
+ },
+};
+#endif /* CONFIG_MTD_NAND_PLATFORM */
+
+static struct platform_device *pnx833x_platform_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_PNX8XXX) || defined(CONFIG_SERIAL_PNX8XXX_MODULE)
+ &pnx833x_uart_device,
+#endif
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+ &pnx833x_usb_ehci_device,
+#endif
+#if defined(CONFIG_I2C_PNX0105) || defined(CONFIG_I2C_PNX0105_MODULE)
+ &pnx833x_i2c0_device,
+ &pnx833x_i2c1_device,
+#endif
+#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE)
+ &pnx833x_ethernet_device,
+#endif
+#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE)
+ &pnx833x_sata_device,
+#endif
+#if defined(CONFIG_MTD_NAND_PLATFORM) ||
defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+ &pnx833x_flash_nand,
+#endif
+};
+
+int __init pnx833x_platform_init(void)
+{
+ int res;
+
+ if (ARRAY_SIZE(pnx833x_platform_devices)) {
+ res = platform_add_devices(pnx833x_platform_devices,
+ ARRAY_SIZE(pnx833x_platform_devices));
+ }
+ return res;
+}
+
+arch_initcall(pnx833x_platform_init);
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/prom.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/prom.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/prom.c 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/prom.c 2008-06-05
09:26:59.000000000 +0100
@@ -0,0 +1,69 @@
+/*
+ * prom.c:
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on software written by:
+ * Nikita Youshchenko <yoush@debian.org>, based on PNX8550 code.
+ *
+ * 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/init.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+
+void __init prom_init_cmdline(void)
+{
+ int argc = fw_arg0;
+ char **argv = (char **)fw_arg1;
+ char *c = &(arcs_cmdline[0]);
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ strcpy(c, argv[i]);
+ c += strlen(argv[i]);
+ if (i < argc-1)
+ *c++ = ' ';
+ }
+ *c = 0;
+}
+
+char __init *prom_getenv(char *envname)
+{
+ extern char **prom_envp;
+ char **env = prom_envp;
+ int i;
+
+ i = strlen(envname);
+
+ while (*env) {
+ if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=')
+ return *env + i + 1;
+ env++;
+ }
+
+ return 0;
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+char * __init prom_getcmdline(void)
+{
+ return arcs_cmdline;
+}
+
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/reset.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/reset.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/reset.c 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/reset.c 2008-06-05
11:27:00.000000000 +0100
@@ -0,0 +1,48 @@
+/*
+ * reset.c: reset support for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on software written by:
+ * Nikita Youshchenko <yoush@debian.org>, based on PNX8550 code.
+ *
+ * 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/slab.h>
+#include <linux/reboot.h>
+#include <pnx833x.h>
+
+void pnx833x_machine_restart(char *command)
+{
+ printk(KERN_ALERT "\n\nRestarting ...\n\n");
+
+ PNX833X_RESET_CONTROL_2 = 0;
+ PNX833X_RESET_CONTROL = 0;
+}
+
+void pnx833x_machine_halt(void)
+{
+ printk(KERN_ALERT "\n\nSystem halted.\n\n");
+
+ while (1)
+ __asm__ __volatile__ ("wait");
+}
+
+void pnx833x_machine_power_off(void)
+{
+ printk(KERN_ALERT "\n\nPower off not implemented.");
+ pnx833x_machine_halt();
+}
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/setup.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/setup.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/setup.c 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/setup.c 2008-06-05
11:46:31.000000000 +0100
@@ -0,0 +1,63 @@
+/*
+ * setup.c: Setup PNX833X Soc.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on software written by:
+ * Nikita Youshchenko <yoush@debian.org>, based on PNX8550 code.
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <asm/reboot.h>
+#include <pnx833x.h>
+#include <gpio.h>
+
+extern void pnx833x_board_setup(void);
+extern void pnx833x_machine_restart(char *);
+extern void pnx833x_machine_halt(void);
+extern void pnx833x_machine_power_off(void);
+
+int __init plat_mem_setup(void)
+{
+ /* fake pci bus to avoid bounce buffers */
+ PCI_DMA_BUS_IS_PHYS = 1;
+
+ /* set mips clock to 320MHz */
+#if defined(CONFIG_SOC_PNX8335)
+ PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ);
+#endif
+ gpio_init(); /* so it will be ready in board_setup() */
+
+ pnx833x_board_setup();
+
+ _machine_restart = pnx833x_machine_restart;
+ _machine_halt = pnx833x_machine_halt;
+ pm_power_off = pnx833x_machine_power_off;
+
+ /* IO/MEM resources. */
+ set_io_port_base(KSEG1);
+ ioport_resource.start = 0;
+ ioport_resource.end = ~0;
+ iomem_resource.start = 0;
+ iomem_resource.end = ~0;
+
+ return 0;
+}
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/board.c
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/board.c
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/board.c 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/board.c 2008-06-05
11:17:10.000000000 +0100
@@ -0,0 +1,138 @@
+/*
+ * board.c: STB225 board support.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on software written by:
+ * Nikita Youshchenko <yoush@debian.org>, based on PNX8550 code.
+ *
+ * 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/init.h>
+#include <asm/bootinfo.h>
+#include <linux/mm.h>
+#include <pnx833x.h>
+#include <gpio.h>
+
+/* endianess twiddlers */
+#define PNX8335_DEBUG0 0x4400
+#define PNX8335_DEBUG1 0x4404
+#define PNX8335_DEBUG2 0x4408
+#define PNX8335_DEBUG3 0x440c
+#define PNX8335_DEBUG4 0x4410
+#define PNX8335_DEBUG5 0x4414
+#define PNX8335_DEBUG6 0x4418
+#define PNX8335_DEBUG7 0x441c
+
+int prom_argc;
+char **prom_argv = 0, **prom_envp = 0;
+
+extern void prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "NXP STB22x";
+}
+
+static inline unsigned long env_or_default(char *env, unsigned long dfl)
+{
+ char *str = prom_getenv(env);
+ return str ? simple_strtol(str, 0, 0) : dfl;
+}
+
+void __init prom_init(void)
+{
+ unsigned long memsize;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **)fw_arg1;
+ prom_envp = (char **)fw_arg2;
+
+ prom_init_cmdline();
+
+ memsize = env_or_default("memsize", 0x02000000);
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
+
+void __init pnx833x_board_setup(void)
+{
+#if defined(CONFIG_SERIAL_PNX8XXX) || defined(CONFIG_SERIAL_PNX8XXX_MODULE)
+ gpio_select_function_alt(4);
+ gpio_select_output(4);
+ gpio_select_function_alt(5);
+ gpio_select_input(5);
+ gpio_select_function_alt(6);
+ gpio_select_input(6);
+ gpio_select_function_alt(7);
+ gpio_select_output(7);
+#endif
+
+#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
+ gpio_select_function_alt(25);
+ gpio_select_function_alt(26);
+#endif
+
+#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE)
+ gpio_select_function_alt(27);
+ gpio_select_function_alt(28);
+ gpio_select_function_alt(29);
+ gpio_select_function_alt(30);
+ gpio_select_function_alt(31);
+ gpio_select_function_alt(32);
+ gpio_select_function_alt(33);
+#endif
+
+#if defined(CONFIG_MTD_NAND_PLATFORM) ||
defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+ /* Setup MIU for NAND access on CS0...
+ *
+ * (it seems that we must also configure CS1 for reliable operation,
+ * otherwise the first read ID command will fail if it's read as 4 bytes
+ * but pass if it's read as 1 word.)
+ */
+
+ /* Setup MIU CS0 & CS1 timing */
+ PNX833X_MIU_SEL0 = 0;
+ PNX833X_MIU_SEL1 = 0;
+ PNX833X_MIU_SEL0_TIMING = 0x50003081;
+ PNX833X_MIU_SEL1_TIMING = 0x50003081;
+
+ /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does
not need this) */
+ gpio_select_function_alt(0);
+
+ /* Setup GPIO 04 to input NAND read/busy signal */
+ gpio_select_function_io(4);
+ gpio_select_input(4);
+
+ /* Setup GPIO 05 to disable NAND write protect */
+ gpio_select_function_io(5);
+ gpio_select_output(5);
+ gpio_write(1, 5);
+
+#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE)
+
+ /* Set up MIU for 16-bit NOR access on CS0 and CS1... */
+
+ /* Setup MIU CS0 & CS1 timing */
+ PNX833X_MIU_SEL0 = 1;
+ PNX833X_MIU_SEL1 = 1;
+ PNX833X_MIU_SEL0_TIMING = 0x6A08D082;
+ PNX833X_MIU_SEL1_TIMING = 0x6A08D082;
+
+ /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does
not need this) */
+ gpio_select_function_alt(0);
+#endif
+}
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/Makefile
linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/Makefile
--- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/Makefile 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/Makefile 2008-03-03
13:09:30.000000000 +0000
@@ -0,0 +1 @@
+lib-y := board.o
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/drivers/i2c/busses/i2c-pnx0105.c
linux-2.6.26-rc4/drivers/i2c/busses/i2c-pnx0105.c
--- linux-2.6.26-rc4.orig/drivers/i2c/busses/i2c-pnx0105.c 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/drivers/i2c/busses/i2c-pnx0105.c 2008-06-05
11:25:57.000000000 +0100
@@ -0,0 +1,328 @@
+/*
+ * i2c-pnx0105.c: driver for PNX833X I2C (IP0105 Block)
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Daniel Laird <daniel.j.laird@nxp.com>
+ *
+ * Copyright (C) 2006 Nikita Youshchenko <yoush@debian.org>
+ *
+ * Partially based on i2c-pca-isa driver, Copyright (C) 2004 Arcom Control
+ * Systems.
+ *
+ * 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-pnx0105.h>
+#include <linux/i2c-algo-pca.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+static inline unsigned long i2c_pnx0105_in(struct i2c_pnx0105_dev
*dev, int offset)
+{
+ return readl((unsigned long *)(dev->base + offset));
+}
+
+static inline void i2c_pnx0105_out(struct i2c_pnx0105_dev *dev, int
offset, unsigned long value)
+{
+ writel(value, (unsigned long *)(dev->base + offset));
+}
+
+static void i2c_pnx0105_writebyte(void *pa, int reg, int val)
+{
+ struct i2c_algo_pca_data *algo_data = container_of(pa, struct
i2c_algo_pca_data, data);
+ struct i2c_pnx0105_dev *dev = container_of(algo_data, struct
i2c_pnx0105_dev, algo_data);
+ int old_si;
+
+#ifdef DEBUG
+ static char *names[] = { "T/O", "DAT", "ADR", "CON"};
+ printk(KERN_DEBUG "i2c_pnx0105(0x%08lx): write %s <= %#04x\n",
dev->base, names[reg], val);
+#endif
+
+ switch (reg) {
+
+ case I2C_PCA_DAT:
+ i2c_pnx0105_out(dev, I2C_PNX0105_DAT, val & 255);
+ break;
+
+ case I2C_PCA_ADR:
+ i2c_pnx0105_out(dev, I2C_PNX0105_ADDRESS, val & 255);
+ break;
+
+ case I2C_PCA_CON:
+ /* Possible RACE: just after init, or after stop,
+ SI bit is zero. That means that when STA bit
+ is written, hardware starts to process it
+ immediately. It could complete very fast (or
+ perhaps thread may get preempted), so when code
+ several lines below is executed, SI could already
+ be set to indicate that STA processing is complete.
+ In this case, SI must NOT be cleared here, so
+ hardware won't continue and send slave address
+ before it was written to register.
+ However, if SI bit is currently set, hardware
+ won't process command immediately, and SI should
+ be cleared at the bottom, to enable processing.
+ Solution: just check SI here, and clear it only
+ if it was set before any new value was written
+ to command register.
+ */
+ old_si = i2c_pnx0105_in(dev, I2C_PNX0105_INT_STATUS) & 1;
+
+ i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, val & 255);
+
+ /* We have to process STO bit separately */
+ if (val & I2C_PCA_CON_STO)
+ i2c_pnx0105_out(dev, I2C_PNX0105_STOP, 1);
+
+ /* And also SI bit ... */
+ if (old_si && !(val & I2C_PCA_CON_SI)) {
+ i2c_pnx0105_out(dev, I2C_PNX0105_INT_CLEAR, 1);
+ if (dev->irq > -1 && !(val & I2C_PCA_CON_STO))
+ i2c_pnx0105_out(dev, I2C_PNX0105_INT_ENABLE, 1);
+ }
+
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+static int i2c_pnx0105_readbyte(void *pa, int reg)
+{
+ struct i2c_algo_pca_data *algo_data = container_of(pa, struct
i2c_algo_pca_data, data);
+ struct i2c_pnx0105_dev *dev = container_of(algo_data, struct
i2c_pnx0105_dev, algo_data);
+ int res = 0;
+
+ switch (reg) {
+
+ case I2C_PCA_STA:
+ if (dev->timeout) {
+ res = 0xff;
+ dev->timeout = 0;
+ } else
+ res = i2c_pnx0105_in(dev, I2C_PNX0105_STATUS) & 255;
+ break;
+
+ case I2C_PCA_DAT:
+ res = i2c_pnx0105_in(dev, I2C_PNX0105_DAT) & 255;
+ break;
+
+ case I2C_PCA_CON:
+ res = i2c_pnx0105_in(dev, I2C_PNX0105_CONTROL) & 255;
+
+ /* Read SI bit from elsewhere */
+ if (i2c_pnx0105_in(dev, I2C_PNX0105_INT_STATUS))
+ res |= I2C_PCA_CON_SI;
+ else
+ res &= ~I2C_PCA_CON_SI;
+
+ break;
+
+ default:
+ BUG();
+ }
+
+#ifdef DEBUG
+ {
+ static char *names[] = { "STA", "DAT", "ADR", "CON"};
+ printk(KERN_DEBUG "i2c_pnx0105(0x%08lx): read %s => %#04x\n",
dev->base, names[reg], res);
+ }
+#endif
+ return res;
+}
+
+static inline void i2c_pnx0105_reset(struct i2c_pnx0105_dev *dev)
+{
+ unsigned long val = i2c_pnx0105_in(dev, I2C_PNX0105_CONTROL) & 0x47;
+ i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, val | 0x40);
+ i2c_pnx0105_out(dev, I2C_PNX0105_STOP, 1);
+ i2c_pnx0105_out(dev, I2C_PNX0105_INT_CLEAR, 1);
+ udelay(200);
+ i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, val);
+}
+
+static inline int i2c_pnx0105_intr_condition(struct i2c_pnx0105_dev *dev)
+{
+ return i2c_pnx0105_in(dev, I2C_PNX0105_INT_STATUS) & 1;
+}
+
+static int i2c_pnx0105_waitforcompletion(void *pa)
+{
+ struct i2c_algo_pca_data *algo_data = container_of(pa, struct
i2c_algo_pca_data, data);
+ struct i2c_pnx0105_dev *dev = container_of(algo_data, struct
i2c_pnx0105_dev, algo_data);
+
+ /* Set some timeout */
+#define JIFFIES_TO_WAIT ((HZ / 100) + 1) /* attempt to
model 10 milliseconds */
+
+ if (dev->irq > -1) {
+ wait_event_timeout(dev->wait,
+
i2c_pnx0105_intr_condition(dev), JIFFIES_TO_WAIT);
+ } else {
+ unsigned long end = jiffies + JIFFIES_TO_WAIT;
+ while (!i2c_pnx0105_intr_condition(dev) &&
+ time_before(jiffies, end)) {
+ if (in_atomic())
+ udelay(100);
+ else
+ schedule();
+ }
+ }
+
+ if (i2c_pnx0105_intr_condition(dev))
+ return 0;
+
+ /* Timeout. Reset device and make next status read to return 0xff */
+ i2c_pnx0105_reset(dev);
+ dev->timeout = 1;
+ return -EIO; /* Ignored anyway */
+}
+
+static irqreturn_t i2c_pnx0105_interrupt(int this_irq, void *dev_id)
+{
+ struct i2c_pnx0105_dev *dev = (struct i2c_pnx0105_dev *)dev_id;
+
+ /* Disable interrupt for a while (until it's actually handled) */
+ i2c_pnx0105_out(dev, I2C_PNX0105_INT_ENABLE, 0);
+
+ /* Wake up any process waiting for this interrupt */
+ wake_up_interruptible(&dev->wait);
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit i2c_pnx0105_probe(struct platform_device *pdev)
+{
+ struct i2c_pnx0105_dev *dev = (struct i2c_pnx0105_dev *)
pdev->dev.platform_data;
+ struct i2c_algo_pca_data *algo_data = &dev->algo_data;
+ struct i2c_adapter *adap = &dev->adap;
+ int res;
+
+ algo_data->write_byte = i2c_pnx0105_writebyte;
+ algo_data->read_byte = i2c_pnx0105_readbyte;
+ algo_data->wait_for_completion = i2c_pnx0105_waitforcompletion;
+
+ adap->owner = THIS_MODULE;
+ adap->id = I2C_HW_A_PNX0105;
+ adap->algo_data = algo_data;
+ strncpy(adap->name, pdev->name, I2C_NAME_SIZE);
+
+ dev->timeout = 0;
+ init_waitqueue_head(&dev->wait);
+
+ if (request_region(dev->base, I2C_PNX0105_IO_SIZE, "i2c-pnx") == 0) {
+ printk(KERN_ERR "i2c-pnx0105: request_region(0x%08lx) failed\n",
+ dev->base);
+ return -EBUSY;
+ }
+
+ /* Disable interrupt - just to be sure ... */
+ i2c_pnx0105_out(dev, I2C_PNX0105_INT_ENABLE, 0);
+
+ if (dev->irq > -1) {
+ res = request_irq(dev->irq, i2c_pnx0105_interrupt, 0,
"i2c-pnx", dev);
+ if (res < 0) {
+ printk(KERN_ERR "i2c-pnx0105: request_irq() failed\n");
+ goto err_region;
+ }
+ }
+
+ /* Rude attempt to probe hardware, to avoid future hangups if it is
+ not responding */
+ i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, 0x60);
+ udelay(200);
+ res = i2c_pnx0105_intr_condition(dev) ? 0 : -ENODEV;
+ i2c_pnx0105_reset(dev);
+
+ if (res < 0) {
+ printk(KERN_ERR "i2c-pnx0105: device at 0x%08lx is not
responding\n",
+ dev->base);
+ goto err_irq;
+ }
+
+ res = i2c_pca_add_bus(adap);
+ if (res < 0) {
+ printk(KERN_ERR "i2c-pnx0105: i2c_pca_add_bus() failed\n");
+ goto err_irq;
+ }
+
+ printk(KERN_INFO "i2c-pnx0105: registered device at 0x%08lx",
dev->base);
+ if (dev->irq > -1)
+ printk(KERN_ERR ", irq %d", dev->irq);
+ printk(KERN_INFO "\n");
+
+ return 0;
+
+err_irq:
+ if (dev->irq > -1)
+ free_irq(dev->irq, dev);
+
+err_region:
+ release_region(dev->base, I2C_PNX0105_IO_SIZE);
+
+ return res;
+}
+
+static int __devexit i2c_pnx0105_remove(struct platform_device *pdev)
+{
+ struct i2c_pnx0105_dev *dev = (struct i2c_pnx0105_dev *)
pdev->dev.platform_data;
+ struct i2c_adapter *adap = &dev->adap;
+ int res;
+
+ res = i2c_del_adapter(adap);
+ if (res < 0)
+ return res;
+
+ if (dev->irq > -1)
+ free_irq(dev->irq, dev);
+
+ release_region(dev->base, I2C_PNX0105_IO_SIZE);
+
+ return 0;
+}
+
+static struct platform_driver i2c_pnx0105_driver = {
+ .probe = i2c_pnx0105_probe,
+ .remove = __devexit_p(i2c_pnx0105_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "i2c-pnx0105",
+ },
+};
+
+static int __init i2c_pnx0105_init(void)
+{
+ return platform_driver_register(&i2c_pnx0105_driver);
+}
+
+static void __exit i2c_pnx0105_cleanup(void)
+{
+ platform_driver_unregister(&i2c_pnx0105_driver);
+}
+
+module_init(i2c_pnx0105_init);
+module_exit(i2c_pnx0105_cleanup);
+
+MODULE_AUTHOR("Nikita Youshchenko <yoush@debian.org>");
+MODULE_DESCRIPTION("PNX833X I2C driver");
+MODULE_LICENSE("GPL");
+
+
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/drivers/i2c/busses/Kconfig
linux-2.6.26-rc4/drivers/i2c/busses/Kconfig
--- linux-2.6.26-rc4.orig/drivers/i2c/busses/Kconfig 2008-06-03
10:56:53.000000000 +0100
+++ linux-2.6.26-rc4/drivers/i2c/busses/Kconfig 2008-06-04
09:29:35.000000000 +0100
@@ -677,6 +677,18 @@
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
+config I2C_PNX0105
+ tristate "I2C bus support for Philips PNX8XXX targets"
+ depends on I2C && SOC_PNX833X
+ select I2C_ALGOPCA
+ default y
+ help
+ Support for NXP PNX SoC internal I2C (IP0105).
+ Say y or m if you want to use PNX I2C interfaces.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-pnx0105.
+
config I2C_PMCMSP
tristate "PMC MSP I2C TWI Controller"
depends on PMC_MSP
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/drivers/i2c/busses/Makefile
linux-2.6.26-rc4/drivers/i2c/busses/Makefile
--- linux-2.6.26-rc4.orig/drivers/i2c/busses/Makefile 2008-06-03
10:56:53.000000000 +0100
+++ linux-2.6.26-rc4/drivers/i2c/busses/Makefile 2008-06-04
09:29:40.000000000 +0100
@@ -34,6 +34,7 @@
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
+obj-$(CONFIG_I2C_PNX0105) += i2c-pnx0105.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/net/ip3902.c
linux-2.6.26-rc4/drivers/net/ip3902.c
--- linux-2.6.26-rc4.orig/drivers/net/ip3902.c 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/drivers/net/ip3902.c 2008-06-05
11:27:28.000000000 +0100
@@ -0,0 +1,1534 @@
+/*
+ * ip3902.c: NXP ip3902 embedded 10/100 Ethernet controller support
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * Based on ax88796.c, by Ben Dooks.
+ * Based on previous ip3902.c by Nikita V. Youshchenko
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/inet_lro.h>
+#include <asm/system.h>
+#include <linux/io.h>
+
+#define DRVNAME "ip3902-eth"
+#define DRVVERSION "1.00"
+
+#define IP3902_NAPI
+
+/* "Strange hardware" support macros */
+
+/* These control endianness of descriptors and statuses.
+ * If none if LITTLE_ENDIAN_xxx and BIG_ENDIAN_xxx is defined, system endian
+ * is used for xxx */
+#define LITTLE_ENDIAN_DESCRIPTORS
+#undef BIG_ENDIAN_DESCRIPTORS
+#undef LITTLE_ENDIAN_STATUSES
+#define BIG_ENDIAN_STATUSES
+
+#define ETH_RX_SKB_SIZE 0x600 /* 1536 bytes, just over max mtu */
+#define TX_RING_SIZE 64
+#define RX_RING_SIZE 64
+#define IP3902_NAPI_WEIGHT 48
+#define MAX_LRO_DESCRIPTORS 6
+#define LRO_THRESHOLD 3
+
+#define BYTES_IN_ETHERNET_CRC 4
+#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
+
+#define NEXT_TX(i) (((i) == TX_RING_SIZE-1) ? 0 : (i)+1)
+#define NEXT_RX(i) (((i) == RX_RING_SIZE-1) ? 0 : (i)+1)
+
+/* Access to IP3902 registers */
+
+/* Alcatel (Packet Engines) core registers */
+#define MAC1_REG 0x000 /* R/W: MAC configuration register 1 */
+#define MAC2_REG 0x004 /* R/W: MAC configuration register 2 */
+#define IPGT_REG 0x008 /* R/W: Back-to-Back
Inter-Packet-Gap register */
+#define IPGR_REG 0x00c /* R/W: Non Back-to-Back
Inter-Packet-Gap register */
+#define CLRT_REG 0x010 /* R/W: Collision window /
Retry register */
+#define MAXF_REG 0x014 /* R/W: Maximum Frame register */
+#define SUPP_REG 0x018 /* R/W: PHY Support register */
+#define TEST_REG 0x01C /* R/W: Test register */
+#define MCFG_REG 0x020 /* R/W: MII Mgmt
Con???guration register */
+#define MCMD_REG 0x024 /* R/W: MII Mgmt Command register */
+#define MADR_REG 0x028 /* R/W: MII Mgmt Address register */
+#define MWTD_REG 0x02C /* WO: MII Mgmt Write Data register */
+#define MRDD_REG 0x030 /* RO: MII Mgmt Read Data register */
+#define MIND_REG 0x034 /* RO: MII Mgmt Indicators register */
+#define SA0_REG 0x040 /* R/W: Station
Address 0 register */
+#define SA1_REG 0x044 /* R/W: Station
Address 1 register */
+#define SA2_REG 0x048 /* R/W: Station
Address 2 register */
+
+/* Control registers */
+#define COMMAND_REG 0x100 /* R/W: Command register */
+#define STATUS_REG 0x104 /* RO: Status register */
+#define RX_DESC_REG 0x108 /* R/W: Receive descriptor
base address register */
+#define RX_STATUS_REG 0x10C /* R/W: Receive status base
address register */
+#define RX_DESC_NUMBER_REG 0x110 /* R/W: Receive number of
descriptors register */
+#define RX_PRODUCE_INDEX_REG 0x114 /* RO: Receive produce index
register */
+#define RX_CONSUME_INDEX_REG 0x118 /* R/W: Receive consume index
register */
+#define TX_DESC_REG 0x11C /* R/W: Non real-time transmit
descriptor
base address register */
+#define TX_STATUS_REG 0x120 /* R/W: Non real-time transmit status
base address register */
+#define TX_DESC_NUMBER_REG 0x124 /* R/W: Non real-time transmit
number of descriptors register */
+#define TX_PRODUCE_INDEX_REG 0x128 /* R/W: Non real-time transmit
produce index register */
+#define TX_CONSUME_INDEX_REG 0x12C /* RO: Non real-time transmit
consume index register */
+#define TX_RT_DESC_REG 0x130 /* R/W: Real-time transmit descriptor
base address register */
+#define TX_RT_STATUS_REG 0x134 /* R/W: Real-time transmit status base
address register */
+#define TX_RT_DESC_NUMBER_REG 0x138 /* R/W: Real-time transmit number
of descriptors register */
+#define TX_RT_PRODUCE_INDEX_REG 0x13C /* R/W: Real-time transmit
produce index register */
+#define TX_RT_CONSUME_INDEX_REG 0x140 /* RO: Real-time transmit
consume index register */
+#define QOS_TIMEOUT_REG 0x148 /* R/W: Transmit
quality of service
time-out register */
+#define TSV0_REG 0x158 /* RO: Transmit status vector
0 register */
+#define TSV1_REG 0x15C /* RO: Transmit status vector
1 register */
+#define RSV_REG 0x160 /* RO: Receive status
vector register */
+#define FC_COUNTER_REG 0x170 /* R/W: Flow control counter register */
+#define FC_STATUS_REG 0x174 /* RO: Flow control status register */
+
+/* Rx filter registers */
+#define FILTER_CTRL_REG 0x200 /* R/W: Receive filter
control register */
+#define FILTER_WOL_STATUS_REG 0x204 /* RO: Receive filter WoL status
register */
+#define FILTER_WOL_CLEAR_REG 0x208 /* WO: Receive filter WoL
clear register */
+#define HASH_FILTER_L_REG 0x210 /* R/W: Hash filter table LSBs
register */
+#define HASH_FILTER_H_REG 0x214 /* R/W: Hash filter table MSBs
register */
+
+/* DVP Standard registers */
+#define INT_STATUS_REG 0xFE0 /* RO: Interrupt status register */
+#define INT_ENABLE_REG 0xFE4 /* R/W: Interrupt enable register */
+#define INT_CLEAR_REG 0xFE8 /* WO: Interrupt clear register */
+#define INT_SET_REG 0xFEC /* WO: Interrupt set register */
+#define POWERDOWN_REG 0xFF4 /* R/W: Power-down register */
+#define MODULE_ID_REG 0xFFC /* RO: Module ID register */
+
+/* Bits for MAC1 register */
+#define MAC1_SOFT_RESET (1 << 15)
+#define MAC1_TX_FLOW_CONTROL (1 << 3)
+#define MAC1_RX_FLOW_CONTROL (1 << 2)
+#define MAC1_RECEIVE_PASS_ALL (1 << 1)
+#define MAC1_RECEIVE_ENABLE (1 << 0)
+
+/* Bits for MAC2 register */
+#define MAC2_AUTO_DETECT_PAD_ENABLE (1 << 7)
+#define MAC2_VLAN_PAD_ENABLE (1 << 6)
+#define MAC2_PAD_CRC_ENABLE (1 << 5)
+#define MAC2_CRC_ENABLE (1 << 4)
+#define MAC2_FULL_DUPLEX (1 << 0)
+
+#define INITIAL_MAC2 (MAC2_AUTO_DETECT_PAD_ENABLE |
MAC2_VLAN_PAD_ENABLE | MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE)
+
+/* Recommended values for IPGT register (see sec. 3.3.2.3 0f datasheet */
+#define IPGT_FD_VALUE 0x15
+#define IPGT_HD_VALUE 0x12
+
+/* Bits for MCMD register */
+#define MCMD_READ (1 << 0)
+
+/* Bits for MIND register */
+#define MIND_NOT_VALID (1 << 2)
+#define MIND_BUSY (1 << 0)
+
+/* Bits for command register */
+#define COMMAND_ENABLE_QOS (1 << 11)
+#define COMMAND_FULL_DUPLEX (1 << 10)
+#define COMMAND_RMII_MODE (1 << 9)
+#define COMMAND_TX_FLOW_CONTROL (1 << 8)
+#define COMMAND_PROMISC (1 << 7)
+#define COMMAND_ALLOW_SHORT (1 << 6)
+#define COMMAND_RX_RESET (1 << 5)
+#define COMMAND_TX_RESET (1 << 4)
+#define COMMAND_RESET (1 << 3)
+#define COMMAND_TX_RT_ENABLE (1 << 2)
+#define COMMAND_TX_ENABLE (1 << 1)
+#define COMMAND_RX_ENABLE (1 << 0)
+
+/* Bits for receive filter control register */
+#define FILTER_ACCEPT_SELF (1 << 5)
+#define FILTER_ACCEPT_MCAST_HASH (1 << 4)
+#define FILTER_ACCEPT_UCAST_HASH (1 << 3)
+#define FILTER_ACCEPT_MCAST_ANY (1 << 2)
+#define FILTER_ACCEPT_BCAST_ANY (1 << 1)
+#define FILTER_ACCEPT_UCAST_ANY (1 << 0)
+
+/* Bits for interrupt registers */
+#define WAKEUP_INT (1 << 13)
+#define SOFT_INT (1 << 12)
+#define TX_RT_DONE_INT (1 << 11)
+#define TX_RT_FINISHED_INT (1 << 10)
+#define TX_RT_ERROR_INT (1 << 9)
+#define TX_RT_UNDERRUN_INT (1 << 8)
+#define TX_DONE_INT (1 << 7)
+#define TX_FINISHED_INT (1 << 6)
+#define TX_ERROR_INT (1 << 5)
+#define TX_UNDERRUN_INT (1 << 4)
+#define RX_DONE_INT (1 << 3)
+#define RX_FINISHED_INT (1 << 2)
+#define RX_ERROR_INT (1 << 1)
+#define RX_OVERRUN_INT (1 << 0)
+
+/* Bit for POWERDOWN register */
+#define POWERDOWN_VALUE (1 << 31)
+
+/* Bits for TX control */
+#define TX_CONTROL_INT (1 << 31)
+#define TX_CONTROL_LAST (1 << 30)
+#define TX_CONTROL_CRC (1 << 29)
+#define TX_CONTROL_PAD (1 << 28)
+#define TX_CONTROL_HUGE (1 << 27)
+#define TX_CONTROL_OVERRIDE (1 << 26)
+
+/* these flags used for non-last fragment of a frame */
+#define TX_CONTROL_ALL_NOTLAST (TX_CONTROL_CRC | TX_CONTROL_PAD |
TX_CONTROL_OVERRIDE)
+/* these flags used for last fragment of a frame, and for single-fragment
+ * frames */
+#define TX_CONTROL_ALL_LAST (TX_CONTROL_ALL_NOTLAST | TX_CONTROL_LAST
| TX_CONTROL_INT)
+
+/* Bits for TX status */
+#define TX_STATUS_ERROR (1 << 31)
+#define TX_STATUS_UNDERRUN (1 << 29)
+#define TX_STATUS_LATE_COLLISION (1 << 28)
+#define TX_STATUS_MANY_COLLISIONS (1 << 27)
+#define TX_STATUS_MANY_DEFER (1 << 26)
+#define TX_STATUS_COLLISIONS(s) ((s >> 21) & 15)
+
+/* Bits for RX control */
+#define RX_CONTROL_INT (1 << 31)
+
+/* Bits for RX status */
+#define RX_STATUS_ERROR (1 << 31)
+#define RX_STATUS_LAST_FRAG (1 << 30)
+#define RX_STATUS_OVERRUN (1 << 28)
+#define RX_STATUS_ALIGNMENT_ERROR (1 << 27)
+#define RX_STATUS_RANGE_ERROR (1 << 26)
+#define RX_STATUS_LENGTH_ERROR (1 << 25)
+#define RX_STATUS_SYMBOL_ERROR (1 << 24)
+#define RX_STATUS_CRC_ERROR (1 << 23)
+#define RX_STATUS_BROADCAST (1 << 22)
+#define RX_STATUS_MULTICAST (1 << 21)
+#define RX_STATUS_FAIL_FILTER (1 << 20)
+#define RX_STATUS_VLAN (1 << 19)
+#define RX_STATUS_CONTROL_FRAME (1 << 18)
+#define RX_STATUS_LENGTH(s) ((s & 0x7ff) + 1)
+
+/* Bits for RSV register */
+#define RSV_VLAN (1 << 30)
+#define RSV_CONTROL_FRAME (1 << 27)
+#define RSV_DRIBBLE_NIBBLE (1 << 26)
+#define RSV_BROADCAST (1 << 25)
+#define RSV_MULTICAST (1 << 24)
+#define RSV_LENGTH_OUT_OF_RANGE (1 << 22)
+#define RSV_LENGTH_CHECK_ERROR (1 << 21)
+#define RSV_CRC_ERROR (1 << 20)
+#define RSV_RECEIVE_CODE_VIOLATION (1 << 19)
+#define RSV_MASK 0xFFFF
+
+static char *mac_address;
+module_param(mac_address, charp, S_IRUGO);
+MODULE_PARM_DESC(mac_address, "MAC address of the device");
+
+
+/* device private data */
+struct ip3902_descriptor {
+ unsigned long address;
+ unsigned long control;
+};
+
+struct ip3902_rx_status {
+ unsigned long status;
+ unsigned long hash_crc;
+};
+
+struct ip3902_dma_struct {
+ struct ip3902_descriptor rx_desc[RX_RING_SIZE];
+ struct ip3902_rx_status rx_status[RX_RING_SIZE];
+ struct ip3902_descriptor tx_desc[TX_RING_SIZE];
+ unsigned long tx_status[TX_RING_SIZE];
+};
+
+struct ip3902_private {
+ spinlock_t mii_lock;
+ struct mii_if_info mii;
+ u32 msg_enable;
+
+ spinlock_t lock;
+ struct net_device *ndev;
+ struct platform_device *pdev;
+ struct resource *bus;
+ void __iomem *mem;
+#ifdef IP3902_NAPI
+ struct napi_struct napi;
+#endif
+
+ struct ip3902_dma_struct *ds; /* descriptors and statuses */
+ dma_addr_t ds_dma;
+
+ struct sk_buff *rx_skb[RX_RING_SIZE]; /* where to recieve to */
+ struct sk_buff *tx_skb[TX_RING_SIZE]; /* where to send from */
+ bool tx_first_desc[TX_RING_SIZE]; /* true if this is the
first desc
of an skb */
+
+ int rx_next_allocate; /* index in rx ring
where skb should be allocated */
+ int rx_next_consume; /* index in rx ring
where data should be read
when available */
+ int tx_next_produce; /* index in tx ring
where new data should be put */
+ int tx_next_deallocate; /* index in tx ring of
first not freed skb */
+
+#ifdef CONFIG_INET_LRO
+ bool use_lro;
+ int lro_count;
+ struct net_lro_mgr lro_mgr;
+ struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
+ struct timer_list lro_timer;
+#endif
+
+ unsigned char running;
+ unsigned char resume_open;
+
+};
+
+static inline unsigned long ip3902_read_reg(struct net_device *ndev, int reg)
+{
+ unsigned long value = readl((void * __iomem)(ndev->base_addr + reg));
+ return value;
+}
+
+static inline void ip3902_write_reg(struct net_device *ndev, int reg,
+
unsigned long val)
+{
+ writel(val, (void * __iomem)(ndev->base_addr + reg));
+}
+
+static inline void ip3902_write_tx_desc(struct ip3902_private
*ip3902_priv, int pos, unsigned long address, unsigned long control)
+{
+#if defined(BIG_ENDIAN_DESCRIPTORS)
+ ip3902_priv->ds->tx_desc[pos].address = cpu_to_be32(address);
+ ip3902_priv->ds->tx_desc[pos].control = cpu_to_be32(control);
+#elif defined(LITTLE_ENDIAN_DESCRIPTORS)
+ ip3902_priv->ds->tx_desc[pos].address = cpu_to_le32(address);
+ ip3902_priv->ds->tx_desc[pos].control = cpu_to_le32(control);
+#else
+ ip3902_priv->ds->tx_desc[pos].address = address;
+ ip3902_priv->ds->tx_desc[pos].control = control;
+#endif
+ wmb();
+}
+
+static inline void ip3902_read_tx_desc(struct ip3902_private
*ip3902_priv, int pos, dma_addr_t *address, int *length)
+{
+#if defined(BIG_ENDIAN_DESCRIPTORS)
+ *address =
(dma_addr_t)be32_to_cpu(ip3902_priv->ds->tx_desc[pos].address);
+ *length =
(int)be32_to_cpu(ip3902_priv->ds->tx_desc[pos].control) & 0xffff;
+#elif defined(LITTLE_ENDIAN_DESCRIPTORS)
+ *address =
(dma_addr_t)le32_to_cpu(ip3902_priv->ds->tx_desc[pos].address);
+ *length =
(int)le32_to_cpu(ip3902_priv->ds->tx_desc[pos].control) & 0xffff;
+#else
+ *address = (dma_addr_t)ip3902_priv->ds->tx_desc[pos].address;
+ *length = (int)ip3902_priv->ds->tx_desc[pos].control & 0xffff;
+#endif
+}
+
+static inline unsigned long ip3902_read_tx_status(struct
ip3902_private *ip3902_priv, int pos)
+{
+#if defined(BIG_ENDIAN_STATUSES)
+ return be32_to_cpu(ip3902_priv->ds->tx_status[pos]);
+#elif defined(LITTLE_ENDIAN_STATUSES)
+ return le32_to_cpu(ip3902_priv->ds->tx_status[pos]);
+#else
+ return ip3902_priv->ds->tx_status[pos];
+#endif
+}
+
+static inline void ip3902_write_rx_desc(struct ip3902_private
*ip3902_priv, int pos, unsigned long address, unsigned long control)
+{
+#if defined(BIG_ENDIAN_DESCRIPTORS)
+ ip3902_priv->ds->rx_desc[pos].address = cpu_to_be32(address);
+ ip3902_priv->ds->rx_desc[pos].control = cpu_to_be32(control);
+#elif defined(LITTLE_ENDIAN_DESCRIPTORS)
+ ip3902_priv->ds->rx_desc[pos].address = cpu_to_le32(address);
+ ip3902_priv->ds->rx_desc[pos].control = cpu_to_le32(control);
+#else
+ ip3902_priv->ds->rx_desc[pos].address = address;
+ ip3902_priv->ds->rx_desc[pos].control = control;
+#endif
+ wmb();
+}
+
+static inline void ip3902_read_rx_desc(struct ip3902_private
*ip3902_priv, int pos, dma_addr_t *address, int *length)
+{
+#if defined(BIG_ENDIAN_DESCRIPTORS)
+ *address =
(dma_addr_t)be32_to_cpu(ip3902_priv->ds->rx_desc[pos].address);
+ *length =
(int)be32_to_cpu(ip3902_priv->ds->rx_desc[pos].control) & 0xffff;
+#elif defined(LITTLE_ENDIAN_DESCRIPTORS)
+ *address =
(dma_addr_t)le32_to_cpu(ip3902_priv->ds->rx_desc[pos].address);
+ *length =
(int)le32_to_cpu(ip3902_priv->ds->rx_desc[pos].control) & 0xffff;
+#else
+ *address = (dma_addr_t)ip3902_priv->ds->rx_desc[pos].address;
+ *length = (int)ip3902_priv->ds->rx_desc[pos].control & 0xffff;
+#endif
+}
+
+static inline unsigned long ip3902_read_rx_status(struct net_device
*ndev, struct ip3902_private *ip3902_priv, int pos)
+{
+#if defined(BIG_ENDIAN_STATUSES)
+ return be32_to_cpu(ip3902_priv->ds->rx_status[pos].status);
+#elif defined(LITTLE_ENDIAN_STATUSES)
+ return le32_to_cpu(ip3902_priv->ds->rx_status[pos].status);
+#else
+ return ip3902_priv->ds->rx_status[pos].status;
+#endif
+}
+
+static inline void ip3902_write_madr_reg(struct net_device *ndev, int
phy_id, int location)
+{
+ /* assume ranges of phy_id and location are correct - we set masks in
+ * struct mii_if_info for that */
+
+ unsigned long val = (phy_id << 8) | location;
+ ip3902_write_reg(ndev, MADR_REG, val);
+}
+
+static inline int ip3902_wait_mdio_op_complete(struct net_device
*ndev, unsigned long mask)
+{
+ int timeout = 10000; /* to avoid hangup in case of
unexpected badness ... */
+
+ while (--timeout > 0) {
+ if ((ip3902_read_reg(ndev, MIND_REG) & mask) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -EIO;
+}
+
+static int ip3902_mdio_read(struct net_device *ndev, int phy_id, int location)
+{
+ ip3902_write_madr_reg(ndev, phy_id, location);
+ ip3902_write_reg(ndev, MCMD_REG, 0);
+ ip3902_write_reg(ndev, MCMD_REG, MCMD_READ);
+ if (ip3902_wait_mdio_op_complete(ndev, MIND_NOT_VALID | MIND_BUSY) < 0)
+ return 0;
+ else
+ return ip3902_read_reg(ndev, MRDD_REG) & 0xffff;
+}
+
+static void ip3902_mdio_write(struct net_device *ndev, int phy_id,
int location, int val)
+{
+ ip3902_write_madr_reg(ndev, phy_id, location);
+ ip3902_write_reg(ndev, MWTD_REG, val & 0xffff);
+ ip3902_wait_mdio_op_complete(ndev, MIND_BUSY);
+}
+
+static inline int ip3902_nr_free_descs(int head, int tail, int size)
+{
+ int free;
+
+ if (head >= tail)
+ free = (tail + size) - head;
+ else
+ free = tail - head;
+
+ return free;
+}
+
+static void ip3902_eth_rx_refill_descs(struct net_device *ndev,
struct ip3902_private *ip3902_priv)
+{
+ do {
+ int rx_index = ip3902_priv->rx_next_allocate;
+ struct sk_buff *skb = netdev_alloc_skb(ndev, ETH_RX_SKB_SIZE +
dma_get_cache_alignment());
+
+ if (skb) {
+ int unaligned = (((u32)skb->data) + ETH_HLEN) &
(dma_get_cache_alignment() - 1);
+ unsigned long desc_address;
+
+ if (unaligned)
+ skb_reserve(skb,
(dma_get_cache_alignment() - unaligned));
+
+ desc_address = dma_map_single(NULL, skb->data,
ETH_RX_SKB_SIZE,
DMA_FROM_DEVICE);
+ ip3902_write_rx_desc(ip3902_priv, rx_index,
desc_address,
(ETH_RX_SKB_SIZE - 1) | RX_CONTROL_INT);
+
+ ip3902_priv->rx_skb[rx_index] = skb;
+ ip3902_priv->rx_next_allocate = NEXT_RX(rx_index);
+ } else {
+ ip3902_write_reg(ndev, RX_CONSUME_INDEX_REG,
ip3902_priv->rx_next_allocate);
+ return;
+ }
+ } while (ip3902_priv->rx_next_allocate != ip3902_priv->rx_next_consume);
+
+ ip3902_write_reg(ndev, RX_CONSUME_INDEX_REG,
ip3902_priv->rx_next_allocate);
+}
+
+static int ip3902_eth_receive_queue(struct net_device *ndev, struct
ip3902_private *ip3902_priv, int budget)
+{
+ int rx_index = ip3902_priv->rx_next_consume;
+ int write_index = ip3902_read_reg(ndev, RX_PRODUCE_INDEX_REG);
+ int received = 0;
+ int limit;
+
+ do {
+ limit = write_index;
+ spin_lock(&ip3902_priv->lock);
+ while (rx_index != limit) {
+ unsigned long status =
ip3902_read_rx_status(ndev, ip3902_priv, rx_index);
+
+ if (!(status & RX_STATUS_LAST_FRAG)) {
+ printk(DRVNAME ": broken RX status:
%08lx\n", status);
+ continue;
+ }
+
+ if (status & RX_STATUS_FAIL_FILTER)
+ continue;
+
+ /* Looks like hardware returns RANGE_ERROR for
each frame */
+ if (status & (RX_STATUS_OVERRUN |
RX_STATUS_ALIGNMENT_ERROR |
RX_STATUS_LENGTH_ERROR | RX_STATUS_CRC_ERROR)) {
+ ndev->stats.rx_errors++;
+
+ if (status & RX_STATUS_OVERRUN)
+ ndev->stats.rx_fifo_errors++;
+
+ if (status & RX_STATUS_ALIGNMENT_ERROR)
+ ndev->stats.rx_frame_errors++;
+
+ if (status & (RX_STATUS_RANGE_ERROR |
RX_STATUS_LENGTH_ERROR))
+ ndev->stats.rx_length_errors++;
+
+ if (status & RX_STATUS_CRC_ERROR)
+ ndev->stats.rx_crc_errors++;
+
+ } else {
+ if (--budget < 0) {
+ /* we got packets, but no quota */
+ /* store current ring pointer state */
+ ip3902_priv->rx_next_consume = rx_index;
+ return received;
+ } else {
+ struct sk_buff *skb =
ip3902_priv->rx_skb[rx_index];
+ int length =
RX_STATUS_LENGTH(status);
+ dma_addr_t data_addr;
+ int data_length;
+
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += length;
+ if (status & RX_STATUS_MULTICAST)
+ ndev->stats.multicast++;
+
+ skb_put(skb, length -
BYTES_IN_ETHERNET_CRC);
+ skb->protocol =
eth_type_trans(skb, ndev);
+
+#ifdef CONFIG_INET_LRO
+ if (ip3902_priv->use_lro)
+
lro_receive_skb(&ip3902_priv->lro_mgr, skb, ip3902_priv);
+ else
+ netif_receive_skb(skb);
+
+ ip3902_priv->lro_count++;
+#else
+#ifdef IP3902_NAPI
+ netif_receive_skb(skb);
+#else
+ netif_rx(skb);
+#endif
+#endif
+
+
ip3902_read_rx_desc(ip3902_priv, rx_index, &data_addr, &data_length);
+ dma_unmap_single(NULL,
data_addr, ETH_RX_SKB_SIZE, DMA_FROM_DEVICE);
+
+ ip3902_priv->rx_skb[rx_index] = NULL;
+ ndev->last_rx = jiffies;
+ received++;
+ }
+ }
+ rx_index = NEXT_RX(rx_index);
+ }
+
+ spin_unlock(&ip3902_priv->lock);
+ ip3902_priv->rx_next_consume = rx_index;
+ ip3902_eth_rx_refill_descs(ndev, ip3902_priv);
+ write_index = ip3902_read_reg(ndev, RX_PRODUCE_INDEX_REG);
+ } while (limit != write_index);
+
+#ifdef CONFIG_INET_LRO
+ if (ip3902_priv->use_lro) {
+ if (timer_pending(&ip3902_priv->lro_timer)) {
+ mod_timer(&ip3902_priv->lro_timer, jiffies + 2);
+ } else {
+ ip3902_priv->lro_timer.expires = jiffies + 2;
+ add_timer(&ip3902_priv->lro_timer);
+ }
+ }
+#endif
+
+ return received;
+}
+
+#ifdef IP3902_NAPI
+static int ip3902_poll(struct napi_struct *napi, int budget)
+{
+ struct ip3902_private *ip3902_priv = container_of(napi, struct
ip3902_private, napi);
+ struct net_device *ndev = ip3902_priv->ndev;
+ int work_done;
+
+ work_done = ip3902_eth_receive_queue(ndev, ip3902_priv, budget);
+
+ if (work_done < budget) {
+ ip3902_write_reg(ndev, INT_CLEAR_REG, RX_DONE_INT);
+ ip3902_write_reg(ndev, INT_CLEAR_REG, 0);
+ netif_rx_complete(ndev, napi);
+ ip3902_write_reg(ndev, INT_ENABLE_REG, (TX_UNDERRUN_INT |
RX_DONE_INT | RX_OVERRUN_INT));
+ }
+
+ return work_done;
+}
+#endif
+
+#ifdef CONFIG_INET_LRO
+static void ip3902_lro_timeout(unsigned long data)
+{
+ struct ip3902_private *ip3902_priv = (struct ip3902_private *)data;
+
+ spin_lock(&ip3902_priv->lock);
+ if (ip3902_priv->lro_count <= LRO_THRESHOLD) {
+ ip3902_priv->use_lro = false;
+ ip3902_priv->lro_count = 0;
+ }
+ lro_flush_all(&ip3902_priv->lro_mgr);
+ spin_unlock(&ip3902_priv->lock);
+}
+#endif
+
+#define ip3902_eth_free_completed_tx_descs(ndev, priv)
ip3902_eth_free_tx_descs(ndev, priv, 0)
+#define ip3902_eth_free_all_tx_descs(ndev, priv)
ip3902_eth_free_tx_descs(ndev, priv, 1)
+
+static void ip3902_eth_free_tx_descs(struct net_device *ndev, struct
ip3902_private *ip3902_priv, int force)
+{
+ int limit;
+
+ if (force)
+ limit = ip3902_priv->tx_next_produce;
+ else
+ limit = ip3902_read_reg(ndev, TX_CONSUME_INDEX_REG);
+
+ while (ip3902_priv->tx_next_deallocate != limit) {
+ int length;
+ int tx_index;
+ unsigned long status;
+ dma_addr_t addr;
+ struct sk_buff *skb;
+
+ tx_index = ip3902_priv->tx_next_deallocate;
+
+ ip3902_priv->tx_next_deallocate = NEXT_TX(tx_index);
+ ip3902_read_tx_desc(ip3902_priv, tx_index, &addr, &length);
+ skb = ip3902_priv->tx_skb[tx_index];
+
+ status = ip3902_read_tx_status(ip3902_priv, tx_index);
+ if (status & TX_STATUS_ERROR) {
+ ndev->stats.tx_errors++;
+ if (status & TX_STATUS_LATE_COLLISION)
+ ndev->stats.tx_aborted_errors++;
+
+ if (status & (TX_STATUS_MANY_COLLISIONS |
TX_STATUS_MANY_DEFER))
+ ndev->stats.tx_window_errors++;
+
+ } else {
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
+ ndev->stats.collisions += TX_STATUS_COLLISIONS(status);
+ }
+
+ if (skb)
+ ip3902_priv->tx_skb[tx_index] = NULL;
+
+ if (ip3902_priv->tx_first_desc[tx_index] == true)
+ dma_unmap_single(NULL, addr, length, DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, addr, length, DMA_TO_DEVICE);
+
+ if (skb)
+ dev_kfree_skb_irq(skb);
+ }
+}
+
+static void ip3902_reset_tx(struct net_device *ndev, struct
ip3902_private *ip3902_priv, int initial)
+{
+ unsigned long val;
+
+ /* Reset Tx hardware */
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val &= ~(COMMAND_TX_RT_ENABLE | COMMAND_TX_ENABLE);
+ val |= COMMAND_TX_RESET;
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+
+ if (!initial)
+ ip3902_eth_free_all_tx_descs(ndev, ip3902_priv);
+
+ ip3902_priv->tx_next_produce = 0;
+ ip3902_priv->tx_next_deallocate = 0;
+
+ /* Configure Tx registers */
+ ip3902_write_reg(ndev, TX_DESC_REG, ip3902_priv->ds_dma +
offsetof(struct ip3902_dma_struct, tx_desc));
+ ip3902_write_reg(ndev, TX_STATUS_REG, ip3902_priv->ds_dma +
offsetof(struct ip3902_dma_struct, tx_status));
+ ip3902_write_reg(ndev, TX_DESC_NUMBER_REG, TX_RING_SIZE - 1);
+ ip3902_write_reg(ndev, TX_PRODUCE_INDEX_REG,
ip3902_priv->tx_next_produce);
+ ip3902_write_reg(ndev, TX_CONSUME_INDEX_REG,
ip3902_priv->tx_next_deallocate);
+}
+
+static void ip3902_reset_rx(struct net_device *ndev, struct
ip3902_private *ip3902_priv, int init)
+{
+ unsigned long val;
+
+ /* Reset Rx hardware */
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val &= ~COMMAND_RX_ENABLE;
+ val |= COMMAND_RX_RESET;
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+
+ /* Set maximum frame size register */
+ ip3902_write_reg(ndev, MAXF_REG, ETH_RX_SKB_SIZE);
+
+ if (init) {
+ ip3902_priv->rx_next_allocate = 0;
+ ip3902_priv->rx_next_consume = 0;
+ ip3902_eth_rx_refill_descs(ndev, ip3902_priv);
+ }
+
+ /* Prepare skb's for Rx (any skb's already prepared will be reused)
+ * and configure Rx registers */
+ ip3902_write_reg(ndev, RX_DESC_REG, ip3902_priv->ds_dma +
offsetof(struct ip3902_dma_struct, rx_desc));
+ ip3902_write_reg(ndev, RX_STATUS_REG, ip3902_priv->ds_dma +
offsetof(struct ip3902_dma_struct, rx_status));
+ ip3902_write_reg(ndev, RX_DESC_NUMBER_REG, RX_RING_SIZE - 1);
+ ip3902_write_reg(ndev, RX_PRODUCE_INDEX_REG,
ip3902_priv->rx_next_consume);
+}
+
+static inline void ip3902_start_tx(struct net_device *ndev)
+{
+ unsigned long val;
+
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val |= COMMAND_TX_ENABLE;
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+}
+
+static inline void ip3902_start_rx(struct net_device *ndev)
+{
+ unsigned long val;
+
+ /* First on high-level ... */
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val |= (COMMAND_RX_ENABLE | COMMAND_ALLOW_SHORT);
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+
+ /* ... and then on low-level (after high level is ready to receive) */
+ val = ip3902_read_reg(ndev, MAC1_REG);
+ val |= MAC1_RECEIVE_ENABLE; /* flow control frames won't be passed
to driver */
+ ip3902_write_reg(ndev, MAC1_REG, val);
+}
+
+/* Interrupt handler body - split out to use both in interrupt handler
+ * and in net poll controller.
+ *
+ * Internal routine, called with lock held. */
+static void ip3902_do_handle_interrupt(struct net_device *ndev,
struct ip3902_private *ip3902_priv, unsigned long status)
+{
+ ip3902_write_reg(ndev, INT_CLEAR_REG, status);
+ ip3902_write_reg(ndev, INT_CLEAR_REG, 0);
+
+ if (status & TX_UNDERRUN_INT) {
+ printk(KERN_ERR DRVNAME ": %s: fatal Tx underrun,
resetting Tx\n",
ndev->name);
+ ip3902_reset_tx(ndev, ip3902_priv, 0);
+ ip3902_start_tx(ndev);
+ }
+
+ if (status & RX_OVERRUN_INT) {
+ printk(KERN_ERR DRVNAME ": %s: fatal Rx overrun,
resetting Rx\n",
ndev->name);
+ ip3902_reset_rx(ndev, ip3902_priv, 0);
+ ip3902_start_rx(ndev);
+ } else if (status & RX_DONE_INT) {
+#ifdef IP3902_NAPI
+ /* Disable the Rx interrupt */
+ ip3902_write_reg(ndev, INT_ENABLE_REG, (RX_OVERRUN_INT
| TX_UNDERRUN_INT));
+ netif_rx_schedule(ndev, &ip3902_priv->napi);
+#else
+ ip3902_eth_receive_queue(ndev, ip3902_priv, RX_RING_SIZE);
+#endif
+ }
+}
+
+static irqreturn_t ip3902_interrupt(int irq, void *dev_instance)
+{
+ struct net_device *ndev = (struct net_device *) dev_instance;
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ unsigned long status;
+
+ status = ip3902_read_reg(ndev, INT_STATUS_REG) & (TX_DONE_INT |
TX_UNDERRUN_INT | RX_DONE_INT | RX_OVERRUN_INT);
+ do {
+ if (!status) {
+ return IRQ_NONE;
+ } else {
+ ip3902_do_handle_interrupt(ndev, ip3902_priv, status);
+ status = ip3902_read_reg(ndev, INT_STATUS_REG)
& (TX_DONE_INT |
TX_UNDERRUN_INT | RX_DONE_INT | RX_OVERRUN_INT);
+ }
+ } while (status);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ip3902_net_poll(struct net_device *ndev)
+{
+ disable_irq_lockdep(ndev->irq);
+ ip3902_interrupt(ndev->irq, ndev);
+ enable_irq_lockdep(ndev->irq);
+}
+#endif
+
+static int eth_alloc_tx_desc_index(struct ip3902_private *ip3902_priv)
+{
+ int tx_desc_curr;
+
+ tx_desc_curr = ip3902_priv->tx_next_produce;
+ ip3902_priv->tx_next_produce = NEXT_TX(tx_desc_curr);
+
+ return tx_desc_curr;
+}
+
+static void eth_tx_fill_frag_descs(struct ip3902_private
*ip3902_priv, struct sk_buff *skb)
+{
+ int frag = 0;
+ int tx_index;
+
+ do {
+ skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+ unsigned long desc_address;
+ unsigned long desc_control;
+
+ tx_index = eth_alloc_tx_desc_index(ip3902_priv);
+
+ if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
+ desc_control = (this_frag->size - 1) |
TX_CONTROL_ALL_NOTLAST;
+ ip3902_priv->tx_skb[tx_index] = skb;
+ } else {
+ desc_control = (this_frag->size - 1) |
TX_CONTROL_ALL_LAST;
+ ip3902_priv->tx_skb[tx_index] = NULL;
+ }
+
+ ip3902_priv->tx_first_desc[tx_index] = false;
+ desc_address = dma_map_page(NULL, this_frag->page,
+
this_frag->page_offset,
+
this_frag->size,
+
DMA_TO_DEVICE);
+ ip3902_write_tx_desc(ip3902_priv, tx_index,
desc_address, desc_control);
+ } while (++frag < skb_shinfo(skb)->nr_frags);
+}
+
+static int ip3902_submit_skb_for_tx(struct net_device *ndev, struct
sk_buff *skb)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ int nr_frags;
+ int free_desc;
+ int ret = 0;
+
+#ifdef CONFIG_INET_LRO
+ if (ip3902_priv->lro_count > LRO_THRESHOLD)
+ ip3902_priv->use_lro = true;
+
+ ip3902_priv->lro_count = 0;
+#endif
+
+ free_desc = ip3902_nr_free_descs(ip3902_priv->tx_next_produce,
ip3902_priv->tx_next_deallocate, TX_RING_SIZE);
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
+ if (free_desc <= nr_frags) {
+ ip3902_eth_free_completed_tx_descs(ndev, ip3902_priv);
+ free_desc = ip3902_nr_free_descs(ip3902_priv->tx_next_produce,
ip3902_priv->tx_next_deallocate, TX_RING_SIZE);
+ }
+
+ if (free_desc > nr_frags) {
+ unsigned long desc_address;
+ unsigned long desc_control;
+ int tx_index;
+ int length;
+
+ tx_index = eth_alloc_tx_desc_index(ip3902_priv);
+
+ if (nr_frags) {
+ eth_tx_fill_frag_descs(ip3902_priv, skb);
+ length = skb_headlen(skb);
+ desc_control = (length - 1) | TX_CONTROL_ALL_NOTLAST;
+ ip3902_priv->tx_skb[tx_index] = NULL;
+ } else {
+ length = skb->len;
+ desc_control = (length - 1) | TX_CONTROL_ALL_LAST;
+ ip3902_priv->tx_skb[tx_index] = skb;
+ }
+
+ ip3902_priv->tx_first_desc[tx_index] = true;
+ desc_address = dma_map_single(NULL, skb->data,
length, DMA_TO_DEVICE);
+
+ ip3902_write_tx_desc(ip3902_priv, tx_index,
desc_address, desc_control);
+ ip3902_write_reg(ndev, TX_PRODUCE_INDEX_REG,
ip3902_priv->tx_next_produce);
+ ip3902_eth_free_completed_tx_descs(ndev, ip3902_priv);
+ } else {
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+static int ip3902_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ int ret;
+
+ BUG_ON(netif_queue_stopped(ndev));
+ BUG_ON(skb == NULL);
+ ret = ip3902_submit_skb_for_tx(ndev, skb);
+
+ if (ret) {
+ printk(KERN_ERR "%s: transmit with queue full\n", ndev->name);
+ netif_stop_queue(ndev);
+ } else {
+ ndev->stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ ndev->trans_start = jiffies;
+ }
+
+ return ret; /* success */
+}
+
+static void ip3902_do_set_rx_filter(struct net_device *ndev, struct
ip3902_private *ip3902_priv)
+{
+ unsigned long creg, freg;
+
+ creg = ip3902_read_reg(ndev, COMMAND_REG);
+ if (ndev->flags & IFF_PROMISC) {
+ /* If interface is in promiscuous mode, just disable filter */
+ ip3902_write_reg(ndev, COMMAND_REG, creg | COMMAND_PROMISC);
+ return;
+ }
+ /* Enable filter */
+ ip3902_write_reg(ndev, COMMAND_REG, creg & ~COMMAND_PROMISC);
+
+ /* Frames for self address and broadcast frames are always accepted */
+ freg = FILTER_ACCEPT_SELF | FILTER_ACCEPT_BCAST_ANY;
+
+ if (ndev->flags & IFF_ALLMULTI) {
+ /* Accept all multicast frames */
+ freg |= FILTER_ACCEPT_MCAST_ANY;
+ } else if (ndev->mc_count > 0) {
+ /* Accept some multicast frames */
+ u64 hash_mask = 0;
+ struct dev_mc_list *mc;
+
+ freg |= FILTER_ACCEPT_MCAST_HASH;
+ for (mc = ndev->mc_list; mc; mc = mc->next) {
+ int b = (ether_crc(ETH_ALEN, mc->dmi_addr) >>
23) & 0x3f;
+ hash_mask |= (1 << b);
+ }
+ ip3902_write_reg(ndev, HASH_FILTER_L_REG, hash_mask &
0xffffffff);
+ ip3902_write_reg(ndev, HASH_FILTER_H_REG, hash_mask >> 32);
+ }
+
+ ip3902_write_reg(ndev, FILTER_CTRL_REG, freg);
+}
+
+static void ip3902_set_rx_filter(struct net_device *ndev)
+{
+ struct ip3902_private *ip3902_priv = (struct ip3902_private
*)netdev_priv(ndev);
+
+ ip3902_do_set_rx_filter(ndev, ip3902_priv);
+}
+
+static void set_duplex_mode(struct net_device *ndev, int duplex)
+{
+ unsigned long val;
+
+ if (duplex) {
+ /* Full Duplex mode */
+
+ val = ip3902_read_reg(ndev, MAC2_REG);
+ val |= MAC2_FULL_DUPLEX;
+ ip3902_write_reg(ndev, MAC2_REG, val);
+
+ ip3902_write_reg(ndev, IPGT_REG, IPGT_FD_VALUE);
+
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val |= COMMAND_FULL_DUPLEX;
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+ } else {
+ /* Half Duplex mode */
+
+ val = ip3902_read_reg(ndev, MAC2_REG);
+ val &= ~MAC2_FULL_DUPLEX;
+ ip3902_write_reg(ndev, MAC2_REG, val);
+
+ ip3902_write_reg(ndev, IPGT_REG, IPGT_HD_VALUE);
+
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val &= ~COMMAND_FULL_DUPLEX;
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+ }
+}
+
+static int ip3902_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ unsigned int duplex_changed;
+ unsigned long flags;
+ int rc;
+
+ if (!netif_running(ndev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&ip3902_priv->mii_lock, flags);
+ rc = generic_mii_ioctl(&ip3902_priv->mii, if_mii(req), cmd,
&duplex_changed);
+ spin_unlock_irqrestore(&ip3902_priv->mii_lock, flags);
+ if (duplex_changed)
+ set_duplex_mode(ndev, ip3902_priv->mii.full_duplex);
+
+ return rc;
+}
+
+/* ethtool ops */
+
+static void ip3902_get_drvinfo(struct net_device *ndev,
+ struct
ethtool_drvinfo *info)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+
+ strcpy(info->driver, DRVNAME);
+ strcpy(info->version, DRVVERSION);
+ strcpy(info->bus_info, ip3902_priv->ndev->name);
+}
+
+static int ip3902_get_settings(struct net_device *ndev, struct
ethtool_cmd *cmd)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip3902_priv->mii_lock, flags);
+ mii_ethtool_gset(&ip3902_priv->mii, cmd);
+ spin_lock_irqsave(&ip3902_priv->mii_lock, flags);
+
+ return 0;
+}
+
+static int ip3902_set_settings(struct net_device *ndev, struct
ethtool_cmd *cmd)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&ip3902_priv->mii_lock, flags);
+ rc = mii_ethtool_sset(&ip3902_priv->mii, cmd);
+ spin_lock_irqsave(&ip3902_priv->mii_lock, flags);
+
+ return rc;
+}
+
+static int ip3902_nway_reset(struct net_device *ndev)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ return mii_nway_restart(&ip3902_priv->mii);
+}
+
+static u32 ip3902_get_link(struct net_device *ndev)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ return mii_link_ok(&ip3902_priv->mii);
+}
+
+static const struct ethtool_ops ip3902_ethtool_ops = {
+ .get_drvinfo = ip3902_get_drvinfo,
+ .get_settings = ip3902_get_settings,
+ .set_settings = ip3902_set_settings,
+ .nway_reset = ip3902_nway_reset,
+ .get_link = ip3902_get_link,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+};
+
+/* setup code */
+
+static void ip3902_eth_update_mac_address(struct net_device *ndev)
+{
+ ip3902_write_reg(ndev, SA0_REG, (ndev->dev_addr[5] << 8) |
ndev->dev_addr[4]);
+ ip3902_write_reg(ndev, SA1_REG, (ndev->dev_addr[3] << 8) |
ndev->dev_addr[2]);
+ ip3902_write_reg(ndev, SA2_REG, (ndev->dev_addr[1] << 8) |
ndev->dev_addr[0]);
+}
+
+static int ip3902_eth_set_mac_address(struct net_device *ndev, void *addr)
+{
+ int i;
+
+ for (i = 0; i < 6; i++)
+ /* +2 is for the offset of the HW addr type */
+ ndev->dev_addr[i] = ((unsigned char *)addr)[i + 2];
+
+ ip3902_eth_update_mac_address(ndev);
+ return 0;
+}
+
+static void ip3902_hw_deinit(struct net_device *ndev)
+{
+ unsigned long val;
+
+ /* Stop Rx and Tx hardware and disable interrupts */
+ val = ip3902_read_reg(ndev, COMMAND_REG);
+ val &= ~(COMMAND_TX_ENABLE | COMMAND_RX_ENABLE);
+ ip3902_write_reg(ndev, COMMAND_REG, val);
+ ip3902_write_reg(ndev, INT_ENABLE_REG, 0);
+
+ /* Put low-level hardware into reset, and high-level into poweroff */
+ ip3902_write_reg(ndev, MAC1_REG, MAC1_SOFT_RESET);
+ ip3902_write_reg(ndev, POWERDOWN_REG, POWERDOWN_VALUE);
+}
+
+static int ethernet_phy_get(struct net_device *ndev)
+{
+ int addr;
+
+ for (addr = 1; addr < 32; addr++) {
+ int stat;
+ stat = ip3902_mdio_read(ndev, addr, MII_BMSR);
+ if ((stat != 0) && (stat != 0xffff))
+ return addr;
+ }
+ printk(KERN_ERR DRVNAME ": could not locate PHY\n");
+ return -EIO;
+}
+
+static int ip3902_hw_init(struct net_device *ndev, struct
ip3902_private *ip3902_priv)
+{
+ int ret = 0;
+
+ /* Poweron hardware */
+ ip3902_write_reg(ndev, POWERDOWN_REG, 0);
+
+ /* Move low level out of reset (also initialize the registers)*/
+ ip3902_write_reg(ndev, MAC1_REG, 0);
+ ip3902_write_reg(ndev, MAC2_REG, INITIAL_MAC2);
+
+ ip3902_priv->mii.phy_id = ethernet_phy_get(ndev);
+
+ if (ip3902_priv->mii.phy_id < 0) {
+ ret = ip3902_priv->mii.phy_id;
+ } else {
+ ip3902_eth_update_mac_address(ndev);
+
+ /* "Initialize" command register (before resets - those routines
+ * use read-modify-write operations on that register */
+ ip3902_write_reg(ndev, COMMAND_REG, COMMAND_ALLOW_SHORT);
+
+ /* Reset and configure Rx and Tx */
+ ip3902_reset_tx(ndev, ip3902_priv, 1);
+ ip3902_reset_rx(ndev, ip3902_priv, 1);
+
+ /* Initialize Rx filtering */
+ ip3902_do_set_rx_filter(ndev, ip3902_priv);
+
+ /* Clear all interrupts, and enable interesting interrupts */
+ ip3902_write_reg(ndev, INT_CLEAR_REG, 0xffffffff);
+ ip3902_write_reg(ndev, INT_CLEAR_REG, 0);
+ ip3902_write_reg(ndev, INT_ENABLE_REG, (TX_UNDERRUN_INT |
RX_DONE_INT | RX_OVERRUN_INT));
+
+ /* Start Tx and Rx hardware */
+ ip3902_start_tx(ndev);
+ ip3902_start_rx(ndev);
+ }
+ return 0;
+}
+
+static int ip3902_open(struct net_device *ndev)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+ int ret;
+
+ dev_dbg(&ip3902_priv->ndev->dev, "%s: open\n", ndev->name);
+
+ ret = request_irq(ndev->irq, ip3902_interrupt, 0, ndev->name, ndev);
+ if (ret)
+ return ret;
+
+ ret = ip3902_hw_init(ndev, ip3902_priv);
+
+ if (ret)
+ return ret;
+
+ mii_check_media(&ip3902_priv->mii, netif_msg_link(ip3902_priv), 1);
+ set_duplex_mode(ndev, ip3902_priv->mii.full_duplex);
+
+#ifdef CONFIG_INET_LRO
+ init_timer(&ip3902_priv->lro_timer);
+ ip3902_priv->lro_timer.data = (unsigned long) ip3902_priv;
+ ip3902_priv->lro_timer.function = ip3902_lro_timeout;
+#endif
+
+ netif_start_queue(ndev);
+
+#ifdef IP3902_NAPI
+ napi_enable(&ip3902_priv->napi);
+#endif
+
+ ip3902_priv->running = 1;
+
+ return 0;
+}
+
+static int ip3902_close(struct net_device *ndev)
+{
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+
+ dev_dbg(&ip3902_priv->ndev->dev, "%s: close\n", ndev->name);
+
+ ip3902_priv->running = 0;
+ wmb();
+
+#ifdef CONFIG_INET_LRO
+ del_timer(&ip3902_priv->lro_timer);
+#endif
+
+#ifdef IP3902_NAPI
+ napi_disable(&ip3902_priv->napi);
+#endif
+
+ ip3902_hw_deinit(ndev);
+
+ netif_stop_queue(ndev);
+
+ ip3902_eth_free_all_tx_descs(ndev, ip3902_priv);
+
+ free_irq(ndev->irq, ndev);
+ return 0;
+}
+
+static int parse_mac_address(struct net_device *ndev)
+{
+ int n = sscanf(mac_address, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &ndev->dev_addr[0], &ndev->dev_addr[1],
+ &ndev->dev_addr[2], &ndev->dev_addr[3],
+ &ndev->dev_addr[4], &ndev->dev_addr[5]);
+
+ if (n == 6)
+ return 0;
+
+ printk(KERN_WARNING DRVNAME": failed to parse mac address string
\"%s\"\n", mac_address);
+ return -EINVAL;
+}
+
+static void ip3902_hw_shutdown(struct net_device *ndev, struct
ip3902_private *ip3902_priv)
+{
+ dma_free_coherent(NULL, sizeof(*(ip3902_priv->ds)), ip3902_priv->ds,
ip3902_priv->ds_dma);
+}
+
+static int ip3902_hw_startup(struct net_device *ndev, struct
ip3902_private *ip3902_priv)
+{
+ ip3902_priv->ds = dma_alloc_coherent(NULL,
sizeof(*(ip3902_priv->ds)), &ip3902_priv->ds_dma, GFP_KERNEL);
+ if (!ip3902_priv->ds) {
+ printk(KERN_ERR DRVNAME ": can't allocate DMA structure\n");
+ ip3902_hw_shutdown(ndev, ip3902_priv);
+ return -ENOMEM;
+ }
+
+ /* Poweron hardware */
+ ip3902_write_reg(ndev, POWERDOWN_REG, 0);
+
+ /* set mii clock */
+ ip3902_write_reg(ndev, MCFG_REG, 0x1c);
+
+ /* Move low level out of reset (also initialize the registers)*/
+ ip3902_write_reg(ndev, MAC1_REG, 0);
+ ip3902_write_reg(ndev, MAC2_REG, INITIAL_MAC2);
+
+ if (!mac_address || parse_mac_address(ndev) < 0) {
+ unsigned long val;
+
+ val = ip3902_read_reg(ndev, SA0_REG);
+ ndev->dev_addr[5] = (val >> 8) & 255;
+ ndev->dev_addr[4] = val & 255;
+ val = ip3902_read_reg(ndev, SA1_REG);
+ ndev->dev_addr[3] = (val >> 8) & 255;
+ ndev->dev_addr[2] = val & 255;
+ val = ip3902_read_reg(ndev, SA2_REG);
+ ndev->dev_addr[1] = (val >> 8) & 255;
+ ndev->dev_addr[0] = val & 255;
+ }
+
+ /* Put low-level hardware into reset, and high-level into poweroff */
+ ip3902_write_reg(ndev, MAC1_REG, MAC1_SOFT_RESET);
+ ip3902_write_reg(ndev, POWERDOWN_REG, POWERDOWN_VALUE);
+
+ return 0;
+}
+
+static int ip3902_init_dev(struct net_device *ndev, struct
ip3902_private *ip3902_priv)
+{
+ int ret;
+
+ ret = ip3902_hw_startup(ndev, ip3902_priv);
+
+ if (!ret) {
+ ndev->hard_start_xmit = ip3902_start_xmit;
+ ndev->set_mac_address = ip3902_eth_set_mac_address;
+ ndev->set_multicast_list = ip3902_set_rx_filter;
+ ndev->open = ip3902_open;
+ ndev->stop = ip3902_close;
+ ndev->do_ioctl = ip3902_ioctl;
+ ndev->features = 0;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = ip3902_net_poll;
+#endif
+ SET_ETHTOOL_OPS(ndev, &ip3902_ethtool_ops);
+
+ ip3902_priv->msg_enable = NETIF_MSG_LINK;
+ ip3902_priv->mii.phy_id_mask = 0x1f;
+ ip3902_priv->mii.reg_num_mask = 0x1f;
+ ip3902_priv->mii.mdio_read = ip3902_mdio_read;
+ ip3902_priv->mii.mdio_write = ip3902_mdio_write;
+ ip3902_priv->mii.dev = ndev;
+
+ spin_lock_init(&ip3902_priv->lock);
+
+ ret = register_netdev(ndev);
+
+ if (ret)
+ ip3902_hw_shutdown(ndev, ip3902_priv);
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_INET_LRO
+static int ip3902_get_skb_hdr(struct sk_buff *skb, void **iphdr, void
**tcph, u64 *hdr_flags, void *priv)
+{
+ unsigned int ip_len;
+ struct iphdr *iph;
+
+ /* non tcp packet */
+ skb_reset_network_header(skb);
+ iph = ip_hdr(skb);
+ if (iph->protocol != IPPROTO_TCP)
+ return -1;
+
+ ip_len = ip_hdrlen(skb);
+ skb_set_transport_header(skb, ip_len);
+ *tcph = tcp_hdr(skb);
+
+ /* check if ip header and tcp header are complete */
+ if (iph->tot_len < ip_len + tcp_hdrlen(skb))
+ return -1;
+
+ *hdr_flags = LRO_IPV4 | LRO_TCP;
+ *iphdr = iph;
+
+ return 0;
+}
+#endif
+
+static int ip3902_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ unregister_netdev(ndev);
+
+ iounmap(ip3902_priv->mem);
+ release_resource(ip3902_priv->bus);
+ kfree(ip3902_priv->bus);
+
+ free_netdev(ndev);
+
+ return 0;
+}
+
+/* ip3902_probe
+ *
+ * This is the entry point when the platform device system uses to
+ * notify us of a new device to attach to. Allocate memory, find
+ * the resources and information passed, and map the necessary registers.
+*/
+
+static int ip3902_probe(struct platform_device *pdev)
+{
+ struct net_device *ndev;
+ struct ip3902_private *ip3902_priv;
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ ndev = alloc_etherdev(sizeof(struct ip3902_private));
+
+ if (ndev == NULL)
+ return -ENOMEM;
+
+ ip3902_priv = netdev_priv(ndev);
+
+ memset(ip3902_priv, 0, sizeof(struct ip3902_private));
+
+ spin_lock_init(&ip3902_priv->mii_lock);
+
+ ip3902_priv->ndev = ndev;
+ ip3902_priv->pdev = pdev;
+
+#ifdef IP3902_NAPI
+ netif_napi_add(ndev, &ip3902_priv->napi, ip3902_poll,
IP3902_NAPI_WEIGHT);
+#endif
+
+#ifdef CONFIG_INET_LRO
+ ip3902_priv->use_lro = false;
+ ip3902_priv->lro_count = 0;
+ ip3902_priv->lro_mgr.max_aggr = IP3902_NAPI_WEIGHT;
+ ip3902_priv->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
+ ip3902_priv->lro_mgr.lro_arr = ip3902_priv->lro_desc;
+ ip3902_priv->lro_mgr.get_skb_header = ip3902_get_skb_hdr;
+#ifdef IP3902_NAPI
+ ip3902_priv->lro_mgr.features = LRO_F_NAPI;
+#else
+ ip3902_priv->lro_mgr.features = 0;
+#endif
+ ip3902_priv->lro_mgr.dev = ndev;
+ ip3902_priv->lro_mgr.ip_summed = 0;
+ ip3902_priv->lro_mgr.ip_summed_aggr = 0;
+#endif
+
+ platform_set_drvdata(pdev, ndev);
+
+ /* find the platform resources */
+ ndev->irq = platform_get_irq(pdev, 0);
+ if (ndev->irq < 0) {
+ dev_err(&pdev->dev, "no IRQ specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no MEM specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+ size = (res->end - res->start) + 1;
+
+ ip3902_priv->bus = request_mem_region(res->start & 0x1fffffff, size,
pdev->name);
+ if (ip3902_priv->bus == NULL) {
+ dev_err(&pdev->dev, "cannot reserve registers\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ ip3902_priv->mem = ioremap(res->start & 0x1fffffff, size);
+ ndev->base_addr = (unsigned long)ip3902_priv->mem;
+
+ if (ip3902_priv->mem == NULL) {
+ dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
+
+ ret = -ENXIO;
+ goto exit_req;
+ }
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ /* got resources, now initialise and register device */
+ ret = ip3902_init_dev(ndev, ip3902_priv);
+ if (!ret) {
+ printk(KERN_INFO "NXP ip3902 10/100 Ethernet platform
driver irq %d
base %08lx\n", ndev->irq, ndev->base_addr);
+ return 0;
+ }
+
+exit_req:
+ release_resource(ip3902_priv->bus);
+ kfree(ip3902_priv->bus);
+
+exit_mem:
+ free_netdev(ndev);
+
+ return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+static int ip3902_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+
+ ip3902_priv->resume_open = ip3902_priv->running;
+
+ netif_device_detach(ndev);
+ ip3902_close(ndev);
+
+ return 0;
+}
+
+static int ip3902_resume(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ip3902_private *ip3902_priv = netdev_priv(ndev);
+
+ netif_device_attach(ndev);
+
+ if (ip3902_priv->resume_open)
+ ip3902_open(ndev);
+
+ return 0;
+}
+
+#else
+ #define ip3902_suspend NULL
+ #define ip3902_resume NULL
+#endif
+
+static struct platform_driver ip3902drv = {
+ .driver = {
+ .name = "ip3902-eth",
+ .owner = THIS_MODULE,
+ },
+ .probe = ip3902_probe,
+ .remove = ip3902_remove,
+ .suspend = ip3902_suspend,
+ .resume = ip3902_resume,
+};
+
+static int __init ip3902drv_init(void)
+{
+ return platform_driver_register(&ip3902drv);
+}
+
+static void __exit ip3902drv_exit(void)
+{
+ platform_driver_unregister(&ip3902drv);
+}
+
+module_init(ip3902drv_init);
+module_exit(ip3902drv_exit);
+
+MODULE_DESCRIPTION("NXP IP3902 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Chris Steel, <chris.steel@nxp.com>");
+MODULE_LICENSE("GPL v2");
diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/net/Kconfig
linux-2.6.26-rc4/drivers/net/Kconfig
--- linux-2.6.26-rc4.orig/drivers/net/Kconfig 2008-06-03
10:56:55.000000000 +0100
+++ linux-2.6.26-rc4/drivers/net/Kconfig 2008-06-03
17:16:59.000000000 +0100
@@ -1884,6 +1884,15 @@
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
+config IP3902
+ tristate "NXP IP3902 ethernet hardware support"
+ depends on SOC_PNX8335 && NET_ETHERNET
+ select MII
+ select CRC32
+ help
+ This is a driver for NXP IP3902 ethernet hardware found
+ in PNX8335 and probably other SOCs.
+
source "drivers/net/fec_8xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/net/Makefile
linux-2.6.26-rc4/drivers/net/Makefile
--- linux-2.6.26-rc4.orig/drivers/net/Makefile 2008-06-03
10:56:55.000000000 +0100
+++ linux-2.6.26-rc4/drivers/net/Makefile 2008-06-03
17:17:11.000000000 +0100
@@ -122,6 +122,7 @@
obj-$(CONFIG_FORCEDETH) += forcedeth.o
obj-$(CONFIG_NE_H8300) += ne-h8300.o
obj-$(CONFIG_AX88796) += ax88796.o
+obj-$(CONFIG_IP3902) += ip3902.o
obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/gpio.h
linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/gpio.h
--- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/gpio.h 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/gpio.h 2008-06-05
11:07:19.000000000 +0100
@@ -0,0 +1,171 @@
+/*
+ * gpio.h: GPIO Support for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * 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.
+ */
+#ifndef __ASM_MIPS_MACH_PNX833X_GPIO_H
+#define __ASM_MIPS_MACH_PNX833X_GPIO_H
+
+/* BIG FAT WARNING: races danger!
+ No protections exist here. Current users are only early init code,
+ when locking is not needed because no cuncurency yet exists there,
+ and GPIO IRQ dispatcher, which does locking.
+ However, if many uses will ever happen, proper locking will be needed
+ - including locking between different uses
+*/
+
+#include "pnx833x.h"
+
+#define SET_REG_BIT(reg, bit) reg |= (1 << (bit))
+#define CLEAR_REG_BIT(reg, bit) reg &= ~(1 << (bit))
+
+/* Initialize GPIO to a known state */
+static inline void gpio_init(void)
+{
+ PNX833X_PIO_DIR = 0;
+ PNX833X_PIO_DIR2 = 0;
+ PNX833X_PIO_SEL = 0;
+ PNX833X_PIO_SEL2 = 0;
+ PNX833X_PIO_INT_EDGE = 0;
+ PNX833X_PIO_INT_HI = 0;
+ PNX833X_PIO_INT_LO = 0;
+
+ /* clear any GPIO interrupt requests */
+ PNX833X_PIO_INT_CLEAR = 0xffff;
+ PNX833X_PIO_INT_CLEAR = 0;
+ PNX833X_PIO_INT_ENABLE = 0;
+}
+
+/* Select GPIO direction for a pin */
+static inline void gpio_select_input(unsigned int pin)
+{
+ if (pin < 32)
+ CLEAR_REG_BIT(PNX833X_PIO_DIR, pin);
+ else
+ CLEAR_REG_BIT(PNX833X_PIO_DIR2, pin & 31);
+}
+static inline void gpio_select_output(unsigned int pin)
+{
+ if (pin < 32)
+ SET_REG_BIT(PNX833X_PIO_DIR, pin);
+ else
+ SET_REG_BIT(PNX833X_PIO_DIR2, pin & 31);
+}
+
+/* Select GPIO or alternate function for a pin */
+static inline void gpio_select_function_io(unsigned int pin)
+{
+ if (pin < 32)
+ CLEAR_REG_BIT(PNX833X_PIO_SEL, pin);
+ else
+ CLEAR_REG_BIT(PNX833X_PIO_SEL2, pin & 31);
+}
+static inline void gpio_select_function_alt(unsigned int pin)
+{
+ if (pin < 32)
+ SET_REG_BIT(PNX833X_PIO_SEL, pin);
+ else
+ SET_REG_BIT(PNX833X_PIO_SEL2, pin & 31);
+}
+
+/* Read GPIO pin */
+static inline int gpio_read(unsigned int pin)
+{
+ if (pin < 32)
+ return(PNX833X_PIO_IN >> pin) & 1;
+ else
+ return(PNX833X_PIO_IN2 >> (pin & 31)) & 1;
+}
+
+/* Write GPIO pin */
+static inline void gpio_write(unsigned int val, unsigned int pin)
+{
+ if (pin < 32) {
+ if (val)
+ SET_REG_BIT(PNX833X_PIO_OUT, pin);
+ else
+ CLEAR_REG_BIT(PNX833X_PIO_OUT, pin);
+ } else {
+ if (val)
+ SET_REG_BIT(PNX833X_PIO_OUT2, pin & 31);
+ else
+ CLEAR_REG_BIT(PNX833X_PIO_OUT2, pin & 31);
+ }
+}
+
+/* Configure GPIO interrupt */
+#define GPIO_INT_NONE 0
+#define GPIO_INT_LEVEL_LOW 1
+#define GPIO_INT_LEVEL_HIGH 2
+#define GPIO_INT_EDGE_RISING 3
+#define GPIO_INT_EDGE_FALLING 4
+#define GPIO_INT_EDGE_BOTH 5
+static inline void gpio_setup_irq(int when, unsigned int pin)
+{
+ switch (when) {
+ case GPIO_INT_LEVEL_LOW:
+ CLEAR_REG_BIT(PNX833X_PIO_INT_EDGE, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_HI, pin);
+ SET_REG_BIT(PNX833X_PIO_INT_LO, pin);
+ break;
+ case GPIO_INT_LEVEL_HIGH:
+ CLEAR_REG_BIT(PNX833X_PIO_INT_EDGE, pin);
+ SET_REG_BIT(PNX833X_PIO_INT_HI, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_LO, pin);
+ break;
+ case GPIO_INT_EDGE_RISING:
+ SET_REG_BIT(PNX833X_PIO_INT_EDGE, pin);
+ SET_REG_BIT(PNX833X_PIO_INT_HI, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_LO, pin);
+ break;
+ case GPIO_INT_EDGE_FALLING:
+ SET_REG_BIT(PNX833X_PIO_INT_EDGE, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_HI, pin);
+ SET_REG_BIT(PNX833X_PIO_INT_LO, pin);
+ break;
+ case GPIO_INT_EDGE_BOTH:
+ SET_REG_BIT(PNX833X_PIO_INT_EDGE, pin);
+ SET_REG_BIT(PNX833X_PIO_INT_HI, pin);
+ SET_REG_BIT(PNX833X_PIO_INT_LO, pin);
+ break;
+ default:
+ CLEAR_REG_BIT(PNX833X_PIO_INT_EDGE, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_HI, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_LO, pin);
+ break;
+ }
+}
+
+/* Enable/disable GPIO interrupt */
+static inline void gpio_enable_irq(unsigned int pin)
+{
+ SET_REG_BIT(PNX833X_PIO_INT_ENABLE, pin);
+}
+static inline void gpio_disable_irq(unsigned int pin)
+{
+ CLEAR_REG_BIT(PNX833X_PIO_INT_ENABLE, pin);
+}
+
+/* Clear GPIO interrupt request */
+static inline void gpio_clear_irq(unsigned int pin)
+{
+ SET_REG_BIT(PNX833X_PIO_INT_CLEAR, pin);
+ CLEAR_REG_BIT(PNX833X_PIO_INT_CLEAR, pin);
+}
+
+#endif
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/irq.h
linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/irq.h
--- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/irq.h 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/irq.h 2008-06-05
10:28:19.000000000 +0100
@@ -0,0 +1,138 @@
+/*
+ * irq.h: IRQ mappings for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * 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.
+ */
+
+#ifndef __ASM_MIPS_MACH_PNX833X_IRQ_H
+#define __ASM_MIPS_MACH_PNX833X_IRQ_H
+/*
+ * The "IRQ numbers" are completely virtual.
+ *
+ * In PNX8330/1, we have 48 interrupt lines, numbered from 1 to 48.
+ * Let's use numbers 1..48 for PIC interrupts, number 0 for timer interrupt,
+ * numbers 49..64 for (virtual) GPIO interrupts.
+ *
+ * In PNX8335, we have 57 interrupt lines, numbered from 1 to 57,
+ * connected to PIC, which uses core hardware interrupt 2, and also
+ * a timer interrupt through hardware interrupt 5.
+ * Let's use numbers 1..64 for PIC interrupts, number 0 for timer interrupt,
+ * numbers 65..80 for (virtual) GPIO interrupts.
+ *
+ */
+
+#if defined(CONFIG_SOC_PNX8335)
+ #define PNX833X_PIC_NUM_IRQ 58
+#else
+ #define PNX833X_PIC_NUM_IRQ 37
+#endif
+
+#define MIPS_CPU_NUM_IRQ 8
+#define PNX833X_GPIO_NUM_IRQ 16
+
+#define MIPS_CPU_IRQ_BASE 0
+#define PNX833X_PIC_IRQ_BASE (MIPS_CPU_IRQ_BASE +
MIPS_CPU_NUM_IRQ)
+#define PNX833X_GPIO_IRQ_BASE (PNX833X_PIC_IRQ_BASE
+ PNX833X_PIC_NUM_IRQ)
+#define NR_IRQS
(MIPS_CPU_NUM_IRQ + PNX833X_PIC_NUM_IRQ +
PNX833X_GPIO_NUM_IRQ)
+
+
+#define PNX833X_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7)
+
+/* Interrupts supported by PIC */
+#define PNX833X_PIC_I2C0_INT (PNX833X_PIC_IRQ_BASE + 1)
+#define PNX833X_PIC_I2C1_INT (PNX833X_PIC_IRQ_BASE + 2)
+#define PNX833X_PIC_UART0_INT (PNX833X_PIC_IRQ_BASE + 3)
+#define PNX833X_PIC_UART1_INT (PNX833X_PIC_IRQ_BASE + 4)
+#define PNX833X_PIC_TS_IN0_DV_INT (PNX833X_PIC_IRQ_BASE + 5)
+#define PNX833X_PIC_TS_IN0_DMA_INT (PNX833X_PIC_IRQ_BASE + 6)
+#define PNX833X_PIC_GPIO_INT (PNX833X_PIC_IRQ_BASE + 7)
+#define PNX833X_PIC_AUDIO_DEC_INT (PNX833X_PIC_IRQ_BASE + 8)
+#define PNX833X_PIC_VIDEO_DEC_INT (PNX833X_PIC_IRQ_BASE + 9)
+#define PNX833X_PIC_CONFIG_INT (PNX833X_PIC_IRQ_BASE + 10)
+#define PNX833X_PIC_AOI_INT
(PNX833X_PIC_IRQ_BASE + 11)
+#define PNX833X_PIC_SYNC_INT (PNX833X_PIC_IRQ_BASE + 12)
+#define PNX8330_PIC_SPU_INT
(PNX833X_PIC_IRQ_BASE + 13)
+#define PNX8335_PIC_SATA_INT (PNX833X_PIC_IRQ_BASE + 13)
+#define PNX833X_PIC_OSD_INT
(PNX833X_PIC_IRQ_BASE + 14)
+#define PNX833X_PIC_DISP1_INT (PNX833X_PIC_IRQ_BASE + 15)
+#define PNX833X_PIC_DEINTERLACER_INT (PNX833X_PIC_IRQ_BASE + 16)
+#define PNX833X_PIC_DISPLAY2_INT (PNX833X_PIC_IRQ_BASE + 17)
+#define PNX833X_PIC_VC_INT
(PNX833X_PIC_IRQ_BASE + 18)
+#define PNX833X_PIC_SC_INT
(PNX833X_PIC_IRQ_BASE + 19)
+#define PNX833X_PIC_IDE_INT
(PNX833X_PIC_IRQ_BASE + 20)
+#define PNX833X_PIC_IDE_DMA_INT
(PNX833X_PIC_IRQ_BASE + 21)
+#define PNX833X_PIC_TS_IN1_DV_INT (PNX833X_PIC_IRQ_BASE + 22)
+#define PNX833X_PIC_TS_IN1_DMA_INT (PNX833X_PIC_IRQ_BASE + 23)
+#define PNX833X_PIC_SGDX_DMA_INT (PNX833X_PIC_IRQ_BASE + 24)
+#define PNX833X_PIC_TS_OUT_INT (PNX833X_PIC_IRQ_BASE + 25)
+#define PNX833X_PIC_IR_INT
(PNX833X_PIC_IRQ_BASE + 26)
+#define PNX833X_PIC_VMSP1_INT (PNX833X_PIC_IRQ_BASE + 27)
+#define PNX833X_PIC_VMSP2_INT (PNX833X_PIC_IRQ_BASE + 28)
+#define PNX833X_PIC_PIBC_INT (PNX833X_PIC_IRQ_BASE + 29)
+#define PNX833X_PIC_TS_IN0_TRD_INT (PNX833X_PIC_IRQ_BASE + 30)
+#define PNX833X_PIC_SGDX_TPD_INT (PNX833X_PIC_IRQ_BASE + 31)
+#define PNX833X_PIC_USB_INT
(PNX833X_PIC_IRQ_BASE + 32)
+#define PNX833X_PIC_TS_IN1_TRD_INT (PNX833X_PIC_IRQ_BASE + 33)
+#define PNX833X_PIC_CLOCK_INT (PNX833X_PIC_IRQ_BASE + 34)
+#define PNX833X_PIC_SGDX_PARSER_INT (PNX833X_PIC_IRQ_BASE + 35)
+#define PNX833X_PIC_VMSP_DMA_INT (PNX833X_PIC_IRQ_BASE + 36)
+
+#if defined(CONFIG_SOC_PNX8335)
+#define PNX8335_PIC_MIU_INT
(PNX833X_PIC_IRQ_BASE + 37)
+#define PNX8335_PIC_AVCHIP_IRQ_INT
(PNX833X_PIC_IRQ_BASE + 38)
+#define PNX8335_PIC_SYNC_HD_INT
(PNX833X_PIC_IRQ_BASE + 39)
+#define PNX8335_PIC_DISP_HD_INT
(PNX833X_PIC_IRQ_BASE + 40)
+#define PNX8335_PIC_DISP_SCALER_INT
(PNX833X_PIC_IRQ_BASE + 41)
+#define PNX8335_PIC_OSD_HD1_INT
(PNX833X_PIC_IRQ_BASE + 42)
+#define PNX8335_PIC_DTL_WRITER_Y_INT (PNX833X_PIC_IRQ_BASE + 43)
+#define PNX8335_PIC_DTL_WRITER_C_INT (PNX833X_PIC_IRQ_BASE + 44)
+#define PNX8335_PIC_DTL_EMULATOR_Y_IR_INT (PNX833X_PIC_IRQ_BASE + 45)
+#define PNX8335_PIC_DTL_EMULATOR_C_IR_INT (PNX833X_PIC_IRQ_BASE + 46)
+#define PNX8335_PIC_DENC_TTX_INT
(PNX833X_PIC_IRQ_BASE + 47)
+#define PNX8335_PIC_MMI_SIF0_INT
(PNX833X_PIC_IRQ_BASE + 48)
+#define PNX8335_PIC_MMI_SIF1_INT
(PNX833X_PIC_IRQ_BASE + 49)
+#define PNX8335_PIC_MMI_CDMMU_INT
(PNX833X_PIC_IRQ_BASE + 50)
+#define PNX8335_PIC_PIBCS_INT
(PNX833X_PIC_IRQ_BASE + 51)
+#define PNX8335_PIC_ETHERNET_INT
(PNX833X_PIC_IRQ_BASE + 52)
+#define PNX8335_PIC_VMSP1_0_INT
(PNX833X_PIC_IRQ_BASE + 53)
+#define PNX8335_PIC_VMSP1_1_INT
(PNX833X_PIC_IRQ_BASE + 54)
+#define PNX8335_PIC_VMSP1_DMA_INT
(PNX833X_PIC_IRQ_BASE + 55)
+#define PNX8335_PIC_TDGR_DE_INT
(PNX833X_PIC_IRQ_BASE + 56)
+#define PNX8335_PIC_IR1_IRQ_INT
(PNX833X_PIC_IRQ_BASE + 57)
+#endif
+
+/* GPIO interrupts */
+#define PNX833X_GPIO_0_INT
(PNX833X_GPIO_IRQ_BASE + 0)
+#define PNX833X_GPIO_1_INT
(PNX833X_GPIO_IRQ_BASE + 1)
+#define PNX833X_GPIO_2_INT
(PNX833X_GPIO_IRQ_BASE + 2)
+#define PNX833X_GPIO_3_INT
(PNX833X_GPIO_IRQ_BASE + 3)
+#define PNX833X_GPIO_4_INT
(PNX833X_GPIO_IRQ_BASE + 4)
+#define PNX833X_GPIO_5_INT
(PNX833X_GPIO_IRQ_BASE + 5)
+#define PNX833X_GPIO_6_INT
(PNX833X_GPIO_IRQ_BASE + 6)
+#define PNX833X_GPIO_7_INT
(PNX833X_GPIO_IRQ_BASE + 7)
+#define PNX833X_GPIO_8_INT
(PNX833X_GPIO_IRQ_BASE + 8)
+#define PNX833X_GPIO_9_INT
(PNX833X_GPIO_IRQ_BASE + 9)
+#define PNX833X_GPIO_10_INT
(PNX833X_GPIO_IRQ_BASE + 10)
+#define PNX833X_GPIO_11_INT
(PNX833X_GPIO_IRQ_BASE + 11)
+#define PNX833X_GPIO_12_INT
(PNX833X_GPIO_IRQ_BASE + 12)
+#define PNX833X_GPIO_13_INT
(PNX833X_GPIO_IRQ_BASE + 13)
+#define PNX833X_GPIO_14_INT
(PNX833X_GPIO_IRQ_BASE + 14)
+#define PNX833X_GPIO_15_INT
(PNX833X_GPIO_IRQ_BASE + 15)
+
+#endif
+
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/pnx833x.h
linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/pnx833x.h
--- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/pnx833x.h
1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/pnx833x.h 2008-06-05
10:11:24.000000000 +0100
@@ -0,0 +1,194 @@
+/*
+ * pnx833x.h: Register mappings for PNX833X.
+ *
+ * Copyright 2008 NXP Semiconductors
+ * Chris Steel <chris.steel@nxp.com>
+ *
+ * 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.
+ */
+#ifndef __ASM_MIPS_MACH_PNX833X_PNX833X_H
+#define __ASM_MIPS_MACH_PNX833X_PNX833X_H
+
+/* All regs are accessed in KSEG1 */
+#define PNX833X_BASE (0xa0000000ul + 0x17E00000ul)
+
+#define PNX833X_REG(offs) *((volatile unsigned long
*)(PNX833X_BASE + offs))
+
+/* Registers are named exactly as in PNX833X docs, just with PNX833X_ prefix */
+
+/* Read access to multibit fields */
+#define PNX833X_BIT(val, reg, field) ((val) & PNX833X_##reg##_##field)
+#define PNX833X_REGBIT(reg, field) PNX833X_BIT(PNX833X_##reg, reg, field)
+
+/* Use PNX833X_FIELD to extract a field from val */
+#define PNX_FIELD(cpu, val, reg, field) \
+ (((val) & PNX##cpu##_##reg##_##field##_MASK) >> \
+ PNX##cpu##_##reg##_##field##_SHIFT)
+#define PNX833X_FIELD(val, reg, field) PNX_FIELD(833X, val, reg, field)
+#define PNX8330_FIELD(val, reg, field) PNX_FIELD(8330, val, reg, field)
+#define PNX8335_FIELD(val, reg, field) PNX_FIELD(8335, val, reg, field)
+
+/* Use PNX833X_REGFIELD to extract a field from a register */
+#define PNX833X_REGFIELD(reg, field) PNX833X_FIELD(PNX833X_##reg, reg, field)
+#define PNX8330_REGFIELD(reg, field) PNX8330_FIELD(PNX8330_##reg, reg, field)
+#define PNX8335_REGFIELD(reg, field) PNX8335_FIELD(PNX8335_##reg, reg, field)
+
+
+#define PNX_WRITEFIELD(cpu, val, reg, field) \
+ PNX##cpu##_##reg = (PNX##cpu##_##reg &
~(PNX##cpu##_##reg##_##field##_MASK)) | \
+ ((val) <<
PNX##cpu##_##reg##_##field##_SHIFT)
+#define PNX833X_WRITEFIELD(val, reg, field) \
+ PNX_WRITEFIELD(833X, val, reg, field)
+#define PNX8330_WRITEFIELD(val, reg, field) \
+ PNX_WRITEFIELD(8330, val, reg, field)
+#define PNX8335_WRITEFIELD(val, reg, field) \
+ PNX_WRITEFIELD(8335, val, reg, field)
+
+
+/* Macros to detect CPU type */
+
+#define PNX833X_CONFIG_MODULE_ID PNX833X_REG(0x7FFC)
+#define PNX833X_CONFIG_MODULE_ID_MAJREV_MASK 0x0000f000
+#define PNX833X_CONFIG_MODULE_ID_MAJREV_SHIFT 12
+#define PNX8330_CONFIG_MODULE_MAJREV 4
+#define PNX8335_CONFIG_MODULE_MAJREV 5
+#define CPU_IS_PNX8330 (PNX833X_REGFIELD(CONFIG_MODULE_ID, MAJREV) == \
+ PNX8330_CONFIG_MODULE_MAJREV)
+#define CPU_IS_PNX8335 (PNX833X_REGFIELD(CONFIG_MODULE_ID, MAJREV) == \
+ PNX8335_CONFIG_MODULE_MAJREV)
+
+
+
+#define PNX833X_RESET_CONTROL PNX833X_REG(0x8004)
+#define PNX833X_RESET_CONTROL_2 PNX833X_REG(0x8014)
+
+#define PNX833X_PIC_REG(offs) PNX833X_REG(0x01000 + (offs))
+#define PNX833X_PIC_INT_PRIORITY PNX833X_PIC_REG(0x0)
+#define PNX833X_PIC_INT_SRC PNX833X_PIC_REG(0x4)
+#define PNX833X_PIC_INT_SRC_INT_SRC_MASK 0x00000FF8ul /* bits 11:3 */
+#define PNX833X_PIC_INT_SRC_INT_SRC_SHIFT 3
+#define PNX833X_PIC_INT_REG(irq) PNX833X_PIC_REG(0x10 + 4*(irq))
+
+#define PNX833X_CLOCK_CPUCP_CTL PNX833X_REG(0x9228)
+#define PNX833X_CLOCK_CPUCP_CTL_EXIT_RESET 0x00000002ul /* bit 1 */
+#define PNX833X_CLOCK_CPUCP_CTL_DIV_CLOCK_MASK 0x00000018ul /* bits 4:3 */
+#define PNX833X_CLOCK_CPUCP_CTL_DIV_CLOCK_SHIFT 3
+
+#define PNX8335_CLOCK_PLL_CPU_CTL PNX833X_REG(0x9020)
+#define PNX8335_CLOCK_PLL_CPU_CTL_FREQ_MASK 0x1f
+#define PNX8335_CLOCK_PLL_CPU_CTL_FREQ_SHIFT 0
+
+#define PNX833X_CONFIG_MUX PNX833X_REG(0x7004)
+#define PNX833X_CONFIG_MUX_IDE_MUX 0x00000080 /* bit 7 */
+
+#define PNX8330_CONFIG_POLYFUSE_7 PNX833X_REG(0x7040)
+#define PNX8330_CONFIG_POLYFUSE_7_BOOT_MODE_MASK 0x00180000
+#define PNX8330_CONFIG_POLYFUSE_7_BOOT_MODE_SHIFT 19
+
+#define PNX833X_PIO_IN PNX833X_REG(0xF000)
+#define PNX833X_PIO_OUT PNX833X_REG(0xF004)
+#define PNX833X_PIO_DIR PNX833X_REG(0xF008)
+#define PNX833X_PIO_SEL PNX833X_REG(0xF014)
+#define PNX833X_PIO_INT_EDGE PNX833X_REG(0xF020)
+#define PNX833X_PIO_INT_HI PNX833X_REG(0xF024)
+#define PNX833X_PIO_INT_LO PNX833X_REG(0xF028)
+#define PNX833X_PIO_INT_STATUS PNX833X_REG(0xFFE0)
+#define PNX833X_PIO_INT_ENABLE PNX833X_REG(0xFFE4)
+#define PNX833X_PIO_INT_CLEAR PNX833X_REG(0xFFE8)
+#define PNX833X_PIO_IN2 PNX833X_REG(0xF05C)
+#define PNX833X_PIO_OUT2 PNX833X_REG(0xF060)
+#define PNX833X_PIO_DIR2 PNX833X_REG(0xF064)
+#define PNX833X_PIO_SEL2 PNX833X_REG(0xF068)
+
+#define PNX833X_UART0_PORTS_START (PNX833X_BASE + 0xB000)
+#define PNX833X_UART0_PORTS_END (PNX833X_BASE + 0xBFFF)
+#define PNX833X_UART1_PORTS_START (PNX833X_BASE + 0xC000)
+#define PNX833X_UART1_PORTS_END (PNX833X_BASE + 0xCFFF)
+
+#define PNX833X_USB_PORTS_START (PNX833X_BASE + 0x19000)
+#define PNX833X_USB_PORTS_END (PNX833X_BASE + 0x19FFF)
+
+#define PNX833X_CONFIG_USB PNX833X_REG(0x7008)
+
+#define PNX833X_I2C0_PORTS_START (PNX833X_BASE + 0xD000)
+#define PNX833X_I2C0_PORTS_END (PNX833X_BASE + 0xDFFF)
+#define PNX833X_I2C1_PORTS_START (PNX833X_BASE + 0xE000)
+#define PNX833X_I2C1_PORTS_END (PNX833X_BASE + 0xEFFF)
+
+#define PNX833X_IDE_PORTS_START (PNX833X_BASE + 0x1A000)
+#define PNX833X_IDE_PORTS_END (PNX833X_BASE + 0x1AFFF)
+#define PNX833X_IDE_MODULE_ID PNX833X_REG(0x1AFFC)
+
+#define PNX833X_IDE_MODULE_ID_MODULE_ID_MASK 0xFFFF0000
+#define PNX833X_IDE_MODULE_ID_MODULE_ID_SHIFT 16
+#define PNX833X_IDE_MODULE_ID_VALUE 0xA009
+
+
+#define PNX833X_MIU_SEL0 PNX833X_REG(0x2004)
+#define PNX833X_MIU_SEL0_TIMING PNX833X_REG(0x2008)
+#define PNX833X_MIU_SEL1 PNX833X_REG(0x200C)
+#define PNX833X_MIU_SEL1_TIMING PNX833X_REG(0x2010)
+#define PNX833X_MIU_SEL2 PNX833X_REG(0x2014)
+#define PNX833X_MIU_SEL2_TIMING PNX833X_REG(0x2018)
+#define PNX833X_MIU_SEL3 PNX833X_REG(0x201C)
+#define PNX833X_MIU_SEL3_TIMING PNX833X_REG(0x2020)
+
+#define PNX833X_MIU_SEL0_SPI_MODE_ENABLE_MASK (1 << 14)
+#define PNX833X_MIU_SEL0_SPI_MODE_ENABLE_SHIFT 14
+
+#define PNX833X_MIU_SEL0_BURST_MODE_ENABLE_MASK (1 << 7)
+#define PNX833X_MIU_SEL0_BURST_MODE_ENABLE_SHIFT 7
+
+#define PNX833X_MIU_SEL0_BURST_PAGE_LEN_MASK (0xF << 9)
+#define PNX833X_MIU_SEL0_BURST_PAGE_LEN_SHIFT 9
+
+#define PNX833X_MIU_CONFIG_SPI PNX833X_REG(0x2000)
+
+#define PNX833X_MIU_CONFIG_SPI_OPCODE_MASK (0xFF << 3)
+#define PNX833X_MIU_CONFIG_SPI_OPCODE_SHIFT 3
+
+#define PNX833X_MIU_CONFIG_SPI_DATA_ENABLE_MASK (1 << 2)
+#define PNX833X_MIU_CONFIG_SPI_DATA_ENABLE_SHIFT 2
+
+#define PNX833X_MIU_CONFIG_SPI_ADDR_ENABLE_MASK (1 << 1)
+#define PNX833X_MIU_CONFIG_SPI_ADDR_ENABLE_SHIFT 1
+
+#define PNX833X_MIU_CONFIG_SPI_SYNC_MASK (1 << 0)
+#define PNX833X_MIU_CONFIG_SPI_SYNC_SHIFT 0
+
+#define PNX833X_WRITE_CONFIG_SPI(opcode, data_enable, addr_enable, sync) \
+ PNX833X_MIU_CONFIG_SPI = \
+ ((opcode) << PNX833X_MIU_CONFIG_SPI_OPCODE_SHIFT) | \
+ ((data_enable) << PNX833X_MIU_CONFIG_SPI_DATA_ENABLE_SHIFT) | \
+ ((addr_enable) << PNX833X_MIU_CONFIG_SPI_ADDR_ENABLE_SHIFT) | \
+ ((sync) << PNX833X_MIU_CONFIG_SPI_SYNC_SHIFT)
+
+#define PNX8335_IP3902_PORTS_START (PNX833X_BASE + 0x2F000)
+#define PNX8335_IP3902_PORTS_END (PNX833X_BASE + 0x2FFFF)
+#define PNX8335_IP3902_MODULE_ID PNX833X_REG(0x2FFFC)
+
+#define PNX8335_IP3902_MODULE_ID_MODULE_ID_MASK 0xFFFF0000
+#define PNX8335_IP3902_MODULE_ID_MODULE_ID_SHIFT 16
+#define PNX8335_IP3902_MODULE_ID_VALUE 0x3902
+
+#define PNX8335_SATA_PORTS_START (PNX833X_BASE + 0x2E000)
+#define PNX8335_SATA_PORTS_END (PNX833X_BASE + 0x2EFFF)
+#define PNX8335_SATA_MODULE_ID PNX833X_REG(0x2EFFC)
+
+#define PNX8335_SATA_MODULE_ID_MODULE_ID_MASK 0xFFFF0000
+#define PNX8335_SATA_MODULE_ID_MODULE_ID_SHIFT 16
+#define PNX8335_SATA_MODULE_ID_VALUE 0xA099
+
+#endif
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/war.h
linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/war.h
--- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/war.h 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/war.h 2008-06-05
09:34:22.000000000 +0100
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_PNX833X_WAR_H
+#define __ASM_MIPS_MACH_PNX833X_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */
diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/linux/i2c-id.h
linux-2.6.26-rc4/include/linux/i2c-id.h
--- linux-2.6.26-rc4.orig/include/linux/i2c-id.h 2008-06-05
11:41:44.000000000 +0100
+++ linux-2.6.26-rc4/include/linux/i2c-id.h 2008-06-04
09:33:51.000000000 +0100
@@ -129,6 +129,7 @@
/* --- PCA 9564 based algorithms */
#define I2C_HW_A_ISA 0x1a0000 /* generic ISA Bus interface card */
+#define I2C_HW_A_PNX0105 0x1a0001 /* NXP PNX833X SoC I2C */
/* --- PowerPC on-chip adapters
*/
#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
diff -urN --exclude=.svn
linux-2.6.26-rc4.orig/include/linux/i2c-pnx0105.h
linux-2.6.26-rc4/include/linux/i2c-pnx0105.h
--- linux-2.6.26-rc4.orig/include/linux/i2c-pnx0105.h 1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.26-rc4/include/linux/i2c-pnx0105.h 2008-06-05
09:32:31.000000000 +0100
@@ -0,0 +1,58 @@
+/*
+ * i2c-pnx0105.h: driver for PNX833X I2C (IP0105 Block)
+ * Copyright (C) 2006 Nikita Youshchenko <yoush@debian.org>
+ *
+ * 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.
+ */
+#ifndef _LINUX_I2C_PNX0105_H
+#define _LINUX_I2C_PNX0105_H
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-pca.h>
+#include <linux/wait.h>
+
+struct i2c_pnx0105_dev {
+ unsigned long base;
+ int irq;
+ unsigned char clock; /* value to write to freq bits of control reg */
+ unsigned char bus_addr; /* bus address for slave mode; currently not
supported */
+
+ int timeout; /* non-zero when timeout was detected */
+ wait_queue_head_t wait;
+
+ struct i2c_algo_pca_data algo_data;
+ struct i2c_adapter adap;
+};
+
+/* Register area size */
+#define I2C_PNX0105_IO_SIZE 0x1000
+
+/* Register offsets */
+#define I2C_PNX0105_CONTROL 0x0000
+#define I2C_PNX0105_DAT 0x0004
+#define I2C_PNX0105_STATUS 0x0008
+#define I2C_PNX0105_ADDRESS 0x000C
+#define I2C_PNX0105_STOP 0x0010
+#define I2C_PNX0105_PD 0x0014
+#define I2C_PNX0105_SET_PINS 0x0018
+#define I2C_PNX0105_OBS_PINS 0x001C
+#define I2C_PNX0105_INT_STATUS 0x0FE0
+#define I2C_PNX0105_INT_ENABLE 0x0FE4
+#define I2C_PNX0105_INT_CLEAR 0x0FE8
+#define I2C_PNX0105_INT_SET 0x0FEC
+#define I2C_PNX0105_POWER_DOWN 0x0FF4
+#define I2C_PNX0105_MODULE_ID 0x0FFC
+
+#endif
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel
2008-06-05 19:45 Daniel Laird
@ 2008-06-05 20:43 ` Florian Fainelli
0 siblings, 0 replies; 6+ messages in thread
From: Florian Fainelli @ 2008-06-05 20:43 UTC (permalink / raw)
To: Daniel Laird; +Cc: linux-mips, ralf
Hello Daniel,
Le Thursday 05 June 2008 21:45:13 Daniel Laird, vous avez écrit :
> The following patch add support for the NXP PNX833x SOC. More
> specifically it adds support for
> the STB222/5 variant. This has I2C support, NAND and onboard ethernet
> support.
You should send the i2c parts to Jean Delvare and Ben Dooks, the I2C
maintainers. Ethernet part should be sent to the netdev mailing-list.
You can send the other pending parts to their respective maintainers, since
your drivers will be either platform drivers, and/or they depend on
CONFIG_NXP_STB225, they can be merged now, and get active when MIPS code is
merged as well.
I have posted some comments below in the body of your email, code looks
overall very good.
> +/***********************************************
> +* INCLUDE FILES *
> +************************************************/
> +
> +#include <asm/mach-pnx833x/pnx833x.h>
> +#include <linux/serial_pnx8xxx.h>
You might want to get rid of such comments with lines of *, and probably
reorder the inclusion to include first linux then asm headers.
> +#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE)
> +static struct resource pnx833x_sata_resources[] = {
> + [0] = {
> + .start = PNX8335_SATA_PORTS_START,
> + .end = PNX8335_SATA_PORTS_END,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = PNX8335_PIC_SATA_INT,
> + .end = PNX8335_PIC_SATA_INT,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +static struct platform_device pnx833x_sata_device = {
> + .name = "pnx833x-sata",
> + .id = -1,
> + .num_resources = ARRAY_SIZE(pnx833x_sata_resources),
> + .resource = pnx833x_sata_resources,
> +};
> +#endif
What about defining those resources anyway ?
> +
> +#if defined(CONFIG_MTD_NAND_PLATFORM) ||
> defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
Same here and others below too.
> +
> +#define STB225_NAND_BASE 0x18000000 /* I/O location(gets
> remapped)*/ +#define STB225_NAND_CLE_MASK 0x00100000 /* I/O location
> with CLE high */ +#define STB225_NAND_ALE_MASK 0x00010000 /* I/O
> location with ALE high */ +
You might want to put this in an header file instead.
> +void pnx833x_machine_halt(void)
> +{
> + printk(KERN_ALERT "\n\nSystem halted.\n\n");
> +
> + while (1)
> + __asm__ __volatile__ ("wait");
> +}
You might want to use cpu_relax(); instead of the assembly wait instruction.
> +
> +void pnx833x_machine_power_off(void)
> +{
> + printk(KERN_ALERT "\n\nPower off not implemented.");
> + pnx833x_machine_halt();
> +}
And put some less alarming message here, like "*** You can safely turn off the
board".
> +int __init plat_mem_setup(void)
> +{
> + /* fake pci bus to avoid bounce buffers */
> + PCI_DMA_BUS_IS_PHYS = 1;
> +
> + /* set mips clock to 320MHz */
> +#if defined(CONFIG_SOC_PNX8335)
> + PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ);
> +#endif
> + gpio_init(); /* so it will be ready in board_setup() */
You can move the GPIO code into its own C file, and use arch_initcall to
initialise it. Prefixing gpio_init with pnx83xx is better to be consistent
with other functions. See below for more comments about the GPIO code.
> +static inline unsigned long ip3902_read_reg(struct net_device *ndev, int
> reg) +{
> + unsigned long value = readl((void * __iomem)(ndev->base_addr +
> reg)); + return value;
Useless cast to void * __iomem in general, did your compiler produced a
warning on this ?
Netdev people will probably ask you to use NAPI unconditionnaly for new
drivers.
> +#ifdef IP3902_NAPI
> +static int ip3902_poll(struct napi_struct *napi, int budget)
> +{
> + struct ip3902_private *ip3902_priv = container_of(napi, struct
> ip3902_private, napi);
> + struct net_device *ndev = ip3902_priv->ndev;
> + int work_done;
> +
> + work_done = ip3902_eth_receive_queue(ndev, ip3902_priv, budget);
> +
> + if (work_done < budget) {
> + ip3902_write_reg(ndev, INT_CLEAR_REG, RX_DONE_INT);
> + ip3902_write_reg(ndev, INT_CLEAR_REG, 0);
> + netif_rx_complete(ndev, napi);
> + ip3902_write_reg(ndev, INT_ENABLE_REG, (TX_UNDERRUN_INT |
> RX_DONE_INT | RX_OVERRUN_INT));
> + }
> +
> + return work_done;
> +}
> +#endif
> +/* BIG FAT WARNING: races danger!
> + No protections exist here. Current users are only early init code,
> + when locking is not needed because no cuncurency yet exists there,
> + and GPIO IRQ dispatcher, which does locking.
> + However, if many uses will ever happen, proper locking will be needed
> + - including locking between different uses
You should consider using the GPIO library, or read what is done for BCM47xx,
AU1000 and TX4938. This should be easy since you comply with most of your
functions to this GPIO API. Providing your board specific gpio functions, the
rest of the API will handle locking and interrupt context for you.
Also, prefix your functions so that they will not collide with the other
implementations naming scheme.
Such functions might be provided by the C file instead, in the archicture
code. Remapping GPIO registers or things like that can be done there as well
at board boot time.
--
Cordialement, Florian Fainelli
------------------------------
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-06-11 11:01 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-11 10:53 [PATCH] : Add support for NXP PNX833x (STB222/5) into linux kernel Daniel Laird
2008-06-11 11:01 ` Ralf Baechle
-- strict thread matches above, loose matches on Subject: below --
2008-06-06 8:32 Daniel Laird
2008-06-11 10:43 ` Ralf Baechle
2008-06-05 19:45 Daniel Laird
2008-06-05 20:43 ` Florian Fainelli
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox