mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	cns21xx: add support for 3.2
SVN-Revision: 30971
This commit is contained in:
		
							parent
							
								
									45d5b24190
								
							
						
					
					
						commit
						6dbe40f7d4
					
				
							
								
								
									
										142
									
								
								target/linux/cns21xx/config-3.2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								target/linux/cns21xx/config-3.2
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,142 @@
 | 
			
		||||
CONFIG_ALIGNMENT_TRAP=y
 | 
			
		||||
CONFIG_ARCH_CNS21XX=y
 | 
			
		||||
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
 | 
			
		||||
CONFIG_ARCH_REQUIRE_GPIOLIB=y
 | 
			
		||||
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 | 
			
		||||
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 | 
			
		||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
 | 
			
		||||
# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
 | 
			
		||||
CONFIG_ARM=y
 | 
			
		||||
# CONFIG_ARM_CPU_SUSPEND is not set
 | 
			
		||||
CONFIG_ARM_L1_CACHE_SHIFT=4
 | 
			
		||||
CONFIG_ARM_L1_CACHE_SHIFT_4=y
 | 
			
		||||
# CONFIG_ARPD is not set
 | 
			
		||||
CONFIG_ATA=m
 | 
			
		||||
CONFIG_BCMA_POSSIBLE=y
 | 
			
		||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 | 
			
		||||
CONFIG_CMDLINE="console=ttyS0,38400 rootfstype=squashfs,jffs2 noinitrd"
 | 
			
		||||
CONFIG_CMDLINE_FROM_BOOTLOADER=y
 | 
			
		||||
CONFIG_CNS21XX_DEV_GEC=y
 | 
			
		||||
CONFIG_CNS21XX_DEV_SPI_MASTER=y
 | 
			
		||||
CONFIG_CNS21XX_DEV_USB=y
 | 
			
		||||
CONFIG_CNS21XX_GEC=y
 | 
			
		||||
CONFIG_CPU_32v4=y
 | 
			
		||||
CONFIG_CPU_ABRT_EV4=y
 | 
			
		||||
# CONFIG_CPU_BPREDICT_DISABLE is not set
 | 
			
		||||
CONFIG_CPU_CACHE_FA=y
 | 
			
		||||
CONFIG_CPU_CACHE_VIVT=y
 | 
			
		||||
CONFIG_CPU_COPY_FA=y
 | 
			
		||||
CONFIG_CPU_CP15=y
 | 
			
		||||
CONFIG_CPU_CP15_MMU=y
 | 
			
		||||
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 | 
			
		||||
CONFIG_CPU_FA526=y
 | 
			
		||||
# CONFIG_CPU_ICACHE_DISABLE is not set
 | 
			
		||||
CONFIG_CPU_PABRT_LEGACY=y
 | 
			
		||||
CONFIG_CPU_TLB_FA=y
 | 
			
		||||
CONFIG_CPU_USE_DOMAINS=y
 | 
			
		||||
# CONFIG_DEBUG_USER is not set
 | 
			
		||||
CONFIG_DECOMPRESS_LZMA=y
 | 
			
		||||
CONFIG_DLCI=m
 | 
			
		||||
CONFIG_DLCI_MAX=8
 | 
			
		||||
CONFIG_DMADEVICES=y
 | 
			
		||||
CONFIG_DNOTIFY=y
 | 
			
		||||
CONFIG_EEPROM_AT25=y
 | 
			
		||||
CONFIG_ELF_CORE=y
 | 
			
		||||
CONFIG_FA_WATCHDOG=y
 | 
			
		||||
CONFIG_FRAME_POINTER=y
 | 
			
		||||
CONFIG_GENERIC_ATOMIC64=y
 | 
			
		||||
CONFIG_GENERIC_BUG=y
 | 
			
		||||
CONFIG_GENERIC_GPIO=y
 | 
			
		||||
CONFIG_GENERIC_IRQ_SHOW=y
 | 
			
		||||
CONFIG_GPIOLIB=y
 | 
			
		||||
CONFIG_GPIO_SYSFS=y
 | 
			
		||||
# CONFIG_HAMRADIO is not set
 | 
			
		||||
CONFIG_HARDIRQS_SW_RESEND=y
 | 
			
		||||
CONFIG_HAS_DMA=y
 | 
			
		||||
CONFIG_HAS_IOMEM=y
 | 
			
		||||
CONFIG_HAS_IOPORT=y
 | 
			
		||||
CONFIG_HAVE_AOUT=y
 | 
			
		||||
CONFIG_HAVE_ARCH_KGDB=y
 | 
			
		||||
CONFIG_HAVE_ARCH_PFN_VALID=y
 | 
			
		||||
CONFIG_HAVE_C_RECORDMCOUNT=y
 | 
			
		||||
CONFIG_HAVE_DMA_API_DEBUG=y
 | 
			
		||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
 | 
			
		||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 | 
			
		||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 | 
			
		||||
CONFIG_HAVE_FUNCTION_TRACER=y
 | 
			
		||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 | 
			
		||||
CONFIG_HAVE_GENERIC_HARDIRQS=y
 | 
			
		||||
CONFIG_HAVE_IRQ_WORK=y
 | 
			
		||||
CONFIG_HAVE_KERNEL_GZIP=y
 | 
			
		||||
CONFIG_HAVE_KERNEL_LZMA=y
 | 
			
		||||
CONFIG_HAVE_KERNEL_LZO=y
 | 
			
		||||
CONFIG_HAVE_KERNEL_XZ=y
 | 
			
		||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 | 
			
		||||
CONFIG_HAVE_MEMBLOCK=y
 | 
			
		||||
CONFIG_HAVE_OPROFILE=y
 | 
			
		||||
CONFIG_HAVE_PERF_EVENTS=y
 | 
			
		||||
CONFIG_HAVE_PROC_CPU=y
 | 
			
		||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
 | 
			
		||||
CONFIG_HAVE_SPARSE_IRQ=y
 | 
			
		||||
CONFIG_HDLC=m
 | 
			
		||||
CONFIG_HDLC_CISCO=m
 | 
			
		||||
CONFIG_HDLC_FR=m
 | 
			
		||||
CONFIG_HDLC_PPP=m
 | 
			
		||||
CONFIG_HDLC_RAW=m
 | 
			
		||||
CONFIG_HWMON=y
 | 
			
		||||
# CONFIG_HWMON_DEBUG_CHIP is not set
 | 
			
		||||
CONFIG_HW_RANDOM=y
 | 
			
		||||
CONFIG_INITRAMFS_SOURCE=""
 | 
			
		||||
# CONFIG_IP_ADVANCED_ROUTER is not set
 | 
			
		||||
CONFIG_IP_PIMSM_V1=y
 | 
			
		||||
CONFIG_IP_PIMSM_V2=y
 | 
			
		||||
CONFIG_KTIME_SCALAR=y
 | 
			
		||||
# CONFIG_LEDS_GPIO is not set
 | 
			
		||||
CONFIG_LEGACY_PTYS=y
 | 
			
		||||
CONFIG_LEGACY_PTY_COUNT=256
 | 
			
		||||
CONFIG_M25PXX_USE_FAST_READ=y
 | 
			
		||||
CONFIG_MACH_NSB3AST=y
 | 
			
		||||
CONFIG_MACH_NS_K330=y
 | 
			
		||||
CONFIG_MDIO_BOARDINFO=y
 | 
			
		||||
# CONFIG_MTD_CFI is not set
 | 
			
		||||
CONFIG_MTD_M25P80=y
 | 
			
		||||
CONFIG_NEED_DMA_MAP_STATE=y
 | 
			
		||||
CONFIG_NEED_PER_CPU_KM=y
 | 
			
		||||
CONFIG_NLS=m
 | 
			
		||||
CONFIG_PAGEFLAGS_EXTENDED=y
 | 
			
		||||
CONFIG_PAGE_OFFSET=0xC0000000
 | 
			
		||||
# CONFIG_PCI_SYSCALL is not set
 | 
			
		||||
CONFIG_PERF_USE_VMALLOC=y
 | 
			
		||||
CONFIG_PHYLIB=y
 | 
			
		||||
CONFIG_PHYS_OFFSET=0x00000000
 | 
			
		||||
CONFIG_PLAT_FA=y
 | 
			
		||||
CONFIG_PLAT_FA_GPIO=y
 | 
			
		||||
CONFIG_PLAT_FA_TIME=y
 | 
			
		||||
# CONFIG_PREEMPT_RCU is not set
 | 
			
		||||
# CONFIG_QUOTACTL is not set
 | 
			
		||||
CONFIG_SCSI=m
 | 
			
		||||
CONFIG_SCSI_MOD=m
 | 
			
		||||
# CONFIG_SCSI_MULTI_LUN is not set
 | 
			
		||||
# CONFIG_SENSORS_SCH56XX_COMMON is not set
 | 
			
		||||
CONFIG_SERIO=y
 | 
			
		||||
CONFIG_SERIO_LIBPS2=y
 | 
			
		||||
# CONFIG_SERIO_RAW is not set
 | 
			
		||||
CONFIG_SERIO_SERPORT=y
 | 
			
		||||
CONFIG_SPI=y
 | 
			
		||||
CONFIG_SPI_BITBANG=y
 | 
			
		||||
CONFIG_SPI_CNS21XX=y
 | 
			
		||||
CONFIG_SPI_DEBUG=y
 | 
			
		||||
# CONFIG_SPI_GPIO is not set
 | 
			
		||||
CONFIG_SPI_MASTER=y
 | 
			
		||||
CONFIG_SPLIT_PTLOCK_CPUS=999999
 | 
			
		||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 | 
			
		||||
CONFIG_UID16=y
 | 
			
		||||
# CONFIG_USB_ARCH_HAS_XHCI is not set
 | 
			
		||||
CONFIG_USB_SUPPORT=y
 | 
			
		||||
CONFIG_VECTORS_BASE=0xffff0000
 | 
			
		||||
CONFIG_VM_EVENT_COUNTERS=y
 | 
			
		||||
CONFIG_WAN=y
 | 
			
		||||
CONFIG_XZ_DEC=y
 | 
			
		||||
CONFIG_ZBOOT_ROM_BSS=0x0
 | 
			
		||||
CONFIG_ZBOOT_ROM_TEXT=0x0
 | 
			
		||||
CONFIG_ZONE_DMA_FLAG=0
 | 
			
		||||
@ -0,0 +1,24 @@
 | 
			
		||||
--- a/kernel/printk.c
 | 
			
		||||
+++ b/kernel/printk.c
 | 
			
		||||
@@ -44,6 +44,10 @@
 | 
			
		||||
 
 | 
			
		||||
 #include <asm/uaccess.h>
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_DEBUG_LL
 | 
			
		||||
+extern void printascii(char *);
 | 
			
		||||
+#endif /* CONFIG_DEBUG_LL */
 | 
			
		||||
+
 | 
			
		||||
 /*
 | 
			
		||||
  * Architectures can override it:
 | 
			
		||||
  */
 | 
			
		||||
