All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] XBurst JZ4730 support
@ 2010-02-25  6:28 Graham Gower
  2010-02-25  6:29 ` [PATCH 1/3] Add " Graham Gower
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Graham Gower @ 2010-02-25  6:28 UTC (permalink / raw)
  To: linux-mips

This patch set contains support for Ingenic's XBurst cpu, plus basic
support for their JZ4730 reference boards.


Graham Gower (3):
  Add XBurst JZ4730 support.
  8250: serial driver changes for XBurst SoCs.
  net: add driver for JZ4730 ethernet controller.

 arch/mips/Kconfig                                |   13 +
 arch/mips/Makefile                               |   14 +-
 arch/mips/boot/Makefile                          |   15 +-
 arch/mips/include/asm/bootinfo.h                 |    7 +
 arch/mips/include/asm/cpu.h                      |    9 +
 arch/mips/include/asm/mach-generic/irq.h         |    2 +-
 arch/mips/include/asm/mach-xburst/clock-jz4730.h |   41 +
 arch/mips/include/asm/mach-xburst/dma-jz4730.h   |  156 +++
 arch/mips/include/asm/mach-xburst/irq-jz4730.h   |   33 +
 arch/mips/include/asm/mach-xburst/uart-jz4730.h  |  141 +++
 arch/mips/include/asm/mach-xburst/war.h          |   25 +
 arch/mips/include/asm/mach-xburst/xburst.h       |   20 +
 arch/mips/include/asm/r4kcache.h                 |  240 +++++
 arch/mips/kernel/cpu-probe.c                     |   21 +
 arch/mips/mm/c-r4k.c                             |   30 +
 arch/mips/mm/tlbex.c                             |    5 +
 arch/mips/xburst/Kconfig                         |   23 +
 arch/mips/xburst/Makefile                        |    3 +
 arch/mips/xburst/jz4730/Makefile                 |   11 +
 arch/mips/xburst/jz4730/board-libra.c            |   32 +
 arch/mips/xburst/jz4730/board-pmp.c              |   32 +
 arch/mips/xburst/jz4730/clocks.c                 |  294 +++++
 arch/mips/xburst/jz4730/irq.c                    |  104 ++
 arch/mips/xburst/jz4730/platform.c               |   49 +
 arch/mips/xburst/jz4730/prom.c                   |  104 ++
 arch/mips/xburst/jz4730/setup.c                  |  136 +++
 arch/mips/xburst/jz4730/time.c                   |  140 +++
 drivers/net/Kconfig                              |   10 +
 drivers/net/Makefile                             |    1 +
 drivers/net/jz_eth.c                             | 1232 ++++++++++++++++++++++
 drivers/net/jz_eth.h                             |  403 +++++++
 drivers/serial/8250.c                            |   12 +
 32 files changed, 3355 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-xburst/clock-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/dma-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/irq-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/uart-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/war.h
 create mode 100644 arch/mips/include/asm/mach-xburst/xburst.h
 create mode 100644 arch/mips/xburst/Kconfig
 create mode 100644 arch/mips/xburst/Makefile
 create mode 100644 arch/mips/xburst/jz4730/Makefile
 create mode 100644 arch/mips/xburst/jz4730/board-libra.c
 create mode 100644 arch/mips/xburst/jz4730/board-pmp.c
 create mode 100644 arch/mips/xburst/jz4730/clocks.c
 create mode 100644 arch/mips/xburst/jz4730/irq.c
 create mode 100644 arch/mips/xburst/jz4730/platform.c
 create mode 100644 arch/mips/xburst/jz4730/prom.c
 create mode 100644 arch/mips/xburst/jz4730/setup.c
 create mode 100644 arch/mips/xburst/jz4730/time.c
 create mode 100644 drivers/net/jz_eth.c
 create mode 100644 drivers/net/jz_eth.h

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] Add XBurst JZ4730 support.
  2010-02-25  6:28 [PATCH 0/3] XBurst JZ4730 support Graham Gower
@ 2010-02-25  6:29 ` Graham Gower
  2010-02-25  6:30 ` [PATCH 2/3] 8250: serial driver changes for XBurst SoCs Graham Gower
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Graham Gower @ 2010-02-25  6:29 UTC (permalink / raw)
  To: linux-mips

Provides support for Ingenic's XBurst cpu. With initial support for
their JZ4730 SoC based PMP reference platform and Libra dev board.

Signed-off-by: Graham Gower <graham.gower@gmail.com>
---
 arch/mips/Kconfig                                |   13 +
 arch/mips/Makefile                               |   14 +-
 arch/mips/boot/Makefile                          |   15 +-
 arch/mips/include/asm/bootinfo.h                 |    7 +
 arch/mips/include/asm/cpu.h                      |    9 +
 arch/mips/include/asm/mach-generic/irq.h         |    2 +-
 arch/mips/include/asm/mach-xburst/clock-jz4730.h |   41 +++
 arch/mips/include/asm/mach-xburst/dma-jz4730.h   |  156 ++++++++++++
 arch/mips/include/asm/mach-xburst/irq-jz4730.h   |   33 +++
 arch/mips/include/asm/mach-xburst/uart-jz4730.h  |  141 +++++++++++
 arch/mips/include/asm/mach-xburst/war.h          |   25 ++
 arch/mips/include/asm/mach-xburst/xburst.h       |   20 ++
 arch/mips/include/asm/r5kcache.h                 |  240 ++++++++++++++++++
 arch/mips/kernel/cpu-probe.c                     |   21 ++
 arch/mips/mm/c-r4k.c                             |   30 +++
 arch/mips/mm/tlbex.c                             |    5 +
 arch/mips/xburst/Kconfig                         |   23 ++
 arch/mips/xburst/Makefile                        |    3 +
 arch/mips/xburst/jz4730/Makefile                 |   11 +
 arch/mips/xburst/jz4730/board-libra.c            |   32 +++
 arch/mips/xburst/jz4730/board-pmp.c              |   32 +++
 arch/mips/xburst/jz4730/clocks.c                 |  294 ++++++++++++++++++++++
 arch/mips/xburst/jz4730/irq.c                    |  104 ++++++++
 arch/mips/xburst/jz4730/platform.c               |   49 ++++
 arch/mips/xburst/jz4730/prom.c                   |  104 ++++++++
 arch/mips/xburst/jz4730/setup.c                  |  136 ++++++++++
 arch/mips/xburst/jz4730/time.c                   |  140 ++++++++++
 27 files changed, 1697 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-xburst/clock-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/dma-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/irq-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/uart-jz4730.h
 create mode 100644 arch/mips/include/asm/mach-xburst/war.h
 create mode 100644 arch/mips/include/asm/mach-xburst/xburst.h
 create mode 100644 arch/mips/xburst/Kconfig
 create mode 100644 arch/mips/xburst/Makefile
 create mode 100644 arch/mips/xburst/jz4730/Makefile
 create mode 100644 arch/mips/xburst/jz4730/board-libra.c
 create mode 100644 arch/mips/xburst/jz4730/board-pmp.c
 create mode 100644 arch/mips/xburst/jz4730/clocks.c
 create mode 100644 arch/mips/xburst/jz4730/irq.c
 create mode 100644 arch/mips/xburst/jz4730/platform.c
 create mode 100644 arch/mips/xburst/jz4730/prom.c
 create mode 100644 arch/mips/xburst/jz4730/setup.c
 create mode 100644 arch/mips/xburst/jz4730/time.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 8b5d174..ec5bd51 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -679,6 +679,18 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
 		Hikari
 	  Say Y here for most Octeon reference boards.
 
+config XBURST
+	bool "Ingenic XBurst based machines"
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select SYS_HAS_EARLY_PRINTK
+	select BOOT_RAW
+
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
@@ -693,6 +705,7 @@ source "arch/mips/txx9/Kconfig"
 source "arch/mips/vr41xx/Kconfig"
 source "arch/mips/cavium-octeon/Kconfig"
 source "arch/mips/loongson/Kconfig"
+source "arch/mips/xburst/Kconfig"
 
 endmenu
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 1893efd..f153e23 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -637,6 +637,13 @@ else
 load-$(CONFIG_CPU_CAVIUM_OCTEON) 	+= 0xffffffff81100000
 endif
 
+#
+# Ingenic XBurst
+#
+core-$(CONFIG_XBURST)	+= arch/mips/xburst/
+cflags-$(CONFIG_XBURST)	+= -I$(srctree)/arch/mips/include/asm/mach-xburst
+load-$(CONFIG_XBURST)	+= 0xffffffff80010000
+
 cflags-y			+= -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/
 
@@ -711,7 +718,8 @@ vmlinux.32: vmlinux
 vmlinux.64: vmlinux
 	$(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
 
-makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1)
+makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \
+	  VMLINUX_LOAD_ADDRESS=$(load-y) $(1)
 makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
 	   VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1)
 
@@ -738,6 +746,9 @@ vmlinux.ecoff: $(vmlinux-32)
 vmlinux.srec: $(vmlinux-32)
 	+@$(call makeboot,$@)
 
+uImage: $(vmlinux-32)
+	+@$(call makeboot,$@)
+
 CLEAN_FILES += vmlinux.ecoff \
 	       vmlinux.srec
 
@@ -771,6 +782,7 @@ define archhelp
 	echo '  vmlinuz.ecoff        - ECOFF zboot image'
 	echo '  vmlinuz.bin          - Raw binary zboot image'
 	echo '  vmlinuz.srec         - SREC zboot image'
+	echo '  uImage               - U-Boot image'
 	echo
 	echo '  These will be default as apropriate for a configured platform.'
 endef
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
index e39a08e..5215534 100644
--- a/arch/mips/boot/Makefile
+++ b/arch/mips/boot/Makefile
@@ -24,6 +24,7 @@ drop-sections	= .reginfo .mdebug .comment .note .pdr .options .MIPS.options
 strip-flags	= $(addprefix --remove-section=,$(drop-sections))
 
 VMLINUX = vmlinux
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
 
 all: vmlinux.ecoff vmlinux.srec
 
@@ -39,7 +40,19 @@ vmlinux.bin: $(VMLINUX)
 vmlinux.srec: $(VMLINUX)
 	$(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec
 
+uImage: vmlinux.bin
+	rm -f $(obj)/vmlinux.bin.gz
+	gzip -9 $(obj)/vmlinux.bin
+	$(CONFIG_SHELL) $(MKIMAGE) \
+		-A mips -O linux -T kernel -C gzip \
+		-a $(VMLINUX_LOAD_ADDRESS) -e $(VMLINUX_LOAD_ADDRESS) \
+		-n 'Linux-$(KERNELRELEASE)' \
+		-d $(obj)/vmlinux.bin.gz \
+		$(obj)/uImage
+
 clean-files += elf2ecoff \
 	       vmlinux.bin \
+	       vmlinux.bin.gz \
 	       vmlinux.ecoff \
-	       vmlinux.srec
+	       vmlinux.srec \
+	       uImage
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 09eee09..e21c0fb 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -71,6 +71,13 @@
 #define MACH_LEMOTE_LL2F       7
 #define MACH_LOONGSON_END      8
 
+/*
+ * Valid machtype for XBurst
+ */
+#define MACH_XBURST_UNKNOWN	0
+#define MACH_XBURST_JZ4730	1
+#define MACH_XBURST_JZ4740	2
+
 extern char *system_type;
 const char *get_system_type(void);
 
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index cf373a9..dd91d72 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -34,6 +34,7 @@
 #define PRID_COMP_LSI		0x080000
 #define PRID_COMP_LEXRA		0x0b0000
 #define PRID_COMP_CAVIUM	0x0d0000
+#define PRID_COMP_INGENIC	0xd00000
 
 
 /*
@@ -133,6 +134,13 @@
 #define PRID_IMP_CAVIUM_CN52XX 0x0700
 
 /*
+ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
+ */
+
+#define PRID_IMP_XBURST 0x0200
+
+
+/*
  * Definitions for 7:0 on legacy processors
  */
 
@@ -219,6 +227,7 @@ enum cpu_type_enum {
 	CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
 	CPU_ALCHEMY, CPU_PR4450, CPU_BCM3302, CPU_BCM4710,
 	CPU_BCM6338, CPU_BCM6345, CPU_BCM6348, CPU_BCM6358,
+	CPU_XBURST,
 
 	/*
 	 * MIPS64 class processors
diff --git a/arch/mips/include/asm/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h
index 70d9a25..73b7a83 100644
--- a/arch/mips/include/asm/mach-generic/irq.h
+++ b/arch/mips/include/asm/mach-generic/irq.h
@@ -9,7 +9,7 @@
 #define __ASM_MACH_GENERIC_IRQ_H
 
 #ifndef NR_IRQS
-#define NR_IRQS	128
+#define NR_IRQS	256
 #endif
 
 #ifdef CONFIG_I8259
diff --git a/arch/mips/include/asm/mach-xburst/clock-jz4730.h b/arch/mips/include/asm/mach-xburst/clock-jz4730.h
new file mode 100644
index 0000000..884738c
--- /dev/null
+++ b/arch/mips/include/asm/mach-xburst/clock-jz4730.h
@@ -0,0 +1,41 @@
+/*
+ *  JZ4730 clocks definition.
+ *
+ *  Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc.
+ *
+ *  Author: <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_XBURST_CLOCK_JZ4730_H__
+#define __ASM_MACH_XBURST_CLOCK_JZ4730_H__
+
+/*
+ * JZ4730 clocks structure
+ */
+struct jz_clocks {
+	unsigned int extal;
+	unsigned int extal2;
+
+	unsigned int iclk;	/* CPU core clock */
+	unsigned int sclk;	/* AHB bus clock */
+	unsigned int mclk;	/* Memory bus clock */
+	unsigned int pclk;	/* APB bus clock */
+	unsigned int devclk;	/* Devcie clock to specific modules */
+	unsigned int rtcclk;	/* RTC module clock */
+	unsigned int uartclk;	/* UART module clock */
+	unsigned int lcdclk;	/* LCD module clock */
+	unsigned int pixclk;	/* LCD pixel clock */
+	unsigned int usbclk;	/* USB module clock */
+	unsigned int i2sclk;	/* I2S module clock */
+	unsigned int mscclk;	/* MMC/SD module clock */
+};
+
+extern struct jz_clocks jz_clocks;
+
+void jz_cpm_set_usbclk(int external);
+
+#endif /* __ASM_MACH_XBURST_CLOCK_JZ4730_H__ */
diff --git a/arch/mips/include/asm/mach-xburst/dma-jz4730.h b/arch/mips/include/asm/mach-xburst/dma-jz4730.h
new file mode 100644
index 0000000..d02b443
--- /dev/null
+++ b/arch/mips/include/asm/mach-xburst/dma-jz4730.h
@@ -0,0 +1,156 @@
+
+#ifndef __ASM_MACH_XBURST_DMA_JZ4730_H
+#define __ASM_MACH_XBURST_DMA_JZ4730_H
+
+#define	DMAC_BASE	0xB3020000
+
+#define DMAC_DSAR(n)	(DMAC_BASE + (0x00 + (n) * 0x20))
+#define DMAC_DDAR(n)	(DMAC_BASE + (0x04 + (n) * 0x20))
+#define DMAC_DTCR(n)	(DMAC_BASE + (0x08 + (n) * 0x20))
+#define DMAC_DRSR(n)	(DMAC_BASE + (0x0c + (n) * 0x20))
+#define DMAC_DCCSR(n)	(DMAC_BASE + (0x10 + (n) * 0x20))
+#define DMAC_DMAIPR	(DMAC_BASE + 0xf8)
+#define DMAC_DMACR	(DMAC_BASE + 0xfc)
+
+#define DMAC_DRSR_RS_BIT	0
+#define DMAC_DRSR_RS_MASK	(0x1f << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_EXTREXTR		(0 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_PCMCIAOUT	(4 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_PCMCIAIN		(5 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_AUTO		(8 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_DESOUT		(10 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_DESIN		(11 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART3OUT		(14 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART3IN		(15 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART2OUT		(16 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART2IN		(17 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART1OUT		(18 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART1IN		(19 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART0OUT		(20 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_UART0IN		(21 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_SSIOUT		(22 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_SSIIN		(23 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_AICOUT		(24 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_AICIN		(25 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_MSCOUT		(26 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_MSCIN		(27 << DMAC_DRSR_RS_BIT)
+  #define DMAC_DRSR_RS_OST2		(28 << DMAC_DRSR_RS_BIT)
+
+#define DMAC_DCCSR_EACKS	(1 << 31)
+#define DMAC_DCCSR_EACKM	(1 << 30)
+#define DMAC_DCCSR_ERDM_BIT	28
+#define DMAC_DCCSR_ERDM_MASK	(0x03 << DMAC_DCCSR_ERDM_BIT)
+  #define DMAC_DCCSR_ERDM_LLEVEL	(0 << DMAC_DCCSR_ERDM_BIT)
+  #define DMAC_DCCSR_ERDM_FEDGE		(1 << DMAC_DCCSR_ERDM_BIT)
+  #define DMAC_DCCSR_ERDM_HLEVEL	(2 << DMAC_DCCSR_ERDM_BIT)
+  #define DMAC_DCCSR_ERDM_REDGE		(3 << DMAC_DCCSR_ERDM_BIT)
+#define DMAC_DCCSR_EOPM		(1 << 27)
+#define DMAC_DCCSR_SAM		(1 << 23)
+#define DMAC_DCCSR_DAM		(1 << 22)
+#define DMAC_DCCSR_RDIL_BIT	16
+#define DMAC_DCCSR_RDIL_MASK	(0x0f << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_IGN	(0 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_2	(1 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_4	(2 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_8	(3 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_12	(4 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_16	(5 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_20	(6 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_24	(7 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_28	(8 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_32	(9 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_48	(10 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_60	(11 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_64	(12 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_124	(13 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_128	(14 << DMAC_DCCSR_RDIL_BIT)
+  #define DMAC_DCCSR_RDIL_200	(15 << DMAC_DCCSR_RDIL_BIT)
+#define DMAC_DCCSR_SWDH_BIT	14
+#define DMAC_DCCSR_SWDH_MASK	(0x03 << DMAC_DCCSR_SWDH_BIT)
+  #define DMAC_DCCSR_SWDH_32	(0 << DMAC_DCCSR_SWDH_BIT)
+  #define DMAC_DCCSR_SWDH_8	(1 << DMAC_DCCSR_SWDH_BIT)
+  #define DMAC_DCCSR_SWDH_16	(2 << DMAC_DCCSR_SWDH_BIT)
+#define DMAC_DCCSR_DWDH_BIT	12
+#define DMAC_DCCSR_DWDH_MASK	(0x03 << DMAC_DCCSR_DWDH_BIT)
+  #define DMAC_DCCSR_DWDH_32	(0 << DMAC_DCCSR_DWDH_BIT)
+  #define DMAC_DCCSR_DWDH_8	(1 << DMAC_DCCSR_DWDH_BIT)
+  #define DMAC_DCCSR_DWDH_16	(2 << DMAC_DCCSR_DWDH_BIT)
+#define DMAC_DCCSR_DS_BIT	8
+#define DMAC_DCCSR_DS_MASK	(0x07 << DMAC_DCCSR_DS_BIT)
+  #define DMAC_DCCSR_DS_32b	(0 << DMAC_DCCSR_DS_BIT)
+  #define DMAC_DCCSR_DS_8b	(1 << DMAC_DCCSR_DS_BIT)
+  #define DMAC_DCCSR_DS_16b	(2 << DMAC_DCCSR_DS_BIT)
+  #define DMAC_DCCSR_DS_16B	(3 << DMAC_DCCSR_DS_BIT)
+  #define DMAC_DCCSR_DS_32B	(4 << DMAC_DCCSR_DS_BIT)
+#define DMAC_DCCSR_TM		(1 << 7)
+#define DMAC_DCCSR_AR		(1 << 4)
+#define DMAC_DCCSR_TC		(1 << 3)
+#define DMAC_DCCSR_HLT		(1 << 2)
+#define DMAC_DCCSR_TCIE		(1 << 1)
+#define DMAC_DCCSR_CHDE		(1 << 0)
+
+#define DMAC_DMAIPR_CINT_BIT	8
+#define DMAC_DMAIPR_CINT_MASK	(0xff << DMAC_DMAIPR_CINT_BIT)
+
+#define DMAC_DMACR_PR_BIT	8
+#define DMAC_DMACR_PR_MASK	(0x03 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_01234567	(0 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_02314675	(1 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_20136457	(2 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_ROUNDROBIN	(3 << DMAC_DMACR_PR_BIT)
+#define DMAC_DMACR_HTR		(1 << 3)
+#define DMAC_DMACR_AER		(1 << 2)
+#define DMAC_DMACR_DME		(1 << 0)
+
+#define IRQ_DMA_0	32
+#define NUM_DMA		6
+
+#define DMAC_DSAR0      DMAC_DSAR(0)
+#define DMAC_DDAR0      DMAC_DDAR(0)
+#define DMAC_DTCR0      DMAC_DTCR(0)
+#define DMAC_DRSR0      DMAC_DRSR(0)
+#define DMAC_DCCSR0     DMAC_DCCSR(0)
+
+#define DMAC_DSAR1      DMAC_DSAR(1)
+#define DMAC_DDAR1      DMAC_DDAR(1)
+#define DMAC_DTCR1      DMAC_DTCR(1)
+#define DMAC_DRSR1      DMAC_DRSR(1)
+#define DMAC_DCCSR1     DMAC_DCCSR(1)
+
+#define DMAC_DSAR2      DMAC_DSAR(2)
+#define DMAC_DDAR2      DMAC_DDAR(2)
+#define DMAC_DTCR2      DMAC_DTCR(2)
+#define DMAC_DRSR2      DMAC_DRSR(2)
+#define DMAC_DCCSR2     DMAC_DCCSR(2)
+
+#define DMAC_DSAR3      DMAC_DSAR(3)
+#define DMAC_DDAR3      DMAC_DDAR(3)
+#define DMAC_DTCR3      DMAC_DTCR(3)
+#define DMAC_DRSR3      DMAC_DRSR(3)
+#define DMAC_DCCSR3     DMAC_DCCSR(3)
+
+#define DMAC_DSAR4      DMAC_DSAR(4)
+#define DMAC_DDAR4      DMAC_DDAR(4)
+#define DMAC_DTCR4      DMAC_DTCR(4)
+#define DMAC_DRSR4      DMAC_DRSR(4)
+#define DMAC_DCCSR4     DMAC_DCCSR(4)
+
+#define DMAC_DSAR5      DMAC_DSAR(5)
+#define DMAC_DDAR5      DMAC_DDAR(5)
+#define DMAC_DTCR5      DMAC_DTCR(5)
+#define DMAC_DRSR5      DMAC_DRSR(5)
+#define DMAC_DCCSR5     DMAC_DCCSR(5)
+
+#define DMAC_DSAR6      DMAC_DSAR(6)
+#define DMAC_DDAR6      DMAC_DDAR(6)
+#define DMAC_DTCR6      DMAC_DTCR(6)
+#define DMAC_DRSR6      DMAC_DRSR(6)
+#define DMAC_DCCSR6     DMAC_DCCSR(6)
+
+#define DMAC_DSAR7      DMAC_DSAR(7)
+#define DMAC_DDAR7      DMAC_DDAR(7)
+#define DMAC_DTCR7      DMAC_DTCR(7)
+#define DMAC_DRSR7      DMAC_DRSR(7)
+#define DMAC_DCCSR7     DMAC_DCCSR(7)
+
+#endif /* __ASM_MACH_XBURST_DMA_JZ4730_H */
diff --git a/arch/mips/include/asm/mach-xburst/irq-jz4730.h b/arch/mips/include/asm/mach-xburst/irq-jz4730.h
new file mode 100644
index 0000000..087b99e
--- /dev/null
+++ b/arch/mips/include/asm/mach-xburst/irq-jz4730.h
@@ -0,0 +1,33 @@
+#ifndef __ASM_MACH_XBURST_IRQ_JZ4730_H
+#define __ASM_MACH_XBURST_IRQ_JZ4730_H
+
+#define IRQ_I2C		1
+#define IRQ_PS2		2
+#define IRQ_UPRT	3
+#define IRQ_CORE	4
+#define IRQ_UART3	6
+#define IRQ_UART2	7
+#define IRQ_UART1	8
+#define IRQ_UART0	9
+#define IRQ_SCC1	10
+#define IRQ_SCC0	11
+#define IRQ_UDC		12
+#define IRQ_UHC		13
+#define IRQ_MSC		14
+#define IRQ_RTC		15
+#define IRQ_FIR		16
+#define IRQ_SSI		17
+#define IRQ_CIM		18
+#define IRQ_ETH		19
+#define IRQ_AIC		20
+#define IRQ_DMAC	21
+#define IRQ_OST2	22
+#define IRQ_OST1	23
+#define IRQ_OST0	24
+#define IRQ_GPIO3	25
+#define IRQ_GPIO2	26
+#define IRQ_GPIO1	27
+#define IRQ_GPIO0	28
+#define IRQ_LCD		30
+
+#endif /* __ASM_MACH_XBURST_IRQ_JZ4730_H */
diff --git a/arch/mips/include/asm/mach-xburst/uart-jz4730.h b/arch/mips/include/asm/mach-xburst/uart-jz4730.h
new file mode 100644
index 0000000..f7f6fcd
--- /dev/null
+++ b/arch/mips/include/asm/mach-xburst/uart-jz4730.h
@@ -0,0 +1,141 @@
+/*
+ *  UART registers for jz4730.
+ *
+ *  Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_XBURST_UART_JZ4730_H
+#define __ASM_MACH_XBURST_UART_JZ4730_H
+
+#define	UART0_BASE	0xB0030000
+#define	UART1_BASE	0xB0031000
+#define	UART2_BASE	0xB0032000
+#define	UART3_BASE	0xB0033000
+
+/* register offset */
+#define OFF_RDR		0x00	/* R  8b H'xx */
+#define OFF_TDR		0x00	/* W  8b H'xx */
+#define OFF_DLLR	0x00	/* RW 8b H'00 */
+#define OFF_DLHR	0x04	/* RW 8b H'00 */
+#define OFF_IER		0x04	/* RW 8b H'00 */
+#define OFF_ISR		0x08	/* R  8b H'01 */
+#define OFF_FCR		0x08	/* W  8b H'00 */
+#define OFF_LCR		0x0C	/* RW 8b H'00 */
+#define OFF_MCR		0x10	/* RW 8b H'00 */
+#define OFF_LSR		0x14	/* R  8b H'00 */
+#define OFF_MSR		0x18	/* R  8b H'00 */
+#define OFF_SPR		0x1C	/* RW 8b H'00 */
+#define OFF_MCR		0x10	/* RW 8b H'00 */
+#define OFF_SIRCR	0x20	/* RW 8b H'00, UART0 */
+
+/*
+ * Define macros for UARTIER
+ * UART Interrupt Enable Register
+ */
+#define UARTIER_RIE	(1 << 0)	/* 0: receive fifo "full" interrupt disable */
+#define UARTIER_TIE	(1 << 1)	/* 0: transmit fifo "empty" interrupt disable */
+#define UARTIER_RLIE	(1 << 2)	/* 0: receive line status interrupt disable */
+#define UARTIER_MIE	(1 << 3)	/* 0: modem status interrupt disable */
+#define UARTIER_RTIE	(1 << 4)	/* 0: receive timeout interrupt disable */
+
+/*
+ * Define macros for UARTISR
+ * UART Interrupt Status Register
+ */
+#define UARTISR_IP	(1 << 0)	/* 0: interrupt is pending  1: no interrupt */
+#define UARTISR_IID	(7 << 1)	/* Source of Interrupt */
+#define UARTISR_IID_MSI		(0 << 1)	/* Modem status interrupt */
+#define UARTISR_IID_THRI	(1 << 1)	/* Transmitter holding register empty */
+#define UARTISR_IID_RDI		(2 << 1)	/* Receiver data interrupt */
+#define UARTISR_IID_RLSI	(3 << 1)	/* Receiver line status interrupt */
+#define UARTISR_FFMS	(3 << 6)	/* FIFO mode select, set when UARTFCR.FE is set to 1 */
+#define UARTISR_FFMS_NO_FIFO	(0 << 6)
+#define UARTISR_FFMS_FIFO_MODE	(3 << 6)
+
+/*
+ * Define macros for UARTFCR
+ * UART FIFO Control Register
+ */
+#define UARTFCR_FE	(1 << 0)	/* 0: non-FIFO mode  1: FIFO mode */
+#define UARTFCR_RFLS	(1 << 1)	/* write 1 to flush receive FIFO */
+#define UARTFCR_TFLS	(1 << 2)	/* write 1 to flush transmit FIFO */
+#define UARTFCR_DMS	(1 << 3)	/* 0: disable DMA mode */
+#define UARTFCR_UUE	(1 << 4)	/* 0: disable UART */
+#define UARTFCR_RTRG	(3 << 6)	/* Receive FIFO Data Trigger */
+#define UARTFCR_RTRG_1	(0 << 6)
+#define UARTFCR_RTRG_4	(1 << 6)
+#define UARTFCR_RTRG_8	(2 << 6)
+#define UARTFCR_RTRG_15	(3 << 6)
+
+/*
+ * Define macros for UARTLCR
+ * UART Line Control Register
+ */
+#define UARTLCR_WLEN	(3 << 0)	/* word length */
+#define UARTLCR_WLEN_5	(0 << 0)
+#define UARTLCR_WLEN_6	(1 << 0)
+#define UARTLCR_WLEN_7	(2 << 0)
+#define UARTLCR_WLEN_8	(3 << 0)
+#define UARTLCR_STOP	(1 << 2)	/* 0: 1 stop bit when word length is 5,6,7,8
+					   1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */
+#define UARTLCR_PE	(1 << 3)	/* 0: parity disable */
+#define UARTLCR_PROE	(1 << 4)	/* 0: even parity  1: odd parity */
+#define UARTLCR_SPAR	(1 << 5)	/* 0: sticky parity disable */
+#define UARTLCR_SBRK	(1 << 6)	/* write 0 normal, write 1 send break */
+#define UARTLCR_DLAB	(1 << 7)	/* 0: access UARTRDR/TDR/IER  1: access UARTDLLR/DLHR */
+
+/*
+ * Define macros for UARTLSR
+ * UART Line Status Register
+ */
+#define UARTLSR_DR	(1 << 0)	/* 0: receive FIFO is empty  1: receive data is ready */
+#define UARTLSR_ORER	(1 << 1)	/* 0: no overrun error */
+#define UARTLSR_PER	(1 << 2)	/* 0: no parity error */
+#define UARTLSR_FER	(1 << 3)	/* 0; no framing error */
+#define UARTLSR_BRK	(1 << 4)	/* 0: no break detected  1: receive a break signal */
+#define UARTLSR_TDRQ	(1 << 5)	/* 1: transmit FIFO half "empty" */
+#define UARTLSR_TEMT	(1 << 6)	/* 1: transmit FIFO and shift registers empty */
+#define UARTLSR_RFER	(1 << 7)	/* 0: no receive error  1: receive error in FIFO mode */
+
+/*
+ * Define macros for UARTMCR
+ * UART Modem Control Register
+ */
+#define UARTMCR_DTR	(1 << 0)	/* 0: DTR_ ouput high */
+#define UARTMCR_RTS	(1 << 1)	/* 0: RTS_ output high */
+#define UARTMCR_OUT1	(1 << 2)	/* 0: UARTMSR.RI is set to 0 and RI_ input high */
+#define UARTMCR_OUT2	(1 << 3)	/* 0: UARTMSR.DCD is set to 0 and DCD_ input high */
+#define UARTMCR_LOOP	(1 << 4)	/* 0: normal  1: loopback mode */
+#define UARTMCR_MCE	(1 << 7)	/* 0: modem function is disable */
+
+/*
+ * Define macros for UARTMSR
+ * UART Modem Status Register
+ */
+#define UARTMSR_DCTS	(1 << 0)	/* 0: no change on CTS_ pin since last read of UARTMSR */
+#define UARTMSR_DDSR	(1 << 1)	/* 0: no change on DSR_ pin since last read of UARTMSR */
+#define UARTMSR_DRI	(1 << 2)	/* 0: no change on RI_ pin since last read of UARTMSR */
+#define UARTMSR_DDCD	(1 << 3)	/* 0: no change on DCD_ pin since last read of UARTMSR */
+#define UARTMSR_CTS	(1 << 4)	/* 0: CTS_ pin is high */
+#define UARTMSR_DSR	(1 << 5)	/* 0: DSR_ pin is high */
+#define UARTMSR_RI	(1 << 6)	/* 0: RI_ pin is high */
+#define UARTMSR_DCD	(1 << 7)	/* 0: DCD_ pin is high */
+
+/*
+ * Define macros for SIRCR
+ * Slow IrDA Control Register
+ */
+#define SIRCR_TSIRE	(1 << 0)	/* 0: transmitter is in UART mode  1: IrDA mode */
+#define SIRCR_RSIRE	(1 << 1)	/* 0: receiver is in UART mode  1: IrDA mode */
+#define SIRCR_TPWS	(1 << 2)	/* 0: transmit 0 pulse width is 3/16 of bit length
+					   1: 0 pulse width is 1.6us for 115.2Kbps */
+#define SIRCR_TXPL	(1 << 3)	/* 0: encoder generates a positive pulse for 0 */
+#define SIRCR_RXPL	(1 << 4)	/* 0: decoder interprets positive pulse as 0 */
+
+
+
+#endif /* __ASM_MACH_XBURST_UART_JZ4730_H */
diff --git a/arch/mips/include/asm/mach-xburst/war.h b/arch/mips/include/asm/mach-xburst/war.h
new file mode 100644
index 0000000..5acdf58
--- /dev/null
+++ b/arch/mips/include/asm/mach-xburst/war.h
@@ -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_MACH_XBURST_WAR_H
+#define __ASM_MACH_XBURST_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_MACH_XBURST_WAR_H */
diff --git a/arch/mips/include/asm/mach-xburst/xburst.h b/arch/mips/include/asm/mach-xburst/xburst.h
new file mode 100644
index 0000000..4b2c40c
--- /dev/null
+++ b/arch/mips/include/asm/mach-xburst/xburst.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_XBURST_H
+#define __ASM_XBURST_H
+
+#ifdef CONFIG_XBURST_JZ4730
+#include "clock-jz4730.h"
+#include "irq-jz4730.h"
+#include "uart-jz4730.h"
+#endif
+
+void jz_usb0_set_function(int host);
+
+#endif /* __ASM_XBURST_H */
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 387bf59..f0bb7c3 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -17,6 +17,59 @@
 #include <asm/cpu-features.h>
 #include <asm/mipsmtregs.h>
 
+#ifdef CONFIG_XBURST
+
+#define K0_TO_K1()				\
+do {						\
+	unsigned long __k0_addr;		\
+						\
+	__asm__ __volatile__(			\
+	"la %0, 1f\n\t"				\
+	"or	%0, %0, %1\n\t"			\
+	"jr	%0\n\t"				\
+	"nop\n\t"				\
+	"1: nop\n"				\
+	: "=&r"(__k0_addr)			\
+	: "r" (0x20000000) );			\
+} while(0)
+
+#define K1_TO_K0()				\
+do {						\
+	unsigned long __k0_addr;		\
+	__asm__ __volatile__(			\
+	"nop;nop;nop;nop;nop;nop;nop\n\t"	\
+	"la %0, 1f\n\t"				\
+	"jr	%0\n\t"				\
+	"nop\n\t"				\
+	"1:	nop\n"				\
+	: "=&r" (__k0_addr));			\
+} while (0)
+
+#define INVALIDATE_BTB()			\
+do {						\
+	unsigned long tmp;			\
+	__asm__ __volatile__(			\
+	".set mips32\n\t"			\
+	"mfc0 %0, $16, 7\n\t"			\
+	"nop\n\t"				\
+	"ori %0, 2\n\t"				\
+	"mtc0 %0, $16, 7\n\t"			\
+	"nop\n\t"				\
+	: "=&r" (tmp));				\
+} while (0)
+
+#define SYNC_WB() __asm__ __volatile__ ("sync")
+
+#else /* CONFIG_XBURST */
+
+#define K0_TO_K1() do { } while (0)
+#define K1_TO_K0() do { } while (0)
+#define INVALIDATE_BTB() do { } while (0)
+#define SYNC_WB() do { } while (0)
+
+#endif /* CONFIG_XBURST */
+
+
 /*
  * This macro return a properly sign-extended address suitable as base address
  * for indexed cache operations.  Two issues here:
@@ -144,6 +197,7 @@ static inline void flush_icache_line_indexed(unsigned long addr)
 {
 	__iflush_prologue
 	cache_op(Index_Invalidate_I, addr);
+	INVALIDATE_BTB();
 	__iflush_epilogue
 }
 
@@ -151,6 +205,7 @@ static inline void flush_dcache_line_indexed(unsigned long addr)
 {
 	__dflush_prologue
 	cache_op(Index_Writeback_Inv_D, addr);
+	SYNC_WB();
 	__dflush_epilogue
 }
 
@@ -163,6 +218,7 @@ static inline void flush_icache_line(unsigned long addr)
 {
 	__iflush_prologue
 	cache_op(Hit_Invalidate_I, addr);
+	INVALIDATE_BTB();
 	__iflush_epilogue
 }
 
@@ -170,6 +226,7 @@ static inline void flush_dcache_line(unsigned long addr)
 {
 	__dflush_prologue
 	cache_op(Hit_Writeback_Inv_D, addr);
+	SYNC_WB();
 	__dflush_epilogue
 }
 
@@ -177,6 +234,7 @@ static inline void invalidate_dcache_line(unsigned long addr)
 {
 	__dflush_prologue
 	cache_op(Hit_Invalidate_D, addr);
+	SYNC_WB();
 	__dflush_epilogue
 }
 
@@ -209,6 +267,7 @@ static inline void flush_scache_line(unsigned long addr)
 static inline void protected_flush_icache_line(unsigned long addr)
 {
 	protected_cache_op(Hit_Invalidate_I, addr);
+	INVALIDATE_BTB();
 }
 
 /*
@@ -220,6 +279,7 @@ static inline void protected_flush_icache_line(unsigned long addr)
 static inline void protected_writeback_dcache_line(unsigned long addr)
 {
 	protected_cache_op(Hit_Writeback_Inv_D, addr);
+	SYNC_WB();
 }
 
 static inline void protected_writeback_scache_line(unsigned long addr)
@@ -396,8 +456,12 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
+
+#ifndef CONFIG_XBURST
 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
+#endif
+
 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
@@ -405,12 +469,124 @@ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
 
 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
+
+#ifndef CONFIG_XBURST
 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
+#endif
+
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
 
+#ifdef CONFIG_XBURST
+
+static inline void blast_dcache32(void)
+{
+	unsigned long start = INDEX_BASE;
+	unsigned long end = start + current_cpu_data.dcache.waysize;
+	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
+	unsigned long ws_end = current_cpu_data.dcache.ways <<
+	                       current_cpu_data.dcache.waybit;
+	unsigned long ws, addr;
+
+	for (ws = 0; ws < ws_end; ws += ws_inc)
+		for (addr = start; addr < end; addr += 0x400)
+			cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
+
+	SYNC_WB();
+}
+
+static inline void blast_dcache32_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	do {
+		cache32_unroll32(start,Hit_Writeback_Inv_D);
+		start += 0x400;
+	} while (start < end);
+
+	SYNC_WB();
+}
+
+static inline void blast_dcache32_page_indexed(unsigned long page)
+{
+	unsigned long indexmask = current_cpu_data.dcache.waysize - 1;
+	unsigned long start = INDEX_BASE + (page & indexmask);
+	unsigned long end = start + PAGE_SIZE;
+	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
+	unsigned long ws_end = current_cpu_data.dcache.ways <<
+	                       current_cpu_data.dcache.waybit;
+	unsigned long ws, addr;
+
+	for (ws = 0; ws < ws_end; ws += ws_inc)
+		for (addr = start; addr < end; addr += 0x400)
+			cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
+
+	SYNC_WB();
+}
+
+static inline void blast_icache32(void)
+{
+	unsigned long start = INDEX_BASE;
+	unsigned long end = start + current_cpu_data.icache.waysize;
+	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+	unsigned long ws_end = current_cpu_data.icache.ways <<
+	                       current_cpu_data.icache.waybit;
+	unsigned long ws, addr;
+
+	K0_TO_K1();
+
+	for (ws = 0; ws < ws_end; ws += ws_inc)
+		for (addr = start; addr < end; addr += 0x400)
+			cache32_unroll32(addr|ws,Index_Invalidate_I);
+
+	INVALIDATE_BTB();
+
+	K1_TO_K0();
+}
+
+static inline void blast_icache32_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	K0_TO_K1();
+
+	do {
+		cache32_unroll32(start,Hit_Invalidate_I);
+		start += 0x400;
+	} while (start < end);
+
+	INVALIDATE_BTB();
+
+	K1_TO_K0();
+}
+
+static inline void blast_icache32_page_indexed(unsigned long page)
+{
+	unsigned long indexmask = current_cpu_data.icache.waysize - 1;
+	unsigned long start = INDEX_BASE + (page & indexmask);
+	unsigned long end = start + PAGE_SIZE;
+	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+	unsigned long ws_end = current_cpu_data.icache.ways <<
+	                       current_cpu_data.icache.waybit;
+	unsigned long ws, addr;
+
+	K0_TO_K1();
+
+	for (ws = 0; ws < ws_end; ws += ws_inc)
+		for (addr = start; addr < end; addr += 0x400)
+			cache32_unroll32(addr|ws,Index_Invalidate_I);
+
+	INVALIDATE_BTB();
+
+	K1_TO_K0();
+}
+
+#endif /* CONFIG_XBURST */
+
 /* build blast_xxx_range, protected_blast_xxx_range */
 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
@@ -432,13 +608,77 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
 	__##pfx##flush_epilogue						\
 }
 
+#ifndef CONFIG_XBURST
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
+#endif
+
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
+
+#ifndef CONFIG_XBURST
 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
+#endif
+
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
 /* blast_inv_dcache_range */
 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
 
+
+#ifdef CONFIG_XBURST
+
+static inline void protected_blast_dcache_range(unsigned long start,
+						unsigned long end)
+{
+	unsigned long lsize = cpu_dcache_line_size();
+	unsigned long addr = start & ~(lsize - 1);
+	unsigned long aend = (end - 1) & ~(lsize - 1);
+
+	while (1) {
+		protected_cache_op(Hit_Writeback_Inv_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+	SYNC_WB();
+}
+
+static inline void protected_blast_icache_range(unsigned long start,
+						unsigned long end)
+{
+	unsigned long lsize = cpu_icache_line_size();
+	unsigned long addr = start & ~(lsize - 1);
+	unsigned long aend = (end - 1) & ~(lsize - 1);
+
+	K0_TO_K1();
+
+	while (1) {
+		protected_cache_op(Hit_Invalidate_I, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+	INVALIDATE_BTB();
+
+	K1_TO_K0();
+}
+
+static inline void blast_dcache_range(unsigned long start,
+				      unsigned long end)
+{
+	unsigned long lsize = cpu_dcache_line_size();
+	unsigned long addr = start & ~(lsize - 1);
+	unsigned long aend = (end - 1) & ~(lsize - 1);
+
+	while (1) {
+		cache_op(Hit_Writeback_Inv_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+	SYNC_WB();
+}
+
+#endif /* CONFIG_XBURST */
+
 #endif /* _ASM_R4KCACHE_H */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 758ad42..89a9468 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -162,6 +162,7 @@ void __init check_wait(void)
 	case CPU_BCM6348:
 	case CPU_BCM6358:
 	case CPU_CAVIUM_OCTEON:
+	case CPU_XBURST:
 		cpu_wait = r4k_wait;
 		break;
 
@@ -913,6 +914,23 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
 	}
 }
 
+static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
+{
+	decode_configs(c);
+	c->options &= ~MIPS_CPU_COUNTER; /* XBurst has no CP0 counter. */
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_XBURST:
+		c->cputype = CPU_XBURST;
+		c->isa_level = MIPS_CPU_ISA_M32R1;
+		c->tlbsize = 32;
+		__cpu_name[cpu] = "Ingenic XBurst";
+		break;
+	default:
+		panic("Unknown Ingenic Processor ID!");
+		break;
+	}
+}
+
 const char *__cpu_name[NR_CPUS];
 
 __cpuinit void cpu_probe(void)
@@ -950,6 +968,9 @@ __cpuinit void cpu_probe(void)
 	case PRID_COMP_CAVIUM:
 		cpu_probe_cavium(c, cpu);
 		break;
+	case PRID_COMP_INGENIC:
+		cpu_probe_ingenic(c, cpu);
+		break;
 	}
 
 	BUG_ON(!__cpu_name[cpu]);
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 6721ee2..8cae4e3 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -928,6 +928,36 @@ static void __cpuinit probe_pcache(void)
 		c->dcache.waybit = 0;
 		break;
 
+	case CPU_XBURST:
+		config1 = read_c0_config1();
+		config1 = (config1 >> 22) & 0x07;
+		if (config1 == 0x07)
+			config1 = 10;
+		else
+			config1 = config1 + 11;
+		config1 += 2;
+		icache_size = (1 << config1);
+		c->icache.linesz = 32;
+		c->icache.ways = 4;
+		c->icache.waybit = __ffs(icache_size / c->icache.ways);
+
+		config1 = read_c0_config1();
+		config1 = (config1 >> 13) & 0x07;
+		if (config1 == 0x07)
+			config1 = 10;
+		else
+			config1 = config1 + 11;
+		config1 += 2;
+		dcache_size = (1 << config1);
+		c->dcache.linesz = 32;
+		c->dcache.ways = 4;
+		c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
+
+		c->dcache.flags = 0;
+		c->options |= MIPS_CPU_PREFETCH;
+
+		break;
+
 	default:
 		if (!(config & MIPS_CONF_M))
 			panic("Don't know how to probe P-caches on this cpu.");
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index badcf5e..34ef8c9 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -390,6 +390,11 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
 		tlbw(p);
 		break;
 
+	case CPU_XBURST:
+		tlbw(p);
+		uasm_i_nop(p);
+		break;
+
 	default:
 		panic("No TLB refill handler yet (CPU type: %d)",
 		      current_cpu_data.cputype);
diff --git a/arch/mips/xburst/Kconfig b/arch/mips/xburst/Kconfig
new file mode 100644
index 0000000..fc12741
--- /dev/null
+++ b/arch/mips/xburst/Kconfig
@@ -0,0 +1,23 @@
+choice
+	prompt "XBurst SoC Type"
+	depends on XBURST
+
+config XBURST_JZ4730
+	bool "Ingenic JZ4730"
+
+#config XBURST_JZ4740
+#	bool "Ingenic JZ4740"
+
+endchoice
+
+choice
+	prompt "JZ4730 board"
+	depends on XBURST_JZ4730
+
+config JZ4730_PMP
+	bool "Ingenic PMP reference board"
+
+config JZ4730_LIBRA
+	bool "Ingenic Libra dev board"
+
+endchoice
diff --git a/arch/mips/xburst/Makefile b/arch/mips/xburst/Makefile
new file mode 100644
index 0000000..a96d462
--- /dev/null
+++ b/arch/mips/xburst/Makefile
@@ -0,0 +1,3 @@
+#
+# jz4730 SoC based systems
+obj-$(CONFIG_XBURST_JZ4730) += jz4730/
diff --git a/arch/mips/xburst/jz4730/Makefile b/arch/mips/xburst/jz4730/Makefile
new file mode 100644
index 0000000..100c64b
--- /dev/null
+++ b/arch/mips/xburst/jz4730/Makefile
@@ -0,0 +1,11 @@
+#
+# JZ4730 SoC based systems.
+#
+
+obj-y += irq.o prom.o setup.o time.o clocks.o platform.o
+
+# Ingenic's Libra dev board
+obj-$(CONFIG_JZ4730_LIBRA)	+= board-libra.o
+
+# Ingenic's Portable Media Player reference platform
+obj-$(CONFIG_JZ4730_PMP)	+= board-pmp.o
diff --git a/arch/mips/xburst/jz4730/board-libra.c b/arch/mips/xburst/jz4730/board-libra.c
new file mode 100644
index 0000000..795bdd5
--- /dev/null
+++ b/arch/mips/xburst/jz4730/board-libra.c
@@ -0,0 +1,32 @@
+/*
+ * board-libra.c
+ *
+ * Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <xburst.h>
+
+void __init
+jz_board_get_extal(struct jz_clocks *cks)
+{
+	cks->extal = 3686400;	/* 3.6864 MHz */
+	cks->extal2 = 32768;	/* 32.768 KHz */
+}
+
+void __init
+jz_board_setup(void)
+{
+	/*
+	 * USB is much more reliable using the external USB clock,
+	 * not the PLL divider.
+	 */
+	jz_cpm_set_usbclk(1);
+
+	/* USB0 as host. */
+	jz_usb0_set_function(1);
+}
diff --git a/arch/mips/xburst/jz4730/board-pmp.c b/arch/mips/xburst/jz4730/board-pmp.c
new file mode 100644
index 0000000..90c5692
--- /dev/null
+++ b/arch/mips/xburst/jz4730/board-pmp.c
@@ -0,0 +1,32 @@
+/*
+ * board-pmp.c
+ *
+ * Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <xburst.h>
+
+void __init
+jz_board_get_extal(struct jz_clocks *cks)
+{
+	cks->extal = 12000000;	/* 12 MHz */
+	cks->extal2 = 32768;	/* 32.768 KHz */
+}
+
+void __init
+jz_board_setup(void)
+{
+	/*
+	 * USB is much more reliable using the external USB clock,
+	 * not the PLL divider.
+	 */
+	jz_cpm_set_usbclk(1);
+
+	/* USB0 as device. */
+	jz_usb0_set_function(0);
+}
diff --git a/arch/mips/xburst/jz4730/clocks.c b/arch/mips/xburst/jz4730/clocks.c
new file mode 100644
index 0000000..abc887f
--- /dev/null
+++ b/arch/mips/xburst/jz4730/clocks.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *
+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc.
+ * Author: <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <xburst.h>
+
+extern void __init jz_board_get_extal(struct jz_clocks *);
+
+struct jz_clocks jz_clocks;
+EXPORT_SYMBOL(jz_clocks);
+
+static void __iomem *cpm_base;
+
+#define	CPM_BASE	0x10000000
+
+#define CPM_CFCR	0x00
+#define CPM_LPCR	0x04
+#define CPM_RSTR	0x08
+#define CPM_PLCR1	0x10
+#define CPM_OCR		0x1c
+#define CPM_MSCR	0x20
+#define CPM_SCR		0x24
+#define CPM_WRER	0x28
+#define CPM_WFER	0x2c
+#define CPM_WER		0x30
+#define CPM_WSR		0x34
+#define CPM_GSR0	0x38
+#define CPM_GSR1	0x3c
+#define CPM_GSR2	0x40
+#define CPM_SPR		0x44
+#define CPM_GSR3	0x48
+#define CPM_CFCR2	0x60
+
+#define CPM_CFCR_SSI		(1 << 31)
+#define CPM_CFCR_LCD		(1 << 30)
+#define CPM_CFCR_I2S		(1 << 29)
+#define CPM_CFCR_UCS		(1 << 28)
+#define CPM_CFCR_UFR_BIT	25
+#define CPM_CFCR_UFR_MASK	(0x07 << CPM_CFCR_UFR_BIT)
+#define CPM_CFCR_MSC		(1 << 24)
+#define CPM_CFCR_CKOEN2		(1 << 23)
+#define CPM_CFCR_CKOEN1		(1 << 22)
+#define CPM_CFCR_UPE		(1 << 20)
+#define CPM_CFCR_MFR_BIT	16
+#define CPM_CFCR_MFR_MASK	(0x0f << CPM_CFCR_MFR_BIT)
+#define CPM_CFCR_LFR_BIT	12
+#define CPM_CFCR_LFR_MASK	(0x0f << CPM_CFCR_LFR_BIT)
+#define CPM_CFCR_PFR_BIT	8
+#define CPM_CFCR_PFR_MASK	(0x0f << CPM_CFCR_PFR_BIT)
+#define CPM_CFCR_SFR_BIT	4
+#define CPM_CFCR_SFR_MASK	(0x0f << CPM_CFCR_SFR_BIT)
+#define CPM_CFCR_IFR_BIT	0
+#define CPM_CFCR_IFR_MASK	(0x0f << CPM_CFCR_IFR_BIT)
+
+#define CPM_PLCR1_PLL1FD_BIT	23
+#define CPM_PLCR1_PLL1FD_MASK	(0x1ff << CPM_PLCR1_PLL1FD_BIT)
+#define CPM_PLCR1_PLL1RD_BIT	18
+#define CPM_PLCR1_PLL1RD_MASK	(0x1f << CPM_PLCR1_PLL1RD_BIT)
+#define CPM_PLCR1_PLL1OD_BIT	16
+#define CPM_PLCR1_PLL1OD_MASK	(0x03 << CPM_PLCR1_PLL1OD_BIT)
+#define CPM_PLCR1_PLL1S		(1 << 10)
+#define CPM_PLCR1_PLL1BP	(1 << 9)
+#define CPM_PLCR1_PLL1EN	(1 << 8)
+#define CPM_PLCR1_PLL1ST_BIT	0
+#define CPM_PLCR1_PLL1ST_MASK	(0xff << CPM_PLCR1_PLL1ST_BIT)
+
+#define CPM_LPCR_DUTY_BIT	3
+#define CPM_LPCR_DUTY_MASK	(0x1f << CPM_LPCR_DUTY_BIT)
+#define CPM_LPCR_DOZE		(1 << 2)
+#define CPM_LPCR_LPM_BIT	0
+#define CPM_LPCR_LPM_MASK	(0x03 << CPM_LPCR_LPM_BIT)
+  #define CPM_LPCR_LPM_IDLE		(0 << CPM_LPCR_LPM_BIT)
+  #define CPM_LPCR_LPM_SLEEP		(1 << CPM_LPCR_LPM_BIT)
+  #define CPM_LPCR_LPM_HIBERNATE	(2 << CPM_LPCR_LPM_BIT)
+
+
+static __inline__ unsigned int
+cpm_get_pllout(void)
+{
+	unsigned int nf, nr, no, pllout;
+	unsigned long plcr = readl(cpm_base + CPM_PLCR1);
+	unsigned long od[4] = {1, 2, 2, 4};
+	if (plcr & CPM_PLCR1_PLL1EN) {
+		nf = (plcr & CPM_PLCR1_PLL1FD_MASK) >> CPM_PLCR1_PLL1FD_BIT;
+		nr = (plcr & CPM_PLCR1_PLL1RD_MASK) >> CPM_PLCR1_PLL1RD_BIT;
+		no = od[((plcr & CPM_PLCR1_PLL1OD_MASK) >> CPM_PLCR1_PLL1OD_BIT)];
+		pllout = (jz_clocks.extal) / ((nr+2) * no) * (nf+2);
+	} else
+		pllout = jz_clocks.extal;
+	return pllout;
+}
+
+static __inline__ unsigned int
+cpm_get_iclk(void)
+{
+	unsigned int iclk;
+	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	unsigned long plcr = readl(cpm_base + CPM_PLCR1);
+	if (plcr & CPM_PLCR1_PLL1EN)
+		iclk = cpm_get_pllout() /
+		       div[(cfcr & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT];
+	else
+		iclk = jz_clocks.extal;
+	return iclk;
+}
+
+static __inline__ unsigned int
+cpm_get_sclk(void)
+{
+	unsigned int sclk;
+	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	unsigned long plcr = readl(cpm_base + CPM_PLCR1);
+	if (plcr & CPM_PLCR1_PLL1EN)
+		sclk = cpm_get_pllout() /
+		       div[(cfcr & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT];
+	else
+		sclk = jz_clocks.extal;
+	return sclk;
+}
+
+static __inline__ unsigned int
+cpm_get_mclk(void)
+{
+	unsigned int mclk;
+	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	unsigned long plcr = readl(cpm_base + CPM_PLCR1);
+	if (plcr & CPM_PLCR1_PLL1EN)
+		mclk = cpm_get_pllout() /
+		       div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT];
+	else
+		mclk = jz_clocks.extal;
+	return mclk;
+}
+
+static __inline__ unsigned int
+cpm_get_pclk(void)
+{
+	unsigned int devclk;
+	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	unsigned long plcr = readl(cpm_base + CPM_PLCR1);
+	if (plcr & CPM_PLCR1_PLL1EN)
+		devclk = cpm_get_pllout() /
+			 div[(cfcr & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT];
+	else
+		devclk = jz_clocks.extal;
+	return devclk;
+}
+
+static __inline__ unsigned int
+cpm_get_lcdclk(void)
+{
+	unsigned int lcdclk;
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	unsigned long plcr = readl(cpm_base + CPM_PLCR1);
+	if (plcr & CPM_PLCR1_PLL1EN)
+		lcdclk = cpm_get_pllout() /
+			(((cfcr & CPM_CFCR_LFR_MASK) >> CPM_CFCR_LFR_BIT) + 1);
+	else
+		lcdclk = jz_clocks.extal;
+	return lcdclk;
+}
+
+static __inline__ unsigned int
+cpm_get_pixclk(void)
+{
+	unsigned int pixclk;
+	unsigned long cfcr2 = readl(cpm_base + CPM_CFCR2);
+	pixclk = cpm_get_pllout() / (cfcr2 + 1);
+	return pixclk;
+}
+
+static __inline__ unsigned int
+cpm_get_devclk(void)
+{
+	return jz_clocks.extal;
+}
+
+static __inline__ unsigned int
+cpm_get_rtcclk(void)
+{
+	return jz_clocks.extal2;
+}
+
+static __inline__ unsigned int
+cpm_get_uartclk(void)
+{
+	return jz_clocks.extal;
+}
+
+static __inline__ unsigned int
+cpm_get_usbclk(void)
+{
+	unsigned int usbclk;
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	if (cfcr & CPM_CFCR_UCS)
+		usbclk = 48000000;
+	else
+		usbclk = cpm_get_pllout() /
+			(((cfcr &CPM_CFCR_UFR_MASK) >> CPM_CFCR_UFR_BIT) + 1);
+	return usbclk;
+}
+
+static __inline__ unsigned int
+cpm_get_i2sclk(void)
+{
+	unsigned int i2sclk;
+	unsigned long cfcr = readl(cpm_base + CPM_CFCR);
+	i2sclk = cpm_get_pllout() /
+		((cfcr & CPM_CFCR_I2S) ? 2: 1);
+	return i2sclk;
+}
+
+static __inline__ unsigned int
+cpm_get_mscclk(void)
+{
+	if (readl(cpm_base + CPM_CFCR) & CPM_CFCR_MSC)
+		return 24000000;
+	else
+		return 16000000;
+}
+
+
+void
+jz_cpm_set_usbclk(int external)
+{
+	u32 cfcr = readl(cpm_base + CPM_CFCR);
+
+	if (external)
+		cfcr |= CPM_CFCR_UCS;
+	else
+		cfcr &= ~CPM_CFCR_UCS;
+
+	writel(cfcr, cpm_base + CPM_CFCR);
+
+	jz_clocks.usbclk = cpm_get_usbclk();
+}
+
+void __init
+jz_cpm_setup(void)
+{
+	u32 lcr, cfcr;
+
+	cpm_base = ioremap_nocache(CPM_BASE, 0xfff);
+	if (cpm_base == NULL) {
+		panic(KERN_ERR "Couldn't map CPM_BASE(0x%x)\n", CPM_BASE);
+	}
+
+	/* Enter idle mode when sleep instruction is executed. */
+	lcr = readl(cpm_base + CPM_LPCR) & ~CPM_LPCR_LPM_MASK;
+	lcr |= CPM_LPCR_LPM_IDLE;
+	writel(lcr, cpm_base + CPM_LPCR);
+
+	/* Enable SDRAM clock. */
+	cfcr = readl(cpm_base + CPM_CFCR) | CPM_CFCR_CKOEN1;
+	writel(cfcr, cpm_base + CPM_CFCR);
+
+	/* Enable all clocks. */
+	writel(0, cpm_base + CPM_MSCR);
+
+	/* Fill in jz_extal, jz_extal2. */
+	jz_board_get_extal(&jz_clocks);
+
+	jz_clocks.iclk = cpm_get_iclk();
+	jz_clocks.sclk = cpm_get_sclk();
+	jz_clocks.mclk = cpm_get_mclk();
+	jz_clocks.pclk = cpm_get_pclk();
+	jz_clocks.devclk = cpm_get_devclk();
+	jz_clocks.rtcclk = cpm_get_rtcclk();
+	jz_clocks.uartclk = cpm_get_uartclk();
+	jz_clocks.lcdclk = cpm_get_lcdclk();
+	jz_clocks.pixclk = cpm_get_pixclk();
+	jz_clocks.usbclk = cpm_get_usbclk();
+	jz_clocks.i2sclk = cpm_get_i2sclk();
+	jz_clocks.mscclk = cpm_get_mscclk();
+
+	printk("CPU clock: %dMHz, System clock: %dMHz, Memory clock: %dMHz, Peripheral clock: %dMHz\n",
+		(jz_clocks.iclk + 500000) / 1000000,
+		(jz_clocks.sclk + 500000) / 1000000,
+		(jz_clocks.mclk + 500000) / 1000000,
+		(jz_clocks.pclk + 500000) / 1000000);
+}
diff --git a/arch/mips/xburst/jz4730/irq.c b/arch/mips/xburst/jz4730/irq.c
new file mode 100644
index 0000000..7e12e69
--- /dev/null
+++ b/arch/mips/xburst/jz4730/irq.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *
+ * Copyright (c) 2006-2007  Ingenic Semiconductor Inc.
+ * Author: <jlwei@ingenic.cn>
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/system.h>
+#include <xburst.h>
+
+#define	INTC_BASE	0x10001000
+
+#define INTC_ISR	0x00
+#define INTC_IMR	0x04
+#define INTC_IMSR	0x08
+#define INTC_IMCR	0x0c
+#define INTC_IPR	0x10
+
+static void __iomem *intc_base;
+
+static void
+mask_intc_irq(unsigned int irq)
+{
+	writel(1<<irq, intc_base + INTC_IMSR);
+}
+
+static void
+unmask_intc_irq(unsigned int irq)
+{
+	writel(1<<irq, intc_base + INTC_IMCR);
+}
+
+static void
+ack_intc_irq(unsigned int irq)
+{
+	writel(1<<irq, intc_base + INTC_IPR);
+}
+
+static void
+end_intc_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+		unmask_intc_irq(irq);
+	}
+}
+
+static struct irq_chip intc_irq_type = {
+	.name = "INTC",
+	.mask = mask_intc_irq,
+	.unmask = unmask_intc_irq,
+	.ack = ack_intc_irq,
+	.end = end_intc_irq,
+};
+
+asmlinkage void
+plat_irq_dispatch(void)
+{
+	int irq;
+	static u32 pending = 0;
+
+	pending |= readl(intc_base + INTC_IPR);
+
+	if (!pending)
+		return;
+
+	irq = ffs(pending) - 1;
+	pending &= ~(1<<irq);
+
+	switch (irq) {
+		case IRQ_GPIO0:
+		case IRQ_GPIO1:
+		case IRQ_GPIO2:
+		case IRQ_GPIO3:
+		case IRQ_DMAC:
+			/* unhandled for now */
+			printk(KERN_WARNING "%s: %d unhandled\n", __FUNCTION__,
+					irq);
+			return;
+	}
+
+	generic_handle_irq(irq);
+}
+
+void __init
+arch_init_irq(void)
+{
+	int i;
+
+	intc_base = ioremap_nocache(INTC_BASE, 0xfff);
+
+	for (i=0; i<32; i++) {
+		mask_intc_irq(i);
+		set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+	}
+}
+
diff --git a/arch/mips/xburst/jz4730/platform.c b/arch/mips/xburst/jz4730/platform.c
new file mode 100644
index 0000000..cff660a
--- /dev/null
+++ b/arch/mips/xburst/jz4730/platform.c
@@ -0,0 +1,49 @@
+/*
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <xburst.h>
+
+#define	ETH_BASE	0x13100000
+
+static struct resource jz_eth_resources[] = {
+	[0] = {
+		.start	= ETH_BASE,
+		.end	= ETH_BASE + 0xffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_ETH,
+		.end	= IRQ_ETH,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 jz_eth_dmamask = ~(u32)0;
+
+static struct platform_device jz_eth_device = {
+	.name	= "jz-eth",
+	.id	= 0,
+	.dev = {
+		.dma_mask		= &jz_eth_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(jz_eth_resources),
+	.resource	= jz_eth_resources,
+};
+
+static struct platform_device *jz4730_devices[] __initdata = {
+	&jz_eth_device,
+};
+
+static int __init
+jz4730_platform_init(void)
+{
+	return platform_add_devices(jz4730_devices, ARRAY_SIZE(jz4730_devices));
+}
+
+arch_initcall(jz4730_platform_init);
diff --git a/arch/mips/xburst/jz4730/prom.c b/arch/mips/xburst/jz4730/prom.c
new file mode 100644
index 0000000..60c46bc
--- /dev/null
+++ b/arch/mips/xburst/jz4730/prom.c
@@ -0,0 +1,104 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, supports YAMON and U-Boot.
+ *
+ * Copyright 2000, 2001, 2006 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <xburst.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+char *prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+void prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+	        strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	if (prom_argc > 1)
+		*cp = '\0';
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init prom_init(void)
+{
+	prom_argc = (int) fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
+
+	mips_machtype = MACH_XBURST_JZ4730;
+
+	prom_init_cmdline();
+	add_memory_region(0, 0x04000000, BOOT_MEM_RAM);
+}
+
+/* used by early printk */
+void prom_putchar(char c)
+{
+	volatile u8 *uart_lsr = (volatile u8 *)(UART3_BASE + OFF_LSR);
+	volatile u8 *uart_tdr = (volatile u8 *)(UART3_BASE + OFF_TDR);
+
+	/* Wait for fifo to shift out some bytes */
+	while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
+
+	*uart_tdr = (u8)c;
+}
+
+const char *get_system_type(void)
+{
+        return "JZ4730";
+}
diff --git a/arch/mips/xburst/jz4730/setup.c b/arch/mips/xburst/jz4730/setup.c
new file mode 100644
index 0000000..777ac27
--- /dev/null
+++ b/arch/mips/xburst/jz4730/setup.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *
+ * Copyright (C) 2006-2007  Ingenic Semiconductor Inc.
+ * Author: <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <asm/mips-boards/prom.h>
+#include <xburst.h>
+
+extern void __init jz_board_setup(void);
+extern void __init jz_cpm_setup(void);
+
+/* System Bus Arbiter control*/
+#define	SBA_CNTL	0x13000000
+void __iomem *sba_cntl;
+
+#define	DMAC_BASE	0x13020000
+#define DMAC_DMACR	0xfc
+#define DMAC_DMACR_PR_BIT	8
+#define DMAC_DMACR_PR_MASK	(0x03 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_01234567	(0 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_02314675	(1 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_20136457	(2 << DMAC_DMACR_PR_BIT)
+  #define DMAC_DMACR_PR_ROUNDROBIN	(3 << DMAC_DMACR_PR_BIT)
+#define DMAC_DMACR_HTR		(1 << 3)
+#define DMAC_DMACR_AER		(1 << 2)
+#define DMAC_DMACR_DME		(1 << 0)
+
+
+static void __init
+jz_serial_setup(void)
+{
+#ifdef CONFIG_SERIAL_8250
+	struct uart_port s;
+
+	memset(&s, 0, sizeof(s));
+
+	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	s.iotype = UPIO_MEM;
+	s.regshift = 2;
+	s.uartclk = jz_clocks.uartclk;
+
+	s.line = 0;
+	s.membase = (u8 *)UART0_BASE;
+	s.irq = IRQ_UART0;
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial ttyS0 setup failed!\n");
+	}
+
+	s.line = 1;
+	s.membase = (u8 *)UART1_BASE;
+	s.irq = IRQ_UART1;
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial ttyS1 setup failed!\n");
+	}
+
+	s.line = 2;
+	s.membase = (u8 *)UART2_BASE;
+	s.irq = IRQ_UART2;
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial ttyS2 setup failed!\n");
+	}
+
+	s.line = 3;
+	s.membase = (u8 *)UART3_BASE;
+	s.irq = IRQ_UART3;
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial ttyS3 setup failed!\n");
+	}
+#endif
+}
+
+static void __init
+jz_dma_setup(void)
+{
+	void __iomem *dmac_base;
+	u32 dmacr;
+
+	dmac_base = ioremap_nocache(DMAC_BASE, 0xffff);
+	if (dmac_base == NULL) {
+		panic(KERN_ERR "Couldn't map DMAC_BASE(0x%x)\n", DMAC_BASE);
+	}
+
+	/* Set DMA priority and enable all channels. */
+	dmacr = readl(dmac_base + DMAC_DMACR);
+	dmacr |= DMAC_DMACR_DME | DMAC_DMACR_PR_ROUNDROBIN;
+	writel(dmacr, dmac_base + DMAC_DMACR);
+
+}
+
+void
+jz_usb0_set_function(int host)
+{
+	u32 sba = readl(sba_cntl);
+
+	if (host)
+		sba |= (1<<7);
+	else /* device */
+		sba &= ~(1<<7);
+
+	writel(sba, sba_cntl);
+}
+
+void __init
+plat_mem_setup(void)
+{
+	/* IO/MEM resources. */
+	set_io_port_base(0);
+	ioport_resource.start = 0x00000000;
+	ioport_resource.end = 0xffffffff;
+	iomem_resource.start = 0x00000000;
+	iomem_resource.end = 0xffffffff;
+
+	jz_cpm_setup();
+
+	sba_cntl = ioremap_nocache(SBA_CNTL, 0xffff);
+	if (sba_cntl == NULL) {
+		panic(KERN_ERR "Couldn't map SBA_CNTL(0x%x)\n", SBA_CNTL);
+	}
+
+	/* Set bus priority: DMAC > LCD > CIM > ETH > USB > CIM */
+	writel((readl(sba_cntl) & 0xfffffff0) | 0x08, sba_cntl);
+
+	jz_serial_setup();
+	jz_dma_setup();
+	jz_board_setup();
+}
diff --git a/arch/mips/xburst/jz4730/time.c b/arch/mips/xburst/jz4730/time.c
new file mode 100644
index 0000000..c3bd06a
--- /dev/null
+++ b/arch/mips/xburst/jz4730/time.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2010 Ubiq Technologies. <graham.gower@gmail.com>
+ *
+ * Copyright (c) 2006-2008  Ingenic Semiconductor Inc.
+ * Author: <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/clockchips.h>
+
+#include <xburst.h>
+
+#define	OST_BASE	0x10002000
+#define OST_TER		0x00	/* 8bit reg */
+#define OST_TRDR0	0x10
+#define OST_TCNT0	0x14
+#define OST_TCSR0	0x18	/* 16bit reg */
+#define OST_TCRB0	0x1c
+
+#define OST_TCSR_BUSY		(1 << 7)
+#define OST_TCSR_UF		(1 << 6)
+#define OST_TCSR_UIE		(1 << 5)
+#define OST_TCSR_CKS_BIT	0
+#define OST_TCSR_CKS_MASK	(0x07 << OST_TCSR_CKS_BIT)
+  #define OST_TCSR_CKS_PCLK_4	(0 << OST_TCSR_CKS_BIT)
+  #define OST_TCSR_CKS_PCLK_16	(1 << OST_TCSR_CKS_BIT)
+  #define OST_TCSR_CKS_PCLK_64	(2 << OST_TCSR_CKS_BIT)
+  #define OST_TCSR_CKS_PCLK_256	(3 << OST_TCSR_CKS_BIT)
+  #define OST_TCSR_CKS_RTCCLK	(4 << OST_TCSR_CKS_BIT)
+  #define OST_TCSR_CKS_EXTAL	(5 << OST_TCSR_CKS_BIT)
+
+static void __iomem *ost_base;
+static u32 timer_max;
+
+static cycle_t
+jz_get_cycles(struct clocksource *cs)
+{
+	u32 cnt;
+
+	cnt = readl(ost_base + OST_TCNT0);
+
+	/* Wait for clock sync. */
+	while ((readw(ost_base + OST_TCSR0) & OST_TCSR_BUSY))
+		;
+
+	cnt = readl(ost_base + OST_TCRB0);
+
+	return jiffies*(jz_clocks.extal/HZ) + (timer_max - cnt);
+}
+
+static void
+jz_set_mode(enum clock_event_mode mode,
+		struct clock_event_device *evt)
+{
+}
+
+static irqreturn_t
+jz_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *cd = dev_id;
+	u16 tcsr0;
+
+	/* ACK timer */
+	tcsr0 = readw(ost_base + OST_TCSR0);
+	tcsr0 &= ~OST_TCSR_UF;
+	writew(tcsr0, ost_base + OST_TCSR0);
+
+	cd->event_handler(cd);
+	return IRQ_HANDLED;
+}
+
+static struct clocksource jz_clocksource = {
+	.name	= "jz4730-ost0",
+	.rating	= 300,
+	.read	= jz_get_cycles,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.shift	= 10,
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct clock_event_device jz_clockevent_device = {
+	.name		= "jz4730-ckevent-ost0",
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.rating		= 300,
+	.irq		= IRQ_OST0,
+	.set_mode	= jz_set_mode,
+};
+
+static struct irqaction jz_irqaction = {
+	.name		= "jz4730-irq-ost0",
+	.handler	= jz_timer_interrupt,
+	.flags		= IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
+};
+
+void __init
+plat_time_init(void)
+{
+	ost_base = ioremap_nocache(OST_BASE, 0xfff);
+	if (ost_base == NULL) {
+		panic(KERN_ERR "Couldn't map OST_BASE(0x%x)\n", OST_BASE);
+	}
+
+	jz_clockevent_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&jz_clockevent_device);
+
+	jz_irqaction.dev_id = &jz_clockevent_device;
+	setup_irq(IRQ_OST0, &jz_irqaction);
+
+	jz_clocksource.mult = clocksource_hz2mult(jz_clocks.extal,
+					jz_clocksource.shift);
+	clocksource_register(&jz_clocksource);
+
+	timer_max = (jz_clocks.extal + (HZ>>1)) / HZ;
+
+	/* Disable timers. */
+	writeb(0, ost_base + OST_TER);
+
+	/* Use extal as the clock source, interrupt when timer 0 underflows. */
+	writew(OST_TCSR_CKS_EXTAL|OST_TCSR_UIE, ost_base + OST_TCSR0);
+
+	/* Set timer 0's reset value upon underflow. */
+	writel(timer_max, ost_base + OST_TRDR0);
+
+	/* Set timer 0's initial value. */
+	writel(timer_max, ost_base + OST_TCNT0);
+
+	/* Wait for clock sync. */
+	while ((readw(ost_base + OST_TCSR0) & OST_TCSR_BUSY))
+		;
+
+	/* Enable timer 0.*/
+	writeb(0x1, ost_base + OST_TER);
+
+}
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] 8250: serial driver changes for XBurst SoCs.
  2010-02-25  6:28 [PATCH 0/3] XBurst JZ4730 support Graham Gower
  2010-02-25  6:29 ` [PATCH 1/3] Add " Graham Gower
