1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-24 00:07:11 +02:00

update xburst qi_lb60 to linux-v3.2.1

This commit is contained in:
Xiangfu Liu 2012-02-23 18:28:08 +08:00
parent 76c9a5db03
commit c2528ed099
48 changed files with 3342 additions and 15461 deletions

View File

@ -12,7 +12,7 @@ BOARDNAME:=Ingenic XBurst
FEATURES:=jffs2 targz ubifs audio
SUBTARGETS:=qi_lb60 n516 n526 id800wt
LINUX_VERSION:=3.0
LINUX_VERSION:=3.2.1
DEVICE_TYPE=other

View File

@ -6,15 +6,14 @@ CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_ARPD is not set
# CONFIG_ATH79 is not set
# CONFIG_ATMEL_PWM is not set
CONFIG_BATTERY_JZ4740=y
CONFIG_BCMA_POSSIBLE=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BRIDGE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_CHARGER_GPIO=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_CPU_HAS_PREFETCH=y
@ -31,6 +30,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
CONFIG_DEVMEM=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_EARLY_PRINTK=y
@ -40,26 +40,10 @@ CONFIG_EXT4_FS=y
CONFIG_FAT_FS=y
CONFIG_FB=y
# CONFIG_FB_JZ4740 is not set
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_TMIO is not set
# CONFIG_FB_WMT_GE_ROPS is not set
# CONFIG_FIRMWARE_EDID is not set
CONFIG_FONTS=y
# CONFIG_FONT_10x18 is not set
# CONFIG_FONT_6x11 is not set
# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_8x16 is not set
# CONFIG_FONT_8x8 is not set
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_SUN12x22 is not set
CONFIG_FONT_SUN8x16=y
CONFIG_FORCE_MAX_ZONEORDER=12
# CONFIG_FRAMEBUFFER_CONSOLE is not set
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FREEZER=y
CONFIG_FS_MBCACHE=y
CONFIG_GENERIC_ATOMIC64=y
@ -89,8 +73,6 @@ CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_GENERIC_HARDIRQS=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_IRQ_WORK=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
@ -103,11 +85,9 @@ CONFIG_HW_CONSOLE=y
# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
# CONFIG_INLINE_WRITE_UNLOCK is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
CONFIG_INOTIFY_USER=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_KEXEC=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_INPUT_MOUSE=y
CONFIG_INPUT_MOUSEDEV=y
@ -117,23 +97,15 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_PWM_BEEPER is not set
CONFIG_INPUT_UINPUT=y
CONFIG_IRQ_CPU=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_JBD2=y
# CONFIG_JZ4740_ADC is not set
# CONFIG_JZ4740_QI_LB60 is not set
# CONFIG_JZ4740_ID800WT is not set
# CONFIG_JZ4740_N516 is not set
# CONFIG_JZ4740_N526 is not set
CONFIG_JZ4740_QI_LB60=y
CONFIG_KALLSYMS=y
CONFIG_KEXEC=y
# CONFIG_KEYBOARD_GPIO is not set
# CONFIG_LANTIQ is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=2
# CONFIG_LOGO is not set
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
# CONFIG_LOGO_LINUX_CLUT224 is not set
# CONFIG_LOGO_OPENWRT_CLUT224 is not set
# CONFIG_LOGO_NANONOTE_CLUT224 is not set
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MACH_JZ4740=y
@ -164,7 +136,6 @@ CONFIG_MOUSE_PS2=y
# CONFIG_MTD_CFI is not set
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_NAND=y
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_JZ4740=y
# CONFIG_MTD_SM_COMMON is not set
@ -175,9 +146,7 @@ CONFIG_MTD_UBI_BEB_RESERVE=1
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
# CONFIG_NET_ETHERNET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_NEW_LEDS is not set
CONFIG_NLS=y
@ -223,16 +192,19 @@ CONFIG_PAGEFLAGS_EXTENDED=y
# CONFIG_PDA_POWER is not set
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PM=y
CONFIG_PM_CLK=y
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
CONFIG_PREEMPT=y
CONFIG_PREEMPT_COUNT=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_RCU is not set
CONFIG_PREEMPT_RCU=y
CONFIG_PRINTK_TIME=y
CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_QUOTACTL is not set
# CONFIG_RCU_BOOST is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_CMOS is not set
CONFIG_RTC_DRV_JZ4740=y
@ -253,7 +225,7 @@ CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_TINY_PREEMPT_RCU is not set
CONFIG_TINY_PREEMPT_RCU=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
# CONFIG_UBIFS_FS_DEBUG is not set
@ -261,30 +233,32 @@ CONFIG_UBIFS_FS_LZO=y
# CONFIG_UBIFS_FS_XATTR is not set
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB_ARCH_HAS_XHCI is not set
# CONFIG_USB_CDC_COMPOSITE is not set
CONFIG_USB_COMMON=y
CONFIG_USB_ETH=y
# CONFIG_USB_ETH_EEM is not set
# CONFIG_USB_ETH_RNDIS is not set
# CONFIG_USB_FILE_STORAGE is not set
# CONFIG_USB_FUNCTIONFS is not set
# CONFIG_USB_FUSB300 is not set
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
# CONFIG_USB_GADGET_DEBUG_FS is not set
CONFIG_USB_GADGET_DUALSPEED=y
# CONFIG_USB_GADGET_FUSB300 is not set
CONFIG_USB_GADGET_JZ4740=y
# CONFIG_USB_GADGET_M66592 is not set
# CONFIG_USB_GADGET_PXA_U2O is not set
# CONFIG_USB_GADGET_R8A66597 is not set
CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
CONFIG_USB_GADGET_VBUS_DRAW=2
# CONFIG_USB_G_ACM_MS is not set
# CONFIG_USB_G_DBGP is not set
# CONFIG_USB_G_HID is not set
# CONFIG_USB_G_NCM is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_G_SERIAL is not set
CONFIG_USB_JZ4740=y
# CONFIG_USB_M66592 is not set
# CONFIG_USB_NET2272 is not set
# CONFIG_USB_R8A66597 is not set
CONFIG_USB_SUPPORT=y
# CONFIG_USB_ZERO is not set
CONFIG_VFAT_FS=y
@ -292,6 +266,7 @@ CONFIG_VFAT_FS=y
# CONFIG_VLAN_8021Q is not set
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_CONSOLE_SLEEP=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_WATCHDOG is not set
CONFIG_ZONE_DMA_FLAG=0

View File

@ -1,339 +0,0 @@
From 2f669aa98831b7248402bab6a07b1b6f722cb6e9 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 24 Apr 2010 17:34:29 +0200
Subject: [PATCH 01/32] JZ4740 cache quirks
---
arch/mips/include/asm/r4kcache.h | 231 ++++++++++++++++++++++++++++++++++++++
1 files changed, 231 insertions(+), 0 deletions(-)
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 54ea47d..3feee5b 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -17,6 +17,58 @@
#include <asm/cpu-features.h>
#include <asm/mipsmtregs.h>
+#ifdef CONFIG_MACH_JZ4740
+
+#define K0_TO_K1() \
+do { \
+ unsigned long __k0_addr; \
+ \
+ __asm__ __volatile__( \
+ "la %0, 1f\n\t" \
+ "or %0, %0, %1\n\t" \
+ "jr %0\n\t" \
+ "nop\n\t" \
+ "1: nop\n" \
+ : "=&r"(__k0_addr) \
+ : "r" (0x20000000) ); \
+} while(0)
+
+#define K1_TO_K0() \
+do { \
+ unsigned long __k0_addr; \
+ __asm__ __volatile__( \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ "la %0, 1f\n\t" \
+ "jr %0\n\t" \
+ "nop\n\t" \
+ "1: nop\n" \
+ : "=&r" (__k0_addr)); \
+} while (0)
+
+#define INVALIDATE_BTB() \
+do { \
+ unsigned long tmp; \
+ __asm__ __volatile__( \
+ ".set mips32\n\t" \
+ "mfc0 %0, $16, 7\n\t" \
+ "nop\n\t" \
+ "ori %0, 2\n\t" \
+ "mtc0 %0, $16, 7\n\t" \
+ "nop\n\t" \
+ : "=&r" (tmp)); \
+} while (0)
+
+#define SYNC_WB() __asm__ __volatile__ ("sync")
+
+#else /* CONFIG_JZRISC */
+
+#define K0_TO_K1() do { } while (0)
+#define K1_TO_K0() do { } while (0)
+#define INVALIDATE_BTB() do { } while (0)
+#define SYNC_WB() do { } while (0)
+
+#endif /* CONFIG_JZRISC */
+
/*
* This macro return a properly sign-extended address suitable as base address
* for indexed cache operations. Two issues here:
@@ -144,6 +196,7 @@ static inline void flush_icache_line_indexed(unsigned long addr)
{
__iflush_prologue
cache_op(Index_Invalidate_I, addr);
+ INVALIDATE_BTB();
__iflush_epilogue
}
@@ -151,6 +204,7 @@ static inline void flush_dcache_line_indexed(unsigned long addr)
{
__dflush_prologue
cache_op(Index_Writeback_Inv_D, addr);
+ SYNC_WB();
__dflush_epilogue
}
@@ -163,6 +217,7 @@ static inline void flush_icache_line(unsigned long addr)
{
__iflush_prologue
cache_op(Hit_Invalidate_I, addr);
+ INVALIDATE_BTB();
__iflush_epilogue
}
@@ -170,6 +225,7 @@ static inline void flush_dcache_line(unsigned long addr)
{
__dflush_prologue
cache_op(Hit_Writeback_Inv_D, addr);
+ SYNC_WB();
__dflush_epilogue
}
@@ -177,6 +233,7 @@ static inline void invalidate_dcache_line(unsigned long addr)
{
__dflush_prologue
cache_op(Hit_Invalidate_D, addr);
+ SYNC_WB();
__dflush_epilogue
}
@@ -209,6 +266,7 @@ static inline void flush_scache_line(unsigned long addr)
static inline void protected_flush_icache_line(unsigned long addr)
{
protected_cache_op(Hit_Invalidate_I, addr);
+ INVALIDATE_BTB();
}
/*
@@ -220,6 +278,7 @@ static inline void protected_flush_icache_line(unsigned long addr)
static inline void protected_writeback_dcache_line(unsigned long addr)
{
protected_cache_op(Hit_Writeback_Inv_D, addr);
+ SYNC_WB();
}
static inline void protected_writeback_scache_line(unsigned long addr)
@@ -396,8 +455,10 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
+#ifndef CONFIG_JZRISC
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
+#endif
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
@@ -405,12 +466,122 @@ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
+#ifndef CONFIG_JZRISC
__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
+#endif
__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
+#ifdef CONFIG_JZRISC
+
+static inline void blast_dcache32(void)
+{
+ unsigned long start = INDEX_BASE;
+ unsigned long end = start + current_cpu_data.dcache.waysize;
+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
+ unsigned long ws_end = current_cpu_data.dcache.ways <<
+ current_cpu_data.dcache.waybit;
+ unsigned long ws, addr;
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
+ cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
+
+ SYNC_WB();
+}
+
+static inline void blast_dcache32_page(unsigned long page)
+{
+ unsigned long start = page;
+ unsigned long end = page + PAGE_SIZE;
+
+ do {
+ cache32_unroll32(start,Hit_Writeback_Inv_D);
+ start += 0x400;
+ } while (start < end);
+
+ SYNC_WB();
+}
+
+static inline void blast_dcache32_page_indexed(unsigned long page)
+{
+ unsigned long indexmask = current_cpu_data.dcache.waysize - 1;
+ unsigned long start = INDEX_BASE + (page & indexmask);
+ unsigned long end = start + PAGE_SIZE;
+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
+ unsigned long ws_end = current_cpu_data.dcache.ways <<
+ current_cpu_data.dcache.waybit;
+ unsigned long ws, addr;
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
+ cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
+
+ SYNC_WB();
+}
+
+static inline void blast_icache32(void)
+{
+ unsigned long start = INDEX_BASE;
+ unsigned long end = start + current_cpu_data.icache.waysize;
+ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+ unsigned long ws_end = current_cpu_data.icache.ways <<
+ current_cpu_data.icache.waybit;
+ unsigned long ws, addr;
+
+ K0_TO_K1();
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
+ cache32_unroll32(addr|ws,Index_Invalidate_I);
+
+ INVALIDATE_BTB();
+
+ K1_TO_K0();
+}
+
+static inline void blast_icache32_page(unsigned long page)
+{
+ unsigned long start = page;
+ unsigned long end = page + PAGE_SIZE;
+
+ K0_TO_K1();
+
+ do {
+ cache32_unroll32(start,Hit_Invalidate_I);
+ start += 0x400;
+ } while (start < end);
+
+ INVALIDATE_BTB();
+
+ K1_TO_K0();
+}
+
+static inline void blast_icache32_page_indexed(unsigned long page)
+{
+ unsigned long indexmask = current_cpu_data.icache.waysize - 1;
+ unsigned long start = INDEX_BASE + (page & indexmask);
+ unsigned long end = start + PAGE_SIZE;
+ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+ unsigned long ws_end = current_cpu_data.icache.ways <<
+ current_cpu_data.icache.waybit;
+ unsigned long ws, addr;
+
+ K0_TO_K1();
+
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
+ cache32_unroll32(addr|ws,Index_Invalidate_I);
+
+ INVALIDATE_BTB();
+
+ K1_TO_K0();
+}
+
+#endif /* CONFIG_JZRISC */
+
/* build blast_xxx_range, protected_blast_xxx_range */
#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
@@ -432,13 +603,73 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
__##pfx##flush_epilogue \
}
+#ifndef CONFIG_JZRISC
__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
+#endif
__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
+#ifndef CONFIG_JZRISC
__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
+#endif
__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
/* blast_inv_dcache_range */
__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
+#ifdef CONFIG_JZRISC
+
+static inline void protected_blast_dcache_range(unsigned long start,
+ unsigned long end)
+{
+ unsigned long lsize = cpu_dcache_line_size();
+ unsigned long addr = start & ~(lsize - 1);
+ unsigned long aend = (end - 1) & ~(lsize - 1);
+
+ while (1) {
+ protected_cache_op(Hit_Writeback_Inv_D, addr);
+ if (addr == aend)
+ break;
+ addr += lsize;
+ }
+ SYNC_WB();
+}
+
+static inline void protected_blast_icache_range(unsigned long start,
+ unsigned long end)
+{
+ unsigned long lsize = cpu_icache_line_size();
+ unsigned long addr = start & ~(lsize - 1);
+ unsigned long aend = (end - 1) & ~(lsize - 1);
+
+ K0_TO_K1();
+
+ while (1) {
+ protected_cache_op(Hit_Invalidate_I, addr);
+ if (addr == aend)
+ break;
+ addr += lsize;
+ }
+ INVALIDATE_BTB();
+
+ K1_TO_K0();
+}
+
+static inline void blast_dcache_range(unsigned long start,
+ unsigned long end)
+{
+ unsigned long lsize = cpu_dcache_line_size();
+ unsigned long addr = start & ~(lsize - 1);
+ unsigned long aend = (end - 1) & ~(lsize - 1);
+
+ while (1) {
+ cache_op(Hit_Writeback_Inv_D, addr);
+ if (addr == aend)
+ break;
+ addr += lsize;
+ }
+ SYNC_WB();
+}
+
+#endif /* CONFIG_JZRISC */
+
#endif /* _ASM_R4KCACHE_H */
--
1.7.4.1

View File

@ -1,679 +0,0 @@
From 633a1f02f183675e3448c45a5ddd5e942ecbc37c Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 24 Apr 2010 17:25:01 +0200
Subject: [PATCH 02/32] Add n516 board support
---
arch/mips/include/asm/mach-jz4740/board-n516.h | 39 +++
arch/mips/jz4740/Kconfig | 4 +
arch/mips/jz4740/Makefile | 1 +
arch/mips/jz4740/board-n516-display.c | 394 ++++++++++++++++++++++++
arch/mips/jz4740/board-n516.c | 182 +++++++++++
5 files changed, 620 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/include/asm/mach-jz4740/board-n516.h
create mode 100644 arch/mips/jz4740/board-n516-display.c
create mode 100644 arch/mips/jz4740/board-n516.c
diff --git a/arch/mips/include/asm/mach-jz4740/board-n516.h b/arch/mips/include/asm/mach-jz4740/board-n516.h
new file mode 100644
index 0000000..090707e
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/board-n516.h
@@ -0,0 +1,39 @@
+/*
+ * linux/include/asm-mips/mach-jz4740/board-n516.h
+ *
+ * JZ4730-based N516 board definition.
+ *
+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_JZ4740_N516_H__
+#define __ASM_JZ4740_N516_H__
+
+#include <asm/mach-jz4740/gpio.h>
+
+/*
+ * GPIO
+ */
+#define GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(17)
+#define GPIO_SD_CD_N JZ_GPIO_PORTD(7)
+#define GPIO_SD_WP JZ_GPIO_PORTD(15)
+#define GPIO_USB_DETECT JZ_GPIO_PORTD(19)
+#define GPIO_CHARG_STAT_N JZ_GPIO_PORTD(16)
+#define GPIO_LED_ENABLE JZ_GPIO_PORTD(28)
+#define GPIO_LPC_INT JZ_GPIO_PORTD(14)
+#define GPIO_HPHONE_DETECT JZ_GPIO_PORTD(20)
+#define GPIO_SPEAKER_ENABLE JZ_GPIO_PORTD(21)
+
+/* Display */
+#define GPIO_DISPLAY_RST_L JZ_GPIO_PORTB(18)
+#define GPIO_DISPLAY_RDY JZ_GPIO_PORTB(17)
+#define GPIO_DISPLAY_STBY JZ_GPIO_PORTC(22)
+#define GPIO_DISPLAY_ERR JZ_GPIO_PORTC(23)
+#define GPIO_DISPLAY_OFF_N JZ_GPIO_PORTD(1)
+
+#endif /* __ASM_JZ4740_N516_H__ */
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 3e7141f..85bfbf3 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -6,6 +6,10 @@ choice
config JZ4740_QI_LB60
bool "Qi Hardware Ben NanoNote"
+config JZ4740_N516
+ bool "Hanvon n516 eBook reader"
+ select SOC_JZ4740
+
endchoice
config HAVE_PWM
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index a9dff33..727270a 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
# board specific support
obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
+obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
# PM support
diff --git a/arch/mips/jz4740/board-n516-display.c b/arch/mips/jz4740/board-n516-display.c
new file mode 100644
index 0000000..0e77a82
--- /dev/null
+++ b/arch/mips/jz4740/board-n516-display.c
@@ -0,0 +1,394 @@
+/*
+ * board-n516-display.c -- Platform device for N516 display
+ *
+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-jz4740/jz4740_fb.h>
+
+#include <asm/mach-jz4740/platform.h>
+#include <asm/mach-jz4740/board-n516.h>
+
+#include <video/metronomefb.h>
+#include <linux/console.h>
+
+static struct fb_videomode n516_fb_modes[] = {
+ [0] = {
+ .name = "Metronome 800x600",
+ .refresh = 50,
+ .xres = 400,
+ .yres = 624,
+ .hsync_len = 31,
+ .vsync_len = 23,
+ .right_margin = 31,
+ .left_margin = 5,
+ .upper_margin = 1,
+ .lower_margin = 2,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ },
+};
+
+static struct jz4740_fb_platform_data n516_fb_pdata = {
+ .num_modes = ARRAY_SIZE(n516_fb_modes),
+ .modes = n516_fb_modes,
+ .bpp = 16,
+ .lcd_type = JZ_LCD_TYPE_GENERIC_16_BIT,
+};
+
+struct n516_board_info {
+ uint8_t *metromem;
+ size_t wfm_size;
+ struct fb_info *host_fbinfo; /* the host LCD controller's fbi */
+ unsigned int fw;
+ unsigned int fh;
+};
+
+static struct platform_device *n516_device;
+static struct n516_board_info n516_board_info;
+
+static int metronome_gpios[] = {
+ GPIO_DISPLAY_STBY,
+ GPIO_DISPLAY_RST_L,
+ GPIO_DISPLAY_RDY,
+ GPIO_DISPLAY_ERR,
+/* GPIO_DISPLAY_OFF_N,*/
+};
+
+static const char *metronome_gpio_names[] = {
+ "Metronome STDBY",
+ "Metronome RST",
+ "Metronome RDY",
+ "Metronome ERR",
+/* "Metronone OFF",*/
+};
+
+static int n516_enable_hostfb(bool enable)
+{
+ int ret;
+ int blank = enable ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+
+ acquire_console_sem();
+ ret = fb_blank(n516_board_info.host_fbinfo, blank);
+ release_console_sem();
+
+ return ret;
+}
+
+static int n516_init_metronome_gpios(struct metronomefb_par *par)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i) {
+ ret = gpio_request(metronome_gpios[i], metronome_gpio_names[i]);
+ if (ret)
+ goto err;
+ }
+
+ gpio_direction_output(GPIO_DISPLAY_OFF_N, 0);
+ gpio_direction_output(GPIO_DISPLAY_RST_L, 0);
+ gpio_direction_output(GPIO_DISPLAY_STBY, 0);
+ gpio_direction_input(GPIO_DISPLAY_RDY);
+ gpio_direction_input(GPIO_DISPLAY_ERR);
+
+ return 0;
+err:
+ for (--i; i >= 0; --i)
+ gpio_free(metronome_gpios[i]);
+
+ return ret;
+}
+
+static int n516_share_video_mem(struct fb_info *info)
+{
+ int ret;
+
+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
+ dev_dbg(&n516_device->dev, "%s, info->var.xres = %u, info->var.yres = %u\n", __func__, info->var.xres, info->var.yres);
+ /* rough check if this is our desired fb and not something else */
+ if ((info->var.xres != n516_fb_pdata.modes[0].xres)
+ || (info->var.yres != n516_fb_pdata.modes[0].yres))
+ return 0;
+
+ /* we've now been notified that we have our new fb */
+ n516_board_info.metromem = info->screen_base;
+ n516_board_info.host_fbinfo = info;
+
+ n516_enable_hostfb(false);
+ /* try to refcount host drv since we are the consumer after this */
+ if (!try_module_get(info->fbops->owner))
+ return -ENODEV;
+
+ /* this _add binds metronomefb to n516. metronomefb refcounts n516 */
+ ret = platform_device_add(n516_device);
+
+ if (ret) {
+ platform_device_put(n516_device);
+ return ret;
+ }
+
+ /* request our platform independent driver */
+ request_module("metronomefb");
+
+ return 0;
+}
+
+static int n516_unshare_video_mem(struct fb_info *info)
+{
+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
+
+ if (info != n516_board_info.host_fbinfo)
+ return 0;
+
+ module_put(n516_board_info.host_fbinfo->fbops->owner);
+ return 0;
+}
+
+static int n516_fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ struct fb_info *info = evdata->info;
+
+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
+
+ if (event == FB_EVENT_FB_REGISTERED)
+ return n516_share_video_mem(info);
+ else if (event == FB_EVENT_FB_UNREGISTERED)
+ return n516_unshare_video_mem(info);
+
+ return 0;
+}
+
+static struct notifier_block n516_fb_notif = {
+ .notifier_call = n516_fb_notifier_callback,
+};
+
+/* this gets called as part of our init. these steps must be done now so
+ * that we can use set_pxa_fb_info */
+static void __init n516_presetup_fb(void)
+{
+ int padding_size;
+ int totalsize;
+
+ /* the frame buffer is divided as follows:
+ command | CRC | padding
+ 16kb waveform data | CRC | padding
+ image data | CRC
+ */
+
+ n516_board_info.fw = 800;
+ n516_board_info.fh = 624;
+
+ /* waveform must be 16k + 2 for checksum */
+ n516_board_info.wfm_size = roundup(16*1024 + 2, n516_board_info.fw);
+
+ padding_size = PAGE_SIZE + (4 * n516_board_info.fw);
+
+ /* total is 1 cmd , 1 wfm, padding and image */
+ totalsize = n516_board_info.fw + n516_board_info.wfm_size;
+ totalsize += padding_size + (n516_board_info.fw*n516_board_info.fh);
+
+ /* save this off because we're manipulating fw after this and
+ * we'll need it when we're ready to setup the framebuffer */
+
+ /* the reason we do this adjustment is because we want to acquire
+ * more framebuffer memory without imposing custom awareness on the
+ * underlying driver */
+ n516_fb_pdata.modes[0].yres = DIV_ROUND_UP(totalsize, n516_board_info.fw);
+
+ jz4740_framebuffer_device.dev.platform_data = &n516_fb_pdata;
+ platform_device_register(&jz4740_framebuffer_device);
+}
+
+/* this gets called by metronomefb as part of its init, in our case, we
+ * have already completed initial framebuffer init in presetup_fb so we
+ * can just setup the fb access pointers */
+static int n516_setup_fb(struct metronomefb_par *par)
+{
+ /* metromem was set up by the notifier in share_video_mem so now
+ * we can use its value to calculate the other entries */
+ par->metromem_cmd = (struct metromem_cmd *) n516_board_info.metromem;
+ par->metromem_wfm = n516_board_info.metromem + n516_board_info.fw;
+ par->metromem_img = par->metromem_wfm + n516_board_info.wfm_size;
+ par->metromem_img_csum = (u16 *) (par->metromem_img + (n516_board_info.fw * n516_board_info.fh));
+ par->metromem_dma = n516_board_info.host_fbinfo->fix.smem_start;
+
+ return 0;
+}
+
+static int n516_get_panel_type(void)
+{
+ return 5;
+}
+
+static irqreturn_t n516_handle_irq(int irq, void *dev_id)
+{
+ struct metronomefb_par *par = dev_id;
+
+ dev_dbg(&par->pdev->dev, "Metronome IRQ! RDY=%d\n", gpio_get_value(GPIO_DISPLAY_RDY));
+ wake_up_all(&par->waitq);
+
+ return IRQ_HANDLED;
+}
+
+static void n516_power_ctl(struct metronomefb_par *par, int cmd)
+{
+ switch (cmd) {
+ case METRONOME_POWER_OFF:
+ gpio_set_value(GPIO_DISPLAY_OFF_N, 1);
+ n516_enable_hostfb(false);
+ break;
+ case METRONOME_POWER_ON:
+ gpio_set_value(GPIO_DISPLAY_OFF_N, 0);
+ n516_enable_hostfb(true);
+ break;
+ }
+}
+
+static int n516_get_rdy(struct metronomefb_par *par)
+{
+ return gpio_get_value(GPIO_DISPLAY_RDY);
+}
+
+static int n516_get_err(struct metronomefb_par *par)
+{
+ return gpio_get_value(GPIO_DISPLAY_ERR);
+}
+
+static int n516_setup_irq(struct fb_info *info)
+{
+ int ret;
+
+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
+
+ ret = request_irq(gpio_to_irq(GPIO_DISPLAY_RDY), n516_handle_irq,
+ IRQF_TRIGGER_RISING,
+ "n516", info->par);
+ if (ret)
+ dev_err(&n516_device->dev, "request_irq failed: %d\n", ret);
+
+ return ret;
+}
+
+static void n516_set_rst(struct metronomefb_par *par, int state)
+{
+ dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY));
+ if (state)
+ gpio_set_value(GPIO_DISPLAY_RST_L, 1);
+ else
+ gpio_set_value(GPIO_DISPLAY_RST_L, 0);
+}
+
+static void n516_set_stdby(struct metronomefb_par *par, int state)
+{
+ dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY));
+ if (state)
+ gpio_set_value(GPIO_DISPLAY_STBY, 1);
+ else
+ gpio_set_value(GPIO_DISPLAY_STBY, 0);
+}
+
+static int n516_wait_event(struct metronomefb_par *par)
+{
+ unsigned long timeout = jiffies + HZ / 20;
+
+ dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n",
+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
+ while (n516_get_rdy(par) && time_before(jiffies, timeout))
+ schedule();
+
+ dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n",
+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
+ return wait_event_timeout(par->waitq,
+ n516_get_rdy(par), HZ * 2) ? 0 : -EIO;
+}
+
+static int n516_wait_event_intr(struct metronomefb_par *par)
+{
+ unsigned long timeout = jiffies + HZ/20;
+
+ dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n",
+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
+ while (n516_get_rdy(par) && time_before(jiffies, timeout))
+ schedule();
+
+ dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n",
+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
+ return wait_event_interruptible_timeout(par->waitq,
+ n516_get_rdy(par), HZ * 2) ? 0 : -EIO;
+}
+
+static void n516_cleanup(struct metronomefb_par *par)
+{
+ int i;
+
+ free_irq(gpio_to_irq(GPIO_DISPLAY_RDY), par);
+ for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i)
+ gpio_free(metronome_gpios[i]);
+}
+
+static struct metronome_board n516_board __initdata = {
+ .owner = THIS_MODULE,
+ .power_ctl = n516_power_ctl,
+ .setup_irq = n516_setup_irq,
+ .setup_io = n516_init_metronome_gpios,
+ .setup_fb = n516_setup_fb,
+ .set_rst = n516_set_rst,
+ .get_err = n516_get_err,
+ .get_rdy = n516_get_rdy,
+ .set_stdby = n516_set_stdby,
+ .met_wait_event = n516_wait_event,
+ .met_wait_event_intr = n516_wait_event_intr,
+ .get_panel_type = n516_get_panel_type,
+ .cleanup = n516_cleanup,
+};
+
+static int __init n516_init(void)
+{
+ int ret;
+
+ /* Keep the metronome off, until its driver is loaded */
+ ret = gpio_request(GPIO_DISPLAY_OFF_N, "Display off");
+ if (ret)
+ return ret;
+
+ gpio_direction_output(GPIO_DISPLAY_OFF_N, 1);
+
+ /* before anything else, we request notification for any fb
+ * creation events */
+ fb_register_client(&n516_fb_notif);
+
+ n516_device = platform_device_alloc("metronomefb", -1);
+ if (!n516_device)
+ return -ENOMEM;
+
+ /* the n516_board that will be seen by metronomefb is a copy */
+ platform_device_add_data(n516_device, &n516_board,
+ sizeof(n516_board));
+
+ n516_presetup_fb();
+
+ return 0;
+}
+module_init(n516_init);
+
+MODULE_DESCRIPTION("board driver for n516 display");
+MODULE_AUTHOR("Yauhen Kharuzhy");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/jz4740/board-n516.c b/arch/mips/jz4740/board-n516.c
new file mode 100644
index 0000000..678885c
--- /dev/null
+++ b/arch/mips/jz4740/board-n516.c
@@ -0,0 +1,182 @@
+/*
+ * linux/arch/mips/jz4740/board-516.c
+ *
+ * JZ4740 n516 board setup routines.
+ *
+ * Copyright (c) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/leds.h>
+
+#include <linux/power_supply.h>
+#include <linux/power/gpio-charger.h>
+
+#include <linux/i2c.h>
+
+#include <asm/mach-jz4740/jz4740_mmc.h>
+#include <asm/mach-jz4740/jz4740_nand.h>
+
+#include <asm/mach-jz4740/board-n516.h>
+#include <asm/mach-jz4740/platform.h>
+
+#include "clock.h"
+
+static long n516_panic_blink(int state)
+{
+ gpio_set_value(GPIO_LED_ENABLE, state ? 1 : 0);
+ return 0;
+}
+
+static void __init board_gpio_setup(void)
+{
+/* jz_gpio_enable_pullup(JZ_GPIO_PORTD(23));
+ jz_gpio_enable_pullup(JZ_GPIO_PORTD(24));*/
+}
+
+static const struct i2c_board_info n516_i2c_board_info[] = {
+ {
+ .type = "LPC524",
+ .addr = 0x54,
+ },
+ {
+ .type = "lm75a",
+ .addr = 0x48,
+ }
+};
+
+static struct jz4740_mmc_platform_data n516_mmc_pdata = {
+ .gpio_card_detect = GPIO_SD_CD_N,
+ .card_detect_active_low = 1,
+ .gpio_read_only = -1,
+ .gpio_power = GPIO_SD_VCC_EN_N,
+ .power_active_low = 1,
+};
+
+static struct gpio_led n516_leds[] = {
+ {
+ .name = "n516:blue:power",
+ .gpio = GPIO_LED_ENABLE,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ .default_trigger = "nand-disk",
+ }
+};
+
+static struct gpio_led_platform_data n516_leds_pdata = {
+ .leds = n516_leds,
+ .num_leds = ARRAY_SIZE(n516_leds),
+};
+
+static struct platform_device n516_leds_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &n516_leds_pdata,
+ },
+};
+
+static struct mtd_partition n516_partitions[] = {
+ { .name = "NAND BOOT partition",
+ .offset = 0 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND KERNEL partition",
+ .offset = 4 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND ROOTFS partition",
+ .offset = 8 * 0x100000,
+ .size = 504 * 0x100000,
+ },
+};
+
+static struct nand_ecclayout n516_ecclayout = {
+ .eccbytes = 36,
+ .eccpos = {
+ 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ },
+ .oobfree = {
+ {
+ .offset = 2,
+ .length = 4
+ },
+ {
+ .offset = 42,
+ .length = 22,
+ }
+ }
+};
+
+static struct jz_nand_platform_data n516_nand_pdata = {
+ .ecc_layout = &n516_ecclayout,
+ .partitions = n516_partitions,
+ .num_partitions = ARRAY_SIZE(n516_partitions),
+ .busy_gpio = 94,
+};
+
+static char *n516_batteries[] = {
+ "n516_battery",
+};
+
+static struct gpio_charger_platform_data n516_charger_pdata = {
+ .name = "usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .gpio = GPIO_USB_DETECT,
+ .gpio_active_low = 1,
+ .batteries = n516_batteries,
+ .num_batteries = ARRAY_SIZE(n516_batteries),
+};
+
+static struct platform_device n516_charger_device = {
+ .name = "gpio-charger",
+ .dev = {
+ .platform_data = &n516_charger_pdata,
+ },
+};
+
+static struct platform_device *n516_devices[] __initdata = {
+ &jz4740_nand_device,
+ &n516_leds_device,
+ &jz4740_mmc_device,
+ &jz4740_i2s_device,
+ &jz4740_codec_device,
+ &jz4740_rtc_device,
+ &jz4740_udc_device,
+ &jz4740_i2c_device,
+ &n516_charger_device,
+};
+
+struct jz4740_clock_board_data jz4740_clock_bdata = {
+ .ext_rate = 12000000,
+ .rtc_rate = 32768,
+};
+
+static int n516_setup_platform(void)
+{
+ jz4740_serial_device_register();
+ board_gpio_setup();
+
+ panic_blink = n516_panic_blink;
+ i2c_register_board_info(0, n516_i2c_board_info, ARRAY_SIZE(n516_i2c_board_info));
+ jz4740_mmc_device.dev.platform_data = &n516_mmc_pdata;
+ jz4740_nand_device.dev.platform_data = &n516_nand_pdata;
+
+ return platform_add_devices(n516_devices, ARRAY_SIZE(n516_devices));
+}
+arch_initcall(n516_setup_platform);
--
1.7.4.1