@@ -897,6 +901,10 @@ asmlinkage int vprintk(const char *fmt,
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_DEBUG_LL
 | 
			
		||||
+	printascii(printk_buf);
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 	/*
 | 
			
		||||
 	 * Copy the output into log_buf. If the caller didn't provide
 | 
			
		||||
 	 * the appropriate log prefix, we insert them here
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
--- a/arch/arm/Kconfig
 | 
			
		||||
+++ b/arch/arm/Kconfig
 | 
			
		||||
@@ -1100,10 +1100,15 @@ source "arch/arm/mach-vt8500/Kconfig"
 | 
			
		||||
 
 | 
			
		||||
 source "arch/arm/mach-w90x900/Kconfig"
 | 
			
		||||
 
 | 
			
		||||
+source "arch/arm/plat-fa/Kconfig"
 | 
			
		||||
+
 | 
			
		||||
 # Definitions to make life easier
 | 
			
		||||
 config ARCH_ACORN
 | 
			
		||||
 	bool
 | 
			
		||||
 
 | 
			
		||||
+config PLAT_FA
 | 
			
		||||
+	bool
 | 
			
		||||
+
 | 
			
		||||
 config PLAT_IOP
 | 
			
		||||
 	bool
 | 
			
		||||
 	select GENERIC_CLOCKEVENTS
 | 
			
		||||
--- a/arch/arm/Makefile
 | 
			
		||||
+++ b/arch/arm/Makefile
 | 
			
		||||
@@ -206,6 +206,7 @@ plat-$(CONFIG_ARCH_OMAP)	:= omap
 | 
			
		||||
 plat-$(CONFIG_ARCH_S3C64XX)	:= samsung
 | 
			
		||||
 plat-$(CONFIG_ARCH_TCC_926)	:= tcc
 | 
			
		||||
 plat-$(CONFIG_ARCH_ZYNQ)	:= versatile
 | 
			
		||||
+plat-$(CONFIG_PLAT_FA)		:= fa
 | 
			
		||||
 plat-$(CONFIG_PLAT_IOP)		:= iop
 | 
			
		||||
 plat-$(CONFIG_PLAT_NOMADIK)	:= nomadik
 | 
			
		||||
 plat-$(CONFIG_PLAT_ORION)	:= orion
 | 
			
		||||
@@ -304,7 +305,7 @@ define archhelp
 | 
			
		||||
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
 | 
			
		||||
   echo  '* xipImage      - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
 | 
			
		||||
   echo  '  uImage        - U-Boot wrapped zImage'
 | 
			
		||||
-  echo  '  bootpImage    - Combined zImage and initial RAM disk' 
 | 
			
		||||
+  echo  '  bootpImage    - Combined zImage and initial RAM disk'
 | 
			
		||||
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
 | 
			
		||||
   echo  '  dtbs          - Build device tree blobs for enabled boards'
 | 
			
		||||
   echo  '  install       - Install uncompressed kernel'
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/plat-fa/Makefile
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
+#
 | 
			
		||||
+# Makefile for the linux kernel.
 | 
			
		||||
+#
 | 
			
		||||
+
 | 
			
		||||
+obj-y :=
 | 
			
		||||
+
 | 
			
		||||
+obj-m :=
 | 
			
		||||
+obj-n :=
 | 
			
		||||
+obj-  :=
 | 
			
		||||
+
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/plat-fa/Kconfig
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
+if PLAT_FA
 | 
			
		||||
+
 | 
			
		||||
+endif
 | 
			
		||||
							
								
								
									
										143
									
								
								target/linux/cns21xx/patches-3.2/004-arm-add-fa-time.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								target/linux/cns21xx/patches-3.2/004-arm-add-fa-time.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,143 @@
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/plat-fa/include/plat/time.h
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
+ * it under the terms of the GNU General Public License as published by
 | 
			
		||||
+ * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
+ * (at your option) any later version.
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#ifndef _FA_TIME_H
 | 
			
		||||
+#define _FA_TIME_H
 | 
			
		||||
+
 | 
			
		||||
+#define FA_TIMER1	0
 | 
			
		||||
+#define FA_TIMER2	1
 | 
			
		||||
+#define FA_TIMER3	2
 | 
			
		||||
+
 | 
			
		||||
+int __init fa_timer_init(unsigned int mapbase, unsigned int irq,
 | 
			
		||||
+			 unsigned int timer, unsigned int freq);
 | 
			
		||||
+
 | 
			
		||||
+#endif /* _FA_TIME_H */
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/plat-fa/time.c
 | 
			
		||||
@@ -0,0 +1,97 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (C) 2001-2006 Storlink, Corp.
 | 
			
		||||
+ *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
+ * it under the terms of the GNU General Public License 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/interrupt.h>
 | 
			
		||||
+#include <linux/irq.h>
 | 
			
		||||
+#include <linux/io.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <asm/mach/time.h>
 | 
			
		||||
+#include <plat/time.h>
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Register definitions for the timers
 | 
			
		||||
+ */
 | 
			
		||||
+#define TIMER_COUNT(_base, _tmr)	((_base) + 0x00 + (_tmr) * 0x10)
 | 
			
		||||
+#define TIMER_LOAD(_base, _tmr)		((_base) + 0x04 + (_tmr) * 0x10)
 | 
			
		||||
+#define TIMER_MATCH1(_base, _tmr)	((_base) + 0x08 + (_tmr) * 0x10)
 | 
			
		||||
+#define TIMER_MATCH2(_base, _tmr)	((_base) + 0x0c + (_tmr) * 0x10)
 | 
			
		||||
+
 | 
			
		||||
+#define TIMER_CR(_base)			((_base) + 0x30)
 | 
			
		||||
+#define TIMER_STATUS(_base)		((_base) + 0x34)
 | 
			
		||||
+#define TIMER_MASK(_base)		((_base) + 0x38)
 | 
			
		||||
+
 | 
			
		||||
+#define TIMER_SIZE		0x3c
 | 
			
		||||
+
 | 
			
		||||
+#define TIMER_CR_ENABLE(x)	(1 << ((x) * 3))
 | 
			
		||||
+#define TIMER_CR_CLOCK(x)	(1 << ((x) * 3 + 1))
 | 
			
		||||
+#define TIMER_CR_INT(x)		(1 << ((x) * 3 + 2))
 | 
			
		||||
+#define TIMER_CR_DOWN(x)	(1 << ((x) * 3 + 9))
 | 
			
		||||
+
 | 
			
		||||
+#define TIMER_MASK_MATCH1(x)	(1 << ((x) * 3))
 | 
			
		||||
+#define TIMER_MASK_MATCH2(x)	(1 << ((x) * 3 + 1))
 | 
			
		||||
+#define TIMER_MASK_OF(x)	(1 << ((x) * 3 + 2))
 | 
			
		||||
+
 | 
			
		||||
+#define TIMER_MASK_ALL		0x7ff
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * IRQ handler for the timer
 | 
			
		||||
+ */
 | 
			
		||||
+static irqreturn_t fa_timer_interrupt(int irq, void *dev_id)
 | 
			
		||||
+{
 | 
			
		||||
+	timer_tick();
 | 
			
		||||
+	return IRQ_HANDLED;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct irqaction fa_timer_irq = {
 | 
			
		||||
+	.name		= "Timer Tick",
 | 
			
		||||
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
 | 
			
		||||
+	.handler	= fa_timer_interrupt,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+int __init fa_timer_init(unsigned int mapbase, unsigned int irq,
 | 
			
		||||
+			 unsigned int timer, unsigned int freq)
 | 
			
		||||
+{
 | 
			
		||||
+	void __iomem *base;
 | 
			
		||||
+
 | 
			
		||||
+	base = ioremap(mapbase, TIMER_SIZE);
 | 
			
		||||
+	if (!base)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+	/* disable timers, clear status and mask all interrupts */
 | 
			
		||||
+	__raw_writel(0, TIMER_CR(base));
 | 
			
		||||
+	__raw_writel(0, TIMER_STATUS(base));
 | 
			
		||||
+	__raw_writel(TIMER_MASK_ALL, TIMER_MASK(base));
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * Make irqs happen for the system timer
 | 
			
		||||
+	 */
 | 
			
		||||
+	setup_irq(irq, &fa_timer_irq);
 | 
			
		||||
+
 | 
			
		||||
+	/* Setup the timer */
 | 
			
		||||
+	__raw_writel(freq / HZ, TIMER_COUNT(base, timer));
 | 
			
		||||
+	__raw_writel(freq / HZ, TIMER_LOAD(base, timer));
 | 
			
		||||
+	__raw_writel(0, TIMER_MATCH1(base, timer));
 | 
			
		||||
+	__raw_writel(0, TIMER_MATCH2(base, timer));
 | 
			
		||||
+
 | 
			
		||||
+	/* Enable interrupt and start the timer */
 | 
			
		||||
+	__raw_writel(TIMER_MASK_ALL & ~TIMER_MASK_OF(timer),
 | 
			
		||||
+		     TIMER_MASK(base));
 | 
			
		||||
+
 | 
			
		||||
+	__raw_writel(TIMER_CR_ENABLE(timer) |
 | 
			
		||||
+		     TIMER_CR_INT(timer) |
 | 
			
		||||
+		     TIMER_CR_DOWN(timer),
 | 
			
		||||
+		     TIMER_CR(base));
 | 
			
		||||
+
 | 
			
		||||
+	iounmap(base);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
--- a/arch/arm/plat-fa/Kconfig
 | 
			
		||||
+++ b/arch/arm/plat-fa/Kconfig
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
 if PLAT_FA
 | 
			
		||||
 
 | 
			
		||||
+config PLAT_FA_TIME
 | 
			
		||||
+	def_bool n
 | 
			
		||||
+
 | 
			
		||||
 endif
 | 
			
		||||
--- a/arch/arm/plat-fa/Makefile
 | 
			
		||||
+++ b/arch/arm/plat-fa/Makefile
 | 
			
		||||
@@ -4,6 +4,8 @@
 | 
			
		||||
 
 | 
			
		||||
 obj-y :=
 | 
			
		||||
 
 | 
			
		||||
+obj-$(CONFIG_PLAT_FA_TIME)	+= time.o
 | 
			
		||||
+
 | 
			
		||||
 obj-m :=
 | 
			
		||||
 obj-n :=
 | 
			
		||||
 obj-  :=
 | 
			
		||||
@ -0,0 +1,343 @@
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/plat-fa/gpio.c
 | 
			
		||||
@@ -0,0 +1,283 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ * Gpiochip and interrupt routines for Faraday FA526 based SoCs
 | 
			
		||||
+ *
 | 
			
		||||
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 | 
			
		||||
+ * Copyright (C) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ * Based on plat-mxc/gpio.c:
 | 
			
		||||
+ *  MXC GPIO supchip. (c) 2008 Daniel Mack <daniel@caiaq.de>
 | 
			
		||||
+ *  Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 | 
			
		||||
+ *
 | 
			
		||||
+ * 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/spinlock.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <plat/gpio.h>
 | 
			
		||||
+
 | 
			
		||||
+#define GPIO_DATA_OUT		0x0
 | 
			
		||||
+#define GPIO_DATA_IN		0x4
 | 
			
		||||
+#define GPIO_DIR		0x8
 | 
			
		||||
+#define GPIO_DATA_SET		0x10
 | 
			
		||||
+#define GPIO_DATA_CLR		0x14
 | 
			
		||||
+#define GPIO_PULL_EN		0x18
 | 
			
		||||
+#define GPIO_PULL_TYPE		0x1C
 | 
			
		||||
+#define GPIO_INT_EN		0x20
 | 
			
		||||
+#define GPIO_INT_STAT		0x24
 | 
			
		||||
+#define GPIO_INT_MASK		0x2C
 | 
			
		||||
+#define GPIO_INT_CLR		0x30
 | 
			
		||||
+#define GPIO_INT_TYPE		0x34
 | 
			
		||||
+#define GPIO_INT_BOTH_EDGE	0x38
 | 
			
		||||
+#define GPIO_INT_LEVEL		0x3C
 | 
			
		||||
+#define GPIO_DEBOUNCE_EN	0x40
 | 
			
		||||
+#define GPIO_DEBOUNCE_PRESCALE	0x44
 | 
			
		||||
+
 | 
			
		||||
+#define GPIO_REGS_SIZE		0x48
 | 
			
		||||
+
 | 
			
		||||
+static DEFINE_SPINLOCK(fa_gpio_lock);
 | 
			
		||||
+
 | 
			
		||||
+static inline struct fa_gpio_chip *to_fgc(struct gpio_chip *chip)
 | 
			
		||||
+{
 | 
			
		||||
+	return container_of(chip, struct fa_gpio_chip, gpio_chip);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void _fa_gpio_irq_setenable(struct irq_data *d, int enable)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq);
 | 
			
		||||
+	void __iomem *base = fgc->mem_base;
 | 
			
		||||
+	unsigned int gpio = d->irq - fgc->irq_base;
 | 
			
		||||
+	unsigned int reg;
 | 
			
		||||
+
 | 
			
		||||
+	reg = __raw_readl(base + GPIO_INT_EN);
 | 
			
		||||
+	reg = (reg & (~(1 << gpio))) | (!!enable << gpio);
 | 
			
		||||
+	__raw_writel(reg, base + GPIO_INT_EN);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void fa_gpio_irq_ack(struct irq_data *d)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq);
 | 
			
		||||
+	unsigned int gpio = d->irq - fgc->irq_base;
 | 
			
		||||
+
 | 
			
		||||
+	__raw_writel(1 << gpio, fgc->mem_base + GPIO_INT_CLR);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void fa_gpio_irq_mask(struct irq_data *d)
 | 
			
		||||
+{
 | 
			
		||||
+	_fa_gpio_irq_setenable(d, 0);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void fa_gpio_irq_unmask(struct irq_data *d)
 | 
			
		||||
+{
 | 
			
		||||
+	_fa_gpio_irq_setenable(d, 1);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = irq_get_chip_data(d->irq);
 | 
			
		||||
+	void __iomem *base = fgc->mem_base;
 | 
			
		||||
+	unsigned int gpio = d->irq - fgc->irq_base;
 | 
			
		||||
+	unsigned int gpio_mask = 1 << gpio;
 | 
			
		||||
+	unsigned int reg_both, reg_level, reg_type;
 | 
			
		||||
+
 | 
			
		||||
+	reg_type = __raw_readl(base + GPIO_INT_TYPE);
 | 
			
		||||
+	reg_level = __raw_readl(base + GPIO_INT_LEVEL);
 | 
			
		||||
+	reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
 | 
			
		||||
+
 | 
			
		||||
+	switch (type) {
 | 
			
		||||
+	case IRQ_TYPE_EDGE_BOTH:
 | 
			
		||||
+		reg_type &= ~gpio_mask;
 | 
			
		||||
+		reg_both |= gpio_mask;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case IRQ_TYPE_EDGE_RISING:
 | 
			
		||||
+		reg_type &= ~gpio_mask;
 | 
			
		||||
+		reg_both &= ~gpio_mask;
 | 
			
		||||
+		reg_level &= ~gpio_mask;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case IRQ_TYPE_EDGE_FALLING:
 | 
			
		||||
+		reg_type &= ~gpio_mask;
 | 
			
		||||
+		reg_both &= ~gpio_mask;
 | 
			
		||||
+		reg_level |= gpio_mask;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case IRQ_TYPE_LEVEL_HIGH:
 | 
			
		||||
+		reg_type |= gpio_mask;
 | 
			
		||||
+		reg_level &= ~gpio_mask;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case IRQ_TYPE_LEVEL_LOW:
 | 
			
		||||
+		reg_type |= gpio_mask;
 | 
			
		||||
+		reg_level |= gpio_mask;
 | 
			
		||||
+		break;
 | 
			
		||||
+	default:
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	__raw_writel(reg_type, base + GPIO_INT_TYPE);
 | 
			
		||||
+	__raw_writel(reg_level, base + GPIO_INT_LEVEL);
 | 
			
		||||
+	__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
 | 
			
		||||
+
 | 
			
		||||
+	fa_gpio_irq_ack(d);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void fa_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_data *data = irq_get_handler_data(irq);
 | 
			
		||||
+	unsigned int chip;
 | 
			
		||||
+
 | 
			
		||||
+	for (chip = 0; chip < data->nchips; chip++) {
 | 
			
		||||
+		struct fa_gpio_chip *fgc = &data->chips[chip];
 | 
			
		||||
+		unsigned int status;
 | 
			
		||||
+		unsigned int i;
 | 
			
		||||
+
 | 
			
		||||
+		status = __raw_readl(fgc->mem_base + GPIO_INT_STAT);
 | 
			
		||||
+		for (i = fgc->irq_base; status != 0; status >>= 1, i++) {
 | 
			
		||||
+			if ((status & 1) == 0)
 | 
			
		||||
+				continue;
 | 
			
		||||
+
 | 
			
		||||
+			BUG_ON(!(irq_desc[i].handle_irq));
 | 
			
		||||
+			irq_desc[i].handle_irq(i, &irq_desc[i]);
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct irq_chip fa_gpio_irq_chip = {
 | 
			
		||||
+	.name		= "GPIO",
 | 
			
		||||
+	.irq_ack	= fa_gpio_irq_ack,
 | 
			
		||||
+	.irq_mask	= fa_gpio_irq_mask,
 | 
			
		||||
+	.irq_unmask	= fa_gpio_irq_unmask,
 | 
			
		||||
+	.irq_set_type	= fa_gpio_irq_set_type,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void _fa_gpio_set_direction(struct fa_gpio_chip *fgc, unsigned offset,
 | 
			
		||||
+				   int is_output)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int reg;
 | 
			
		||||
+
 | 
			
		||||
+	reg = __raw_readl(fgc->mem_base + GPIO_DIR);
 | 
			
		||||
+	if (is_output)
 | 
			
		||||
+		reg |= 1 << offset;
 | 
			
		||||
+	else
 | 
			
		||||
+		reg &= ~(1 << offset);
 | 
			
		||||
+	__raw_writel(reg, fgc->mem_base + GPIO_DIR);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void _fa_gpio_set(struct fa_gpio_chip *fgc, unsigned offset, int value)
 | 
			
		||||
+{
 | 
			
		||||
+	if (value)
 | 
			
		||||
+		__raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_SET);
 | 
			
		||||
+	else
 | 
			
		||||
+		__raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_CLR);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void fa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = to_fgc(chip);
 | 
			
		||||
+
 | 
			
		||||
+	_fa_gpio_set(fgc, offset, value);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_gpio_get(struct gpio_chip *chip, unsigned offset)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = to_fgc(chip);
 | 
			
		||||
+
 | 
			
		||||
+	return (__raw_readl(fgc->mem_base + GPIO_DATA_IN) >> offset) & 1;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = to_fgc(chip);
 | 
			
		||||
+
 | 
			
		||||
+	return fgc->irq_base + offset;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = to_fgc(chip);
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
+
 | 
			
		||||
+	spin_lock_irqsave(&fa_gpio_lock, flags);
 | 
			
		||||
+
 | 
			
		||||
+	_fa_gpio_set_direction(fgc, offset, 0);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock_irqrestore(&fa_gpio_lock, flags);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_gpio_direction_output(struct gpio_chip *chip,
 | 
			
		||||
+				    unsigned offset,
 | 
			
		||||
+				    int value)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_gpio_chip *fgc = to_fgc(chip);
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
+
 | 
			
		||||
+	spin_lock_irqsave(&fa_gpio_lock, flags);
 | 
			
		||||
+
 | 
			
		||||
+	_fa_gpio_set(fgc, offset, value);
 | 
			
		||||
+	_fa_gpio_set_direction(fgc, offset, 1);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock_irqrestore(&fa_gpio_lock, flags);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_gpio_init_chip(struct fa_gpio_chip *fgc)
 | 
			
		||||
+{
 | 
			
		||||
+	void __iomem *mem_base;
 | 
			
		||||
+	unsigned int i;
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	mem_base = ioremap(fgc->map_base, GPIO_REGS_SIZE);
 | 
			
		||||
+	if (!mem_base)
 | 
			
		||||
+		return -ENXIO;
 | 
			
		||||
+
 | 
			
		||||
+	fgc->mem_base = mem_base;
 | 
			
		||||
+
 | 
			
		||||
+	fgc->gpio_chip.direction_input = fa_gpio_direction_input;
 | 
			
		||||
+	fgc->gpio_chip.direction_output = fa_gpio_direction_output;
 | 
			
		||||
+	fgc->gpio_chip.get = fa_gpio_get;
 | 
			
		||||
+	fgc->gpio_chip.set = fa_gpio_set;
 | 
			
		||||
+	fgc->gpio_chip.to_irq = fa_gpio_to_irq;
 | 
			
		||||
+
 | 
			
		||||
+	/* disable, unmask and clear all interrupts */
 | 
			
		||||
+	__raw_writel(0x0, mem_base + GPIO_INT_EN);
 | 
			
		||||
+	__raw_writel(0x0, mem_base + GPIO_INT_MASK);
 | 
			
		||||
+	__raw_writel(~0x0, mem_base + GPIO_INT_CLR);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = fgc->irq_base;
 | 
			
		||||
+	     i < fgc->irq_base + fgc->gpio_chip.ngpio; i++) {
 | 
			
		||||
+		irq_set_chip(i, &fa_gpio_irq_chip);
 | 
			
		||||
+		irq_set_chip_data(i, fgc);
 | 
			
		||||
+		irq_set_handler(i, handle_edge_irq);
 | 
			
		||||
+		set_irq_flags(i, IRQF_VALID);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	err = gpiochip_add(&fgc->gpio_chip);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		goto unmap;
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+ unmap:
 | 
			
		||||
+	iounmap(fgc->mem_base);
 | 
			
		||||
+	return err;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+void __init fa_gpio_init(struct fa_gpio_data *data)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int i;
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < data->nchips; i++) {
 | 
			
		||||
+		int err;
 | 
			
		||||
+
 | 
			
		||||
+		err = fa_gpio_init_chip(&data->chips[i]);
 | 
			
		||||
+		if (WARN(err, "GPIO init failed\n"))
 | 
			
		||||
+			return;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	irq_set_chained_handler(data->irq, fa_gpio_irq_handler);
 | 
			
		||||
+	irq_set_handler_data(data->irq, data);
 | 
			
		||||
+}
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/plat-fa/include/plat/gpio.h
 | 
			
		||||
@@ -0,0 +1,33 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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 _FA_GPIO_H
 | 
			
		||||
+#define _FA_GPIO_H
 | 
			
		||||
+
 | 
			
		||||
+#include <linux/init.h>
 | 
			
		||||
+#include <linux/gpio.h>
 | 
			
		||||
+#include <linux/irq.h>
 | 
			
		||||
+#include <linux/io.h>
 | 
			
		||||
+
 | 
			
		||||
+struct fa_gpio_chip {
 | 
			
		||||
+	struct gpio_chip	gpio_chip;
 | 
			
		||||
+	unsigned int		map_base;
 | 
			
		||||
+	unsigned int		irq_base;
 | 
			
		||||
+
 | 
			
		||||
+	void __iomem		*mem_base;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct fa_gpio_data {
 | 
			
		||||
+	struct fa_gpio_chip	*chips;
 | 
			
		||||
+	unsigned int		nchips;
 | 
			
		||||
+	unsigned int		irq;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+void __init fa_gpio_init(struct fa_gpio_data *data);
 | 
			
		||||
+
 | 
			
		||||
+#endif /* _FA_GPIO_H */
 | 
			
		||||
--- a/arch/arm/plat-fa/Kconfig
 | 
			
		||||
+++ b/arch/arm/plat-fa/Kconfig
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
 if PLAT_FA
 | 
			
		||||
 
 | 
			
		||||
+config PLAT_FA_GPIO
 | 
			
		||||
+	def_bool n
 | 
			
		||||
+
 | 
			
		||||
 config PLAT_FA_TIME
 | 
			
		||||
 	def_bool n
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/arm/plat-fa/Makefile
 | 
			
		||||
+++ b/arch/arm/plat-fa/Makefile
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
 
 | 
			
		||||
 obj-y :=
 | 
			
		||||
 
 | 
			
		||||
+obj-$(CONFIG_PLAT_FA_GPIO)	+= gpio.o
 | 
			
		||||
 obj-$(CONFIG_PLAT_FA_TIME)	+= time.o
 | 
			
		||||
 
 | 
			
		||||
 obj-m :=
 | 
			
		||||
@ -0,0 +1,458 @@
 | 
			
		||||
--- a/drivers/watchdog/Kconfig
 | 
			
		||||
+++ b/drivers/watchdog/Kconfig
 | 
			
		||||
@@ -343,6 +343,13 @@ config IMX2_WDT
 | 
			
		||||
 	  To compile this driver as a module, choose M here: the
 | 
			
		||||
 	  module will be called imx2_wdt.
 | 
			
		||||
 
 | 
			
		||||
+config FA_WATCHDOG
 | 
			
		||||
+	tristate "Faraday watchdog"
 | 
			
		||||
+	depends on ARCH_GEMINI
 | 
			
		||||
+	help
 | 
			
		||||
+	  Say Y here if you want support for the built-in watchdog timer
 | 
			
		||||
+	  found in some Faraday FA526 based SoCs.
 | 
			
		||||
+
 | 
			
		||||
 # AVR32 Architecture
 | 
			
		||||
 
 | 
			
		||||
 config AT32AP700X_WDT
 | 
			
		||||
--- a/drivers/watchdog/Makefile
 | 
			
		||||
+++ b/drivers/watchdog/Makefile
 | 
			
		||||
@@ -53,6 +53,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3
 | 
			
		||||
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
 | 
			
		||||
 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 | 
			
		||||
 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
 | 
			
		||||
+obj-$(CONFIG_FA_WATCHDOG) += fa_wdt.o
 | 
			
		||||
 
 | 
			
		||||
 # AVR32 Architecture
 | 
			
		||||
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/drivers/watchdog/fa_wdt.c
 | 
			
		||||
@@ -0,0 +1,413 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Watchdog driver for SoCs based on the Faraday FA526 core
 | 
			
		||||
+ *
 | 
			
		||||
+ *  Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 | 
			
		||||
+ *  Copyright (C) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
+ * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
+ * published by the Free Software Foundation.
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#include <linux/kernel.h>
 | 
			
		||||
+#include <linux/module.h>
 | 
			
		||||
+#include <linux/init.h>
 | 
			
		||||
+#include <linux/io.h>
 | 
			
		||||
+#include <linux/fs.h>
 | 
			
		||||
+#include <linux/notifier.h>
 | 
			
		||||
+#include <linux/reboot.h>
 | 
			
		||||
+#include <linux/uaccess.h>
 | 
			
		||||
+#include <linux/miscdevice.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/watchdog.h>
 | 
			
		||||
+#include <linux/slab.h>
 | 
			
		||||
+#include <linux/fa_wdt.h>
 | 
			
		||||
+
 | 
			
		||||
+#define FA_WDCOUNTER		0x0
 | 
			
		||||
+#define FA_WDLOAD		0x4
 | 
			
		||||
+#define FA_WDRESTART		0x8
 | 
			
		||||
+
 | 
			
		||||
+#define WDRESTART_MAGIC		0x5AB9
 | 
			
		||||
+
 | 
			
		||||
+#define FA_WDCR			0xC
 | 
			
		||||
+
 | 
			
		||||
+#define WDCR_CLOCK_5MHZ		(1 << 4)
 | 
			
		||||
+#define WDCR_SYS_RST		(1 << 1)
 | 
			
		||||
+#define WDCR_ENABLE		(1 << 0)
 | 
			
		||||
+
 | 
			
		||||
+#define WDT_DEFAULT_TIMEOUT	13
 | 
			
		||||
+
 | 
			
		||||
+/* status bits */
 | 
			
		||||
+#define WDT_ACTIVE		0
 | 
			
		||||
+#define WDT_OK_TO_CLOSE		1
 | 
			
		||||
+
 | 
			
		||||
+static unsigned int timeout = WDT_DEFAULT_TIMEOUT;
 | 
			
		||||
+static int nowayout = WATCHDOG_NOWAYOUT;
 | 
			
		||||
+
 | 
			
		||||
+static DEFINE_SPINLOCK(fa_wdt_lock);
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device *fa_wdt_dev;
 | 
			
		||||
+
 | 
			
		||||
+struct fa_wdt_struct {
 | 
			
		||||
+	struct resource		*res;
 | 
			
		||||
+	struct device		*dev;
 | 
			
		||||
+	void __iomem		*base;
 | 
			
		||||
+	unsigned long		status;
 | 
			
		||||
+	unsigned int		clock;
 | 
			
		||||
+	unsigned int		max_timeout;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static const struct watchdog_info fa_wdt_info = {
 | 
			
		||||
+	.identity	= "Faraday watchdog",
 | 
			
		||||
+	.options	= WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
 | 
			
		||||
+			  WDIOF_SETTIMEOUT,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+/* Disable the watchdog. */
 | 
			
		||||
+static void fa_wdt_stop(struct fa_wdt_struct *fa_wdt)
 | 
			
		||||
+{
 | 
			
		||||
+	spin_lock(&fa_wdt_lock);
 | 
			
		||||
+
 | 
			
		||||
+	__raw_writel(0, fa_wdt->base + FA_WDCR);
 | 
			
		||||
+
 | 
			
		||||
+	clear_bit(WDT_ACTIVE, &fa_wdt->status);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock(&fa_wdt_lock);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Service the watchdog */
 | 
			
		||||
+static void fa_wdt_service(struct fa_wdt_struct *fa_wdt)
 | 
			
		||||
+{
 | 
			
		||||
+	__raw_writel(WDRESTART_MAGIC, fa_wdt->base + FA_WDRESTART);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Enable and reset the watchdog. */
 | 
			
		||||
+static void fa_wdt_start(struct fa_wdt_struct *fa_wdt)
 | 
			
		||||
+{
 | 
			
		||||
+	spin_lock(&fa_wdt_lock);
 | 
			
		||||
+
 | 
			
		||||
+	__raw_writel(timeout * fa_wdt->clock,
 | 
			
		||||
+		     fa_wdt->base + FA_WDLOAD);
 | 
			
		||||
+
 | 
			
		||||
+	fa_wdt_service(fa_wdt);
 | 
			
		||||
+
 | 
			
		||||
+	/* set clock before enabling */
 | 
			
		||||
+	__raw_writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
 | 
			
		||||
+			fa_wdt->base + FA_WDCR);
 | 
			
		||||
+
 | 
			
		||||
+	__raw_writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
 | 
			
		||||
+			fa_wdt->base + FA_WDCR);
 | 
			
		||||
+
 | 
			
		||||
+	set_bit(WDT_ACTIVE, &fa_wdt->status);
 | 
			
		||||
+
 | 
			
		||||
+	spin_unlock(&fa_wdt_lock);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Watchdog device is opened, and watchdog starts running. */
 | 
			
		||||
+static int fa_wdt_open(struct inode *inode, struct file *file)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = platform_get_drvdata(fa_wdt_dev);
 | 
			
		||||
+
 | 
			
		||||
+	if (test_bit(WDT_ACTIVE, &fa_wdt->status))
 | 
			
		||||
+		return -EBUSY;
 | 
			
		||||
+
 | 
			
		||||
+	file->private_data = fa_wdt;
 | 
			
		||||
+
 | 
			
		||||
+	fa_wdt_start(fa_wdt);
 | 
			
		||||
+
 | 
			
		||||
+	return nonseekable_open(inode, file);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Close the watchdog device. */
 | 
			
		||||
+static int fa_wdt_close(struct inode *inode, struct file *file)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = file->private_data;
 | 
			
		||||
+
 | 
			
		||||
+	/* Disable the watchdog if possible */
 | 
			
		||||
+	if (test_bit(WDT_OK_TO_CLOSE, &fa_wdt->status))
 | 
			
		||||
+		fa_wdt_stop(fa_wdt);
 | 
			
		||||
+	else
 | 
			
		||||
+		dev_warn(fa_wdt->dev, "Device closed unexpectedly - timer will not stop\n");
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Handle commands from user-space. */
 | 
			
		||||
+static long fa_wdt_ioctl(struct file *file, unsigned int cmd,
 | 
			
		||||
+			 unsigned long arg)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = file->private_data;
 | 
			
		||||
+
 | 
			
		||||
+	int value;
 | 
			
		||||
+
 | 
			
		||||
+	switch (cmd) {
 | 
			
		||||
+	case WDIOC_KEEPALIVE:
 | 
			
		||||
+		fa_wdt_service(fa_wdt);
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	case WDIOC_GETSUPPORT:
 | 
			
		||||
+		return copy_to_user((struct watchdog_info *)arg, &fa_wdt_info,
 | 
			
		||||
+			sizeof(fa_wdt_info)) ? -EFAULT : 0;
 | 
			
		||||
+
 | 
			
		||||
+	case WDIOC_SETTIMEOUT:
 | 
			
		||||
+		if (get_user(value, (int *)arg))
 | 
			
		||||
+			return -EFAULT;
 | 
			
		||||
+
 | 
			
		||||
+		if ((value < 1) || (value > fa_wdt->max_timeout))
 | 
			
		||||
+			return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
+		timeout = value;
 | 
			
		||||
+
 | 
			
		||||
+		/* restart wdt to use new timeout */
 | 
			
		||||
+		fa_wdt_stop(fa_wdt);
 | 
			
		||||
+		fa_wdt_start(fa_wdt);
 | 
			
		||||
+
 | 
			
		||||
+		/* Fall through */
 | 
			
		||||
+	case WDIOC_GETTIMEOUT:
 | 
			
		||||
+		return put_user(timeout, (int *)arg);
 | 
			
		||||
+
 | 
			
		||||
+	case WDIOC_GETTIMELEFT:
 | 
			
		||||
+		value = __raw_readl(fa_wdt->base + FA_WDCOUNTER);
 | 
			
		||||
+		return put_user(value / fa_wdt->clock, (int *)arg);
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return -ENOTTY;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Refresh the watchdog whenever device is written to. */
 | 
			
		||||
+static ssize_t fa_wdt_write(struct file *file, const char *data,
 | 
			
		||||
+			    size_t len, loff_t *ppos)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = file->private_data;
 | 
			
		||||
+
 | 
			
		||||
+	if (len) {
 | 
			
		||||
+		if (!nowayout) {
 | 
			
		||||
+			size_t i;
 | 
			
		||||
+
 | 
			
		||||
+			clear_bit(WDT_OK_TO_CLOSE, &fa_wdt->status);
 | 
			
		||||
+			for (i = 0; i != len; i++) {
 | 
			
		||||
+				char c;
 | 
			
		||||
+
 | 
			
		||||
+				if (get_user(c, data + i))
 | 
			
		||||
+					return -EFAULT;
 | 
			
		||||
+				if (c == 'V')
 | 
			
		||||
+					set_bit(WDT_OK_TO_CLOSE,
 | 
			
		||||
+						&fa_wdt->status);
 | 
			
		||||
+			}
 | 
			
		||||
+		}
 | 
			
		||||
+		fa_wdt_service(fa_wdt);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return len;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_wdt_notify_sys(struct notifier_block *this,
 | 
			
		||||
+			     unsigned long code, void *unused)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = platform_get_drvdata(fa_wdt_dev);
 | 
			
		||||
+
 | 
			
		||||
+	if (code == SYS_DOWN || code == SYS_HALT)
 | 
			
		||||
+		fa_wdt_stop(fa_wdt);
 | 
			
		||||
+
 | 
			
		||||
+	return NOTIFY_DONE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct notifier_block fa_wdt_notifier = {
 | 
			
		||||
+	.notifier_call = fa_wdt_notify_sys,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static const struct file_operations fa_wdt_fops = {
 | 
			
		||||
+	.owner		= THIS_MODULE,
 | 
			
		||||
+	.llseek		= no_llseek,
 | 
			
		||||
+	.unlocked_ioctl	= fa_wdt_ioctl,
 | 
			
		||||
+	.open		= fa_wdt_open,
 | 
			
		||||
+	.release	= fa_wdt_close,
 | 
			
		||||
+	.write		= fa_wdt_write,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct miscdevice fa_wdt_miscdev = {
 | 
			
		||||
+	.minor		= WATCHDOG_MINOR,
 | 
			
		||||
+	.name		= "watchdog",
 | 
			
		||||
+	.fops		= &fa_wdt_fops,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void fa_wdt_shutdown(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
 | 
			
		||||
+
 | 
			
		||||
+	fa_wdt_stop(fa_wdt);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int __devinit fa_wdt_probe(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret;
 | 
			
		||||
+	int res_size;
 | 
			
		||||
+	struct resource *res;
 | 
			
		||||
+	void __iomem *base;
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt;
 | 
			
		||||
+	struct fa_wdt_platform_data *pdata;
 | 
			
		||||
+
 | 
			
		||||
+	pdata = pdev->dev.platform_data;
 | 
			
		||||
+	if (!pdata) {
 | 
			
		||||
+		dev_err(&pdev->dev, "no platform data specified\n");
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (!pdata->clock) {
 | 
			
		||||
+		dev_err(&pdev->dev, "invalid clock value\n");
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
+	if (!res) {
 | 
			
		||||
+		dev_err(&pdev->dev, "can't get device resources\n");
 | 
			
		||||
+		return -ENODEV;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	res_size = resource_size(res);
 | 
			
		||||
+	if (!request_mem_region(res->start, res_size, res->name)) {
 | 
			
		||||
+		dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
 | 
			
		||||
+			res_size, res->start);
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	base = ioremap(res->start, res_size);
 | 
			
		||||
+	if (!base) {
 | 
			
		||||
+		dev_err(&pdev->dev, "ioremap failed\n");
 | 
			
		||||
+		ret = -EIO;
 | 
			
		||||
+		goto fail0;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	fa_wdt = kzalloc(sizeof(struct fa_wdt_struct), GFP_KERNEL);
 | 
			
		||||
+	if (!fa_wdt) {
 | 
			
		||||
+		dev_err(&pdev->dev, "can't allocate interface\n");
 | 
			
		||||
+		ret = -ENOMEM;
 | 
			
		||||
+		goto fail1;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	/* Setup fa_wdt driver structure */
 | 
			
		||||
+	fa_wdt->base = base;
 | 
			
		||||
+	fa_wdt->res = res;
 | 
			
		||||
+	fa_wdt->dev = &pdev->dev;
 | 
			
		||||
+	fa_wdt->clock = pdata->clock;
 | 
			
		||||
+	fa_wdt->max_timeout = 0xffffffffU / pdata->clock;
 | 
			
		||||
+
 | 
			
		||||
+	/* Set up platform driver data */
 | 
			
		||||
+	platform_set_drvdata(pdev, fa_wdt);
 | 
			
		||||
+	fa_wdt_dev = pdev;
 | 
			
		||||
+
 | 
			
		||||
+	if (fa_wdt_miscdev.parent) {
 | 
			
		||||
+		ret = -EBUSY;
 | 
			
		||||
+		goto fail2;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	ret = register_reboot_notifier(&fa_wdt_notifier);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		goto fail2;
 | 
			
		||||
+
 | 
			
		||||
+	fa_wdt_miscdev.parent = &pdev->dev;
 | 
			
		||||
+
 | 
			
		||||
+	ret = misc_register(&fa_wdt_miscdev);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		goto fail3;
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+fail3:
 | 
			
		||||
+	unregister_reboot_notifier(&fa_wdt_notifier);
 | 
			
		||||
+fail2:
 | 
			
		||||
+	platform_set_drvdata(pdev, NULL);
 | 
			
		||||
+	kfree(fa_wdt);
 | 
			
		||||
+fail1:
 | 
			
		||||
+	iounmap(base);
 | 
			
		||||
+fail0:
 | 
			
		||||
+	release_mem_region(res->start, res_size);
 | 
			
		||||
+
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int __devexit fa_wdt_remove(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
 | 
			
		||||
+
 | 
			
		||||
+	platform_set_drvdata(pdev, NULL);
 | 
			
		||||
+	misc_deregister(&fa_wdt_miscdev);
 | 
			
		||||
+	unregister_reboot_notifier(&fa_wdt_notifier);
 | 
			
		||||
+	fa_wdt_dev = NULL;
 | 
			
		||||
+	iounmap(fa_wdt->base);
 | 
			
		||||
+	release_mem_region(fa_wdt->res->start, resource_size(fa_wdt->res));
 | 
			
		||||
+
 | 
			
		||||
+	kfree(fa_wdt);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+#ifdef CONFIG_PM
 | 
			
		||||
+static int fa_wdt_suspend(struct platform_device *pdev, pm_message_t message)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
 | 
			
		||||
+	unsigned int reg;
 | 
			
		||||
+
 | 
			
		||||
+	reg = __raw_readw(fa_wdt->base + FA_WDCR);
 | 
			
		||||
+	reg &= ~(WDCR_WDENABLE);
 | 
			
		||||
+	__raw_writel(reg, fa_wdt->base + FA_WDCR);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int fa_wdt_resume(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
 | 
			
		||||
+	unsigned int reg;
 | 
			
		||||
+
 | 
			
		||||
+	if (fa_wdt->status) {
 | 
			
		||||
+		reg = __raw_readw(fa_wdt->base + FA_WDCR);
 | 
			
		||||
+		reg |= WDCR_WDENABLE;
 | 
			
		||||
+		__raw_writel(reg, fa_wdt->base + FA_WDCR);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+#else
 | 
			
		||||
+#define fa_wdt_suspend	NULL
 | 
			
		||||
+#define fa_wdt_resume	NULL
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_driver fa_wdt_driver = {
 | 
			
		||||
+	.probe		= fa_wdt_probe,
 | 
			
		||||
+	.remove		= __devexit_p(fa_wdt_remove),
 | 
			
		||||
+	.shutdown	= fa_wdt_shutdown,
 | 
			
		||||
+	.suspend	= fa_wdt_suspend,
 | 
			
		||||
+	.resume		= fa_wdt_resume,
 | 
			
		||||
+	.driver		= {
 | 
			
		||||
+		.name	= "fa-wdt",
 | 
			
		||||
+		.owner	= THIS_MODULE,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static int __init fa_wdt_init(void)
 | 
			
		||||
+{
 | 
			
		||||
+	return platform_driver_probe(&fa_wdt_driver, fa_wdt_probe);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void __exit fa_wdt_exit(void)
 | 
			
		||||
+{
 | 
			
		||||
+	platform_driver_unregister(&fa_wdt_driver);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+module_init(fa_wdt_init);
 | 
			
		||||
+module_exit(fa_wdt_exit);
 | 
			
		||||
+
 | 
			
		||||
+module_param(timeout, uint, 0);
 | 
			
		||||
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
 | 
			
		||||
+
 | 
			
		||||
+module_param(nowayout, int, 0);
 | 
			
		||||
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 | 
			
		||||
+
 | 
			
		||||
+MODULE_AUTHOR("Paulius Zaleckas");
 | 
			
		||||
+MODULE_AUTHOR("Gabor Juhos");
 | 
			
		||||
+MODULE_DESCRIPTION("Watchdog driver for Faraday FA526 based SoCs");
 | 
			
		||||
+MODULE_LICENSE("GPL v2");
 | 
			
		||||
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 | 
			
		||||
+MODULE_ALIAS("platform:fa-wdt");
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/include/linux/fa_wdt.h
 | 
			
		||||
@@ -0,0 +1,13 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ * Platform data definition for the Faraday watchdog driver
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#ifndef _FA_WDT_H
 | 
			
		||||
+#define _FA_WDT_H
 | 
			
		||||
+
 | 
			
		||||
+struct fa_wdt_platform_data {
 | 
			
		||||
+	unsigned int	clock;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+#endif /* _FA_WDT_H */
 | 
			
		||||
+
 | 
			
		||||
							
								
								
									
										2086
									
								
								target/linux/cns21xx/patches-3.2/100-cns21xx-core.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2086
									
								
								target/linux/cns21xx/patches-3.2/100-cns21xx-core.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,103 @@
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
@@ -15,4 +15,7 @@ void __init cns21xx_init_irq(void);
 | 
			
		||||
 
 | 
			
		||||
 extern struct sys_timer cns21xx_timer;
 | 
			
		||||
 
 | 
			
		||||
+int __init cns21xx_register_uart0(void);
 | 
			
		||||
+int __init cns21xx_register_uart1(void);
 | 
			
		||||
+
 | 
			
		||||
 #endif /* _MACH_CNS21XX_COMMON_H */
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/devices.c
 | 
			
		||||
@@ -0,0 +1,79 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2008 Cavium Networks
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file is free software; you can redistribute it and/or modify
 | 
			
		||||
+ *  it under the terms of the GNU General Public License, Version 2, as
 | 
			
		||||
+ *  published by the Free Software Foundation.
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#include <linux/kernel.h>
 | 
			
		||||
+#include <linux/init.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/serial_8250.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/irqs.h>
 | 
			
		||||
+#include <mach/hardware.h>
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+#include <mach/cns21xx_misc.h>
 | 
			
		||||
+
 | 
			
		||||
+#define CNS21XX_UART_CLOCK	24000000
 | 
			
		||||
+
 | 
			
		||||
+#define CNS21XX_UART_FLAGS (UPF_SKIP_TEST | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST)
 | 
			
		||||
+
 | 
			
		||||
+static struct plat_serial8250_port cns21xx_uart0_data[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.mapbase	= CNS21XX_UART0_BASE,
 | 
			
		||||
+		.membase	= (void *) CNS21XX_UART0_BASE_VIRT,
 | 
			
		||||
+		.irq		= CNS21XX_IRQ_UART0,
 | 
			
		||||
+		.uartclk	= CNS21XX_UART_CLOCK,
 | 
			
		||||
+		.regshift	= 2,
 | 
			
		||||
+		.iotype		= UPIO_MEM,
 | 
			
		||||
+		.type		= PORT_16550A,
 | 
			
		||||
+		.flags		= CNS21XX_UART_FLAGS,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		/* terminating entry */
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device cns21xx_uart0_device = {
 | 
			
		||||
+	.name	= "serial8250",
 | 
			
		||||
+	.id	= PLAT8250_DEV_PLATFORM,
 | 
			
		||||
+	.dev	= {
 | 
			
		||||
+		.platform_data = cns21xx_uart0_data,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+int __init cns21xx_register_uart0(void)
 | 
			
		||||
+{
 | 
			
		||||
+	return platform_device_register(&cns21xx_uart0_device);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct plat_serial8250_port cns21xx_uart1_data[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.mapbase	= CNS21XX_UART1_BASE,
 | 
			
		||||
+		.membase	= (void *) CNS21XX_UART1_BASE_VIRT,
 | 
			
		||||
+		.irq		= CNS21XX_IRQ_UART1,
 | 
			
		||||
+		.uartclk	= CNS21XX_UART_CLOCK,
 | 
			
		||||
+		.regshift	= 2,
 | 
			
		||||
+		.iotype		= UPIO_MEM,
 | 
			
		||||
+		.type		= PORT_16550A,
 | 
			
		||||
+		.flags		= CNS21XX_UART_FLAGS,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		/* terminating entry */
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device cns21xx_uart1_device = {
 | 
			
		||||
+	.name	= "serial8250",
 | 
			
		||||
+	.id	= PLAT8250_DEV_PLATFORM1,
 | 
			
		||||
+	.dev	= {
 | 
			
		||||
+		.platform_data = cns21xx_uart1_data,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+int __init cns21xx_register_uart1(void)
 | 
			
		||||
+{
 | 
			
		||||
+	HAL_MISC_ENABLE_UART1_PINS();
 | 
			
		||||
+	return platform_device_register(&cns21xx_uart1_device);
 | 
			
		||||
+}
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 
 | 
			
		||||
 # Object file lists.
 | 
			
		||||
 
 | 
			
		||||
-obj-y		:= core.o irq.o mm.o time.o
 | 
			
		||||
+obj-y		:= core.o devices.o irq.o mm.o time.o
 | 
			
		||||
 
 | 
			
		||||
 # machine specific files
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,85 @@
 | 
			
		||||
--- a/arch/arm/Kconfig
 | 
			
		||||
+++ b/arch/arm/Kconfig
 | 
			
		||||
@@ -360,6 +360,8 @@ config ARCH_CNS21XX
 | 
			
		||||
 	select CPU_FA526
 | 
			
		||||
 	select PLAT_FA
 | 
			
		||||
 	select PLAT_FA_TIME
 | 
			
		||||
+	select PLAT_FA_GPIO
 | 
			
		||||
+	select ARCH_REQUIRE_GPIOLIB
 | 
			
		||||
 	select ARM_L1_CACHE_SHIFT_4
 | 
			
		||||
 	help
 | 
			
		||||
 	  Support for Cavium Networks CNS21xx family.
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 
 | 
			
		||||
 void __init cns21xx_map_io(void);
 | 
			
		||||
 void __init cns21xx_init_irq(void);
 | 
			
		||||
+void __init cns21xx_gpio_init(void);
 | 
			
		||||
 
 | 
			
		||||
 extern struct sys_timer cns21xx_timer;
 | 
			
		||||
 
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/gpio.c
 | 
			
		||||
@@ -0,0 +1,45 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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 <plat/gpio.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+#include <mach/irqs.h>
 | 
			
		||||
+
 | 
			
		||||
+static struct fa_gpio_chip cns21xx_gpio_chips[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.gpio_chip = {
 | 
			
		||||
+			.label	= "GPIOA",
 | 
			
		||||
+			.base	= 0,
 | 
			
		||||
+			.ngpio	= 32,
 | 
			
		||||
+		},
 | 
			
		||||
+
 | 
			
		||||
+		.map_base	= CNS21XX_GPIOA_BASE,
 | 
			
		||||
+		.irq_base	= CNS21XX_GPIO_IRQ_BASE,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.gpio_chip = {
 | 
			
		||||
+			.label	= "GPIOB",
 | 
			
		||||
+			.base	= 32,
 | 
			
		||||
+			.ngpio	= 32,
 | 
			
		||||
+		},
 | 
			
		||||
+
 | 
			
		||||
+		.map_base	= CNS21XX_GPIOB_BASE,
 | 
			
		||||
+		.irq_base	= CNS21XX_GPIO_IRQ_BASE + 32,
 | 
			
		||||
+	}
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct fa_gpio_data cns21xx_gpio_data = {
 | 
			
		||||
+	.chips	= cns21xx_gpio_chips,
 | 
			
		||||
+	.nchips = ARRAY_SIZE(cns21xx_gpio_chips),
 | 
			
		||||
+	.irq	= CNS21XX_IRQ_GPIO,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+void __init cns21xx_gpio_init(void)
 | 
			
		||||
+{
 | 
			
		||||
+	fa_gpio_init(&cns21xx_gpio_data);
 | 
			
		||||
+}
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/include/mach/gpio.h
 | 
			
		||||
@@ -0,0 +1,2 @@
 | 
			
		||||
+/* empty */
 | 
			
		||||
+
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 
 | 
			
		||||
 # Object file lists.
 | 
			
		||||
 
 | 
			
		||||
-obj-y		:= core.o devices.o irq.o mm.o time.o
 | 
			
		||||
+obj-y		:= core.o devices.o gpio.o irq.o mm.o time.o
 | 
			
		||||
 
 | 
			
		||||
 # machine specific files
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,230 @@
 | 
			
		||||
--- a/drivers/usb/host/ohci-hcd.c
 | 
			
		||||
+++ b/drivers/usb/host/ohci-hcd.c
 | 
			
		||||
@@ -579,7 +579,6 @@ static int ohci_run (struct ohci_hcd *oh
 | 
			
		||||
 
 | 
			
		||||
 	/* boot firmware should have set this up (5.1.1.3.1) */
 | 
			
		||||
 	if (first) {
 | 
			
		||||
-
 | 
			
		||||
 		val = ohci_readl (ohci, &ohci->regs->fminterval);
 | 
			
		||||
 		ohci->fminterval = val & 0x3fff;
 | 
			
		||||
 		if (ohci->fminterval != FI)
 | 
			
		||||
@@ -663,6 +662,9 @@ retry:
 | 
			
		||||
 
 | 
			
		||||
 	periodic_reinit (ohci);
 | 
			
		||||
 
 | 
			
		||||
+	if (ohci->flags & OHCI_QUIRK_INIT_FMINTERVAL)
 | 
			
		||||
+		ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval);
 | 
			
		||||
+
 | 
			
		||||
 	/* some OHCI implementations are finicky about how they init.
 | 
			
		||||
 	 * bogus values here mean not even enumeration could work.
 | 
			
		||||
 	 */
 | 
			
		||||
@@ -1101,6 +1103,11 @@ MODULE_LICENSE ("GPL");
 | 
			
		||||
 #define PLATFORM_DRIVER		ohci_octeon_driver
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_ARCH_CNS21XX
 | 
			
		||||
+#include "ohci-cns21xx.c"
 | 
			
		||||
+#define PLATFORM_DRIVER		ohci_cns21xx_driver
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 #ifdef CONFIG_USB_CNS3XXX_OHCI
 | 
			
		||||
 #include "ohci-cns3xxx.c"
 | 
			
		||||
 #define PLATFORM_DRIVER		ohci_hcd_cns3xxx_driver
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/drivers/usb/host/ohci-cns21xx.c
 | 
			
		||||
@@ -0,0 +1,175 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2008 Cavium Networks
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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/platform_device.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+
 | 
			
		||||
+#define DRIVER_NAME	"cns21xx-ohci"
 | 
			
		||||
+
 | 
			
		||||
+static int __devinit cns21xx_ohci_start(struct usb_hcd *hcd)
 | 
			
		||||
+{
 | 
			
		||||
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	ret = ohci_init(ohci);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		return ret;
 | 
			
		||||
+
 | 
			
		||||
+	ret = ohci_run(ohci);
 | 
			
		||||
+	if (ret) {
 | 
			
		||||
+		err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
 | 
			
		||||
+		goto err;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+err:
 | 
			
		||||
+	ohci_stop(hcd);
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static const struct hc_driver ohci_cns21xx_hc_driver = {
 | 
			
		||||
+	.description		= hcd_name,
 | 
			
		||||
+	.product_desc		= "cns21xx-ohci",
 | 
			
		||||
+	.hcd_priv_size		= sizeof(struct ohci_hcd),
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * generic hardware linkage
 | 
			
		||||
+	 */
 | 
			
		||||
+	.irq			= ohci_irq,
 | 
			
		||||
+	.flags			= HCD_USB11 | HCD_MEMORY,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * basic lifecycle operations
 | 
			
		||||
+	 */
 | 
			
		||||
+	.start			= cns21xx_ohci_start,
 | 
			
		||||
+	.stop			= ohci_stop,
 | 
			
		||||
+	.shutdown		= ohci_shutdown,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * managing i/o requests and associated device resources
 | 
			
		||||
+	 */
 | 
			
		||||
+	.urb_enqueue		= ohci_urb_enqueue,
 | 
			
		||||
+	.urb_dequeue		= ohci_urb_dequeue,
 | 
			
		||||
+	.endpoint_disable	= ohci_endpoint_disable,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * scheduling support
 | 
			
		||||
+	 */
 | 
			
		||||
+	.get_frame_number	= ohci_get_frame,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * root hub support
 | 
			
		||||
+	 */
 | 
			
		||||
+	.hub_status_data	= ohci_hub_status_data,
 | 
			
		||||
+	.hub_control		= ohci_hub_control,
 | 
			
		||||
+	.start_port_reset	= ohci_start_port_reset,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void cns21xx_ohci_init_hc(void)
 | 
			
		||||
+{
 | 
			
		||||
+	__raw_writel(0x146, CNS21XX_OHCI_CONFIG_BASE_VIRT + 0x04);
 | 
			
		||||
+	__raw_writel(0x200, CNS21XX_OHCI_CONFIG_BASE_VIRT + 0x44);
 | 
			
		||||
+	msleep(100);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int ohci_cns21xx_probe(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct usb_hcd *hcd;
 | 
			
		||||
+	struct resource *res;
 | 
			
		||||
+	struct ohci_hcd *ohci;
 | 
			
		||||
+	int irq;
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	if (usb_disabled())
 | 
			
		||||
+		return -ENODEV;
 | 
			
		||||
+
 | 
			
		||||
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 | 
			
		||||
+	if (!res) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
 | 
			
		||||
+			dev_name(&pdev->dev));
 | 
			
		||||
+		return -ENODEV;
 | 
			
		||||
+	}
 | 
			
		||||
+	irq = res->start;
 | 
			
		||||
+
 | 
			
		||||
+	hcd = usb_create_hcd(&ohci_cns21xx_hc_driver, &pdev->dev,
 | 
			
		||||
+			     dev_name(&pdev->dev));
 | 
			
		||||
+	if (!hcd)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
+	if (!res) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "no base address specified for %s\n",
 | 
			
		||||
+			dev_name(&pdev->dev));
 | 
			
		||||
+		ret = -ENODEV;
 | 
			
		||||
+		goto err_put_hcd;
 | 
			
		||||
+	}
 | 
			
		||||
+	hcd->rsrc_start	= res->start;
 | 
			
		||||
+	hcd->rsrc_len	= res->end - res->start + 1;
 | 
			
		||||
+
 | 
			
		||||
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "controller already in use\n");
 | 
			
		||||
+		ret = -EBUSY;
 | 
			
		||||
+		goto err_put_hcd;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 | 
			
		||||
+	if (!hcd->regs) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "error mapping memory\n");
 | 
			
		||||
+		ret = -EFAULT;
 | 
			
		||||
+		goto err_release_region;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_ohci_init_hc();
 | 
			
		||||
+
 | 
			
		||||
+	ohci = hcd_to_ohci(hcd);
 | 
			
		||||
+	ohci->flags |= OHCI_QUIRK_INIT_FMINTERVAL;
 | 
			
		||||
+	ohci_hcd_init(ohci);
 | 
			
		||||
+
 | 
			
		||||
+	ret = usb_add_hcd(hcd, irq,  IRQF_DISABLED);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		goto err_unmap;
 | 
			
		||||
+
 | 
			
		||||
+	platform_set_drvdata(pdev, hcd);
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+err_unmap:
 | 
			
		||||
+	iounmap(hcd->regs);
 | 
			
		||||
+err_release_region:
 | 
			
		||||
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 | 
			
		||||
+err_put_hcd:
 | 
			
		||||
+	usb_put_hcd(hcd);
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int ohci_cns21xx_remove(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 | 
			
		||||
+
 | 
			
		||||
+	usb_remove_hcd(hcd);
 | 
			
		||||
+	iounmap(hcd->regs);
 | 
			
		||||
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 | 
			
		||||
+	usb_put_hcd(hcd);
 | 
			
		||||
+	platform_set_drvdata(pdev, NULL);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_driver ohci_cns21xx_driver = {
 | 
			
		||||
+	.probe		= ohci_cns21xx_probe,
 | 
			
		||||
+	.remove		= ohci_cns21xx_remove,
 | 
			
		||||
+	.shutdown	= usb_hcd_platform_shutdown,
 | 
			
		||||
+	.driver		= {
 | 
			
		||||
+		.owner	= THIS_MODULE,
 | 
			
		||||
+		.name	= DRIVER_NAME,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
 | 
			
		||||
--- a/drivers/usb/host/ohci.h
 | 
			
		||||
+++ b/drivers/usb/host/ohci.h
 | 
			
		||||
@@ -403,6 +403,7 @@ struct ohci_hcd {
 | 
			
		||||
 #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
 | 
			
		||||
 #define	OHCI_QUIRK_AMD_PLL	0x200			/* AMD PLL quirk*/
 | 
			
		||||
 #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
 | 
			
		||||
+#define OHCI_QUIRK_INIT_FMINTERVAL 0x1000		/* fminterval must be initialized */
 | 
			
		||||
 	// there are also chip quirks/bugs in init logic
 | 
			
		||||
 
 | 
			
		||||
 	struct work_struct	nec_work;	/* Worker for NEC quirk */
 | 
			
		||||
--- a/arch/arm/Kconfig
 | 
			
		||||
+++ b/arch/arm/Kconfig
 | 
			
		||||
@@ -363,6 +363,7 @@ config ARCH_CNS21XX
 | 
			
		||||
 	select PLAT_FA_GPIO
 | 
			
		||||
 	select ARCH_REQUIRE_GPIOLIB
 | 
			
		||||
 	select ARM_L1_CACHE_SHIFT_4
 | 
			
		||||
+	select USB_ARCH_HAS_OHCI
 | 
			
		||||
 	help
 | 
			
		||||
 	  Support for Cavium Networks CNS21xx family.
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,213 @@
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/drivers/usb/host/ehci-cns21xx.c
 | 
			
		||||
@@ -0,0 +1,186 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2008 Cavium Networks
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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/platform_device.h>
 | 
			
		||||
+#include <linux/irq.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+
 | 
			
		||||
+#define DRIVER_NAME	"cns21xx-ehci"
 | 
			
		||||
+
 | 
			
		||||
+static int cns21xx_ehci_reset(struct usb_hcd *hcd)
 | 
			
		||||
+{
 | 
			
		||||
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	ret = ehci_halt(ehci);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		return ret;
 | 
			
		||||
+
 | 
			
		||||
+	ret = ehci_init(hcd);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		return ret;
 | 
			
		||||
+
 | 
			
		||||
+	ehci_reset(ehci);
 | 
			
		||||
+	ehci_port_power(ehci, 0);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static const struct hc_driver ehci_cns21xx_hc_driver = {
 | 
			
		||||
+	.description		= hcd_name,
 | 
			
		||||
+        .product_desc		= DRIVER_NAME,
 | 
			
		||||
+        .hcd_priv_size		= sizeof(struct ehci_hcd),
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * generic hardware linkage
 | 
			
		||||
+	 */
 | 
			
		||||
+	.irq			= ehci_irq,
 | 
			
		||||
+	.flags			= HCD_MEMORY | HCD_USB2,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * basic lifecycle operations
 | 
			
		||||
+	 */
 | 
			
		||||
+	.reset			= cns21xx_ehci_reset,
 | 
			
		||||
+	.start			= ehci_run,
 | 
			
		||||
+	.stop			= ehci_stop,
 | 
			
		||||
+	.shutdown		= ehci_shutdown,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * managing i/o requests and associated device resources
 | 
			
		||||
+	 */
 | 
			
		||||
+	.urb_enqueue		= ehci_urb_enqueue,
 | 
			
		||||
+	.urb_dequeue		= ehci_urb_dequeue,
 | 
			
		||||
+	.endpoint_disable	= ehci_endpoint_disable,
 | 
			
		||||
+	.endpoint_reset		= ehci_endpoint_reset,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * scheduling support
 | 
			
		||||
+	 */
 | 
			
		||||
+	.get_frame_number	= ehci_get_frame,
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * root hub support
 | 
			
		||||
+	 */
 | 
			
		||||
+	.hub_status_data	= ehci_hub_status_data,
 | 
			
		||||
+	.hub_control		= ehci_hub_control,
 | 
			
		||||
+	.relinquish_port	= ehci_relinquish_port,
 | 
			
		||||
+	.port_handed_over	= ehci_port_handed_over,
 | 
			
		||||
+
 | 
			
		||||
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void cns21xx_ehci_init_hc(void)
 | 
			
		||||
+{
 | 
			
		||||
+	__raw_writel(0x106, CNS21XX_EHCI_CONFIG_BASE_VIRT + 0x04);
 | 
			
		||||
+	__raw_writel((3 << 5) | 0x2000, CNS21XX_EHCI_CONFIG_BASE_VIRT + 0x40);
 | 
			
		||||
+	msleep(100);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int ehci_cns21xx_probe(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct usb_hcd *hcd;
 | 
			
		||||
+	struct ehci_hcd *ehci;
 | 
			
		||||
+	struct resource *res;
 | 
			
		||||
+	int irq;
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	if (usb_disabled())
 | 
			
		||||
+		return -ENODEV;
 | 
			
		||||
+
 | 
			
		||||
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 | 
			
		||||
+	if (!res) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
 | 
			
		||||
+			dev_name(&pdev->dev));
 | 
			
		||||
+		return -ENODEV;
 | 
			
		||||
+	}
 | 
			
		||||
+	irq = res->start;
 | 
			
		||||
+
 | 
			
		||||
+	hcd = usb_create_hcd(&ehci_cns21xx_hc_driver, &pdev->dev,
 | 
			
		||||
+			     dev_name(&pdev->dev));
 | 
			
		||||
+	if (!hcd)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
+	if (!res) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "no base address specified for %s\n",
 | 
			
		||||
+			dev_name(&pdev->dev));
 | 
			
		||||
+		ret = -ENODEV;
 | 
			
		||||
+		goto err_put_hcd;
 | 
			
		||||
+	}
 | 
			
		||||
+	hcd->rsrc_start	= res->start;
 | 
			
		||||
+	hcd->rsrc_len	= res->end - res->start + 1;
 | 
			
		||||
+
 | 
			
		||||
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "controller already in use\n");
 | 
			
		||||
+		ret = -EBUSY;
 | 
			
		||||
+		goto err_put_hcd;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 | 
			
		||||
+	if (!hcd->regs) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "error mapping memory\n");
 | 
			
		||||
+		ret = -EFAULT;
 | 
			
		||||
+		goto err_release_region;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_ehci_init_hc();
 | 
			
		||||
+
 | 
			
		||||
+	ehci = hcd_to_ehci(hcd);
 | 
			
		||||
+
 | 
			
		||||
+	ehci->caps = hcd->regs;
 | 
			
		||||
+	ehci->regs = hcd->regs +
 | 
			
		||||
+		     HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
 | 
			
		||||
+	dbg_hcs_params(ehci, "reset");
 | 
			
		||||
+	dbg_hcc_params(ehci, "reset");
 | 
			
		||||
+
 | 
			
		||||
+	/* cache this readonly data; minimize chip reads */
 | 
			
		||||
+	ehci->hcs_params = readl(&ehci->caps->hcs_params);
 | 
			
		||||
+	ehci->sbrn = 0x20;
 | 
			
		||||
+
 | 
			
		||||
+	ret = usb_add_hcd(hcd, CNS21XX_IRQ_EHCI, IRQF_DISABLED);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		goto err_unmap;
 | 
			
		||||
+
 | 
			
		||||
+	platform_set_drvdata(pdev, hcd);
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+err_unmap:
 | 
			
		||||
+	iounmap(hcd->regs);
 | 
			
		||||
+err_release_region:
 | 
			
		||||
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 | 
			
		||||
+err_put_hcd:
 | 
			
		||||
+	usb_put_hcd(hcd);
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int ehci_cns21xx_remove(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 | 
			
		||||
+
 | 
			
		||||
+	usb_remove_hcd(hcd);
 | 
			
		||||
+	iounmap(hcd->regs);
 | 
			
		||||
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 | 
			
		||||
+	usb_put_hcd(hcd);
 | 
			
		||||
+	platform_set_drvdata(pdev, NULL);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_driver ehci_cns21xx_driver = {
 | 
			
		||||
+	.probe		= ehci_cns21xx_probe,
 | 
			
		||||
+	.remove		= ehci_cns21xx_remove,
 | 
			
		||||
+	.shutdown       = usb_hcd_platform_shutdown,
 | 
			
		||||
+	.driver		= {
 | 
			
		||||
+		.owner	= THIS_MODULE,
 | 
			
		||||
+		.name	= DRIVER_NAME,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
 | 
			
		||||
--- a/drivers/usb/host/ehci-hcd.c
 | 
			
		||||
+++ b/drivers/usb/host/ehci-hcd.c
 | 
			
		||||
@@ -1329,6 +1329,11 @@ MODULE_LICENSE ("GPL");
 | 
			
		||||
 #define PLATFORM_DRIVER		ehci_xls_driver
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_ARCH_CNS21XX
 | 
			
		||||
+#include "ehci-cns21xx.c"
 | 
			
		||||
+#define PLATFORM_DRIVER		ehci_cns21xx_driver
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
 | 
			
		||||
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
 | 
			
		||||
     !defined(XILINX_OF_PLATFORM_DRIVER)
 | 
			
		||||
--- a/arch/arm/Kconfig
 | 
			
		||||
+++ b/arch/arm/Kconfig
 | 
			
		||||
@@ -364,6 +364,7 @@ config ARCH_CNS21XX
 | 
			
		||||
 	select ARCH_REQUIRE_GPIOLIB
 | 
			
		||||
 	select ARM_L1_CACHE_SHIFT_4
 | 
			
		||||
 	select USB_ARCH_HAS_OHCI
 | 
			
		||||
+	select USB_ARCH_HAS_EHCI
 | 
			
		||||
 	help
 | 
			
		||||
 	  Support for Cavium Networks CNS21xx family.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										578
									
								
								target/linux/cns21xx/patches-3.2/105-cns21xx-spi-driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										578
									
								
								target/linux/cns21xx/patches-3.2/105-cns21xx-spi-driver.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,578 @@
 | 
			
		||||
--- a/include/linux/spi/spi.h
 | 
			
		||||
+++ b/include/linux/spi/spi.h
 | 
			
		||||
@@ -445,6 +445,8 @@ struct spi_transfer {
 | 
			
		||||
 	u16		delay_usecs;
 | 
			
		||||
 	u32		speed_hz;
 | 
			
		||||
 
 | 
			
		||||
+	unsigned	last_in_message_list;
 | 
			
		||||
+
 | 
			
		||||
 	struct list_head transfer_list;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/spi/Kconfig
 | 
			
		||||
+++ b/drivers/spi/Kconfig
 | 
			
		||||
@@ -163,6 +163,14 @@ config SPI_GPIO_OLD
 | 
			
		||||
 
 | 
			
		||||
 	  If unsure, say N.
 | 
			
		||||
 
 | 
			
		||||
+config SPI_CNS21XX
 | 
			
		||||
+	tristate "Cavium Netowrks CNS21xx SPI master"
 | 
			
		||||
+	depends on ARCH_CNS21XX && EXPERIMENTAL
 | 
			
		||||
+	select SPI_BITBANG
 | 
			
		||||
+	help
 | 
			
		||||
+	  This driver supports the buil-in SPI controller of the Cavium Networks
 | 
			
		||||
+	  CNS21xx SoCs.
 | 
			
		||||
+
 | 
			
		||||
 config SPI_IMX
 | 
			
		||||
 	tristate "Freescale i.MX SPI controllers"
 | 
			
		||||
 	depends on ARCH_MXC
 | 
			
		||||
--- a/drivers/spi/Makefile
 | 
			
		||||
+++ b/drivers/spi/Makefile
 | 
			
		||||
@@ -18,6 +18,7 @@ obj-$(CONFIG_SPI_BFIN)			+= spi-bfin5xx.
 | 
			
		||||
 obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o
 | 
			
		||||
 obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o
 | 
			
		||||
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.o
 | 
			
		||||
+obj-$(CONFIG_SPI_CNS21XX)		+= spi-cns21xx.o
 | 
			
		||||
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= spi-coldfire-qspi.o
 | 
			
		||||
 obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
 | 
			
		||||
 obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
 | 
			
		||||
--- a/drivers/spi/spi-bitbang.c
 | 
			
		||||
+++ b/drivers/spi/spi-bitbang.c
 | 
			
		||||
@@ -330,6 +330,13 @@ static void bitbang_work(struct work_str
 | 
			
		||||
 				 */
 | 
			
		||||
 				if (!m->is_dma_mapped)
 | 
			
		||||
 					t->rx_dma = t->tx_dma = 0;
 | 
			
		||||
+
 | 
			
		||||
+				if (t->transfer_list.next == &m->transfers) {
 | 
			
		||||
+					t->last_in_message_list = 1;
 | 
			
		||||
+				} else {
 | 
			
		||||
+					t->last_in_message_list = 0;
 | 
			
		||||
+				}
 | 
			
		||||
+
 | 
			
		||||
 				status = bitbang->txrx_bufs(spi, t);
 | 
			
		||||
 			}
 | 
			
		||||
 			if (status > 0)
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/drivers/spi/spi-cns21xx.c
 | 
			
		||||
@@ -0,0 +1,521 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2008 Cavium Networks
 | 
			
		||||
+ *  Copyright (c) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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 <linux/spinlock.h>
 | 
			
		||||
+#include <linux/workqueue.h>
 | 
			
		||||
+#include <linux/interrupt.h>
 | 
			
		||||
+#include <linux/delay.h>
 | 
			
		||||
+#include <linux/errno.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/io.h>
 | 
			
		||||
+#include <linux/spi/spi.h>
 | 
			
		||||
+#include <linux/spi/spi_bitbang.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/hardware.h>
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+
 | 
			
		||||
+#define DRIVER_NAME	"cns21xx-spi"
 | 
			
		||||
+
 | 
			
		||||
+#ifdef CONFIG_CNS21XX_SPI_DEBUG
 | 
			
		||||
+#define DBG(fmt, args...)	pr_info("[CNS21XX_SPI_DEBUG]" fmt, ## args)
 | 
			
		||||
+#else
 | 
			
		||||
+#define DBG(fmt, args...)	do {} while (0)
 | 
			
		||||
+#endif /*  CNS21XX_SPI_DEBUG */
 | 
			
		||||
+
 | 
			
		||||
+#define SPI_REG_CFG			0x40
 | 
			
		||||
+#define SPI_REG_STAT			0x44
 | 
			
		||||
+#define SPI_REG_BIT_RATE		0x48
 | 
			
		||||
+#define SPI_REG_TX_CTRL			0x4c
 | 
			
		||||
+#define SPI_REG_TX_DATA			0x50
 | 
			
		||||
+#define SPI_REG_RX_CTRL			0x54
 | 
			
		||||
+#define SPI_REG_RX_DATA			0x58
 | 
			
		||||
+#define SPI_REG_FIFO_TX_CFG		0x5c
 | 
			
		||||
+#define SPI_REG_FIFO_TX_CTRL		0x60
 | 
			
		||||
+#define SPI_REG_FIFO_RX_CFG		0x64
 | 
			
		||||
+#define SPI_REG_INTR_STAT		0x68
 | 
			
		||||
+#define SPI_REG_INTR_ENA		0x6c
 | 
			
		||||
+
 | 
			
		||||
+#define CFG_SPI_EN			BIT(31)
 | 
			
		||||
+#define CFG_SPI_CLKPOL			BIT(14)
 | 
			
		||||
+#define CFG_SPI_CLKPHA			BIT(13)
 | 
			
		||||
+#define CFG_SPI_MASTER_EN		BIT(11)
 | 
			
		||||
+#define CFG_SPI_CHAR_LEN_M		0x3
 | 
			
		||||
+#define CFG_SPI_CHAR_LEN_8BITS		0
 | 
			
		||||
+#define CFG_SPI_CHAR_LEN_16BITS		1
 | 
			
		||||
+#define CFG_SPI_CHAR_LEN_24BITS		2
 | 
			
		||||
+#define CFG_SPI_CHAR_LEN_32BITS		3
 | 
			
		||||
+
 | 
			
		||||
+#define STAT_SPI_BUSY_STA		BIT(1)
 | 
			
		||||
+
 | 
			
		||||
+#define BIT_RATE_DIV_1			0
 | 
			
		||||
+#define BIT_RATE_DIV_2			1
 | 
			
		||||
+#define BIT_RATE_DIV_4			2
 | 
			
		||||
+#define BIT_RATE_DIV_8			3
 | 
			
		||||
+#define BIT_RATE_DIV_16			4
 | 
			
		||||
+#define BIT_RATE_DIV_32			5
 | 
			
		||||
+#define BIT_RATE_DIV_64			6
 | 
			
		||||
+#define BIT_RATE_DIV_128		7
 | 
			
		||||
+
 | 
			
		||||
+#define TX_CTRL_SPI_TXDAT_EOF		BIT(2)
 | 
			
		||||
+#define TX_CTRL_SPI_TXCH_NUM_M		0x3
 | 
			
		||||
+#define TX_CTRL_CLEAR_MASK		(TX_CTRL_SPI_TXDAT_EOF | \
 | 
			
		||||
+					 TX_CTRL_SPI_TXCH_NUM_M)
 | 
			
		||||
+
 | 
			
		||||
+#define RX_CTRL_SPI_RXDAT_EOF		BIT(2)
 | 
			
		||||
+#define RX_CTRL_SPI_RXCH_NUM_M		0x3
 | 
			
		||||
+
 | 
			
		||||
+#define INTR_STAT_SPI_TXBF_UNRN_FG	BIT(7)
 | 
			
		||||
+#define INTR_STAT_SPI_RXBF_OVRN_FG	BIT(6)
 | 
			
		||||
+#define INTR_STAT_SPI_TXFF_UNRN_FG	BIT(5)
 | 
			
		||||
+#define INTR_STAT_SPI_RXFF_OVRN_FG	BIT(4)
 | 
			
		||||
+#define INTR_STAT_SPI_TXBUF_FG		BIT(3)
 | 
			
		||||
+#define INTR_STAT_SPI_RXBUF_FG		BIT(2)
 | 
			
		||||
+#define INTR_STAT_SPI_TXFF_FG		BIT(1)
 | 
			
		||||
+#define INTR_STAT_SPI_RXFF_FG		BIT(0)
 | 
			
		||||
+
 | 
			
		||||
+#define INTR_STAT_CLEAR_MASK		(INTR_STAT_SPI_TXBF_UNRN_FG | \
 | 
			
		||||
+					 INTR_STAT_SPI_RXBF_OVRN_FG | \
 | 
			
		||||
+					 INTR_STAT_SPI_TXFF_UNRN_FG | \
 | 
			
		||||
+					 INTR_STAT_SPI_RXFF_OVRN_FG)
 | 
			
		||||
+
 | 
			
		||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_M	0x3
 | 
			
		||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_S	4
 | 
			
		||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_2	0
 | 
			
		||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_4	1
 | 
			
		||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_6	0
 | 
			
		||||
+#define FIFO_TX_CFG_SPI_TXFF_STATUS_M	0xf
 | 
			
		||||
+
 | 
			
		||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_M	0x3
 | 
			
		||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_S	4
 | 
			
		||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_2	0
 | 
			
		||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_4	1
 | 
			
		||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_6	0
 | 
			
		||||
+#define FIFO_RX_CFG_SPI_RXFF_STATUS_M	0xf
 | 
			
		||||
+
 | 
			
		||||
+#define CNS21XX_SPI_NUM_BIT_RATES	8
 | 
			
		||||
+
 | 
			
		||||
+struct cns21xx_spi {
 | 
			
		||||
+	struct spi_bitbang	bitbang;
 | 
			
		||||
+
 | 
			
		||||
+	struct spi_master	*master;
 | 
			
		||||
+	struct device		*dev;
 | 
			
		||||
+	void __iomem		*base;
 | 
			
		||||
+	struct resource		*region;
 | 
			
		||||
+
 | 
			
		||||
+	unsigned		freq_max;
 | 
			
		||||
+	unsigned		freq_min;
 | 
			
		||||
+
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static inline struct cns21xx_spi *to_hw(struct spi_device *spi)
 | 
			
		||||
+{
 | 
			
		||||
+	return spi_master_get_devdata(spi->master);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline u32 cns21xx_spi_rr(struct cns21xx_spi *hw, unsigned int reg)
 | 
			
		||||
+{
 | 
			
		||||
+	return __raw_readl(hw->base + reg);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline void cns21xx_spi_wr(struct cns21xx_spi *hw, u32 val,
 | 
			
		||||
+				  unsigned int reg)
 | 
			
		||||
+{
 | 
			
		||||
+	__raw_writel(val, hw->base + reg);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+#define CNS21XX_SPI_RETRY_COUNT		100
 | 
			
		||||
+static inline int cns21xx_spi_wait(struct cns21xx_spi *hw, unsigned int reg,
 | 
			
		||||
+				   u32 mask, u32 val)
 | 
			
		||||
+{
 | 
			
		||||
+	int retry_cnt = 0;
 | 
			
		||||
+
 | 
			
		||||
+	do {
 | 
			
		||||
+		if ((cns21xx_spi_rr(hw, reg) & mask) == val)
 | 
			
		||||
+			break;
 | 
			
		||||
+
 | 
			
		||||
+		if (++retry_cnt > CNS21XX_SPI_RETRY_COUNT) {
 | 
			
		||||
+			dev_err(hw->dev, "timeout waiting on register %02x\n",
 | 
			
		||||
+				reg);
 | 
			
		||||
+			return -EIO;
 | 
			
		||||
+		}
 | 
			
		||||
+	} while (1);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int cns21xx_spi_txrx_word(struct cns21xx_spi *hw, u8 tx_channel,
 | 
			
		||||
+				 u8 tx_eof_flag, u32 tx_data, u32 *rx_data)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int tx_ctrl;
 | 
			
		||||
+	u8 rx_channel;
 | 
			
		||||
+	u8 rx_eof_flag;
 | 
			
		||||
+	int err = 0;
 | 
			
		||||
+
 | 
			
		||||
+	err = cns21xx_spi_wait(hw, SPI_REG_STAT, STAT_SPI_BUSY_STA, 0);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		return err;
 | 
			
		||||
+
 | 
			
		||||
+	err = cns21xx_spi_wait(hw, SPI_REG_INTR_STAT, INTR_STAT_SPI_TXBUF_FG,
 | 
			
		||||
+			       INTR_STAT_SPI_TXBUF_FG);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		return err;
 | 
			
		||||
+
 | 
			
		||||
+	tx_ctrl = cns21xx_spi_rr(hw, SPI_REG_TX_CTRL);
 | 
			
		||||
+	tx_ctrl &= ~(TX_CTRL_CLEAR_MASK);
 | 
			
		||||
+	tx_ctrl |= (tx_channel & TX_CTRL_SPI_TXCH_NUM_M);
 | 
			
		||||
+	tx_ctrl |= (tx_eof_flag) ? TX_CTRL_SPI_TXDAT_EOF : 0;
 | 
			
		||||
+	cns21xx_spi_wr(hw, tx_ctrl, SPI_REG_TX_CTRL);
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_spi_wr(hw, tx_data, SPI_REG_TX_DATA);
 | 
			
		||||
+
 | 
			
		||||
+	err = cns21xx_spi_wait(hw, SPI_REG_INTR_STAT, INTR_STAT_SPI_RXBUF_FG,
 | 
			
		||||
+			       INTR_STAT_SPI_RXBUF_FG);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		return err;
 | 
			
		||||
+
 | 
			
		||||
+	rx_channel = cns21xx_spi_rr(hw, SPI_REG_RX_CTRL) &
 | 
			
		||||
+					RX_CTRL_SPI_RXCH_NUM_M;
 | 
			
		||||
+
 | 
			
		||||
+	rx_eof_flag = (cns21xx_spi_rr(hw, SPI_REG_RX_CTRL) &
 | 
			
		||||
+					RX_CTRL_SPI_RXDAT_EOF) ? 1 : 0;
 | 
			
		||||
+
 | 
			
		||||
+	*rx_data = cns21xx_spi_rr(hw, SPI_REG_RX_DATA);
 | 
			
		||||
+
 | 
			
		||||
+	if ((tx_channel != rx_channel) || (tx_eof_flag != rx_eof_flag))
 | 
			
		||||
+		return -EPROTO;
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void cns21xx_spi_chipselect(struct spi_device *spi, int value)
 | 
			
		||||
+{
 | 
			
		||||
+	struct cns21xx_spi *hw = to_hw(spi);
 | 
			
		||||
+	unsigned int spi_config;
 | 
			
		||||
+	unsigned int tx_ctrl;
 | 
			
		||||
+
 | 
			
		||||
+	switch (value) {
 | 
			
		||||
+	case BITBANG_CS_INACTIVE:
 | 
			
		||||
+		break;
 | 
			
		||||
+
 | 
			
		||||
+	case BITBANG_CS_ACTIVE:
 | 
			
		||||
+		spi_config = cns21xx_spi_rr(hw, SPI_REG_CFG);
 | 
			
		||||
+
 | 
			
		||||
+		if (spi->mode & SPI_CPHA)
 | 
			
		||||
+			spi_config |= CFG_SPI_CLKPHA;
 | 
			
		||||
+		else
 | 
			
		||||
+			spi_config &= ~CFG_SPI_CLKPHA;
 | 
			
		||||
+
 | 
			
		||||
+		if (spi->mode & SPI_CPOL)
 | 
			
		||||
+			spi_config |= CFG_SPI_CLKPOL;
 | 
			
		||||
+		else
 | 
			
		||||
+			spi_config &= ~CFG_SPI_CLKPOL;
 | 
			
		||||
+
 | 
			
		||||
+		cns21xx_spi_wr(hw, spi_config, SPI_REG_CFG);
 | 
			
		||||
+
 | 
			
		||||
+		tx_ctrl = cns21xx_spi_rr(hw, SPI_REG_TX_CTRL);
 | 
			
		||||
+		tx_ctrl &= ~(TX_CTRL_CLEAR_MASK);
 | 
			
		||||
+		tx_ctrl |= (spi->chip_select & TX_CTRL_SPI_TXCH_NUM_M);
 | 
			
		||||
+		cns21xx_spi_wr(hw, tx_ctrl, SPI_REG_TX_CTRL);
 | 
			
		||||
+
 | 
			
		||||
+		break;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int cns21xx_spi_setup(struct spi_device *spi)
 | 
			
		||||
+{
 | 
			
		||||
+	struct cns21xx_spi *hw = to_hw(spi);
 | 
			
		||||
+
 | 
			
		||||
+	if (spi->bits_per_word != 8) {
 | 
			
		||||
+		dev_err(&spi->dev, "%s: invalid bits_per_word=%u\n",
 | 
			
		||||
+			__func__, spi->bits_per_word);
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (spi->max_speed_hz == 0)
 | 
			
		||||
+		spi->max_speed_hz = hw->freq_max;
 | 
			
		||||
+
 | 
			
		||||
+	if (spi->max_speed_hz > hw->freq_max ||
 | 
			
		||||
+	    spi->max_speed_hz < hw->freq_min) {
 | 
			
		||||
+		dev_err(&spi->dev, "%s: max_speed_hz=%u out of range\n",
 | 
			
		||||
+			__func__, spi->max_speed_hz);
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int cns21xx_spi_setup_transfer(struct spi_device *spi,
 | 
			
		||||
+				      struct spi_transfer *t)
 | 
			
		||||
+{
 | 
			
		||||
+	struct cns21xx_spi *hw = to_hw(spi);
 | 
			
		||||
+	u8	bits_per_word;
 | 
			
		||||
+	u32	hz;
 | 
			
		||||
+	int	i;
 | 
			
		||||
+
 | 
			
		||||
+	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
 | 
			
		||||
+	hz = t ? t->speed_hz : spi->max_speed_hz;
 | 
			
		||||
+
 | 
			
		||||
+	if (!bits_per_word)
 | 
			
		||||
+		bits_per_word = spi->bits_per_word;
 | 
			
		||||
+
 | 
			
		||||
+	if (!hz)
 | 
			
		||||
+		hz = spi->max_speed_hz;
 | 
			
		||||
+
 | 
			
		||||
+	if (bits_per_word != 8) {
 | 
			
		||||
+		dev_err(&spi->dev, "%s: invalid bits_per_word=%u\n",
 | 
			
		||||
+			__func__, bits_per_word);
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
 | 
			
		||||
+		dev_err(&spi->dev, "%s: max_speed_hz=%u out of range\n",
 | 
			
		||||
+			__func__, hz);
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < CNS21XX_SPI_NUM_BIT_RATES; i++)
 | 
			
		||||
+		if (spi->max_speed_hz > (cns21xx_get_apb_freq() >> i))
 | 
			
		||||
+			break;
 | 
			
		||||
+
 | 
			
		||||
+	DBG("max_speed:%uHz, curr_speed:%luHz, rate_index=%d\n",
 | 
			
		||||
+	    spi->max_speed_hz, cns21xx_get_apb_freq() / (1 << i), i);
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_spi_wr(hw, i, SPI_REG_BIT_RATE);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int cns21xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 | 
			
		||||
+{
 | 
			
		||||
+	struct cns21xx_spi *hw = to_hw(spi);
 | 
			
		||||
+	const unsigned char *tx_buf;
 | 
			
		||||
+	unsigned char *rx_buf;
 | 
			
		||||
+	u32 rx_data;
 | 
			
		||||
+	int tx_eof;
 | 
			
		||||
+	int err = 0;
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	tx_buf = t->tx_buf;
 | 
			
		||||
+	rx_buf = t->rx_buf;
 | 
			
		||||
+	tx_eof = t->last_in_message_list;
 | 
			
		||||
+
 | 
			
		||||
+	DBG("txrx: tx %p, rx %p, len %d\n", tx_buf, rx_buf, t->len);
 | 
			
		||||
+
 | 
			
		||||
+	if (tx_buf) {
 | 
			
		||||
+		for (i = 0; i < t->len; i++)
 | 
			
		||||
+			DBG("tx_buf[%02d]: 0x%02x\n", i, tx_buf[i]);
 | 
			
		||||
+
 | 
			
		||||
+		for (i = 0; i < (t->len - 1); i++) {
 | 
			
		||||
+			err = cns21xx_spi_txrx_word(hw, spi->chip_select, 0,
 | 
			
		||||
+						    tx_buf[i], &rx_data);
 | 
			
		||||
+			if (err)
 | 
			
		||||
+				goto done;
 | 
			
		||||
+
 | 
			
		||||
+			if (rx_buf) {
 | 
			
		||||
+				rx_buf[i] = rx_data;
 | 
			
		||||
+				DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
 | 
			
		||||
+			}
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		err = cns21xx_spi_txrx_word(hw, spi->chip_select, tx_eof,
 | 
			
		||||
+					    tx_buf[i], &rx_data);
 | 
			
		||||
+		if (err)
 | 
			
		||||
+			goto done;
 | 
			
		||||
+
 | 
			
		||||
+		if ((tx_eof) && rx_buf) {
 | 
			
		||||
+			rx_buf[i] = rx_data;
 | 
			
		||||
+			DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
 | 
			
		||||
+		}
 | 
			
		||||
+	} else if (rx_buf) {
 | 
			
		||||
+		for (i = 0; i < (t->len - 1); i++) {
 | 
			
		||||
+			err = cns21xx_spi_txrx_word(hw, spi->chip_select, 0,
 | 
			
		||||
+						    0xff, &rx_data);
 | 
			
		||||
+			if (err)
 | 
			
		||||
+				goto done;
 | 
			
		||||
+
 | 
			
		||||
+			rx_buf[i] = rx_data;
 | 
			
		||||
+			DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		err = cns21xx_spi_txrx_word(hw, spi->chip_select, tx_eof,
 | 
			
		||||
+					    0xff, &rx_data);
 | 
			
		||||
+		if (err)
 | 
			
		||||
+			goto done;
 | 
			
		||||
+
 | 
			
		||||
+		rx_buf[i] = rx_data;
 | 
			
		||||
+		DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+ done:
 | 
			
		||||
+	return (err) ? err : t->len;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void __init cns21xx_spi_hw_init(struct cns21xx_spi *hw)
 | 
			
		||||
+{
 | 
			
		||||
+	u32 t;
 | 
			
		||||
+	u32 pclk;
 | 
			
		||||
+
 | 
			
		||||
+	/* Setup configuration register */
 | 
			
		||||
+	cns21xx_spi_wr(hw, CFG_SPI_MASTER_EN, SPI_REG_CFG);
 | 
			
		||||
+
 | 
			
		||||
+	/* Set default clock to PCLK/2 */
 | 
			
		||||
+	cns21xx_spi_wr(hw, BIT_RATE_DIV_2, SPI_REG_BIT_RATE);
 | 
			
		||||
+
 | 
			
		||||
+	/* Configure SPI's Tx channel */
 | 
			
		||||
+	cns21xx_spi_wr(hw, 0, SPI_REG_TX_CTRL);
 | 
			
		||||
+
 | 
			
		||||
+	/* Configure Tx FIFO Threshold */
 | 
			
		||||
+	t = cns21xx_spi_rr(hw, SPI_REG_FIFO_TX_CFG);
 | 
			
		||||
+	t &= ~(FIFO_TX_CFG_SPI_TXFF_THRED_M << FIFO_TX_CFG_SPI_TXFF_THRED_S);
 | 
			
		||||
+	t |= (FIFO_TX_CFG_SPI_TXFF_THRED_2 << FIFO_TX_CFG_SPI_TXFF_THRED_S);
 | 
			
		||||
+	cns21xx_spi_wr(hw, t, SPI_REG_FIFO_TX_CFG);
 | 
			
		||||
+
 | 
			
		||||
+	/* Configure Rx FIFO Threshold */
 | 
			
		||||
+	t = cns21xx_spi_rr(hw, SPI_REG_FIFO_RX_CFG);
 | 
			
		||||
+	t &= ~(FIFO_RX_CFG_SPI_RXFF_THRED_M << FIFO_RX_CFG_SPI_RXFF_THRED_S);
 | 
			
		||||
+	t |= (FIFO_RX_CFG_SPI_RXFF_THRED_2 << FIFO_RX_CFG_SPI_RXFF_THRED_S);
 | 
			
		||||
+	cns21xx_spi_wr(hw, t, SPI_REG_FIFO_RX_CFG);
 | 
			
		||||
+
 | 
			
		||||
+	/* Disable interrupts, and clear interrupt status */
 | 
			
		||||
+	cns21xx_spi_wr(hw, 0, SPI_REG_INTR_ENA);
 | 
			
		||||
+	cns21xx_spi_wr(hw, INTR_STAT_CLEAR_MASK, SPI_REG_INTR_STAT);
 | 
			
		||||
+
 | 
			
		||||
+	(void) cns21xx_spi_rr(hw, SPI_REG_RX_DATA);
 | 
			
		||||
+
 | 
			
		||||
+	/* Enable SPI */
 | 
			
		||||
+	t = cns21xx_spi_rr(hw, SPI_REG_CFG);
 | 
			
		||||
+	t |= CFG_SPI_EN;
 | 
			
		||||
+	cns21xx_spi_wr(hw, t, SPI_REG_CFG);
 | 
			
		||||
+
 | 
			
		||||
+	pclk = cns21xx_get_apb_freq();
 | 
			
		||||
+	hw->freq_max = pclk;
 | 
			
		||||
+	hw->freq_min = pclk / (1 << BIT_RATE_DIV_128);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int __init cns21xx_spi_probe(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct cns21xx_spi *hw;
 | 
			
		||||
+	struct spi_master *master;
 | 
			
		||||
+	struct resource *res;
 | 
			
		||||
+	int err = 0;
 | 
			
		||||
+
 | 
			
		||||
+	master = spi_alloc_master(&pdev->dev, sizeof(struct cns21xx_spi));
 | 
			
		||||
+	if (!master) {
 | 
			
		||||
+		dev_err(&pdev->dev, "No memory for spi_master\n");
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	hw = spi_master_get_devdata(master);
 | 
			
		||||
+
 | 
			
		||||
+	platform_set_drvdata(pdev, hw);
 | 
			
		||||
+	hw->master = spi_master_get(master);
 | 
			
		||||
+	hw->dev = &pdev->dev;
 | 
			
		||||
+
 | 
			
		||||
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
+	if (!res) {
 | 
			
		||||
+		dev_dbg(&pdev->dev, "no MEM resource found\n");
 | 
			
		||||
+		err = -ENOENT;
 | 
			
		||||
+		goto err_put_master;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	hw->region = request_mem_region(res->start, resource_size(res),
 | 
			
		||||
+					dev_name(&pdev->dev));
 | 
			
		||||
+	if (!hw->region) {
 | 
			
		||||
+		dev_err(&pdev->dev, "unable to reserve iomem region\n");
 | 
			
		||||
+		err = -ENXIO;
 | 
			
		||||
+		goto err_put_master;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	hw->base = ioremap(res->start, resource_size(res));
 | 
			
		||||
+	if (!hw->base) {
 | 
			
		||||
+		dev_err(&pdev->dev, "ioremap failed\n");
 | 
			
		||||
+		err = -ENOENT;
 | 
			
		||||
+		goto err_release_region;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_spi_hw_init(hw);
 | 
			
		||||
+
 | 
			
		||||
+	master->bus_num = pdev->id;
 | 
			
		||||
+	if (master->bus_num == -1)
 | 
			
		||||
+		master->bus_num = 0;
 | 
			
		||||
+
 | 
			
		||||
+	master->num_chipselect = 4;
 | 
			
		||||
+	master->setup = cns21xx_spi_setup;
 | 
			
		||||
+
 | 
			
		||||
+	hw->bitbang.master = hw->master;
 | 
			
		||||
+	hw->bitbang.chipselect = cns21xx_spi_chipselect;
 | 
			
		||||
+	hw->bitbang.txrx_bufs = cns21xx_spi_txrx;
 | 
			
		||||
+	hw->bitbang.setup_transfer = cns21xx_spi_setup_transfer;
 | 
			
		||||
+
 | 
			
		||||
+	err = spi_bitbang_start(&hw->bitbang);
 | 
			
		||||
+	if (err) {
 | 
			
		||||
+		dev_err(hw->dev, "unable to register SPI master\n");
 | 
			
		||||
+		goto err_unmap;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	dev_info(hw->dev, "iomem at %08x\n", res->start);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+ err_unmap:
 | 
			
		||||
+	iounmap(hw->base);
 | 
			
		||||
+
 | 
			
		||||
+ err_release_region:
 | 
			
		||||
+	release_resource(hw->region);
 | 
			
		||||
+	kfree(hw->region);
 | 
			
		||||
+
 | 
			
		||||
+ err_put_master:
 | 
			
		||||
+	spi_master_put(hw->bitbang.master);
 | 
			
		||||
+	platform_set_drvdata(pdev, NULL);
 | 
			
		||||
+
 | 
			
		||||
+	return err;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int __devexit cns21xx_spi_remove(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	struct cns21xx_spi *hw = platform_get_drvdata(pdev);
 | 
			
		||||
+
 | 
			
		||||
+	spi_bitbang_stop(&hw->bitbang);
 | 
			
		||||
+	iounmap(hw->base);
 | 
			
		||||
+	release_resource(hw->region);
 | 
			
		||||
+	kfree(hw->region);
 | 
			
		||||
+	spi_master_put(hw->bitbang.master);
 | 
			
		||||
+	platform_set_drvdata(pdev, NULL);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_driver cns21xx_spi_driver = {
 | 
			
		||||
+	.remove		= __devexit_p(cns21xx_spi_remove),
 | 
			
		||||
+	.driver		= {
 | 
			
		||||
+		.name	= DRIVER_NAME,
 | 
			
		||||
+		.owner	= THIS_MODULE,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static int __init cns21xx_spi_init(void)
 | 
			
		||||
+{
 | 
			
		||||
+	return platform_driver_probe(&cns21xx_spi_driver, cns21xx_spi_probe);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void __exit cns21xx_spi_exit(void)
 | 
			
		||||
+{
 | 
			
		||||
+	platform_driver_unregister(&cns21xx_spi_driver);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+module_init(cns21xx_spi_init);
 | 
			
		||||
+module_exit(cns21xx_spi_exit);
 | 
			
		||||
+
 | 
			
		||||
+MODULE_DESCRIPTION("Cavium Networks CNS21xx SPI Controller driver");
 | 
			
		||||
+MODULE_AUTHOR("STAR Semi Corp.");
 | 
			
		||||
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
 | 
			
		||||
+MODULE_LICENSE("GPL v2");
 | 
			
		||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
 | 
			
		||||
							
								
								
									
										2507
									
								
								target/linux/cns21xx/patches-3.2/106-cns21xx-gec-driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2507
									
								
								target/linux/cns21xx/patches-3.2/106-cns21xx-gec-driver.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,104 @@
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/dev-usb.c
 | 
			
		||||
@@ -0,0 +1,71 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2008 Cavium Networks
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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/irq.h>
 | 
			
		||||
+#include <linux/dma-mapping.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+
 | 
			
		||||
+static u64 cns21xx_usb_dmamask = DMA_BIT_MASK(32);
 | 
			
		||||
+
 | 
			
		||||
+static struct resource cns21xx_ohci_resources[] = {
 | 
			
		||||
+	[0] = {
 | 
			
		||||
+		.start	= CNS21XX_OHCI_CTRL_BASE,
 | 
			
		||||
+		.end	= CNS21XX_OHCI_CTRL_BASE + SZ_1M - 1,
 | 
			
		||||
+		.flags	= IORESOURCE_MEM,
 | 
			
		||||
+	},
 | 
			
		||||
+	[1] = {
 | 
			
		||||
+		.start	= CNS21XX_IRQ_OHCI,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_OHCI,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device cns21xx_ohci_device = {
 | 
			
		||||
+	.name		= "cns21xx-ohci",
 | 
			
		||||
+	.id		= -1,
 | 
			
		||||
+	.dev = {
 | 
			
		||||
+		.dma_mask		= &cns21xx_usb_dmamask,
 | 
			
		||||
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 | 
			
		||||
+	},
 | 
			
		||||
+	.resource	= cns21xx_ohci_resources,
 | 
			
		||||
+	.num_resources	= ARRAY_SIZE(cns21xx_ohci_resources),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct resource cns21xx_ehci_resources[] = {
 | 
			
		||||
+	[0] = {
 | 
			
		||||
+		.start	= CNS21XX_EHCI_CTRL_BASE,
 | 
			
		||||
+		.end	= CNS21XX_EHCI_CTRL_BASE + SZ_1M - 1,
 | 
			
		||||
+		.flags	= IORESOURCE_MEM,
 | 
			
		||||
+	},
 | 
			
		||||
+	[1] = {
 | 
			
		||||
+		.start	= CNS21XX_IRQ_EHCI,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_EHCI,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device cns21xx_ehci_device = {
 | 
			
		||||
+	.name		= "cns21xx-ehci",
 | 
			
		||||
+	.id		= -1,
 | 
			
		||||
+	.dev		= {
 | 
			
		||||
+		.dma_mask		= &cns21xx_usb_dmamask,
 | 
			
		||||
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 | 
			
		||||
+	},
 | 
			
		||||
+	.resource	= cns21xx_ehci_resources,
 | 
			
		||||
+	.num_resources	= ARRAY_SIZE(cns21xx_ehci_resources),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+void __init cns21xx_register_usb(void)
 | 
			
		||||
+{
 | 
			
		||||
+	platform_device_register(&cns21xx_ehci_device);
 | 
			
		||||
+	platform_device_register(&cns21xx_ohci_device);
 | 
			
		||||
+}
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
@@ -3,4 +3,7 @@ if ARCH_CNS21XX
 | 
			
		||||
 menu "Cavium Networks CNS21xx based machines"
 | 
			
		||||
 endmenu
 | 
			
		||||
 
 | 
			
		||||
+config CNS21XX_DEV_USB
 | 
			
		||||
+	def_bool n
 | 
			
		||||
+
 | 
			
		||||
 endif
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -6,5 +6,8 @@
 | 
			
		||||
 
 | 
			
		||||
 obj-y		:= core.o devices.o gpio.o irq.o mm.o time.o
 | 
			
		||||
 
 | 
			
		||||
+# devices
 | 
			
		||||
+obj-$(CONFIG_CNS21XX_DEV_USB)		+= dev-usb.o
 | 
			
		||||
+
 | 
			
		||||
 # machine specific files
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
@@ -18,5 +18,6 @@ extern struct sys_timer cns21xx_timer;
 | 
			
		||||
 
 | 
			
		||||
 int __init cns21xx_register_uart0(void);
 | 
			
		||||
 int __init cns21xx_register_uart1(void);
 | 
			
		||||
+int __init cns21xx_register_usb(void);
 | 
			
		||||
 
 | 
			
		||||
 #endif /* _MACH_CNS21XX_COMMON_H */
 | 
			
		||||
@ -0,0 +1,63 @@
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
@@ -19,5 +19,6 @@ extern struct sys_timer cns21xx_timer;
 | 
			
		||||
 int __init cns21xx_register_uart0(void);
 | 
			
		||||
 int __init cns21xx_register_uart1(void);
 | 
			
		||||
 int __init cns21xx_register_usb(void);
 | 
			
		||||
+int __init cns21xx_register_wdt(void);
 | 
			
		||||
 
 | 
			
		||||
 #endif /* _MACH_CNS21XX_COMMON_H */
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/devices.c
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/devices.c
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
 #include <linux/init.h>
 | 
			
		||||
 #include <linux/platform_device.h>
 | 
			
		||||
 #include <linux/serial_8250.h>
 | 
			
		||||
+#include <linux/fa_wdt.h>
 | 
			
		||||
 
 | 
			
		||||
 #include <mach/irqs.h>
 | 
			
		||||
 #include <mach/hardware.h>
 | 
			
		||||
@@ -77,3 +78,32 @@ int __init cns21xx_register_uart1(void)
 | 
			
		||||
 	HAL_MISC_ENABLE_UART1_PINS();
 | 
			
		||||
 	return platform_device_register(&cns21xx_uart1_device);
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+static struct resource cns21xx_wdt_resources[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.start	= CNS21XX_WDT_BASE,
 | 
			
		||||
+		.end	= CNS21XX_WDT_BASE + SZ_4K - 1,
 | 
			
		||||
+		.flags	= IORESOURCE_MEM,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+#define CNS21XX_WDT_CLOCK	10	/* 10 Hz */
 | 
			
		||||
+
 | 
			
		||||
+static struct fa_wdt_platform_data cns21xx_wdt_data = {
 | 
			
		||||
+	.clock	= CNS21XX_WDT_CLOCK,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device cns21xx_wdt_device = {
 | 
			
		||||
+	.name			= "fa-wdt",
 | 
			
		||||
+	.id			= -1,
 | 
			
		||||
+	.resource 		= cns21xx_wdt_resources,
 | 
			
		||||
+	.num_resources		= ARRAY_SIZE(cns21xx_wdt_resources),
 | 
			
		||||
+	.dev = {
 | 
			
		||||
+		.platform_data	= &cns21xx_wdt_data,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+int __init cns21xx_register_wdt(void)
 | 
			
		||||
+{
 | 
			
		||||
+	return platform_device_register(&cns21xx_wdt_device);
 | 
			
		||||
+}
 | 
			
		||||
--- a/drivers/watchdog/Kconfig
 | 
			
		||||
+++ b/drivers/watchdog/Kconfig
 | 
			
		||||
@@ -345,7 +345,7 @@ config IMX2_WDT
 | 
			
		||||
 
 | 
			
		||||
 config FA_WATCHDOG
 | 
			
		||||
 	tristate "Faraday watchdog"
 | 
			
		||||
-	depends on ARCH_GEMINI
 | 
			
		||||
+	depends on ARCH_GEMINI || ARCH_CNS21XX
 | 
			
		||||
 	help
 | 
			
		||||
 	  Say Y here if you want support for the built-in watchdog timer
 | 
			
		||||
 	  found in some Faraday FA526 based SoCs.
 | 
			
		||||
@ -0,0 +1,117 @@
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/dev-spi-master.c
 | 
			
		||||
@@ -0,0 +1,83 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file is free software; you can redistribute it and/or modify
 | 
			
		||||
+ *  it under the terms of the GNU General Public License, Version 2, as
 | 
			
		||||
+ *  published by the Free Software Foundation.
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#include <linux/kernel.h>
 | 
			
		||||
+#include <linux/init.h>
 | 
			
		||||
+#include <linux/spi/spi.h>
 | 
			
		||||
+#include <linux/dma-mapping.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/hardware.h>
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+#include <mach/cns21xx_misc.h>
 | 
			
		||||
+#include <mach/cns21xx_powermgmt.h>
 | 
			
		||||
+#include <mach/irqs.h>
 | 
			
		||||
+
 | 
			
		||||
+#include "common.h"
 | 
			
		||||
+
 | 
			
		||||
+static u64 spi_dmamask = DMA_BIT_MASK(32);
 | 
			
		||||
+static struct resource cns21xx_spi_resources[] = {
 | 
			
		||||
+	[0] = {
 | 
			
		||||
+		.start	= CNS21XX_SPI_BASE,
 | 
			
		||||
+		.end	= CNS21XX_SPI_BASE + SZ_4K - 1,
 | 
			
		||||
+		.flags	= IORESOURCE_MEM,
 | 
			
		||||
+	},
 | 
			
		||||
+	[1] = {
 | 
			
		||||
+		.start	= CNS21XX_IRQ_SPI,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_SPI,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device cns21xx_spi_master_device = {
 | 
			
		||||
+	.name		= "cns21xx-spi",
 | 
			
		||||
+	.id		= -1,
 | 
			
		||||
+	.dev		= {
 | 
			
		||||
+		.dma_mask		= &spi_dmamask,
 | 
			
		||||
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 | 
			
		||||
+	},
 | 
			
		||||
+	.resource	= cns21xx_spi_resources,
 | 
			
		||||
+	.num_resources	= ARRAY_SIZE(cns21xx_spi_resources),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+void __init cns21xx_register_spi_master(int id, struct spi_board_info *info,
 | 
			
		||||
+					unsigned int n)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int i;
 | 
			
		||||
+
 | 
			
		||||
+	/* Enable SPI pins */
 | 
			
		||||
+	HAL_MISC_ENABLE_SPIDR_PINS();
 | 
			
		||||
+	HAL_MISC_ENABLE_SPICLK_PINS();
 | 
			
		||||
+	for (i = 0; i < n; i++) {
 | 
			
		||||
+		switch (info[i].chip_select) {
 | 
			
		||||
+		case 0:
 | 
			
		||||
+			HAL_MISC_ENABLE_SPICSN0_PINS();
 | 
			
		||||
+			break;
 | 
			
		||||
+		case 1:
 | 
			
		||||
+			HAL_MISC_ENABLE_SPICSN1_PINS();
 | 
			
		||||
+			break;
 | 
			
		||||
+		case 2:
 | 
			
		||||
+			HAL_MISC_ENABLE_SPICSN2_PINS();
 | 
			
		||||
+			break;
 | 
			
		||||
+		case 3:
 | 
			
		||||
+			HAL_MISC_ENABLE_SPICSN3_PINS();
 | 
			
		||||
+			break;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	/* Disable SPI serial flash access through 0x30000000 region */
 | 
			
		||||
+	HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS();
 | 
			
		||||
+
 | 
			
		||||
+	/* Enable SPI clock */
 | 
			
		||||
+	HAL_PWRMGT_ENABLE_SPI_CLOCK();
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_spi_master_device.id = id;
 | 
			
		||||
+
 | 
			
		||||
+	spi_register_board_info(info, n);
 | 
			
		||||
+	platform_device_register(&cns21xx_spi_master_device);
 | 
			
		||||
+}
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
@@ -6,4 +6,7 @@ endmenu
 | 
			
		||||
 config CNS21XX_DEV_USB
 | 
			
		||||
 	def_bool n
 | 
			
		||||
 
 | 
			
		||||
+config CNS21XX_DEV_SPI_MASTER
 | 
			
		||||
+	def_bool n
 | 
			
		||||
+
 | 
			
		||||
 endif
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -8,6 +8,7 @@ obj-y		:= core.o devices.o gpio.o irq.o
 | 
			
		||||
 
 | 
			
		||||
 # devices
 | 
			
		||||
 obj-$(CONFIG_CNS21XX_DEV_USB)		+= dev-usb.o
 | 
			
		||||
+obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER)	+= dev-spi-master.o
 | 
			
		||||
 
 | 
			
		||||
 # machine specific files
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/common.h
 | 
			
		||||
@@ -21,4 +21,8 @@ int __init cns21xx_register_uart1(void);
 | 
			
		||||
 int __init cns21xx_register_usb(void);
 | 
			
		||||
 int __init cns21xx_register_wdt(void);
 | 
			
		||||
 
 | 
			
		||||
+struct spi_board_info;
 | 
			
		||||
+void __init cns21xx_register_spi_master(int id, struct spi_board_info *info,
 | 
			
		||||
+					unsigned int n);
 | 
			
		||||
+
 | 
			
		||||
 #endif /* _MACH_CNS21XX_COMMON_H */
 | 
			
		||||
@ -0,0 +1,178 @@
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
@@ -3,6 +3,9 @@ if ARCH_CNS21XX
 | 
			
		||||
 menu "Cavium Networks CNS21xx based machines"
 | 
			
		||||
 endmenu
 | 
			
		||||
 
 | 
			
		||||
+config CNS21XX_DEV_GEC
 | 
			
		||||
+	def_bool n
 | 
			
		||||
+
 | 
			
		||||
 config CNS21XX_DEV_USB
 | 
			
		||||
 	def_bool n
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
 obj-y		:= core.o devices.o gpio.o irq.o mm.o time.o
 | 
			
		||||
 
 | 
			
		||||
 # devices
 | 
			
		||||
+obj-$(CONFIG_CNS21XX_DEV_GEC)		+= dev-gec.o
 | 
			
		||||
 obj-$(CONFIG_CNS21XX_DEV_USB)		+= dev-usb.o
 | 
			
		||||
 obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER)	+= dev-spi-master.o
 | 
			
		||||
 
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/dev-gec.c
 | 
			
		||||
@@ -0,0 +1,98 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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/dma-mapping.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/etherdevice.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <asm/sizes.h>
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+#include <mach/irqs.h>
 | 
			
		||||
+
 | 
			
		||||
+#include "dev-gec.h"
 | 
			
		||||
+
 | 
			
		||||
+static u8 cns21xx_ethaddr[ETH_ALEN];
 | 
			
		||||
+struct cns21xx_gec_plat_data cns21xx_gec_data;
 | 
			
		||||
+
 | 
			
		||||
+static struct resource cns21xx_gec_resources[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.start	= CNS21XX_NIC_BASE,
 | 
			
		||||
+		.end	= CNS21XX_NIC_BASE + SZ_4K - 1,
 | 
			
		||||
+		.flags	= IORESOURCE_MEM,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name	= CNS21XX_GEC_STATUS_IRQ_NAME,
 | 
			
		||||
+		.start	= CNS21XX_IRQ_NIC_STATUS,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_NIC_STATUS,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name	= CNS21XX_GEC_RXRC_IRQ_NAME,
 | 
			
		||||
+		.start	= CNS21XX_IRQ_NIC_RXRC,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_NIC_RXRC,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name	= CNS21XX_GEC_RXQF_IRQ_NAME,
 | 
			
		||||
+		.start	= CNS21XX_IRQ_NIC_RXQF,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_NIC_RXQF,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name	= CNS21XX_GEC_TXTC_IRQ_NAME,
 | 
			
		||||
+		.start	= CNS21XX_IRQ_NIC_TXTC,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_NIC_TXTC,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name	= CNS21XX_GEC_TXQE_IRQ_NAME,
 | 
			
		||||
+		.start	= CNS21XX_IRQ_NIC_TXQE,
 | 
			
		||||
+		.end	= CNS21XX_IRQ_NIC_TXQE,
 | 
			
		||||
+		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
+	}
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static u64 cns21xx_gec_dmamask = DMA_BIT_MASK(32);
 | 
			
		||||
+static struct platform_device cns21xx_gec_device = {
 | 
			
		||||
+	.name			= "cns21xx-gec",
 | 
			
		||||
+	.id			= -1,
 | 
			
		||||
+	.resource		= cns21xx_gec_resources,
 | 
			
		||||
+	.num_resources		= ARRAY_SIZE(cns21xx_gec_resources),
 | 
			
		||||
+	.dev = {
 | 
			
		||||
+		.dma_mask		= &cns21xx_gec_dmamask,
 | 
			
		||||
+		.coherent_dma_mask 	= DMA_BIT_MASK(32),
 | 
			
		||||
+		.platform_data		= &cns21xx_gec_data,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static int __init cns21xx_ethaddr_setup(char *str)
 | 
			
		||||
+{
 | 
			
		||||
+	int t;
 | 
			
		||||
+
 | 
			
		||||
+	t = sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
 | 
			
		||||
+		   &cns21xx_ethaddr[0], &cns21xx_ethaddr[1],
 | 
			
		||||
+		   &cns21xx_ethaddr[2], &cns21xx_ethaddr[3],
 | 
			
		||||
+		   &cns21xx_ethaddr[4], &cns21xx_ethaddr[5]);
 | 
			
		||||
+
 | 
			
		||||
+	if (t != ETH_ALEN)
 | 
			
		||||
+		pr_err("cns21xx: failed to parse mac address \"%s\"\n", str);
 | 
			
		||||
+
 | 
			
		||||
+	return 1;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+__setup("ethaddr=", cns21xx_ethaddr_setup);
 | 
			
		||||
+
 | 
			
		||||
+__init int cns21xx_register_gec(void)
 | 
			
		||||
+{
 | 
			
		||||
+	if (cns21xx_gec_data.mac_addr == NULL)
 | 
			
		||||
+		cns21xx_gec_data.mac_addr = cns21xx_ethaddr;
 | 
			
		||||
+
 | 
			
		||||
+	if (!is_valid_ether_addr(cns21xx_gec_data.mac_addr)) {
 | 
			
		||||
+		random_ether_addr(cns21xx_gec_data.mac_addr);
 | 
			
		||||
+		pr_debug("cns21xx: using random MAC address \"%s\"\n",
 | 
			
		||||
+			cns21xx_gec_data.mac_addr);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return platform_device_register(&cns21xx_gec_device);
 | 
			
		||||
+}
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/dev-gec.h
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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 _CNS21XX_DEV_GEC_H
 | 
			
		||||
+#define _CNS21XX_DEV_GEC_H
 | 
			
		||||
+
 | 
			
		||||
+#include <mach/cns21xx_gec_platform.h>
 | 
			
		||||
+
 | 
			
		||||
+extern struct cns21xx_gec_plat_data cns21xx_gec_data;
 | 
			
		||||
+
 | 
			
		||||
+__init int cns21xx_register_gec(void);
 | 
			
		||||
+
 | 
			
		||||
+#endif /* _CNS21XX_DEV_GEC_H */
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/include/mach/cns21xx_gec_platform.h
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file 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 _CNS21XX_GEC_PLATFORM_H
 | 
			
		||||
+#define _CNS21XX_GEC_PLATFORM_H
 | 
			
		||||
+
 | 
			
		||||
+#define CNS21XX_GEC_STATUS_IRQ_NAME	"status"
 | 
			
		||||
+#define CNS21XX_GEC_RXRC_IRQ_NAME	"rxrc"
 | 
			
		||||
+#define CNS21XX_GEC_RXQF_IRQ_NAME	"rxqf"
 | 
			
		||||
+#define CNS21XX_GEC_TXTC_IRQ_NAME	"txtc"
 | 
			
		||||
+#define CNS21XX_GEC_TXQE_IRQ_NAME	"txqe"
 | 
			
		||||
+
 | 
			
		||||
+enum cns21xx_gec_phy_type {
 | 
			
		||||
+	CNS21XX_GEC_PHY_TYPE_INTERNAL = 0,
 | 
			
		||||
+	CNS21XX_GEC_PHY_TYPE_VSC8601,
 | 
			
		||||
+	CNS21XX_GEC_PHY_TYPE_IP101A,
 | 
			
		||||
+	CNS21XX_GEC_PHY_TYPE_IP1001,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct cns21xx_gec_plat_data {
 | 
			
		||||
+	u8				*mac_addr;
 | 
			
		||||
+	enum cns21xx_gec_phy_type	phy_type;
 | 
			
		||||
+	u8				phy_addr;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+#endif /* _CNS21XX_GEC_PLATFORM_H */
 | 
			
		||||
							
								
								
									
										233
									
								
								target/linux/cns21xx/patches-3.2/301-cns21xx-mach-ns-k330.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								target/linux/cns21xx/patches-3.2/301-cns21xx-mach-ns-k330.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,233 @@
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
@@ -1,6 +1,16 @@
 | 
			
		||||
 if ARCH_CNS21XX
 | 
			
		||||
 
 | 
			
		||||
 menu "Cavium Networks CNS21xx based machines"
 | 
			
		||||
+
 | 
			
		||||
+config MACH_NS_K330
 | 
			
		||||
+	bool "NS-K330 NAS"
 | 
			
		||||
+	select CNS21XX_DEV_GEC
 | 
			
		||||
+	select CNS21XX_DEV_SPI_MASTER
 | 
			
		||||
+	select CNS21XX_DEV_USB
 | 
			
		||||
+	help
 | 
			
		||||
+	  Say Y here if you intend to run this kernel on the
 | 
			
		||||
+	  NS-K330 NAS board.
 | 
			
		||||
+
 | 
			
		||||
 endmenu
 | 
			
		||||
 
 | 
			
		||||
 config CNS21XX_DEV_GEC
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/mach-ns-k330.c
 | 
			
		||||
@@ -0,0 +1,203 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  NS-K330 NAS board support
 | 
			
		||||
+ *
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file is free software; you can redistribute it and/or modify
 | 
			
		||||
+ *  it under the terms of the GNU General Public License, Version 2, as
 | 
			
		||||
+ *  published by the Free Software Foundation.
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#include <linux/kernel.h>
 | 
			
		||||
+#include <linux/init.h>
 | 
			
		||||
+#include <linux/mtd/mtd.h>
 | 
			
		||||
+#include <linux/mtd/map.h>
 | 
			
		||||
+#include <linux/mtd/partitions.h>
 | 
			
		||||
+#include <linux/spi/spi.h>
 | 
			
		||||
+#include <linux/spi/flash.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/gpio.h>
 | 
			
		||||
+#include <linux/leds.h>
 | 
			
		||||
+#include <linux/gpio_keys.h>
 | 
			
		||||
+#include <linux/input.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <asm/setup.h>
 | 
			
		||||
+#include <asm/mach-types.h>
 | 
			
		||||
+#include <asm/mach/arch.h>
 | 
			
		||||
+#include <asm/mach/time.h>
 | 
			
		||||
+#include <mach/hardware.h>
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+#include <mach/cns21xx_misc.h>
 | 
			
		||||
+
 | 
			
		||||
+#include "common.h"
 | 
			
		||||
+#include "dev-gec.h"
 | 
			
		||||
+
 | 
			
		||||
+#define NS_K330_GPIO_LED_LINK		1
 | 
			
		||||
+#define NS_K330_GPIO_LED_USB1		16
 | 
			
		||||
+#define NS_K330_GPIO_LED_USB2		17
 | 
			
		||||
+#define NS_K330_GPIO_LED_ETH_GREEN	22
 | 
			
		||||
+#define NS_K330_GPIO_LED_ETH_ORANGE	23
 | 
			
		||||
+
 | 
			
		||||
+#define NS_K330_GPIO_BTN_RESET		13
 | 
			
		||||
+#define NS_K330_GPIO_BTN_USB1		14
 | 
			
		||||
+#define NS_K330_GPIO_BTN_USB2		15
 | 
			
		||||
+
 | 
			
		||||
+static struct mtd_partition ns_k330_partitions[] =  {
 | 
			
		||||
+	{
 | 
			
		||||
+		.name		= "boot",
 | 
			
		||||
+		.offset		= 0x0,
 | 
			
		||||
+		.size		= 0x040000,
 | 
			
		||||
+		.mask_flags	= MTD_WRITEABLE,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "config",
 | 
			
		||||
+		.offset		= 0x040000,
 | 
			
		||||
+		.size		= 0x020000,
 | 
			
		||||
+		.mask_flags	= MTD_WRITEABLE,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "kernel",
 | 
			
		||||
+		.offset		= 0x060000,
 | 
			
		||||
+		.size		= 0x100000,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "rootfs",
 | 
			
		||||
+		.offset		= 0x160000,
 | 
			
		||||
+		.size		= 0x290000,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "firmware",
 | 
			
		||||
+		.offset		= 0x060000,
 | 
			
		||||
+		.size		= 0x390000,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct flash_platform_data ns_k330_flash_data = {
 | 
			
		||||
+        .parts          = ns_k330_partitions,
 | 
			
		||||
+        .nr_parts       = ARRAY_SIZE(ns_k330_partitions),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct spi_board_info ns_k330_spi_board_info[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.bus_num	= 0,
 | 
			
		||||
+		.chip_select	= 0,
 | 
			
		||||
+		.max_speed_hz	= 25000000,
 | 
			
		||||
+		.modalias	= "m25p80",
 | 
			
		||||
+		.platform_data	= &ns_k330_flash_data,
 | 
			
		||||
+	}
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_led ns_k330_gpio_leds[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.name		= "ns-k330:red:link",
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_LED_LINK,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "ns-k330:green:usb1",
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_LED_USB1,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "ns-k330:green:usb2",
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_LED_USB2,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "ns-k330:green:eth",
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_LED_ETH_GREEN,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "ns-k330:orange:eth",
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_LED_ETH_ORANGE,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_led_platform_data ns_k330_gpio_leds_data = {
 | 
			
		||||
+	.num_leds		= ARRAY_SIZE(ns_k330_gpio_leds),
 | 
			
		||||
+	.leds			= ns_k330_gpio_leds,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device ns_k330_gpio_leds_device = {
 | 
			
		||||
+	.name			= "leds-gpio",
 | 
			
		||||
+	.id			= -1,
 | 
			
		||||
+	.dev.platform_data	= &ns_k330_gpio_leds_data,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_keys_button ns_k330_gpio_keys[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.code		= KEY_RESTART,
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_BTN_RESET,
 | 
			
		||||
+		.desc		= "Reset Button",
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	},
 | 
			
		||||
+	{
 | 
			
		||||
+		.code		= BTN_0,
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_BTN_USB1,
 | 
			
		||||
+		.desc		= "USB1 Button",
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	},
 | 
			
		||||
+	{
 | 
			
		||||
+		.code		= BTN_1,
 | 
			
		||||
+		.gpio		= NS_K330_GPIO_BTN_USB2,
 | 
			
		||||
+		.desc		= "USB2 Button",
 | 
			
		||||
+		.active_low	= 0,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_keys_platform_data ns_k330_gpio_keys_data = {
 | 
			
		||||
+	.buttons	= ns_k330_gpio_keys,
 | 
			
		||||
+	.nbuttons	= ARRAY_SIZE(ns_k330_gpio_keys),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device ns_k330_gpio_keys_device = {
 | 
			
		||||
+	.name		= "gpio-keys",
 | 
			
		||||
+	.id		= -1,
 | 
			
		||||
+	.num_resources	= 0,
 | 
			
		||||
+	.dev		= {
 | 
			
		||||
+		.platform_data	= &ns_k330_gpio_keys_data,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void __init ns_k330_fixup(struct tag *tags, char **cmdline,
 | 
			
		||||
+				 struct meminfo *mi)
 | 
			
		||||
+{
 | 
			
		||||
+	struct tag *t;
 | 
			
		||||
+
 | 
			
		||||
+	/* The board has 32MB of RAM mapped at 0. */
 | 
			
		||||
+	mi->nr_banks = 1;
 | 
			
		||||
+	mi->bank[0].start = 0;
 | 
			
		||||
+	mi->bank[0].size = SZ_32M;
 | 
			
		||||
+
 | 
			
		||||
+	for (t = tags; t->hdr.size; t = tag_next(t)) {
 | 
			
		||||
+		switch (t->hdr.tag) {
 | 
			
		||||
+		case ATAG_CORE:
 | 
			
		||||
+			if (t->u.core.rootdev == 255)
 | 
			
		||||
+				t->u.core.rootdev = 0;
 | 
			
		||||
+			break;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void __init ns_k330_init(void)
 | 
			
		||||
+{
 | 
			
		||||
+	cns21xx_gpio_init();
 | 
			
		||||
+
 | 
			
		||||
+	HAL_MISC_DISABLE_LED012_PINS();
 | 
			
		||||
+	HAL_MISC_DISABLE_I2C_PINS();
 | 
			
		||||
+	HAL_MISC_DISABLE_I2S_PINS();
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_register_uart0();
 | 
			
		||||
+	cns21xx_register_wdt();
 | 
			
		||||
+	cns21xx_register_usb();
 | 
			
		||||
+	cns21xx_register_spi_master(-1, ns_k330_spi_board_info,
 | 
			
		||||
+				    ARRAY_SIZE(ns_k330_spi_board_info));
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_gec_data.phy_type = CNS21XX_GEC_PHY_TYPE_INTERNAL;
 | 
			
		||||
+	cns21xx_register_gec();
 | 
			
		||||
+
 | 
			
		||||
+	platform_device_register(&ns_k330_gpio_leds_device);
 | 
			
		||||
+	platform_device_register(&ns_k330_gpio_keys_device);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+MACHINE_START(NS_K330, "NS-K330 NAS")
 | 
			
		||||
+	.fixup		= ns_k330_fixup,
 | 
			
		||||
+	.map_io		= cns21xx_map_io,
 | 
			
		||||
+	.init_irq	= cns21xx_init_irq,
 | 
			
		||||
+	.timer		= &cns21xx_timer,
 | 
			
		||||
+	.init_machine	= ns_k330_init,
 | 
			
		||||
+MACHINE_END
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -12,4 +12,4 @@ obj-$(CONFIG_CNS21XX_DEV_USB)		+= dev-us
 | 
			
		||||
 obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER)	+= dev-spi-master.o
 | 
			
		||||
 
 | 
			
		||||
 # machine specific files
 | 
			
		||||
-
 | 
			
		||||
+obj-$(CONFIG_MACH_NS_K330)		+= mach-ns-k330.o
 | 
			
		||||
							
								
								
									
										200
									
								
								target/linux/cns21xx/patches-3.2/302-cns21xx-mach-nsb3ast.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								target/linux/cns21xx/patches-3.2/302-cns21xx-mach-nsb3ast.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,200 @@
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Kconfig
 | 
			
		||||
@@ -2,6 +2,15 @@ if ARCH_CNS21XX
 | 
			
		||||
 
 | 
			
		||||
 menu "Cavium Networks CNS21xx based machines"
 | 
			
		||||
 
 | 
			
		||||
+config MACH_NSB3AST
 | 
			
		||||
+	bool "AGESTAR NSB3AST support"
 | 
			
		||||
+	select CNS21XX_DEV_GEC
 | 
			
		||||
+	select CNS21XX_DEV_SPI_MASTER
 | 
			
		||||
+	select CNS21XX_DEV_USB
 | 
			
		||||
+	help
 | 
			
		||||
+	  Say Y here if you intend to run this kernel on the
 | 
			
		||||
+	  AGESTAR NSB3AST board.
 | 
			
		||||
+
 | 
			
		||||
 config MACH_NS_K330
 | 
			
		||||
 	bool "NS-K330 NAS"
 | 
			
		||||
 	select CNS21XX_DEV_GEC
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/mach-nsb3ast.c
 | 
			
		||||
@@ -0,0 +1,172 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ *  AGESTAR NSB3AST board support
 | 
			
		||||
+ *
 | 
			
		||||
+ *  Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
+ *
 | 
			
		||||
+ *  This file is free software; you can redistribute it and/or modify
 | 
			
		||||
+ *  it under the terms of the GNU General Public License, Version 2, as
 | 
			
		||||
+ *  published by the Free Software Foundation.
 | 
			
		||||
+ */
 | 
			
		||||
+
 | 
			
		||||
+#include <linux/kernel.h>
 | 
			
		||||
+#include <linux/init.h>
 | 
			
		||||
+#include <linux/mtd/mtd.h>
 | 
			
		||||
+#include <linux/mtd/map.h>
 | 
			
		||||
+#include <linux/mtd/partitions.h>
 | 
			
		||||
+#include <linux/spi/spi.h>
 | 
			
		||||
+#include <linux/spi/flash.h>
 | 
			
		||||
+#include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/gpio.h>
 | 
			
		||||
+#include <linux/leds.h>
 | 
			
		||||
+#include <linux/gpio_keys.h>
 | 
			
		||||
+#include <linux/input.h>
 | 
			
		||||
+
 | 
			
		||||
+#include <asm/setup.h>
 | 
			
		||||
+#include <asm/mach-types.h>
 | 
			
		||||
+#include <asm/mach/arch.h>
 | 
			
		||||
+#include <asm/mach/time.h>
 | 
			
		||||
+#include <mach/hardware.h>
 | 
			
		||||
+#include <mach/cns21xx.h>
 | 
			
		||||
+#include <mach/cns21xx_misc.h>
 | 
			
		||||
+
 | 
			
		||||
+#include "common.h"
 | 
			
		||||
+#include "dev-gec.h"
 | 
			
		||||
+
 | 
			
		||||
+static struct mtd_partition nsb3ast_partitions[] =  {
 | 
			
		||||
+	{
 | 
			
		||||
+		.name		= "armboot",
 | 
			
		||||
+		.offset		= 0x0,
 | 
			
		||||
+		.size		= 0x040000,
 | 
			
		||||
+		.mask_flags	= MTD_WRITEABLE,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "kernel",
 | 
			
		||||
+		.offset		= 0x040000,
 | 
			
		||||
+		.size		= 0x100000,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "rootfs",
 | 
			
		||||
+		.offset		= 0x140000,
 | 
			
		||||
+		.size		= 0x6c0000,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "firmware",
 | 
			
		||||
+		.offset		= 0x040000,
 | 
			
		||||
+		.size		= 0x7c0000,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "wholeflash",
 | 
			
		||||
+		.offset		= 0x0,
 | 
			
		||||
+		.size		= 0x800000,
 | 
			
		||||
+		.mask_flags	= MTD_WRITEABLE,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct flash_platform_data nsb3ast_flash_data = {
 | 
			
		||||
+        .parts          = nsb3ast_partitions,
 | 
			
		||||
+        .nr_parts       = ARRAY_SIZE(nsb3ast_partitions),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct spi_board_info nsb3ast_spi_board_info[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.bus_num	= 0,
 | 
			
		||||
+		.chip_select	= 0,
 | 
			
		||||
+		.max_speed_hz	= 25000000,
 | 
			
		||||
+		.modalias	= "m25p80",
 | 
			
		||||
+		.platform_data	= &nsb3ast_flash_data,
 | 
			
		||||
+	}
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_led nsb3ast_gpio_leds[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.name		= "nsb3ast:red:d1",
 | 
			
		||||
+		.gpio		= 15,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}, {
 | 
			
		||||
+		.name		= "nsb3ast:amber:eth",
 | 
			
		||||
+		.gpio		= 22,
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	}
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_led_platform_data nsb3ast_gpio_leds_data = {
 | 
			
		||||
+	.num_leds		= ARRAY_SIZE(nsb3ast_gpio_leds),
 | 
			
		||||
+	.leds			= nsb3ast_gpio_leds,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device nsb3ast_gpio_leds_device = {
 | 
			
		||||
+	.name			= "leds-gpio",
 | 
			
		||||
+	.id			= -1,
 | 
			
		||||
+	.dev.platform_data	= &nsb3ast_gpio_leds_data,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_keys_button nsb3ast_gpio_keys[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.code		= KEY_RESTART,
 | 
			
		||||
+		.gpio		= 0,
 | 
			
		||||
+		.desc		= "Reset Button",
 | 
			
		||||
+		.active_low	= 1,
 | 
			
		||||
+	},
 | 
			
		||||
+	{
 | 
			
		||||
+		.code		= BTN_0,
 | 
			
		||||
+		.gpio		= 2,
 | 
			
		||||
+		.desc		= "USB Button",
 | 
			
		||||
+		.active_low	= 0,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct gpio_keys_platform_data nsb3ast_gpio_keys_data = {
 | 
			
		||||
+	.buttons	= nsb3ast_gpio_keys,
 | 
			
		||||
+	.nbuttons	= ARRAY_SIZE(nsb3ast_gpio_keys),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static struct platform_device nsb3ast_gpio_keys_device = {
 | 
			
		||||
+	.name		= "gpio-keys",
 | 
			
		||||
+	.id		= -1,
 | 
			
		||||
+	.num_resources	= 0,
 | 
			
		||||
+	.dev		= {
 | 
			
		||||
+		.platform_data	= &nsb3ast_gpio_keys_data,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void __init nsb3ast_fixup(struct tag *tags, char **cmdline,
 | 
			
		||||
+			  	 struct meminfo *mi)
 | 
			
		||||
+{
 | 
			
		||||
+	struct tag *t;
 | 
			
		||||
+
 | 
			
		||||
+	/* The board has 32MB of RAM mapped at 0. */
 | 
			
		||||
+	mi->nr_banks = 1;
 | 
			
		||||
+	mi->bank[0].start = 0;
 | 
			
		||||
+	mi->bank[0].size = SZ_32M;
 | 
			
		||||
+
 | 
			
		||||
+	for (t = tags; t->hdr.size; t = tag_next(t)) {
 | 
			
		||||
+		switch (t->hdr.tag) {
 | 
			
		||||
+		case ATAG_CORE:
 | 
			
		||||
+			if (t->u.core.rootdev == 255)
 | 
			
		||||
+				t->u.core.rootdev = 0;
 | 
			
		||||
+			break;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void __init nsb3ast_init(void)
 | 
			
		||||
+{
 | 
			
		||||
+	cns21xx_gpio_init();
 | 
			
		||||
+	cns21xx_register_uart0();
 | 
			
		||||
+	cns21xx_register_uart1();
 | 
			
		||||
+	cns21xx_register_wdt();
 | 
			
		||||
+	cns21xx_register_usb();
 | 
			
		||||
+	cns21xx_register_spi_master(-1, nsb3ast_spi_board_info,
 | 
			
		||||
+				    ARRAY_SIZE(nsb3ast_spi_board_info));
 | 
			
		||||
+
 | 
			
		||||
+	cns21xx_gec_data.phy_type = CNS21XX_GEC_PHY_TYPE_INTERNAL;
 | 
			
		||||
+	cns21xx_register_gec();
 | 
			
		||||
+
 | 
			
		||||
+	HAL_MISC_DISABLE_LED012_PINS();
 | 
			
		||||
+	platform_device_register(&nsb3ast_gpio_leds_device);
 | 
			
		||||
+	platform_device_register(&nsb3ast_gpio_keys_device);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+MACHINE_START(NSB3AST, "AGESTAR NSB3AST")
 | 
			
		||||
+	.fixup		= nsb3ast_fixup,
 | 
			
		||||
+	.map_io		= cns21xx_map_io,
 | 
			
		||||
+	.init_irq	= cns21xx_init_irq,
 | 
			
		||||
+	.timer		= &cns21xx_timer,
 | 
			
		||||
+	.init_machine	= nsb3ast_init,
 | 
			
		||||
+MACHINE_END
 | 
			
		||||
--- a/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
+++ b/arch/arm/mach-cns21xx/Makefile
 | 
			
		||||
@@ -13,3 +13,4 @@ obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER)	+=
 | 
			
		||||
 
 | 
			
		||||
 # machine specific files
 | 
			
		||||
 obj-$(CONFIG_MACH_NS_K330)		+= mach-ns-k330.o
 | 
			
		||||
+obj-$(CONFIG_MACH_NSB3AST)		+= mach-nsb3ast.o
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user