@ 2010-02-25  6:30 ` Graham Gower
  2010-02-25  6:31 ` [PATCH 3/3] net: add driver for JZ4730 ethernet controller Graham Gower
  2010-02-25  7:52 ` [PATCH 0/3] XBurst JZ4730 support Florian Fainelli
  3 siblings, 0 replies; 10+ messages in thread
From: Graham Gower @ 2010-02-25  6:30 UTC (permalink / raw)
  To: linux-mips


Signed-off-by: Graham Gower <graham.gower@gmail.com>
---
 drivers/serial/8250.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index e9b15c3..dfe6640 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -199,7 +199,11 @@ static const struct serial8250_config uart_config[] = {
 	[PORT_16550A] = {
 		.name		= "16550A",
 		.fifo_size	= 16,
+#ifndef CONFIG_XBURST
 		.tx_loadsz	= 16,
+#else
+		.tx_loadsz	= 8,
+#endif
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
 		.flags		= UART_CAP_FIFO,
 	},
@@ -406,6 +410,10 @@ static unsigned int mem_serial_in(struct uart_port *p, int offset)
 static void mem_serial_out(struct uart_port *p, int offset, int value)
 {
 	offset = map_8250_out_reg(p, offset) << p->regshift;
+#if defined(CONFIG_XBURST)
+	if (offset == (UART_FCR << p->regshift))
+		value |= 0x10; /* set FCR.UUE */
+#endif
 	writeb(value, p->membase + offset);
 }
 
@@ -2354,6 +2362,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
 	if (up->capabilities & UART_CAP_UUE)
 		up->ier |= UART_IER_UUE | UART_IER_RTOIE;
 
+#ifdef CONFIG_XBURST
+	up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */
+#endif
+
 	serial_out(up, UART_IER, up->ier);
 
 	if (up->capabilities & UART_CAP_EFR) {
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] net: add driver for JZ4730 ethernet controller.
  2010-02-25  6:28 [PATCH 0/3] XBurst JZ4730 support Graham Gower
  2010-02-25  6:29 ` [PATCH 1/3] Add " Graham Gower
  2010-02-25  6:30 ` [PATCH 2/3] 8250: serial driver changes for XBurst SoCs Graham Gower
@ 2010-02-25  6:31 ` Graham Gower
  2010-02-25  7:52 ` [PATCH 0/3] XBurst JZ4730 support Florian Fainelli
  3 siblings, 0 replies; 10+ messages in thread
From: Graham Gower @ 2010-02-25  6:31 UTC (permalink / raw)
  To: linux-mips


Signed-off-by: Graham Gower <graham.gower@gmail.com>
---
 drivers/net/Kconfig  |   10 +
 drivers/net/Makefile |    1 +
 drivers/net/jz_eth.c | 1232 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/jz_eth.h |  403 +++++++++++++++++
 4 files changed, 1646 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/jz_eth.c
 create mode 100644 drivers/net/jz_eth.h

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7f8ad5d..7e8060a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1951,6 +1951,16 @@ config BCM63XX_ENET
 	  This driver supports the ethernet MACs in the Broadcom 63xx
 	  MIPS chipset family (BCM63XX).
 
+config JZ_ETH
+	tristate "JZ4730/JZ5730 On-Chip Ethernet support"
+	depends on XBURST_JZ4730
+	select MII
+	help
+	  This driver supports the JZ4730/JZ5730 On-Chip Ethernet interface.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called jz_eth.
+
 source "drivers/net/fs_enet/Kconfig"
 
 source "drivers/net/octeon/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 657ccc3..da8ff86 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -141,6 +141,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_JZ_ETH) += jz_eth.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
diff --git a/drivers/net/jz_eth.c b/drivers/net/jz_eth.c
new file mode 100644
index 0000000..624c081
--- /dev/null
+++ b/drivers/net/jz_eth.c
@@ -0,0 +1,1232 @@
+/*
+ *  Jz4730/Jz5730 On-Chip ethernet driver.
+ *
+ *  Copyright (C) 2009, 2010 Ubiq Technologies <graham.gower@gmail.com>
+ *  Copyright (C) 2005 - 2007  Ingenic Semiconductor Inc.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <xburst.h>
+
+#include "jz_eth.h"
+
+#define DRV_NAME	"jz_eth"
+#define DRV_VERSION	"1.2"
+
+MODULE_AUTHOR("Peter Wei <jlwei@ingenic.cn>");
+MODULE_DESCRIPTION("JzSOC On-chip Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static void __iomem *jz_eth_base;
+static char *hwaddr = NULL;
+static int debug = -1;
+static struct mii_if_info mii_info;
+
+MODULE_PARM_DESC(debug, "i");
+MODULE_PARM_DESC(hwaddr,"s");
+
+static irqreturn_t jz_eth_interrupt(int irq, void *dev_id);
+
+static int link_check_thread (void *data);
+
+static inline void
+ring_inv(jz_desc_t ring[], int ring_index)
+{
+	unsigned long addr = (unsigned long)&ring[ring_index];
+	dma_cache_inv(addr, sizeof(jz_desc_t));
+}
+
+static inline void
+ring_wback(jz_desc_t ring[], int ring_index)
+{
+	unsigned long addr = (unsigned long)&ring[ring_index];
+	dma_cache_wback(addr, sizeof(jz_desc_t));
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		unsigned char num;
+
+		if((*str == '.') || (*str == ':'))
+			str++;
+		num = str2hexnum(*str++) << 4;
+		num |= (str2hexnum(*str++));
+		ea[i] = num;
+	}
+}
+
+static int ethaddr_cmd = 0;
+static unsigned char ethaddr_hex[6];
+
+static int __init ethernet_addr_setup(char *str)
+{
+	if (!str) {
+	        printk("ethaddr not set in command line\n");
+		return -1;
+	}
+	ethaddr_cmd = 1;
+	str2eaddr(ethaddr_hex, str);
+
+	return 0;
+}
+
+__setup("ethaddr=", ethernet_addr_setup);
+
+static int get_mac_address(struct net_device *dev)
+{
+	int i;
+	unsigned char flag0=0;
+	unsigned char flag1=0xff;
+	
+	dev->dev_addr[0] = 0xff;
+	if (hwaddr != NULL) {
+		/* insmod jz-ethc.o hwaddr=00:ef:a3:c1:00:10 */
+		str2eaddr(dev->dev_addr, hwaddr);
+	} else if (ethaddr_cmd) {
+		/* linux command line: ethaddr=00:ef:a3:c1:00:10 */
+		for (i=0; i<6; i++)
+			dev->dev_addr[i] = ethaddr_hex[i];
+	}
+
+	/* check whether valid MAC address */
+	for (i=0; i<6; i++) {
+		flag0 |= dev->dev_addr[i];
+		flag1 &= dev->dev_addr[i];
+	}
+	if ((dev->dev_addr[0] & 0xC0) || (flag0 == 0) || (flag1 == 0xff)) {
+		printk("WARNING: There is not MAC address, use default ..\n");
+		dev->dev_addr[0] = 0x00;
+		dev->dev_addr[1] = 0xef;
+		dev->dev_addr[2] = 0xa3;
+		dev->dev_addr[3] = 0xc1;
+		dev->dev_addr[4] = 0x00;
+		dev->dev_addr[5] = 0x10;
+		dev->dev_addr[5] = 0x03;
+	}
+	memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
+	if (!is_valid_ether_addr(dev->perm_addr))
+		printk(KERN_ERR "%s: ethaddr is b0rken!\n", dev->name);
+	return 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+static u32 jz_eth_curr_mode(struct net_device *dev);
+
+/*
+ * Ethernet START/STOP routines
+ */
+#define START_ETH() \
+	do { \
+		s32 val; \
+		val = readl(jz_eth_base + DMA_OMR); \
+		val |= OMR_ST | OMR_SR; \
+		writel(val, jz_eth_base + DMA_OMR); \
+	} while(0)
+
+#define STOP_ETH() \
+	do { \
+		s32 val; \
+		val = readl(jz_eth_base + DMA_OMR); \
+		val &= ~(OMR_ST|OMR_SR); \
+		writel(val, jz_eth_base + DMA_OMR); \
+	} while(0)
+
+/*
+ * Link check routines
+ */
+static void start_check(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+
+	np->thread_die = 0;
+	init_waitqueue_head(&np->thr_wait);
+	init_completion (&np->thr_exited);
+
+	np->thread = kthread_run(link_check_thread,(void *)dev,
+			"%s-linkcheck", dev->name);
+	if (IS_ERR(np->thread))
+		printk(KERN_ERR "%s: unable to start kernel thread\n", dev->name);
+}
+
+static int close_check(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	int ret = 0;
+
+	if (np->thread != NULL) {
+		np->thread_die = 1;
+		wmb();
+		ret = send_sig(SIGTERM, np->thread, 1);
+		if (ret) {
+			printk(KERN_ERR "%s: unable to signal thread\n", dev->name);
+			return 1;
+		}
+		wait_for_completion (&np->thr_exited);
+	}
+	return 0;
+}
+
+static int link_check_thread(void *data)
+{
+	struct net_device *dev=(struct net_device *)data;
+	struct jz_eth_private *np = netdev_priv(dev);
+	unsigned char current_link;
+	unsigned long timeout;
+
+	while (1) {
+		timeout = 3*HZ;
+		do {
+			timeout = interruptible_sleep_on_timeout (&np->thr_wait, timeout);
+			/* make swsusp happy with our thread */
+//			if (current->flags & PF_FREEZE)
+//				refrigerator(PF_FREEZE);
+		} while (!signal_pending (current) && (timeout > 0));
+
+		if (signal_pending (current)) {
+			spin_lock_irq(&current->sighand->siglock);
+			flush_signals(current);
+			spin_unlock_irq(&current->sighand->siglock);
+		}
+
+		if (np->thread_die)
+			break;
+		
+		current_link=mii_link_ok(&mii_info);
+		if (np->link_state!=current_link) {
+			if (current_link) {
+				printk(KERN_INFO "%s: Ethernet Link OK!\n",dev->name);
+				jz_eth_curr_mode(dev);
+				netif_carrier_on(dev);
+			}
+			else {
+				printk(KERN_WARNING "%s: Ethernet Link offline!\n",dev->name);
+				netif_carrier_off(dev);
+			}
+		}
+		np->link_state=current_link;
+
+	}
+	complete_and_exit (&np->thr_exited, 0);	
+}
+
+
+/*
+ * Reset ethernet device
+ */
+static inline void jz_eth_reset(void)
+{				
+	u32 i;					
+	i = readl(jz_eth_base + DMA_BMR);
+	writel(i | BMR_SWR, jz_eth_base + DMA_BMR);			
+	for(i = 0; i < 1000; i++) {			
+		if(!(readl(jz_eth_base + DMA_BMR) & BMR_SWR)) break;	
+		mdelay(1);			
+	}						
+}
+
+/*
+ * MII operation routines 
+ */
+static inline void mii_wait(void)
+{
+	int i;
+	for(i = 0; i < 10000; i++) {
+		if(!(readl(jz_eth_base + MAC_MIIA) & 0x1)) 
+			break;
+		mdelay(1);
+	}
+	if (i >= 10000)
+		printk("MII wait timeout : %d.\n", i);
+}
+
+static int mdio_read(struct net_device *dev,int phy_id, int location)
+{
+	u32 mii_cmd = (phy_id << 11) | (location << 6) | 1;
+	int retval = 0;
+	
+	writel(mii_cmd, jz_eth_base + MAC_MIIA);
+	mii_wait();
+	retval = readl(jz_eth_base + MAC_MIID) & 0x0000ffff;
+
+	return retval;
+	
+}
+
+static void mdio_write(struct net_device *dev,int phy_id, int location, int data)
+{
+	u32 mii_cmd = (phy_id << 11) | (location << 6) | 0x2 /*| 1*/;
+
+	writel(mii_cmd, jz_eth_base + MAC_MIIA);
+	writel(data & 0x0000ffff, jz_eth_base + MAC_MIID);
+	mii_cmd = (phy_id << 11) | (location << 6) | 0x2 | 1;
+	writel(mii_cmd, jz_eth_base + MAC_MIIA);
+	mii_wait();
+}
+
+
+/*
+ * Search MII phy
+ */
+static int jz_search_mii_phy(struct net_device *dev)
+{
+	
+	struct jz_eth_private *np = netdev_priv(dev);
+	int phy, phy_idx = 0;
+
+	np->valid_phy = 0xff;
+	for (phy = 0; phy < 32; phy++) {
+		int mii_status = mdio_read(dev,phy, 1);
+		if (mii_status != 0xffff  &&  mii_status != 0x0000) {
+			np->phys[phy_idx] = phy;
+			np->ecmds[phy_idx].speed=SPEED_100;
+			np->ecmds[phy_idx].duplex=DUPLEX_FULL;
+			np->ecmds[phy_idx].port=PORT_MII;
+			np->ecmds[phy_idx].transceiver=XCVR_INTERNAL;
+			np->ecmds[phy_idx].phy_address=np->phys[phy_idx];
+			np->ecmds[phy_idx].autoneg=AUTONEG_ENABLE;
+			np->ecmds[phy_idx].advertising=(ADVERTISED_10baseT_Half |
+							ADVERTISED_10baseT_Full |
+							ADVERTISED_100baseT_Half |
+							ADVERTISED_100baseT_Full);
+			phy_idx++;
+			break;
+		}
+	}
+	if (phy_idx == 1) {
+		np->valid_phy = np->phys[0];
+		np->phy_type = 0;
+	}
+	if (phy_idx != 0) {
+		phy = np->valid_phy;
+		np->advertising = mdio_read(dev,phy, 4);
+	}
+	return phy_idx;
+}
+
+/*
+ * CRC calc for Destination Address for gets hashtable index
+ */
+
+#define POLYNOMIAL 0x04c11db7UL
+static u16 jz_hashtable_index(u8 *addr)
+{
+	u32 crc = 0xffffffff, msb;
+	int  i, j;
+	u32  byte;
+	for (i = 0; i < 6; i++) {
+		byte = *addr++;
+		for (j = 0; j < 8; j++) {
+			msb = crc >> 31;
+			crc <<= 1;
+			if (msb ^ (byte & 1)) crc ^= POLYNOMIAL;
+			byte >>= 1;
+		}
+	}
+	return ((int)(crc >> 26));
+}
+
+/*
+ * Multicast filter and config multicast hash table
+ */
+#define MULTICAST_FILTER_LIMIT 64
+
+static void jz_set_multicast_list(struct net_device *dev)
+{
+	int i, hash_index;
+	u32 mcr, hash_h, hash_l, hash_bit;
+	
+	mcr = readl(jz_eth_base + MAC_MCR);
+	mcr &= ~(MCR_PR | MCR_PM | MCR_HP);
+	
+	if (dev->flags & IFF_PROMISC) {
+		/* Accept any kinds of packets */
+		mcr |= MCR_PR;
+		hash_h = 0xffffffff;
+		hash_l = 0xffffffff;
+	}
+	else  if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > MULTICAST_FILTER_LIMIT)){
+		/* Accept all multicast packets */
+		mcr |= MCR_PM;
+		hash_h = 0xffffffff;
+		hash_l = 0xffffffff;
+	}
+	else if (dev->flags & IFF_MULTICAST)
+	{
+		/* Update multicast hash table */
+		struct dev_mc_list *mclist;
+		hash_h = readl(jz_eth_base + MAC_HTH);
+		hash_l = readl(jz_eth_base + MAC_HTL);
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+		     i++, mclist = mclist->next)
+		{
+			hash_index = jz_hashtable_index(mclist->dmi_addr);
+			hash_bit=0x00000001;
+			hash_bit <<= (hash_index & 0x1f);
+			if (hash_index > 0x1f) 
+				hash_h |= hash_bit;
+			else
+				hash_l |= hash_bit;
+		}
+		writel(hash_h, jz_eth_base + MAC_HTH);
+		writel(hash_l, jz_eth_base + MAC_HTL);
+		mcr |= MCR_HP;
+	}
+	writel(mcr, jz_eth_base + MAC_MCR);
+}
+
+static inline int jz_phy_reset(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	unsigned int mii_reg0;
+	int i;
+
+	mii_reg0 = mdio_read(dev,np->valid_phy,MII_BMCR);
+	mii_reg0 |= MII_CR_RST;
+	mdio_write(dev, np->valid_phy, MII_BMCR, mii_reg0);
+
+	for (i=0; i<1000; i++) {
+		mdelay(1);
+		mii_reg0 = mdio_read(dev, np->valid_phy, MII_BMCR);
+		if (!(mii_reg0 & MII_CR_RST))
+			break;
+	}
+
+	if (i >= 1000)
+		/* phy error */
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Start Auto-Negotiation function for PHY 
+ */
+static int jz_autonet_complete(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	int i;
+	u32 mii_reg1, timeout = 3000;
+
+	for (i=0; i<timeout; i++) {
+		mdelay(1);
+		mii_reg1 = mdio_read(dev, np->valid_phy, MII_BMSR);
+		if (mii_reg1 & MII_SR_ASSC)
+			break;
+	}
+
+	if (i >= timeout)
+		/* auto negotiation error */
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Get current mode of eth phy
+ */
+static u32 jz_eth_curr_mode(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	unsigned int mii_reg17;
+	u32 flag = 0;
+
+	mii_reg17 = mdio_read(dev,np->valid_phy,MII_DSCSR); 
+	np->media = mii_reg17>>12;
+	if (np->media==8) {
+		printk(KERN_INFO "%s: Current Mode is [100M Full Duplex]",dev->name);
+		flag = 0;
+		np->full_duplex=1;
+	}
+	if (np->media==4) {
+		printk(KERN_INFO "%s: Current Mode is [100M Half Duplex]",dev->name);
+		flag = 0;
+		np->full_duplex=0;
+	}
+	if (np->media==2) {
+		printk(KERN_INFO "%s: Current Mode is [10M Full Duplex]",dev->name);
+		flag = OMR_TTM;
+		np->full_duplex=1;
+	}
+	if (np->media==1) {
+		printk(KERN_INFO "%s: Current Mode is [10M Half Duplex]",dev->name);
+		flag = OMR_TTM;
+		np->full_duplex=0;
+	}
+	printk("\n");
+	return flag;
+}
+
+/*
+ * Ethernet device hardware init
+ * This routine initializes the ethernet device hardware and PHY
+ */
+static int jz_init_hw(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	struct ethtool_cmd ecmd;
+	u32 mcr, omr;
+	u32 sts, flag = 0;
+	int i;
+
+	jz_eth_reset();
+	STOP_ETH();
+
+	/* Set MAC address */
+	writel(le32_to_cpu(*(unsigned long *)&dev->dev_addr[0]),
+			jz_eth_base + MAC_MAL);
+	writel(le32_to_cpu(*(unsigned long *)&dev->dev_addr[4]),
+			jz_eth_base + MAC_MAH);
+	printk("%s: JZ On-Chip ethernet (MAC ", dev->name);
+	for (i = 0; i < 5; i++) {
+		printk("%2.2x:", dev->dev_addr[i]);
+	}
+	printk("%2.2x, IRQ %d)\n", dev->dev_addr[i], dev->irq);
+
+	if ((np->mii_phy_cnt = jz_search_mii_phy(dev)) == 0) {
+		printk("%s: PHY not found, bailing.\n", dev->name);
+		return -ENXIO;
+	}
+
+	printk("%s: Found %d PHY on JZ MAC\n", dev->name, np->mii_phy_cnt);
+
+	mii_info.phy_id = np->valid_phy;
+	mii_info.dev = dev;
+	mii_info.mdio_read = &mdio_read;
+	mii_info.mdio_write = &mdio_write;
+
+	ecmd.speed = SPEED_100;
+	ecmd.duplex = DUPLEX_FULL;
+	ecmd.port = PORT_MII;
+	ecmd.transceiver = XCVR_INTERNAL;
+	ecmd.phy_address = np->valid_phy;
+	ecmd.autoneg = AUTONEG_ENABLE;
+	ecmd.advertising = ADVERTISED_10baseT_Half
+				| ADVERTISED_10baseT_Full
+				| ADVERTISED_100baseT_Half
+				| ADVERTISED_100baseT_Full;
+
+	mii_ethtool_sset(&mii_info,&ecmd);
+
+	if (jz_autonet_complete(dev)) 
+		printk(KERN_WARNING "%s: Ethernet Module AutoNegotiation failed\n",dev->name);
+	mii_ethtool_gset(&mii_info,&ecmd);
+
+	printk(KERN_INFO "%s: Provide Modes: ",dev->name);
+	for (i = 0; i < 5;i++) 
+		if (ecmd.advertising & (1<<i))
+			printk("(%d)%s", i+1, media_types[i]);
+	printk("\n");  
+
+	flag = jz_eth_curr_mode(dev);
+
+	/* Config OMR register */
+	omr = readl(jz_eth_base + DMA_OMR) & ~OMR_TTM;
+	omr |= flag;
+	//omr |= OMR_OSF;
+	omr |= OMR_SF;
+	writel(omr, jz_eth_base + DMA_OMR);
+
+	readl(jz_eth_base + DMA_MFC); //through read operation to clear the register for 0x0000000
+
+	/* Set the programmable burst length (value 1 or 4 is validate)*/
+#if 0 /* __BIG_ENDIAN__ */
+	writel(PBL_4 | DSL_0 | 0x100080, jz_eth_base + DMA_BMR);  /* DSL_0: see DESC_SKIP_LEN and DESC_ALIGN */
+#else /* __LITTLE_ENDIAN__ */
+	writel(PBL_4 | DSL_0, jz_eth_base + DMA_BMR);  /* DSL_0: see DESC_SKIP_LEN and DESC_ALIGN */
+#endif
+
+	/* Config MCR register*/
+	mcr = (readl(jz_eth_base + MAC_MCR) & ~(MCR_PS | MCR_HBD | MCR_FDX));   
+	if(np->full_duplex)
+		mcr |= MCR_FDX;
+	mcr |= MCR_BFD | MCR_TE | MCR_RE | MCR_OWD|MCR_HBD;
+	writel(mcr, jz_eth_base + MAC_MCR);
+
+	/* Set base address of TX and RX descriptors */
+	writel(np->dma_rx_ring, jz_eth_base + DMA_RRBA);
+	writel(np->dma_tx_ring, jz_eth_base + DMA_TRBA);
+
+	START_ETH();
+
+	/* set interrupt mask */
+	writel(IMR_DEFAULT | IMR_ENABLE, jz_eth_base + DMA_IMR);
+
+	/* Reset any pending (stale) interrupts */
+	sts = readl(jz_eth_base + DMA_STS);
+	writel(sts, jz_eth_base + DMA_STS);
+
+	return 0;
+}
+
+static void jz_eth_ring_init(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < NUM_RX_DESCS; i++) {
+		np->rx_ring[i].status = cpu_to_le32(R_OWN);
+		np->rx_ring[i].desc1 = cpu_to_le32(RX_BUF_SIZE | RD_RCH);
+		np->rx_ring[i].buf1_addr = cpu_to_le32(np->dma_rx_buf + i*RX_BUF_SIZE);
+		np->rx_ring[i].next_addr = cpu_to_le32(np->dma_rx_ring + (i+1) * sizeof (jz_desc_t));
+	}
+	np->rx_ring[NUM_RX_DESCS - 1].next_addr = cpu_to_le32(np->dma_rx_ring);
+
+	for (i = 0; i < NUM_TX_DESCS; i++) {
+		np->tx_ring[i].status = cpu_to_le32(0);
+		np->tx_ring[i].desc1  = cpu_to_le32(TD_TCH);
+		np->tx_ring[i].buf1_addr = 0;
+		np->tx_ring[i].next_addr = cpu_to_le32(np->dma_tx_ring + (i+1) * sizeof (jz_desc_t));
+	}
+	np->tx_ring[NUM_TX_DESCS - 1].next_addr = cpu_to_le32(np->dma_tx_ring);
+
+	np->rx_head = 0;
+	np->tx_head = np->tx_tail = 0;
+
+	dma_cache_wback((unsigned long)np->rx_ring, sizeof(jz_desc_t)*NUM_RX_DESCS);
+	dma_cache_wback((unsigned long)np->tx_ring, sizeof(jz_desc_t)*NUM_TX_DESCS);
+}
+
+static int jz_eth_open(struct net_device *dev)
+{
+	int retval;
+
+	jz_eth_ring_init(dev);
+
+	if ((retval = jz_init_hw(dev)) != 0)
+		return retval;
+
+	retval = request_irq(dev->irq, jz_eth_interrupt, 0, dev->name, dev);
+	if (retval) {
+		printk(KERN_WARNING "%s: unable to get IRQ %d .\n", dev->name, dev->irq);
+		return -EAGAIN;
+	}
+
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
+	start_check(dev);
+
+	return 0;
+}
+
+static int jz_eth_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	close_check(dev);
+	STOP_ETH();
+	free_irq(dev->irq, dev);
+	return 0;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the device open or closed.
+ */
+static struct net_device_stats * jz_eth_get_stats(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	int tmp;
+
+	tmp = readl(jz_eth_base + DMA_MFC); // After read clear to zero
+	np->stats.rx_missed_errors += (tmp & MFC_CNT2) + ((tmp & MFC_CNT1) >> 16);
+
+	return &np->stats;
+}
+
+/*
+ * ethtool routines
+ */
+static int jz_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, "OCS");
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&mii_info, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&mii_info, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&mii_info);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&mii_info);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+
+}
+
+/*
+ * Config device
+ */
+static int jz_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	struct mii_ioctl_data *data, rdata;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return jz_ethtool_ioctl(dev, (void *) rq->ifr_data);
+	case SIOCGMIIPHY:
+	case SIOCDEVPRIVATE:
+		data = (struct mii_ioctl_data *)&rq->ifr_data;
+		data->phy_id = np->valid_phy;
+	case SIOCGMIIREG:
+	case SIOCDEVPRIVATE+1:
+		data = (struct mii_ioctl_data *)&rq->ifr_data;
+		data->val_out = mdio_read(dev,np->valid_phy, data->reg_num & 0x1f);
+		return 0;
+	case SIOCSMIIREG:
+	case SIOCDEVPRIVATE+2:
+		data = (struct mii_ioctl_data *)&rq->ifr_data;
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		mdio_write(dev,np->valid_phy, data->reg_num & 0x1f, data->val_in);
+		return 0;
+	case READ_COMMAND:	
+		data = (struct mii_ioctl_data *)rq->ifr_data;
+		if (copy_from_user(&rdata,data,sizeof(rdata)))
+			return -EFAULT;
+		rdata.val_out = mdio_read(dev,rdata.phy_id, rdata.reg_num & 0x1f);
+		if (copy_to_user(data,&rdata,sizeof(rdata)))
+			return -EFAULT;
+		return 0;
+	case WRITE_COMMAND:
+		if (np->phy_type==1) {
+			data = (struct mii_ioctl_data *)rq->ifr_data;
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+			if (copy_from_user(&rdata,data,sizeof(rdata)))
+				return -EFAULT;
+			mdio_write(dev,rdata.phy_id, rdata.reg_num & 0x1f, rdata.val_in);
+		}
+		return 0;
+	case GETDRIVERINFO:
+		if (np->phy_type==1) {
+			data = (struct mii_ioctl_data *)rq->ifr_data;
+			if (copy_from_user(&rdata,data,sizeof(rdata)))
+				return -EFAULT;
+			rdata.val_in = 0x1;
+			rdata.val_out = 0x00d0;
+			if (copy_to_user(data,&rdata,sizeof(rdata)))
+				return -EFAULT;
+		}
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+/*
+ * Received one packet
+ */
+static void eth_rxready(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	struct sk_buff *skb;
+	unsigned char *pkt_ptr;
+	u32 pkt_len;
+	u32 status;
+
+	ring_inv(np->rx_ring, np->rx_head);
+	status = le32_to_cpu(np->rx_ring[np->rx_head].status);
+	while (!(status & R_OWN)) {               /* owner bit = 0 */
+		if (status & RD_ES) {              /* error summary */
+			np->stats.rx_errors++;    /* Update the error stats. */
+			if (status & (RD_RF | RD_TL))
+				np->stats.rx_frame_errors++;
+			if (status & RD_CE)
+				np->stats.rx_crc_errors++;
+			if (status & RD_TL)
+				np->stats.rx_length_errors++;
+		} else {
+			pkt_ptr = bus_to_virt(le32_to_cpu(np->rx_ring[np->rx_head].buf1_addr));
+			pkt_len = ((status & RD_FL) >> 16) - 4;
+
+			skb = dev_alloc_skb(pkt_len + 2);
+			if (skb == NULL) {
+				printk("%s: Memory squeeze, dropping.\n",
+				       dev->name);
+				np->stats.rx_dropped++;
+				break;
+			}
+			skb->dev = dev;
+			skb_reserve(skb, 2); /* 16 byte align */
+
+			memcpy(skb->data, pkt_ptr, pkt_len);
+			skb_put(skb, pkt_len);
+
+			skb->protocol = eth_type_trans(skb,dev);
+			netif_rx(skb);	/* pass the packet to upper layers */
+			dev->last_rx = jiffies;
+			np->stats.rx_packets++;
+			np->stats.rx_bytes += pkt_len;
+		}
+		np->rx_ring[np->rx_head].status = cpu_to_le32(R_OWN);
+
+		np->rx_head ++;
+		if (np->rx_head >= NUM_RX_DESCS)
+			np->rx_head = 0;
+		ring_inv(np->rx_ring, np->rx_head);
+		status = le32_to_cpu(np->rx_ring[np->rx_head].status);
+	}
+}
+
+/*
+ * Tx timeout routine 
+ */
+static void jz_eth_tx_timeout(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+
+	jz_init_hw(dev);
+	np->stats.tx_errors ++;
+	netif_wake_queue(dev);
+}
+
+/*
+ * One packet was transmitted
+ */
+static void eth_txdone(struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	int tx_tail = np->tx_tail;
+	int entry;
+	u32 status;
+
+	while (tx_tail != np->tx_head) {
+		entry = tx_tail % NUM_TX_DESCS;
+		ring_inv(np->tx_ring, entry);
+		status = le32_to_cpu(np->tx_ring[entry].status);
+		if (status & T_OWN)
+			break;
+		if (status & TD_ES ) {       /* Error summary */
+			np->stats.tx_errors++;
+			if (status & TD_NC) np->stats.tx_carrier_errors++;
+			if (status & TD_LC) np->stats.tx_window_errors++;
+			if (status & TD_UF) np->stats.tx_fifo_errors++;
+			if (status & TD_DE) np->stats.tx_aborted_errors++;
+			if (np->tx_head != np->tx_tail)
+				writel(1, jz_eth_base + DMA_TPD);  /* Restart a stalled TX */
+		} else
+			np->stats.tx_packets++;
+		/* Update the collision counter */
+		np->stats.collisions += ((status & TD_EC) ? 16 : ((status & TD_CC) >> 3));
+		/* Free the original skb */
+		if (np->tx_skb[entry]) {
+			dev_kfree_skb_irq(np->tx_skb[entry]);
+			np->tx_skb[entry] = 0;
+		}
+		tx_tail++;
+	}
+	if (np->tx_full && (tx_tail + NUM_TX_DESCS > np->tx_head + 1)) {
+		/* The ring is no longer full */
+		np->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+	np->tx_tail = tx_tail;
+}
+
+/*
+ * Update the tx descriptor
+ */
+static void load_tx_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	int entry = np->tx_head % NUM_TX_DESCS;
+
+	np->tx_ring[entry].buf1_addr = cpu_to_le32(virt_to_bus(buf));
+	np->tx_ring[entry].desc1 &= cpu_to_le32((TD_TER | TD_TCH));
+	np->tx_ring[entry].desc1 |= cpu_to_le32(flags);
+	np->tx_ring[entry].status = cpu_to_le32(T_OWN);
+	np->tx_skb[entry] = skb;
+
+	ring_wback(np->tx_ring, entry);
+}
+
+/*
+ * Transmit one packet
+ */
+static int jz_eth_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	struct jz_eth_private *np = netdev_priv(dev);
+	u32 length;
+
+	if (np->tx_full) {
+		return 0;
+	}
+
+	length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+	dma_cache_wback((unsigned long)skb->data, length);
+	load_tx_packet(dev, (char *)skb->data,
+			TD_IC | TD_LS | TD_FS | (length & TD_TBS1), skb);
+
+	spin_lock_irq(&np->lock);
+	np->tx_head ++;
+	np->stats.tx_bytes += length;
+	writel(1, jz_eth_base + DMA_TPD);		/* Start the TX */
+
+	dev->trans_start = jiffies;	/* for timeout */
+	if (np->tx_tail + NUM_TX_DESCS > np->tx_head + 1) {
+		np->tx_full = 0;
+	}
+	else {
+		np->tx_full = 1;
+		netif_stop_queue(dev);
+	}
+	spin_unlock_irq(&np->lock);
+
+	return 0;
+}
+
+/*
+ * Interrupt service routine
+ */
+static irqreturn_t jz_eth_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct jz_eth_private *np = netdev_priv(dev);
+	u32 sts;
+	int i;
+
+	spin_lock(&np->lock);
+
+	writel((readl(jz_eth_base + DMA_IMR) & ~IMR_ENABLE),
+			jz_eth_base + DMA_IMR);
+
+	for (i = 0; i < 100; i++) {
+		/* clear status */
+		sts = readl(jz_eth_base + DMA_STS);
+		writel(sts, jz_eth_base + DMA_STS);
+
+		if (!(sts & IMR_DEFAULT))
+			break;
+
+		if (sts & (DMA_INT_RI | DMA_INT_RU))
+			/* Rx IRQ */
+			eth_rxready(dev);
+		if (sts & (DMA_INT_TI | DMA_INT_TU)) {
+			/* Tx IRQ */
+			eth_txdone(dev);
+		}
+
+		/* check error conditions */
+		if (sts & DMA_INT_FB){
+			STOP_ETH();
+			printk(KERN_ERR "%s: Fatal bus error occurred, sts=%#8x, "
+					"device stopped.\n",dev->name, sts);
+			break;
+		}
+
+		/* Transmit underrun */
+		if (sts & DMA_INT_UN) {
+			u32 omr;
+			omr = readl(jz_eth_base + DMA_OMR);
+			if (!(omr & OMR_SF)) {
+				omr &= ~(OMR_ST | OMR_SR);
+				writel(omr, jz_eth_base + DMA_OMR);
+
+				/* wait for stop */
+				while (readl(jz_eth_base + DMA_STS) & STS_TS)
+					;
+
+				/* increase transmit threshold if possible */
+				if ((omr & OMR_TR) < OMR_TR) {
+					omr += TR_24;
+				} else {
+					omr |= OMR_SF;
+				}
+				writel(omr | OMR_ST | OMR_SR,
+						jz_eth_base + DMA_OMR);
+			}
+		}
+	}
+
+	writel(readl(jz_eth_base + DMA_IMR)|IMR_ENABLE, jz_eth_base + DMA_IMR);
+
+	spin_unlock(&np->lock);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM
+/*
+ * Suspend the ETH interface.
+ */
+static int jz_eth_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct jz_eth_private *jep = netdev_priv(dev);
+	unsigned long flags, tmp;
+
+	if (!netif_running(dev))
+		return 0;
+
+	netif_device_detach(dev);
+
+	spin_lock_irqsave(&jep->lock, flags);
+
+	/* Disable interrupts, stop Tx and Rx. */
+	writel(0, jz_eth_base + DMA_IMR);
+	STOP_ETH();
+
+	/* Update the error counts. */
+	tmp = readl(jz_eth_base + DMA_MFC);
+	jep->stats.rx_missed_errors += (tmp & 0x1ffff);
+	jep->stats.rx_fifo_errors += ((tmp >> 17) & 0x7ff);
+
+	spin_unlock_irqrestore(&jep->lock, flags);
+
+	return 0;
+}
+
+/*
+ * Resume the ETH interface.
+ */
+static int jz_eth_resume(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+
+	if (!netif_running(dev))
+		return 0;
+
+	jz_eth_ring_init(dev);
+	jz_init_hw(dev);
+
+	netif_device_attach(dev);
+	netif_wake_queue(dev);
+
+	return 0;
+}
+#else
+#define jz_eth_suspend NULL
+#define jz_eth_resume NULL
+#endif /* CONFIG_PM */
+
+static const struct net_device_ops jz_netdev_ops = {
+	.ndo_open = jz_eth_open,
+	.ndo_stop = jz_eth_close,
+	.ndo_start_xmit = jz_eth_send_packet,
+	.ndo_set_multicast_list = jz_set_multicast_list,
+	.ndo_tx_timeout = jz_eth_tx_timeout,
+	.ndo_get_stats = jz_eth_get_stats,
+	.ndo_do_ioctl = jz_eth_ioctl,
+};
+
+static int jz_eth_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct jz_eth_private *np;
+	int ret;
+
+	dev = alloc_etherdev(sizeof(struct jz_eth_private));
+	if (!dev) {
+		printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	np = netdev_priv(dev);
+	memset(np, 0, sizeof(struct jz_eth_private));
+
+	np->vaddr_rx_buf = (u32)dma_alloc_noncoherent(NULL,
+					NUM_RX_DESCS*RX_BUF_SIZE,
+					&np->dma_rx_buf, 0);
+
+	if (!np->vaddr_rx_buf) {
+		printk(KERN_ERR "%s: Cannot alloc dma buffers\n", DRV_NAME);
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	np->dma_rx_ring = virt_to_bus(np->rx_ring);
+	np->dma_tx_ring = virt_to_bus(np->tx_ring);
+	np->full_duplex = 1;
+	np->link_state = 1;
+
+	dev->irq = platform_get_irq(pdev, 0);
+	if (dev->irq < 0) {
+		ret = -ENXIO;
+		goto err2;
+	}
+
+	np->iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!np->iores) {
+		ret = -ENXIO;
+		goto err2;
+	}
+
+	np->iores = request_mem_region(np->iores->start,
+			resource_size(np->iores), pdev->name);
+	if (!np->iores) {
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	jz_eth_base = ioremap_nocache(np->iores->start,
+			resource_size(np->iores));
+	if (!jz_eth_base) {
+		ret = -EBUSY;
+		goto err3;
+	}
+
+	spin_lock_init(&np->lock);
+
+	dev->netdev_ops = &jz_netdev_ops;
+	dev->watchdog_timeo = ETH_TX_TIMEOUT;
+
+	/* configure MAC address */
+	get_mac_address(dev);
+
+	platform_set_drvdata(pdev, dev);
+
+	if ((ret = register_netdev(dev)) != 0) {
+		printk(KERN_ERR "%s: Cannot register net device, error %d\n",
+				DRV_NAME, ret);
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	iounmap(jz_eth_base);
+err3:
+	release_mem_region(np->iores->start, 0x10000);
+err2:
+	dma_free_noncoherent(NULL, NUM_RX_DESCS * RX_BUF_SIZE,
+			     (void *)np->vaddr_rx_buf, np->dma_rx_buf);
+err1:
+	free_netdev(dev);
+err0:
+	return ret;
+}
+
+static int jz_eth_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct jz_eth_private *np = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	iounmap(jz_eth_base);
+	release_mem_region(np->iores->start, 0x10000);
+	dma_free_noncoherent(NULL, NUM_RX_DESCS * RX_BUF_SIZE,
+			     (void *)np->vaddr_rx_buf, np->dma_rx_buf);
+	free_netdev(dev);
+	return 0;
+}
+
+static struct platform_driver jz_eth_driver = {
+	.driver = {
+		.name = "jz-eth"
+	},
+	.probe = jz_eth_probe,
+	.remove = jz_eth_remove,
+	.suspend = jz_eth_suspend,
+	.resume = jz_eth_resume,
+};
+
+static int __init jz_eth_init(void)
+{
+	return platform_driver_register(&jz_eth_driver);
+}
+
+static void __exit jz_eth_exit(void)
+{
+	platform_driver_unregister(&jz_eth_driver);
+}
+
+module_init(jz_eth_init);
+module_exit(jz_eth_exit);
diff --git a/drivers/net/jz_eth.h b/drivers/net/jz_eth.h
new file mode 100644
index 0000000..62d147c
--- /dev/null
+++ b/drivers/net/jz_eth.h
@@ -0,0 +1,403 @@
+/*
+ *  Jz4730/Jz5730 On-Chip ethernet driver.
+ *
+ *  Copyright (C) 2005 - 2007  Ingenic Semiconductor Inc.
+ *
+ * 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.
+ */
+#ifndef __JZ_ETH_H__
+#define __JZ_ETH_H__
+
+/* DMA control and status registers */
+#define DMA_BMR                0x1000 // Bus mode
+#define DMA_TPD                0x1004 // Transmit poll demand register
+#define DMA_RPD                0x1008 // Receieve poll demand register
+#define DMA_RRBA               0x100C // Receieve descriptor base address
+#define DMA_TRBA               0x1010 // Transmit descriptor base address
+#define DMA_STS                0x1014 // Status register
+#define DMA_OMR                0x1018 // Command register
+#define DMA_IMR                0x101C
+#define DMA_MFC                0x1020
+
+/* DMA CSR8-CSR19 reserved */
+#define DMA_CTA                0x1050
+#define DMA_CRA                0x1054
+
+/* Mac control and status registers */
+#define MAC_MCR                0x0000
+#define MAC_MAH                0x0004
+#define MAC_MAL                0x0008
+#define MAC_HTH                0x000C
+#define MAC_HTL                0x0010
+#define MAC_MIIA               0x0014
+#define MAC_MIID               0x0018
+#define MAC_FCR                0x001C
+#define MAC_VTR1               0x0020
+#define MAC_VTR2               0x0024
+
+/*
+ * Bus Mode Register (DMA_BMR)
+ */
+#define BMR_PBL    0x00003f00       /* Programmable Burst Length */
+#define BMR_DSL    0x0000007c       /* Descriptor Skip Length */
+#define BMR_BAR    0x00000002       /* Bus ARbitration */
+#define BMR_SWR    0x00000001       /* Software Reset */
+
+#define PBL_0      0x00000000       /*  DMA burst length = amount in RX FIFO */
+#define PBL_1      0x00000100       /*  1 longword  DMA burst length */
+#define PBL_2      0x00000200       /*  2 longwords DMA burst length */
+#define PBL_4      0x00000400       /*  4 longwords DMA burst length */
+#define PBL_8      0x00000800       /*  8 longwords DMA burst length */
+#define PBL_16     0x00001000       /* 16 longwords DMA burst length */
+#define PBL_32     0x00002000       /* 32 longwords DMA burst length */
+
+#define DSL_0      0x00000000       /*  0 longword  / descriptor */
+#define DSL_1      0x00000004       /*  1 longword  / descriptor */
+#define DSL_2      0x00000008       /*  2 longwords / descriptor */
+#define DSL_4      0x00000010       /*  4 longwords / descriptor */
+#define DSL_8      0x00000020       /*  8 longwords / descriptor */
+#define DSL_16     0x00000040       /* 16 longwords / descriptor */
+#define DSL_32     0x00000080       /* 32 longwords / descriptor */
+
+/*
+ * Status Register (DMA_STS)
+ */
+#define STS_BE     0x03800000       /* Bus Error Bits */
+#define STS_TS     0x00700000       /* Transmit Process State */
+#define STS_RS     0x000e0000       /* Receive Process State */
+
+#define TS_STOP    0x00000000       /* Stopped */
+#define TS_FTD     0x00100000       /* Running Fetch Transmit Descriptor */
+#define TS_WEOT    0x00200000       /* Running Wait for End Of Transmission */
+#define TS_QDAT    0x00300000       /* Running Queue skb data into TX FIFO */
+#define TS_RES     0x00400000       /* Reserved */
+#define TS_SPKT    0x00500000       /* Reserved */
+#define TS_SUSP    0x00600000       /* Suspended */
+#define TS_CLTD    0x00700000       /* Running Close Transmit Descriptor */
+
+#define RS_STOP    0x00000000       /* Stopped */
+#define RS_FRD     0x00020000       /* Running Fetch Receive Descriptor */
+#define RS_CEOR    0x00040000       /* Running Check for End of Receive Packet */
+#define RS_WFRP    0x00060000       /* Running Wait for Receive Packet */
+#define RS_SUSP    0x00080000       /* Suspended */
+#define RS_CLRD    0x000a0000       /* Running Close Receive Descriptor */
+#define RS_FLUSH   0x000c0000       /* Running Flush RX FIFO */
+#define RS_QRFS    0x000e0000       /* Running Queue RX FIFO into RX Skb */
+
+/*
+ * Operation Mode Register (DMA_OMR)
+ */
+#define OMR_TTM    0x00400000       /* Transmit Threshold Mode */
+#define OMR_SF     0x00200000       /* Store and Forward */
+#define OMR_TR     0x0000c000       /* Threshold Control Bits */
+#define OMR_ST     0x00002000       /* Start/Stop Transmission Command */
+#define OMR_OSF    0x00000004       /* Operate on Second Frame */
+#define OMR_SR     0x00000002       /* Start/Stop Receive */
+
+#define TR_18      0x00000000       /* Threshold set to 18 (32) bytes */
+#define TR_24      0x00004000       /* Threshold set to 24 (64) bytes */
+#define TR_32      0x00008000       /* Threshold set to 32 (128) bytes */
+#define TR_40      0x0000c000       /* Threshold set to 40 (256) bytes */
+
+/*
+ * Missed Frames Counters (DMA_MFC)
+ */
+//#define MFC_CNT1   0xffff0000       /* Missed Frames Counter Bits by application */
+#define MFC_CNT1   0x0ffe0000       /* Missed Frames Counter Bits by application */
+#define MFC_CNT2   0x0000ffff       /* Missed Frames Counter Bits by controller */
+
+/*
+ * Mac control  Register (MAC_MCR)
+ */
+#define MCR_RA     0x80000000       /* Receive All */
+#define MCR_HBD    0x10000000       /* HeartBeat Disable */
+#define MCR_PS     0x08000000       /* Port Select */
+#define MCR_OWD    0x00800000       /* Receive own Disable */
+#define MCR_OM     0x00600000       /* Operating(loopback) Mode */
+#define MCR_FDX    0x00100000       /* Full Duplex Mode */
+#define MCR_PM     0x00080000       /* Pass All Multicast */
+#define MCR_PR     0x00040000       /* Promiscuous Mode */
+#define MCR_IF     0x00020000       /* Inverse Filtering */
+#define MCR_PB     0x00010000       /* Pass Bad Frames */
+#define MCR_HO     0x00008000       /* Hash Only Filtering Mode */
+#define MCR_HP     0x00002000       /* Hash/Perfect Receive Filtering Mode */
+#define MCR_FC     0x00001000       /* Late Collision control */
+#define MCR_BFD    0x00000800       /* Boardcast frame Disable */
+#define MCR_RED    0x00000400       /* Retry Disable */
+#define MCR_APS    0x00000100       /* Automatic pad stripping */
+#define MCR_BL     0x000000c0       /* Back off Limit */
+#define MCR_DC     0x00000020       /* Deferral check */
+#define MCR_TE     0x00000008       /* Transmitter enable */
+#define MCR_RE     0x00000004       /* Receiver enable */
+
+#define MCR_MII_10  ( OMR_TTM | MCR_PS)
+#define MCR_MII_100 ( MCR_HBD | MCR_PS)
+
+/* Flow control Register (MAC_FCR) */
+#define FCR_PT     0xffff0000       /* Pause time */
+#define FCR_PCF    0x00000004       /* Pass control frames */
+#define FCR_FCE    0x00000002       /* Flow control enable */
+#define FCR_FCB    0x00000001       /* Flow control busy */
+
+
+/* Constants for the interrupt mask and
+ * interrupt status registers. (DMA_SIS and DMA_IMR)
+ */
+#define DMA_INT_NI             0x00010000       // Normal interrupt summary
+#define DMA_INT_AI             0x00008000       // Abnormal interrupt summary
+#define DMA_INT_ER             0x00004000       // Early receive interrupt
+#define DMA_INT_FB             0x00002000       // Fatal bus error
+#define DMA_INT_ET             0x00000400       // Early transmit interrupt
+#define DMA_INT_RW             0x00000200       // Receive watchdog timeout
+#define DMA_INT_RS             0x00000100       // Receive stop
+#define DMA_INT_RU             0x00000080       // Receive buffer unavailble
+#define DMA_INT_RI             0x00000040       // Receive interrupt
+#define DMA_INT_UN             0x00000020       // Underflow 
+#define DMA_INT_TJ             0x00000008       // Transmit jabber timeout
+#define DMA_INT_TU             0x00000004       // Transmit buffer unavailble 
+#define DMA_INT_TS             0x00000002       // Transmit stop
+#define DMA_INT_TI             0x00000001       // Transmit interrupt
+
+/*
+ * Receive Descriptor Bit Summary
+ */
+#define R_OWN      0x80000000       /* Own Bit */
+#define RD_FF      0x40000000       /* Filtering Fail */
+#define RD_FL      0x3fff0000       /* Frame Length */
+#define RD_ES      0x00008000       /* Error Summary */
+#define RD_DE      0x00004000       /* Descriptor Error */
+#define RD_LE      0x00001000       /* Length Error */
+#define RD_RF      0x00000800       /* Runt Frame */
+#define RD_MF      0x00000400       /* Multicast Frame */
+#define RD_FS      0x00000200       /* First Descriptor */
+#define RD_LS      0x00000100       /* Last Descriptor */
+#define RD_TL      0x00000080       /* Frame Too Long */
+#define RD_CS      0x00000040       /* Collision Seen */
+#define RD_FT      0x00000020       /* Frame Type */
+#define RD_RJ      0x00000010       /* Receive Watchdog timeout*/
+#define RD_RE      0x00000008       /* Report on MII Error */
+#define RD_DB      0x00000004       /* Dribbling Bit */
+#define RD_CE      0x00000002       /* CRC Error */
+
+#define RD_RER     0x02000000       /* Receive End Of Ring */
+#define RD_RCH     0x01000000       /* Second Address Chained */
+#define RD_RBS2    0x003ff800       /* Buffer 2 Size */
+#define RD_RBS1    0x000007ff       /* Buffer 1 Size */
+
+/*
+ * Transmit Descriptor Bit Summary
+ */
+#define T_OWN      0x80000000       /* Own Bit */
+#define TD_ES      0x00008000       /* Frame Aborted (error summary)*/
+#define TD_LO      0x00000800       /* Loss Of Carrier */
+#define TD_NC      0x00000400       /* No Carrier */
+#define TD_LC      0x00000200       /* Late Collision */
+#define TD_EC      0x00000100       /* Excessive Collisions */
+#define TD_HF      0x00000080       /* Heartbeat Fail */
+#define TD_CC      0x0000003c       /* Collision Counter */
+#define TD_UF      0x00000002       /* Underflow Error */
+#define TD_DE      0x00000001       /* Deferred */
+
+#define TD_IC      0x80000000       /* Interrupt On Completion */
+#define TD_LS      0x40000000       /* Last Segment */
+#define TD_FS      0x20000000       /* First Segment */
+#define TD_FT1     0x10000000       /* Filtering Type */
+#define TD_SET     0x08000000       /* Setup Packet */
+#define TD_AC      0x04000000       /* Add CRC Disable */
+#define TD_TER     0x02000000       /* Transmit End Of Ring */
+#define TD_TCH     0x01000000       /* Second Address Chained */
+#define TD_DPD     0x00800000       /* Disabled Padding */
+#define TD_FT0     0x00400000       /* Filtering Type */
+#define TD_TBS2    0x003ff800       /* Buffer 2 Size */
+#define TD_TBS1    0x000007ff       /* Buffer 1 Size */
+
+#define PERFECT_F  0x00000000
+#define HASH_F     TD_FT0
+#define INVERSE_F  TD_FT1
+#define HASH_O_F   (TD_FT1 | TD_F0)
+
+/*
+ * Constant setting
+ */
+
+#define IMR_DEFAULT    ( DMA_INT_TI | DMA_INT_RI |	\
+                         DMA_INT_TS | DMA_INT_RS |	\
+                         DMA_INT_TU | DMA_INT_RU |	\
+                         DMA_INT_FB )
+
+#define IMR_ENABLE     (DMA_INT_NI | DMA_INT_AI)
+
+#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
+#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
+
+#define HASH_TABLE_LEN   512       /* Bits */
+#define HASH_BITS        0x01ff    /* 9 LS bits */
+
+#define SETUP_FRAME_LEN  192       /* Bytes */
+#define IMPERF_PA_OFFSET 156       /* Bytes */
+
+/*
+ * Address Filtering Modes
+ */
+#define PERFECT              0     /* 16 perfect physical addresses */
+#define HASH_PERF            1     /* 1 perfect, 512 multicast addresses */
+#define PERFECT_REJ          2     /* Reject 16 perfect physical addresses */
+#define ALL_HASH             3     /* Hashes all physical & multicast addrs */
+
+#define ALL                  0     /* Clear out all the setup frame */
+#define PHYS_ADDR_ONLY       1     /* Update the physical address only */
+
+/* MII register */
+#define MII_BMCR       0x00          /* MII Basic Mode Control Register */
+#define MII_BMSR       0x01          /* MII Basic Mode Status Register */
+#define MII_ID1        0x02          /* PHY Identifier Register 1 */
+#define MII_ID2        0x03          /* PHY Identifier Register 2 */
+#define MII_ANAR       0x04          /* Auto Negotiation Advertisement Register */
+#define MII_ANLPAR     0x05          /* Auto Negotiation Link Partner Ability */
+#define MII_ANER       0x06          /* Auto Negotiation Expansion */
+#define MII_DSCR       0x10          /* Davicom Specified Configration Register */
+#define MII_DSCSR      0x11          /* Davicom Specified Configration/Status Register */
+#define MII_10BTCSR    0x12          /* 10base-T Specified Configration/Status Register */
+
+
+#define MII_PREAMBLE 0xffffffff    /* MII Management Preamble */
+#define MII_TEST     0xaaaaaaaa    /* MII Test Signal */
+#define MII_STRD     0x06          /* Start of Frame+Op Code: use low nibble */
+#define MII_STWR     0x0a          /* Start of Frame+Op Code: use low nibble */
+
+/*
+ * MII Management Control Register
+ */
+#define MII_CR_RST  0x8000         /* RESET the PHY chip */
+#define MII_CR_LPBK 0x4000         /* Loopback enable */
+#define MII_CR_SPD  0x2000         /* 0: 10Mb/s; 1: 100Mb/s */
+#define MII_CR_ASSE 0x1000         /* Auto Speed Select Enable */
+#define MII_CR_PD   0x0800         /* Power Down */
+#define MII_CR_ISOL 0x0400         /* Isolate Mode */
+#define MII_CR_RAN  0x0200         /* Restart Auto Negotiation */
+#define MII_CR_FDM  0x0100         /* Full Duplex Mode */
+#define MII_CR_CTE  0x0080         /* Collision Test Enable */
+
+/*
+ * MII Management Status Register
+ */
+#define MII_SR_T4C  0x8000         /* 100BASE-T4 capable */
+#define MII_SR_TXFD 0x4000         /* 100BASE-TX Full Duplex capable */
+#define MII_SR_TXHD 0x2000         /* 100BASE-TX Half Duplex capable */
+#define MII_SR_TFD  0x1000         /* 10BASE-T Full Duplex capable */
+#define MII_SR_THD  0x0800         /* 10BASE-T Half Duplex capable */
+#define MII_SR_ASSC 0x0020         /* Auto Speed Selection Complete*/
+#define MII_SR_RFD  0x0010         /* Remote Fault Detected */
+#define MII_SR_ANC  0x0008         /* Auto Negotiation capable */
+#define MII_SR_LKS  0x0004         /* Link Status */
+#define MII_SR_JABD 0x0002         /* Jabber Detect */
+#define MII_SR_XC   0x0001         /* Extended Capabilities */
+
+/*
+ * MII Management Auto Negotiation Advertisement Register
+ */
+#define MII_ANA_TAF  0x03e0        /* Technology Ability Field */
+#define MII_ANA_T4AM 0x0200        /* T4 Technology Ability Mask */
+#define MII_ANA_TXAM 0x0180        /* TX Technology Ability Mask */
+#define MII_ANA_FDAM 0x0140        /* Full Duplex Technology Ability Mask */
+#define MII_ANA_HDAM 0x02a0        /* Half Duplex Technology Ability Mask */
+#define MII_ANA_100M 0x0380        /* 100Mb Technology Ability Mask */
+#define MII_ANA_10M  0x0060        /* 10Mb Technology Ability Mask */
+#define MII_ANA_CSMA 0x0001        /* CSMA-CD Capable */
+
+/*
+ * MII Management Auto Negotiation Remote End Register
+ */
+#define MII_ANLPA_NP   0x8000      /* Next Page (Enable) */
+#define MII_ANLPA_ACK  0x4000      /* Remote Acknowledge */
+#define MII_ANLPA_RF   0x2000      /* Remote Fault */
+#define MII_ANLPA_TAF  0x03e0      /* Technology Ability Field */
+#define MII_ANLPA_T4AM 0x0200      /* T4 Technology Ability Mask */
+#define MII_ANLPA_TXAM 0x0180      /* TX Technology Ability Mask */
+#define MII_ANLPA_FDAM 0x0140      /* Full Duplex Technology Ability Mask */
+#define MII_ANLPA_HDAM 0x02a0      /* Half Duplex Technology Ability Mask */
+#define MII_ANLPA_100M 0x0380      /* 100Mb Technology Ability Mask */
+#define MII_ANLPA_10M  0x0060      /* 10Mb Technology Ability Mask */
+#define MII_ANLPA_CSMA 0x0001      /* CSMA-CD Capable */
+
+/*
+ * MII Management DAVICOM Specified Configuration And Status Register
+ */
+#define MII_DSCSR_100FDX       0x8000  /* 100M Full Duplex Operation Mode */    
+#define MII_DSCSR_100HDX       0x4000  /* 100M Half Duplex Operation Mode */
+#define MII_DSCSR_10FDX        0x2000  /* 10M  Full Duplex Operation Mode */
+#define MII_DSCSR_10HDX        0x1000  /* 10M  Half Duplex Operation Mode */
+#define MII_DSCSR_ANMB         0x000f  /* Auto-Negotiation Monitor Bits   */
+
+
+/*
+ * Used by IOCTL
+ */
+#define READ_COMMAND		(SIOCDEVPRIVATE+4)
+#define WRITE_COMMAND		(SIOCDEVPRIVATE+5)
+#define GETDRIVERINFO		(SIOCDEVPRIVATE+6)
+
+/*
+ * Device data and structure
+ */
+
+#define ETH_TX_TIMEOUT		(6*HZ)
+
+#define RX_BUF_SIZE		1536
+
+#define NUM_RX_DESCS		32
+#define NUM_TX_DESCS		16
+
+static const char *media_types[] = {
+	"10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ", 
+	"100baseTx-FD", "100baseT4", 0
+};
+
+typedef struct {
+	unsigned int status;
+	unsigned int desc1;
+	unsigned int buf1_addr;
+	unsigned int next_addr;
+} jz_desc_t;	
+
+struct jz_eth_private {
+	jz_desc_t tx_ring[NUM_TX_DESCS];	/* transmit descriptors */
+	jz_desc_t rx_ring[NUM_RX_DESCS];	/* receive descriptors */
+	dma_addr_t dma_tx_ring;                 /* bus address of tx ring */
+	dma_addr_t dma_rx_ring;                 /* bus address of rx ring */
+	dma_addr_t dma_rx_buf;			/* DMA address of rx buffer  */	
+	unsigned int vaddr_rx_buf;		/* virtual address of rx buffer  */
+
+	unsigned int rx_head;			/* first rx descriptor */
+	unsigned int tx_head;			/* first tx descriptor */
+	unsigned int tx_tail;  			/* last unacked transmit packet */
+	unsigned int tx_full;			/* transmit buffers are full */
+	struct sk_buff *tx_skb[NUM_TX_DESCS];	/* skbuffs for packets to transmit */
+
+	struct net_device_stats stats;
+	spinlock_t lock;
+
+	int media;				/* Media (eg TP), mode (eg 100B)*/
+	int full_duplex;			/* Current duplex setting. */
+	int link_state;
+	char phys[32];				/* List of attached PHY devices */
+	char valid_phy;				/* Current linked phy-id with MAC */
+	int mii_phy_cnt;
+	int phy_type;				/* 1-RTL8309,0-DVCOM */
+	struct ethtool_cmd ecmds[32];
+	u16 advertising;			/* NWay media advertisement */
+
+	struct task_struct *thread;		/* Link check thread */
+	int thread_die;
+	struct completion thr_exited;
+	wait_queue_head_t thr_wait;
+
+	struct pm_dev *pmdev;
+
+	struct resource *iores;
+};
+
+#endif /* __JZ_ETH_H__ */
-- 
1.6.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] XBurst JZ4730 support
  2010-02-25  6:28 [PATCH 0/3] XBurst JZ4730 support Graham Gower
                   ` (2 preceding siblings ...)
  2010-02-25  6:31 ` [PATCH 3/3] net: add driver for JZ4730 ethernet controller Graham Gower
@ 2010-02-25  7:52 ` Florian Fainelli
  2010-02-25 21:12   ` Graham Gower
  3 siblings, 1 reply; 10+ messages in thread
From: Florian Fainelli @ 2010-02-25  7:52 UTC (permalink / raw)
  To: Graham Gower, Mirko Vogt, Lars-Peter Clausen; +Cc: linux-mips

Hi Graham,

On Thursday 25 February 2010 07:28:32 Graham Gower wrote:
> This patch set contains support for Ingenic's XBurst cpu, plus basic
> support for their JZ4730 reference boards.
> 
> 
> Graham Gower (3):
>   Add XBurst JZ4730 support.
>   8250: serial driver changes for XBurst SoCs.
>   net: add driver for JZ4730 ethernet controller.

Seems like patches 1 and 3 were too big and got retained by the mailing-list 
program.

Maybe you should work with the OpenWrt and qi-hardware guys to get the jz4740 
also merged in the same time?

> 
>  arch/mips/Kconfig                                |   13 +
>  arch/mips/Makefile                               |   14 +-
>  arch/mips/boot/Makefile                          |   15 +-
>  arch/mips/include/asm/bootinfo.h                 |    7 +
>  arch/mips/include/asm/cpu.h                      |    9 +
>  arch/mips/include/asm/mach-generic/irq.h         |    2 +-
>  arch/mips/include/asm/mach-xburst/clock-jz4730.h |   41 +
>  arch/mips/include/asm/mach-xburst/dma-jz4730.h   |  156 +++
>  arch/mips/include/asm/mach-xburst/irq-jz4730.h   |   33 +
>  arch/mips/include/asm/mach-xburst/uart-jz4730.h  |  141 +++
>  arch/mips/include/asm/mach-xburst/war.h          |   25 +
>  arch/mips/include/asm/mach-xburst/xburst.h       |   20 +
>  arch/mips/include/asm/r4kcache.h                 |  240 +++++
>  arch/mips/kernel/cpu-probe.c                     |   21 +
>  arch/mips/mm/c-r4k.c                             |   30 +
>  arch/mips/mm/tlbex.c                             |    5 +
>  arch/mips/xburst/Kconfig                         |   23 +
>  arch/mips/xburst/Makefile                        |    3 +
>  arch/mips/xburst/jz4730/Makefile                 |   11 +
>  arch/mips/xburst/jz4730/board-libra.c            |   32 +
>  arch/mips/xburst/jz4730/board-pmp.c              |   32 +
>  arch/mips/xburst/jz4730/clocks.c                 |  294 +++++
>  arch/mips/xburst/jz4730/irq.c                    |  104 ++
>  arch/mips/xburst/jz4730/platform.c               |   49 +
>  arch/mips/xburst/jz4730/prom.c                   |  104 ++
>  arch/mips/xburst/jz4730/setup.c                  |  136 +++
>  arch/mips/xburst/jz4730/time.c                   |  140 +++
>  drivers/net/Kconfig                              |   10 +
>  drivers/net/Makefile                             |    1 +
>  drivers/net/jz_eth.c                             | 1232
>  ++++++++++++++++++++++ drivers/net/jz_eth.h                             | 
>  403 +++++++
>  drivers/serial/8250.c                            |   12 +
>  32 files changed, 3355 insertions(+), 3 deletions(-)
>  create mode 100644 arch/mips/include/asm/mach-xburst/clock-jz4730.h
>  create mode 100644 arch/mips/include/asm/mach-xburst/dma-jz4730.h
>  create mode 100644 arch/mips/include/asm/mach-xburst/irq-jz4730.h
>  create mode 100644 arch/mips/include/asm/mach-xburst/uart-jz4730.h
>  create mode 100644 arch/mips/include/asm/mach-xburst/war.h
>  create mode 100644 arch/mips/include/asm/mach-xburst/xburst.h
>  create mode 100644 arch/mips/xburst/Kconfig
>  create mode 100644 arch/mips/xburst/Makefile
>  create mode 100644 arch/mips/xburst/jz4730/Makefile
>  create mode 100644 arch/mips/xburst/jz4730/board-libra.c
>  create mode 100644 arch/mips/xburst/jz4730/board-pmp.c
>  create mode 100644 arch/mips/xburst/jz4730/clocks.c
>  create mode 100644 arch/mips/xburst/jz4730/irq.c
>  create mode 100644 arch/mips/xburst/jz4730/platform.c
>  create mode 100644 arch/mips/xburst/jz4730/prom.c
>  create mode 100644 arch/mips/xburst/jz4730/setup.c
>  create mode 100644 arch/mips/xburst/jz4730/time.c
>  create mode 100644 drivers/net/jz_eth.c
>  create mode 100644 drivers/net/jz_eth.h
> 

-- 
Regards, Florian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] XBurst JZ4730 support
  2010-02-25  7:52 ` [PATCH 0/3] XBurst JZ4730 support Florian Fainelli