View File

@ -1,368 +0,0 @@
From dcc0d9f15146c100a843dfa62ba259e208330f07 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 24 Apr 2010 17:25:23 +0200
Subject: [PATCH 03/32] Add n526 board support
---
arch/mips/jz4740/Kconfig | 4 +
arch/mips/jz4740/Makefile | 1 +
arch/mips/jz4740/board-n526.c | 320 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 325 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/jz4740/board-n526.c
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 85bfbf3..2f366d7 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -10,6 +10,10 @@ config JZ4740_N516
bool "Hanvon n516 eBook reader"
select SOC_JZ4740
+config JZ4740_N526
+ bool "Hanvon n526 eBook reader"
+ select SOC_JZ4740
+
endchoice
config HAVE_PWM
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 727270a..e8f2904 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
+obj-$(CONFIG_JZ4740_N526) += board-n526.o
# PM support
diff --git a/arch/mips/jz4740/board-n526.c b/arch/mips/jz4740/board-n526.c
new file mode 100644
index 0000000..494c4cb
--- /dev/null
+++ b/arch/mips/jz4740/board-n526.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ * N526 eBook reader support
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <video/broadsheetfb.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/leds.h>
+
+#include <linux/i2c.h>
+
+#include "clock.h"
+
+#include <asm/mach-jz4740/jz4740_mmc.h>
+#include <asm/mach-jz4740/jz4740_nand.h>
+#include <asm/mach-jz4740/jz4740_fb.h>
+
+#include <asm/mach-jz4740/platform.h>
+
+/* NAND */
+static struct nand_ecclayout n526_ecclayout = {
+ .eccbytes = 36,
+ .eccpos = {
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41},
+ .oobfree = {
+ {
+ .offset = 2,
+ .length = 4,
+ },
+ {
+ .offset = 42,
+ .length = 22,
+ },
+ }
+};
+
+static struct mtd_partition n526_partitions[] = {
+ { .name = "NAND BOOT partition",
+ .offset = 0 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND KERNEL partition",
+ .offset = 4 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND ROOTFS partition",
+ .offset = 16 * 0x100000,
+ .size = 498 * 0x100000,
+ },
+};
+
+static struct jz_nand_platform_data n526_nand_pdata = {
+ .ecc_layout = &n526_ecclayout,
+ .partitions = n526_partitions,
+ .num_partitions = ARRAY_SIZE(n526_partitions),
+ .busy_gpio = JZ_GPIO_PORTC(30),
+};
+
+static struct jz4740_mmc_platform_data n526_mmc_pdata = {
+ .gpio_card_detect = JZ_GPIO_PORTD(7),
+ .card_detect_active_low = 1,
+ .gpio_read_only = -1,
+ .gpio_power = JZ_GPIO_PORTD(17),
+ .power_active_low = 1,
+};
+
+static struct gpio_led n526_leds[] = {
+ {
+ .name = "n526:blue:power",
+ .gpio = JZ_GPIO_PORTD(28),
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }
+};
+
+static struct gpio_led_platform_data n526_leds_pdata = {
+ .leds = n526_leds,
+ .num_leds = ARRAY_SIZE(n526_leds),
+};
+
+static struct platform_device n526_leds_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &n526_leds_pdata,
+ },
+};
+
+static void __init board_gpio_setup(void)
+{
+ /* We only need to enable/disable pullup here for pins used in generic
+ * drivers. Everything else is done by the drivers themselfs. */
+ jz_gpio_disable_pullup(JZ_GPIO_PORTD(17));
+ jz_gpio_enable_pullup(JZ_GPIO_PORTD(7));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(19));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(20));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(21));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(23));
+}
+
+
+static const int n526_eink_ctrl_gpios[] = {
+ 0,
+ JZ_GPIO_PORTC(23),
+ JZ_GPIO_PORTC(19),
+ JZ_GPIO_PORTC(20),
+};
+
+static void n526_eink_set_ctl(struct broadsheetfb_par * par, unsigned char ctrl, u8
+value)
+{
+ gpio_set_value(n526_eink_ctrl_gpios[ctrl], value);
+}
+
+
+static int n526_eink_wait(struct broadsheetfb_par *par)
+{
+ wait_event(par->waitq, gpio_get_value(JZ_GPIO_PORTB(17)));
+
+ return 0;
+}
+
+static u16 n526_eink_get_hdb(struct broadsheetfb_par *par)
+{
+ u16 value = 0;
+ jz_gpio_port_direction_input(JZ_GPIO_PORTC(0), 0xffff);
+ gpio_set_value(JZ_GPIO_PORTC(21), 0);
+ mdelay(100);
+
+ value = jz_gpio_port_get_value(JZ_GPIO_PORTC(0), 0xffff);
+
+ gpio_set_value(JZ_GPIO_PORTC(21), 1);
+ jz_gpio_port_direction_output(JZ_GPIO_PORTC(0), 0xffff);
+ return value;
+}
+
+static void n526_eink_set_hdb(struct broadsheetfb_par *par, u16 value)
+{
+ jz_gpio_port_set_value(JZ_GPIO_PORTC(0), value, 0xffff);
+}
+
+static int n526_eink_init(struct broadsheetfb_par *par)
+{
+ int i;
+
+ gpio_request(JZ_GPIO_PORTD(1), "display reset");
+ gpio_direction_output(JZ_GPIO_PORTD(1), 1);
+ mdelay(10);
+ gpio_set_value(JZ_GPIO_PORTD(1), 0);
+
+ gpio_request(JZ_GPIO_PORTB(18), "eink enable");
+ gpio_direction_output(JZ_GPIO_PORTB(18), 0);
+
+ gpio_request(JZ_GPIO_PORTB(29), "foobar");
+ gpio_direction_output(JZ_GPIO_PORTB(29), 1);
+
+ for(i = 1; i < ARRAY_SIZE(n526_eink_ctrl_gpios); ++i) {
+ gpio_request(n526_eink_ctrl_gpios[i], "eink display ctrl");
+ gpio_direction_output(n526_eink_ctrl_gpios[i], 0);
+ }
+
+ gpio_request(JZ_GPIO_PORTC(22), "foobar");
+ gpio_direction_input(JZ_GPIO_PORTC(22));
+ gpio_request(JZ_GPIO_PORTC(21), "eink nRD");
+ gpio_direction_output(JZ_GPIO_PORTC(21), 1);
+
+ for(i = 0; i < 16; ++i) {
+ gpio_request(JZ_GPIO_PORTC(i), "eink display data");
+ }
+ jz_gpio_port_direction_output(JZ_GPIO_PORTC(0), 0xffff);
+
+ gpio_set_value(JZ_GPIO_PORTB(18), 1);
+
+ return 0;
+}
+
+static irqreturn_t n526_eink_busy_irq(int irq, void *devid)
+{
+ struct broadsheetfb_par *par = devid;
+ wake_up(&par->waitq);
+
+ return IRQ_HANDLED;
+}
+
+static int n526_eink_setup_irq(struct fb_info *info)
+{
+ int ret;
+ struct broadsheetfb_par *par = info->par;
+
+ gpio_request(JZ_GPIO_PORTB(17), "eink busy");
+ gpio_direction_input(JZ_GPIO_PORTB(17));
+
+ ret = request_irq(gpio_to_irq(JZ_GPIO_PORTB(17)), n526_eink_busy_irq,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "eink busyline", par);
+ if (ret)
+ printk("n526 display: Failed to request busyline irq: %d\n", ret);
+ return 0;
+}
+
+static void n526_eink_cleanup(struct broadsheetfb_par *par)
+{
+}
+
+static struct broadsheet_board broadsheet_pdata = {
+ .owner = THIS_MODULE,
+ .init = n526_eink_init,
+ .wait_for_rdy = n526_eink_wait,
+ .set_ctl = n526_eink_set_ctl,
+ .set_hdb = n526_eink_set_hdb,
+ .get_hdb = n526_eink_get_hdb,
+ .cleanup = n526_eink_cleanup,
+ .setup_irq = n526_eink_setup_irq,
+};
+
+static struct platform_device n526_broadsheet_device = {
+ .name = "broadsheetfb",
+ .id = -1,
+ .dev = {
+ .platform_data = &broadsheet_pdata,
+ },
+};
+
+/* Buttons */
+static struct gpio_keys_button n526_gpio_keys_buttons[] = {
+ [0] = {
+ .code = KEY_ENTER,
+ .gpio = 0,
+ .active_low = 1,
+ .desc = "Power",
+ },
+};
+
+static struct gpio_keys_platform_data n526_gpio_keys_data = {
+ .nbuttons = ARRAY_SIZE(n526_gpio_keys_buttons),
+ .buttons = n526_gpio_keys_buttons,
+};
+
+static struct platform_device n526_gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &n526_gpio_keys_data,
+ }
+};
+
+static struct i2c_board_info n526_i2c_board_info = {
+ .type = "n526-lpc",
+ .addr = 0x54,
+};
+
+static struct platform_device *n526_platform_devices[] __initdata = {
+ &jz4740_usb_ohci_device,
+ &jz4740_udc_device,
+ &jz4740_mmc_device,
+ &jz4740_nand_device,
+ &jz4740_i2s_device,
+ &jz4740_codec_device,
+ &jz4740_pcm_device,
+ &jz4740_rtc_device,
+ &jz4740_i2c_device,
+ &n526_leds_device,
+ &n526_broadsheet_device,
+ &n526_gpio_keys_device,
+};
+
+static int __init n526_init_platform_devices(void)
+{
+ jz4740_nand_device.dev.platform_data = &n526_nand_pdata;
+ jz4740_mmc_device.dev.platform_data = &n526_mmc_pdata;
+
+ jz4740_serial_device_register();
+
+ n526_i2c_board_info.irq = gpio_to_irq(JZ_GPIO_PORTD(14)),
+ i2c_register_board_info(0, &n526_i2c_board_info, 1);
+
+ return platform_add_devices(n526_platform_devices,
+ ARRAY_SIZE(n526_platform_devices));
+
+}
+
+struct jz4740_clock_board_data jz4740_clock_bdata = {
+ .ext_rate = 12000000,
+ .rtc_rate = 32768,
+};
+
+static int __init n526_board_setup(void)
+{
+ board_gpio_setup();
+
+ if (n526_init_platform_devices())
+ panic("Failed to initalize platform devices\n");
+
+ return 0;
+}
+arch_initcall(n526_board_setup);
--
1.7.4.1

View File

@ -1,206 +0,0 @@
From 322d8e1ccf544f576d60622dc304f136cef64a3b Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 5 Sep 2010 20:34:08 +0200
Subject: [PATCH 04/32] MIPS: JZ4740: Add id800wt board
---
arch/mips/jz4740/Kconfig | 4 +
arch/mips/jz4740/Makefile | 1 +
arch/mips/jz4740/board-id800wt.c | 158 ++++++++++++++++++++++++++++++++++++++
3 files changed, 163 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/jz4740/board-id800wt.c
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 2f366d7..680a2bd 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -14,6 +14,10 @@ config JZ4740_N526
bool "Hanvon n526 eBook reader"
select SOC_JZ4740
+config JZ4740_ID800WT
+ bool "Sungale id800wt picture frame"
+ select SOC_JZ4740
+
endchoice
config HAVE_PWM
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index e8f2904..72eb2ad 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
obj-$(CONFIG_JZ4740_N526) += board-n526.o
+obj-$(CONFIG_JZ4740_ID800WT) += board-id800wt.o
# PM support
diff --git a/arch/mips/jz4740/board-id800wt.c b/arch/mips/jz4740/board-id800wt.c
new file mode 100644
index 0000000..93fc996
--- /dev/null
+++ b/arch/mips/jz4740/board-id800wt.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-jz4740/platform.h>
+
+#include <linux/input.h>
+#include <linux/power_supply.h>
+#include <linux/pwm_backlight.h>
+
+#include "clock.h"
+
+#include <asm/mach-jz4740/jz4740_fb.h>
+#include <asm/mach-jz4740/jz4740_nand.h>
+
+/* NAND */
+static struct nand_ecclayout id800wt_ecclayout = {
+ .oobfree = {
+ {
+ .offset = 2,
+ .length = 4,
+ },
+ {
+ .offset = 42,
+ .length = 22,
+ },
+ }
+};
+
+static struct mtd_partition id800wt_partitions[] = {
+ { .name = "NAND BOOT partition",
+ .offset = 0 * 0x100000,
+ .size = 2 * 0x100000,
+ },
+ { .name = "NAND KERNEL partition",
+ .offset = 2 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND ROOTFS partition",
+ .offset = 6 * 0x100000,
+ .size = 498 * 0x100000,
+ },
+};
+
+static struct jz_nand_platform_data id800wt_nand_pdata = {
+ .ecc_layout = &id800wt_ecclayout,
+ .partitions = id800wt_partitions,
+ .num_partitions = ARRAY_SIZE(id800wt_partitions),
+ .busy_gpio = JZ_GPIO_PORTC(30),
+};
+
+/* Display */
+static struct fb_videomode id800wt_video_modes[] = {
+ {
+ .name = "800x600",
+ .xres = 800,
+ .yres = 600,
+ .refresh = 40,
+ .left_margin = 0,
+ .right_margin = 255,
+ .upper_margin = 0,
+ .lower_margin = 35,
+ .hsync_len = 1,
+ .vsync_len = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+};
+
+static struct jz4740_fb_platform_data id800wt_fb_pdata = {
+ .width = 60,
+ .height = 45,
+ .num_modes = ARRAY_SIZE(id800wt_video_modes),
+ .modes = id800wt_video_modes,
+ .bpp = 16,
+ .lcd_type = JZ_LCD_TYPE_SPECIAL_TFT_1,
+ .pixclk_falling_edge = 1,
+ .special_tft_config = {
+ .spl = JZ4740_FB_SPECIAL_TFT_CONFIG(1051, 1053),
+ .cls = JZ4740_FB_SPECIAL_TFT_CONFIG(631, 744),
+ .ps = JZ4740_FB_SPECIAL_TFT_CONFIG(0, 45),
+ .rev = JZ4740_FB_SPECIAL_TFT_CONFIG(0, 0),
+ },
+};
+
+/* Backlight */
+static int id800wt_backlight_invert(struct device *dev, int brightness)
+{
+ return 255 - brightness;
+}
+
+static struct platform_pwm_backlight_data id800wt_backlight_data = {
+ .pwm_id = 7,
+ .max_brightness = 255,
+ .dft_brightness = 255,
+ .pwm_period_ns = 8000000,
+ .notify = id800wt_backlight_invert,
+};
+
+static struct platform_device id800wt_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .platform_data = &id800wt_backlight_data,
+ .parent = &jz4740_framebuffer_device.dev,
+ },
+};
+
+static struct platform_device *jz_platform_devices[] __initdata = {
+ &jz4740_usb_ohci_device,
+ &jz4740_udc_device,
+ &jz4740_nand_device,
+ &jz4740_framebuffer_device,
+ &jz4740_i2s_device,
+ &jz4740_codec_device,
+ &jz4740_pcm_device,
+ &jz4740_rtc_device,
+ &jz4740_adc_device,
+ &id800wt_backlight_device,
+};
+
+static int __init id800wt_init_platform_devices(void)
+{
+ jz4740_framebuffer_device.dev.platform_data = &id800wt_fb_pdata;
+ jz4740_nand_device.dev.platform_data = &id800wt_nand_pdata;
+
+ jz4740_serial_device_register();
+
+ jz_gpio_enable_pullup(JZ_GPIO_LCD_PS);
+ jz_gpio_enable_pullup(JZ_GPIO_LCD_REV);
+
+ return platform_add_devices(jz_platform_devices,
+ ARRAY_SIZE(jz_platform_devices));
+}
+
+struct jz4740_clock_board_data jz4740_clock_bdata = {
+ .ext_rate = 12000000,
+ .rtc_rate = 32768,
+};
+
+static int __init id800wt_board_setup(void)
+{
+ printk("Sungale pictureframe id800wt setup\n");
+
+ if (id800wt_init_platform_devices())
+ panic("Failed to initalize platform devices\n");
+
+ return 0;
+}
+arch_initcall(id800wt_board_setup);
--
1.7.4.1

View File

@ -1,352 +0,0 @@
From 523f9ca02b5c2c8b79f1d01fff03b1191a6aed6c Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 1 Aug 2010 21:34:54 +0200
Subject: [PATCH 05/32] Add N516 sound SoC board driver
---
sound/soc/jz4740/Kconfig | 8 ++
sound/soc/jz4740/Makefile | 2 +
sound/soc/jz4740/n516.c | 303 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 313 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/jz4740/n516.c
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
index 5351cba..08530ca 100644
--- a/sound/soc/jz4740/Kconfig
+++ b/sound/soc/jz4740/Kconfig
@@ -21,3 +21,11 @@ config SND_JZ4740_SOC_QI_LB60
help
Say Y if you want to add support for ASoC audio on the Qi LB60 board
a.k.a Qi Ben NanoNote.
+
+config SND_JZ4740_SOC_N516
+ tristate "SoC Audio support for Hanvon N516 eBook reader"
+ depends on SND_JZ4740_SOC && JZ4740_N516
+ select SND_JZ4740_SOC_I2S
+ select SND_SOC_JZCODEC
+ help
+ Say Y if you want to enable support for SoC audio on the Hanvon N516.
diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
index be873c1..b64d912 100644
--- a/sound/soc/jz4740/Makefile
+++ b/sound/soc/jz4740/Makefile
@@ -9,5 +9,7 @@ obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
# Jz4740 Machine Support
snd-soc-qi-lb60-objs := qi_lb60.o
+snd-soc-n516-objs := n516.o
obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o
+obj-$(CONFIG_SND_JZ4740_SOC_N516) += snd-soc-n516.o
diff --git a/sound/soc/jz4740/n516.c b/sound/soc/jz4740/n516.c
new file mode 100644
index 0000000..9cb51c2
--- /dev/null
+++ b/sound/soc/jz4740/n516.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
+ * OpenInkpot project
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+
+#include "../codecs/jzcodec.h"
+#include "jz4740-pcm.h"
+#include "jz4740-i2s.h"
+
+#include <asm/mach-jz4740/board-n516.h>
+
+enum {
+ N516_SPEAKER_AUTO = 0,
+ N516_SPEAKER_OFF = 1,
+ N516_SPEAKER_ON = 2,
+};
+
+static int n516_speaker_mode;
+static struct snd_soc_codec *n516_codec;
+static struct work_struct n516_headphone_work;
+
+static void n516_ext_control(void)
+{
+ if (!n516_codec)
+ return;
+
+ switch (n516_speaker_mode) {
+ case N516_SPEAKER_ON:
+ snd_soc_dapm_enable_pin(n516_codec, "Speaker");
+ break;
+ case N516_SPEAKER_OFF:
+ snd_soc_dapm_disable_pin(n516_codec, "Speaker");
+ break;
+ case N516_SPEAKER_AUTO:
+ if (snd_soc_dapm_get_pin_status(n516_codec, "Headphone"))
+ snd_soc_dapm_disable_pin(n516_codec, "Speaker");
+ else
+ snd_soc_dapm_enable_pin(n516_codec, "Speaker");
+ break;
+ default:
+ break;
+ }
+
+ /* signal a DAPM event */
+ snd_soc_dapm_sync(n516_codec);
+}
+
+static int n516_speaker_event(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *ctrl, int event)
+{
+ int on = !SND_SOC_DAPM_EVENT_OFF(event);
+
+ gpio_set_value(GPIO_SPEAKER_ENABLE, on);
+
+ return 0;
+}
+
+static void n516_headphone_event_work(struct work_struct *work)
+{
+ n516_ext_control();
+}
+
+static int n516_headphone_event(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *ctrl, int event)
+{
+ /* We can't call soc_dapm_sync from a event handler */
+ if (event & (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD))
+ schedule_work(&n516_headphone_work);
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget n516_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker", n516_speaker_event),
+ SND_SOC_DAPM_HP("Headphone", n516_headphone_event),
+ SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route n516_routes[] = {
+ {"Mic", NULL, "MIC"},
+ {"Speaker", NULL, "LOUT"},
+ {"Speaker", NULL, "ROUT"},
+ {"Headphone", NULL, "LOUT"},
+ {"Headphone", NULL, "ROUT"},
+};
+
+static const char *n516_speaker_modes[] = {"Auto", "Off", "On"};
+static const struct soc_enum n516_speaker_mode_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(n516_speaker_modes), n516_speaker_modes);
+
+static int n516_get_speaker_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = n516_speaker_mode;
+ return 0;
+}
+
+static int n516_set_speaker_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (n516_speaker_mode == ucontrol->value.integer.value[0])
+ return 0;
+
+ n516_speaker_mode = ucontrol->value.integer.value[0];
+ n516_ext_control();
+ return 1;
+}
+
+static const struct snd_kcontrol_new n516_controls[] = {
+ SOC_ENUM_EXT("Speaker Function", n516_speaker_mode_enum,
+ n516_get_speaker_mode, n516_set_speaker_mode),
+};
+
+#define N516_DAIFMT (SND_SOC_DAIFMT_I2S | \
+ SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
+static int n516_codec_init(struct snd_soc_codec *codec)
+{
+ int ret;
+ struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
+ struct snd_soc_dai *codec_dai = codec->socdev->card->dai_link->codec_dai;
+
+ n516_codec = codec;
+
+ snd_soc_dapm_nc_pin(codec, "LIN");
+ snd_soc_dapm_nc_pin(codec, "RIN");
+
+ ret = snd_soc_dai_set_fmt(codec_dai, N516_DAIFMT);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set codec dai format: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, N516_DAIFMT);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, JZCODEC_SYSCLK, 111,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set codec dai sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_controls(codec, n516_controls,
+ ARRAY_SIZE(n516_controls));
+ if (ret) {
+ dev_err(codec->dev, "Failed to add controls: %d\n", ret);
+ return ret;
+ }
+
+
+ ret = snd_soc_dapm_new_controls(codec, n516_widgets,
+ ARRAY_SIZE(n516_widgets));
+ if (ret) {
+ dev_err(codec->dev, "Failed to add dapm controls: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(codec, n516_routes, ARRAY_SIZE(n516_routes));
+ if (ret) {
+ dev_err(codec->dev, "Failed to add dapm routes: %d\n", ret);
+ return ret;
+ }
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link n516_dai = {
+ .name = "jz-codec",
+ .stream_name = "JZCODEC",
+ .cpu_dai = &jz4740_i2s_dai,
+ .codec_dai = &jz_codec_dai,
+ .init = n516_codec_init,
+};
+
+static struct snd_soc_card n516_card = {
+ .name = "N516",
+ .dai_link = &n516_dai,
+ .num_links = 1,
+ .platform = &jz4740_soc_platform,
+};
+
+static struct snd_soc_device n516_snd_devdata = {
+ .card = &n516_card,
+ .codec_dev = &soc_codec_dev_jzcodec,
+};
+
+static struct platform_device *n516_snd_device;
+
+static struct snd_soc_jack n516_hp_jack;
+
+static struct snd_soc_jack_pin n516_hp_pin = {
+ .pin = "Headphone",
+ .mask = SND_JACK_HEADPHONE,
+};
+
+static struct snd_soc_jack_gpio n516_hp_gpio = {
+ .gpio = GPIO_HPHONE_DETECT,
+ .name = "Headphone detect",
+ .report = SND_JACK_HEADPHONE,
+ .debounce_time = 100,
+};
+
+static int __init n516_add_headphone_jack(void)
+{
+ int ret;
+
+ ret = snd_soc_jack_new(&n516_card, "Headphone jack",
+ SND_JACK_HEADPHONE, &n516_hp_jack);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&n516_hp_jack, 1, &n516_hp_pin);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_gpios(&n516_hp_jack, 1, &n516_hp_gpio);
+
+ return ret;
+}
+
+static int __init n516_init(void)
+{
+ int ret;
+
+ n516_snd_device = platform_device_alloc("soc-audio", -1);
+
+ if (!n516_snd_device)
+ return -ENOMEM;
+
+ ret = gpio_request(GPIO_SPEAKER_ENABLE, "Speaker enable");
+ if (ret) {
+ pr_err("n516 snd: Failed to request SPEAKER_ENABLE GPIO(%d): %d\n",
+ GPIO_SPEAKER_ENABLE, ret);
+ goto err_device_put;
+ }
+
+ gpio_direction_output(GPIO_SPEAKER_ENABLE, 0);
+ INIT_WORK(&n516_headphone_work, n516_headphone_event_work);
+
+ platform_set_drvdata(n516_snd_device, &n516_snd_devdata);
+ n516_snd_devdata.dev = &n516_snd_device->dev;
+ ret = platform_device_add(n516_snd_device);
+ if (ret) {
+ pr_err("n516 snd: Failed to add snd soc device: %d\n", ret);
+ goto err_unset_pdata;
+ }
+
+ ret = n516_add_headphone_jack();
+ /* We can live without it, so just print a warning */
+ if (ret)
+ pr_warning("n516 snd: Failed to initalise headphone jack: %d\n", ret);
+
+ return 0;
+
+err_unset_pdata:
+ platform_set_drvdata(n516_snd_device, NULL);
+/*err_gpio_free_speaker:*/
+ gpio_free(GPIO_SPEAKER_ENABLE);
+err_device_put:
+ platform_device_put(n516_snd_device);
+
+ return ret;
+}
+module_init(n516_init);
+
+static void __exit n516_exit(void)
+{
+ snd_soc_jack_free_gpios(&n516_hp_jack, 1, &n516_hp_gpio);
+ gpio_free(GPIO_SPEAKER_ENABLE);
+ platform_device_unregister(n516_snd_device);
+}
+module_exit(n516_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC N516 Audio support");
+MODULE_LICENSE("GPL v2");
--
1.7.4.1

View File

@ -1,520 +0,0 @@
From b02e39f1ba2310fedf212d2a6e5d99c4a14fc297 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 12 May 2010 14:22:36 +0200
Subject: [PATCH 06/32] Add n516 lpc driver
---
drivers/misc/Kconfig | 8 +
drivers/misc/Makefile | 1 +
drivers/misc/n516-lpc.c | 471 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 480 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/n516-lpc.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4e349cd..aabc92e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -490,6 +490,14 @@ config PCH_PHUB
To compile this driver as a module, choose M here: the module will
be called pch_phub.
+config N516_LPC
+ tristate "N516 keys & power controller"
+ depends on I2C
+ depends on INPUT
+ depends on POWER_SUPPLY
+ help
+ N516 keyboard & power controller driver
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5f03172..905b807 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -46,3 +46,4 @@ obj-y += ti-st/
obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
obj-y += lis3lv02d/
obj-y += carma/
+obj-$(CONFIG_N516_LPC) += n516-lpc.o
diff --git a/drivers/misc/n516-lpc.c b/drivers/misc/n516-lpc.c
new file mode 100644
index 0000000..2b7a5b3
--- /dev/null
+++ b/drivers/misc/n516-lpc.c
@@ -0,0 +1,471 @@
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/power_supply.h>
+#include <linux/suspend.h>
+
+#include <linux/i2c.h>
+
+#include <asm/mach-jz4740/irq.h>
+#include <asm/mach-jz4740/gpio.h>
+#include <asm/mach-jz4740/board-n516.h>
+
+static int batt_level=0;
+module_param(batt_level, int, 0);
+
+struct n516_lpc_chip {
+ struct i2c_client *i2c_client;
+ struct input_dev *input;
+ unsigned int battery_level;
+ unsigned int suspending:1, can_sleep:1;
+};
+
+static struct n516_lpc_chip *the_lpc;
+
+struct i2c_device_id n516_lpc_i2c_ids[] = {
+ {"LPC524", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, n516_lpc_i2c_ids);
+
+static const unsigned short normal_i2c[] = I2C_ADDRS(0x54);
+
+static const unsigned int n516_lpc_keymap[] = {
+ [0x01] = KEY_4,
+ [0x02] = KEY_3,
+ [0x03] = KEY_2,
+ [0x04] = KEY_1,
+ [0x05] = KEY_0,
+ [0x07] = KEY_9,
+ [0x08] = KEY_8,
+ [0x09] = KEY_7,
+ [0x0a] = KEY_6,
+ [0x0b] = KEY_5,
+ [0x0d] = KEY_PLAYPAUSE,
+ [0x0e] = KEY_MENU,
+ [0x0f] = KEY_SEARCH,
+ [0x10] = KEY_DIRECTION,
+ [0x11] = KEY_SPACE,
+ [0x13] = KEY_ENTER,
+ [0x14] = KEY_UP,
+ [0x15] = KEY_DOWN,
+ [0x16] = KEY_RIGHT,
+ [0x17] = KEY_LEFT,
+ [0x19] = KEY_PAGEDOWN,
+ [0x1a] = KEY_PAGEUP,
+ [0x1c] = KEY_POWER,
+ [0x1d] = KEY_ESC,
+ [0x1e] = KEY_SLEEP,
+ [0x1f] = KEY_WAKEUP,
+};
+
+static const unsigned int batt_charge[] = {0, 7, 20, 45, 65, 80, 100};
+#define MAX_BAT_LEVEL 6
+
+static inline int n516_bat_charging(void)
+{
+ return !gpio_get_value(GPIO_CHARG_STAT_N);
+}
+
+static int n516_bat_get_status(struct power_supply *b)
+{
+ if (power_supply_am_i_supplied(b)) {
+ if (n516_bat_charging())
+ return POWER_SUPPLY_STATUS_CHARGING;
+ else
+ return POWER_SUPPLY_STATUS_FULL;
+ } else {
+ return POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+}
+
+static int n516_bat_get_charge(struct power_supply *b)
+{
+ return batt_charge[the_lpc->battery_level];
+}
+
+static int n516_bat_get_property(struct power_supply *b,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = n516_bat_get_status(b);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = 100;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = n516_bat_get_charge(b);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void n516_bat_power_changed(struct power_supply *p)
+{
+ if (power_supply_am_i_supplied(p) && !n516_bat_charging())
+ the_lpc->battery_level = MAX_BAT_LEVEL;
+
+ power_supply_changed(p);
+}
+
+static enum power_supply_property n516_bat_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+};
+
+static struct power_supply n516_battery = {
+ .name = "n516-battery",
+ .get_property = n516_bat_get_property,
+ .properties = n516_bat_properties,
+ .num_properties = ARRAY_SIZE(n516_bat_properties),
+ .external_power_changed = n516_bat_power_changed,
+};
+
+static irqreturn_t n516_bat_charge_irq(int irq, void *dev)
+{
+ struct power_supply *psy = dev;
+
+ dev_dbg(psy->dev, "Battery charging IRQ\n");
+
+ if (power_supply_am_i_supplied(psy) && !n516_bat_charging())
+ the_lpc->battery_level = MAX_BAT_LEVEL;
+
+ power_supply_changed(psy);
+
+ return IRQ_HANDLED;
+}
+
+static int n516_lpc_send_message(struct n516_lpc_chip *chip, unsigned char val)
+{
+ struct i2c_client *client = chip->i2c_client;
+ struct i2c_msg msg = {client->addr, client->flags, 1, &val};
+ int ret = 0;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ return ret > 0 ? 0 : ret;
+}
+
+static void n516_key_event(struct n516_lpc_chip *chip, unsigned char keycode)
+{
+ struct i2c_client *client = chip->i2c_client;
+ bool long_press = false;
+
+ if (keycode & 0x40) {
+ keycode &= ~0x40;
+ long_press = true;
+ }
+
+ dev_dbg(&client->dev, "keycode: 0x%02x, long_press: 0x%02x\n", keycode, (unsigned int)long_press);
+
+ if (keycode >= ARRAY_SIZE(n516_lpc_keymap) || n516_lpc_keymap[keycode] == 0)
+ return;
+
+ if (long_press)
+ input_report_key(chip->input, KEY_LEFTALT, 1);
+
+ input_report_key(chip->input, n516_lpc_keymap[keycode], 1);
+ input_sync(chip->input);
+ input_report_key(chip->input, n516_lpc_keymap[keycode], 0);
+
+ if (long_press)
+ input_report_key(chip->input, KEY_LEFTALT, 0);
+ input_sync(chip->input);
+}
+
+static void n516_battery_event(struct n516_lpc_chip *chip, unsigned char battery_level)
+{
+ if (battery_level != chip->battery_level) {
+ chip->battery_level = battery_level;
+ power_supply_changed(&n516_battery);
+ }
+}
+
+static irqreturn_t n516_lpc_irq_thread(int irq, void *devid)
+{
+ struct n516_lpc_chip *chip = (struct n516_lpc_chip*)devid;
+ int ret;
+ unsigned char raw_msg;
+ struct i2c_client *client = chip->i2c_client;
+ struct i2c_msg msg = {client->addr, client->flags | I2C_M_RD, 1, &raw_msg};
+
+ if (client->dev.power.status >= DPM_OFF)
+ return IRQ_HANDLED;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1) {
+ dev_dbg(&client->dev, "I2C error: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ dev_dbg(&client->dev, "msg: 0x%02x\n", raw_msg);
+
+ /* Ack wakeup event */
+ if ((raw_msg & ~0x40) < ARRAY_SIZE(n516_lpc_keymap))
+ n516_key_event(chip, raw_msg);
+ else if ((raw_msg >= 0x81) && (raw_msg <= 0x87))
+ n516_battery_event(chip, raw_msg - 0x81);
+ else if (raw_msg == 0x7e)
+ n516_lpc_send_message(chip, 0x00);
+ else
+ dev_warn(&client->dev, "Unknown message: %x\n", raw_msg);
+
+ if (chip->suspending)
+ chip->can_sleep = 0;
+
+ return IRQ_HANDLED;
+}
+
+static void n516_lpc_power_off(void)
+{
+ struct i2c_client *client = the_lpc->i2c_client;
+ unsigned char val = 0x01;
+ struct i2c_msg msg = {client->addr, client->flags, 1, &val};
+
+ printk("Issue LPC POWEROFF command...\n");
+ while (1)
+ i2c_transfer(client->adapter, &msg, 1);
+}
+
+static int n516_lpc_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+ return 0;
+}
+
+static int n516_lpc_suspend_notifier(struct notifier_block *nb,
+ unsigned long event,
+ void *dummy)
+{
+ switch(event) {
+ case PM_SUSPEND_PREPARE:
+ the_lpc->suspending = 1;
+ the_lpc->can_sleep = 1;
+ break;
+ case PM_POST_SUSPEND:
+ the_lpc->suspending = 0;
+ the_lpc->can_sleep = 1;
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block n516_lpc_notif_block = {
+ .notifier_call = n516_lpc_suspend_notifier,
+};
+
+static int __devinit n516_lpc_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct n516_lpc_chip *chip;
+ struct input_dev *input;
+ int ret = 0;
+ int i;
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ the_lpc = chip;
+ chip->i2c_client = client;
+ if ((batt_level > 0) && (batt_level < ARRAY_SIZE(batt_charge)))
+ chip->battery_level = batt_level;
+ else
+ chip->battery_level = 1;
+
+ i2c_set_clientdata(client, chip);
+
+ ret = gpio_request(GPIO_LPC_INT, "LPC interrupt request");
+ if (ret) {
+ dev_err(&client->dev, "Unable to reguest LPC INT GPIO\n");
+ goto err_gpio_req_lpcint;
+ }
+
+ ret = gpio_request(GPIO_CHARG_STAT_N, "LPC charging status");
+ if (ret) {
+ dev_err(&client->dev, "Unable to reguest CHARG STAT GPIO\n");
+ goto err_gpio_req_chargstat;
+ }
+
+ /* Enter normal mode */
+ n516_lpc_send_message(chip, 0x2);
+
+ input = input_allocate_device();
+ if (!input) {
+ dev_err(&client->dev, "Unable to allocate input device\n");
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ chip->input = input;
+
+ __set_bit(EV_KEY, input->evbit);
+
+ for (i = 0; i < ARRAY_SIZE(n516_lpc_keymap); i++)
+ __set_bit(n516_lpc_keymap[i], input->keybit);
+
+ __set_bit(KEY_LEFTALT, input->keybit);
+
+ input->name = "n516-keys";
+ input->phys = "n516-keys/input0";
+ input->dev.parent = &client->dev;
+ input->id.bustype = BUS_I2C;
+ input->id.vendor = 0x0001;
+ input->id.product = 0x0001;
+ input->id.version = 0x0100;
+
+ ret = input_register_device(input);
+ if (ret < 0) {
+ dev_err(&client->dev, "Unable to register input device\n");
+ goto err_input_register;
+ }
+
+ ret = power_supply_register(NULL, &n516_battery);
+ if (ret) {
+ dev_err(&client->dev, "Unable to register N516 battery\n");
+ goto err_bat_reg;
+ }
+
+ ret = request_threaded_irq(gpio_to_irq(GPIO_LPC_INT), NULL,
+ n516_lpc_irq_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "lpc", chip);
+ if (ret) {
+ dev_err(&client->dev, "request_irq failed: %d\n", ret);
+ goto err_request_lpc_irq;
+ }
+
+ ret = request_irq(gpio_to_irq(GPIO_CHARG_STAT_N), n516_bat_charge_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "battery charging", &n516_battery);
+ if (ret) {
+ dev_err(&client->dev, "Unable to claim battery charging IRQ\n");
+ goto err_request_chrg_irq;
+ }
+
+ pm_power_off = n516_lpc_power_off;
+ ret = register_pm_notifier(&n516_lpc_notif_block);
+ if (ret) {
+ dev_err(&client->dev, "Unable to register PM notify block\n");
+ goto err_reg_pm_notifier;
+ }
+
+ device_init_wakeup(&client->dev, 1);
+
+ return 0;
+
+ unregister_pm_notifier(&n516_lpc_notif_block);
+err_reg_pm_notifier:
+ free_irq(gpio_to_irq(GPIO_CHARG_STAT_N), &n516_battery);
+err_request_chrg_irq:
+ free_irq(gpio_to_irq(GPIO_LPC_INT), chip);
+err_request_lpc_irq:
+ power_supply_unregister(&n516_battery);
+err_bat_reg:
+ input_unregister_device(input);
+err_input_register:
+ input_free_device(input);
+err_input_alloc:
+ gpio_free(GPIO_CHARG_STAT_N);
+err_gpio_req_chargstat:
+ gpio_free(GPIO_LPC_INT);
+err_gpio_req_lpcint:
+ i2c_set_clientdata(client, NULL);
+ kfree(chip);
+
+ return ret;
+}
+
+static int __devexit n516_lpc_remove(struct i2c_client *client)
+{
+ struct n516_lpc_chip *chip = i2c_get_clientdata(client);
+
+ unregister_pm_notifier(&n516_lpc_notif_block);
+ pm_power_off = NULL;
+ free_irq(gpio_to_irq(GPIO_CHARG_STAT_N), &n516_battery);
+ free_irq(gpio_to_irq(GPIO_LPC_INT), chip);
+ power_supply_unregister(&n516_battery);
+ input_unregister_device(chip->input);
+ gpio_free(GPIO_CHARG_STAT_N);
+ gpio_free(GPIO_LPC_INT);
+ i2c_set_clientdata(client, NULL);
+ kfree(chip);
+
+ return 0;
+}
+
+#if CONFIG_PM
+static int n516_lpc_suspend(struct i2c_client *client, pm_message_t msg)
+{
+ if (!the_lpc->can_sleep)
+ return -EBUSY;
+
+ if (device_may_wakeup(&client->dev))
+ enable_irq_wake(gpio_to_irq(GPIO_LPC_INT));
+
+ return 0;
+}
+
+static int n516_lpc_resume(struct i2c_client *client)
+{
+ if (device_may_wakeup(&client->dev))
+ disable_irq_wake(gpio_to_irq(GPIO_LPC_INT));
+
+ return 0;
+}
+#else
+#define n516_lpc_suspend NULL
+#define n516_lpc_resume NULL
+#endif
+
+
+static struct i2c_driver n516_lpc_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "n516-keys",
+ .owner = THIS_MODULE,
+ },
+ .probe = n516_lpc_probe,
+ .remove = __devexit_p(n516_lpc_remove),
+ .detect = n516_lpc_detect,
+ .id_table = n516_lpc_i2c_ids,
+ .address_list = normal_i2c,
+ .suspend = n516_lpc_suspend,
+ .resume = n516_lpc_resume,
+};
+
+static int __init n516_lpc_init(void)
+{
+ return i2c_add_driver(&n516_lpc_driver);
+}
+module_init(n516_lpc_init);
+
+static void __exit n516_lpc_exit(void)
+{
+ i2c_del_driver(&n516_lpc_driver);
+}
+module_exit(n516_lpc_exit);
+
+MODULE_AUTHOR("Yauhen Kharuzhy");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Keys and power controller driver for N516");
+MODULE_ALIAS("platform:n516-keys");
--
1.7.4.1

View File

@ -1,219 +0,0 @@
From 19d5c8c334a79951d927a1b6eb25bf6a896c9ab5 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 24 Apr 2010 12:38:41 +0200
Subject: [PATCH 07/32] Add N526 sound SoC board driver
---
sound/soc/jz4740/Kconfig | 8 ++
sound/soc/jz4740/Makefile | 2 +
sound/soc/jz4740/n526.c | 169 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 179 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/jz4740/n526.c
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
index 08530ca..c222dcb 100644
--- a/sound/soc/jz4740/Kconfig
+++ b/sound/soc/jz4740/Kconfig
@@ -29,3 +29,11 @@ config SND_JZ4740_SOC_N516
select SND_SOC_JZCODEC
help
Say Y if you want to enable support for SoC audio on the Hanvon N516.
+
+config SND_JZ4740_SOC_N526
+ tristate "SoC Audio support for Hanvon N526 eBook reader"
+ depends on SND_JZ4740_SOC && JZ4740_N526
+ select SND_JZ4740_SOC_I2S
+ select SND_SOC_JZCODEC
+ help
+ Say Y if you want to enable support for SoC audio on the Hanvon N526.
diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
index b64d912..e7952d3 100644
--- a/sound/soc/jz4740/Makefile
+++ b/sound/soc/jz4740/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
# Jz4740 Machine Support
snd-soc-qi-lb60-objs := qi_lb60.o
snd-soc-n516-objs := n516.o
+snd-soc-n526-objs := n526.o
obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o
obj-$(CONFIG_SND_JZ4740_SOC_N516) += snd-soc-n516.o
+obj-$(CONFIG_SND_JZ4740_SOC_N526) += snd-soc-n526.o
diff --git a/sound/soc/jz4740/n526.c b/sound/soc/jz4740/n526.c
new file mode 100644
index 0000000..2283904
--- /dev/null
+++ b/sound/soc/jz4740/n526.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <linux/gpio.h>
+
+#include "../codecs/jzcodec.h"
+#include "jz4740-pcm.h"
+#include "jz4740-i2s.h"
+
+#define N526_AMP_EN_GPIO JZ_GPIO_PORTD(4)
+
+static int n526_spk_event(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *ctrl, int event)
+{
+ gpio_set_value(N526_AMP_EN_GPIO, !SND_SOC_DAPM_EVENT_OFF(event));
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget n526_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker", n526_spk_event),
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route n526_routes[] = {
+ {"Mic", NULL, "MIC"},
+ {"Speaker", NULL, "LOUT"},
+ {"Speaker", NULL, "ROUT"},
+ {"Headphone", NULL, "LOUT"},
+ {"Headphone", NULL, "ROUT"},
+};
+
+static const struct snd_kcontrol_new n526_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
+#define N526_DAIFMT (SND_SOC_DAIFMT_I2S | \
+ SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
+static int n526_codec_init(struct snd_soc_codec *codec)
+{
+ int ret;
+ struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
+ struct snd_soc_dai *codec_dai = codec->socdev->card->dai_link->codec_dai;
+
+ snd_soc_dapm_nc_pin(codec, "LIN");
+ snd_soc_dapm_nc_pin(codec, "RIN");
+
+ ret = snd_soc_dai_set_fmt(codec_dai, N526_DAIFMT);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set codec dai format: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, N526_DAIFMT);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, JZCODEC_SYSCLK, 111,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set codec dai sysclk: %d\n", ret);
+ return ret;
+ }
+
+ snd_soc_dapm_new_controls(codec, n526_widgets, ARRAY_SIZE(n526_widgets));
+
+ snd_soc_add_controls(codec, n526_controls,
+ ARRAY_SIZE(n526_controls));
+
+ snd_soc_dapm_add_routes(codec, n526_routes, ARRAY_SIZE(n526_routes));
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link n526_dai = {
+ .name = "jz-codec",
+ .stream_name = "JZCODEC",
+ .cpu_dai = &jz4740_i2s_dai,
+ .codec_dai = &jz_codec_dai,
+ .init = n526_codec_init,
+};
+
+static struct snd_soc_card n526 = {
+ .name = "N526",
+ .dai_link = &n526_dai,
+ .num_links = 1,
+ .platform = &jz4740_soc_platform,
+};
+
+static struct snd_soc_device n526_snd_devdata = {
+ .card = &n526,
+ .codec_dev = &soc_codec_dev_jzcodec,
+};
+
+static struct platform_device *n526_snd_device;
+
+static int __init n526_init(void)
+{
+ int ret;
+
+ n526_snd_device = platform_device_alloc("soc-audio", -1);
+
+ if (!n526_snd_device)
+ return -ENOMEM;
+
+ ret = gpio_request(N526_AMP_EN_GPIO, "AMP");
+ if (ret) {
+ pr_err("n526 snd: Failed to request AMP GPIO(%d): %d\n",
+ N526_AMP_EN_GPIO, ret);
+ goto err_device_put;
+ }
+
+ gpio_direction_output(JZ_GPIO_PORTD(4), 0);
+
+ platform_set_drvdata(n526_snd_device, &n526_snd_devdata);
+ n526_snd_devdata.dev = &n526_snd_device->dev;
+ ret = platform_device_add(n526_snd_device);
+ if (ret) {
+ pr_err("n526 snd: Failed to add snd soc device: %d\n", ret);
+ goto err_unset_pdata;
+ }
+
+ return 0;
+
+err_unset_pdata:
+ platform_set_drvdata(n526_snd_device, NULL);
+ gpio_free(N526_AMP_EN_GPIO);
+err_device_put:
+ platform_device_put(n526_snd_device);
+
+ return ret;
+}
+module_init(n526_init);
+
+static void __exit n526_exit(void)
+{
+ gpio_free(N526_AMP_EN_GPIO);
+ platform_device_unregister(n526_snd_device);
+}
+module_exit(n526_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC N526 audio support");
+MODULE_LICENSE("GPL v2");
--
1.7.4.1

View File

@ -1,482 +0,0 @@
From 5e219770079a61b8c8e59abe5510678361c94696 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 5 Sep 2010 03:19:10 +0200
Subject: [PATCH 08/32] i2c: Add i2c driver for JZ47XX SoCs
This patch adds a driver for the i2c controller found in Ingenic JZ47XX based
SoCs.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-jz47xx.c | 424 +++++++++++++++++++++++++++++++++++++++
3 files changed, 435 insertions(+), 0 deletions(-)
create mode 100644 drivers/i2c/busses/i2c-jz47xx.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 646068e..5b76fcf 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -434,6 +434,16 @@ config I2C_IXP2000
This driver is deprecated and will be dropped soon. Use i2c-gpio
instead.
+config I2C_JZ47XX
+ tristate "JZ4740 I2C Interface"
+ depends on ARCH_JZ4740
+ help
+ Say Y here if you want support for the I2C controller found on Ingenic
+ JZ47XX based SoCs.
+
+ This driver can also be built as a module. If so, the module will be
+ called i2c-jz47xx.
+
config I2C_MPC
tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
depends on PPC
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e6cf294..07be071 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_I2C_IMX) += i2c-imx.o
obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
+obj-$(CONFIG_I2C_JZ47XX) += i2c-jz47xx.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
diff --git a/drivers/i2c/busses/i2c-jz47xx.c b/drivers/i2c/busses/i2c-jz47xx.c
new file mode 100644
index 0000000..492d350
--- /dev/null
+++ b/drivers/i2c/busses/i2c-jz47xx.c
@@ -0,0 +1,424 @@
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#define JZ47XX_REG_I2C_DATA 0x00
+#define JZ47XX_REG_I2C_CTRL 0x04
+#define JZ47XX_REG_I2C_STATUS 0x08
+#define JZ47XX_REG_I2C_CLOCK 0x0C
+
+#define JZ47XX_I2C_STATUS_FIFO_FULL BIT(4)
+#define JZ47XX_I2C_STATUS_BUSY BIT(3)
+#define JZ47XX_I2C_STATUS_TEND BIT(2)
+#define JZ47XX_I2C_STATUS_DATA_VALID BIT(1)
+#define JZ47XX_I2C_STATUS_NACK BIT(0)
+
+#define JZ47XX_I2C_CTRL_IRQ_ENABLE BIT(4)
+#define JZ47XX_I2C_CTRL_START BIT(3)
+#define JZ47XX_I2C_CTRL_STOP BIT(2)
+#define JZ47XX_I2C_CTRL_NACK BIT(1)
+#define JZ47XX_I2C_CTRL_ENABLE BIT(0)
+
+struct jz47xx_i2c {
+ struct resource *mem;
+ void __iomem *base;
+ int irq;
+ struct clk *clk;
+
+ struct i2c_adapter adapter;
+
+ wait_queue_head_t wait_queue;
+};
+
+static inline struct jz47xx_i2c *adapter_to_jz47xx_i2c(struct i2c_adapter *adap)
+{
+ return container_of(adap, struct jz47xx_i2c, adapter);
+}
+
+static inline void jz47xx_i2c_set_ctrl(struct jz47xx_i2c *jz47xx_i2c,
+ uint8_t mask, uint8_t value)
+{
+ uint8_t ctrl;
+ ctrl = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_CTRL);
+ ctrl &= ~mask;
+ ctrl |= value;
+ printk("ctrl: %x\n", ctrl);
+ writeb(ctrl, jz47xx_i2c->base + JZ47XX_REG_I2C_CTRL);
+}
+
+static irqreturn_t jz47xx_i2c_irq_handler(int irq, void *devid)
+{
+ struct jz47xx_i2c *jz47xx_i2c = devid;
+
+ printk("IRQ\n");
+
+ wake_up(&jz47xx_i2c->wait_queue);
+
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_IRQ_ENABLE, 0);
+
+ return IRQ_HANDLED;
+}
+
+static inline void jz47xx_i2c_set_data_valid(struct jz47xx_i2c *jz47xx_i2c,
+ bool valid)
+{
+ uint8_t val;
+ val = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
+ if (valid)
+ val |= JZ47XX_I2C_STATUS_DATA_VALID;
+ else
+ val &= ~JZ47XX_I2C_STATUS_DATA_VALID;
+ writeb(val, jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
+}
+
+static int jz47xx_i2c_test_event(struct jz47xx_i2c *jz47xx_i2c, uint8_t mask, uint8_t value)
+{
+ uint8_t status;
+
+ mask |= JZ47XX_I2C_STATUS_NACK;
+ value |= JZ47XX_I2C_STATUS_NACK;
+
+ status = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
+ printk("status: %x %x %x %x\n", status, mask, value, (status & mask) ^
+ value);
+ if (((status & mask) ^ value) == mask) {
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_IRQ_ENABLE,
+ JZ47XX_I2C_CTRL_IRQ_ENABLE);
+ return 0;
+ }
+ return 1;
+}
+
+static int jz47xx_i2c_wait_event_or_nack(struct jz47xx_i2c *jz47xx_i2c, uint8_t
+mask, uint8_t value)
+{
+ int ret;
+
+ ret = wait_event_interruptible_timeout(jz47xx_i2c->wait_queue,
+ jz47xx_i2c_test_event(jz47xx_i2c, mask, value), 30 * HZ);
+
+/* while (!jz47xx_i2c_test_event(jz47xx_i2c, mask, value));
+
+ ret = 1;*/
+
+ printk("wait event or nack: %d %x\n", ret, readb(jz47xx_i2c->base +
+ JZ47XX_REG_I2C_STATUS));
+
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ else if(ret > 0) {
+ if (readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS) & JZ47XX_I2C_STATUS_NACK)
+ ret = -EIO;
+ else
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int jz47xx_i2c_wait_event(struct jz47xx_i2c *jz47xx_i2c, uint8_t event)
+{
+ int ret;
+
+ ret = wait_event_interruptible_timeout(jz47xx_i2c->wait_queue,
+ jz47xx_i2c_test_event(jz47xx_i2c, event, event), 30 * HZ);
+
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ else if(ret > 0)
+ ret = 0;
+
+ return ret;
+}
+
+
+static int jz47xx_i2c_write_msg(struct jz47xx_i2c *jz47xx_i2c,
+ struct i2c_msg *msg)
+{
+ int ret;
+ int i;
+
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ for (i = 0; i < msg->len; ++i) {
+ writeb(msg->buf[i], jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
+ jz47xx_i2c_set_data_valid(jz47xx_i2c, true);
+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
+ JZ47XX_I2C_STATUS_DATA_VALID, 0);
+ if (ret)
+ break;
+ }
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_STOP,
+ JZ47XX_I2C_CTRL_STOP);
+
+ if (!ret)
+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c, JZ47XX_I2C_STATUS_TEND,
+ JZ47XX_I2C_STATUS_TEND);
+
+ return ret;
+}
+
+static int jz47xx_i2c_read_msg(struct jz47xx_i2c *jz47xx_i2c,
+ struct i2c_msg *msg)
+{
+ int i;
+ int ret;
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
+ msg->len == 1 ? JZ47XX_I2C_CTRL_NACK : 0);
+
+ for (i = 0; i < msg->len; ++i) {
+ ret = jz47xx_i2c_wait_event(jz47xx_i2c, JZ47XX_I2C_STATUS_DATA_VALID);
+ if (ret) {
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
+ JZ47XX_I2C_CTRL_NACK);
+ break;
+ }
+
+ if (i == msg->len - 2) {
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
+ JZ47XX_I2C_CTRL_NACK);
+ }
+
+ msg->buf[i] = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
+ printk("read: %x\n", msg->buf[i]);
+ jz47xx_i2c_set_data_valid(jz47xx_i2c, false);
+ }
+
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_STOP,
+ JZ47XX_I2C_CTRL_STOP);
+
+ return ret;
+}
+
+static int jz47xx_i2c_xfer_msg(struct jz47xx_i2c *jz47xx_i2c,
+ struct i2c_msg *msg)
+{
+ uint8_t addr;
+ int ret;
+
+ addr = msg->addr << 1;
+ if (msg->flags & I2C_M_RD)
+ addr |= 1;
+
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_START,
+ JZ47XX_I2C_CTRL_START);
+ writeb(addr, jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
+ jz47xx_i2c_set_data_valid(jz47xx_i2c, true);
+
+ if (msg->flags & I2C_M_RD) {
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
+ JZ47XX_I2C_STATUS_TEND, JZ47XX_I2C_STATUS_TEND);
+ if (!ret)
+ ret = jz47xx_i2c_read_msg(jz47xx_i2c, msg);
+ } else {
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
+ JZ47XX_I2C_STATUS_DATA_VALID, 0);
+ if (!ret)
+ ret = jz47xx_i2c_write_msg(jz47xx_i2c, msg);
+ }
+
+ return ret;
+}
+
+static int jz47xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int
+num)
+{
+ struct jz47xx_i2c *jz47xx_i2c = adapter_to_jz47xx_i2c(adap);
+ int ret = 0;
+ int i;
+ int mask = JZ47XX_I2C_CTRL_ENABLE;
+
+ printk("xfer: %d %x\n", num, readb(jz47xx_i2c->base +
+ JZ47XX_REG_I2C_STATUS));
+
+ clk_enable(jz47xx_i2c->clk);
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, mask, mask);
+
+ for (i = 0; i < num; ++i) {
+ ret = jz47xx_i2c_xfer_msg(jz47xx_i2c, &msgs[i]);
+ if (ret)
+ break;
+ }
+
+ jz47xx_i2c_set_ctrl(jz47xx_i2c, mask, 0);
+ clk_disable(jz47xx_i2c->clk);
+
+ printk("xfer ret: %d\n", ret);
+
+ return ret;
+}
+
+static u32 jz47xx_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm jz47xx_i2c_algorithm = {
+ .master_xfer = jz47xx_i2c_xfer,
+ .functionality = jz47xx_i2c_functionality,
+};
+
+const static struct jz_gpio_bulk_request jz47xx_i2c_pins[] = {
+ JZ_GPIO_BULK_PIN(I2C_SDA),
+ JZ_GPIO_BULK_PIN(I2C_SCK),
+};
+
+static int __devinit jz47xx_i2c_probe(struct platform_device *pdev)
+{
+ struct jz47xx_i2c *jz47xx_i2c;
+ struct resource *mem;
+ void __iomem *base;
+ struct clk *clk;
+ int irq;
+ int ret;
+
+ irq = platform_get_irq(pdev, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
+ return irq;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "Failed to get iomem region\n");
+ return -ENXIO;
+ }
+
+ mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
+ if (!mem) {
+ dev_err(&pdev->dev, "Failed to request iomem region\n");
+ return -EBUSY;
+ }
+
+ base = ioremap(mem->start, resource_size(mem));
+ if (!base) {
+ dev_err(&pdev->dev, "Failed to ioremap iomem\n");
+ ret = -EBUSY;
+ goto err_release_mem_region;
+ }
+
+ clk = clk_get(&pdev->dev, "i2c");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto err_iounmap;
+ }
+
+ jz47xx_i2c = kzalloc(sizeof(*jz47xx_i2c), GFP_KERNEL);
+ if (!jz47xx_i2c) {
+ ret = -ENOMEM;
+ goto err_clk_put;
+ }
+
+ jz47xx_i2c->adapter.owner = THIS_MODULE;
+ jz47xx_i2c->adapter.algo = &jz47xx_i2c_algorithm;
+ jz47xx_i2c->adapter.dev.parent = &pdev->dev;
+ jz47xx_i2c->adapter.nr = pdev->id < 0 ?: 0;
+ strcpy(jz47xx_i2c->adapter.name, pdev->name);
+
+ jz47xx_i2c->mem = mem;
+ jz47xx_i2c->base = base;
+ jz47xx_i2c->clk = clk;
+ jz47xx_i2c->irq = irq;
+
+ init_waitqueue_head(&jz47xx_i2c->wait_queue);
+
+ ret = request_irq(irq, jz47xx_i2c_irq_handler, 0, pdev->name, jz47xx_i2c);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+ goto err_free;
+ }
+
+ ret = jz_gpio_bulk_request(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request i2c pins: %d\n", ret);
+ goto err_free_irq;
+ }
+
+ writew(0x10, jz47xx_i2c->base + JZ47XX_REG_I2C_CLOCK);
+
+ ret = i2c_add_numbered_adapter(&jz47xx_i2c->adapter);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add i2c adapter: %d\n", ret);
+ goto err_free_gpios;
+ }
+
+ platform_set_drvdata(pdev, jz47xx_i2c);
+
+ printk("JZ4740 I2C\n");
+
+ return 0;
+
+err_free_gpios:
+ jz_gpio_bulk_free(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
+err_free_irq:
+ free_irq(irq, jz47xx_i2c);
+err_free:
+ kfree(jz47xx_i2c);
+err_clk_put:
+ clk_put(clk);
+err_iounmap:
+ iounmap(base);
+err_release_mem_region:
+ release_mem_region(mem->start, resource_size(mem));
+ return ret;
+}
+
+static int __devexit jz47xx_i2c_remove(struct platform_device *pdev)
+{
+ struct jz47xx_i2c *jz47xx_i2c = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ i2c_del_adapter(&jz47xx_i2c->adapter);
+
+ jz_gpio_bulk_free(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
+
+ free_irq(jz47xx_i2c->irq, jz47xx_i2c);
+ clk_put(jz47xx_i2c->clk);
+
+ iounmap(jz47xx_i2c->base);
+ release_mem_region(jz47xx_i2c->mem->start, resource_size(jz47xx_i2c->mem));
+
+ kfree(jz47xx_i2c);
+
+ return 0;
+}
+
+static struct platform_driver jz47xx_i2c_driver = {
+ .probe = jz47xx_i2c_probe,
+ .remove = jz47xx_i2c_remove,
+ .driver = {
+ .name = "jz47xx-i2c",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init jz47xx_i2c_init(void)
+{
+ return platform_driver_register(&jz47xx_i2c_driver);
+}
+module_init(jz47xx_i2c_init);
+
+static void jz47xx_i2c_exit(void)
+{
+ platform_driver_unregister(&jz47xx_i2c_driver);
+}
+module_exit(jz47xx_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("I2C adapter driver for JZ47XX SoCs");
+MODULE_ALIAS("platform:jz47xx-i2c");
+
--
1.7.4.1

View File

@ -1,29 +0,0 @@
From 05bc4140f9da08fa48d81131ffa785e3026773a8 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 5 Sep 2010 03:21:51 +0200
Subject: [PATCH 09/32] MIPS: JZ4740: Fix i2c driver name.
The i2c driver is generic to all JZ47XX based SoCs not only the JZ4740. Reflect
this in the driver name.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
arch/mips/jz4740/platform.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 10929e2..cc6de5b 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -142,7 +142,7 @@ static struct resource jz4740_i2c_resources[] = {
};
struct platform_device jz4740_i2c_device = {
- .name = "jz4740-i2c",
+ .name = "jz47xx-i2c",
.id = 0,
.num_resources = ARRAY_SIZE(jz4740_i2c_resources),
.resource = jz4740_i2c_resources,
--
1.7.4.1

View File

@ -1,71 +0,0 @@
From 659b0bb01c8e567d4593ffbd7acd6b8ceab0edf3 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 5 Sep 2010 20:36:59 +0200
Subject: [PATCH 10/32] MFD: jz4740-adc: Add support for the touchscreen part of the adc unit
---
drivers/mfd/jz4740-adc.c | 27 ++++++++++++++++++++++++---
include/linux/jz4740-adc.h | 2 +-
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index a0bd0cf..3be161e 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -46,9 +46,9 @@
enum {
JZ_ADC_IRQ_ADCIN = 0,
JZ_ADC_IRQ_BATTERY,
- JZ_ADC_IRQ_TOUCH,
- JZ_ADC_IRQ_PENUP,
- JZ_ADC_IRQ_PENDOWN,
+ JZ_ADC_IRQ_TS_DATA_READY,
+ JZ_ADC_IRQ_TS_PENUP,
+ JZ_ADC_IRQ_TS_PENDOWN,
};
struct jz4740_adc {
@@ -226,6 +226,27 @@ static struct resource jz4740_battery_resources[] = {
},
};
+static struct resource jz4740_ts_resources[] = {
+ {
+ .start = JZ_ADC_IRQ_TS_DATA_READY,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = JZ_ADC_IRQ_TS_PENUP,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = JZ_ADC_IRQ_TS_PENDOWN,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = JZ_REG_ADC_TOUCHSCREEN_BASE,
+ .end = JZ_REG_ADC_TOUCHSCREEN_BASE + 0xb,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+
const struct mfd_cell jz4740_adc_cells[] = {
{
.id = 0,
diff --git a/include/linux/jz4740-adc.h b/include/linux/jz4740-adc.h
index 9053f95..3f15f66 100644
--- a/include/linux/jz4740-adc.h
+++ b/include/linux/jz4740-adc.h
@@ -25,7 +25,7 @@ int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val);
#define JZ_ADC_CONFIG_BAT_MB BIT(4)
#define JZ_ADC_CONFIG_DNUM(dnum) ((dnum) << 16)
-#define JZ_ADC_CONFIG_XYZ_OFFSET(dnum) ((xyz) << 13)
+#define JZ_ADC_CONFIG_XYZ_OFFSET(xyz) ((xyz) << 13)
#define JZ_ADC_CONFIG_SAMPLE_NUM(x) ((x) << 10)
#define JZ_ADC_CONFIG_CLKDIV(div) ((div) << 5)
--
1.7.4.1

View File

@ -1,389 +0,0 @@
From 71e0648ad022c6f05e1bed1fcca69abc8abde4d9 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 5 Sep 2010 20:45:08 +0200
Subject: [PATCH 11/32] input: Add touchscreen driver for the JZ4740 SoC
This patch adds a touchscreen driver for the Ingenic JZ4740 SoC.
The touchscreen controller is part of the ADC unit and thus this driver is a mfd
cell from the jz4740-adc driver.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/input/touchscreen/Kconfig | 12 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/jz4740-ts.c | 330 +++++++++++++++++++++++++++++++++
3 files changed, 343 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/jz4740-ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index cabd9e5..10836e5 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -726,4 +726,16 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_JZ4740
+ tristate "JZ4740 touchscreen support"
+ depends on MFD_JZ4740_ADC
+ help
+ Say Y here if you want support for the touchscreen controller found on
+ Ingenic JZ4740 SoCs.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called jz4740-ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 282d6f7..d8cc316 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
+obj-$(CONFIG_TOUCHSCREEN_JZ4740) += jz4740-ts.o
obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
diff --git a/drivers/input/touchscreen/jz4740-ts.c b/drivers/input/touchscreen/jz4740-ts.c
new file mode 100644
index 0000000..dd5de34
--- /dev/null
+++ b/drivers/input/touchscreen/jz4740-ts.c
@@ -0,0 +1,330 @@
+/*
+ * Touchscreen driver for Ingenic JZ SoCs.
+ *
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * 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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/input.h>
+#include <linux/bitops.h>
+#include <linux/jz4740-adc.h>
+
+struct jz4740_ts {
+ struct platform_device *pdev;
+
+ struct resource *mem;
+ void __iomem *base;
+
+ int irq_penup;
+ int irq_pendown;
+ int irq_data_ready;
+
+ struct mfd_cell *cell;
+ struct input_dev *input;
+
+ bool is_open;
+};
+
+static irqreturn_t jz4740_ts_data_ready_irq_handler(int irq, void *devid)
+{
+ struct jz4740_ts *jz4740_ts = devid;
+ uint32_t data;
+ unsigned long x, y, z1, z2, pressure;
+
+ data = readl(jz4740_ts->base + 0x08);
+ x = data & 0xfff;
+ y = (data >> 16) & 0xfff;
+
+ data = readl(jz4740_ts->base + 0x08);
+ z1 = data & 0xfff;
+ z2 = (data >> 16) & 0xfff;
+ if (z1 == 0) {
+ pressure = 4095UL;
+ } else if (z1 > z2) {
+ pressure = 0;
+ } else {
+ if (data & 0x8000)
+ pressure = (((480UL * x * z2) / z1) - 480UL * x) / 4096UL;
+ else
+ pressure = (((272UL * y * z2) / z1) - 272UL * y) / 4096UL;
+ if (pressure >= 4096UL)
+ pressure = 4095UL;
+ pressure = 4095UL - pressure;
+ }
+
+ input_report_abs(jz4740_ts->input, ABS_X, y);
+ input_report_abs(jz4740_ts->input, ABS_Y, 4095 - x);
+ input_report_abs(jz4740_ts->input, ABS_PRESSURE, pressure);
+ input_report_key(jz4740_ts->input, BTN_TOUCH, 1);
+ input_sync(jz4740_ts->input);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t jz4740_ts_pen_irq_handler(int irq, void *devid)
+{
+ struct jz4740_ts *jz4740_ts = devid;
+ int is_pressed;
+
+ if (irq == jz4740_ts->irq_penup) {
+ enable_irq(jz4740_ts->irq_pendown);
+ is_pressed = 0;
+ } else {
+ enable_irq(jz4740_ts->irq_penup);
+ is_pressed = 1;
+ }
+ disable_irq_nosync(irq);
+
+ printk("pen irq: %d\n", irq);
+ input_report_key(jz4740_ts->input, BTN_TOUCH, is_pressed);
+ if (is_pressed == 0)
+ input_report_abs(jz4740_ts->input, ABS_PRESSURE, 0);
+ input_sync(jz4740_ts->input);
+
+ return IRQ_HANDLED;
+}
+
+static int jz4740_ts_open(struct input_dev *input)
+{
+ struct jz4740_ts *jz4740_ts = input_get_drvdata(input);
+
+ jz4740_ts->is_open = true;
+ jz4740_ts->cell->enable(jz4740_ts->pdev);
+
+ return 0;
+}
+
+static void jz4740_ts_close(struct input_dev *input)
+{
+ struct jz4740_ts *jz4740_ts = input_get_drvdata(input);
+
+ jz4740_ts->cell->disable(jz4740_ts->pdev);
+ jz4740_ts->is_open = false;
+}
+
+static int __devinit jz4740_ts_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct jz4740_ts *jz4740_ts;
+ struct input_dev *input;
+
+ jz4740_ts = kzalloc(sizeof(*jz4740_ts), GFP_KERNEL);
+ if (!jz4740_ts) {
+ dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+ return -ENOMEM;
+ }
+
+ jz4740_ts->pdev = pdev;
+ jz4740_ts->cell = pdev->dev.platform_data;
+
+ jz4740_ts->irq_data_ready = platform_get_irq(pdev, 0);
+ if (jz4740_ts->irq_data_ready < 0) {
+ ret = jz4740_ts->irq_data_ready;
+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
+ goto err_free;
+ }
+
+ jz4740_ts->irq_penup = platform_get_irq(pdev, 1);
+ if (jz4740_ts->irq_penup < 0) {
+ ret = jz4740_ts->irq_penup;
+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
+ goto err_free;
+ }
+
+ jz4740_ts->irq_pendown = platform_get_irq(pdev, 2);
+ if (jz4740_ts->irq_pendown < 0) {
+ ret = jz4740_ts->irq_pendown;
+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
+ goto err_free;
+ }
+
+ jz4740_ts->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!jz4740_ts->mem) {
+ ret = -ENOENT;
+ dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
+ goto err_free;
+ }
+
+ jz4740_ts->mem = request_mem_region(jz4740_ts->mem->start,
+ resource_size(jz4740_ts->mem), pdev->name);
+ if (!jz4740_ts->mem) {
+ ret = -EBUSY;
+ dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+ goto err_free;
+ }
+
+ jz4740_ts->base = ioremap_nocache(jz4740_ts->mem->start,
+ resource_size(jz4740_ts->mem));
+ if (!jz4740_ts->base) {
+ ret = -EBUSY;
+ dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
+ goto err_release_mem_region;
+ }
+
+ input = input_allocate_device();
+ if (!input) {
+ dev_err(&pdev->dev, "Failed to allocate input device\n");
+ ret = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ __set_bit(BTN_TOUCH, input->keybit);
+
+ input_set_abs_params(input, ABS_X, 150, 3920, 0, 0);
+ input_set_abs_params(input, ABS_Y, 270, 3700, 0, 0);
+ input_set_abs_params(input, ABS_PRESSURE, 0, 4096, 0, 0);
+
+ input->name = pdev->name;
+ input->phys = "jz4740";
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = &pdev->dev;
+
+ input->open = jz4740_ts_open;
+ input->close = jz4740_ts_close;
+
+ input_set_drvdata(input, jz4740_ts);
+
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register input device: %d\n", ret);
+ input_free_device(input);
+ goto err_iounmap;
+ }
+ jz4740_ts->input = input;
+
+ ret = request_irq(jz4740_ts->irq_data_ready, jz4740_ts_data_ready_irq_handler, 0, pdev->name,
+ jz4740_ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
+ goto err_input_unregister_device;
+ }
+ ret = request_irq(jz4740_ts->irq_penup, jz4740_ts_pen_irq_handler, 0, pdev->name,
+ jz4740_ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
+ goto err_free_irq_data_ready;
+ }
+ disable_irq(jz4740_ts->irq_penup);
+ ret = request_irq(jz4740_ts->irq_pendown, jz4740_ts_pen_irq_handler, 0, pdev->name,
+ jz4740_ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
+ goto err_free_irq_penup;
+ }
+ platform_set_drvdata(pdev, jz4740_ts);
+
+ jz4740_adc_set_config(pdev->dev.parent,
+ JZ_ADC_CONFIG_EX_IN | JZ_ADC_CONFIG_XYZ_OFFSET(2) | JZ_ADC_CONFIG_DNUM(7),
+ JZ_ADC_CONFIG_EX_IN | JZ_ADC_CONFIG_XYZ_MASK | JZ_ADC_CONFIG_DNUM_MASK);
+
+
+ writel(0x15e, jz4740_ts->base);
+ writel(0x32, jz4740_ts->base + 0x04);
+
+ return 0;
+
+err_free_irq_penup:
+ free_irq(jz4740_ts->irq_penup, jz4740_ts);
+err_free_irq_data_ready:
+ free_irq(jz4740_ts->irq_data_ready, jz4740_ts);
+err_input_unregister_device:
+ input_unregister_device(jz4740_ts->input);
+err_iounmap:
+ platform_set_drvdata(pdev, NULL);
+ iounmap(jz4740_ts->base);
+err_release_mem_region:
+ release_mem_region(jz4740_ts->mem->start, resource_size(jz4740_ts->mem));
+err_free:
+ kfree(jz4740_ts);
+ return ret;
+}
+
+static int __devexit jz4740_ts_remove(struct platform_device *pdev)
+{
+ struct jz4740_ts *jz4740_ts = platform_get_drvdata(pdev);
+
+
+ free_irq(jz4740_ts->irq_pendown, jz4740_ts);
+ free_irq(jz4740_ts->irq_penup, jz4740_ts);
+ free_irq(jz4740_ts->irq_data_ready, jz4740_ts);
+
+ input_unregister_device(jz4740_ts->input);
+
+ iounmap(jz4740_ts->base);
+ release_mem_region(jz4740_ts->mem->start, resource_size(jz4740_ts->mem));
+
+ kfree(jz4740_ts);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int jz4740_ts_suspend(struct device *dev)
+{
+ struct jz4740_ts *jz4740_ts = dev_get_drvdata(dev);
+
+ if (jz4740_ts->is_open);
+ jz4740_ts->cell->disable(jz4740_ts->pdev);
+
+ return 0;
+}
+
+static int jz4740_ts_resume(struct device *dev)
+{
+ struct jz4740_ts *jz4740_ts = dev_get_drvdata(dev);
+
+ if (jz4740_ts->is_open);
+ jz4740_ts->cell->enable(jz4740_ts->pdev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops jz4740_ts_pm_ops = {
+ .suspend = jz4740_ts_suspend,
+ .resume = jz4740_ts_resume,
+};
+
+#define JZ4740_TS_PM_OPS (&jz4740_ts_pm_ops)
+#else
+#define JZ4740_TS_PM_OPS NULL
+#endif
+
+static struct platform_driver jz4740_ts_driver = {
+ .probe = jz4740_ts_probe,
+ .remove = __devexit_p(jz4740_ts_remove),
+ .driver = {
+ .name = "jz4740-ts",
+ .owner = THIS_MODULE,
+ .pm = JZ4740_TS_PM_OPS,
+ },
+};
+
+static int __init jz4740_ts_init(void)
+{
+ return platform_driver_register(&jz4740_ts_driver);
+}
+module_init(jz4740_ts_init);
+
+static void __exit jz4740_ts_exit(void)
+{
+ platform_driver_unregister(&jz4740_ts_driver);
+}
+module_exit(jz4740_ts_exit);
+
+MODULE_ALIAS("platform:jz4740-ts");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("JZ4740 SoC battery driver");
--
1.7.4.1

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
From 8a760f273f94b72e882d7f82b04ade72ae739a6b Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Wed, 14 Sep 2011 15:12:41 +0800
Subject: [PATCH 25/32] Update to new platform code
---
drivers/mtd/nand/jz4740_nand.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 6e813da..95b4fc9 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -311,7 +311,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
if (ret)
goto err_free;
- ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
+ ret = jz_nand_ioremap_resource(pdev, "bank1", &nand->bank_mem,
&nand->bank_base);
if (ret)
goto err_iounmap_mmio;
--
1.7.4.1

View File

@ -1,208 +0,0 @@
From 2dc84f90409839e6a85bd9e25394a387c86d12a1 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
Date: Wed, 14 Sep 2011 14:29:58 +0800
Subject: [PATCH 29/32] Add new jz4740_lcd.h
---
drivers/video/jz4740_fb.c | 78 +----------------------------------
drivers/video/jz4740_lcd.h | 99 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+), 77 deletions(-)
create mode 100644 drivers/video/jz4740_lcd.h
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
index de36693..6b48367 100644
--- a/drivers/video/jz4740_fb.c
+++ b/drivers/video/jz4740_fb.c
@@ -29,83 +29,7 @@
#include <asm/mach-jz4740/jz4740_fb.h>
#include <asm/mach-jz4740/gpio.h>
-#define JZ_REG_LCD_CFG 0x00
-#define JZ_REG_LCD_VSYNC 0x04
-#define JZ_REG_LCD_HSYNC 0x08
-#define JZ_REG_LCD_VAT 0x0C
-#define JZ_REG_LCD_DAH 0x10
-#define JZ_REG_LCD_DAV 0x14
-#define JZ_REG_LCD_PS 0x18
-#define JZ_REG_LCD_CLS 0x1C
-#define JZ_REG_LCD_SPL 0x20
-#define JZ_REG_LCD_REV 0x24
-#define JZ_REG_LCD_CTRL 0x30
-#define JZ_REG_LCD_STATE 0x34
-#define JZ_REG_LCD_IID 0x38
-#define JZ_REG_LCD_DA0 0x40
-#define JZ_REG_LCD_SA0 0x44
-#define JZ_REG_LCD_FID0 0x48
-#define JZ_REG_LCD_CMD0 0x4C
-#define JZ_REG_LCD_DA1 0x50
-#define JZ_REG_LCD_SA1 0x54
-#define JZ_REG_LCD_FID1 0x58
-#define JZ_REG_LCD_CMD1 0x5C
-
-#define JZ_LCD_CFG_SLCD BIT(31)
-#define JZ_LCD_CFG_PS_DISABLE BIT(23)
-#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
-#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
-#define JZ_LCD_CFG_REV_DISABLE BIT(20)
-#define JZ_LCD_CFG_HSYNCM BIT(19)
-#define JZ_LCD_CFG_PCLKM BIT(18)
-#define JZ_LCD_CFG_INV BIT(17)
-#define JZ_LCD_CFG_SYNC_DIR BIT(16)
-#define JZ_LCD_CFG_PS_POLARITY BIT(15)
-#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
-#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
-#define JZ_LCD_CFG_REV_POLARITY BIT(12)
-#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
-#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
-#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
-#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
-#define JZ_LCD_CFG_18_BIT BIT(7)
-#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
-#define JZ_LCD_CFG_MODE_MASK 0xf
-
-#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
-#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
-#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
-#define JZ_LCD_CTRL_RGB555 BIT(27)
-#define JZ_LCD_CTRL_OFUP BIT(26)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
-#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
-#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
-#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
-#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
-#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
-#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
-#define JZ_LCD_CTRL_DD_IRQ BIT(8)
-#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
-#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
-#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
-#define JZ_LCD_CTRL_DISABLE BIT(4)
-#define JZ_LCD_CTRL_ENABLE BIT(3)
-#define JZ_LCD_CTRL_BPP_1 0x0
-#define JZ_LCD_CTRL_BPP_2 0x1
-#define JZ_LCD_CTRL_BPP_4 0x2
-#define JZ_LCD_CTRL_BPP_8 0x3
-#define JZ_LCD_CTRL_BPP_15_16 0x4
-#define JZ_LCD_CTRL_BPP_18_24 0x5
-
-#define JZ_LCD_CMD_SOF_IRQ BIT(15)
-#define JZ_LCD_CMD_EOF_IRQ BIT(16)
-#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
-
-#define JZ_LCD_SYNC_MASK 0x3ff
-
-#define JZ_LCD_STATE_DISABLED BIT(0)
+#include "jz4740_lcd.h"
struct jzfb_framedesc {
uint32_t next;
diff --git a/drivers/video/jz4740_lcd.h b/drivers/video/jz4740_lcd.h
new file mode 100644
index 0000000..ac7caa5
--- /dev/null
+++ b/drivers/video/jz4740_lcd.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4720/JZ4740 SoC LCD framebuffer driver
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __JZ4740_LCD_H__
+#define __JZ4740_LCD_H__
+
+#include <linux/bitops.h>
+
+#define JZ_REG_LCD_CFG 0x00
+#define JZ_REG_LCD_VSYNC 0x04
+#define JZ_REG_LCD_HSYNC 0x08
+#define JZ_REG_LCD_VAT 0x0C
+#define JZ_REG_LCD_DAH 0x10
+#define JZ_REG_LCD_DAV 0x14
+#define JZ_REG_LCD_PS 0x18
+#define JZ_REG_LCD_CLS 0x1C
+#define JZ_REG_LCD_SPL 0x20
+#define JZ_REG_LCD_REV 0x24
+#define JZ_REG_LCD_CTRL 0x30
+#define JZ_REG_LCD_STATE 0x34
+#define JZ_REG_LCD_IID 0x38
+#define JZ_REG_LCD_DA0 0x40
+#define JZ_REG_LCD_SA0 0x44
+#define JZ_REG_LCD_FID0 0x48
+#define JZ_REG_LCD_CMD0 0x4C
+#define JZ_REG_LCD_DA1 0x50
+#define JZ_REG_LCD_SA1 0x54
+#define JZ_REG_LCD_FID1 0x58
+#define JZ_REG_LCD_CMD1 0x5C
+
+#define JZ_LCD_CFG_SLCD BIT(31)
+#define JZ_LCD_CFG_PS_DISABLE BIT(23)
+#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
+#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
+#define JZ_LCD_CFG_REV_DISABLE BIT(20)
+#define JZ_LCD_CFG_HSYNCM BIT(19)
+#define JZ_LCD_CFG_PCLKM BIT(18)
+#define JZ_LCD_CFG_INV BIT(17)
+#define JZ_LCD_CFG_SYNC_DIR BIT(16)
+#define JZ_LCD_CFG_PS_POLARITY BIT(15)
+#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
+#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
+#define JZ_LCD_CFG_REV_POLARITY BIT(12)
+#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
+#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
+#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
+#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
+#define JZ_LCD_CFG_18_BIT BIT(7)
+#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
+#define JZ_LCD_CFG_MODE_MASK 0xf
+
+#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
+#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
+#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
+#define JZ_LCD_CTRL_RGB555 BIT(27)
+#define JZ_LCD_CTRL_OFUP BIT(26)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
+#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
+#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
+#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
+#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
+#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
+#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
+#define JZ_LCD_CTRL_DD_IRQ BIT(8)
+#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
+#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
+#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
+#define JZ_LCD_CTRL_DISABLE BIT(4)
+#define JZ_LCD_CTRL_ENABLE BIT(3)
+#define JZ_LCD_CTRL_BPP_1 0x0
+#define JZ_LCD_CTRL_BPP_2 0x1
+#define JZ_LCD_CTRL_BPP_4 0x2
+#define JZ_LCD_CTRL_BPP_8 0x3
+#define JZ_LCD_CTRL_BPP_15_16 0x4
+#define JZ_LCD_CTRL_BPP_18_24 0x5
+
+#define JZ_LCD_CMD_SOF_IRQ BIT(15)
+#define JZ_LCD_CMD_EOF_IRQ BIT(16)
+#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
+
+#define JZ_LCD_SYNC_MASK 0x3ff
+
+#define JZ_LCD_STATE_DISABLED BIT(0)
+
+#endif /*__JZ4740_LCD_H__*/
--
1.7.4.1

View File

@ -1,14 +1,15 @@
From e4334870d2348cc326cb9135e9da83cdbec9e95e Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:45:19 +0800
Subject: [PATCH 18/32] 901-ubi-Read-only-the-vid-header-instead-of-the-whole-pa.patch
From 73aab29ddc44a3e1a7156473ad5bc9cd80704274 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 15 Mar 2011 12:49:15 +0100
Subject: [PATCH 01/28] ubi: Read only the vid header instead of the whole
page
---
drivers/mtd/ubi/io.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8c1b1c7..b0346e4 100644
index f20b6f2..e66079d 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -1031,7 +1031,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
@ -17,9 +18,9 @@ index 8c1b1c7..b0346e4 100644
read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
- ubi->vid_hdr_alsize);
+ UBI_VID_HDR_SIZE + ubi->vid_hdr_shift);
if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
return read_err;
--
1.7.4.1
1.7.5.4

View File

@ -1,48 +1,47 @@
From ecd72bc68f9b9a39cb0f1ec456787c61f03be978 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
Date: Tue, 13 Sep 2011 16:07:41 +0800
Subject: [PATCH 13/32] Add jz4740 udc driver
From 537082e01849ca85227c5b462b8ac9aceb11b77a Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 24 Apr 2010 12:18:46 +0200
Subject: [PATCH 02/28] Add jz4740 udc driver
History:
- driver by Ingenic
- patch by Lars-Peter Clausen.
- updated to 3.1 by Maarten ter Huurne
---
drivers/usb/gadget/Kconfig | 13 +
drivers/usb/gadget/Kconfig | 8 +
drivers/usb/gadget/Makefile | 1 +
drivers/usb/gadget/gadget_chips.h | 8 +
drivers/usb/gadget/jz4740_udc.c | 2188 +++++++++++++++++++++++++++++++++++++
drivers/usb/gadget/gadget_chips.h | 3 +
drivers/usb/gadget/jz4740_udc.c | 2199 +++++++++++++++++++++++++++++++++++++
drivers/usb/gadget/jz4740_udc.h | 101 ++
5 files changed, 2311 insertions(+), 0 deletions(-)
5 files changed, 2312 insertions(+), 0 deletions(-)
create mode 100644 drivers/usb/gadget/jz4740_udc.c
create mode 100644 drivers/usb/gadget/jz4740_udc.h
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 029e288..750480c 100644
index 23a4473..89b7d28 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -121,6 +121,19 @@ choice
#
# Integrated controllers
#
+config USB_GADGET_JZ4740
+ boolean "JZ4740 UDC"
@@ -178,6 +178,14 @@ config USB_FUSB300
help
Faraday usb device controller FUSB300 driver
+config USB_JZ4740
+ tristate "JZ4740 UDC"
+ depends on MACH_JZ4740
+ select USB_GADGET_SELECTED
+ select USB_GADGET_DUALSPEED
+ help
+ Select this to support the Ingenic JZ4740 processor
+ high speed USB device controller.
+ Select this to support the Ingenic JZ4740 processor
+ high speed USB device controller.
+
+config USB_JZ4740
+ tristate
+ depends on USB_GADGET_JZ4740
+ default USB_GADGET
config USB_GADGET_AT91
boolean "Atmel AT91 USB Device Port"
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 4fe92b1..e0e2dd8 100644
index b54ac61..2d65f6e 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o
mv_udc-y := mv_udc_core.o mv_udc_phy.o
@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o
mv_udc-y := mv_udc_core.o
obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
+obj-$(CONFIG_USB_JZ4740) += jz4740_udc.o
@ -50,37 +49,32 @@ index 4fe92b1..e0e2dd8 100644
#
# USB gadget drivers
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index bcdac7c..12f5205 100644
index a8855d0..99f1580 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -15,6 +15,12 @@
#ifndef __GADGET_CHIPS_H
#define __GADGET_CHIPS_H
+#ifdef CONFIG_USB_GADGET_JZ4740
+#define gadget_is_jz4740(g) !strcmp("ingenic_hsusb", (g)->name)
+#else
+#define gadget_is_jz4740(g) 0
+#endif
+
#ifdef CONFIG_USB_GADGET_NET2280
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
#else
@@ -223,6 +229,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x29;
else if (gadget_is_s3c_hsudc(gadget))
return 0x30;
@@ -36,6 +36,7 @@
#define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name))
#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name))
+#define gadget_is_jz4740(g) (!strcmp("ingenic_hsusb", (g)->name))
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name))
#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
@@ -118,6 +119,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x31;
else if (gadget_is_dwc3(gadget))
return 0x32;
+ else if (gadget_is_jz4740(gadget))
+ return 0x31;
+ return 0x33;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/jz4740_udc.c b/drivers/usb/gadget/jz4740_udc.c
new file mode 100644
index 0000000..528fd57
index 0000000..8d36434
--- /dev/null
+++ b/drivers/usb/gadget/jz4740_udc.c
@@ -0,0 +1,2188 @@
@@ -0,0 +1,2199 @@
+/*
+ * linux/drivers/usb/gadget/jz4740_udc.c
+ *
@ -243,6 +237,9 @@ index 0000000..528fd57
+/*
+ * Local declarations.
+ */
+static int jz4740_udc_start(struct usb_gadget_driver *driver,
+ int (*bind)(struct usb_gadget *));
+static int jz4740_udc_stop(struct usb_gadget_driver *driver);
+static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep);
+static void jz4740_handle_ep0(struct jz4740_udc *dev, uint32_t intr);
+
@ -496,7 +493,7 @@ index 0000000..528fd57
+ * Register entry point for the peripheral controller driver.
+ */
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int jz4740_udc_start(struct usb_gadget_driver *driver,
+ int (*bind)(struct usb_gadget *))
+{
+ struct jz4740_udc *dev = &jz4740_udc_controller;
@ -533,7 +530,6 @@ index 0000000..528fd57
+
+ return 0;
+}
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+
+static void stop_activity(struct jz4740_udc *dev,
+ struct usb_gadget_driver *driver)
@ -572,7 +568,7 @@ index 0000000..528fd57
+/*
+ * Unregister entry point for the peripheral controller driver.
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int jz4740_udc_stop(struct usb_gadget_driver *driver)
+{
+ struct jz4740_udc *dev = &jz4740_udc_controller;
+ unsigned long flags;
@ -599,8 +595,6 @@ index 0000000..528fd57
+ return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+
+/** Write request to FIFO (max write == maxp size)
@ -2019,6 +2013,8 @@ index 0000000..528fd57
+ .get_frame = jz4740_udc_get_frame,
+ .wakeup = jz4740_udc_wakeup,
+ .pullup = jz4740_udc_pullup,
+ .start = jz4740_udc_start,
+ .stop = jz4740_udc_stop,
+};
+
+static struct usb_ep_ops jz4740_ep_ops = {
@ -2170,9 +2166,15 @@ index 0000000..528fd57
+ jz4740_udc->irq = platform_get_irq(pdev, 0);
+ ret = request_irq(jz4740_udc->irq, jz4740_udc_irq, 0, pdev->name,
+ jz4740_udc);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+ goto err_iounmap;
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+ goto err_iounmap;
+ }
+
+ ret = usb_add_gadget_udc(&pdev->dev, &jz4740_udc->gadget);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add gadget: %d\n", ret);
+ goto err_free_irq;
+ }
+
+ udc_disable(jz4740_udc);
@ -2180,6 +2182,8 @@ index 0000000..528fd57
+
+ return 0;
+
+err_free_irq:
+ free_irq(jz4740_udc->irq, pdev);
+err_iounmap:
+ iounmap(jz4740_udc->base);
+err_release_mem_region:
@ -2197,6 +2201,7 @@ index 0000000..528fd57
+{
+ struct jz4740_udc *dev = platform_get_drvdata(pdev);
+
+ usb_del_gadget_udc(&dev->gadget);
+ if (dev->driver)
+ return -EBUSY;
+
@ -2377,5 +2382,5 @@ index 0000000..53fd1da
+
+#endif /* __USB_GADGET_JZ4740_H__ */
--
1.7.4.1
1.7.5.4

View File

@ -1,17 +1,18 @@
From a525f2fabe86dfd4a1acc057afcb31de319ca3e5 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:45:39 +0800
Subject: [PATCH 19/32] 902-NAND-Optimize-NAND_ECC_HW_OOB_FIRST-read.patch
From b971c50dc50c07f981a1619f977e7509db9c4eac Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 26 Feb 2011 15:30:07 +0100
Subject: [PATCH 03/28] NAND: Optimize NAND_ECC_HW_OOB_FIRST read
Avoid sending unnecessary READ commands to the chip.
---
drivers/mtd/nand/nand_base.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a46e9bb..a9afe23 100644
index 3ed9c5e..184aa93 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1305,9 +1305,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
@@ -1294,9 +1294,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
uint8_t *ecc_calc = chip->buffers->ecccalc;
/* Read the OOB area first */
@ -30,7 +31,7 @@ index a46e9bb..a9afe23 100644
for (i = 0; i < chip->ecc.total; i++)
ecc_code[i] = chip->oob_poi[eccpos[i]];
@@ -1477,7 +1483,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
@@ -1465,7 +1471,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (realpage != chip->pagebuf || oob) {
bufpoi = aligned ? buf : chip->buffers->databuf;
@ -40,5 +41,5 @@ index a46e9bb..a9afe23 100644
sndcmd = 0;
}
--
1.7.4.1
1.7.5.4

View File

@ -1,7 +1,8 @@
From e4e1ca7caccf399366d8dbbf6539217e2c7ea852 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:45:59 +0800
Subject: [PATCH 20/32] 903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_HW_O.patch
From 297d8a7bdfb755778d4189ca2861dd2a6125e972 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 15 Mar 2011 12:33:41 +0100
Subject: [PATCH 04/28] NAND: Add support for subpage reads for
NAND_ECC_HW_OOB_FIRST
---
drivers/mtd/nand/nand_base.c | 78 ++++++++++++++++++++++++++++++++++++++++--
@ -9,11 +10,11 @@ Subject: [PATCH 20/32] 903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_HW_O.
2 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a9afe23..f1214af 100644
index 184aa93..0131e84 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1156,7 +1156,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @bufpoi: buffer to store read data
@@ -1143,7 +1143,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @bufpoi: buffer to store read data
*/
static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
@ -21,11 +22,10 @@ index a9afe23..f1214af 100644
{
int start_step, end_step, num_steps;
uint32_t *eccpos = chip->ecc.layout->eccpos;
@@ -1334,6 +1334,75 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
return 0;
@@ -1324,6 +1324,75 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
}
+ /**
/**
+ * nand_read_subpage_hwecc_oob_first - [REPLACABLE] hw ecc based sub-page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
@ -94,10 +94,11 @@ index a9afe23..f1214af 100644
+ return 0;
+}
+
/**
* nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
* @mtd: mtd info structure
@@ -1494,7 +1563,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
+/**
* nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
* @mtd: mtd info structure
* @chip: nand chip info structure
@@ -1482,7 +1551,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
bufpoi, page);
else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
ret = chip->ecc.read_subpage(mtd, chip,
@ -106,8 +107,8 @@ index a9afe23..f1214af 100644
else
ret = chip->ecc.read_page(mtd, chip, bufpoi,
page);
@@ -3286,8 +3355,11 @@ int nand_scan_tail(struct mtd_info *mtd)
"Hardware ECC not possible\n");
@@ -3292,8 +3361,11 @@ int nand_scan_tail(struct mtd_info *mtd)
"hardware ECC not possible\n");
BUG();
}
- if (!chip->ecc.read_page)
@ -118,9 +119,9 @@ index a9afe23..f1214af 100644
+ }
case NAND_ECC_HW:
/* Use standard hwecc read page function ? */
/* Use standard hwecc read page function? */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c2b9ac4..85e8847 100644
index 904131b..9034100 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -211,9 +211,9 @@ typedef enum {
@ -130,13 +131,13 @@ index c2b9ac4..85e8847 100644
-/* Large page NAND with SOFT_ECC should support subpage reads */
-#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
- && (chip->page_shift > 9))
+/* Large page NAND with read_subpage should support subpage reads */
+/* Large page NAND with read_subpage set should support subpage reads */
+#define NAND_SUBPAGE_READ(chip) (((chip)->ecc.read_subpage) \
+ && ((chip)->page_shift > 9))
/* Mask to zero out the chip options, which come from the id table */
#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR)
@@ -377,7 +377,7 @@ struct nand_ecc_ctrl {
@@ -367,7 +367,7 @@ struct nand_ecc_ctrl {
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page);
int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
@ -144,7 +145,7 @@ index c2b9ac4..85e8847 100644
+ uint32_t offs, uint32_t len, uint8_t *buf, int page);
void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf);
int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page,
int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
--
1.7.4.1
1.7.5.4

View File

@ -1,17 +1,17 @@
From 5fa159fe903240a78136ba90bfefc91d899fcfe3 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:46:14 +0800
Subject: [PATCH 21/32] 904-NAND-Optimize-reading-the-eec-data-for-the-JZ4740-ev.patch
From 4f28237a750afd1112b6f1266d36f8b718efe89c Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Tue, 6 Mar 2012 11:19:26 +0800
Subject: [PATCH 05/28] NAND-Optimize-reading-the-eec-data-for-the-JZ4740
---
drivers/mtd/nand/nand_base.c | 14 ++++----------
1 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index f1214af..37c0cfb 100644
index 0131e84..74b8cce 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1306,8 +1306,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
@@ -1295,8 +1295,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
/* Read the OOB area first */
if (mtd->writesize > 512) {
@ -22,7 +22,7 @@ index f1214af..37c0cfb 100644
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1);
} else {
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
@@ -1315,9 +1315,6 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
@@ -1304,9 +1304,6 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
}
@ -32,7 +32,7 @@ index f1214af..37c0cfb 100644
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
int stat;
@@ -1372,8 +1369,8 @@ static int nand_read_subpage_hwecc_oob_first(struct mtd_info *mtd, struct nand_c
@@ -1361,8 +1358,8 @@ static int nand_read_subpage_hwecc_oob_first(struct mtd_info *mtd, struct nand_c
/* Read the OOB area first */
if (mtd->writesize > 512) {
@ -43,7 +43,7 @@ index f1214af..37c0cfb 100644
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
} else {
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
@@ -1381,9 +1378,6 @@ static int nand_read_subpage_hwecc_oob_first(struct mtd_info *mtd, struct nand_c
@@ -1370,9 +1367,6 @@ static int nand_read_subpage_hwecc_oob_first(struct mtd_info *mtd, struct nand_c
chip->cmdfunc(mtd, NAND_CMD_READ0, data_col_addr, page);
}
@ -54,5 +54,5 @@ index f1214af..37c0cfb 100644
for (i = eccbytes * start_step; num_steps; num_steps--, i += eccbytes, p += eccsize) {
--
1.7.4.1
1.7.5.4

View File

@ -0,0 +1,426 @@
From d5814bdb661d3dac61422f8f69e459be884c9a9d Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Tue, 2 Aug 2011 10:49:28 +0200
Subject: [PATCH 06/28] MTD: NAND: JZ4740: Multi-bank support with
autodetection
The platform data can now specify which external memory banks to probe
for NAND chips, and in which order. Banks that contain a NAND are used
and the other banks are freed.
Squashed version of development done in jz-2.6.38 branch.
Original patch by Lars-Peter Clausen with some bug fixes from me.
Thanks to Paul Cercueil for the initial autodetection patch.
---
arch/mips/include/asm/mach-jz4740/jz4740_nand.h | 4 +
arch/mips/jz4740/platform.c | 20 ++-
drivers/mtd/nand/jz4740_nand.c | 228 +++++++++++++++++++----
3 files changed, 215 insertions(+), 37 deletions(-)
diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
index bb5b9a4..986982d 100644
--- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
+++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
@@ -19,6 +19,8 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#define JZ_NAND_NUM_BANKS 4
+
struct jz_nand_platform_data {
int num_partitions;
struct mtd_partition *partitions;
@@ -27,6 +29,8 @@ struct jz_nand_platform_data {
unsigned int busy_gpio;
+ unsigned char banks[JZ_NAND_NUM_BANKS];
+
void (*ident_callback)(struct platform_device *, struct nand_chip *,
struct mtd_partition **, int *num_partitions);
};
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 10929e2..e342ed4 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -157,11 +157,29 @@ static struct resource jz4740_nand_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- .name = "bank",
+ .name = "bank1",
.start = 0x18000000,
.end = 0x180C0000 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .name = "bank2",
+ .start = 0x14000000,
+ .end = 0x140C0000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "bank3",
+ .start = 0x0C000000,
+ .end = 0x0C0C0000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "bank4",
+ .start = 0x08000000,
+ .end = 0x080C0000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
};
struct platform_device jz4740_nand_device = {
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index e266407..b254b99 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -52,9 +52,10 @@
#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
+#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa
-#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
#define JZ_NAND_MEM_CMD_OFFSET 0x08000
+#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
struct jz_nand {
struct mtd_info mtd;
@@ -62,8 +63,11 @@ struct jz_nand {
void __iomem *base;
struct resource *mem;
- void __iomem *bank_base;
- struct resource *bank_mem;
+ unsigned char banks[JZ_NAND_NUM_BANKS];
+ void __iomem *bank_base[JZ_NAND_NUM_BANKS];
+ struct resource *bank_mem[JZ_NAND_NUM_BANKS];
+
+ int selected_bank;
struct jz_nand_platform_data *pdata;
bool is_reading;
@@ -74,26 +78,50 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
return container_of(mtd, struct jz_nand, mtd);
}
+static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ struct nand_chip *chip = mtd->priv;
+ uint32_t ctrl;
+ int banknr;
+
+ ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
+ ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK;
+
+ if (chipnr == -1) {
+ banknr = -1;
+ } else {
+ banknr = nand->banks[chipnr] - 1;
+ chip->IO_ADDR_R = nand->bank_base[banknr];
+ chip->IO_ADDR_W = nand->bank_base[banknr];
+ }
+ writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
+
+ nand->selected_bank = banknr;
+}
+
static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct nand_chip *chip = mtd->priv;
uint32_t reg;
+ void __iomem *bank_base = nand->bank_base[nand->selected_bank];
+
+ BUG_ON(nand->selected_bank < 0);
if (ctrl & NAND_CTRL_CHANGE) {
BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
if (ctrl & NAND_ALE)
- chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET;
+ bank_base += JZ_NAND_MEM_ADDR_OFFSET;
else if (ctrl & NAND_CLE)
- chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET;
- else
- chip->IO_ADDR_W = nand->bank_base;
+ bank_base += JZ_NAND_MEM_CMD_OFFSET;
+ chip->IO_ADDR_W = bank_base;
reg = readl(nand->base + JZ_REG_NAND_CTRL);
if (ctrl & NAND_NCE)
- reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
+ reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
else
- reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
+ reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
writel(reg, nand->base + JZ_REG_NAND_CTRL);
}
if (dat != NAND_CMD_NONE)
@@ -252,7 +280,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
}
static int jz_nand_ioremap_resource(struct platform_device *pdev,
- const char *name, struct resource **res, void __iomem **base)
+ const char *name, struct resource **res, void *__iomem *base)
{
int ret;
@@ -288,6 +316,90 @@ err:
return ret;
}
+static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base)
+{
+ iounmap(base);
+ release_mem_region(res->start, resource_size(res));
+}
+
+static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) {
+ int ret;
+ int gpio;
+ char gpio_name[9];
+ char res_name[6];
+ uint32_t ctrl;
+ struct mtd_info *mtd = &nand->mtd;
+ struct nand_chip *chip = &nand->chip;
+
+ /* Request GPIO port. */
+ gpio = JZ_GPIO_MEM_CS0 + bank - 1;
+ sprintf(gpio_name, "NAND CS%d", bank);
+ ret = gpio_request(gpio, gpio_name);
+ if (ret) {
+ dev_warn(&pdev->dev,
+ "Failed to request %s gpio %d: %d\n",
+ gpio_name, gpio, ret);
+ goto notfound_gpio;
+ }
+
+ /* Request I/O resource. */
+ sprintf(res_name, "bank%d", bank);
+ ret = jz_nand_ioremap_resource(pdev, res_name,
+ &nand->bank_mem[bank - 1],
+ &nand->bank_base[bank - 1]);
+ if (ret)
+ goto notfound_resource;
+
+ /* Enable chip in bank. */
+ jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0);
+ ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
+ ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
+ writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
+
+ if (chipnr == 0) {
+ /* Detect first chip. */
+ ret = nand_scan_ident(mtd, 1, NULL);
+ if (ret)
+ goto notfound_id;
+
+ /* Retrieve the IDs from the first chip. */
+ chip->select_chip(mtd, 0);
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+ *nand_maf_id = chip->read_byte(mtd);
+ *nand_dev_id = chip->read_byte(mtd);
+ } else {
+ /* Detect additional chip. */
+ chip->select_chip(mtd, chipnr);
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+ if (*nand_maf_id != chip->read_byte(mtd)
+ || *nand_dev_id != chip->read_byte(mtd)) {
+ ret = -ENODEV;
+ goto notfound_id;
+ }
+
+ /* Update size of the MTD. */
+ chip->numchips++;
+ mtd->size += chip->chipsize;
+ }
+
+ dev_info(&pdev->dev, "Found chip %i on bank %i\n", chipnr, bank);
+ return 0;
+
+notfound_id:
+ dev_info(&pdev->dev, "No chip found on bank %i\n", bank);
+ ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1));
+ writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
+ jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
+ jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
+ nand->bank_base[bank - 1]);
+notfound_resource:
+ gpio_free(gpio);
+notfound_gpio:
+ return ret;
+}
+
static int __devinit jz_nand_probe(struct platform_device *pdev)
{
int ret;
@@ -295,6 +407,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
struct nand_chip *chip;
struct mtd_info *mtd;
struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+ size_t chipnr, bank_idx;
+ uint8_t nand_maf_id = 0, nand_dev_id = 0;
nand = kzalloc(sizeof(*nand), GFP_KERNEL);
if (!nand) {
@@ -305,10 +419,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
if (ret)
goto err_free;
- ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
- &nand->bank_base);
- if (ret)
- goto err_iounmap_mmio;
if (pdata && gpio_is_valid(pdata->busy_gpio)) {
ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
@@ -316,7 +426,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Failed to request busy gpio %d: %d\n",
pdata->busy_gpio, ret);
- goto err_iounmap_mem;
+ goto err_iounmap_mmio;
}
}
@@ -338,22 +448,51 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
chip->chip_delay = 50;
chip->cmd_ctrl = jz_nand_cmd_ctrl;
+ chip->select_chip = jz_nand_select_chip;
if (pdata && gpio_is_valid(pdata->busy_gpio))
chip->dev_ready = jz_nand_dev_ready;
- chip->IO_ADDR_R = nand->bank_base;
- chip->IO_ADDR_W = nand->bank_base;
-
nand->pdata = pdata;
platform_set_drvdata(pdev, nand);
- writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL);
-
- ret = nand_scan_ident(mtd, 1, NULL);
- if (ret) {
- dev_err(&pdev->dev, "Failed to scan nand\n");
- goto err_gpio_free;
+ /* We are going to autodetect NAND chips in the banks specified in the
+ * platform data. Although nand_scan_ident() can detect multiple chips,
+ * it requires those chips to be numbered consecuitively, which is not
+ * always the case for external memory banks. And a fixed chip-to-bank
+ * mapping is not practical either, since for example Dingoo units
+ * produced at different times have NAND chips in different banks.
+ */
+ chipnr = 0;
+ for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) {
+ unsigned char bank;
+
+ /* If there is no platform data, look for NAND in bank 1,
+ * which is the most likely bank since it is the only one
+ * that can be booted from.
+ */
+ bank = pdata ? pdata->banks[bank_idx] : bank_idx ^ 1;
+ if (bank == 0)
+ break;
+ if (bank > JZ_NAND_NUM_BANKS) {
+ dev_warn(&pdev->dev,
+ "Skipping non-existing bank: %d\n", bank);
+ continue;
+ }
+ /* The detection routine will directly or indirectly call
+ * jz_nand_select_chip(), so nand->banks has to contain the
+ * bank we're checking.
+ */
+ nand->banks[chipnr] = bank;
+ if (jz_nand_detect_bank(pdev, nand, bank, chipnr,
+ &nand_maf_id, &nand_dev_id) == 0)
+ chipnr++;
+ else
+ nand->banks[chipnr] = 0;
+ }
+ if (chipnr == 0) {
+ dev_err(&pdev->dev, "No NAND chips found\n");
+ goto err_gpio_busy;
}
if (pdata && pdata->ident_callback) {
@@ -363,8 +502,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
ret = nand_scan_tail(mtd);
if (ret) {
- dev_err(&pdev->dev, "Failed to scan nand\n");
- goto err_gpio_free;
+ dev_err(&pdev->dev, "Failed to scan NAND\n");
+ goto err_unclaim_banks;
}
ret = mtd_device_parse_register(mtd, NULL, 0,
@@ -381,14 +520,21 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
return 0;
err_nand_release:
- nand_release(&nand->mtd);
-err_gpio_free:
+ nand_release(mtd);
+err_unclaim_banks:
+ while (chipnr--) {
+ unsigned char bank = nand->banks[chipnr];
+ gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
+ jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
+ nand->bank_base[bank - 1]);
+ }
+ writel(0, nand->base + JZ_REG_NAND_CTRL);
+err_gpio_busy:
+ if (pdata && gpio_is_valid(pdata->busy_gpio))
+ gpio_free(pdata->busy_gpio);
platform_set_drvdata(pdev, NULL);
- gpio_free(pdata->busy_gpio);
-err_iounmap_mem:
- iounmap(nand->bank_base);
err_iounmap_mmio:
- iounmap(nand->base);
+ jz_nand_iounmap_resource(nand->mem, nand->base);
err_free:
kfree(nand);
return ret;
@@ -397,16 +543,26 @@ err_free:
static int __devexit jz_nand_remove(struct platform_device *pdev)
{
struct jz_nand *nand = platform_get_drvdata(pdev);
+ struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+ size_t i;
nand_release(&nand->mtd);
/* Deassert and disable all chips */
writel(0, nand->base + JZ_REG_NAND_CTRL);
- iounmap(nand->bank_base);
- release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem));
- iounmap(nand->base);
- release_mem_region(nand->mem->start, resource_size(nand->mem));
+ for (i = 0; i < JZ_NAND_NUM_BANKS; ++i) {
+ unsigned char bank = nand->banks[i];
+ if (bank != 0) {
+ jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
+ nand->bank_base[bank - 1]);
+ gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
+ }
+ }
+ if (pdata && gpio_is_valid(pdata->busy_gpio))
+ gpio_free(pdata->busy_gpio);
+
+ jz_nand_iounmap_resource(nand->mem, nand->base);
platform_set_drvdata(pdev, NULL);
kfree(nand);
--
1.7.5.4