@ 2010-02-25 21:12   ` Graham Gower
  2010-02-26  1:51     ` Lars-Peter Clausen
  0 siblings, 1 reply; 10+ messages in thread
From: Graham Gower @ 2010-02-25 21:12 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Mirko Vogt, Lars-Peter Clausen, linux-mips

On 25 February 2010 18:22, Florian Fainelli <florian@openwrt.org> wrote:
> Hi Graham,
>
> On Thursday 25 February 2010 07:28:32 Graham Gower wrote:
>> This patch set contains support for Ingenic's XBurst cpu, plus basic
>> support for their JZ4730 reference boards.
>>
>>
>> Graham Gower (3):
>>   Add XBurst JZ4730 support.
>>   8250: serial driver changes for XBurst SoCs.
>>   net: add driver for JZ4730 ethernet controller.
>
> Seems like patches 1 and 3 were too big and got retained by the mailing-list
> program.

They seem to have made it to the list archives now. Thread here:
http://www.linux-mips.org/archives/linux-mips/2010-02/msg00243.html

>
> Maybe you should work with the OpenWrt and qi-hardware guys to get the jz4740
> also merged in the same time?
>

I've not seen any active attempt to get xburst code merged before and
assumed there was no interest from others. I'm happy to be wrong on
this.

My patch does not preclude adding jz4740 support. I don't have any of
these devices however, so have only included code for the jz4730.