View File

@ -1,7 +1,7 @@
From d7a92f8ccdca40672a2a242c756fb52c31b2bdba Mon Sep 17 00:00:00 2001
From 2248fb9c47fe7e72c735d6c16aba27bf92e1673a Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 1 Aug 2010 21:19:40 +0200
Subject: [PATCH 12/32] Add ili8960 lcd driver
Subject: [PATCH 07/28] Add ili8960 lcd driver
---
drivers/video/backlight/Kconfig | 7 +
@ -11,7 +11,7 @@ Subject: [PATCH 12/32] Add ili8960 lcd driver
create mode 100644 drivers/video/backlight/ili8960.c
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 2d93c8d..2fad528 100644
index 278aeaa..f617883 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -59,6 +59,13 @@ config LCD_LTV350QV
@ -29,7 +29,7 @@ index 2d93c8d..2fad528 100644
tristate
help
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index ee72adb..c7af746 100644
index fdd1fc4..01ec378 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
@ -310,5 +310,5 @@ index 0000000..1438e92
+MODULE_DESCRIPTION("LCD driver for Ilitek ili8960");
+MODULE_ALIAS("spi:ili8960");
--
1.7.4.1
1.7.5.4

View File

@ -1,7 +1,8 @@
From 1133e48ddc4c3082dfa78606cff16d3c3bde84c4 Mon Sep 17 00:00:00 2001
From e5f25e25ed6c0478cbba7a32891b911e3183dad4 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 13 Oct 2010 01:17:24 +0200
Subject: [PATCH 22/32] qi_lb60: Don't use 3-wire spi mode for the display for now
Subject: [PATCH 08/28] qi_lb60: Don't use 3-wire spi mode for the display for
now
The spi_gpio driver does not support 3-wire mode.
---
@ -21,5 +22,5 @@ index c3b04be..b622941 100644
};
--
1.7.4.1
1.7.5.4

View File

@ -1,15 +1,31 @@
From ab59753a9df09b990822b15d2593c5c98905684c Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
Date: Wed, 14 Sep 2011 14:29:51 +0800
Subject: [PATCH 27/32] Add DEVMEM support
From 4003b9a2c05f4d0d37535c3dffbf4a7b47d5c36c Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Wed, 8 Sep 2010 02:31:19 +0200
Subject: [PATCH 09/28] /dev/mem: Add kernel config option to omit this
device.
Omitting this device prevents software from accessing the hardware directly, which can cause trouble if the kernel accesses the same hardware.
It also saves some space on embedded systems.
---
drivers/char/Kconfig | 10 ++++++++++
drivers/char/mem.c | 17 +++++++++++++++++
2 files changed, 27 insertions(+), 0 deletions(-)
arch/x86/Kconfig.debug | 1 +
drivers/char/Kconfig | 10 ++++++++++
drivers/char/mem.c | 17 +++++++++++++++++
3 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index bf56e17..0c97d51 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -7,6 +7,7 @@ source "lib/Kconfig.debug"
config STRICT_DEVMEM
bool "Filter access to /dev/mem"
+ depends on DEVMEM
---help---
If this option is disabled, you allow userspace (root) access to all
of memory, including kernel and userspace memory. Accidental
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 49502bc..770f678 100644
index 4364303..a2e462e 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -6,6 +6,16 @@ menu "Character devices"
@ -30,10 +46,10 @@ index 49502bc..770f678 100644
bool "/dev/kmem virtual device support"
default y
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 8fc04b4..eb78f37 100644
index 1451790..a6020ca 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -86,6 +86,8 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
@@ -87,6 +87,8 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
{
}
@ -42,7 +58,7 @@ index 8fc04b4..eb78f37 100644
/*
* This funcion reads the *physical* memory. The f_pos points directly to the
* memory location.
@@ -209,6 +211,10 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
@@ -210,6 +212,10 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
return written;
}
@ -53,7 +69,7 @@ index 8fc04b4..eb78f37 100644
int __weak phys_mem_access_prot_allowed(struct file *file,
unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
{
@@ -330,6 +336,8 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
@@ -331,6 +337,8 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
return 0;
}
@ -62,7 +78,7 @@ index 8fc04b4..eb78f37 100644
#ifdef CONFIG_DEVKMEM
static int mmap_kmem(struct file *file, struct vm_area_struct *vma)
{
@@ -693,6 +701,7 @@ static loff_t null_lseek(struct file *file, loff_t offset, int orig)
@@ -694,6 +702,7 @@ static loff_t null_lseek(struct file *file, loff_t offset, int orig)
return file->f_pos = 0;
}
@ -70,7 +86,7 @@ index 8fc04b4..eb78f37 100644
/*
* The memory devices use the full 32/64 bits of the offset, and so we cannot
* check against negative addresses: they are ok. The return value is weird,
@@ -725,11 +734,15 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
@@ -726,11 +735,15 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return ret;
}
@ -86,7 +102,7 @@ index 8fc04b4..eb78f37 100644
#define zero_lseek null_lseek
#define full_lseek null_lseek
@@ -739,6 +752,7 @@ static int open_port(struct inode * inode, struct file * filp)
@@ -740,6 +753,7 @@ static int open_port(struct inode * inode, struct file * filp)
#define open_kmem open_mem
#define open_oldmem open_mem
@ -94,7 +110,7 @@ index 8fc04b4..eb78f37 100644
static const struct file_operations mem_fops = {
.llseek = memory_lseek,
.read = read_mem,
@@ -747,6 +761,7 @@ static const struct file_operations mem_fops = {
@@ -748,6 +762,7 @@ static const struct file_operations mem_fops = {
.open = open_mem,
.get_unmapped_area = get_unmapped_area_mem,
};
@ -102,7 +118,7 @@ index 8fc04b4..eb78f37 100644
#ifdef CONFIG_DEVKMEM
static const struct file_operations kmem_fops = {
@@ -850,7 +865,9 @@ static const struct memdev {
@@ -851,7 +866,9 @@ static const struct memdev {
const struct file_operations *fops;
struct backing_dev_info *dev_info;
} devlist[] = {
@ -113,5 +129,5 @@ index 8fc04b4..eb78f37 100644
[2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi },
#endif
--
1.7.4.1
1.7.5.4

View File

@ -1,18 +1,18 @@
From b0b7794018b75ce33be133664fb58ab3e6efc2e8 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
Date: Wed, 14 Sep 2011 14:29:52 +0800
Subject: [PATCH 28/32] Add cpufreq support
From ca40c7542f0cd0e0dfa074bd4ccefc04b8561427 Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Tue, 2 Aug 2011 10:26:09 +0200
Subject: [PATCH 10/28] cpufreq_stats: Support runtime changes to frequency
table.
---
drivers/cpufreq/cpufreq_stats.c | 161 ++++++++++++++++++++-------------------
drivers/mmc/host/jz4740_mmc.c | 69 ++++++++++++++++-
2 files changed, 150 insertions(+), 80 deletions(-)
1 files changed, 83 insertions(+), 78 deletions(-)
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index faf7c52..86d032c 100644
index c5072a9..95f6eb9 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -20,6 +20,7 @@
@@ -21,6 +21,7 @@
#include <linux/kobject.h>
#include <linux/spinlock.h>
#include <linux/notifier.h>
@ -20,7 +20,7 @@ index faf7c52..86d032c 100644
#include <asm/cputime.h>
static spinlock_t cpufreq_stats_lock;
@@ -36,7 +37,7 @@ struct cpufreq_stats {
@@ -37,7 +38,7 @@ struct cpufreq_stats {
unsigned long long last_time;
unsigned int max_state;
unsigned int state_num;
@ -29,7 +29,7 @@ index faf7c52..86d032c 100644
cputime64_t *time_in_state;
unsigned int *freq_table;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
@@ -59,7 +60,7 @@ static int cpufreq_stats_update(unsigned int cpu)
@@ -60,7 +61,7 @@ static int cpufreq_stats_update(unsigned int cpu)
cur_time = get_jiffies_64();
spin_lock(&cpufreq_stats_lock);
stat = per_cpu(cpufreq_stats_table, cpu);
@ -38,7 +38,7 @@ index faf7c52..86d032c 100644
stat->time_in_state[stat->last_index] =
cputime64_add(stat->time_in_state[stat->last_index],
cputime_sub(cur_time, stat->last_time));
@@ -82,7 +83,7 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
@@ -83,7 +84,7 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0;
int i;
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
@ -47,7 +47,7 @@ index faf7c52..86d032c 100644
return 0;
cpufreq_stats_update(stat->cpu);
for (i = 0; i < stat->state_num; i++) {
@@ -100,7 +101,7 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
@@ -101,7 +102,7 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
int i, j;
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
@ -56,7 +56,7 @@ index faf7c52..86d032c 100644
return 0;
cpufreq_stats_update(stat->cpu);
len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
@@ -159,63 +160,35 @@ static struct attribute_group stats_attr_group = {
@@ -160,63 +161,35 @@ static struct attribute_group stats_attr_group = {
static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
{
int index;
@ -130,7 +130,7 @@ index faf7c52..86d032c 100644
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
unsigned int freq = table[i].frequency;
@@ -224,40 +197,73 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
@@ -225,40 +198,73 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
count++;
}
@ -222,7 +222,7 @@ index faf7c52..86d032c 100644
kfree(stat);
per_cpu(cpufreq_stats_table, cpu) = NULL;
return ret;
@@ -275,10 +281,12 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
@@ -276,10 +282,12 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
table = cpufreq_frequency_get_table(cpu);
if (!table)
return 0;
@ -239,7 +239,7 @@ index faf7c52..86d032c 100644
}
static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
@@ -298,21 +306,23 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
@@ -299,21 +307,23 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
old_index = stat->last_index;
new_index = freq_table_get_index(stat, freq->new);
@ -270,7 +270,7 @@ index faf7c52..86d032c 100644
spin_unlock(&cpufreq_stats_lock);
return 0;
}
@@ -328,9 +338,6 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
@@ -329,9 +339,6 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
case CPU_ONLINE_FROZEN:
cpufreq_update_policy(cpu);
break;
@ -280,7 +280,7 @@ index faf7c52..86d032c 100644
case CPU_DEAD:
case CPU_DEAD_FROZEN:
cpufreq_stats_free_table(cpu);
@@ -339,10 +346,9 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
@@ -340,10 +347,9 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
@ -293,7 +293,7 @@ index faf7c52..86d032c 100644
};
static struct notifier_block notifier_policy_block = {
@@ -389,7 +395,6 @@ static void __exit cpufreq_stats_exit(void)
@@ -390,7 +396,6 @@ static void __exit cpufreq_stats_exit(void)
unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
for_each_online_cpu(cpu) {
cpufreq_stats_free_table(cpu);
@ -301,125 +301,6 @@ index faf7c52..86d032c 100644
}
}
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 74218ad..6e40f1b 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/scatterlist.h>
#include <linux/clk.h>
+#include <linux/cpufreq.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
@@ -685,6 +686,60 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
}
+#ifdef CONFIG_CPU_FREQ
+
+static struct jz4740_mmc_host *cpufreq_host;
+
+static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ /* TODO: We only have to take action when the PLL freq changes:
+ the main dividers have no influence on the MSC device clock. */
+
+ if (val == CPUFREQ_PRECHANGE) {
+ mmc_claim_host(cpufreq_host->mmc);
+ clk_disable(cpufreq_host->clk);
+ } else if (val == CPUFREQ_POSTCHANGE) {
+ struct mmc_ios *ios = &cpufreq_host->mmc->ios;
+ if (ios->clock)
+ jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
+ if (ios->power_mode != MMC_POWER_OFF)
+ clk_enable(cpufreq_host->clk);
+ mmc_release_host(cpufreq_host->mmc);
+ }
+ return 0;
+}
+
+static struct notifier_block jz4740_mmc_cpufreq_nb = {
+ .notifier_call = jz4740_mmc_cpufreq_transition,
+};
+
+static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
+{
+ cpufreq_host = host;
+ return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void jz4740_mmc_cpufreq_unregister(void)
+{
+ cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+
+static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
+{
+ return 0;
+}
+
+static inline void jz4740_mmc_cpufreq_unregister(void)
+{
+}
+
+#endif
+
static const struct mmc_host_ops jz4740_mmc_ops = {
.request = jz4740_mmc_request,
.set_ios = jz4740_mmc_set_ios,
@@ -834,11 +889,18 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
goto err_free_host;
}
+ ret = jz4740_mmc_cpufreq_register(host);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register cpufreq transition notifier\n");
+ goto err_clk_put;
+ }
+
host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
ret = -ENOENT;
dev_err(&pdev->dev, "Failed to get base platform memory\n");
- goto err_clk_put;
+ goto err_cpufreq_unreg;
}
host->mem = request_mem_region(host->mem->start,
@@ -846,7 +908,7 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
if (!host->mem) {
ret = -EBUSY;
dev_err(&pdev->dev, "Failed to request base memory region\n");
- goto err_clk_put;
+ goto err_cpufreq_unreg;
}
host->base = ioremap_nocache(host->mem->start, resource_size(host->mem));
@@ -929,6 +991,8 @@ err_iounmap:
iounmap(host->base);
err_release_mem_region:
release_mem_region(host->mem->start, resource_size(host->mem));
+err_cpufreq_unreg:
+ jz4740_mmc_cpufreq_unregister();
err_clk_put:
clk_put(host->clk);
err_free_host:
@@ -958,6 +1022,7 @@ static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
iounmap(host->base);
release_mem_region(host->mem->start, resource_size(host->mem));
+ jz4740_mmc_cpufreq_unregister();
clk_put(host->clk);
platform_set_drvdata(pdev, NULL);
--
1.7.4.1
1.7.5.4

View File

@ -0,0 +1,358 @@
From 27ff621cd9a5347efda4be502abbef13a99146ce Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Sun, 29 Aug 2010 08:11:00 +0200
Subject: [PATCH 11/28] MIPS: JZ4740: Added setting of PLL rate and main
dividers.
This functionality makes a cpufreq driver possible.
Squashed version of the development done in the jz-2.6.39 branch.
---
arch/mips/jz4740/clock.c | 230 ++++++++++++++++++++++++++++++++++++++++++++--
arch/mips/jz4740/clock.h | 4 +
2 files changed, 224 insertions(+), 10 deletions(-)
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index 118a8a5..da423d1 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -1,5 +1,8 @@
/*
+ * Copyright (c) 2006-2007, Ingenic Semiconductor Inc.
* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ * Copyright (c) 2010, Ulrich Hecht <ulrich.hecht@gmail.com>
+ * Copyright (c) 2010, Maarten ter Huurne <maarten@treewalker.org>
* JZ4740 SoC clock support
*
* This program is free software; you can redistribute it and/or modify it
@@ -41,16 +44,20 @@
#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
-#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
#define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
-#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
#define JZ_CLOCK_CTRL_UDIV_OFFSET 23
#define JZ_CLOCK_CTRL_LDIV_OFFSET 16
#define JZ_CLOCK_CTRL_MDIV_OFFSET 12
#define JZ_CLOCK_CTRL_PDIV_OFFSET 8
#define JZ_CLOCK_CTRL_HDIV_OFFSET 4
#define JZ_CLOCK_CTRL_CDIV_OFFSET 0
+#define JZ_CLOCK_CTRL_UDIV_MASK (0x3f << JZ_CLOCK_CTRL_UDIV_OFFSET)
+#define JZ_CLOCK_CTRL_LDIV_MASK (0x1f << JZ_CLOCK_CTRL_LDIV_OFFSET)
+#define JZ_CLOCK_CTRL_MDIV_MASK (0x0f << JZ_CLOCK_CTRL_MDIV_OFFSET)
+#define JZ_CLOCK_CTRL_PDIV_MASK (0x0f << JZ_CLOCK_CTRL_PDIV_OFFSET)
+#define JZ_CLOCK_CTRL_HDIV_MASK (0x0f << JZ_CLOCK_CTRL_HDIV_OFFSET)
+#define JZ_CLOCK_CTRL_CDIV_MASK (0x0f << JZ_CLOCK_CTRL_CDIV_OFFSET)
#define JZ_CLOCK_GATE_UART0 BIT(0)
#define JZ_CLOCK_GATE_TCU BIT(1)
@@ -90,6 +97,7 @@
#define JZ_CLOCK_PLL_M_OFFSET 23
#define JZ_CLOCK_PLL_N_OFFSET 18
#define JZ_CLOCK_PLL_OD_OFFSET 16
+#define JZ_CLOCK_PLL_STABILIZE_OFFSET 0
#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
@@ -97,10 +105,15 @@
#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
+#define JZ_REG_EMC_RTCNT 0x88
+#define JZ_REG_EMC_RTCOR 0x8C
+
static void __iomem *jz_clock_base;
static spinlock_t jz_clock_lock;
static LIST_HEAD(jz_clocks);
+static void __iomem *jz_emc_base;
+
struct main_clk {
struct clk clk;
uint32_t div_offset;
@@ -204,25 +217,88 @@ static int jz_clk_ko_is_enabled(struct clk *clk)
return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
}
+static struct static_clk jz_clk_ext;
+
+static unsigned long jz_clk_pll_calc_rate(
+ unsigned int in_div, unsigned int feedback, unsigned int out_div)
+{
+ return ((jz_clk_ext.rate / in_div) * feedback) / out_div;
+}
+
+static void jz_clk_pll_calc_dividers(unsigned long rate,
+ unsigned int *in_div, unsigned int *feedback, unsigned int *out_div)
+{
+ unsigned int target;
+
+ /* The frequency after the input divider must be between 1 and 15 MHz.
+ The highest divider yields the best resolution. */
+ *in_div = jz_clk_ext.rate / 1000000;
+ if (*in_div >= 34)
+ *in_div = 33;
+
+ /* The frequency before the output divider must be between 100 and
+ 500 MHz. The lowest target rate is more energy efficient. */
+ if (rate < 25000000) {
+ *out_div = 4;
+ target = 25000000 * 4;
+ } else if (rate <= 50000000) {
+ *out_div = 4;
+ target = rate * 4;
+ } else if (rate <= 100000000) {
+ *out_div = 2;
+ target = rate * 2;
+ } else if (rate <= 500000000) {
+ *out_div = 1;
+ target = rate;
+ } else {
+ *out_div = 1;
+ target = 500000000;
+ }
+
+ /* Compute the feedback divider.
+ Since the divided input is at least 1 MHz and the target frequency
+ at most 500 MHz, the feedback will be at most 500 and will therefore
+ always fit in the 9-bit register.
+ Similarly, the divided input is at most 15 MHz and the target
+ frequency at least 100 MHz, so the feedback will be at least 6
+ where the minimum supported value is 2. */
+ *feedback = ((target / 1000) * *in_div) / (jz_clk_ext.rate / 1000);
+}
+
+static unsigned long jz_clk_pll_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int in_div, feedback, out_div;
+ /* The PLL frequency must be a multiple of 24 MHz, since the LCD pixel
+ * clock must be exactly 12 MHz for the TV-out to work.
+ * TODO: A multiple of 12 MHz for the PLL would work if the PLL would
+ * not be divided by 2 before being passed to the set of derived
+ * clocks that includes the LCD pixel clock.
+ * TODO: Systemwide decisions like this should be made by the board
+ * support code, so add some kind of hook for that.
+ */
+ unsigned long rate24 = (rate / 24000000) * 24000000;
+
+ jz_clk_pll_calc_dividers(rate24, &in_div, &feedback, &out_div);
+ return jz_clk_pll_calc_rate(in_div, feedback, out_div);
+}
+
static const int pllno[] = {1, 2, 2, 4};
static unsigned long jz_clk_pll_get_rate(struct clk *clk)
{
uint32_t val;
- int m;
- int n;
- int od;
+ unsigned int in_div, feedback, out_div;
val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
if (val & JZ_CLOCK_PLL_BYPASS)
return clk_get_rate(clk->parent);
- m = ((val >> 23) & 0x1ff) + 2;
- n = ((val >> 18) & 0x1f) + 2;
- od = (val >> 16) & 0x3;
+ feedback = ((val >> 23) & 0x1ff) + 2;
+ in_div = ((val >> 18) & 0x1f) + 2;
+ out_div = pllno[(val >> 16) & 0x3];
- return ((clk_get_rate(clk->parent) / n) * m) / pllno[od];
+ return jz_clk_pll_calc_rate(in_div, feedback, out_div);
}
static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
@@ -235,7 +311,77 @@ static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
return jz_clk_pll_get_rate(clk->parent) >> 1;
}
-static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
+
+static void sdram_set_pll(unsigned int pllin)
+{
+ unsigned int ns, sdramclock;
+
+ ns = 1000000000 / pllin;
+ sdramclock = (SDRAM_TREF / ns) / 64 + 1;
+ if (sdramclock > 0xff) sdramclock = 0xff;
+ /* Set refresh registers */
+ writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCOR);
+ writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCNT);
+}
+
+static int jz_clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int ctrl, plcr1;
+ unsigned int feedback, in_div, out_div, pllout, pllout2;
+
+ jz_clk_pll_calc_dividers(rate, &in_div, &feedback, &out_div);
+
+ ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+ pllout = jz_clk_pll_calc_rate(in_div, feedback, out_div);
+ pllout2 = (ctrl & JZ_CLOCK_CTRL_PLL_HALF) ? pllout : (pllout / 2);
+
+ /* Init UHC clock */
+ writel(pllout2 / 48000000 - 1, jz_clock_base + JZ_REG_CLOCK_UHC);
+
+ plcr1 = ((feedback - 2) << JZ_CLOCK_PLL_M_OFFSET) |
+ ((in_div - 2) << JZ_CLOCK_PLL_N_OFFSET) |
+ ((out_div - 1) << JZ_CLOCK_PLL_OD_OFFSET) |
+ (0x20 << JZ_CLOCK_PLL_STABILIZE_OFFSET) |
+ JZ_CLOCK_PLL_ENABLED;
+
+ sdram_set_pll(pllout);
+
+ /* LCD pixclock */
+ writel(pllout2 / 12000000 - 1, jz_clock_base + JZ_REG_CLOCK_LCD);
+
+ /* configure PLL */
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".align 5\n"
+ "sw %1,0(%0)\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ ".set reorder\n\t"
+ :
+ : "r" (jz_clock_base + JZ_REG_CLOCK_PLL), "r" (plcr1));
+
+ /* MtH: For some reason the MSC will have problems if this flag is not
+ restored, even though the MSC is supposedly the only divider
+ that is not affected by this flag. */
+ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_CHANGE_ENABLE);
+
+ return 0;
+}
+
+static const unsigned int jz_clk_main_divs[] = {
+ 1, 2, 3, 4, 6, 8, 12, 16, 24, 32
+};
+static const unsigned int jz_clk_main_divs_inv[] = {
+ -1, 0, 1, 2, 3, -1, 4, -1, 5, -1, -1, -1, 6, -1, -1, -1,
+ 7, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1,
+ 9
+};
static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
{
@@ -290,6 +436,64 @@ static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
return 0;
}
+static struct main_clk jz_clk_cpu;
+
+int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv,
+ unsigned int mdiv, unsigned int pdiv)
+{
+ unsigned int cdiv_enc, hdiv_enc, mdiv_enc, pdiv_enc;
+ unsigned int ctrl;
+ unsigned int tmp, wait;
+
+ if (cdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
+ hdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
+ mdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
+ pdiv >= ARRAY_SIZE(jz_clk_main_divs_inv))
+ return -EINVAL;
+ cdiv_enc = jz_clk_main_divs_inv[cdiv];
+ hdiv_enc = jz_clk_main_divs_inv[hdiv];
+ mdiv_enc = jz_clk_main_divs_inv[mdiv];
+ pdiv_enc = jz_clk_main_divs_inv[pdiv];
+ if (cdiv_enc == (unsigned int)-1 ||
+ hdiv_enc == (unsigned int)-1 ||
+ mdiv_enc == (unsigned int)-1 ||
+ pdiv_enc == (unsigned int)-1)
+ return -EINVAL;
+
+ ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+ ctrl &= ~(JZ_CLOCK_CTRL_CHANGE_ENABLE |
+ JZ_CLOCK_CTRL_CDIV_MASK | JZ_CLOCK_CTRL_HDIV_MASK |
+ JZ_CLOCK_CTRL_MDIV_MASK | JZ_CLOCK_CTRL_PDIV_MASK);
+ if (immediate) ctrl |= JZ_CLOCK_CTRL_CHANGE_ENABLE;
+ ctrl |= (cdiv_enc << JZ_CLOCK_CTRL_CDIV_OFFSET) |
+ (hdiv_enc << JZ_CLOCK_CTRL_HDIV_OFFSET) |
+ (mdiv_enc << JZ_CLOCK_CTRL_MDIV_OFFSET) |
+ (pdiv_enc << JZ_CLOCK_CTRL_PDIV_OFFSET);
+
+ /* set dividers */
+ /* delay loops lifted from the old Ingenic cpufreq driver */
+ wait = ((clk_get_rate(&jz_clk_cpu.clk) / 1000000) * 500) / 1000;
+ __asm__ __volatile__(
+ ".set noreorder\n\t"
+ ".align 5\n"
+ "sw %2,0(%1)\n\t"
+ "li %0,0\n\t"
+ "1:\n\t"
+ "bne %0,%3,1b\n\t"
+ "addi %0, 1\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ ".set reorder\n\t"
+ : "=r" (tmp)
+ : "r" (jz_clock_base + JZ_REG_CLOCK_CTRL), "r" (ctrl),
+ "r" (wait));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(clk_main_set_dividers);
+
static struct clk_ops jz_clk_static_ops = {
.get_rate = jz_clk_static_get_rate,
.enable = jz_clk_enable_gating,
@@ -307,6 +511,8 @@ static struct static_clk jz_clk_ext = {
static struct clk_ops jz_clk_pll_ops = {
.get_rate = jz_clk_pll_get_rate,
+ .set_rate = jz_clk_pll_set_rate,
+ .round_rate = jz_clk_pll_round_rate,
};
static struct clk jz_clk_pll = {
@@ -897,6 +1103,10 @@ static int jz4740_clock_init(void)
if (!jz_clock_base)
return -EBUSY;
+ jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100);
+ if (!jz_emc_base)
+ return -EBUSY;
+
spin_lock_init(&jz_clock_lock);
jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h
index 5d07499..cc8d1db 100644
--- a/arch/mips/jz4740/clock.h
+++ b/arch/mips/jz4740/clock.h
@@ -17,6 +17,7 @@
#define __MIPS_JZ4740_CLOCK_H__
#include <linux/list.h>
+#include <linux/types.h>
struct jz4740_clock_board_data {
unsigned long ext_rate;
@@ -63,6 +64,9 @@ struct clk {
int clk_is_enabled(struct clk *clk);
+int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv,
+ unsigned int mdiv, unsigned int pdiv);
+
#ifdef CONFIG_DEBUG_FS
void jz4740_clock_debugfs_init(void);
void jz4740_clock_debugfs_add_clk(struct clk *clk);
--
1.7.5.4

View File

@ -0,0 +1,310 @@
From d0f0d5739a31c12d349980ed05a670fa1e84696d Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Wed, 16 Mar 2011 03:16:04 +0100
Subject: [PATCH 12/28] MIPS: JZ4740: Add cpufreq support.
This is a squashed version of Uli's driver that was further developed in the opendingux-kernel repository.
---
arch/mips/Kconfig | 1 +
arch/mips/jz4740/Makefile | 1 +
arch/mips/jz4740/cpufreq.c | 226 ++++++++++++++++++++++++++++++++++++++
arch/mips/kernel/cpufreq/Kconfig | 13 ++-
4 files changed, 240 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/jz4740/cpufreq.c
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d46f1da..8128df7 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -209,6 +209,7 @@ config MACH_JZ4740
select HAVE_PWM
select HAVE_CLK
select GENERIC_IRQ_CHIP
+ select CPU_SUPPORTS_CPUFREQ
config LANTIQ
bool "Lantiq based platforms"
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index a9dff33..15f828e 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
# PM support
obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_CPU_FREQ_JZ) += cpufreq.o
ccflags-y := -Werror -Wall
diff --git a/arch/mips/jz4740/cpufreq.c b/arch/mips/jz4740/cpufreq.c
new file mode 100644
index 0000000..aa41e9f
--- /dev/null
+++ b/arch/mips/jz4740/cpufreq.c
@@ -0,0 +1,226 @@
+/*
+ * linux/arch/mips/jz4740/cpufreq.c
+ *
+ * cpufreq driver for JZ4740
+ *
+ * Copyright (c) 2010 Ulrich Hecht <ulrich.hecht@gmail.com>
+ * Copyright (c) 2010 Maarten ter Huurne <maarten@treewalker.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/err.h>
+
+#include <linux/cpufreq.h>
+
+#include <linux/clk.h>
+#include <asm/mach-jz4740/base.h>
+
+#include "clock.h"
+
+#define DEBUG_CPUFREQ
+
+#ifdef DEBUG_CPUFREQ
+#define dprintk(X...) printk(KERN_INFO X)
+#else
+#define dprintk(X...) do { } while(0)
+#endif
+
+#define HCLK_MIN 30000
+/* TODO: The maximum MCLK most likely depends on the SDRAM chips used,
+ so it is board-specific. */
+#define MCLK_MAX 140000
+
+/* Same as jz_clk_main_divs, but with 24 and 32 removed because the hardware
+ spec states those dividers must not be used for CCLK or HCLK. */
+static const unsigned int jz4740_freq_cpu_divs[] = {1, 2, 3, 4, 6, 8, 12, 16};
+
+struct jz4740_freq_percpu_info {
+ unsigned int pll_rate;
+ struct cpufreq_frequency_table table[
+ ARRAY_SIZE(jz4740_freq_cpu_divs) + 1];
+};
+
+static struct clk *pll;
+static struct clk *cclk;
+
+static struct jz4740_freq_percpu_info jz4740_freq_info;
+
+static struct cpufreq_driver cpufreq_jz4740_driver;
+
+static void jz4740_freq_fill_table(struct cpufreq_policy *policy,
+ unsigned int pll_rate)
+{
+ struct cpufreq_frequency_table *table = &jz4740_freq_info.table[0];
+ int i;
+
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */
+ static bool init = false;
+ if (init)
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ else
+ init = true;
+#endif
+
+ jz4740_freq_info.pll_rate = pll_rate;
+
+ for (i = 0; i < ARRAY_SIZE(jz4740_freq_cpu_divs); i++) {
+ unsigned int freq = pll_rate / jz4740_freq_cpu_divs[i];
+ if (freq < HCLK_MIN) break;
+ table[i].index = i;
+ table[i].frequency = freq;
+ }
+ table[i].index = i;
+ table[i].frequency = CPUFREQ_TABLE_END;
+
+ policy->min = table[i - 1].frequency;
+ policy->max = table[0].frequency;
+
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ cpufreq_frequency_table_get_attr(table, policy->cpu);
+#endif
+}
+
+static unsigned int jz4740_freq_get(unsigned int cpu)
+{
+ return clk_get_rate(cclk) / 1000;
+}
+
+static int jz4740_freq_verify(struct cpufreq_policy *policy)
+{
+ unsigned int new_pll;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ new_pll = clk_round_rate(pll, policy->max * 1000) / 1000;
+ if (jz4740_freq_info.pll_rate != new_pll)
+ jz4740_freq_fill_table(policy, new_pll);
+
+ return 0;
+}
+
+static int jz4740_freq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_frequency_table *table = &jz4740_freq_info.table[0];
+ struct cpufreq_freqs freqs;
+ unsigned int new_index = 0;
+ unsigned int old_pll = clk_get_rate(pll) / 1000;
+ unsigned int new_pll = jz4740_freq_info.pll_rate;
+ int ret = 0;
+
+ if (cpufreq_frequency_table_target(policy, table,
+ target_freq, relation, &new_index))
+ return -EINVAL;
+ freqs = (struct cpufreq_freqs) {
+ .old = jz4740_freq_get(policy->cpu),
+ .new = table[new_index].frequency,
+ .cpu = policy->cpu,
+ .flags = cpufreq_jz4740_driver.flags,
+ };
+ if (freqs.new != freqs.old || new_pll != old_pll) {
+ unsigned int cdiv, hdiv, mdiv, pdiv;
+ cdiv = jz4740_freq_cpu_divs[new_index];
+ hdiv = (cdiv == 3 || cdiv == 6) ? cdiv * 2 : cdiv * 3;
+ while (new_pll < HCLK_MIN * hdiv)
+ hdiv -= cdiv;
+ mdiv = hdiv;
+ if (new_pll > MCLK_MAX * mdiv) {
+ /* 4,4 performs better than 3,6 */
+ if (new_pll > MCLK_MAX * 4)
+ mdiv *= 2;
+ else
+ hdiv = mdiv = cdiv * 4;
+ }
+ pdiv = mdiv;
+ dprintk(KERN_INFO "%s: cclk %p, setting from %d to %d, "
+ "dividers %d, %d, %d, %d\n",
+ __FUNCTION__, cclk, freqs.old, freqs.new,
+ cdiv, hdiv, mdiv, pdiv);
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ ret = clk_main_set_dividers(new_pll == old_pll,
+ cdiv, hdiv, mdiv, pdiv);
+ if (ret) {
+ dprintk(KERN_INFO "failed to set dividers\n");
+ } else if (new_pll != old_pll) {
+ dprintk(KERN_INFO "%s: pll %p, setting from %d to %d\n",
+ __FUNCTION__, pll, old_pll, new_pll);
+ ret = clk_set_rate(pll, new_pll * 1000);
+ }
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
+ return ret;
+}
+
+static int jz4740_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+ int ret;
+
+ dprintk(KERN_INFO "Jz4740 cpufreq driver\n");
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ pll = clk_get(NULL, "pll");
+ if (IS_ERR(pll)) {
+ ret = PTR_ERR(pll);
+ goto err_exit;
+ }
+
+ cclk = clk_get(NULL, "cclk");
+ if (IS_ERR(cclk)) {
+ ret = PTR_ERR(cclk);
+ goto err_clk_put_pll;
+ }
+
+ policy->cpuinfo.min_freq = HCLK_MIN;
+ policy->cpuinfo.max_freq = 500000;
+ policy->cpuinfo.transition_latency = 100000; /* in nanoseconds */
+ policy->cur = jz4740_freq_get(policy->cpu);
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ /* min and max are set by jz4740_freq_fill_table() */
+
+ jz4740_freq_fill_table(policy, clk_get_rate(pll) / 1000 /* in kHz */);
+
+ return 0;
+
+err_clk_put_pll:
+ clk_put(pll);
+err_exit:
+ return ret;
+}
+
+static struct cpufreq_driver cpufreq_jz4740_driver = {
+ .init = jz4740_cpufreq_driver_init,
+ .verify = jz4740_freq_verify,
+ .target = jz4740_freq_target,
+ .get = jz4740_freq_get,
+ .name = "jz4740",
+};
+
+static int __init jz4740_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&cpufreq_jz4740_driver);
+}
+
+static void __exit jz4740_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&cpufreq_jz4740_driver);
+}
+
+module_init(jz4740_cpufreq_init);
+module_exit(jz4740_cpufreq_exit);
+
+MODULE_AUTHOR("Ulrich Hecht <ulrich.hecht@gmail.com>, "
+ "Maarten ter Huurne <maarten@treewalker.org>");
+MODULE_DESCRIPTION("cpufreq driver for Jz4740");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/cpufreq/Kconfig b/arch/mips/kernel/cpufreq/Kconfig
index 58c601e..11af8e8 100644
--- a/arch/mips/kernel/cpufreq/Kconfig
+++ b/arch/mips/kernel/cpufreq/Kconfig
@@ -8,7 +8,7 @@ config MIPS_EXTERNAL_TIMER
config MIPS_CPUFREQ
bool
default y
- depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
+ depends on CPU_SUPPORTS_CPUFREQ
if MIPS_CPUFREQ
@@ -24,6 +24,7 @@ config LOONGSON2_CPUFREQ
tristate "Loongson2 CPUFreq Driver"
select CPU_FREQ_TABLE
depends on MIPS_CPUFREQ
+ depends on MIPS_EXTERNAL_TIMER
help
This option adds a CPUFreq driver for loongson processors which
support software configurable cpu frequency.
@@ -34,6 +35,16 @@ config LOONGSON2_CPUFREQ
If in doubt, say N.
+config CPU_FREQ_JZ
+ tristate "CPUfreq driver for JZ CPUs"
+ select CPU_FREQ_TABLE
+ depends on MACH_JZ4740
+ default n
+ help
+ This enables the CPUfreq driver for JZ CPUs.
+
+ If in doubt, say N.
+
endif # CPU_FREQ
endmenu
--
1.7.5.4