-Graham

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] XBurst JZ4730 support
  2010-02-25 21:12   ` Graham Gower
@ 2010-02-26  1:51     ` Lars-Peter Clausen
  2010-02-26  3:34       ` Graham Gower
  0 siblings, 1 reply; 10+ messages in thread
From: Lars-Peter Clausen @ 2010-02-26  1:51 UTC (permalink / raw)
  To: Graham Gower; +Cc: Florian Fainelli, Mirko Vogt, linux-mips

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi

Graham Gower wrote:
> On 25 February 2010 18:22, Florian Fainelli <florian@openwrt.org> wrote:
>> Maybe you should work with the OpenWrt and qi-hardware guys to get the
jz4740
>> also merged in the same time?
>
> I've not seen any active attempt to get xburst code merged before and
> assumed there was no interest from others. I'm happy to be wrong on
> this.
I'm currently working on linux support for a few jz4740 hbased devices.
And it's definitely a goal get the code merged upstream once it is in
proper shape, but there is still some stuff that needs to be done.
Mostly documentation and smaller cleanups.
>
> My patch does not preclude adding jz4740 support. I don't have any of
> these devices however, so have only included code for the jz4730.
Unfortunately I don't have a jz4730 programmers manual to check so I
can't say for sure, but I guess there is quite some code that could be
shared between between both SoCS(and other jz47xx). I think we don't
want to do what Ingenic did with their codebase and copy 'n paste the
same file with minor modifications for each soc type.

You can find the patches (and files) adding jz4740 support to the
linux kernel at [1] and [2].
I suggest you take a look at it and see if we could use some of the
files(irq, gpio, dma, ...) for a common base between all jz47xx SoCs.
>
> -Graham
- - Lars

[1]
https://dev.openwrt.org/browser/trunk/target/linux/xburst/patches-2.6.32
[2] https://dev.openwrt.org/browser/trunk/target/linux/xburst/files-2.6.32
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkuHKQMACgkQBX4mSR26RiOGCgCdGzATziYC4wYLvz0HNhqwFOYi
OXAAn2mZx0e8qmqHtl+Vfm9vau9urpW+
=nIni
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] XBurst JZ4730 support
  2010-02-26  1:51     ` Lars-Peter Clausen
@ 2010-02-26  3:34       ` Graham Gower
  2010-02-26 11:41           ` Anoop P.A.
  0 siblings, 1 reply; 10+ messages in thread
From: Graham Gower @ 2010-02-26  3:34 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Florian Fainelli, Mirko Vogt, linux-mips

On 26 February 2010 12:21, Lars-Peter Clausen <lars@metafoo.de> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi
>
> Graham Gower wrote:
>> On 25 February 2010 18:22, Florian Fainelli <florian@openwrt.org> wrote:
>>> Maybe you should work with the OpenWrt and qi-hardware guys to get the
> jz4740
>>> also merged in the same time?
>>
>> I've not seen any active attempt to get xburst code merged before and
>> assumed there was no interest from others. I'm happy to be wrong on
>> this.
> I'm currently working on linux support for a few jz4740 hbased devices.
> And it's definitely a goal get the code merged upstream once it is in
> proper shape, but there is still some stuff that needs to be done.
> Mostly documentation and smaller cleanups.

I was hoping to get something simple (i.e. bootable with serial) into
the tree and submit other drivers later, as time permits.

>>
>> My patch does not preclude adding jz4740 support. I don't have any of
>> these devices however, so have only included code for the jz4730.
> Unfortunately I don't have a jz4730 programmers manual to check so I
> can't say for sure, but I guess there is quite some code that could be
> shared between between both SoCS(and other jz47xx). I think we don't
> want to do what Ingenic did with their codebase and copy 'n paste the
> same file with minor modifications for each soc type.