View File

@ -0,0 +1,134 @@
From b95144c1b702f98c7902c75beb83f323701eb7c5 Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Sun, 19 Jun 2011 10:57:18 +0200
Subject: [PATCH 13/28] MMC: JZ4740: Added support for CPU frequency changing.
The MSC device clock is stopped before the frequency change.
After the change a new divider is computed and the clock is restarted.
Also the frequency change is postponed if an I/O operation is in progress.
---
drivers/mmc/host/jz4740_mmc.c | 69 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 74218ad..6e40f1b 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/scatterlist.h>
#include <linux/clk.h>
+#include <linux/cpufreq.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
@@ -685,6 +686,60 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
}
+#ifdef CONFIG_CPU_FREQ
+
+static struct jz4740_mmc_host *cpufreq_host;
+
+static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ /* TODO: We only have to take action when the PLL freq changes:
+ the main dividers have no influence on the MSC device clock. */
+
+ if (val == CPUFREQ_PRECHANGE) {
+ mmc_claim_host(cpufreq_host->mmc);
+ clk_disable(cpufreq_host->clk);
+ } else if (val == CPUFREQ_POSTCHANGE) {
+ struct mmc_ios *ios = &cpufreq_host->mmc->ios;
+ if (ios->clock)
+ jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
+ if (ios->power_mode != MMC_POWER_OFF)
+ clk_enable(cpufreq_host->clk);
+ mmc_release_host(cpufreq_host->mmc);
+ }
+ return 0;
+}
+
+static struct notifier_block jz4740_mmc_cpufreq_nb = {
+ .notifier_call = jz4740_mmc_cpufreq_transition,
+};
+
+static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
+{
+ cpufreq_host = host;
+ return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void jz4740_mmc_cpufreq_unregister(void)
+{
+ cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+
+static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
+{
+ return 0;
+}
+
+static inline void jz4740_mmc_cpufreq_unregister(void)
+{
+}
+
+#endif
+
static const struct mmc_host_ops jz4740_mmc_ops = {
.request = jz4740_mmc_request,
.set_ios = jz4740_mmc_set_ios,
@@ -834,11 +889,18 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
goto err_free_host;
}
+ ret = jz4740_mmc_cpufreq_register(host);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register cpufreq transition notifier\n");
+ goto err_clk_put;
+ }
+
host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
ret = -ENOENT;
dev_err(&pdev->dev, "Failed to get base platform memory\n");
- goto err_clk_put;
+ goto err_cpufreq_unreg;
}
host->mem = request_mem_region(host->mem->start,
@@ -846,7 +908,7 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
if (!host->mem) {
ret = -EBUSY;
dev_err(&pdev->dev, "Failed to request base memory region\n");
- goto err_clk_put;
+ goto err_cpufreq_unreg;
}
host->base = ioremap_nocache(host->mem->start, resource_size(host->mem));
@@ -929,6 +991,8 @@ err_iounmap:
iounmap(host->base);
err_release_mem_region:
release_mem_region(host->mem->start, resource_size(host->mem));
+err_cpufreq_unreg:
+ jz4740_mmc_cpufreq_unregister();
err_clk_put:
clk_put(host->clk);
err_free_host:
@@ -958,6 +1022,7 @@ static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
iounmap(host->base);
release_mem_region(host->mem->start, resource_size(host->mem));
+ jz4740_mmc_cpufreq_unregister();
clk_put(host->clk);
platform_set_drvdata(pdev, NULL);
--
1.7.5.4

View File

@ -0,0 +1,95 @@
From 2dcb0ca66d0bffc23d5f001fad81fb1a7a2c371b Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Tue, 28 Jun 2011 22:28:59 +0200
Subject: [PATCH 14/28] MIPS: JZ4740: reset: Initialize hibernate wakeup
counters.
In hibernation mode only the wakeup logic and the RTC are left running,
so this is what users perceive as power down.
If the counters are not initialized, the corresponding pin (typically
connected to the power button) has to be asserted for two seconds
before the device wakes up. Most users expect a shorter wakeup time.
I took the timing values of 100 ms and 60 ms from BouKiCHi's patch for
the Dingoo A320 kernel.
---
arch/mips/jz4740/reset.c | 46 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c
index 5f1fb95..e6d1d7b 100644
--- a/arch/mips/jz4740/reset.c
+++ b/arch/mips/jz4740/reset.c
@@ -21,6 +21,9 @@
#include <asm/mach-jz4740/base.h>
#include <asm/mach-jz4740/timer.h>
+#include "reset.h"
+#include "clock.h"
+
static void jz4740_halt(void)
{
while (1) {
@@ -53,21 +56,52 @@ static void jz4740_restart(char *command)
jz4740_halt();
}
-#define JZ_REG_RTC_CTRL 0x00
-#define JZ_REG_RTC_HIBERNATE 0x20
+#define JZ_REG_RTC_CTRL 0x00
+#define JZ_REG_RTC_HIBERNATE 0x20
+#define JZ_REG_RTC_WAKEUP_FILTER 0x24
+#define JZ_REG_RTC_RESET_COUNTER 0x28
-#define JZ_RTC_CTRL_WRDY BIT(7)
+#define JZ_RTC_CTRL_WRDY BIT(7)
+#define JZ_RTC_WAKEUP_FILTER_MASK 0x0000FFE0
+#define JZ_RTC_RESET_COUNTER_MASK 0x00000FE0
-static void jz4740_power_off(void)
+static inline void jz4740_rtc_wait_ready(void __iomem *rtc_base)
{
- void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x24);
uint32_t ctrl;
-
do {
ctrl = readl(rtc_base + JZ_REG_RTC_CTRL);
} while (!(ctrl & JZ_RTC_CTRL_WRDY));
+}
+static void jz4740_power_off(void)
+{
+ void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38);
+ unsigned long long wakeup_filter_ticks;
+ unsigned long long reset_counter_ticks;
+
+ /* Set minimum wakeup pin assertion time: 100 ms.
+ Range is 0 to 2 sec if RTC is clocked at 32 kHz. */
+ wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000;
+ if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
+ wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
+ else
+ wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
+ jz4740_rtc_wait_ready(rtc_base);
+ writel(wakeup_filter_ticks, rtc_base + JZ_REG_RTC_WAKEUP_FILTER);
+
+ /* Set reset pin low-level assertion time after wakeup: 60 ms.
+ Range is 0 to 125 ms if RTC is clocked at 32 kHz. */
+ reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000;
+ if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
+ reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
+ else
+ reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK;
+ jz4740_rtc_wait_ready(rtc_base);
+ writel(reset_counter_ticks, rtc_base + JZ_REG_RTC_RESET_COUNTER);
+
+ jz4740_rtc_wait_ready(rtc_base);
writel(1, rtc_base + JZ_REG_RTC_HIBERNATE);
+
jz4740_halt();
}
--
1.7.5.4