The 4740 docs are a copy/paste of the 4730 docs with changes here and
there and lots of register shuffling.

>
> You can find the patches (and files) adding jz4740 support to the
> linux kernel at [1] and [2].
> I suggest you take a look at it and see if we could use some of the
> files(irq, gpio, dma, ...) for a common base between all jz47xx SoCs.

The interrupt controllers look quite similar (the irq numbers have
been shuffled around). The gpio and dma controllers are quite
different however.

The MMC and LCD controllers look almost identical. I don't have any
docs for the nand, but Ingenic's code for the 4730 and 4740 look very
similar. The USB gadget code differs (udc controller info is missing
from my 4740 docs) - the jz4730 gadget driver they are shipping is
broken and they ignored my patch to fix it.


-Graham

^ permalink raw reply	[flat|nested] 10+ messages in thread

* blast_dcache32 problem with PREEMPT kernel
@ 2010-02-26 11:41           ` Anoop P.A.
  0 siblings, 0 replies; 10+ messages in thread
From: Anoop P.A. @ 2010-02-26 11:41 UTC (permalink / raw)
  To: linux-mips

Hi list,

I am hitting following bug with CONFIG_PREEMP enabled VSMP kernel (
2.6.24) compiled for mips34K core.


BUG: using smp_processor_id() in preemptible [00000001] code:
usb-storage/190
caller is blast_dcache32+0x30/0x25c
Call Trace:
[<8012f338>] vprintk+0x2e8/0x584
[<8012f354>] vprintk+0x304/0x584
[<801111a0>] blast_dcache32+0x30/0x25c
[<80387d5c>] debug_smp_processor_id+0xcc/0xe0
[<801111a0>] blast_dcache32+0x30/0x25c
[<80387d5c>] debug_smp_processor_id+0xcc/0xe0
[<801111a0>] blast_dcache32+0x30/0x25c
[<8010d9e4>] dma_map_sg+0x128/0x144
[<80410a84>] urb_destroy+0x0/0x38
[<801827b0>] kfree+0x8c/0x20c
[<80411944>] usb_sg_init+0x310/0x324
[<8042a708>] usb_stor_bulk_transfer_sg+0xd0/0x174
[<8042a914>] usb_stor_Bulk_transport+0x168/0x324
[<80121a94>] enqueue_entity+0xcc/0x130
[<8042a3f4>] usb_stor_invoke_transport+0x38/0x27c
[<80149ee8>] remove_wait_queue+0x1c/0x60
[<8054568c>] _spin_unlock_irqrestore+0x24/0x44
[<805425fc>] __down_interruptible+0x144/0x1e4
[<801239f0>] default_wake_function+0x0/0x8
[<8042bd58>] usb_stor_control_thread+0x268/0x320
[<801497c0>] kthread+0x0/0xa4
[<80149800>] kthread+0x40/0xa4
[<801241d8>] complete+0x4c/0x6c
[<8042baf0>] usb_stor_control_thread+0x0/0x320
[<80149818>] kthread+0x58/0xa4
[<8010476c>] kernel_thread_helper+0x10/0x18

Any pointers to debug this / fix this will be greatly appreciated.

Thanking you,

Anoop

^ permalink raw reply	[flat|nested] 10+ messages in thread

* blast_dcache32 problem with PREEMPT kernel
@ 2010-02-26 11:41           ` Anoop P.A.
  0 siblings, 0 replies; 10+ messages in thread
From: Anoop P.A. @ 2010-02-26 11:41 UTC (permalink / raw)
  To: linux-mips

Hi list,

I am hitting following bug with CONFIG_PREEMP enabled VSMP kernel (
2.6.24) compiled for mips34K core.


BUG: using smp_processor_id() in preemptible [00000001] code:
usb-storage/190
caller is blast_dcache32+0x30/0x25c
Call Trace:
[<8012f338>] vprintk+0x2e8/0x584
[<8012f354>] vprintk+0x304/0x584
[<801111a0>] blast_dcache32+0x30/0x25c
[<80387d5c>] debug_smp_processor_id+0xcc/0xe0
[<801111a0>] blast_dcache32+0x30/0x25c
[<80387d5c>] debug_smp_processor_id+0xcc/0xe0
[<801111a0>] blast_dcache32+0x30/0x25c
[<8010d9e4>] dma_map_sg+0x128/0x144
[<80410a84>] urb_destroy+0x0/0x38
[<801827b0>] kfree+0x8c/0x20c
[<80411944>] usb_sg_init+0x310/0x324
[<8042a708>] usb_stor_bulk_transfer_sg+0xd0/0x174
[<8042a914>] usb_stor_Bulk_transport+0x168/0x324
[<80121a94>] enqueue_entity+0xcc/0x130
[<8042a3f4>] usb_stor_invoke_transport+0x38/0x27c
[<80149ee8>] remove_wait_queue+0x1c/0x60
[<8054568c>] _spin_unlock_irqrestore+0x24/0x44
[<805425fc>] __down_interruptible+0x144/0x1e4
[<801239f0>] default_wake_function+0x0/0x8
[<8042bd58>] usb_stor_control_thread+0x268/0x320
[<801497c0>] kthread+0x0/0xa4
[<80149800>] kthread+0x40/0xa4
[<801241d8>] complete+0x4c/0x6c
[<8042baf0>] usb_stor_control_thread+0x0/0x320
[<80149818>] kthread+0x58/0xa4
[<8010476c>] kernel_thread_helper+0x10/0x18

Any pointers to debug this / fix this will be greatly appreciated.

Thanking you,

Anoop

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-02-26 11:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-25  6:28 [PATCH 0/3] XBurst JZ4730 support Graham Gower
2010-02-25  6:29 ` [PATCH 1/3] Add " Graham Gower
2010-02-25  6:30 ` [PATCH 2/3] 8250: serial driver changes for XBurst SoCs Graham Gower
2010-02-25  6:31 ` [PATCH 3/3] net: add driver for JZ4730 ethernet controller Graham Gower
2010-02-25  7:52 ` [PATCH 0/3] XBurst JZ4730 support Florian Fainelli
2010-02-25 21:12   ` Graham Gower
2010-02-26  1:51     ` Lars-Peter Clausen
2010-02-26  3:34       ` Graham Gower
2010-02-26 11:41         ` blast_dcache32 problem with PREEMPT kernel Anoop P.A.
2010-02-26 11:41           ` Anoop P.A.

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.