View File

@ -0,0 +1,36 @@
From 515f8006c03e1065bf98c9148a9ea787e2d120d3 Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Wed, 10 Aug 2011 00:20:16 +0200
Subject: [PATCH 15/28] ASoC: JZ4740: Replaced comma operators with
semicolons.
They were harmless but also unnecessary, probably a leftover from earlier code.
---
sound/soc/jz4740/jz4740-i2s.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index cd22a54..d28b4cc 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -346,7 +346,7 @@ static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
/* Playback */
dma_config = &i2s->pcm_config_playback.dma_config;
- dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
+ dma_config->src_width = JZ4740_DMA_WIDTH_32BIT;
dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
@@ -355,7 +355,7 @@ static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
/* Capture */
dma_config = &i2s->pcm_config_capture.dma_config;
- dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
+ dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT;
dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
dma_config->flags = JZ4740_DMA_DST_AUTOINC;
--
1.7.5.4

View File

@ -1,14 +1,20 @@
From 5e689acca07bccdced123f82e8dde5459eca0d97 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
Date: Wed, 14 Sep 2011 14:30:01 +0800
Subject: [PATCH 26/32] sound: update DMA code
From 8a5087fe59e31efb8641e704058328997c3c8ff1 Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Wed, 10 Aug 2011 00:25:11 +0200
Subject: [PATCH 16/28] ASoC: JZ4740: Support buffer size that is not a
multiple of period size.
This fixes glitches triggered by libao, which sets time-based intervals
instead of byte-based intervals like SDL does.
Thanks to Paul Cercueil for figuring out that the buffer size was causing
the glitches and to Lars Clausen for helping me write the fix.
---
sound/soc/jz4740/jz4740-pcm.c | 21 ++++++++++++++++++---
1 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index fb1483f..71c455d 100644
index d1989cd..1f9a005 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -31,6 +31,7 @@
@ -84,5 +90,5 @@ index fb1483f..71c455d 100644
runtime->private_data = prtd;
--
1.7.4.1
1.7.5.4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
From 295008ce697a5ddb45ee1715b45d5e8024e1165b Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Wed, 11 Jan 2012 22:36:03 +0100
Subject: [PATCH 18/28] MIPS: JZ4740: qi_lb60: Look for NAND chip in bank 1.
All NanoNotes have their NAND in bank 1.
Specifying the bank is required since commit e7ca5a665877a030.
---
arch/mips/jz4740/board-qi_lb60.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index b622941..f2d94c1 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -140,6 +140,7 @@ static void qi_lb60_nand_ident(struct platform_device *pdev,
static struct jz_nand_platform_data qi_lb60_nand_pdata = {
.ident_callback = qi_lb60_nand_ident,
.busy_gpio = 94,
+ .banks = { 1 },
};
/* Keyboard*/
--
1.7.5.4

View File

@ -0,0 +1,128 @@
From 7be17b01bffeccb75c1058eac949f99c3040a9f7 Mon Sep 17 00:00:00 2001
From: Axel Lin <axel.lin@gmail.com>
Date: Fri, 6 Jan 2012 11:30:10 +0800
Subject: [PATCH 19/28] ASoC: jz4740: Convert qi_lb60 to use
snd_soc_register_card()
Use snd_soc_register_card() instead of creating a "soc-audio" platform device.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
arch/mips/jz4740/board-qi_lb60.c | 6 ++++
sound/soc/jz4740/qi_lb60.c | 56 +++++++++++++++++--------------------
2 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index f2d94c1..be14dfb 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -418,6 +418,11 @@ static struct platform_device qi_lb60_charger_device = {
},
};
+/* audio */
+static struct platform_device qi_lb60_audio_device = {
+ .name = "qi-lb60-audio",
+ .id = -1,
+};
static struct platform_device *jz_platform_devices[] __initdata = {
&jz4740_udc_device,
@@ -434,6 +439,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
&qi_lb60_gpio_keys,
&qi_lb60_pwm_beeper,
&qi_lb60_charger_device,
+ &qi_lb60_audio_device,
};
static void __init board_gpio_setup(void)
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
index c5fc339..67ddbdd 100644
--- a/sound/soc/jz4740/qi_lb60.c
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -90,56 +90,52 @@ static struct snd_soc_card qi_lb60 = {
.num_dapm_routes = ARRAY_SIZE(qi_lb60_routes),
};
-static struct platform_device *qi_lb60_snd_device;
-
static const struct gpio qi_lb60_gpios[] = {
{ QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" },
{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
};
-static int __init qi_lb60_init(void)
+static int __devinit qi_lb60_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &qi_lb60;
int ret;
- qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
-
- if (!qi_lb60_snd_device)
- return -ENOMEM;
-
ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
- if (ret) {
- pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret);
- goto err_device_put;
- }
+ if (ret)
+ return ret;
- platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
+ card->dev = &pdev->dev;
- ret = platform_device_add(qi_lb60_snd_device);
+ ret = snd_soc_register_card(card);
if (ret) {
- pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
- goto err_unset_pdata;
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
}
-
- return 0;
-
-err_unset_pdata:
- platform_set_drvdata(qi_lb60_snd_device, NULL);
-/*err_gpio_free_array:*/
- gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-err_device_put:
- platform_device_put(qi_lb60_snd_device);
-
return ret;
}
-module_init(qi_lb60_init);
-static void __exit qi_lb60_exit(void)
+static int __devexit qi_lb60_remove(struct platform_device *pdev)
{
- platform_device_unregister(qi_lb60_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
+ return 0;
}
-module_exit(qi_lb60_exit);
+
+static struct platform_driver qi_lb60_driver = {
+ .driver = {
+ .name = "qi-lb60-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = qi_lb60_probe,
+ .remove = __devexit_p(qi_lb60_remove),
+};
+
+module_platform_driver(qi_lb60_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qi-lb60-audio");
--
1.7.5.4

View File

@ -1,14 +1,15 @@
From c7700fa672bf0a171ceb9f4b092de33e3b306243 Mon Sep 17 00:00:00 2001
From 0c5669e6b4e4ada7f9a3caf0b51b906b5602f260 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sat, 24 Apr 2010 12:23:28 +0200
Subject: [PATCH 14/32] Framebuffer notifier: Call notifier callbacks prior to blanking the screen
Subject: [PATCH 20/28] Framebuffer notifier: Call notifier callbacks prior to
blanking the screen
---
drivers/video/fbmem.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 5aac00e..b1beaa7 100644
index ad93629..e13e6bf 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1032,12 +1032,12 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
@ -38,5 +39,5 @@ index 5aac00e..b1beaa7 100644
}
--
1.7.4.1
1.7.5.4

View File

@ -1,7 +1,7 @@
From 15bd698ca3f4104f3e3c28dcc7619dcef21f40ad Mon Sep 17 00:00:00 2001
From 0126586095ebd44af31f8080e30143a608ab33ca Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:40:08 +0800
Subject: [PATCH 15/32] 500-modifier-keys.patch
Subject: [PATCH 21/28] 500-modifier-keys.patch
---
drivers/tty/vt/defkeymap.c_shipped | 326 +++++++++++++++++++++++++++---------
@ -653,5 +653,5 @@ index 50b30ca..732f395 100644
keycode 117 = F17
keycode 118 = KP_MinPlus
--
1.7.4.1
1.7.5.4

View File

@ -1,7 +1,7 @@
From f4c9a977dc405856676cd1ca435394faf49b5f1c Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:44:15 +0800
Subject: [PATCH 16/32] 850-ks7010-support.patch
From 3aad7806fb868cd3d024954b08b8913e215ef705 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Tue, 6 Mar 2012 09:32:15 +0800
Subject: [PATCH 22/28] sdio-wifi-ks7010-support
---
drivers/mmc/core/core.c | 4 ++--
@ -9,10 +9,10 @@ Subject: [PATCH 16/32] 850-ks7010-support.patch
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7843efe..9b904b8 100644
index 950b97d..9bbc3db 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1020,7 +1020,7 @@ static void mmc_power_up(struct mmc_host *host)
@@ -1303,7 +1303,7 @@ static void mmc_power_up(struct mmc_host *host)
* This delay should be sufficient to allow the power supply
* to reach the minimum voltage.
*/
@ -21,17 +21,17 @@ index 7843efe..9b904b8 100644
host->ios.clock = host->f_init;
@@ -1031,7 +1031,7 @@ static void mmc_power_up(struct mmc_host *host)
@@ -1314,7 +1314,7 @@ static void mmc_power_up(struct mmc_host *host)
* This delay must be at least 74 clock sizes, or 1 ms, or the
* time required to reach a stable voltage.
*/
- mmc_delay(10);
+ mmc_delay(200);
}
static void mmc_power_off(struct mmc_host *host)
mmc_host_clk_release(host);
}
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 541bdb8..3ed300c 100644
index f1c7ed8..7881c4b 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -156,7 +156,8 @@ static int cistpl_funce_common(struct mmc_card *card, struct sdio_func *func,
@ -62,5 +62,5 @@ index 541bdb8..3ed300c 100644
else
func->enable_timeout = jiffies_to_msecs(HZ);
--
1.7.4.1
1.7.5.4

View File

@ -1,14 +1,14 @@
From 1878b22649c3ecde1795d6695b92ca02fa9110c2 Mon Sep 17 00:00:00 2001
From f6c67f56e422de9524d45ffe32aef00b47dcc350 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@macbook.(none)>
Date: Fri, 19 Aug 2011 15:46:52 +0800
Subject: [PATCH 23/32] qi_lb60: NAND: add data partition
Subject: [PATCH 23/28] qi_lb60: NAND: add data partition
---
arch/mips/jz4740/board-qi_lb60.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index b622941..0bc4caa 100644
index be14dfb..4e24b95 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -118,8 +118,13 @@ static struct mtd_partition qi_lb60_partitions_2gb[] = {
@ -27,5 +27,5 @@ index b622941..0bc4caa 100644
static void qi_lb60_nand_ident(struct platform_device *pdev,
--
1.7.4.1
1.7.5.4

View File

@ -1,7 +1,7 @@
From 77de829067262bbe1f7435b087c11ad9a8ea0b06 Mon Sep 17 00:00:00 2001
From 44cb778f4b2c6febb91631243c73f89a91c2f1ca Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Tue, 18 Oct 2011 09:21:04 +0800
Subject: [PATCH 30/32] fbcon-color-fonts
Subject: [PATCH 24/28] fbcon-color-fonts
---
drivers/tty/vt/vt.c | 3 +-
@ -10,7 +10,7 @@ Subject: [PATCH 30/32] fbcon-color-fonts
3 files changed, 173 insertions(+), 32 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index b3915b7..37eaac5 100644
index e716839..298f727 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4034,6 +4034,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
@ -316,5 +316,5 @@ index 8745637..dea9d2c 100644
/* Since linux has a nice crc32 function use it for counting font
--
1.7.4.1
1.7.5.4

View File

@ -1,16 +1,16 @@
From 84f38ed9a131b807927e4aed2f277d8a2fad5286 Mon Sep 17 00:00:00 2001
From 236d01dd323d1158f2744d37766baea85575b290 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Wed, 19 Oct 2011 10:59:47 +0800
Subject: [PATCH 31/32] first patch for atBen
Date: Tue, 6 Mar 2012 11:40:52 +0800
Subject: [PATCH 25/28] first-patch-for-atBen
---
drivers/ieee802154/Kconfig | 55 ++-
drivers/ieee802154/Makefile | 10 +-
drivers/ieee802154/Makefile | 11 +
drivers/ieee802154/adf7242.c | 1034 ++++++++++++++++++++++++++++++++++++++
drivers/ieee802154/at86rf230.c | 872 ++++++++++++++++++++++++++++++++
drivers/ieee802154/at86rf230.h | 211 ++++++++
drivers/ieee802154/cc2420.c | 859 ++++++++++++++++++++++++++++++++
drivers/ieee802154/fakehard.c | 14 +-
drivers/ieee802154/fakehard.c | 12 +-
drivers/ieee802154/fakelb.c | 311 ++++++++++++
drivers/ieee802154/serial.c | 1047 +++++++++++++++++++++++++++++++++++++++
drivers/ieee802154/spi_atben.c | 421 ++++++++++++++++
@ -25,12 +25,12 @@ Subject: [PATCH 31/32] first patch for atBen
include/net/wpan-phy.h | 8 +-
net/Kconfig | 2 +
net/Makefile | 1 +
net/ieee802154/Kconfig | 9 +
net/ieee802154/Kconfig | 8 +
net/ieee802154/Makefile | 3 +
net/ieee802154/dgram.c | 3 +-
net/ieee802154/ieee802154.h | 4 +
net/ieee802154/nl-mac.c | 2 +-
net/ieee802154/nl-phy.c | 48 ++-
net/ieee802154/nl-phy.c | 20 +-
net/ieee802154/nl_policy.c | 1 +
net/ieee802154/wpan-class.c | 2 +-
net/mac802154/Kconfig | 24 +
@ -53,7 +53,7 @@ Subject: [PATCH 31/32] first patch for atBen
net/zigbee/Makefile | 5 +
net/zigbee/af_zigbee.c | 285 +++++++++++
net/zigbee/dgram.c | 401 +++++++++++++++
49 files changed, 9380 insertions(+), 24 deletions(-)
49 files changed, 9356 insertions(+), 18 deletions(-)
create mode 100644 drivers/ieee802154/adf7242.c
create mode 100644 drivers/ieee802154/at86rf230.c
create mode 100644 drivers/ieee802154/at86rf230.h
@ -158,10 +158,10 @@ index 9b9f43a..a323dc1 100644
+ depends on SPI
+
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index 6899913..2a10a6a 100644
index 800a389..6374677 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1,11 @@
@@ -1 +1,12 @@
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
+obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
+obj-$(CONFIG_IEEE802154_SERIAL) += serial.o
@ -170,8 +170,8 @@ index 6899913..2a10a6a 100644
+obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
+obj-$(CONFIG_SPI_ATUSB) += spi_atusb.o
+obj-$(CONFIG_SPI_ATBEN) += spi_atben.o
-ccflags-y := -DDEBUG -DCONFIG_FFD
+
+ccflags-y := -DDEBUG -DCONFIG_FFD
+ccflags-$(CONFIG_IEEE802154_DRIVER_DEBUG) += -DDEBUG
+ccflags-y += -DCONFIG_FFD
diff --git a/drivers/ieee802154/adf7242.c b/drivers/ieee802154/adf7242.c
@ -3175,7 +3175,7 @@ index 0000000..50761de
+module_exit(cc2420_exit);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
index a5a49a1..1170074 100644
index eb0e2cc..1170074 100644
--- a/drivers/ieee802154/fakehard.c
+++ b/drivers/ieee802154/fakehard.c
@@ -259,7 +259,7 @@ static struct ieee802154_mlme_ops fake_mlme = {
@ -3187,16 +3187,7 @@ index a5a49a1..1170074 100644
.get_pan_id = fake_get_pan_id,
.get_short_addr = fake_get_short_addr,
@@ -370,8 +370,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
return -ENOMEM;
}
- phy->dev.platform_data = dev;
-
memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
dev->addr_len);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
@@ -393,6 +391,16 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
@@ -391,6 +391,16 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
priv = netdev_priv(dev);
priv->phy = phy;
@ -5767,12 +5758,12 @@ index 0000000..04d9fb3
+MODULE_DESCRIPTION("ATUSB ben-wpan Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/if.h b/include/linux/if.h
index 3bc63e6..4fc7448 100644
index db20bd4..cec9280 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -77,6 +77,8 @@
#define IFF_OVS_DATAPATH 0x8000 /* device used as Open vSwitch
* datapath port */
@@ -80,6 +80,8 @@
* skbs on transmit */
#define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */
+#define IFF_IEEE802154_COORD 0x400 /* IEEE802.15.4 PAN coordinator */
+
@ -6129,7 +6120,7 @@ index d86fffd..9e119c5 100644
char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
diff --git a/net/Kconfig b/net/Kconfig
index 878151c..66271cc 100644
index a073148..4ab1d57 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -211,6 +211,8 @@ source "net/econet/Kconfig"
@ -6142,7 +6133,7 @@ index 878151c..66271cc 100644
source "net/dcb/Kconfig"
source "net/dns_resolver/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index a51d946..b7a6585 100644
index acdde49..1969e93 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -60,6 +60,7 @@ ifneq ($(CONFIG_DCB),)
@ -6154,13 +6145,13 @@ index a51d946..b7a6585 100644
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig
index 1c1de97..5f1a5af 100644
index 7dee650..3dea3c1 100644
--- a/net/ieee802154/Kconfig
+++ b/net/ieee802154/Kconfig
@@ -10,3 +10,12 @@ config IEEE802154
Say Y here to compile LR-WPAN support into the kernel or say M to
compile it as modules.
@@ -16,3 +16,11 @@ config IEEE802154_6LOWPAN
depends on IEEE802154 && IPV6
---help---
IPv6 compression over IEEE 802.15.4.
+
+config IEEE802154_PROTO_DEBUG
+ bool "IEEE 802.15.4 protocol stack debugging messages"
@ -6169,20 +6160,19 @@ index 1c1de97..5f1a5af 100644
+ help
+ Say Y here to make the IEEE 802.15.4 protocol stack generate
+ extensive debugging messages.
+
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index 5761185..53f1ec3 100644
index d7716d6..e2b6735 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -1,3 +1,6 @@
obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
af_802154-y := af_ieee802154.o raw.o dgram.o
@@ -3,3 +3,6 @@ obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
af_802154-y := af_ieee802154.o raw.o dgram.o
+
+ccflags-$(CONFIG_IEEE802154_PROTO_DEBUG) += -DDEBUG
+ccflags-y += -Wall
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index 1a3334c..5c69833 100644
index faecf64..1f28f3a 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -130,8 +130,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
@ -6211,10 +6201,10 @@ index aadec42..e78d6c6 100644
{ \
.cmd = _cmd, \
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index 71ee110..51e375e 100644
index adaf462..1d23aa6 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -262,7 +262,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid,
@@ -263,7 +263,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid,
if (!hdr)
goto out;
@ -6224,27 +6214,10 @@ index 71ee110..51e375e 100644
NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 02548b2..49a29d7 100644
index c64a38d..76ef7a3 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/if_arp.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/wpan-phy.h>
@@ -44,7 +45,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
pr_debug("%s\n", __func__);
if (!buf)
- return -EMSGSIZE;
+ goto out;
hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
IEEE802154_LIST_PHY);
@@ -56,7 +57,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
@@ -57,7 +57,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, phy->current_page);
NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel);
@ -6253,15 +6226,7 @@ index 02548b2..49a29d7 100644
if (phy->channels_supported[i])
buf[pages++] = phy->channels_supported[i] | (i << 27);
}
@@ -65,7 +66,6 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
pages * sizeof(uint32_t), buf);
mutex_unlock(&phy->pib_lock);
- kfree(buf);
return genlmsg_end(msg, hdr);
nla_put_failure:
@@ -178,6 +178,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
@@ -179,6 +179,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
const char *devname;
int rc = -ENOBUFS;
struct net_device *dev;
@ -6269,16 +6234,7 @@ index 02548b2..49a29d7 100644
pr_debug("%s\n", __func__);
@@ -192,7 +193,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
devname = nla_data(info->attrs[IEEE802154_ATTR_DEV_NAME]);
if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1]
!= '\0')
- return -EINVAL; /* phy name should be null-terminated */
+ return -EINVAL; /* dev name should be null-terminated */
} else {
devname = "wpan%d";
}
@@ -200,6 +201,19 @@ static int ieee802154_add_iface(struct sk_buff *skb,
@@ -201,6 +202,19 @@ static int ieee802154_add_iface(struct sk_buff *skb,
if (strlen(devname) >= IFNAMSIZ)
return -ENAMETOOLONG;
@ -6298,7 +6254,7 @@ index 02548b2..49a29d7 100644
phy = wpan_phy_find(name);
if (!phy)
return -ENODEV;
@@ -213,12 +227,29 @@ static int ieee802154_add_iface(struct sk_buff *skb,
@@ -221,7 +235,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
goto nla_put_failure;
}
@ -6307,41 +6263,7 @@ index 02548b2..49a29d7 100644
if (IS_ERR(dev)) {
rc = PTR_ERR(dev);
goto nla_put_failure;
}
+ if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
+ struct sockaddr addr;
+
+ addr.sa_family = ARPHRD_IEEE802154;
+ nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR], IEEE802154_ADDR_LEN);
+
+ /*
+ * strangely enough, some callbacks (inetdev_event) from
+ * dev_set_mac_address require RTNL_LOCK
+ */
+ rtnl_lock();
+ rc = dev_set_mac_address(dev, &addr);
+ rtnl_unlock();
+ if (rc)
+ goto dev_unregister;
+ }
+
NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));
NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
@@ -228,6 +259,11 @@ static int ieee802154_add_iface(struct sk_buff *skb,
return ieee802154_nl_reply(msg, info);
+dev_unregister:
+ rtnl_lock(); /* del_iface must be called with RTNL lock */
+ phy->del_iface(phy, dev);
+ dev_put(dev);
+ rtnl_unlock();
nla_put_failure:
nlmsg_free(msg);
out_dev:
@@ -257,7 +293,7 @@ static int ieee802154_del_iface(struct sk_buff *skb,
@@ -288,7 +302,7 @@ static int ieee802154_del_iface(struct sk_buff *skb,
if (!dev)
return -ENODEV;
@ -10006,5 +9928,5 @@ index 0000000..4d9b682
+};
+
--
1.7.4.1
1.7.5.4

View File

@ -1,17 +1,17 @@
From 24c474c864c5b53c068a3203393e40894a385fb8 Mon Sep 17 00:00:00 2001
From c5659e82d248ce34443ec3a0eccc813f62b66742 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Tue, 1 Nov 2011 21:15:26 +0800
Subject: [PATCH 32/32] set atben GPIO to func_none
Subject: [PATCH 26/28] set atben GPIO to func_none
---
arch/mips/jz4740/board-qi_lb60.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 0bc4caa..67a5fa3 100644
index 4e24b95..83a1717 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -446,6 +446,13 @@ static void __init board_gpio_setup(void)
@@ -453,6 +453,13 @@ static void __init board_gpio_setup(void)
* drivers. Everything else is done by the drivers themselves. */
jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N);
jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD);
@ -26,5 +26,5 @@ index 0bc4caa..67a5fa3 100644
static int __init qi_lb60_init_platform_devices(void)
--
1.7.4.1
1.7.5.4

View File

@ -1,19 +1,18 @@
From 81734e6cd3cd75be1608717e9cd0a6cac54af528 Mon Sep 17 00:00:00 2001
From 657c83bd702402b1a80bcfab22c92d4cb8ee4336 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Thu, 17 Nov 2011 14:41:20 +0800
Subject: [PATCH] Revert "mmc: sdio: optimized SDIO IRQ handling for single irq"
Date: Tue, 6 Mar 2012 11:42:29 +0800
Subject: [PATCH 27/28] Revert-mmc-sdio-optimized-SDIO-IRQ-handling
This reverts commit 06e8935febe687e2a561707d4c7ca4245d261dbe.
---
drivers/mmc/core/sdio_irq.c | 33 +--------------------------------
include/linux/mmc/card.h | 1 -
2 files changed, 1 insertions(+), 33 deletions(-)
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 03ead02..b300161 100644
index 68f81b9..90437b2 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -31,17 +31,6 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
@@ -32,17 +32,6 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
{
int i, ret, count;
unsigned char pending;
@ -31,16 +30,16 @@ index 03ead02..b300161 100644
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
if (ret) {
@@ -53,7 +42,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
@@ -54,7 +43,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
count = 0;
for (i = 1; i <= 7; i++) {
if (pending & (1 << i)) {
- func = card->sdio_func[i - 1];
+ struct sdio_func *func = card->sdio_func[i - 1];
if (!func) {
printk(KERN_WARNING "%s: pending IRQ for "
pr_warning("%s: pending IRQ for "
"non-existent function\n",
@@ -197,24 +186,6 @@ static int sdio_card_irq_put(struct mmc_card *card)
@@ -198,24 +187,6 @@ static int sdio_card_irq_put(struct mmc_card *card)
return 0;
}
@ -65,7 +64,7 @@ index 03ead02..b300161 100644
/**
* sdio_claim_irq - claim the IRQ for a SDIO function
* @func: SDIO function
@@ -256,7 +227,6 @@ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
@@ -257,7 +228,6 @@ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
ret = sdio_card_irq_get(func->card);
if (ret)
func->irq_handler = NULL;
@ -73,7 +72,7 @@ index 03ead02..b300161 100644
return ret;
}
@@ -281,7 +251,6 @@ int sdio_release_irq(struct sdio_func *func)
@@ -282,7 +252,6 @@ int sdio_release_irq(struct sdio_func *func)
if (func->irq_handler) {
func->irq_handler = NULL;
sdio_card_irq_put(func->card);
@ -82,10 +81,10 @@ index 03ead02..b300161 100644
ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 6ad4355..5fa4f05 100644
index c8ef9bc..db1ab97 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -208,7 +208,6 @@ struct mmc_card {
@@ -245,7 +245,6 @@ struct mmc_card {
struct sdio_cccr cccr; /* common card info */
struct sdio_cis cis; /* common tuple info */
struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */
@ -94,5 +93,5 @@ index 6ad4355..5fa4f05 100644
const char **info; /* info strings */
struct sdio_func_tuple *tuples; /* unknown common tuples */
--
1.7.4.1
1.7.5.4

View File

@ -1,7 +1,7 @@
From 673062dacbdd05ac2ae2b572e3bf9f3e227d507e Mon Sep 17 00:00:00 2001
From feb9831d2869ca852b5341c8ff3f34a7b79f762a Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <xiangfu@sharism.cc>
Date: Thu, 10 Nov 2011 16:16:07 +0800
Subject: [PATCH 33/33] nanonote logo
Date: Tue, 6 Mar 2012 11:46:49 +0800
Subject: [PATCH 28/28] add-nanonote-logo
---
drivers/video/logo/Kconfig | 4 +
@ -13,11 +13,11 @@ Subject: [PATCH 33/33] nanonote logo
create mode 100644 drivers/video/logo/logo_nanonote_clut224.ppm
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 03da067..3992740 100644
index 39ac49e..4121d49 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -86,4 +86,8 @@ config LOGO_OPENWRT_CLUT224
bool "224-color OpenWrt Linux logo"
@@ -82,4 +82,8 @@ config LOGO_M32R_CLUT224
depends on M32R
default y
+config LOGO_NANONOTE_CLUT224
@ -26,24 +26,24 @@ index 03da067..3992740 100644
+
endif # LOGO
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index cbed3a5..a8a0403 100644
index 3b43781..088381f 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_LOGO_SUPERH_VGA16) += logo_superh_vga16.o
@@ -15,6 +15,7 @@ obj-$(CONFIG_LOGO_SUPERH_MONO) += logo_superh_mono.o
obj-$(CONFIG_LOGO_SUPERH_VGA16) += logo_superh_vga16.o
obj-$(CONFIG_LOGO_SUPERH_CLUT224) += logo_superh_clut224.o
obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o
obj-$(CONFIG_LOGO_OPENWRT_CLUT224) += logo_openwrt_clut224.o
+obj-$(CONFIG_LOGO_NANONOTE_CLUT224) += logo_nanonote_clut224.o
obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index 7208830..0fb911c 100644
index ea7a8cc..f530323 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -104,6 +104,10 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
/* OpenWrt logo */
logo = &logo_openwrt_clut224;
@@ -100,6 +100,10 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
/* M32R Linux logo */
logo = &logo_m32r_clut224;
#endif
+#ifdef CONFIG_LOGO_NANONOTE_CLUT224
+ /* Nanonote logo */
@ -211263,17 +211263,17 @@ index 0000000..12a05ac
+1
+0
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
index 67166f3..967d592 100644
index ca5bd91..dd36d13 100644
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -48,6 +48,7 @@ extern const struct linux_logo logo_superh_clut224;
@@ -47,6 +47,7 @@ extern const struct linux_logo logo_superh_vga16;
extern const struct linux_logo logo_superh_clut224;
extern const struct linux_logo logo_m32r_clut224;
extern const struct linux_logo logo_spe_clut224;
extern const struct linux_logo logo_openwrt_clut224;
+extern const struct linux_logo logo_nanonote_clut224;
extern const struct linux_logo *fb_find_logo(int depth);
#ifdef CONFIG_FB_LOGO_EXTRA
--
1.7.4.1
1.7.5.4

View File

@ -1,17 +0,0 @@
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_FB_JZ4740=y
# CONFIG_FB_TMIO is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_INPUT_PWM_BEEPER=y
CONFIG_JZ4740_QI_LB60=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_MATRIX=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_ILI8960=y
CONFIG_LOGO=y
CONFIG_MFD_CORE=y
CONFIG_MFD_JZ4740_ADC=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y

View File

@ -1,36 +0,0 @@
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_FB_JZ4740=y
# CONFIG_FB_TMIO is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_INPUT_PWM_BEEPER=y
CONFIG_JZ4740_QI_LB60=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_MATRIX=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_ILI8960=y
CONFIG_LOGO=y
CONFIG_MFD_CORE=y
CONFIG_MFD_JZ4740_ADC=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
CONFIG_SND_HWDEP=y
CONFIG_SND_SEQUENCER=y
CONFIG_SND_SEQ_DUMMY=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
# CONFIG_SND_RAWMIDI_SEQ is not set
CONFIG_SND_SOC=y
CONFIG_SND_JZ4740_SOC=y
CONFIG_SND_JZ4740_SOC_QI_LB60=y
CONFIG_SND_JZ4740_SOC_I2S=y
CONFIG_SND_SOC_I2C_AND_SPI=y
CONFIG_SND_SOC_JZCODEC=y
# CONFIG_SND_VIRMIDI is not set
CONFIG_SOUND_OSS_CORE_PRECLAIM=y
# CONFIG_SND_SEQUENCER_OSS is not set