From 7d446f792e17f2d11af8714cc9d4bf5c5fb3be49 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 20 Aug 2009 11:38:17 +0200 Subject: [PATCH] Add 2.6.31 patches and files. --- target/linux/xburst/config-2.6.31 | 422 + .../arch/mips/boot/compressed/Makefile | 42 + .../arch/mips/boot/compressed/dummy.c | 4 + .../arch/mips/boot/compressed/head.S | 85 + .../arch/mips/boot/compressed/ld.script | 151 + .../arch/mips/boot/compressed/misc.c | 242 + .../files-2.6.31/arch/mips/boot/tools/entry | 12 + .../arch/mips/boot/tools/filesize | 7 + .../arch/mips/include/asm/jzsoc.h | 26 + .../include/asm/mach-jz4740/board-dipper.h | 69 + .../mips/include/asm/mach-jz4740/board-leo.h | 56 + .../mips/include/asm/mach-jz4740/board-lyra.h | 70 + .../mips/include/asm/mach-jz4740/board-pavo.h | 70 + .../include/asm/mach-jz4740/board-virgo.h | 67 + .../arch/mips/include/asm/mach-jz4740/clock.h | 173 + .../arch/mips/include/asm/mach-jz4740/dma.h | 265 + .../mips/include/asm/mach-jz4740/jz4740.h | 56 + .../arch/mips/include/asm/mach-jz4740/misc.h | 43 + .../arch/mips/include/asm/mach-jz4740/ops.h | 2224 + .../arch/mips/include/asm/mach-jz4740/regs.h | 2392 + .../mips/include/asm/mach-jz4740/serial.h | 30 + .../arch/mips/include/asm/mach-jz4740/war.h | 25 + .../files-2.6.31/arch/mips/jz4740/Makefile | 26 + .../files-2.6.31/arch/mips/jz4740/cpufreq.c | 602 + .../files-2.6.31/arch/mips/jz4740/dma.c | 768 + .../files-2.6.31/arch/mips/jz4740/gpio.c | 297 + .../files-2.6.31/arch/mips/jz4740/i2c.c | 273 + .../files-2.6.31/arch/mips/jz4740/irq.c | 150 + .../files-2.6.31/arch/mips/jz4740/platform.c | 340 + .../xburst/files-2.6.31/arch/mips/jz4740/pm.c | 410 + .../files-2.6.31/arch/mips/jz4740/proc.c | 873 + .../files-2.6.31/arch/mips/jz4740/prom.c | 198 + .../files-2.6.31/arch/mips/jz4740/reset.c | 46 + .../files-2.6.31/arch/mips/jz4740/setup.c | 188 + .../files-2.6.31/arch/mips/jz4740/time.c | 159 + .../files-2.6.31/drivers/mmc/host/jz_mmc.c | 995 + .../files-2.6.31/drivers/mmc/host/jz_mmc.h | 65 + .../drivers/mtd/nand/jz4740_nand.c | 413 + .../files-2.6.31/drivers/power/jz_battery.c | 298 + .../drivers/usb/gadget/jz4740_udc.c | 2297 + .../drivers/usb/gadget/jz4740_udc.h | 121 + .../drivers/usb/gadget/udc_hotplug.h | 50 + .../drivers/usb/gadget/udc_hotplug_core.c | 836 + .../files-2.6.31/drivers/video/jz4740_slcd.c | 1334 + .../files-2.6.31/drivers/video/jz4740_slcd.h | 376 + .../drivers/video/jz_auo_a043fl01v2.h | 129 + .../drivers/video/jz_toppoly_td043mgeb1.h | 157 + .../xburst/files-2.6.31/drivers/video/jzlcd.c | 1538 + .../xburst/files-2.6.31/drivers/video/jzlcd.h | 791 + .../include/linux/mtd/jz4740_nand.h | 31 + .../files-2.6.31/sound/soc/codecs/jzcodec.c | 725 + .../files-2.6.31/sound/soc/codecs/jzcodec.h | 22 + .../files-2.6.31/sound/soc/codecs/jzdlv.c | 981 + .../files-2.6.31/sound/soc/codecs/jzdlv.h | 50 + .../files-2.6.31/sound/soc/jz4740/Kconfig | 34 + .../files-2.6.31/sound/soc/jz4740/Makefile | 15 + .../sound/soc/jz4740/jz4740-ac97.c | 261 + .../sound/soc/jz4740/jz4740-ac97.h | 21 + .../sound/soc/jz4740/jz4740-i2s.c | 297 + .../sound/soc/jz4740/jz4740-i2s.h | 18 + .../sound/soc/jz4740/jz4740-pcm.c | 689 + .../sound/soc/jz4740/jz4740-pcm.h | 33 + .../files-2.6.31/sound/soc/jz4740/pavo.c | 364 + .../files-2.6.31/sound/soc/jz4750/Kconfig | 34 + .../files-2.6.31/sound/soc/jz4750/Makefile | 15 + .../files-2.6.31/sound/soc/jz4750/apus.c | 405 + .../sound/soc/jz4750/jz4750-ac97.c | 261 + .../sound/soc/jz4750/jz4750-ac97.h | 21 + .../sound/soc/jz4750/jz4750-i2s.c | 311 + .../sound/soc/jz4750/jz4750-i2s.h | 18 + .../sound/soc/jz4750/jz4750-pcm.c | 687 + .../sound/soc/jz4750/jz4750-pcm.h | 33 + .../patches-2.6.31/0002-qi_lb60_support_patch | 103429 --------------- .../xburst/patches-2.6.31/001-core.patch | 726 + .../xburst/patches-2.6.31/050-nand.patch | 156 + .../xburst/patches-2.6.31/100-battery.patch | 36 + .../linux/xburst/patches-2.6.31/101-mmc.patch | 45 + .../xburst/patches-2.6.31/102-video.patch | 151 + .../xburst/patches-2.6.31/103-serial.patch | 178 + .../linux/xburst/patches-2.6.31/104-usb.patch | 183 + .../xburst/patches-2.6.31/105-sound.patch | 268 + .../xburst/patches-2.6.31/200-qi_lb60.patch | 319 + 82 files changed, 27649 insertions(+), 103429 deletions(-) create mode 100644 target/linux/xburst/config-2.6.31 create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/Makefile create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/dummy.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/head.S create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/ld.script create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/misc.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/tools/entry create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/boot/tools/filesize create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/jzsoc.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-dipper.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-leo.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-lyra.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-pavo.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-virgo.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/clock.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/dma.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/jz4740.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/misc.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/ops.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/regs.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/serial.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/war.h create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/Makefile create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/cpufreq.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/dma.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/gpio.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/i2c.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/irq.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/platform.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/pm.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/prom.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/reset.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/setup.c create mode 100644 target/linux/xburst/files-2.6.31/arch/mips/jz4740/time.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.h create mode 100644 target/linux/xburst/files-2.6.31/drivers/mtd/nand/jz4740_nand.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/power/jz_battery.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.h create mode 100644 target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug.h create mode 100644 target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug_core.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.c create mode 100644 target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.h create mode 100644 target/linux/xburst/files-2.6.31/drivers/video/jz_auo_a043fl01v2.h create mode 100644 target/linux/xburst/files-2.6.31/drivers/video/jz_toppoly_td043mgeb1.h create mode 100755 target/linux/xburst/files-2.6.31/drivers/video/jzlcd.c create mode 100755 target/linux/xburst/files-2.6.31/drivers/video/jzlcd.h create mode 100644 target/linux/xburst/files-2.6.31/include/linux/mtd/jz4740_nand.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/Kconfig create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/Makefile create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4740/pavo.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/Kconfig create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/Makefile create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/apus.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.h create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.c create mode 100755 target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.h delete mode 100644 target/linux/xburst/patches-2.6.31/0002-qi_lb60_support_patch create mode 100644 target/linux/xburst/patches-2.6.31/001-core.patch create mode 100644 target/linux/xburst/patches-2.6.31/050-nand.patch create mode 100644 target/linux/xburst/patches-2.6.31/100-battery.patch create mode 100644 target/linux/xburst/patches-2.6.31/101-mmc.patch create mode 100644 target/linux/xburst/patches-2.6.31/102-video.patch create mode 100644 target/linux/xburst/patches-2.6.31/103-serial.patch create mode 100644 target/linux/xburst/patches-2.6.31/104-usb.patch create mode 100644 target/linux/xburst/patches-2.6.31/105-sound.patch create mode 100644 target/linux/xburst/patches-2.6.31/200-qi_lb60.patch diff --git a/target/linux/xburst/config-2.6.31 b/target/linux/xburst/config-2.6.31 new file mode 100644 index 000000000..e6795f164 --- /dev/null +++ b/target/linux/xburst/config-2.6.31 @@ -0,0 +1,422 @@ +CONFIG_32BIT=y +# CONFIG_64BIT is not set +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_AR7 is not set +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +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_BACKTRACE_SELF_TEST is not set +CONFIG_BASE_SMALL=0 +# CONFIG_BCM47XX is not set +# CONFIG_BINARY_PRINTF is not set +CONFIG_BITREVERSE=y +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=2 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_SD=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_BRIDGE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CGROUP_SCHED is not set +CONFIG_CMDLINE="mem=32M console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p1 rw rootdelay=2" +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONSTRUCTORS=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_JZ=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +CONFIG_CPU_MIPSR1=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_VR41XX is not set +CONFIG_CRC16=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DNOTIFY=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EARLY_PRINTK=y +CONFIG_ELF_CORE=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT2_FS_XATTR=y +CONFIG_FAT_FS=y +# CONFIG_FAULT_INJECTION is not set +CONFIG_FB=y +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_JZ4740_SLCD is not set +CONFIG_FB_JZLCD_4730_4740=y +CONFIG_FB_JZSOC=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_VIRTUAL 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=y +CONFIG_FONT_8x8=y +# 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 is not set +CONFIG_FORCE_MAX_ZONEORDER=12 +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FSNOTIFY=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +# CONFIG_FW_LOADER is not set +# CONFIG_GCOV_KERNEL is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_GROUP_SCHED=y +# CONFIG_HAMRADIO is not set +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_IDE=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HID=y +CONFIG_HID_SUPPORT=y +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_HW_CONSOLE=y +# CONFIG_HW_RANDOM is not set +# CONFIG_I2C is not set +# CONFIG_IEEE802154 is not set +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MISC is not set +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_ISDN is not set +CONFIG_JFFS2_FS_DEBUG=1 +CONFIG_JZ4740_QI_LB60=y +# CONFIG_JZLCD_AUO_A030FL01_V1 is not set +# CONFIG_JZLCD_CSTN_320x240 is not set +# CONFIG_JZLCD_CSTN_800x600 is not set +CONFIG_JZLCD_FOXCONN_PT035TN01=y +# CONFIG_JZLCD_HYNIX_HT10X21 is not set +# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set +# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set +# CONFIG_JZLCD_MSTN_240x128 is not set +# CONFIG_JZLCD_MSTN_320x240 is not set +# CONFIG_JZLCD_MSTN_480x320 is not set +# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set +# CONFIG_JZLCD_SAMSUNG_LTP400WQF02 is not set +# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set +# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set +# CONFIG_JZLCD_SHARP_LQ035Q7 is not set +# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set +# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set +# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set +# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set +CONFIG_JZRISC=y +CONFIG_JZSOC=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_MATRIX=y +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KGDB is not set +# CONFIG_KMEMCHECK is not set +# CONFIG_LBDAF is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=2 +# CONFIG_LEMOTE_FULONG is not set +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCKD=y +CONFIG_LOCK_KERNEL=y +# CONFIG_LOCK_STAT is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MAC80211_DEFAULT_PS is not set +CONFIG_MAC80211_DEFAULT_PS_VALUE=0 +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_MEDIA_SUPPORT is not set +# CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y +# CONFIG_MIPS_COBALT is not set +# CONFIG_MIPS_FPU_EMU is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_SIM is not set +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_JZ is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODVERSIONS=y +CONFIG_MSDOS_FS=y +CONFIG_MTD_CONCAT=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_JZ4740=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_NETDEVICES is not set +# CONFIG_NETFILTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NEW_LEDS is not set +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4_1 is not set +CONFIG_NLS=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NO_IOPORT is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_PACKET_MMAP is not set +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PAGE_POISONING is not set +CONFIG_PCSPKR_PLATFORM=y +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PPS is not set +CONFIG_PREEMPT=y +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PROM_EMU is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RELAY=y +CONFIG_ROOT_NFS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_RUNTIME_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_SCSI=y +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SDIO_UART is not set +CONFIG_SECCOMP=y +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SLOW_WORK is not set +CONFIG_SOC_JZ4740=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_PRIME=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SYN_COOKIES is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +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_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TIMER_STATS is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_TRAD_SIGNALS=y +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_UBIFS_FS_LZO=y +# CONFIG_UBIFS_FS_XATTR is not set +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_USER_SCHED=y +CONFIG_VFAT_FS=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_VLAN_8021Q is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/Makefile b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/Makefile new file mode 100644 index 000000000..9b4132985 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/Makefile @@ -0,0 +1,42 @@ +# +# linux/arch/mips/boot/compressed/Makefile +# +# create a compressed zImage from the original vmlinux +# + +targets := zImage vmlinuz vmlinux.bin.gz head.o misc.o piggy.o dummy.o + +OBJS := $(obj)/head.o $(obj)/misc.o + +LD_ARGS := -T $(obj)/ld.script -Ttext 0x80600000 -Bstatic +OBJCOPY_ARGS := -O elf32-tradlittlemips + +ENTRY := $(obj)/../tools/entry +FILESIZE := $(obj)/../tools/filesize + +drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options +strip-flags = $(addprefix --remove-section=,$(drop-sections)) + + +$(obj)/vmlinux.bin.gz: vmlinux + rm -f $(obj)/vmlinux.bin.gz + $(OBJCOPY) -O binary $(strip-flags) vmlinux $(obj)/vmlinux.bin + gzip -v9f $(obj)/vmlinux.bin + +$(obj)/head.o: $(obj)/head.S $(obj)/vmlinux.bin.gz vmlinux + $(CC) $(KBUILD_AFLAGS) \ + -DIMAGESIZE=$(shell sh $(FILESIZE) $(obj)/vmlinux.bin.gz) \ + -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) vmlinux ) \ + -DLOADADDR=$(loadaddr) \ + -c -o $(obj)/head.o $< + +$(obj)/vmlinuz: $(OBJS) $(obj)/ld.script $(obj)/vmlinux.bin.gz $(obj)/dummy.o + $(OBJCOPY) \ + --add-section=.image=$(obj)/vmlinux.bin.gz \ + --set-section-flags=.image=contents,alloc,load,readonly,data \ + $(obj)/dummy.o $(obj)/piggy.o + $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/piggy.o + $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap + +zImage: $(obj)/vmlinuz + $(OBJCOPY) -O binary $(obj)/vmlinuz $(obj)/zImage diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/dummy.c b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/dummy.c new file mode 100644 index 000000000..31dbf45bf --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/dummy.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/head.S b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/head.S new file mode 100644 index 000000000..d9700eb50 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/head.S @@ -0,0 +1,85 @@ +/* + * linux/arch/mips/boot/compressed/head.S + * + * Copyright (C) 2005-2008 Ingenic Semiconductor Inc. + */ + +#include +#include +#include +#include + +#define IndexInvalidate_I 0x00 +#define IndexWriteBack_D 0x01 + + .set noreorder + LEAF(startup) +startup: + move s0, a0 /* Save the boot loader transfered args */ + move s1, a1 + move s2, a2 + move s3, a3 + + la a0, _edata + la a1, _end +1: sw zero, 0(a0) /* Clear BSS section */ + bne a1, a0, 1b + addu a0, 4 + + la sp, (.stack + 8192) + + la a0, __image_begin + la a1, IMAGESIZE + la a2, LOADADDR + la ra, 1f + la k0, decompress_kernel + jr k0 + nop +1: + + move a0, s0 + move a1, s1 + move a2, s2 + move a3, s3 + li k0, KERNEL_ENTRY + jr k0 + nop +2: + b 32 + END(startup) + + + LEAF(flushcaches) + la t0, 1f + la t1, 0xa0000000 + or t0, t0, t1 + jr t0 + nop +1: + li k0, 0x80000000 # start address + li k1, 0x80004000 # end address (16KB I-Cache) + subu k1, 128 + +2: + .set mips3 + cache IndexWriteBack_D, 0(k0) + cache IndexWriteBack_D, 32(k0) + cache IndexWriteBack_D, 64(k0) + cache IndexWriteBack_D, 96(k0) + cache IndexInvalidate_I, 0(k0) + cache IndexInvalidate_I, 32(k0) + cache IndexInvalidate_I, 64(k0) + cache IndexInvalidate_I, 96(k0) + .set mips0 + + bne k0, k1, 2b + addu k0, k0, 128 + la t0, 3f + jr t0 + nop +3: + jr ra + nop + END(flushcaches) + + .comm .stack,4096*2,4 diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/ld.script b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/ld.script new file mode 100644 index 000000000..fcf8ba041 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/ld.script @@ -0,0 +1,151 @@ +OUTPUT_ARCH(mips) +ENTRY(startup) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + + .init : { *(.init) } =0 + .text : + { + _ftext = . ; + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0 + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___dbe_table = .; /* Exception table for data bus errors */ + __dbe_table : { *(__dbe_table) } + __stop___dbe_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; + + . = ALIGN(8192); + .data.init_task : { *(.data.init_task) } + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + .fini : { *(.fini) } =0 + .reginfo : { *(.reginfo) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + .data : + { + _fdata = . ; + *(.data) + + /* Put the compressed image here, so bss is on the end. */ + __image_begin = .; + *(.image) + __image_end = .; + /* Align the initial ramdisk image (INITRD) on page boundaries. */ + . = ALIGN(4096); + __ramdisk_begin = .; + *(.initrd) + __ramdisk_end = .; + . = ALIGN(4096); + + CONSTRUCTORS + } + .data1 : { *(.data1) } + _gp = . + 0x8000; + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + . = ALIGN(4); + _edata = .; + PROVIDE (edata = .); + + __bss_start = .; + _fbss = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _end = . ; + PROVIDE (end = .); + } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + /* This is the MIPS specific mdebug section. */ + .mdebug : { *(.mdebug) } + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + .debug 0 : { *(.debug) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .line 0 : { *(.line) } + /* These must appear regardless of . */ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + .comment : { *(.comment) } + .note : { *(.note) } +} diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/misc.c b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/misc.c new file mode 100644 index 000000000..2309feea3 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/compressed/misc.c @@ -0,0 +1,242 @@ +/* + * linux/arch/mips/boot/compressed/misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * + * Adapted for JZSOC by Peter Wei, 2008 + * + */ + +#define size_t int +#define NULL 0 + +/* + * gzip declarations + */ + +#define OF(args) args +#define STATIC static + +#undef memset +#undef memcpy +#define memzero(s, n) memset ((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize = 0; /* valid bytes in inbuf */ +static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ +static unsigned outcnt = 0; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +void* memset(void* s, int c, size_t n); +void* memcpy(void* __dest, __const void* __src, size_t __n); + +extern void flushcaches(void); /* defined in head.S */ + +char *input_data; +int input_len; + +static long bytes_out = 0; +static uch *output_data; +static unsigned long output_ptr = 0; + + +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +static void puts(const char *str) +{ +} + +extern unsigned char _end[]; +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; + +#define HEAP_SIZE 0x10000 + +#include "../../../../lib/inflate.c" + +static void *malloc(int size) +{ + void *p; + + if (size <0) error("Malloc error\n"); + if (free_mem_ptr == 0) error("Memory error\n"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *)free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_end_ptr) + error("\nOut of memory\n"); + + return p; +} + +static void free(void *where) +{ /* Don't care */ +} + +static void gzip_mark(void **ptr) +{ + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + free_mem_ptr = (long) *ptr; +} + +void* memset(void* s, int c, size_t n) +{ + int i; + char *ss = (char*)s; + + for (i=0;i> 3; i > 0; i--) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 2) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 1) { + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1) + *d++ = *s++; + + return __dest; +} + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +static int fill_inbuf(void) +{ + if (insize != 0) { + error("ran out of input data\n"); + } + + inbuf = input_data; + insize = input_len; + inptr = 1; + return inbuf[0]; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +static void flush_window(void) +{ + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out++ = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; +} + +static void error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while(1); /* Halt */ +} + +void decompress_kernel(unsigned int imageaddr, unsigned int imagesize, unsigned int loadaddr) +{ + input_data = (char *)imageaddr; + input_len = imagesize; + output_ptr = 0; + output_data = (uch *)loadaddr; + free_mem_ptr = (unsigned long)_end; + free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; + + makecrc(); + puts("Uncompressing Linux..."); + gunzip(); + flushcaches(); + puts("Ok, booting the kernel."); +} diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/tools/entry b/target/linux/xburst/files-2.6.31/arch/mips/boot/tools/entry new file mode 100644 index 000000000..376e822a6 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/tools/entry @@ -0,0 +1,12 @@ +#!/bin/sh + +# grab the kernel_entry address from the vmlinux elf image +entry=`$1 $2 | grep kernel_entry` + +fs=`echo $entry | grep ffffffff` # check toolchain output + +if [ -n "$fs" ]; then + echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'` +else + echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'` +fi diff --git a/target/linux/xburst/files-2.6.31/arch/mips/boot/tools/filesize b/target/linux/xburst/files-2.6.31/arch/mips/boot/tools/filesize new file mode 100644 index 000000000..2142ad5af --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/boot/tools/filesize @@ -0,0 +1,7 @@ +#!/bin/sh +HOSTNAME=`uname` +if [ "$HOSTNAME" = "Linux" ]; then +echo `ls -l $1 | awk '{print $5}'` +else +echo `ls -l $1 | awk '{print $6}'` +fi diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/jzsoc.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/jzsoc.h new file mode 100644 index 000000000..acac226fc --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/jzsoc.h @@ -0,0 +1,26 @@ +/* + * linux/include/asm-mips/jzsoc.h + * + * Ingenic's JZXXXX SoC common include. + * + * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZSOC_H__ +#define __ASM_JZSOC_H__ + +/* + * SoC include + */ + +#ifdef CONFIG_SOC_JZ4740 +#include +#endif + +#endif /* __ASM_JZSOC_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-dipper.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-dipper.h new file mode 100644 index 000000000..ae84f24d5 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-dipper.h @@ -0,0 +1,69 @@ +/* + * linux/include/asm-mips/mach-jz4740/board-dipper.h + * + * JZ4725-based (16bit) Dipper board ver 1.x definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4725_DIPPER_H__ +#define __ASM_JZ4725_DIPPER_H__ + +/*====================================================================== + * Frequencies of on-board oscillators + */ +#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ +#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ + +/*====================================================================== + * GPIO JZ4725 + */ +#define GPIO_SD_VCC_EN_N 85 /* GPC21 */ +#define GPIO_SD_CD_N 91 /* GPC27 */ +#define GPIO_SD_WP 112 /* GPD16 */ +#define GPIO_USB_DETE 124 /* GPD28 */ +#define GPIO_DC_DETE_N 103 /* GPD7 */ +#define GPIO_CHARG_STAT_N 86 /* GPC22 */ +#define GPIO_DISP_OFF_N 118 /* GPD22 */ + +#define GPIO_UDC_HOTPLUG GPIO_USB_DETE + +/*====================================================================== + * MMC/SD + */ + +#define MSC_WP_PIN GPIO_SD_WP +#define MSC_HOTPLUG_PIN GPIO_SD_CD_N +#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) + +#define __msc_init_io() \ +do { \ + __gpio_as_output(GPIO_SD_VCC_EN_N); \ + __gpio_as_input(GPIO_SD_CD_N); \ +} while (0) + +#define __msc_enable_power() \ +do { \ + __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_disable_power() \ +do { \ + __gpio_set_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_card_detected(s) \ +({ \ + int detected = 1; \ + if (__gpio_get_pin(GPIO_SD_CD_N)) \ + detected = 0; \ + detected; \ +}) + +#endif /* __ASM_JZ4740_DIPPER_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-leo.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-leo.h new file mode 100644 index 000000000..4b883e288 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-leo.h @@ -0,0 +1,56 @@ +#ifndef __ASM_JZ4740_LEO_H__ +#define __ASM_JZ4740_LEO_H__ + +/* + * Define your board specific codes here !!! + */ + +/*====================================================================== + * Frequencies of on-board oscillators + */ +#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ +#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ + + +/*====================================================================== + * GPIO + */ +#define GPIO_DISP_OFF_N 100 +#define GPIO_SD_VCC_EN_N 119 +#define GPIO_SD_CD_N 120 +#define GPIO_SD_WP 111 + +/*====================================================================== + * MMC/SD + */ + +#define MSC_WP_PIN GPIO_SD_WP +#define MSC_HOTPLUG_PIN GPIO_SD_CD_N +#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) + +#define __msc_init_io() \ +do { \ + __gpio_as_output(GPIO_SD_VCC_EN_N); \ + __gpio_as_input(GPIO_SD_CD_N); \ +} while (0) + +#define __msc_enable_power() \ +do { \ + __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_disable_power() \ +do { \ + __gpio_set_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_card_detected(s) \ +({ \ + int detected = 1; \ + __gpio_as_input(GPIO_SD_CD_N); \ + if (__gpio_get_pin(GPIO_SD_CD_N)) \ + detected = 0; \ + detected; \ +}) + +#endif /* __ASM_JZ4740_BOARD_LEO_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-lyra.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-lyra.h new file mode 100644 index 000000000..29e0ce00f --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-lyra.h @@ -0,0 +1,70 @@ +/* + * linux/include/asm-mips/mach-jz4740/board-lyra.h + * + * JZ4740-based LYRA board ver 2.x definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4740_LYRA_H__ +#define __ASM_JZ4740_LYRA_H__ + +/*====================================================================== + * Frequencies of on-board oscillators + */ +#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ +#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ + + +/*====================================================================== + * GPIO + */ +#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ +#define GPIO_SD_CD_N 110 /* GPD14 */ +#define GPIO_SD_WP 112 /* GPD16 */ +#define GPIO_USB_DETE 102 /* GPD6 */ +#define GPIO_DC_DETE_N 103 /* GPD7 */ +#define GPIO_CHARG_STAT_N 111 /* GPD15 */ +#define GPIO_DISP_OFF_N 118 /* GPD22 */ +#define GPIO_LED_EN 124 /* GPD28 */ + +#define GPIO_UDC_HOTPLUG GPIO_USB_DETE +/*====================================================================== + * MMC/SD + */ + +#define MSC_WP_PIN GPIO_SD_WP +#define MSC_HOTPLUG_PIN GPIO_SD_CD_N +#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) + +#define __msc_init_io() \ +do { \ + __gpio_as_output(GPIO_SD_VCC_EN_N); \ + __gpio_as_input(GPIO_SD_CD_N); \ +} while (0) + +#define __msc_enable_power() \ +do { \ + __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_disable_power() \ +do { \ + __gpio_set_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_card_detected(s) \ +({ \ + int detected = 1; \ + if (!(__gpio_get_pin(GPIO_SD_CD_N))) \ + detected = 0; \ + detected; \ +}) + +#endif /* __ASM_JZ4740_LYRA_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-pavo.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-pavo.h new file mode 100644 index 000000000..f33831b89 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-pavo.h @@ -0,0 +1,70 @@ +/* + * linux/include/asm-mips/mach-jz4740/board-pavo.h + * + * JZ4730-based PAVO board ver 2.x definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4740_PAVO_H__ +#define __ASM_JZ4740_PAVO_H__ + +/*====================================================================== + * Frequencies of on-board oscillators + */ +#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ +#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ + + +/*====================================================================== + * GPIO + */ +#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ +#define GPIO_SD_CD_N 110 /* GPD14 */ +#define GPIO_SD_WP 112 /* GPD16 */ +#define GPIO_USB_DETE 102 /* GPD6 */ +#define GPIO_DC_DETE_N 103 /* GPD7 */ +#define GPIO_CHARG_STAT_N 111 /* GPD15 */ +#define GPIO_DISP_OFF_N 118 /* GPD22 */ +#define GPIO_LED_EN 124 /* GPD28 */ + +#define GPIO_UDC_HOTPLUG GPIO_USB_DETE +/*====================================================================== + * MMC/SD + */ + +#define MSC_WP_PIN GPIO_SD_WP +#define MSC_HOTPLUG_PIN GPIO_SD_CD_N +#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) + +#define __msc_init_io() \ +do { \ + __gpio_as_output(GPIO_SD_VCC_EN_N); \ + __gpio_as_input(GPIO_SD_CD_N); \ +} while (0) + +#define __msc_enable_power() \ +do { \ + __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_disable_power() \ +do { \ + __gpio_set_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_card_detected(s) \ +({ \ + int detected = 1; \ + if (__gpio_get_pin(GPIO_SD_CD_N)) \ + detected = 0; \ + detected; \ +}) + +#endif /* __ASM_JZ4740_PAVO_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-virgo.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-virgo.h new file mode 100644 index 000000000..acd7bb717 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/board-virgo.h @@ -0,0 +1,67 @@ +/* + * linux/include/asm-mips/mach-jz4740/board-virgo.h + * + * JZ4720-based VIRGO board ver 1.x definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4720_VIRGO_H__ +#define __ASM_JZ4720_VIRGO_H__ + +/*====================================================================== + * Frequencies of on-board oscillators + */ +#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ +#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ + +/*====================================================================== + * GPIO VIRGO(JZ4720) + */ +#define GPIO_SD_VCC_EN_N 115 /* GPD19 */ +#define GPIO_SD_CD_N 116 /* GPD20 */ +#define GPIO_USB_DETE 114 /* GPD18 */ +#define GPIO_DC_DETE_N 120 /* GPD24 */ +#define GPIO_DISP_OFF_N 118 /* GPD22 */ +#define GPIO_LED_EN 117 /* GPD21 */ + +#define GPIO_UDC_HOTPLUG GPIO_USB_DETE + +/*====================================================================== + * MMC/SD + */ + +#define MSC_HOTPLUG_PIN GPIO_SD_CD_N +#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) + +#define __msc_init_io() \ +do { \ + __gpio_as_output(GPIO_SD_VCC_EN_N); \ + __gpio_as_input(GPIO_SD_CD_N); \ +} while (0) + +#define __msc_enable_power() \ +do { \ + __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_disable_power() \ +do { \ + __gpio_set_pin(GPIO_SD_VCC_EN_N); \ +} while (0) + +#define __msc_card_detected(s) \ +({ \ + int detected = 1; \ + if (__gpio_get_pin(GPIO_SD_CD_N)) \ + detected = 0; \ + detected; \ +}) + +#endif /* __ASM_JZ4720_VIRGO_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/clock.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/clock.h new file mode 100644 index 000000000..11ffe8894 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/clock.h @@ -0,0 +1,173 @@ +/* + * linux/include/asm-mips/mach-jz4740/clock.h + * + * JZ4740 clocks definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4740_CLOCK_H__ +#define __ASM_JZ4740_CLOCK_H__ + +#ifndef JZ_EXTAL +//#define JZ_EXTAL 3686400 /* 3.6864 MHz */ +#define JZ_EXTAL 12000000 /* 3.6864 MHz */ +#endif +#ifndef JZ_EXTAL2 +#define JZ_EXTAL2 32768 /* 32.768 KHz */ +#endif + +/* + * JZ4740 clocks structure + */ +typedef struct { + unsigned int cclk; /* CPU clock */ + unsigned int hclk; /* System bus clock */ + unsigned int pclk; /* Peripheral bus clock */ + unsigned int mclk; /* Flash/SRAM/SDRAM clock */ + unsigned int lcdclk; /* LCDC module clock */ + unsigned int pixclk; /* LCD pixel clock */ + unsigned int i2sclk; /* AIC module clock */ + unsigned int usbclk; /* USB module clock */ + unsigned int mscclk; /* MSC module clock */ + unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ + unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ +} jz_clocks_t; + +extern jz_clocks_t jz_clocks; + + +/* PLL output frequency */ +static __inline__ unsigned int __cpm_get_pllout(void) +{ + unsigned long m, n, no, pllout; + unsigned long cppcr = REG_CPM_CPPCR; + unsigned long od[4] = {1, 2, 2, 4}; + if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { + m = __cpm_get_pllm() + 2; + n = __cpm_get_plln() + 2; + no = od[__cpm_get_pllod()]; + pllout = ((JZ_EXTAL) / (n * no)) * m; + } else + pllout = JZ_EXTAL; + return pllout; +} + +/* PLL output frequency for MSC/I2S/LCD/USB */ +static __inline__ unsigned int __cpm_get_pllout2(void) +{ + if (REG_CPM_CPCCR & CPM_CPCCR_PCS) + return __cpm_get_pllout(); + else + return __cpm_get_pllout()/2; +} + +/* CPU core clock */ +static __inline__ unsigned int __cpm_get_cclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_cdiv()]; +} + +/* AHB system bus clock */ +static __inline__ unsigned int __cpm_get_hclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_hdiv()]; +} + +/* Memory bus clock */ +static __inline__ unsigned int __cpm_get_mclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_mdiv()]; +} + +/* APB peripheral bus clock */ +static __inline__ unsigned int __cpm_get_pclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_pdiv()]; +} + +/* LCDC module clock */ +static __inline__ unsigned int __cpm_get_lcdclk(void) +{ + return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); +} + +/* LCD pixel clock */ +static __inline__ unsigned int __cpm_get_pixclk(void) +{ + return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); +} + +/* I2S clock */ +static __inline__ unsigned int __cpm_get_i2sclk(void) +{ + if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { + return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); + } + else { + return JZ_EXTAL; + } +} + +/* USB clock */ +static __inline__ unsigned int __cpm_get_usbclk(void) +{ + if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { + return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); + } + else { + return JZ_EXTAL; + } +} + +/* MSC clock */ +static __inline__ unsigned int __cpm_get_mscclk(void) +{ + return __cpm_get_pllout2() / (__cpm_get_mscdiv() + 1); +} + +/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ +static __inline__ unsigned int __cpm_get_extalclk(void) +{ + return JZ_EXTAL; +} + +/* RTC clock for CPM,INTC,RTC,TCU,WDT */ +static __inline__ unsigned int __cpm_get_rtcclk(void) +{ + return JZ_EXTAL2; +} + +/* + * Output 24MHz for SD and 16MHz for MMC. + */ +static inline void __cpm_select_msc_clk(int sd) +{ + unsigned int pllout2 = __cpm_get_pllout2(); + unsigned int div = 0; + + if (sd) { + div = pllout2 / 24000000; + } + else { + div = pllout2 / 16000000; + } + + REG_CPM_MSCCDR = div - 1; +} + +#endif /* __ASM_JZ4740_CLOCK_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/dma.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/dma.h new file mode 100644 index 000000000..b82b984ea --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/dma.h @@ -0,0 +1,265 @@ +/* + * linux/include/asm-mips/mach-jz4740/dma.h + * + * JZ4740 DMA definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4740_DMA_H__ +#define __ASM_JZ4740_DMA_H__ + +#include +#include /* need byte IO */ +#include /* And spinlocks */ +#include +#include + +/* + * Descriptor structure for JZ4740 DMA engine + * Note: this structure must always be aligned to a 16-bytes boundary. + */ + +typedef struct { + volatile u32 dcmd; /* DCMD value for the current transfer */ + volatile u32 dsadr; /* DSAR value for the current transfer */ + volatile u32 dtadr; /* DTAR value for the current transfer */ + volatile u32 ddadr; /* Points to the next descriptor + transfer count */ +} jz_dma_desc; + + +/* DMA Device ID's follow */ +enum { + DMA_ID_UART0_TX = 0, + DMA_ID_UART0_RX, + DMA_ID_SSI_TX, + DMA_ID_SSI_RX, + DMA_ID_AIC_TX, + DMA_ID_AIC_RX, + DMA_ID_MSC_TX, + DMA_ID_MSC_RX, + DMA_ID_TCU_OVERFLOW, + DMA_ID_AUTO, + DMA_ID_RAW_SET, + DMA_ID_MAX +}; + +/* DMA modes, simulated by sw */ +#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_AUTOINIT 0x2 +#define DMA_MODE_MASK 0x3 + +struct jz_dma_chan { + int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ + unsigned int io; /* DMA channel number */ + const char *dev_str; /* string describes the DMA channel */ + int irq; /* DMA irq number */ + void *irq_dev; /* DMA private device structure */ + unsigned int fifo_addr; /* physical fifo address of the requested device */ + unsigned int cntl; /* DMA controll */ + unsigned int mode; /* DMA configuration */ + unsigned int source; /* DMA request source */ +}; + +extern struct jz_dma_chan jz_dma_table[]; + + +#define DMA_8BIT_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_8BIT_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ + DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_16BIT_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_16BIT_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_32BIT_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_32BIT_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_16BYTE_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_16BYTE_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_32BYTE_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_32BYTE_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ + DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_AIC_32_16BYTE_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_AIC_32_16BYTE_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_AIC_16BIT_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_AIC_16BIT_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN + +#define DMA_AIC_16BYTE_RX_CMD \ + DMAC_DCMD_DAI | \ + DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN + +#define DMA_AIC_16BYTE_TX_CMD \ + DMAC_DCMD_SAI | \ + DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN + +extern int jz_request_dma(int dev_id, + const char *dev_str, + irqreturn_t (*irqhandler)(int, void *), + unsigned long irqflags, + void *irq_dev_id); +extern void jz_free_dma(unsigned int dmanr); + +extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, + int length, int *eof, void *data); +extern void dump_jz_dma_channel(unsigned int dmanr); + +extern void enable_dma(unsigned int dmanr); +extern void disable_dma(unsigned int dmanr); +extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); +extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); +extern void set_dma_mode(unsigned int dmanr, unsigned int mode); +extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); +extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); +extern unsigned int get_dma_residue(unsigned int dmanr); + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + */ +#define clear_dma_ff(channel) + +static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) +{ + if (dmanr > MAX_DMA_NUM + || jz_dma_table[dmanr].dev_id < 0) + return NULL; + return &jz_dma_table[dmanr]; +} + +static __inline__ int dma_halted(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return 1; + return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; +} + +static __inline__ unsigned int get_dma_mode(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return 0; + return chan->mode; +} + +static __inline__ void clear_dma_done(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return; + REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); +} + +static __inline__ void clear_dma_halt(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return; + REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); + REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT); +} + +static __inline__ void clear_dma_flag(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return; + REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); + REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); +} + +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ +} + +static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) +{ + unsigned long dccsr; + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return 0; + dccsr = REG_DMAC_DCCSR(chan->io); + return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); +} + +static __inline__ int get_dma_done_irq(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return -1; + return chan->irq; +} + +#endif /* __ASM_JZ4740_DMA_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/jz4740.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/jz4740.h new file mode 100644 index 000000000..437caf454 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/jz4740.h @@ -0,0 +1,56 @@ +/* + * linux/include/asm-mips/mach-jz4740/jz4740.h + * + * JZ4740 common definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4740_H__ +#define __ASM_JZ4740_H__ + +#include +#include +#include +#include + +/*------------------------------------------------------------------ + * Platform definitions + */ +#ifdef CONFIG_JZ4740_PAVO +#include +#endif + +#ifdef CONFIG_JZ4740_LEO +#include +#endif + +#ifdef CONFIG_JZ4740_LYRA +#include +#endif + +#ifdef CONFIG_JZ4725_DIPPER +#include +#endif + +#ifdef CONFIG_JZ4720_VIRGO +#include +#endif + +/* Add other platform definition here ... */ + + +/*------------------------------------------------------------------ + * Follows are related to platform definitions + */ + +#include +#include + +#endif /* __ASM_JZ4740_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/misc.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/misc.h new file mode 100644 index 000000000..8f14a5ace --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/misc.h @@ -0,0 +1,43 @@ +/* + * linux/include/asm-mips/mach-jz4740/misc.h + * + * Ingenic's JZ4740 common include. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_JZ4740_MISC_H__ +#define __ASM_JZ4740_MISC_H__ + +/*========================================================== + * I2C + *===========================================================*/ + +#define I2C_EEPROM_DEV 0xA /* b'1010 */ +#define I2C_RTC_DEV 0xD /* b'1101 */ +#define DIMM0_SPD_ADDR 0 +#define DIMM1_SPD_ADDR 1 +#define DIMM2_SPD_ADDR 2 +#define DIMM3_SPD_ADDR 3 +#define JZ_HCI_ADDR 7 + +#define DIMM_SPD_LEN 128 +#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ +#define I2C_RTC_LEN 16 +#define HCI_MAC_OFFSET 64 + +extern void i2c_open(void); +extern void i2c_close(void); +extern void i2c_setclk(unsigned int i2cclk); +extern int i2c_read(unsigned char device, unsigned char *buf, + unsigned char address, int count); +extern int i2c_write(unsigned char device, unsigned char *buf, + unsigned char address, int count); + +#endif /* __ASM_JZ4740_MISC_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/ops.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/ops.h new file mode 100644 index 000000000..6ff050a63 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/ops.h @@ -0,0 +1,2224 @@ +/* + * linux/include/asm-mips/mach-jz4740/ops.h + * + * Ingenic's JZ4740 common include. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +#ifndef __JZ4740_OPS_H__ +#define __JZ4740_OPS_H__ + +/* + * Definition of Module Operations + */ + +/*************************************************************************** + * GPIO + ***************************************************************************/ + +//------------------------------------------------------ +// GPIO Pins Description +// +// PORT 0: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 D0 - +// 1 D1 - +// 2 D2 - +// 3 D3 - +// 4 D4 - +// 5 D5 - +// 6 D6 - +// 7 D7 - +// 8 D8 - +// 9 D9 - +// 10 D10 - +// 11 D11 - +// 12 D12 - +// 13 D13 - +// 14 D14 - +// 15 D15 - +// 16 D16 - +// 17 D17 - +// 18 D18 - +// 19 D19 - +// 20 D20 - +// 21 D21 - +// 22 D22 - +// 23 D23 - +// 24 D24 - +// 25 D25 - +// 26 D26 - +// 27 D27 - +// 28 D28 - +// 29 D29 - +// 30 D30 - +// 31 D31 - +// +//------------------------------------------------------ +// PORT 1: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 A0 - +// 1 A1 - +// 2 A2 - +// 3 A3 - +// 4 A4 - +// 5 A5 - +// 6 A6 - +// 7 A7 - +// 8 A8 - +// 9 A9 - +// 10 A10 - +// 11 A11 - +// 12 A12 - +// 13 A13 - +// 14 A14 - +// 15 A15/CL - +// 16 A16/AL - +// 17 LCD_CLS A21 +// 18 LCD_SPL A22 +// 19 DCS# - +// 20 RAS# - +// 21 CAS# - +// 22 RDWE#/BUFD# - +// 23 CKE - +// 24 CKO - +// 25 CS1# - +// 26 CS2# - +// 27 CS3# - +// 28 CS4# - +// 29 RD# - +// 30 WR# - +// 31 WE0# - +// +// Note: PIN15&16 are CL&AL when connecting to NAND flash. +//------------------------------------------------------ +// PORT 2: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 LCD_D0 - +// 1 LCD_D1 - +// 2 LCD_D2 - +// 3 LCD_D3 - +// 4 LCD_D4 - +// 5 LCD_D5 - +// 6 LCD_D6 - +// 7 LCD_D7 - +// 8 LCD_D8 - +// 9 LCD_D9 - +// 10 LCD_D10 - +// 11 LCD_D11 - +// 12 LCD_D12 - +// 13 LCD_D13 - +// 14 LCD_D14 - +// 15 LCD_D15 - +// 16 LCD_D16 - +// 17 LCD_D17 - +// 18 LCD_PCLK - +// 19 LCD_HSYNC - +// 20 LCD_VSYNC - +// 21 LCD_DE - +// 22 LCD_PS A19 +// 23 LCD_REV A20 +// 24 WE1# - +// 25 WE2# - +// 26 WE3# - +// 27 WAIT# - +// 28 FRE# - +// 29 FWE# - +// 30(NOTE:FRB#) - - +// 31 - - +// +// NOTE(1): PIN30 is used for FRB# when connecting to NAND flash. +//------------------------------------------------------ +// PORT 3: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 CIM_D0 - +// 1 CIM_D1 - +// 2 CIM_D2 - +// 3 CIM_D3 - +// 4 CIM_D4 - +// 5 CIM_D5 - +// 6 CIM_D6 - +// 7 CIM_D7 - +// 8 MSC_CMD - +// 9 MSC_CLK - +// 10 MSC_D0 - +// 11 MSC_D1 - +// 12 MSC_D2 - +// 13 MSC_D3 - +// 14 CIM_MCLK - +// 15 CIM_PCLK - +// 16 CIM_VSYNC - +// 17 CIM_HSYNC - +// 18 SSI_CLK SCLK_RSTN +// 19 SSI_CE0# BIT_CLK(AIC) +// 20 SSI_DT SDATA_OUT(AIC) +// 21 SSI_DR SDATA_IN(AIC) +// 22 SSI_CE1#&GPC SYNC(AIC) +// 23 PWM0 I2C_SDA +// 24 PWM1 I2C_SCK +// 25 PWM2 UART0_TxD +// 26 PWM3 UART0_RxD +// 27 PWM4 A17 +// 28 PWM5 A18 +// 29 - - +// 30 PWM6 UART0_CTS/UART1_RxD +// 31 PWM7 UART0_RTS/UART1_TxD +// +////////////////////////////////////////////////////////// + +/* + * p is the port number (0,1,2,3) + * o is the pin offset (0-31) inside the port + * n is the absolute number of a pin (0-127), regardless of the port + */ + +//------------------------------------------- +// Function Pins Mode + +#define __gpio_as_func0(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXFUNS(p) = (1 << o); \ + REG_GPIO_PXSELC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_func1(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXFUNS(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ +} while (0) + +/* + * D0 ~ D31, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, + * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# + */ +#define __gpio_as_sdram_32bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0xffffffff; \ + REG_GPIO_PXSELC(0) = 0xffffffff; \ + REG_GPIO_PXPES(0) = 0xffffffff; \ + REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ + REG_GPIO_PXSELC(1) = 0x81f9ffff; \ + REG_GPIO_PXPES(1) = 0x81f9ffff; \ + REG_GPIO_PXFUNS(2) = 0x07000000; \ + REG_GPIO_PXSELC(2) = 0x07000000; \ + REG_GPIO_PXPES(2) = 0x07000000; \ +} while (0) + +/* + * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, + * RDWE#, CKO#, WE0#, WE1# + */ +#define __gpio_as_sdram_16bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x5442bfaa; \ + REG_GPIO_PXSELC(0) = 0x5442bfaa; \ + REG_GPIO_PXPES(0) = 0x5442bfaa; \ + REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ + REG_GPIO_PXSELC(1) = 0x81f9ffff; \ + REG_GPIO_PXPES(1) = 0x81f9ffff; \ + REG_GPIO_PXFUNS(2) = 0x01000000; \ + REG_GPIO_PXSELC(2) = 0x01000000; \ + REG_GPIO_PXPES(2) = 0x01000000; \ +} while (0) + +/* + * CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# + */ +#define __gpio_as_nand() \ +do { \ + REG_GPIO_PXFUNS(1) = 0x02018000; \ + REG_GPIO_PXSELC(1) = 0x02018000; \ + REG_GPIO_PXPES(1) = 0x02018000; \ + REG_GPIO_PXFUNS(2) = 0x30000000; \ + REG_GPIO_PXSELC(2) = 0x30000000; \ + REG_GPIO_PXPES(2) = 0x30000000; \ + REG_GPIO_PXFUNC(2) = 0x40000000; \ + REG_GPIO_PXSELC(2) = 0x40000000; \ + REG_GPIO_PXDIRC(2) = 0x40000000; \ + REG_GPIO_PXPES(2) = 0x40000000; \ + REG_GPIO_PXFUNS(1) = 0x00400000; \ + REG_GPIO_PXSELC(1) = 0x00400000; \ +} while (0) + +/* + * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 + */ +#define __gpio_as_nor_8bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x000000ff; \ + REG_GPIO_PXSELC(0) = 0x000000ff; \ + REG_GPIO_PXPES(0) = 0x000000ff; \ + REG_GPIO_PXFUNS(1) = 0x7041ffff; \ + REG_GPIO_PXSELC(1) = 0x7041ffff; \ + REG_GPIO_PXPES(1) = 0x7041ffff; \ + REG_GPIO_PXFUNS(1) = 0x00060000; \ + REG_GPIO_PXSELS(1) = 0x00060000; \ + REG_GPIO_PXPES(1) = 0x00060000; \ + REG_GPIO_PXFUNS(2) = 0x08000000; \ + REG_GPIO_PXSELC(2) = 0x08000000; \ + REG_GPIO_PXPES(2) = 0x08000000; \ + REG_GPIO_PXFUNS(2) = 0x00c00000; \ + REG_GPIO_PXSELS(2) = 0x00c00000; \ + REG_GPIO_PXPES(2) = 0x00c00000; \ + REG_GPIO_PXFUNS(3) = 0x18000000; \ + REG_GPIO_PXSELS(3) = 0x18000000; \ + REG_GPIO_PXPES(3) = 0x18000000; \ +} while (0) + +/* + * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 + */ +#define __gpio_as_nor_16bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x0000ffff; \ + REG_GPIO_PXSELC(0) = 0x0000ffff; \ + REG_GPIO_PXPES(0) = 0x0000ffff; \ + REG_GPIO_PXFUNS(1) = 0x7041ffff; \ + REG_GPIO_PXSELC(1) = 0x7041ffff; \ + REG_GPIO_PXPES(1) = 0x7041ffff; \ + REG_GPIO_PXFUNS(1) = 0x00060000; \ + REG_GPIO_PXSELS(1) = 0x00060000; \ + REG_GPIO_PXPES(1) = 0x00060000; \ + REG_GPIO_PXFUNS(2) = 0x08000000; \ + REG_GPIO_PXSELC(2) = 0x08000000; \ + REG_GPIO_PXPES(2) = 0x08000000; \ + REG_GPIO_PXFUNS(2) = 0x00c00000; \ + REG_GPIO_PXSELS(2) = 0x00c00000; \ + REG_GPIO_PXPES(2) = 0x00c00000; \ + REG_GPIO_PXFUNS(3) = 0x18000000; \ + REG_GPIO_PXSELS(3) = 0x18000000; \ + REG_GPIO_PXPES(3) = 0x18000000; \ +} while (0) + +/* + * UART0_TxD, UART_RxD0 + */ +#define __gpio_as_uart0() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x06000000; \ + REG_GPIO_PXSELS(3) = 0x06000000; \ + REG_GPIO_PXPES(3) = 0x06000000; \ +} while (0) + +/* + * UART0_CTS, UART0_RTS + */ +#define __gpio_as_ctsrts() \ +do { \ + REG_GPIO_PXFUNS(3) = 0xc0000000; \ + REG_GPIO_PXSELS(3) = 0xc0000000; \ + REG_GPIO_PXTRGC(3) = 0xc0000000; \ + REG_GPIO_PXPES(3) = 0xc0000000; \ +} while (0) + +/* + * UART1_TxD, UART1_RxD1 + */ +#define __gpio_as_uart1() \ +do { \ + REG_GPIO_PXFUNS(3) = 0xc0000000; \ + REG_GPIO_PXSELC(3) = 0xc0000000; \ + REG_GPIO_PXTRGS(3) = 0xc0000000; \ + REG_GPIO_PXPES(3) = 0xc0000000; \ +} while (0) + +/* + * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE + */ +#define __gpio_as_lcd_16bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x003cffff; \ + REG_GPIO_PXSELC(2) = 0x003cffff; \ + REG_GPIO_PXPES(2) = 0x003cffff; \ +} while (0) + +/* + * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE + */ +#define __gpio_as_lcd_18bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x003fffff; \ + REG_GPIO_PXSELC(2) = 0x003fffff; \ + REG_GPIO_PXPES(2) = 0x003fffff; \ +} while (0) + +/* + * LCD_PS, LCD_REV, LCD_CLS, LCD_SPL + */ +#define __gpio_as_lcd_special() \ +do { \ + REG_GPIO_PXFUNS(1) = 0x00060000; \ + REG_GPIO_PXSELC(1) = 0x00060000; \ + REG_GPIO_PXPES(1) = 0x00060000; \ + REG_GPIO_PXFUNS(2) = 0x00c00000; \ + REG_GPIO_PXSELC(2) = 0x00c00000; \ + REG_GPIO_PXPES(2) = 0x00c00000; \ +} while (0) + +/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_8bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x001800ff; \ + REG_GPIO_PXSELC(2) = 0x001800ff; \ +} while (0) + +/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_9bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x001801ff; \ + REG_GPIO_PXSELC(2) = 0x001801ff; \ +} while (0) + +/* LCD_D0~LCD_D15, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_16bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x0018ffff; \ + REG_GPIO_PXSELC(2) = 0x0018ffff; \ +} while (0) + +/* LCD_D0~LCD_D17, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_18bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x001bffff; \ + REG_GPIO_PXSELC(2) = 0x001bffff; \ +} while (0) + +/* + * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC + */ +#define __gpio_as_cim() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x0003c0ff; \ + REG_GPIO_PXSELC(3) = 0x0003c0ff; \ + REG_GPIO_PXPES(3) = 0x0003c0ff; \ +} while (0) + +/* + * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET + */ +#define __gpio_as_aic() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x007c0000; \ + REG_GPIO_PXSELS(3) = 0x007c0000; \ + REG_GPIO_PXPES(3) = 0x007c0000; \ +} while (0) + +/* + * MSC_CMD, MSC_CLK, MSC_D0 ~ MSC_D3 + */ +#define __gpio_as_msc() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x00003f00; \ + REG_GPIO_PXSELC(3) = 0x00003f00; \ + REG_GPIO_PXPES(3) = 0x00003f00; \ +} while (0) + +/* + * SSI_CS0, SSI_CLK, SSI_DT, SSI_DR + */ +#define __gpio_as_ssi() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x003c0000; \ + REG_GPIO_PXSELC(3) = 0x003c0000; \ + REG_GPIO_PXPES(3) = 0x003c0000; \ +} while (0) + +/* + * I2C_SCK, I2C_SDA + */ +#define __gpio_as_i2c() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x01800000; \ + REG_GPIO_PXSELS(3) = 0x01800000; \ + REG_GPIO_PXPES(3) = 0x01800000; \ +} while (0) + +/* + * PWM0 + */ +#define __gpio_as_pwm0() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x00800000; \ + REG_GPIO_PXSELC(3) = 0x00800000; \ + REG_GPIO_PXPES(3) = 0x00800000; \ +} while (0) + +/* + * PWM1 + */ +#define __gpio_as_pwm1() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x01000000; \ + REG_GPIO_PXSELC(3) = 0x01000000; \ + REG_GPIO_PXPES(3) = 0x01000000; \ +} while (0) + +/* + * PWM2 + */ +#define __gpio_as_pwm2() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x02000000; \ + REG_GPIO_PXSELC(3) = 0x02000000; \ + REG_GPIO_PXPES(3) = 0x02000000; \ +} while (0) + +/* + * PWM3 + */ +#define __gpio_as_pwm3() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x04000000; \ + REG_GPIO_PXSELC(3) = 0x04000000; \ + REG_GPIO_PXPES(3) = 0x04000000; \ +} while (0) + +/* + * PWM4 + */ +#define __gpio_as_pwm4() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x08000000; \ + REG_GPIO_PXSELC(3) = 0x08000000; \ + REG_GPIO_PXPES(3) = 0x08000000; \ +} while (0) + +/* + * PWM5 + */ +#define __gpio_as_pwm5() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x10000000; \ + REG_GPIO_PXSELC(3) = 0x10000000; \ + REG_GPIO_PXPES(3) = 0x10000000; \ +} while (0) + +/* + * PWM6 + */ +#define __gpio_as_pwm6() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x40000000; \ + REG_GPIO_PXSELC(3) = 0x40000000; \ + REG_GPIO_PXPES(3) = 0x40000000; \ +} while (0) + +/* + * PWM7 + */ +#define __gpio_as_pwm7() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x80000000; \ + REG_GPIO_PXSELC(3) = 0x80000000; \ + REG_GPIO_PXPES(3) = 0x80000000; \ +} while (0) + +/* + * n = 0 ~ 7 + */ +#define __gpio_as_pwm(n) __gpio_as_pwm##n() + +//------------------------------------------- +// GPIO or Interrupt Mode + +#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) + +#define __gpio_port_as_output(p, o) \ +do { \ + REG_GPIO_PXFUNC(p) = (1 << (o)); \ + REG_GPIO_PXSELC(p) = (1 << (o)); \ + REG_GPIO_PXDIRS(p) = (1 << (o)); \ +} while (0) + +#define __gpio_port_as_input(p, o) \ +do { \ + REG_GPIO_PXFUNC(p) = (1 << (o)); \ + REG_GPIO_PXSELC(p) = (1 << (o)); \ + REG_GPIO_PXDIRC(p) = (1 << (o)); \ +} while (0) + +#define __gpio_as_output(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + __gpio_port_as_output(p, o); \ +} while (0) + +#define __gpio_as_input(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + __gpio_port_as_input(p, o); \ +} while (0) + +#define __gpio_set_pin(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXDATS(p) = (1 << o); \ +} while (0) + +#define __gpio_clear_pin(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXDATC(p) = (1 << o); \ +} while (0) + +#define __gpio_get_pin(n) \ +({ \ + unsigned int p, o, v; \ + p = (n) / 32; \ + o = (n) % 32; \ + if (__gpio_get_port(p) & (1 << o)) \ + v = 1; \ + else \ + v = 0; \ + v; \ +}) + +#define __gpio_as_irq_high_level(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGC(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRS(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_irq_low_level(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGC(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRC(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_irq_rise_edge(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGS(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRS(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_irq_fall_edge(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGS(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRC(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_mask_irq(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ +} while (0) + +#define __gpio_unmask_irq(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_ack_irq(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXFLGC(p) = (1 << o); \ +} while (0) + +#define __gpio_get_irq() \ +({ \ + unsigned int p, i, tmp, v = 0; \ + for (p = 3; p >= 0; p--) { \ + tmp = REG_GPIO_PXFLG(p); \ + for (i = 0; i < 32; i++) \ + if (tmp & (1 << i)) \ + v = (32*p + i); \ + } \ + v; \ +}) + +#define __gpio_group_irq(n) \ +({ \ + register int tmp, i; \ + tmp = REG_GPIO_PXFLG((n)); \ + for (i=31;i>=0;i--) \ + if (tmp & (1 << i)) \ + break; \ + i; \ +}) + +#define __gpio_enable_pull(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXPEC(p) = (1 << o); \ +} while (0) + +#define __gpio_disable_pull(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXPES(p) = (1 << o); \ +} while (0) + + +/*************************************************************************** + * CPM + ***************************************************************************/ +#define __cpm_get_pllm() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) +#define __cpm_get_plln() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) +#define __cpm_get_pllod() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) + +#define __cpm_get_cdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) +#define __cpm_get_hdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) +#define __cpm_get_pdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) +#define __cpm_get_mdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) +#define __cpm_get_ldiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) +#define __cpm_get_udiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) +#define __cpm_get_i2sdiv() \ + ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) +#define __cpm_get_pixdiv() \ + ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) +#define __cpm_get_mscdiv() \ + ((REG_CPM_MSCCDR & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) +#define __cpm_get_uhcdiv() \ + ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) +#define __cpm_get_ssidiv() \ + ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) + +#define __cpm_set_cdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) +#define __cpm_set_hdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) +#define __cpm_set_pdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) +#define __cpm_set_mdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) +#define __cpm_set_ldiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) +#define __cpm_set_udiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) +#define __cpm_set_i2sdiv(v) \ + (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) +#define __cpm_set_pixdiv(v) \ + (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) +#define __cpm_set_mscdiv(v) \ + (REG_CPM_MSCCDR = (REG_CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) +#define __cpm_set_uhcdiv(v) \ + (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) +#define __cpm_ssiclk_select_exclk() \ + (REG_CPM_SSICDR &= ~CPM_SSICDR_SCS) +#define __cpm_ssiclk_select_pllout() \ + (REG_CPM_SSICDR |= CPM_SSICDR_SCS) +#define __cpm_set_ssidiv(v) \ + (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) + +#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) +#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) +#define __cpm_enable_cko() (REG_CPM_CPCCR |= CPM_CPCCR_CLKOEN) +#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) +#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) +#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) +#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) +#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) + +#define __cpm_pll_is_on() (REG_CPM_CPPCR & CPM_CPPCR_PLLS) +#define __cpm_pll_bypass() (REG_CPM_CPPCR |= CPM_CPPCR_PLLBP) +#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) + +#define __cpm_get_cclk_doze_duty() \ + ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) +#define __cpm_set_cclk_doze_duty(v) \ + (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) + +#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) +#define __cpm_idle_mode() \ + (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) +#define __cpm_sleep_mode() \ + (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) + +#define __cpm_stop_all() (REG_CPM_CLKGR = 0x7fff) +#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) +#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) +#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) +#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) +#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) +#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) +#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) +#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) +#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC) +#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) +#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) +#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI) +#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) +#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) +#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) +#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) + +#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) +#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) +#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) +#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) +#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) +#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) +#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) +#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) +#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) +#define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC) +#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) +#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) +#define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI) +#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) +#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) +#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) +#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) + +#define __cpm_get_o1st() \ + ((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT) +#define __cpm_set_o1st(v) \ + (REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT))) +#define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_SUSPEND) +#define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE) + + +/*************************************************************************** + * TCU + ***************************************************************************/ +// where 'n' is the TCU channel +#define __tcu_select_extalclk(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) +#define __tcu_select_rtcclk(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) +#define __tcu_select_pclk(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) + +#define __tcu_select_clk_div1(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) +#define __tcu_select_clk_div4(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) +#define __tcu_select_clk_div16(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) +#define __tcu_select_clk_div64(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) +#define __tcu_select_clk_div256(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) +#define __tcu_select_clk_div1024(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) + +#define __tcu_enable_pwm_output(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN ) +#define __tcu_disable_pwm_output(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN ) + +#define __tcu_init_pwm_output_high(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH ) +#define __tcu_init_pwm_output_low(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH ) + +#define __tcu_set_pwm_output_shutdown_graceful(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD ) +#define __tcu_set_pwm_output_shutdown_abrupt(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD ) + +#define __tcu_start_counter(n) ( REG_TCU_TESR |= (1 << (n)) ) +#define __tcu_stop_counter(n) ( REG_TCU_TECR |= (1 << (n)) ) + +#define __tcu_half_match_flag(n) ( REG_TCU_TFR & (1 << ((n) + 16)) ) +#define __tcu_full_match_flag(n) ( REG_TCU_TFR & (1 << (n)) ) +#define __tcu_set_half_match_flag(n) ( REG_TCU_TFSR = (1 << ((n) + 16)) ) +#define __tcu_set_full_match_flag(n) ( REG_TCU_TFSR = (1 << (n)) ) +#define __tcu_clear_half_match_flag(n) ( REG_TCU_TFCR = (1 << ((n) + 16)) ) +#define __tcu_clear_full_match_flag(n) ( REG_TCU_TFCR = (1 << (n)) ) +#define __tcu_mask_half_match_irq(n) ( REG_TCU_TMSR = (1 << ((n) + 16)) ) +#define __tcu_mask_full_match_irq(n) ( REG_TCU_TMSR = (1 << (n)) ) +#define __tcu_unmask_half_match_irq(n) ( REG_TCU_TMCR = (1 << ((n) + 16)) ) +#define __tcu_unmask_full_match_irq(n) ( REG_TCU_TMCR = (1 << (n)) ) + +#define __tcu_wdt_clock_stopped() ( REG_TCU_TSR & TCU_TSSR_WDTSC ) +#define __tcu_timer_clock_stopped(n) ( REG_TCU_TSR & (1 << (n)) ) + +#define __tcu_start_wdt_clock() ( REG_TCU_TSCR = TCU_TSSR_WDTSC ) +#define __tcu_start_timer_clock(n) ( REG_TCU_TSCR = (1 << (n)) ) + +#define __tcu_stop_wdt_clock() ( REG_TCU_TSSR = TCU_TSSR_WDTSC ) +#define __tcu_stop_timer_clock(n) ( REG_TCU_TSSR = (1 << (n)) ) + +#define __tcu_get_count(n) ( REG_TCU_TCNT((n)) ) +#define __tcu_set_count(n,v) ( REG_TCU_TCNT((n)) = (v) ) +#define __tcu_set_full_data(n,v) ( REG_TCU_TDFR((n)) = (v) ) +#define __tcu_set_half_data(n,v) ( REG_TCU_TDHR((n)) = (v) ) + + +/*************************************************************************** + * WDT + ***************************************************************************/ +#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) +#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) +#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) +#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) + +#define __wdt_select_extalclk() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) +#define __wdt_select_rtcclk() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) +#define __wdt_select_pclk() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) + +#define __wdt_select_clk_div1() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) +#define __wdt_select_clk_div4() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) +#define __wdt_select_clk_div16() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) +#define __wdt_select_clk_div64() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) +#define __wdt_select_clk_div256() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) +#define __wdt_select_clk_div1024() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) + + +/*************************************************************************** + * UART + ***************************************************************************/ + +#define __uart_enable(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) +#define __uart_disable(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) + +#define __uart_enable_transmit_irq(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) +#define __uart_disable_transmit_irq(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) + +#define __uart_enable_receive_irq(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) +#define __uart_disable_receive_irq(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) + +#define __uart_enable_loopback(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) +#define __uart_disable_loopback(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) + +#define __uart_set_8n1(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) + +#define __uart_set_baud(n, devclk, baud) \ + do { \ + REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ + REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ + REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ + REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ + } while (0) + +#define __uart_parity_error(n) \ + ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) + +#define __uart_clear_errors(n) \ + ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) + +#define __uart_transmit_fifo_empty(n) \ + ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) + +#define __uart_transmit_end(n) \ + ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) + +#define __uart_transmit_char(n, ch) \ + REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) + +#define __uart_receive_fifo_full(n) \ + ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) + +#define __uart_receive_ready(n) \ + ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) + +#define __uart_receive_char(n) \ + REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) + +#define __uart_disable_irda() \ + ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) +#define __uart_enable_irda() \ + /* Tx high pulse as 0, Rx low pulse as 0 */ \ + ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) + + +/*************************************************************************** + * DMAC + ***************************************************************************/ + +/* n is the DMA channel (0 - 5) */ + +#define __dmac_enable_module() \ + ( REG_DMAC_DMACR |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_RR ) +#define __dmac_disable_module() \ + ( REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE ) + +/* p=0,1,2,3 */ +#define __dmac_set_priority(p) \ +do { \ + REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \ + REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \ +} while (0) + +#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HLT ) +#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AR ) + +#define __dmac_enable_descriptor(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) +#define __dmac_disable_descriptor(n) \ + ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) + +#define __dmac_enable_channel(n) \ + ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN ) +#define __dmac_disable_channel(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN ) +#define __dmac_channel_enabled(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) + +#define __dmac_channel_enable_irq(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) +#define __dmac_channel_disable_irq(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) + +#define __dmac_channel_transmit_halt_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) +#define __dmac_channel_transmit_end_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) +#define __dmac_channel_address_error_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) +#define __dmac_channel_count_terminated_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) +#define __dmac_channel_descriptor_invalid_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) + +#define __dmac_channel_clear_transmit_halt(n) \ + ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT ) +#define __dmac_channel_clear_transmit_end(n) \ + ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) +#define __dmac_channel_clear_address_error(n) \ + ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR ) +#define __dmac_channel_clear_count_terminated(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) +#define __dmac_channel_clear_descriptor_invalid(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) + +#define __dmac_channel_set_single_mode(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TM ) +#define __dmac_channel_set_block_mode(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TM ) + +#define __dmac_channel_set_transfer_unit_32bit(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_16bit(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_8bit(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_16byte(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_32byte(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ +} while (0) + +/* w=8,16,32 */ +#define __dmac_channel_set_dest_port_width(n,w) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ +} while (0) + +/* w=8,16,32 */ +#define __dmac_channel_set_src_port_width(n,w) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ +} while (0) + +/* v=0-15 */ +#define __dmac_channel_set_rdil(n,v) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ + REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ +} while (0) + +#define __dmac_channel_dest_addr_fixed(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) +#define __dmac_channel_dest_addr_increment(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) + +#define __dmac_channel_src_addr_fixed(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) +#define __dmac_channel_src_addr_increment(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) + +#define __dmac_channel_set_doorbell(n) \ + ( REG_DMAC_DMADBSR = (1 << (n)) ) + +#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR & (1 << (n)) ) +#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR &= ~(1 << (n)) ) + +static __inline__ int __dmac_get_irq(void) +{ + int i; + for (i = 0; i < MAX_DMA_NUM; i++) + if (__dmac_channel_irq_detected(i)) + return i; + return -1; +} + + +/*************************************************************************** + * AIC (AC'97 & I2S Controller) + ***************************************************************************/ + +#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) +#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) + +#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) +#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) + +#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) +#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) + +#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) +#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) +#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) + +#define __aic_reset() \ +do { \ + REG_AIC_FR |= AIC_FR_RST; \ +} while(0) + + +#define __aic_set_transmit_trigger(n) \ +do { \ + REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ + REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ +} while(0) + +#define __aic_set_receive_trigger(n) \ +do { \ + REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ + REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ +} while(0) + +#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) +#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) +#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) +#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) +#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) +#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) + +#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) +#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) + +#define __aic_enable_transmit_intr() \ + ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) +#define __aic_disable_transmit_intr() \ + ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) +#define __aic_enable_receive_intr() \ + ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) +#define __aic_disable_receive_intr() \ + ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) + +#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) +#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) +#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) +#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) + +#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) +#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) +#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) +#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) +#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) +#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) + +#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 +#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 +#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 +#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 +#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 +#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 + +#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 +#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 +#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 +#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 +#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 +#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 + +#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) +#define __ac97_set_xs_mono() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ +} while(0) +#define __ac97_set_xs_stereo() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ +} while(0) + +/* In fact, only stereo is support now. */ +#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) +#define __ac97_set_rs_mono() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ +} while(0) +#define __ac97_set_rs_stereo() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ +} while(0) + +#define __ac97_warm_reset_codec() \ + do { \ + REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ + REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ + udelay(2); \ + REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ + REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ + } while (0) + +#define __ac97_cold_reset_codec() \ + do { \ + REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ + udelay(2); \ + REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ + } while (0) + +/* n=8,16,18,20 */ +#define __ac97_set_iass(n) \ + ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) +#define __ac97_set_oass(n) \ + ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) + +#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) +#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) + +/* n=8,16,18,20,24 */ +/*#define __i2s_set_sample_size(n) \ + ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ + +#define __i2s_set_oss_sample_size(n) \ + ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) +#define __i2s_set_iss_sample_size(n) \ + ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) + +#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) +#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) + +#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) +#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) +#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) +#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) + +#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) + +#define __aic_get_transmit_resident() \ + ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) +#define __aic_get_receive_count() \ + ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) + +#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) +#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) +#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) +#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) +#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) +#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) +#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) + +#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) + +#define CODEC_READ_CMD (1 << 19) +#define CODEC_WRITE_CMD (0 << 19) +#define CODEC_REG_INDEX_BIT 12 +#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ +#define CODEC_REG_DATA_BIT 4 +#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ + +#define __ac97_out_rcmd_addr(reg) \ +do { \ + REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ +} while (0) + +#define __ac97_out_wcmd_addr(reg) \ +do { \ + REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ +} while (0) + +#define __ac97_out_data(value) \ +do { \ + REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ +} while (0) + +#define __ac97_in_data() \ + ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) + +#define __ac97_in_status_addr() \ + ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) + +#define __i2s_set_sample_rate(i2sclk, sync) \ + ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) + +#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) +#define __aic_read_rfifo() ( REG_AIC_DR ) + +#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) +#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) + +// +// Define next ops for AC97 compatible +// + +#define AC97_ACSR AIC_ACSR + +#define __ac97_enable() __aic_enable(); __aic_select_ac97() +#define __ac97_disable() __aic_disable() +#define __ac97_reset() __aic_reset() + +#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) +#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) + +#define __ac97_enable_record() __aic_enable_record() +#define __ac97_disable_record() __aic_disable_record() +#define __ac97_enable_replay() __aic_enable_replay() +#define __ac97_disable_replay() __aic_disable_replay() +#define __ac97_enable_loopback() __aic_enable_loopback() +#define __ac97_disable_loopback() __aic_disable_loopback() + +#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() +#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() +#define __ac97_enable_receive_dma() __aic_enable_receive_dma() +#define __ac97_disable_receive_dma() __aic_disable_receive_dma() + +#define __ac97_transmit_request() __aic_transmit_request() +#define __ac97_receive_request() __aic_receive_request() +#define __ac97_transmit_underrun() __aic_transmit_underrun() +#define __ac97_receive_overrun() __aic_receive_overrun() + +#define __ac97_clear_errors() __aic_clear_errors() + +#define __ac97_get_transmit_resident() __aic_get_transmit_resident() +#define __ac97_get_receive_count() __aic_get_receive_count() + +#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() +#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() +#define __ac97_enable_receive_intr() __aic_enable_receive_intr() +#define __ac97_disable_receive_intr() __aic_disable_receive_intr() + +#define __ac97_write_tfifo(v) __aic_write_tfifo(v) +#define __ac97_read_rfifo() __aic_read_rfifo() + +// +// Define next ops for I2S compatible +// + +#define I2S_ACSR AIC_I2SSR + +#define __i2s_enable() __aic_enable(); __aic_select_i2s() +#define __i2s_disable() __aic_disable() +#define __i2s_reset() __aic_reset() + +#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) +#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) + +#define __i2s_enable_record() __aic_enable_record() +#define __i2s_disable_record() __aic_disable_record() +#define __i2s_enable_replay() __aic_enable_replay() +#define __i2s_disable_replay() __aic_disable_replay() +#define __i2s_enable_loopback() __aic_enable_loopback() +#define __i2s_disable_loopback() __aic_disable_loopback() + +#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() +#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() +#define __i2s_enable_receive_dma() __aic_enable_receive_dma() +#define __i2s_disable_receive_dma() __aic_disable_receive_dma() + +#define __i2s_transmit_request() __aic_transmit_request() +#define __i2s_receive_request() __aic_receive_request() +#define __i2s_transmit_underrun() __aic_transmit_underrun() +#define __i2s_receive_overrun() __aic_receive_overrun() + +#define __i2s_clear_errors() __aic_clear_errors() + +#define __i2s_get_transmit_resident() __aic_get_transmit_resident() +#define __i2s_get_receive_count() __aic_get_receive_count() + +#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() +#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() +#define __i2s_enable_receive_intr() __aic_enable_receive_intr() +#define __i2s_disable_receive_intr() __aic_disable_receive_intr() + +#define __i2s_write_tfifo(v) __aic_write_tfifo(v) +#define __i2s_read_rfifo() __aic_read_rfifo() + +#define __i2s_reset_codec() \ + do { \ + } while (0) + + +/*************************************************************************** + * ICDC + ***************************************************************************/ +#define __i2s_internal_codec() __aic_internal_codec() +#define __i2s_external_codec() __aic_external_codec() + +/*************************************************************************** + * INTC + ***************************************************************************/ +#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) +#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) +#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) + + +/*************************************************************************** + * I2C + ***************************************************************************/ + +#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) +#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) + +#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) +#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) +#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) +#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) + +#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) +#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) +#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) + +#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) +#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) +#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) + +#define __i2c_set_clk(dev_clk, i2c_clk) \ + ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) + +#define __i2c_read() ( REG_I2C_DR ) +#define __i2c_write(val) ( REG_I2C_DR = (val) ) + + +/*************************************************************************** + * MSC + ***************************************************************************/ + +#define __msc_start_op() \ + ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) + +#define __msc_set_resto(to) ( REG_MSC_RESTO = to ) +#define __msc_set_rdto(to) ( REG_MSC_RDTO = to ) +#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd ) +#define __msc_set_arg(arg) ( REG_MSC_ARG = arg ) +#define __msc_set_nob(nob) ( REG_MSC_NOB = nob ) +#define __msc_get_nob() ( REG_MSC_NOB ) +#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len ) +#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat ) +#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT ) +#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT ) + +#define __msc_set_cmdat_bus_width1() \ +do { \ + REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ + REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \ +} while(0) + +#define __msc_set_cmdat_bus_width4() \ +do { \ + REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ + REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \ +} while(0) + +#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN ) +#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT ) +#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY ) +#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK ) +#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK ) +#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ ) +#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ ) +#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN ) + +/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ +#define __msc_set_cmdat_res_format(r) \ +do { \ + REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ + REG_MSC_CMDAT |= (r); \ +} while(0) + +#define __msc_clear_cmdat() \ + REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ + MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ + MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) + +#define __msc_get_imask() ( REG_MSC_IMASK ) +#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff ) +#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 ) +#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ ) +#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ ) +#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ ) +#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ ) +#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES ) +#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES ) +#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE ) +#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE ) +#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE ) +#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE ) + +/* n=0,1,2,3,4,5,6,7 */ +#define __msc_set_clkrt(n) \ +do { \ + REG_MSC_CLKRT = n; \ +} while(0) + +#define __msc_get_ireg() ( REG_MSC_IREG ) +#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ ) +#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ ) +#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES ) +#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE ) +#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE ) +#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES ) +#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE ) +#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE ) + +#define __msc_get_stat() ( REG_MSC_STAT ) +#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0) +#define __msc_stat_crc_err() \ + ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) +#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR ) +#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR ) +#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES ) +#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES ) +#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ ) + +#define __msc_rd_resfifo() ( REG_MSC_RES ) +#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO ) +#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v ) + +#define __msc_reset() \ +do { \ + REG_MSC_STRPCL = MSC_STRPCL_RESET; \ + while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \ +} while (0) + +#define __msc_start_clk() \ +do { \ + REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \ +} while (0) + +#define __msc_stop_clk() \ +do { \ + REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \ +} while (0) + +#define MMC_CLK 19169200 +#define SD_CLK 24576000 + +/* msc_clk should little than pclk and little than clk retrieve from card */ +#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ +do { \ + unsigned int rate, pclk, i; \ + pclk = dev_clk; \ + rate = type?SD_CLK:MMC_CLK; \ + if (msc_clk && msc_clk < pclk) \ + pclk = msc_clk; \ + i = 0; \ + while (pclk < rate) \ + { \ + i ++; \ + rate >>= 1; \ + } \ + lv = i; \ +} while(0) + +/* divide rate to little than or equal to 400kHz */ +#define __msc_calc_slow_clk_divisor(type, lv) \ +do { \ + unsigned int rate, i; \ + rate = (type?SD_CLK:MMC_CLK)/1000/400; \ + i = 0; \ + while (rate > 0) \ + { \ + rate >>= 1; \ + i ++; \ + } \ + lv = i; \ +} while(0) + + +/*************************************************************************** + * SSI + ***************************************************************************/ + +#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE ) +#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE ) +#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL ) + +#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK ) + +#define __ssi_select_ce2() \ +do { \ + REG_SSI_CR0 |= SSI_CR0_FSEL; \ + REG_SSI_CR1 &= ~SSI_CR1_MULTS; \ +} while (0) + +#define __ssi_select_gpc() \ +do { \ + REG_SSI_CR0 &= ~SSI_CR0_FSEL; \ + REG_SSI_CR1 |= SSI_CR1_MULTS; \ +} while (0) + +#define __ssi_enable_tx_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE ) + +#define __ssi_disable_tx_intr() \ + ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) + +#define __ssi_enable_rx_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE ) + +#define __ssi_disable_rx_intr() \ + ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) + +#define __ssi_enable_txfifo_half_empty_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_TIE ) +#define __ssi_disable_txfifo_half_empty_intr() \ + ( REG_SSI_CR0 &= ~SSI_CR0_TIE ) +#define __ssi_enable_tx_error_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_TEIE ) +#define __ssi_disable_tx_error_intr() \ + ( REG_SSI_CR0 &= ~SSI_CR0_TEIE ) + +#define __ssi_enable_rxfifo_half_full_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_RIE ) +#define __ssi_disable_rxfifo_half_full_intr() \ + ( REG_SSI_CR0 &= ~SSI_CR0_RIE ) +#define __ssi_enable_rx_error_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_REIE ) +#define __ssi_disable_rx_error_intr() \ + ( REG_SSI_CR0 &= ~SSI_CR0_REIE ) + +#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP ) +#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP ) + +#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV ) +#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV ) + +#define __ssi_finish_receive() \ + ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) + +#define __ssi_disable_recvfinish() \ + ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) + +#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH ) +#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH ) + +#define __ssi_flush_fifo() \ + ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) + +#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN ) +#define __ssi_wait_transmit() ( REG_SSI_CR1 |= SSI_CR1_UNFIN ) + +#define __ssi_spi_format() \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ + REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \ + REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ + REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ +} while (0) + +/* TI's SSP format, must clear SSI_CR1.UNFIN */ +#define __ssi_ssp_format() \ +do { \ + REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ + REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \ +} while (0) + +/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ +#define __ssi_microwire_format() \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ + REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \ + REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ + REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ + REG_SSI_CR0 &= ~SSI_CR0_RFINE; \ +} while (0) + +/* CE# level (FRMHL), CE# in interval time (ITFRM), + clock phase and polarity (PHA POL), + interval time (SSIITR), interval characters/frame (SSIICR) */ + + /* frmhl,endian,mcom,flen,pha,pol MASK */ +#define SSICR1_MISC_MASK \ + ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ + | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \ + +#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \ +do { \ + REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \ + REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \ + (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ + ((pha) << 1) | (pol); \ +} while(0) + +/* Transfer with MSB or LSB first */ +#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST ) +#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST ) + +#define __ssi_set_frame_length(n) \ + REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4) + +/* n = 1 - 16 */ +#define __ssi_set_microwire_command_length(n) \ + ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) ) + +/* Set the clock phase for SPI */ +#define __ssi_set_spi_clock_phase(n) \ + ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | ((n&0x1)<< 1))) + +/* Set the clock polarity for SPI */ +#define __ssi_set_spi_clock_polarity(n) \ + ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | (n&0x1)) ) + +/* n = ix8 */ +#define __ssi_set_tx_trigger(n) \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \ + REG_SSI_CR1 |= (n/8)<> SSI_SR_TFIFONUM_BIT ) + +#define __ssi_get_rxfifo_count() \ + ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) + +#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END ) +#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY ) + +#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF ) +#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE ) +#define __ssi_rxfifo_half_full() ( REG_SSI_SR & SSI_SR_RFHF ) +#define __ssi_txfifo_half_empty() ( REG_SSI_SR & SSI_SR_TFHE ) +#define __ssi_underrun() ( REG_SSI_SR & SSI_SR_UNDR ) +#define __ssi_overrun() ( REG_SSI_SR & SSI_SR_OVER ) +#define __ssi_clear_underrun() ( REG_SSI_SR = ~SSI_SR_UNDR ) +#define __ssi_clear_overrun() ( REG_SSI_SR = ~SSI_SR_OVER ) +#define __ssi_clear_errors() \ + ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) + + +#define __ssi_set_clk(dev_clk, ssi_clk) \ + ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 ) + +#define __ssi_receive_data() REG_SSI_DR +#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) ) + + +/*************************************************************************** + * CIM + ***************************************************************************/ + +#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) +#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) + +#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT ) +#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT ) + +#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP ) +#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP ) + +#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP ) +#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP ) + +#define __cim_sample_data_at_pclk_falling_edge() \ + ( REG_CIM_CFG |= CIM_CFG_PCP ) +#define __cim_sample_data_at_pclk_rising_edge() \ + ( REG_CIM_CFG &= ~CIM_CFG_PCP ) + +#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO ) +#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO ) + +#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC ) +#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC ) + +/* n=0-7 */ +#define __cim_set_data_packing_mode(n) \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \ + REG_CIM_CFG |= (CIM_CFG_PACK_##n); \ +} while (0) + +#define __cim_enable_ccir656_progressive_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_CPM; \ +} while (0) + +#define __cim_enable_ccir656_interlace_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_CIM; \ +} while (0) + +#define __cim_enable_gated_clock_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_GCM; \ +} while (0) + +#define __cim_enable_nongated_clock_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \ +} while (0) + +/* sclk:system bus clock + * mclk: CIM master clock + */ +#define __cim_set_master_clk(sclk, mclk) \ +do { \ + REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \ + REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \ +} while (0) + +#define __cim_enable_sof_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM ) +#define __cim_disable_sof_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM ) + +#define __cim_enable_eof_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM ) +#define __cim_disable_eof_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM ) + +#define __cim_enable_stop_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM ) +#define __cim_disable_stop_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM ) + +#define __cim_enable_trig_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM ) +#define __cim_disable_trig_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM ) + +#define __cim_enable_rxfifo_overflow_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM ) +#define __cim_disable_rxfifo_overflow_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM ) + +/* n=1-16 */ +#define __cim_set_frame_rate(n) \ +do { \ + REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \ + REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \ +} while (0) + +#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN ) +#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN ) + +#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST ) +#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST ) + +/* n=4,8,12,16,20,24,28,32 */ +#define __cim_set_rxfifo_trigger(n) \ +do { \ + REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \ + REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \ +} while (0) + +#define __cim_clear_state() ( REG_CIM_STATE = 0 ) + +#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD ) +#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY ) +#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG ) +#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF ) +#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF ) +#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP ) +#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF ) +#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF ) + +#define __cim_get_iid() ( REG_CIM_IID ) +#define __cim_get_image_data() ( REG_CIM_RXFIFO ) +#define __cim_get_dam_cmd() ( REG_CIM_CMD ) + +#define __cim_set_da(a) ( REG_CIM_DA = (a) ) + +/*************************************************************************** + * LCD + ***************************************************************************/ +#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= (1<> LCD_VSYNC_VPS_BIT ) + +#define __lcd_vsync_get_vpe() \ + ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) +#define __lcd_vsync_set_vpe(n) \ +do { \ + REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ + REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ +} while (0) + +#define __lcd_hsync_get_hps() \ + ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) +#define __lcd_hsync_set_hps(n) \ +do { \ + REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ + REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ +} while (0) + +#define __lcd_hsync_get_hpe() \ + ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) +#define __lcd_hsync_set_hpe(n) \ +do { \ + REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ + REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ +} while (0) + +#define __lcd_vat_get_ht() \ + ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) +#define __lcd_vat_set_ht(n) \ +do { \ + REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ + REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ +} while (0) + +#define __lcd_vat_get_vt() \ + ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) +#define __lcd_vat_set_vt(n) \ +do { \ + REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ + REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ +} while (0) + +#define __lcd_dah_get_hds() \ + ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) +#define __lcd_dah_set_hds(n) \ +do { \ + REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ + REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ +} while (0) + +#define __lcd_dah_get_hde() \ + ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) +#define __lcd_dah_set_hde(n) \ +do { \ + REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ + REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ +} while (0) + +#define __lcd_dav_get_vds() \ + ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) +#define __lcd_dav_set_vds(n) \ +do { \ + REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ + REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ +} while (0) + +#define __lcd_dav_get_vde() \ + ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) +#define __lcd_dav_set_vde(n) \ +do { \ + REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ + REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ +} while (0) + +#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) +#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) +#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) +#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) + +#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) +#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) +#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) +#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) + +#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) +#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) + +#define __lcd_cmd0_get_len() \ + ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) +#define __lcd_cmd1_get_len() \ + ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) + +/******************************************************* + * SMART LCD + *******************************************************/ + +#define __slcd_dma_enable() (REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN) +#define __slcd_dma_disable() \ +do {\ + while (REG_SLCD_STATE & SLCD_STATE_BUSY); \ + REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; \ +} while(0) + +/******************************************************* + * SMART LCD + *******************************************************/ + +#define __slcd_dma_enable() (REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN) +#define __slcd_dma_disable() \ +do {\ + while (REG_SLCD_STATE & SLCD_STATE_BUSY); \ + REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; \ +} while(0) + +/*************************************************************************** + * RTC ops + ***************************************************************************/ + +#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) +#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) +#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) +#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) +#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) +#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) +#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) +#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) +#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) + +#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) +#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) +#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) +#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) + +#define __rtc_get_second() ( REG_RTC_RSR ) +#define __rtc_set_second(v) ( REG_RTC_RSR = v ) + +#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) +#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) + +#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) +#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) +#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) +#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) +#define __rtc_set_adjc_val(v) \ + ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) +#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) +#define __rtc_set_nc1Hz_val(v) \ + ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) + +#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) + +#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) +#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) +#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) +#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) + +#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) +#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) + +#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) +#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) +#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) +#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) +#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) + +#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) +#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) + + + +#endif /* __JZ4740_OPS_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/regs.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/regs.h new file mode 100644 index 000000000..07528bc41 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/regs.h @@ -0,0 +1,2392 @@ +/* + * linux/include/asm-mips/mach-jz4740/regs.h + * + * Ingenic's JZ4740 common include. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __JZ4740_REGS_H__ +#define __JZ4740_REGS_H__ + +#if defined(__ASSEMBLY__) || defined(__LANGUAGE_ASSEMBLY) +#define REG8(addr) (addr) +#define REG16(addr) (addr) +#define REG32(addr) (addr) +#else +#define REG8(addr) *((volatile unsigned char *)(addr)) +#define REG16(addr) *((volatile unsigned short *)(addr)) +#define REG32(addr) *((volatile unsigned int *)(addr)) +#endif + +/* + * Define the module base addresses + */ +#define CPM_BASE 0xB0000000 +#define INTC_BASE 0xB0001000 +#define TCU_BASE 0xB0002000 +#define WDT_BASE 0xB0002000 +#define RTC_BASE 0xB0003000 +#define GPIO_BASE 0xB0010000 +#define AIC_BASE 0xB0020000 +#define ICDC_BASE 0xB0020000 +#define MSC_BASE 0xB0021000 +#define UART0_BASE 0xB0030000 +#define UART1_BASE 0xB0031000 +#define I2C_BASE 0xB0042000 +#define SSI_BASE 0xB0043000 +#define SADC_BASE 0xB0070000 +#define EMC_BASE 0xB3010000 +#define DMAC_BASE 0xB3020000 +#define UHC_BASE 0xB3030000 +#define UDC_BASE 0xB3040000 +#define LCD_BASE 0xB3050000 +#define SLCD_BASE 0xB3050000 +#define CIM_BASE 0xB3060000 +#define IPU_BASE 0xB3080000 +#define ETH_BASE 0xB3100000 + + +/************************************************************************* + * INTC (Interrupt Controller) + *************************************************************************/ +#define INTC_ISR (INTC_BASE + 0x00) +#define INTC_IMR (INTC_BASE + 0x04) +#define INTC_IMSR (INTC_BASE + 0x08) +#define INTC_IMCR (INTC_BASE + 0x0c) +#define INTC_IPR (INTC_BASE + 0x10) + +#define REG_INTC_ISR REG32(INTC_ISR) +#define REG_INTC_IMR REG32(INTC_IMR) +#define REG_INTC_IMSR REG32(INTC_IMSR) +#define REG_INTC_IMCR REG32(INTC_IMCR) +#define REG_INTC_IPR REG32(INTC_IPR) + +// 1st-level interrupts +#define IRQ_I2C 1 +#define IRQ_UHC 3 +#define IRQ_UART1 8 +#define IRQ_UART0 9 +#define IRQ_SADC 12 +#define IRQ_MSC 14 +#define IRQ_RTC 15 +#define IRQ_SSI 16 +#define IRQ_CIM 17 +#define IRQ_AIC 18 +#define IRQ_ETH 19 +#define IRQ_DMAC 20 +#define IRQ_TCU2 21 +#define IRQ_TCU1 22 +#define IRQ_TCU0 23 +#define IRQ_UDC 24 +#define IRQ_GPIO3 25 +#define IRQ_GPIO2 26 +#define IRQ_GPIO1 27 +#define IRQ_GPIO0 28 +#define IRQ_IPU 29 +#define IRQ_LCD 30 + +// 2nd-level interrupts +#define IRQ_DMA_0 32 /* 32 to 37 for DMAC channel 0 to 5 */ +#define IRQ_GPIO_0 48 /* 48 to 175 for GPIO pin 0 to 127 */ + +#define NUM_DMA 6 +#define NUM_GPIO 128 +/************************************************************************* + * RTC + *************************************************************************/ +#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */ +#define RTC_RSR (RTC_BASE + 0x04) /* RTC Second Register */ +#define RTC_RSAR (RTC_BASE + 0x08) /* RTC Second Alarm Register */ +#define RTC_RGR (RTC_BASE + 0x0c) /* RTC Regulator Register */ + +#define RTC_HCR (RTC_BASE + 0x20) /* Hibernate Control Register */ +#define RTC_HWFCR (RTC_BASE + 0x24) /* Hibernate Wakeup Filter Counter Reg */ +#define RTC_HRCR (RTC_BASE + 0x28) /* Hibernate Reset Counter Register */ +#define RTC_HWCR (RTC_BASE + 0x2c) /* Hibernate Wakeup Control Register */ +#define RTC_HWRSR (RTC_BASE + 0x30) /* Hibernate Wakeup Status Register */ +#define RTC_HSPR (RTC_BASE + 0x34) /* Hibernate Scratch Pattern Register */ + +#define REG_RTC_RCR REG32(RTC_RCR) +#define REG_RTC_RSR REG32(RTC_RSR) +#define REG_RTC_RSAR REG32(RTC_RSAR) +#define REG_RTC_RGR REG32(RTC_RGR) +#define REG_RTC_HCR REG32(RTC_HCR) +#define REG_RTC_HWFCR REG32(RTC_HWFCR) +#define REG_RTC_HRCR REG32(RTC_HRCR) +#define REG_RTC_HWCR REG32(RTC_HWCR) +#define REG_RTC_HWRSR REG32(RTC_HWRSR) +#define REG_RTC_HSPR REG32(RTC_HSPR) + +/* RTC Control Register */ +#define RTC_RCR_WRDY_BIT 7 +#define RTC_RCR_WRDY (1 << 7) /* Write Ready Flag */ +#define RTC_RCR_1HZ_BIT 6 +#define RTC_RCR_1HZ (1 << RTC_RCR_1HZ_BIT) /* 1Hz Flag */ +#define RTC_RCR_1HZIE (1 << 5) /* 1Hz Interrupt Enable */ +#define RTC_RCR_AF_BIT 4 +#define RTC_RCR_AF (1 << RTC_RCR_AF_BIT) /* Alarm Flag */ +#define RTC_RCR_AIE (1 << 3) /* Alarm Interrupt Enable */ +#define RTC_RCR_AE (1 << 2) /* Alarm Enable */ +#define RTC_RCR_RTCE (1 << 0) /* RTC Enable */ + +/* RTC Regulator Register */ +#define RTC_RGR_LOCK (1 << 31) /* Lock Bit */ +#define RTC_RGR_ADJC_BIT 16 +#define RTC_RGR_ADJC_MASK (0x3ff << RTC_RGR_ADJC_BIT) +#define RTC_RGR_NC1HZ_BIT 0 +#define RTC_RGR_NC1HZ_MASK (0xffff << RTC_RGR_NC1HZ_BIT) + +/* Hibernate Control Register */ +#define RTC_HCR_PD (1 << 0) /* Power Down */ + +/* Hibernate Wakeup Filter Counter Register */ +#define RTC_HWFCR_BIT 5 +#define RTC_HWFCR_MASK (0x7ff << RTC_HWFCR_BIT) + +/* Hibernate Reset Counter Register */ +#define RTC_HRCR_BIT 5 +#define RTC_HRCR_MASK (0x7f << RTC_HRCR_BIT) + +/* Hibernate Wakeup Control Register */ +#define RTC_HWCR_EALM (1 << 0) /* RTC alarm wakeup enable */ + +/* Hibernate Wakeup Status Register */ +#define RTC_HWRSR_HR (1 << 5) /* Hibernate reset */ +#define RTC_HWRSR_PPR (1 << 4) /* PPR reset */ +#define RTC_HWRSR_PIN (1 << 1) /* Wakeup pin status bit */ +#define RTC_HWRSR_ALM (1 << 0) /* RTC alarm status bit */ + + +/************************************************************************* + * CPM (Clock reset and Power control Management) + *************************************************************************/ +#define CPM_CPCCR (CPM_BASE+0x00) +#define CPM_CPPCR (CPM_BASE+0x10) +#define CPM_I2SCDR (CPM_BASE+0x60) +#define CPM_LPCDR (CPM_BASE+0x64) +#define CPM_MSCCDR (CPM_BASE+0x68) +#define CPM_UHCCDR (CPM_BASE+0x6C) +#define CPM_SSICDR (CPM_BASE+0x74) + +#define CPM_LCR (CPM_BASE+0x04) +#define CPM_CLKGR (CPM_BASE+0x20) +#define CPM_SCR (CPM_BASE+0x24) + +#define CPM_HCR (CPM_BASE+0x30) +#define CPM_HWFCR (CPM_BASE+0x34) +#define CPM_HRCR (CPM_BASE+0x38) +#define CPM_HWCR (CPM_BASE+0x3c) +#define CPM_HWSR (CPM_BASE+0x40) +#define CPM_HSPR (CPM_BASE+0x44) + +#define CPM_RSR (CPM_BASE+0x08) + + +#define REG_CPM_CPCCR REG32(CPM_CPCCR) +#define REG_CPM_CPPCR REG32(CPM_CPPCR) +#define REG_CPM_I2SCDR REG32(CPM_I2SCDR) +#define REG_CPM_LPCDR REG32(CPM_LPCDR) +#define REG_CPM_MSCCDR REG32(CPM_MSCCDR) +#define REG_CPM_UHCCDR REG32(CPM_UHCCDR) +#define REG_CPM_SSICDR REG32(CPM_SSICDR) + +#define REG_CPM_LCR REG32(CPM_LCR) +#define REG_CPM_CLKGR REG32(CPM_CLKGR) +#define REG_CPM_SCR REG32(CPM_SCR) +#define REG_CPM_HCR REG32(CPM_HCR) +#define REG_CPM_HWFCR REG32(CPM_HWFCR) +#define REG_CPM_HRCR REG32(CPM_HRCR) +#define REG_CPM_HWCR REG32(CPM_HWCR) +#define REG_CPM_HWSR REG32(CPM_HWSR) +#define REG_CPM_HSPR REG32(CPM_HSPR) + +#define REG_CPM_RSR REG32(CPM_RSR) + + +/* Clock Control Register */ +#define CPM_CPCCR_I2CS (1 << 31) +#define CPM_CPCCR_CLKOEN (1 << 30) +#define CPM_CPCCR_UCS (1 << 29) +#define CPM_CPCCR_UDIV_BIT 23 +#define CPM_CPCCR_UDIV_MASK (0x3f << CPM_CPCCR_UDIV_BIT) +#define CPM_CPCCR_CE (1 << 22) +#define CPM_CPCCR_PCS (1 << 21) +#define CPM_CPCCR_LDIV_BIT 16 +#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT) +#define CPM_CPCCR_MDIV_BIT 12 +#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT) +#define CPM_CPCCR_PDIV_BIT 8 +#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT) +#define CPM_CPCCR_HDIV_BIT 4 +#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT) +#define CPM_CPCCR_CDIV_BIT 0 +#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT) + +/* I2S Clock Divider Register */ +#define CPM_I2SCDR_I2SDIV_BIT 0 +#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT) + +/* LCD Pixel Clock Divider Register */ +#define CPM_LPCDR_PIXDIV_BIT 0 +#define CPM_LPCDR_PIXDIV_MASK (0x7ff << CPM_LPCDR_PIXDIV_BIT) + +/* MSC Clock Divider Register */ +#define CPM_MSCCDR_MSCDIV_BIT 0 +#define CPM_MSCCDR_MSCDIV_MASK (0x1f << CPM_MSCCDR_MSCDIV_BIT) + +/* UHC Clock Divider Register */ +#define CPM_UHCCDR_UHCDIV_BIT 0 +#define CPM_UHCCDR_UHCDIV_MASK (0xf << CPM_UHCCDR_UHCDIV_BIT) + +/* SSI Clock Divider Register */ +#define CPM_SSICDR_SCS (1<<31) /* SSI clock source selection, 0:EXCLK, 1: PLL */ +#define CPM_SSICDR_SSIDIV_BIT 0 +#define CPM_SSICDR_SSIDIV_MASK (0xf << CPM_SSICDR_SSIDIV_BIT) + +/* PLL Control Register */ +#define CPM_CPPCR_PLLM_BIT 23 +#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT) +#define CPM_CPPCR_PLLN_BIT 18 +#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT) +#define CPM_CPPCR_PLLOD_BIT 16 +#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT) +#define CPM_CPPCR_PLLS (1 << 10) +#define CPM_CPPCR_PLLBP (1 << 9) +#define CPM_CPPCR_PLLEN (1 << 8) +#define CPM_CPPCR_PLLST_BIT 0 +#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT) + +/* Low Power Control Register */ +#define CPM_LCR_DOZE_DUTY_BIT 3 +#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT) +#define CPM_LCR_DOZE_ON (1 << 2) +#define CPM_LCR_LPM_BIT 0 +#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT) + #define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT) + #define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT) + +/* Clock Gate Register */ +#define CPM_CLKGR_UART1 (1 << 15) +#define CPM_CLKGR_UHC (1 << 14) +#define CPM_CLKGR_IPU (1 << 13) +#define CPM_CLKGR_DMAC (1 << 12) +#define CPM_CLKGR_UDC (1 << 11) +#define CPM_CLKGR_LCD (1 << 10) +#define CPM_CLKGR_CIM (1 << 9) +#define CPM_CLKGR_SADC (1 << 8) +#define CPM_CLKGR_MSC (1 << 7) +#define CPM_CLKGR_AIC1 (1 << 6) +#define CPM_CLKGR_AIC2 (1 << 5) +#define CPM_CLKGR_SSI (1 << 4) +#define CPM_CLKGR_I2C (1 << 3) +#define CPM_CLKGR_RTC (1 << 2) +#define CPM_CLKGR_TCU (1 << 1) +#define CPM_CLKGR_UART0 (1 << 0) + +/* Sleep Control Register */ +#define CPM_SCR_O1ST_BIT 8 +#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT) +#define CPM_SCR_USBPHY_ENABLE (1 << 6) +#define CPM_SCR_OSC_ENABLE (1 << 4) + +/* Hibernate Control Register */ +#define CPM_HCR_PD (1 << 0) + +/* Wakeup Filter Counter Register in Hibernate Mode */ +#define CPM_HWFCR_TIME_BIT 0 +#define CPM_HWFCR_TIME_MASK (0x3ff << CPM_HWFCR_TIME_BIT) + +/* Reset Counter Register in Hibernate Mode */ +#define CPM_HRCR_TIME_BIT 0 +#define CPM_HRCR_TIME_MASK (0x7f << CPM_HRCR_TIME_BIT) + +/* Wakeup Control Register in Hibernate Mode */ +#define CPM_HWCR_WLE_LOW (0 << 2) +#define CPM_HWCR_WLE_HIGH (1 << 2) +#define CPM_HWCR_PIN_WAKEUP (1 << 1) +#define CPM_HWCR_RTC_WAKEUP (1 << 0) + +/* Wakeup Status Register in Hibernate Mode */ +#define CPM_HWSR_WSR_PIN (1 << 1) +#define CPM_HWSR_WSR_RTC (1 << 0) + +/* Reset Status Register */ +#define CPM_RSR_HR (1 << 2) +#define CPM_RSR_WR (1 << 1) +#define CPM_RSR_PR (1 << 0) + + +/************************************************************************* + * TCU (Timer Counter Unit) + *************************************************************************/ +#define TCU_TSR (TCU_BASE + 0x1C) /* Timer Stop Register */ +#define TCU_TSSR (TCU_BASE + 0x2C) /* Timer Stop Set Register */ +#define TCU_TSCR (TCU_BASE + 0x3C) /* Timer Stop Clear Register */ +#define TCU_TER (TCU_BASE + 0x10) /* Timer Counter Enable Register */ +#define TCU_TESR (TCU_BASE + 0x14) /* Timer Counter Enable Set Register */ +#define TCU_TECR (TCU_BASE + 0x18) /* Timer Counter Enable Clear Register */ +#define TCU_TFR (TCU_BASE + 0x20) /* Timer Flag Register */ +#define TCU_TFSR (TCU_BASE + 0x24) /* Timer Flag Set Register */ +#define TCU_TFCR (TCU_BASE + 0x28) /* Timer Flag Clear Register */ +#define TCU_TMR (TCU_BASE + 0x30) /* Timer Mask Register */ +#define TCU_TMSR (TCU_BASE + 0x34) /* Timer Mask Set Register */ +#define TCU_TMCR (TCU_BASE + 0x38) /* Timer Mask Clear Register */ +#define TCU_TDFR0 (TCU_BASE + 0x40) /* Timer Data Full Register */ +#define TCU_TDHR0 (TCU_BASE + 0x44) /* Timer Data Half Register */ +#define TCU_TCNT0 (TCU_BASE + 0x48) /* Timer Counter Register */ +#define TCU_TCSR0 (TCU_BASE + 0x4C) /* Timer Control Register */ +#define TCU_TDFR1 (TCU_BASE + 0x50) +#define TCU_TDHR1 (TCU_BASE + 0x54) +#define TCU_TCNT1 (TCU_BASE + 0x58) +#define TCU_TCSR1 (TCU_BASE + 0x5C) +#define TCU_TDFR2 (TCU_BASE + 0x60) +#define TCU_TDHR2 (TCU_BASE + 0x64) +#define TCU_TCNT2 (TCU_BASE + 0x68) +#define TCU_TCSR2 (TCU_BASE + 0x6C) +#define TCU_TDFR3 (TCU_BASE + 0x70) +#define TCU_TDHR3 (TCU_BASE + 0x74) +#define TCU_TCNT3 (TCU_BASE + 0x78) +#define TCU_TCSR3 (TCU_BASE + 0x7C) +#define TCU_TDFR4 (TCU_BASE + 0x80) +#define TCU_TDHR4 (TCU_BASE + 0x84) +#define TCU_TCNT4 (TCU_BASE + 0x88) +#define TCU_TCSR4 (TCU_BASE + 0x8C) +#define TCU_TDFR5 (TCU_BASE + 0x90) +#define TCU_TDHR5 (TCU_BASE + 0x94) +#define TCU_TCNT5 (TCU_BASE + 0x98) +#define TCU_TCSR5 (TCU_BASE + 0x9C) + +#define REG_TCU_TSR REG32(TCU_TSR) +#define REG_TCU_TSSR REG32(TCU_TSSR) +#define REG_TCU_TSCR REG32(TCU_TSCR) +#define REG_TCU_TER REG8(TCU_TER) +#define REG_TCU_TESR REG8(TCU_TESR) +#define REG_TCU_TECR REG8(TCU_TECR) +#define REG_TCU_TFR REG32(TCU_TFR) +#define REG_TCU_TFSR REG32(TCU_TFSR) +#define REG_TCU_TFCR REG32(TCU_TFCR) +#define REG_TCU_TMR REG32(TCU_TMR) +#define REG_TCU_TMSR REG32(TCU_TMSR) +#define REG_TCU_TMCR REG32(TCU_TMCR) +#define REG_TCU_TDFR0 REG16(TCU_TDFR0) +#define REG_TCU_TDHR0 REG16(TCU_TDHR0) +#define REG_TCU_TCNT0 REG16(TCU_TCNT0) +#define REG_TCU_TCSR0 REG16(TCU_TCSR0) +#define REG_TCU_TDFR1 REG16(TCU_TDFR1) +#define REG_TCU_TDHR1 REG16(TCU_TDHR1) +#define REG_TCU_TCNT1 REG16(TCU_TCNT1) +#define REG_TCU_TCSR1 REG16(TCU_TCSR1) +#define REG_TCU_TDFR2 REG16(TCU_TDFR2) +#define REG_TCU_TDHR2 REG16(TCU_TDHR2) +#define REG_TCU_TCNT2 REG16(TCU_TCNT2) +#define REG_TCU_TCSR2 REG16(TCU_TCSR2) +#define REG_TCU_TDFR3 REG16(TCU_TDFR3) +#define REG_TCU_TDHR3 REG16(TCU_TDHR3) +#define REG_TCU_TCNT3 REG16(TCU_TCNT3) +#define REG_TCU_TCSR3 REG16(TCU_TCSR3) +#define REG_TCU_TDFR4 REG16(TCU_TDFR4) +#define REG_TCU_TDHR4 REG16(TCU_TDHR4) +#define REG_TCU_TCNT4 REG16(TCU_TCNT4) +#define REG_TCU_TCSR4 REG16(TCU_TCSR4) + +// n = 0,1,2,3,4,5 +#define TCU_TDFR(n) (TCU_BASE + (0x40 + (n)*0x10)) /* Timer Data Full Reg */ +#define TCU_TDHR(n) (TCU_BASE + (0x44 + (n)*0x10)) /* Timer Data Half Reg */ +#define TCU_TCNT(n) (TCU_BASE + (0x48 + (n)*0x10)) /* Timer Counter Reg */ +#define TCU_TCSR(n) (TCU_BASE + (0x4C + (n)*0x10)) /* Timer Control Reg */ + +#define REG_TCU_TDFR(n) REG16(TCU_TDFR((n))) +#define REG_TCU_TDHR(n) REG16(TCU_TDHR((n))) +#define REG_TCU_TCNT(n) REG16(TCU_TCNT((n))) +#define REG_TCU_TCSR(n) REG16(TCU_TCSR((n))) + +// Register definitions +#define TCU_TCSR_PWM_SD (1 << 9) +#define TCU_TCSR_PWM_INITL_HIGH (1 << 8) +#define TCU_TCSR_PWM_EN (1 << 7) +#define TCU_TCSR_PRESCALE_BIT 3 +#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_EXT_EN (1 << 2) +#define TCU_TCSR_RTC_EN (1 << 1) +#define TCU_TCSR_PCK_EN (1 << 0) + +#define TCU_TER_TCEN5 (1 << 5) +#define TCU_TER_TCEN4 (1 << 4) +#define TCU_TER_TCEN3 (1 << 3) +#define TCU_TER_TCEN2 (1 << 2) +#define TCU_TER_TCEN1 (1 << 1) +#define TCU_TER_TCEN0 (1 << 0) + +#define TCU_TESR_TCST5 (1 << 5) +#define TCU_TESR_TCST4 (1 << 4) +#define TCU_TESR_TCST3 (1 << 3) +#define TCU_TESR_TCST2 (1 << 2) +#define TCU_TESR_TCST1 (1 << 1) +#define TCU_TESR_TCST0 (1 << 0) + +#define TCU_TECR_TCCL5 (1 << 5) +#define TCU_TECR_TCCL4 (1 << 4) +#define TCU_TECR_TCCL3 (1 << 3) +#define TCU_TECR_TCCL2 (1 << 2) +#define TCU_TECR_TCCL1 (1 << 1) +#define TCU_TECR_TCCL0 (1 << 0) + +#define TCU_TFR_HFLAG5 (1 << 21) +#define TCU_TFR_HFLAG4 (1 << 20) +#define TCU_TFR_HFLAG3 (1 << 19) +#define TCU_TFR_HFLAG2 (1 << 18) +#define TCU_TFR_HFLAG1 (1 << 17) +#define TCU_TFR_HFLAG0 (1 << 16) +#define TCU_TFR_FFLAG5 (1 << 5) +#define TCU_TFR_FFLAG4 (1 << 4) +#define TCU_TFR_FFLAG3 (1 << 3) +#define TCU_TFR_FFLAG2 (1 << 2) +#define TCU_TFR_FFLAG1 (1 << 1) +#define TCU_TFR_FFLAG0 (1 << 0) + +#define TCU_TFSR_HFLAG5 (1 << 21) +#define TCU_TFSR_HFLAG4 (1 << 20) +#define TCU_TFSR_HFLAG3 (1 << 19) +#define TCU_TFSR_HFLAG2 (1 << 18) +#define TCU_TFSR_HFLAG1 (1 << 17) +#define TCU_TFSR_HFLAG0 (1 << 16) +#define TCU_TFSR_FFLAG5 (1 << 5) +#define TCU_TFSR_FFLAG4 (1 << 4) +#define TCU_TFSR_FFLAG3 (1 << 3) +#define TCU_TFSR_FFLAG2 (1 << 2) +#define TCU_TFSR_FFLAG1 (1 << 1) +#define TCU_TFSR_FFLAG0 (1 << 0) + +#define TCU_TFCR_HFLAG5 (1 << 21) +#define TCU_TFCR_HFLAG4 (1 << 20) +#define TCU_TFCR_HFLAG3 (1 << 19) +#define TCU_TFCR_HFLAG2 (1 << 18) +#define TCU_TFCR_HFLAG1 (1 << 17) +#define TCU_TFCR_HFLAG0 (1 << 16) +#define TCU_TFCR_FFLAG5 (1 << 5) +#define TCU_TFCR_FFLAG4 (1 << 4) +#define TCU_TFCR_FFLAG3 (1 << 3) +#define TCU_TFCR_FFLAG2 (1 << 2) +#define TCU_TFCR_FFLAG1 (1 << 1) +#define TCU_TFCR_FFLAG0 (1 << 0) + +#define TCU_TMR_HMASK5 (1 << 21) +#define TCU_TMR_HMASK4 (1 << 20) +#define TCU_TMR_HMASK3 (1 << 19) +#define TCU_TMR_HMASK2 (1 << 18) +#define TCU_TMR_HMASK1 (1 << 17) +#define TCU_TMR_HMASK0 (1 << 16) +#define TCU_TMR_FMASK5 (1 << 5) +#define TCU_TMR_FMASK4 (1 << 4) +#define TCU_TMR_FMASK3 (1 << 3) +#define TCU_TMR_FMASK2 (1 << 2) +#define TCU_TMR_FMASK1 (1 << 1) +#define TCU_TMR_FMASK0 (1 << 0) + +#define TCU_TMSR_HMST5 (1 << 21) +#define TCU_TMSR_HMST4 (1 << 20) +#define TCU_TMSR_HMST3 (1 << 19) +#define TCU_TMSR_HMST2 (1 << 18) +#define TCU_TMSR_HMST1 (1 << 17) +#define TCU_TMSR_HMST0 (1 << 16) +#define TCU_TMSR_FMST5 (1 << 5) +#define TCU_TMSR_FMST4 (1 << 4) +#define TCU_TMSR_FMST3 (1 << 3) +#define TCU_TMSR_FMST2 (1 << 2) +#define TCU_TMSR_FMST1 (1 << 1) +#define TCU_TMSR_FMST0 (1 << 0) + +#define TCU_TMCR_HMCL5 (1 << 21) +#define TCU_TMCR_HMCL4 (1 << 20) +#define TCU_TMCR_HMCL3 (1 << 19) +#define TCU_TMCR_HMCL2 (1 << 18) +#define TCU_TMCR_HMCL1 (1 << 17) +#define TCU_TMCR_HMCL0 (1 << 16) +#define TCU_TMCR_FMCL5 (1 << 5) +#define TCU_TMCR_FMCL4 (1 << 4) +#define TCU_TMCR_FMCL3 (1 << 3) +#define TCU_TMCR_FMCL2 (1 << 2) +#define TCU_TMCR_FMCL1 (1 << 1) +#define TCU_TMCR_FMCL0 (1 << 0) + +#define TCU_TSR_WDTS (1 << 16) +#define TCU_TSR_STOP5 (1 << 5) +#define TCU_TSR_STOP4 (1 << 4) +#define TCU_TSR_STOP3 (1 << 3) +#define TCU_TSR_STOP2 (1 << 2) +#define TCU_TSR_STOP1 (1 << 1) +#define TCU_TSR_STOP0 (1 << 0) + +#define TCU_TSSR_WDTSS (1 << 16) +#define TCU_TSSR_STPS5 (1 << 5) +#define TCU_TSSR_STPS4 (1 << 4) +#define TCU_TSSR_STPS3 (1 << 3) +#define TCU_TSSR_STPS2 (1 << 2) +#define TCU_TSSR_STPS1 (1 << 1) +#define TCU_TSSR_STPS0 (1 << 0) + +#define TCU_TSSR_WDTSC (1 << 16) +#define TCU_TSSR_STPC5 (1 << 5) +#define TCU_TSSR_STPC4 (1 << 4) +#define TCU_TSSR_STPC3 (1 << 3) +#define TCU_TSSR_STPC2 (1 << 2) +#define TCU_TSSR_STPC1 (1 << 1) +#define TCU_TSSR_STPC0 (1 << 0) + + +/************************************************************************* + * WDT (WatchDog Timer) + *************************************************************************/ +#define WDT_TDR (WDT_BASE + 0x00) +#define WDT_TCER (WDT_BASE + 0x04) +#define WDT_TCNT (WDT_BASE + 0x08) +#define WDT_TCSR (WDT_BASE + 0x0C) + +#define REG_WDT_TDR REG16(WDT_TDR) +#define REG_WDT_TCER REG8(WDT_TCER) +#define REG_WDT_TCNT REG16(WDT_TCNT) +#define REG_WDT_TCSR REG16(WDT_TCSR) + +// Register definition +#define WDT_TCSR_PRESCALE_BIT 3 +#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT) +#define WDT_TCSR_EXT_EN (1 << 2) +#define WDT_TCSR_RTC_EN (1 << 1) +#define WDT_TCSR_PCK_EN (1 << 0) + +#define WDT_TCER_TCEN (1 << 0) + + +/************************************************************************* + * DMAC (DMA Controller) + *************************************************************************/ + +#define MAX_DMA_NUM 6 /* max 6 channels */ + +#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) /* DMA source address */ +#define DMAC_DTAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) /* DMA target address */ +#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) /* DMA transfer count */ +#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) /* DMA request source */ +#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ +#define DMAC_DCMD(n) (DMAC_BASE + (0x14 + (n) * 0x20)) /* DMA command */ +#define DMAC_DDA(n) (DMAC_BASE + (0x18 + (n) * 0x20)) /* DMA descriptor address */ +#define DMAC_DMACR (DMAC_BASE + 0x0300) /* DMA control register */ +#define DMAC_DMAIPR (DMAC_BASE + 0x0304) /* DMA interrupt pending */ +#define DMAC_DMADBR (DMAC_BASE + 0x0308) /* DMA doorbell */ +#define DMAC_DMADBSR (DMAC_BASE + 0x030C) /* DMA doorbell set */ + +// channel 0 +#define DMAC_DSAR0 DMAC_DSAR(0) +#define DMAC_DTAR0 DMAC_DTAR(0) +#define DMAC_DTCR0 DMAC_DTCR(0) +#define DMAC_DRSR0 DMAC_DRSR(0) +#define DMAC_DCCSR0 DMAC_DCCSR(0) +#define DMAC_DCMD0 DMAC_DCMD(0) +#define DMAC_DDA0 DMAC_DDA(0) + +// channel 1 +#define DMAC_DSAR1 DMAC_DSAR(1) +#define DMAC_DTAR1 DMAC_DTAR(1) +#define DMAC_DTCR1 DMAC_DTCR(1) +#define DMAC_DRSR1 DMAC_DRSR(1) +#define DMAC_DCCSR1 DMAC_DCCSR(1) +#define DMAC_DCMD1 DMAC_DCMD(1) +#define DMAC_DDA1 DMAC_DDA(1) + +// channel 2 +#define DMAC_DSAR2 DMAC_DSAR(2) +#define DMAC_DTAR2 DMAC_DTAR(2) +#define DMAC_DTCR2 DMAC_DTCR(2) +#define DMAC_DRSR2 DMAC_DRSR(2) +#define DMAC_DCCSR2 DMAC_DCCSR(2) +#define DMAC_DCMD2 DMAC_DCMD(2) +#define DMAC_DDA2 DMAC_DDA(2) + +// channel 3 +#define DMAC_DSAR3 DMAC_DSAR(3) +#define DMAC_DTAR3 DMAC_DTAR(3) +#define DMAC_DTCR3 DMAC_DTCR(3) +#define DMAC_DRSR3 DMAC_DRSR(3) +#define DMAC_DCCSR3 DMAC_DCCSR(3) +#define DMAC_DCMD3 DMAC_DCMD(3) +#define DMAC_DDA3 DMAC_DDA(3) + +// channel 4 +#define DMAC_DSAR4 DMAC_DSAR(4) +#define DMAC_DTAR4 DMAC_DTAR(4) +#define DMAC_DTCR4 DMAC_DTCR(4) +#define DMAC_DRSR4 DMAC_DRSR(4) +#define DMAC_DCCSR4 DMAC_DCCSR(4) +#define DMAC_DCMD4 DMAC_DCMD(4) +#define DMAC_DDA4 DMAC_DDA(4) + +// channel 5 +#define DMAC_DSAR5 DMAC_DSAR(5) +#define DMAC_DTAR5 DMAC_DTAR(5) +#define DMAC_DTCR5 DMAC_DTCR(5) +#define DMAC_DRSR5 DMAC_DRSR(5) +#define DMAC_DCCSR5 DMAC_DCCSR(5) +#define DMAC_DCMD5 DMAC_DCMD(5) +#define DMAC_DDA5 DMAC_DDA(5) + +#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n))) +#define REG_DMAC_DTAR(n) REG32(DMAC_DTAR((n))) +#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n))) +#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n))) +#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) +#define REG_DMAC_DCMD(n) REG32(DMAC_DCMD((n))) +#define REG_DMAC_DDA(n) REG32(DMAC_DDA((n))) +#define REG_DMAC_DMACR REG32(DMAC_DMACR) +#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR) +#define REG_DMAC_DMADBR REG32(DMAC_DMADBR) +#define REG_DMAC_DMADBSR REG32(DMAC_DMADBSR) + +// DMA request source register +#define DMAC_DRSR_RS_BIT 0 +#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_TCU (28 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SADC (29 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SLCD (30 << DMAC_DRSR_RS_BIT) + +// DMA channel control/status register +#define DMAC_DCCSR_NDES (1 << 31) /* descriptor (0) or not (1) ? */ +#define DMAC_DCCSR_CDOA_BIT 16 /* copy of DMA offset address */ +#define DMAC_DCCSR_CDOA_MASK (0xff << DMAC_DCCSR_CDOA_BIT) +#define DMAC_DCCSR_INV (1 << 6) /* descriptor invalid */ +#define DMAC_DCCSR_AR (1 << 4) /* address error */ +#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ +#define DMAC_DCCSR_HLT (1 << 2) /* DMA halted */ +#define DMAC_DCCSR_CT (1 << 1) /* count terminated */ +#define DMAC_DCCSR_EN (1 << 0) /* channel enable bit */ + +// DMA channel command register +#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ +#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ +#define DMAC_DCMD_RDIL_BIT 16 /* request detection interval length */ +#define DMAC_DCMD_RDIL_MASK (0x0f << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_IGN (0 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_2 (1 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_4 (2 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_8 (3 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_12 (4 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_16 (5 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_20 (6 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_24 (7 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_28 (8 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_32 (9 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_48 (10 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_60 (11 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_64 (12 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_124 (13 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_128 (14 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_200 (15 << DMAC_DCMD_RDIL_BIT) +#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ +#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ +#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) +#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ +#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ +#define DMAC_DCMD_DES_V (1 << 4) /* descriptor valid flag */ +#define DMAC_DCMD_DES_VM (1 << 3) /* descriptor valid mask: 1:support V-bit */ +#define DMAC_DCMD_DES_VIE (1 << 2) /* DMA valid error interrupt enable */ +#define DMAC_DCMD_TIE (1 << 1) /* DMA transfer interrupt enable */ +#define DMAC_DCMD_LINK (1 << 0) /* descriptor link enable */ + +// DMA descriptor address register +#define DMAC_DDA_BASE_BIT 12 /* descriptor base address */ +#define DMAC_DDA_BASE_MASK (0x0fffff << DMAC_DDA_BASE_BIT) +#define DMAC_DDA_OFFSET_BIT 4 /* descriptor offset address */ +#define DMAC_DDA_OFFSET_MASK (0x0ff << DMAC_DDA_OFFSET_BIT) + +// DMA control register +#define DMAC_DMACR_PR_BIT 8 /* channel priority mode */ +#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_012345 (0 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_023145 (1 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_201345 (2 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_RR (3 << DMAC_DMACR_PR_BIT) /* round robin */ +#define DMAC_DMACR_HLT (1 << 3) /* DMA halt flag */ +#define DMAC_DMACR_AR (1 << 2) /* address error flag */ +#define DMAC_DMACR_DMAE (1 << 0) /* DMA enable bit */ + +// DMA doorbell register +#define DMAC_DMADBR_DB5 (1 << 5) /* doorbell for channel 5 */ +#define DMAC_DMADBR_DB4 (1 << 5) /* doorbell for channel 4 */ +#define DMAC_DMADBR_DB3 (1 << 5) /* doorbell for channel 3 */ +#define DMAC_DMADBR_DB2 (1 << 5) /* doorbell for channel 2 */ +#define DMAC_DMADBR_DB1 (1 << 5) /* doorbell for channel 1 */ +#define DMAC_DMADBR_DB0 (1 << 5) /* doorbell for channel 0 */ + +// DMA doorbell set register +#define DMAC_DMADBSR_DBS5 (1 << 5) /* enable doorbell for channel 5 */ +#define DMAC_DMADBSR_DBS4 (1 << 5) /* enable doorbell for channel 4 */ +#define DMAC_DMADBSR_DBS3 (1 << 5) /* enable doorbell for channel 3 */ +#define DMAC_DMADBSR_DBS2 (1 << 5) /* enable doorbell for channel 2 */ +#define DMAC_DMADBSR_DBS1 (1 << 5) /* enable doorbell for channel 1 */ +#define DMAC_DMADBSR_DBS0 (1 << 5) /* enable doorbell for channel 0 */ + +// DMA interrupt pending register +#define DMAC_DMAIPR_CIRQ5 (1 << 5) /* irq pending status for channel 5 */ +#define DMAC_DMAIPR_CIRQ4 (1 << 4) /* irq pending status for channel 4 */ +#define DMAC_DMAIPR_CIRQ3 (1 << 3) /* irq pending status for channel 3 */ +#define DMAC_DMAIPR_CIRQ2 (1 << 2) /* irq pending status for channel 2 */ +#define DMAC_DMAIPR_CIRQ1 (1 << 1) /* irq pending status for channel 1 */ +#define DMAC_DMAIPR_CIRQ0 (1 << 0) /* irq pending status for channel 0 */ + + +/************************************************************************* + * GPIO (General-Purpose I/O Ports) + *************************************************************************/ +#define MAX_GPIO_NUM 128 + +//n = 0,1,2,3 +#define GPIO_PXPIN(n) (GPIO_BASE + (0x00 + (n)*0x100)) /* PIN Level Register */ +#define GPIO_PXDAT(n) (GPIO_BASE + (0x10 + (n)*0x100)) /* Port Data Register */ +#define GPIO_PXDATS(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Data Set Register */ +#define GPIO_PXDATC(n) (GPIO_BASE + (0x18 + (n)*0x100)) /* Port Data Clear Register */ +#define GPIO_PXIM(n) (GPIO_BASE + (0x20 + (n)*0x100)) /* Interrupt Mask Register */ +#define GPIO_PXIMS(n) (GPIO_BASE + (0x24 + (n)*0x100)) /* Interrupt Mask Set Reg */ +#define GPIO_PXIMC(n) (GPIO_BASE + (0x28 + (n)*0x100)) /* Interrupt Mask Clear Reg */ +#define GPIO_PXPE(n) (GPIO_BASE + (0x30 + (n)*0x100)) /* Pull Enable Register */ +#define GPIO_PXPES(n) (GPIO_BASE + (0x34 + (n)*0x100)) /* Pull Enable Set Reg. */ +#define GPIO_PXPEC(n) (GPIO_BASE + (0x38 + (n)*0x100)) /* Pull Enable Clear Reg. */ +#define GPIO_PXFUN(n) (GPIO_BASE + (0x40 + (n)*0x100)) /* Function Register */ +#define GPIO_PXFUNS(n) (GPIO_BASE + (0x44 + (n)*0x100)) /* Function Set Register */ +#define GPIO_PXFUNC(n) (GPIO_BASE + (0x48 + (n)*0x100)) /* Function Clear Register */ +#define GPIO_PXSEL(n) (GPIO_BASE + (0x50 + (n)*0x100)) /* Select Register */ +#define GPIO_PXSELS(n) (GPIO_BASE + (0x54 + (n)*0x100)) /* Select Set Register */ +#define GPIO_PXSELC(n) (GPIO_BASE + (0x58 + (n)*0x100)) /* Select Clear Register */ +#define GPIO_PXDIR(n) (GPIO_BASE + (0x60 + (n)*0x100)) /* Direction Register */ +#define GPIO_PXDIRS(n) (GPIO_BASE + (0x64 + (n)*0x100)) /* Direction Set Register */ +#define GPIO_PXDIRC(n) (GPIO_BASE + (0x68 + (n)*0x100)) /* Direction Clear Register */ +#define GPIO_PXTRG(n) (GPIO_BASE + (0x70 + (n)*0x100)) /* Trigger Register */ +#define GPIO_PXTRGS(n) (GPIO_BASE + (0x74 + (n)*0x100)) /* Trigger Set Register */ +#define GPIO_PXTRGC(n) (GPIO_BASE + (0x78 + (n)*0x100)) /* Trigger Set Register */ +#define GPIO_PXFLG(n) (GPIO_BASE + (0x80 + (n)*0x100)) /* Port Flag Register */ +#define GPIO_PXFLGC(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Flag Clear Register */ + +#define REG_GPIO_PXPIN(n) REG32(GPIO_PXPIN((n))) /* PIN level */ +#define REG_GPIO_PXDAT(n) REG32(GPIO_PXDAT((n))) /* 1: interrupt pending */ +#define REG_GPIO_PXDATS(n) REG32(GPIO_PXDATS((n))) +#define REG_GPIO_PXDATC(n) REG32(GPIO_PXDATC((n))) +#define REG_GPIO_PXIM(n) REG32(GPIO_PXIM((n))) /* 1: mask pin interrupt */ +#define REG_GPIO_PXIMS(n) REG32(GPIO_PXIMS((n))) +#define REG_GPIO_PXIMC(n) REG32(GPIO_PXIMC((n))) +#define REG_GPIO_PXPE(n) REG32(GPIO_PXPE((n))) /* 1: disable pull up/down */ +#define REG_GPIO_PXPES(n) REG32(GPIO_PXPES((n))) +#define REG_GPIO_PXPEC(n) REG32(GPIO_PXPEC((n))) +#define REG_GPIO_PXFUN(n) REG32(GPIO_PXFUN((n))) /* 0:GPIO or intr, 1:FUNC */ +#define REG_GPIO_PXFUNS(n) REG32(GPIO_PXFUNS((n))) +#define REG_GPIO_PXFUNC(n) REG32(GPIO_PXFUNC((n))) +#define REG_GPIO_PXSEL(n) REG32(GPIO_PXSEL((n))) /* 0:GPIO/Fun0,1:intr/fun1*/ +#define REG_GPIO_PXSELS(n) REG32(GPIO_PXSELS((n))) +#define REG_GPIO_PXSELC(n) REG32(GPIO_PXSELC((n))) +#define REG_GPIO_PXDIR(n) REG32(GPIO_PXDIR((n))) /* 0:input/low-level-trig/falling-edge-trig, 1:output/high-level-trig/rising-edge-trig */ +#define REG_GPIO_PXDIRS(n) REG32(GPIO_PXDIRS((n))) +#define REG_GPIO_PXDIRC(n) REG32(GPIO_PXDIRC((n))) +#define REG_GPIO_PXTRG(n) REG32(GPIO_PXTRG((n))) /* 0:level-trigger, 1:edge-trigger */ +#define REG_GPIO_PXTRGS(n) REG32(GPIO_PXTRGS((n))) +#define REG_GPIO_PXTRGC(n) REG32(GPIO_PXTRGC((n))) +#define REG_GPIO_PXFLG(n) REG32(GPIO_PXFLG((n))) /* interrupt flag */ +#define REG_GPIO_PXFLGC(n) REG32(GPIO_PXFLGC((n))) /* interrupt flag */ + + +/************************************************************************* + * UART + *************************************************************************/ + +#define IRDA_BASE UART0_BASE +#define UART_BASE UART0_BASE +#define UART_OFF 0x1000 + +/* Register Offset */ +#define OFF_RDR (0x00) /* R 8b H'xx */ +#define OFF_TDR (0x00) /* W 8b H'xx */ +#define OFF_DLLR (0x00) /* RW 8b H'00 */ +#define OFF_DLHR (0x04) /* RW 8b H'00 */ +#define OFF_IER (0x04) /* RW 8b H'00 */ +#define OFF_ISR (0x08) /* R 8b H'01 */ +#define OFF_FCR (0x08) /* W 8b H'00 */ +#define OFF_LCR (0x0C) /* RW 8b H'00 */ +#define OFF_MCR (0x10) /* RW 8b H'00 */ +#define OFF_LSR (0x14) /* R 8b H'00 */ +#define OFF_MSR (0x18) /* R 8b H'00 */ +#define OFF_SPR (0x1C) /* RW 8b H'00 */ +#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */ +#define OFF_UMR (0x24) /* RW 8b H'00, UART M Register */ +#define OFF_UACR (0x28) /* RW 8b H'00, UART Add Cycle Register */ + +/* Register Address */ +#define UART0_RDR (UART0_BASE + OFF_RDR) +#define UART0_TDR (UART0_BASE + OFF_TDR) +#define UART0_DLLR (UART0_BASE + OFF_DLLR) +#define UART0_DLHR (UART0_BASE + OFF_DLHR) +#define UART0_IER (UART0_BASE + OFF_IER) +#define UART0_ISR (UART0_BASE + OFF_ISR) +#define UART0_FCR (UART0_BASE + OFF_FCR) +#define UART0_LCR (UART0_BASE + OFF_LCR) +#define UART0_MCR (UART0_BASE + OFF_MCR) +#define UART0_LSR (UART0_BASE + OFF_LSR) +#define UART0_MSR (UART0_BASE + OFF_MSR) +#define UART0_SPR (UART0_BASE + OFF_SPR) +#define UART0_SIRCR (UART0_BASE + OFF_SIRCR) +#define UART0_UMR (UART0_BASE + OFF_UMR) +#define UART0_UACR (UART0_BASE + OFF_UACR) + +/* + * Define macros for UARTIER + * UART Interrupt Enable Register + */ +#define UARTIER_RIE (1 << 0) /* 0: receive fifo full interrupt disable */ +#define UARTIER_TIE (1 << 1) /* 0: transmit fifo empty interrupt disable */ +#define UARTIER_RLIE (1 << 2) /* 0: receive line status interrupt disable */ +#define UARTIER_MIE (1 << 3) /* 0: modem status interrupt disable */ +#define UARTIER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */ + +/* + * Define macros for UARTISR + * UART Interrupt Status Register + */ +#define UARTISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */ +#define UARTISR_IID (7 << 1) /* Source of Interrupt */ +#define UARTISR_IID_MSI (0 << 1) /* Modem status interrupt */ +#define UARTISR_IID_THRI (1 << 1) /* Transmitter holding register empty */ +#define UARTISR_IID_RDI (2 << 1) /* Receiver data interrupt */ +#define UARTISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */ +#define UARTISR_IID_RTO (6 << 1) /* Receive timeout */ +#define UARTISR_FFMS (3 << 6) /* FIFO mode select, set when UARTFCR.FE is set to 1 */ +#define UARTISR_FFMS_NO_FIFO (0 << 6) +#define UARTISR_FFMS_FIFO_MODE (3 << 6) + +/* + * Define macros for UARTFCR + * UART FIFO Control Register + */ +#define UARTFCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */ +#define UARTFCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */ +#define UARTFCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */ +#define UARTFCR_DMS (1 << 3) /* 0: disable DMA mode */ +#define UARTFCR_UUE (1 << 4) /* 0: disable UART */ +#define UARTFCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */ +#define UARTFCR_RTRG_1 (0 << 6) +#define UARTFCR_RTRG_4 (1 << 6) +#define UARTFCR_RTRG_8 (2 << 6) +#define UARTFCR_RTRG_15 (3 << 6) + +/* + * Define macros for UARTLCR + * UART Line Control Register + */ +#define UARTLCR_WLEN (3 << 0) /* word length */ +#define UARTLCR_WLEN_5 (0 << 0) +#define UARTLCR_WLEN_6 (1 << 0) +#define UARTLCR_WLEN_7 (2 << 0) +#define UARTLCR_WLEN_8 (3 << 0) +#define UARTLCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 + 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ +#define UARTLCR_STOP1 (0 << 2) +#define UARTLCR_STOP2 (1 << 2) +#define UARTLCR_PE (1 << 3) /* 0: parity disable */ +#define UARTLCR_PROE (1 << 4) /* 0: even parity 1: odd parity */ +#define UARTLCR_SPAR (1 << 5) /* 0: sticky parity disable */ +#define UARTLCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */ +#define UARTLCR_DLAB (1 << 7) /* 0: access UARTRDR/TDR/IER 1: access UARTDLLR/DLHR */ + +/* + * Define macros for UARTLSR + * UART Line Status Register + */ +#define UARTLSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */ +#define UARTLSR_ORER (1 << 1) /* 0: no overrun error */ +#define UARTLSR_PER (1 << 2) /* 0: no parity error */ +#define UARTLSR_FER (1 << 3) /* 0; no framing error */ +#define UARTLSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */ +#define UARTLSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */ +#define UARTLSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */ +#define UARTLSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */ + +/* + * Define macros for UARTMCR + * UART Modem Control Register + */ +#define UARTMCR_RTS (1 << 1) /* 0: RTS_ output high, 1: RTS_ output low */ +#define UARTMCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */ +#define UARTMCR_MCE (1 << 7) /* 0: modem function is disable */ + +/* + * Define macros for UARTMSR + * UART Modem Status Register + */ +#define UARTMSR_CCTS (1 << 0) /* 1: a change on CTS_ pin */ +#define UARTMSR_CTS (1 << 4) /* 0: CTS_ pin is high */ + +/* + * Define macros for SIRCR + * Slow IrDA Control Register + */ +#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: SIR mode */ +#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: SIR mode */ +#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length + 1: 0 pulse width is 1.6us for 115.2Kbps */ +#define SIRCR_TDPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */ +#define SIRCR_RDPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */ + + +/************************************************************************* + * AIC (AC97/I2S Controller) + *************************************************************************/ +#define AIC_FR (AIC_BASE + 0x000) +#define AIC_CR (AIC_BASE + 0x004) +#define AIC_ACCR1 (AIC_BASE + 0x008) +#define AIC_ACCR2 (AIC_BASE + 0x00C) +#define AIC_I2SCR (AIC_BASE + 0x010) +#define AIC_SR (AIC_BASE + 0x014) +#define AIC_ACSR (AIC_BASE + 0x018) +#define AIC_I2SSR (AIC_BASE + 0x01C) +#define AIC_ACCAR (AIC_BASE + 0x020) +#define AIC_ACCDR (AIC_BASE + 0x024) +#define AIC_ACSAR (AIC_BASE + 0x028) +#define AIC_ACSDR (AIC_BASE + 0x02C) +#define AIC_I2SDIV (AIC_BASE + 0x030) +#define AIC_DR (AIC_BASE + 0x034) + +#define REG_AIC_FR REG32(AIC_FR) +#define REG_AIC_CR REG32(AIC_CR) +#define REG_AIC_ACCR1 REG32(AIC_ACCR1) +#define REG_AIC_ACCR2 REG32(AIC_ACCR2) +#define REG_AIC_I2SCR REG32(AIC_I2SCR) +#define REG_AIC_SR REG32(AIC_SR) +#define REG_AIC_ACSR REG32(AIC_ACSR) +#define REG_AIC_I2SSR REG32(AIC_I2SSR) +#define REG_AIC_ACCAR REG32(AIC_ACCAR) +#define REG_AIC_ACCDR REG32(AIC_ACCDR) +#define REG_AIC_ACSAR REG32(AIC_ACSAR) +#define REG_AIC_ACSDR REG32(AIC_ACSDR) +#define REG_AIC_I2SDIV REG32(AIC_I2SDIV) +#define REG_AIC_DR REG32(AIC_DR) + +/* AIC Controller Configuration Register (AIC_FR) */ + +#define AIC_FR_RFTH_BIT 12 /* Receive FIFO Threshold */ +#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT) +#define AIC_FR_TFTH_BIT 8 /* Transmit FIFO Threshold */ +#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT) +#define AIC_FR_LSMP (1 << 6) /* Play Zero sample or last sample */ +#define AIC_FR_ICDC (1 << 5) /* External(0) or Internal CODEC(1) */ +#define AIC_FR_AUSEL (1 << 4) /* AC97(0) or I2S/MSB-justified(1) */ +#define AIC_FR_RST (1 << 3) /* AIC registers reset */ +#define AIC_FR_BCKD (1 << 2) /* I2S BIT_CLK direction, 0:input,1:output */ +#define AIC_FR_SYNCD (1 << 1) /* I2S SYNC direction, 0:input,1:output */ +#define AIC_FR_ENB (1 << 0) /* AIC enable bit */ + +/* AIC Controller Common Control Register (AIC_CR) */ + +#define AIC_CR_OSS_BIT 19 /* Output Sample Size from memory (AIC V2 only) */ +#define AIC_CR_OSS_MASK (0x7 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_8BIT (0x0 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_16BIT (0x1 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_18BIT (0x2 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_20BIT (0x3 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_24BIT (0x4 << AIC_CR_OSS_BIT) +#define AIC_CR_ISS_BIT 16 /* Input Sample Size from memory (AIC V2 only) */ +#define AIC_CR_ISS_MASK (0x7 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_8BIT (0x0 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_16BIT (0x1 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_18BIT (0x2 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_20BIT (0x3 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_24BIT (0x4 << AIC_CR_ISS_BIT) +#define AIC_CR_RDMS (1 << 15) /* Receive DMA enable */ +#define AIC_CR_TDMS (1 << 14) /* Transmit DMA enable */ +#define AIC_CR_M2S (1 << 11) /* Mono to Stereo enable */ +#define AIC_CR_ENDSW (1 << 10) /* Endian switch enable */ +#define AIC_CR_AVSTSU (1 << 9) /* Signed <-> Unsigned toggle enable */ +#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ +#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ +#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ +#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ +#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ +#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ +#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ +#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ + +/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ + +#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ +#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) + #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ + #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ + #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ + #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ + #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ + #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ + #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ + #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ + #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ + #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ +#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ +#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) + #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ + #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ + #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ + #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ + #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ + #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ + #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ + #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ + #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ + #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ + +/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ + +#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ +#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ +#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ +#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ +#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) + #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ + #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ + #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ + #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ +#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ +#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) + #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ + #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ + #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ + #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ +#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ +#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ +#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ +#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ + +/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ + +#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ +#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ +#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) + #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ + #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ + #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ + #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ + #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ +#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ + +/* AIC Controller FIFO Status Register (AIC_SR) */ + +#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ +#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) +#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ +#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) +#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ +#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ +#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ +#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ + +/* AIC Controller AC-link Status Register (AIC_ACSR) */ + +#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ +#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ +#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ +#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ +#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ +#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ + +/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ + +#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ + +/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ + +#define AIC_ACCAR_CAR_BIT 0 +#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) + +/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ + +#define AIC_ACCDR_CDR_BIT 0 +#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) + +/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ + +#define AIC_ACSAR_SAR_BIT 0 +#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) + +/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ + +#define AIC_ACSDR_SDR_BIT 0 +#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) + +/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ + +#define AIC_I2SDIV_DIV_BIT 0 +#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) + #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ + #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ + #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ + #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ + #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ + #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ + + +/************************************************************************* + * ICDC (Internal CODEC) + *************************************************************************/ +#define ICDC_CR (ICDC_BASE + 0x0400) /* ICDC Control Register */ +#define ICDC_APWAIT (ICDC_BASE + 0x0404) /* Anti-Pop WAIT Stage Timing Control Register */ +#define ICDC_APPRE (ICDC_BASE + 0x0408) /* Anti-Pop HPEN-PRE Stage Timing Control Register */ +#define ICDC_APHPEN (ICDC_BASE + 0x040C) /* Anti-Pop HPEN Stage Timing Control Register */ +#define ICDC_APSR (ICDC_BASE + 0x0410) /* Anti-Pop Status Register */ +#define ICDC_CDCCR1 (ICDC_BASE + 0x0080) +#define ICDC_CDCCR2 (ICDC_BASE + 0x0084) + +#define REG_ICDC_CR REG32(ICDC_CR) +#define REG_ICDC_APWAIT REG32(ICDC_APWAIT) +#define REG_ICDC_APPRE REG32(ICDC_APPRE) +#define REG_ICDC_APHPEN REG32(ICDC_APHPEN) +#define REG_ICDC_APSR REG32(ICDC_APSR) +#define REG_ICDC_CDCCR1 REG32(ICDC_CDCCR1) +#define REG_ICDC_CDCCR2 REG32(ICDC_CDCCR2) + +/* ICDC Control Register */ +#define ICDC_CR_LINVOL_BIT 24 /* LINE Input Volume Gain: GAIN=LINVOL*1.5-34.5 */ +#define ICDC_CR_LINVOL_MASK (0x1f << ICDC_CR_LINVOL_BIT) +#define ICDC_CR_ASRATE_BIT 20 /* Audio Sample Rate */ +#define ICDC_CR_ASRATE_MASK (0x0f << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_8000 (0x0 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_11025 (0x1 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_12000 (0x2 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_16000 (0x3 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_22050 (0x4 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_24000 (0x5 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_32000 (0x6 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_44100 (0x7 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_48000 (0x8 << ICDC_CR_ASRATE_BIT) +#define ICDC_CR_MICBG_BIT 18 /* MIC Boost Gain */ +#define ICDC_CR_MICBG_MASK (0x3 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_0DB (0x0 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_6DB (0x1 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_12DB (0x2 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_20DB (0x3 << ICDC_CR_MICBG_BIT) +#define ICDC_CR_HPVOL_BIT 16 /* Headphone Volume Gain */ +#define ICDC_CR_HPVOL_MASK (0x3 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_0DB (0x0 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_2DB (0x1 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_4DB (0x2 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_6DB (0x3 << ICDC_CR_HPVOL_BIT) +#define ICDC_CR_ELINEIN (1 << 13) /* Enable LINE Input */ +#define ICDC_CR_EMIC (1 << 12) /* Enable MIC Input */ +#define ICDC_CR_SW1ON (1 << 11) /* Switch 1 in CODEC is on */ +#define ICDC_CR_EADC (1 << 10) /* Enable ADC */ +#define ICDC_CR_SW2ON (1 << 9) /* Switch 2 in CODEC is on */ +#define ICDC_CR_EDAC (1 << 8) /* Enable DAC */ +#define ICDC_CR_HPMUTE (1 << 5) /* Headphone Mute */ +#define ICDC_CR_HPTON (1 << 4) /* Headphone Amplifier Trun On */ +#define ICDC_CR_HPTOFF (1 << 3) /* Headphone Amplifier Trun Off */ +#define ICDC_CR_TAAP (1 << 2) /* Turn Around of the Anti-Pop Procedure */ +#define ICDC_CR_EAP (1 << 1) /* Enable Anti-Pop Procedure */ +#define ICDC_CR_SUSPD (1 << 0) /* CODEC Suspend */ + +/* Anti-Pop WAIT Stage Timing Control Register */ +#define ICDC_APWAIT_WAITSN_BIT 0 +#define ICDC_APWAIT_WAITSN_MASK (0x7ff << ICDC_APWAIT_WAITSN_BIT) + +/* Anti-Pop HPEN-PRE Stage Timing Control Register */ +#define ICDC_APPRE_PRESN_BIT 0 +#define ICDC_APPRE_PRESN_MASK (0x1ff << ICDC_APPRE_PRESN_BIT) + +/* Anti-Pop HPEN Stage Timing Control Register */ +#define ICDC_APHPEN_HPENSN_BIT 0 +#define ICDC_APHPEN_HPENSN_MASK (0x3fff << ICDC_APHPEN_HPENSN_BIT) + +/* Anti-Pop Status Register */ +#define ICDC_SR_HPST_BIT 14 /* Headphone Amplifier State */ +#define ICDC_SR_HPST_MASK (0x7 << ICDC_SR_HPST_BIT) +#define ICDC_SR_HPST_HP_OFF (0x0 << ICDC_SR_HPST_BIT) /* HP amplifier is off */ +#define ICDC_SR_HPST_TON_WAIT (0x1 << ICDC_SR_HPST_BIT) /* wait state in turn-on */ + #define ICDC_SR_HPST_TON_PRE (0x2 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-on */ +#define ICDC_SR_HPST_TON_HPEN (0x3 << ICDC_SR_HPST_BIT) /* HP enable state in turn-on */ + #define ICDC_SR_HPST_TOFF_HPEN (0x4 << ICDC_SR_HPST_BIT) /* HP enable state in turn-off */ + #define ICDC_SR_HPST_TOFF_PRE (0x5 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-off */ + #define ICDC_SR_HPST_TOFF_WAIT (0x6 << ICDC_SR_HPST_BIT) /* wait state in turn-off */ + #define ICDC_SR_HPST_HP_ON (0x7 << ICDC_SR_HPST_BIT) /* HP amplifier is on */ +#define ICDC_SR_SNCNT_BIT 0 /* Sample Number Counter */ +#define ICDC_SR_SNCNT_MASK (0x3fff << ICDC_SR_SNCNT_BIT) + + +/************************************************************************* + * I2C + *************************************************************************/ +#define I2C_DR (I2C_BASE + 0x000) +#define I2C_CR (I2C_BASE + 0x004) +#define I2C_SR (I2C_BASE + 0x008) +#define I2C_GR (I2C_BASE + 0x00C) + +#define REG_I2C_DR REG8(I2C_DR) +#define REG_I2C_CR REG8(I2C_CR) +#define REG_I2C_SR REG8(I2C_SR) +#define REG_I2C_GR REG16(I2C_GR) + +/* I2C Control Register (I2C_CR) */ + +#define I2C_CR_IEN (1 << 4) +#define I2C_CR_STA (1 << 3) +#define I2C_CR_STO (1 << 2) +#define I2C_CR_AC (1 << 1) +#define I2C_CR_I2CE (1 << 0) + +/* I2C Status Register (I2C_SR) */ + +#define I2C_SR_STX (1 << 4) +#define I2C_SR_BUSY (1 << 3) +#define I2C_SR_TEND (1 << 2) +#define I2C_SR_DRF (1 << 1) +#define I2C_SR_ACKF (1 << 0) + + +/************************************************************************* + * SSI + *************************************************************************/ +#define SSI_DR (SSI_BASE + 0x000) +#define SSI_CR0 (SSI_BASE + 0x004) +#define SSI_CR1 (SSI_BASE + 0x008) +#define SSI_SR (SSI_BASE + 0x00C) +#define SSI_ITR (SSI_BASE + 0x010) +#define SSI_ICR (SSI_BASE + 0x014) +#define SSI_GR (SSI_BASE + 0x018) + +#define REG_SSI_DR REG32(SSI_DR) +#define REG_SSI_CR0 REG16(SSI_CR0) +#define REG_SSI_CR1 REG32(SSI_CR1) +#define REG_SSI_SR REG32(SSI_SR) +#define REG_SSI_ITR REG16(SSI_ITR) +#define REG_SSI_ICR REG8(SSI_ICR) +#define REG_SSI_GR REG16(SSI_GR) + +/* SSI Data Register (SSI_DR) */ + +#define SSI_DR_GPC_BIT 0 +#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) + +/* SSI Control Register 0 (SSI_CR0) */ + +#define SSI_CR0_SSIE (1 << 15) +#define SSI_CR0_TIE (1 << 14) +#define SSI_CR0_RIE (1 << 13) +#define SSI_CR0_TEIE (1 << 12) +#define SSI_CR0_REIE (1 << 11) +#define SSI_CR0_LOOP (1 << 10) +#define SSI_CR0_RFINE (1 << 9) +#define SSI_CR0_RFINC (1 << 8) +#define SSI_CR0_FSEL (1 << 6) +#define SSI_CR0_TFLUSH (1 << 2) +#define SSI_CR0_RFLUSH (1 << 1) +#define SSI_CR0_DISREV (1 << 0) + +/* SSI Control Register 1 (SSI_CR1) */ + +#define SSI_CR1_FRMHL_BIT 30 +#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) + #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ + #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ + #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ + #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ +#define SSI_CR1_TFVCK_BIT 28 +#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) +#define SSI_CR1_TCKFI_BIT 26 +#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) +#define SSI_CR1_LFST (1 << 25) +#define SSI_CR1_ITFRM (1 << 24) +#define SSI_CR1_UNFIN (1 << 23) +#define SSI_CR1_MULTS (1 << 22) +#define SSI_CR1_FMAT_BIT 20 +#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) + #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ + #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ + #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ + #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ +#define SSI_CR1_TTRG_BIT 16 +#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_8 (1 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_16 (2 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_24 (3 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_32 (4 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_40 (5 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_48 (6 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_56 (7 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_64 (8 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_72 (9 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_80 (10<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_88 (11<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_96 (12<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_104 (13<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_112 (14<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_120 (15<< SSI_CR1_TTRG_BIT) +#define SSI_CR1_MCOM_BIT 12 +#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) + #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ + #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ + #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ + #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ + #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ + #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ + #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ + #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ + #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ + #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ + #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ + #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ + #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ + #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ + #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ + #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ +#define SSI_CR1_RTRG_BIT 8 +#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_8 (1 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_16 (2 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_24 (3 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_32 (4 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_40 (5 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_48 (6 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_56 (7 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_64 (8 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_72 (9 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_80 (10<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_88 (11<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_96 (12<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_104 (13<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_112 (14<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_120 (15<< SSI_CR1_RTRG_BIT) +#define SSI_CR1_FLEN_BIT 4 +#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) +#define SSI_CR1_PHA (1 << 1) +#define SSI_CR1_POL (1 << 0) + +/* SSI Status Register (SSI_SR) */ + +#define SSI_SR_TFIFONUM_BIT 16 +#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) +#define SSI_SR_RFIFONUM_BIT 8 +#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) +#define SSI_SR_END (1 << 7) +#define SSI_SR_BUSY (1 << 6) +#define SSI_SR_TFF (1 << 5) +#define SSI_SR_RFE (1 << 4) +#define SSI_SR_TFHE (1 << 3) +#define SSI_SR_RFHF (1 << 2) +#define SSI_SR_UNDR (1 << 1) +#define SSI_SR_OVER (1 << 0) + +/* SSI Interval Time Control Register (SSI_ITR) */ + +#define SSI_ITR_CNTCLK (1 << 15) +#define SSI_ITR_IVLTM_BIT 0 +#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) + + +/************************************************************************* + * MSC + *************************************************************************/ +#define MSC_STRPCL (MSC_BASE + 0x000) +#define MSC_STAT (MSC_BASE + 0x004) +#define MSC_CLKRT (MSC_BASE + 0x008) +#define MSC_CMDAT (MSC_BASE + 0x00C) +#define MSC_RESTO (MSC_BASE + 0x010) +#define MSC_RDTO (MSC_BASE + 0x014) +#define MSC_BLKLEN (MSC_BASE + 0x018) +#define MSC_NOB (MSC_BASE + 0x01C) +#define MSC_SNOB (MSC_BASE + 0x020) +#define MSC_IMASK (MSC_BASE + 0x024) +#define MSC_IREG (MSC_BASE + 0x028) +#define MSC_CMD (MSC_BASE + 0x02C) +#define MSC_ARG (MSC_BASE + 0x030) +#define MSC_RES (MSC_BASE + 0x034) +#define MSC_RXFIFO (MSC_BASE + 0x038) +#define MSC_TXFIFO (MSC_BASE + 0x03C) + +#define REG_MSC_STRPCL REG16(MSC_STRPCL) +#define REG_MSC_STAT REG32(MSC_STAT) +#define REG_MSC_CLKRT REG16(MSC_CLKRT) +#define REG_MSC_CMDAT REG32(MSC_CMDAT) +#define REG_MSC_RESTO REG16(MSC_RESTO) +#define REG_MSC_RDTO REG16(MSC_RDTO) +#define REG_MSC_BLKLEN REG16(MSC_BLKLEN) +#define REG_MSC_NOB REG16(MSC_NOB) +#define REG_MSC_SNOB REG16(MSC_SNOB) +#define REG_MSC_IMASK REG16(MSC_IMASK) +#define REG_MSC_IREG REG16(MSC_IREG) +#define REG_MSC_CMD REG8(MSC_CMD) +#define REG_MSC_ARG REG32(MSC_ARG) +#define REG_MSC_RES REG16(MSC_RES) +#define REG_MSC_RXFIFO REG32(MSC_RXFIFO) +#define REG_MSC_TXFIFO REG32(MSC_TXFIFO) + +/* MSC Clock and Control Register (MSC_STRPCL) */ + +#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) +#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) +#define MSC_STRPCL_START_READWAIT (1 << 5) +#define MSC_STRPCL_STOP_READWAIT (1 << 4) +#define MSC_STRPCL_RESET (1 << 3) +#define MSC_STRPCL_START_OP (1 << 2) +#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 +#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) + #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ + #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ + +/* MSC Status Register (MSC_STAT) */ + +#define MSC_STAT_IS_RESETTING (1 << 15) +#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) +#define MSC_STAT_PRG_DONE (1 << 13) +#define MSC_STAT_DATA_TRAN_DONE (1 << 12) +#define MSC_STAT_END_CMD_RES (1 << 11) +#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) +#define MSC_STAT_IS_READWAIT (1 << 9) +#define MSC_STAT_CLK_EN (1 << 8) +#define MSC_STAT_DATA_FIFO_FULL (1 << 7) +#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) +#define MSC_STAT_CRC_RES_ERR (1 << 5) +#define MSC_STAT_CRC_READ_ERROR (1 << 4) +#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 +#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) + #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ + #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ + #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ +#define MSC_STAT_TIME_OUT_RES (1 << 1) +#define MSC_STAT_TIME_OUT_READ (1 << 0) + +/* MSC Bus Clock Control Register (MSC_CLKRT) */ + +#define MSC_CLKRT_CLK_RATE_BIT 0 +#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) + #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ + +/* MSC Command Sequence Control Register (MSC_CMDAT) */ + +#define MSC_CMDAT_IO_ABORT (1 << 11) +#define MSC_CMDAT_BUS_WIDTH_BIT 9 +#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) + #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ + #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ + #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) + #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) +#define MSC_CMDAT_DMA_EN (1 << 8) +#define MSC_CMDAT_INIT (1 << 7) +#define MSC_CMDAT_BUSY (1 << 6) +#define MSC_CMDAT_STREAM_BLOCK (1 << 5) +#define MSC_CMDAT_WRITE (1 << 4) +#define MSC_CMDAT_READ (0 << 4) +#define MSC_CMDAT_DATA_EN (1 << 3) +#define MSC_CMDAT_RESPONSE_BIT 0 +#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) + #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ + #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ + #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ + #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ + #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ + #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ + #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ + +#define CMDAT_DMA_EN (1 << 8) +#define CMDAT_INIT (1 << 7) +#define CMDAT_BUSY (1 << 6) +#define CMDAT_STREAM (1 << 5) +#define CMDAT_WRITE (1 << 4) +#define CMDAT_DATA_EN (1 << 3) + +/* MSC Interrupts Mask Register (MSC_IMASK) */ + +#define MSC_IMASK_SDIO (1 << 7) +#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) +#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) +#define MSC_IMASK_END_CMD_RES (1 << 2) +#define MSC_IMASK_PRG_DONE (1 << 1) +#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) + + +/* MSC Interrupts Status Register (MSC_IREG) */ + +#define MSC_IREG_SDIO (1 << 7) +#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) +#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) +#define MSC_IREG_END_CMD_RES (1 << 2) +#define MSC_IREG_PRG_DONE (1 << 1) +#define MSC_IREG_DATA_TRAN_DONE (1 << 0) + + +/************************************************************************* + * EMC (External Memory Controller) + *************************************************************************/ +#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ +#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ +#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ +#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ +#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ +#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ +#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ +#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ +#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ +#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ + +#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ +#define EMC_NFECR (EMC_BASE + 0x100) /* NAND Flash ECC Control Register */ +#define EMC_NFECC (EMC_BASE + 0x104) /* NAND Flash ECC Data Register */ +#define EMC_NFPAR0 (EMC_BASE + 0x108) /* NAND Flash RS Parity 0 Register */ +#define EMC_NFPAR1 (EMC_BASE + 0x10c) /* NAND Flash RS Parity 1 Register */ +#define EMC_NFPAR2 (EMC_BASE + 0x110) /* NAND Flash RS Parity 2 Register */ +#define EMC_NFINTS (EMC_BASE + 0x114) /* NAND Flash Interrupt Status Register */ +#define EMC_NFINTE (EMC_BASE + 0x118) /* NAND Flash Interrupt Enable Register */ +#define EMC_NFERR0 (EMC_BASE + 0x11c) /* NAND Flash RS Error Report 0 Register */ +#define EMC_NFERR1 (EMC_BASE + 0x120) /* NAND Flash RS Error Report 1 Register */ +#define EMC_NFERR2 (EMC_BASE + 0x124) /* NAND Flash RS Error Report 2 Register */ +#define EMC_NFERR3 (EMC_BASE + 0x128) /* NAND Flash RS Error Report 3 Register */ + +#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ +#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ +#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ +#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ +#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ +#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ + + +#define REG_EMC_SMCR0 REG32(EMC_SMCR0) +#define REG_EMC_SMCR1 REG32(EMC_SMCR1) +#define REG_EMC_SMCR2 REG32(EMC_SMCR2) +#define REG_EMC_SMCR3 REG32(EMC_SMCR3) +#define REG_EMC_SMCR4 REG32(EMC_SMCR4) +#define REG_EMC_SACR0 REG32(EMC_SACR0) +#define REG_EMC_SACR1 REG32(EMC_SACR1) +#define REG_EMC_SACR2 REG32(EMC_SACR2) +#define REG_EMC_SACR3 REG32(EMC_SACR3) +#define REG_EMC_SACR4 REG32(EMC_SACR4) + +#define REG_EMC_NFCSR REG32(EMC_NFCSR) +#define REG_EMC_NFECR REG32(EMC_NFECR) +#define REG_EMC_NFECC REG32(EMC_NFECC) +#define REG_EMC_NFPAR0 REG32(EMC_NFPAR0) +#define REG_EMC_NFPAR1 REG32(EMC_NFPAR1) +#define REG_EMC_NFPAR2 REG32(EMC_NFPAR2) +#define REG_EMC_NFINTS REG32(EMC_NFINTS) +#define REG_EMC_NFINTE REG32(EMC_NFINTE) +#define REG_EMC_NFERR0 REG32(EMC_NFERR0) +#define REG_EMC_NFERR1 REG32(EMC_NFERR1) +#define REG_EMC_NFERR2 REG32(EMC_NFERR2) +#define REG_EMC_NFERR3 REG32(EMC_NFERR3) + +#define REG_EMC_DMCR REG32(EMC_DMCR) +#define REG_EMC_RTCSR REG16(EMC_RTCSR) +#define REG_EMC_RTCNT REG16(EMC_RTCNT) +#define REG_EMC_RTCOR REG16(EMC_RTCOR) +#define REG_EMC_DMAR0 REG32(EMC_DMAR0) + +/* Static Memory Control Register */ +#define EMC_SMCR_STRV_BIT 24 +#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) +#define EMC_SMCR_TAW_BIT 20 +#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) +#define EMC_SMCR_TBP_BIT 16 +#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) +#define EMC_SMCR_TAH_BIT 12 +#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) +#define EMC_SMCR_TAS_BIT 8 +#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) +#define EMC_SMCR_BW_BIT 6 +#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) + #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) + #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) + #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) +#define EMC_SMCR_BCM (1 << 3) +#define EMC_SMCR_BL_BIT 1 +#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) +#define EMC_SMCR_SMT (1 << 0) + +/* Static Memory Bank Addr Config Reg */ +#define EMC_SACR_BASE_BIT 8 +#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) +#define EMC_SACR_MASK_BIT 0 +#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) + +/* NAND Flash Control/Status Register */ +#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ +#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ +#define EMC_NFCSR_NFCE3 (1 << 5) +#define EMC_NFCSR_NFE3 (1 << 4) +#define EMC_NFCSR_NFCE2 (1 << 3) +#define EMC_NFCSR_NFE2 (1 << 2) +#define EMC_NFCSR_NFCE1 (1 << 1) +#define EMC_NFCSR_NFE1 (1 << 0) + +/* NAND Flash ECC Control Register */ +#define EMC_NFECR_PRDY (1 << 4) /* Parity Ready */ +#define EMC_NFECR_RS_DECODING (0 << 3) /* RS is in decoding phase */ +#define EMC_NFECR_RS_ENCODING (1 << 3) /* RS is in encoding phase */ +#define EMC_NFECR_HAMMING (0 << 2) /* Select HAMMING Correction Algorithm */ +#define EMC_NFECR_RS (1 << 2) /* Select RS Correction Algorithm */ +#define EMC_NFECR_ERST (1 << 1) /* ECC Reset */ +#define EMC_NFECR_ECCE (1 << 0) /* ECC Enable */ + +/* NAND Flash ECC Data Register */ +#define EMC_NFECC_ECC2_BIT 16 +#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT) +#define EMC_NFECC_ECC1_BIT 8 +#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT) +#define EMC_NFECC_ECC0_BIT 0 +#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT) + +/* NAND Flash Interrupt Status Register */ +#define EMC_NFINTS_ERRCNT_BIT 29 /* Error Count */ +#define EMC_NFINTS_ERRCNT_MASK (0x7 << EMC_NFINTS_ERRCNT_BIT) +#define EMC_NFINTS_PADF (1 << 4) /* Padding Finished */ +#define EMC_NFINTS_DECF (1 << 3) /* Decoding Finished */ +#define EMC_NFINTS_ENCF (1 << 2) /* Encoding Finished */ +#define EMC_NFINTS_UNCOR (1 << 1) /* Uncorrectable Error Occurred */ +#define EMC_NFINTS_ERR (1 << 0) /* Error Occurred */ + +/* NAND Flash Interrupt Enable Register */ +#define EMC_NFINTE_PADFE (1 << 4) /* Padding Finished Interrupt Enable */ +#define EMC_NFINTE_DECFE (1 << 3) /* Decoding Finished Interrupt Enable */ +#define EMC_NFINTE_ENCFE (1 << 2) /* Encoding Finished Interrupt Enable */ +#define EMC_NFINTE_UNCORE (1 << 1) /* Uncorrectable Error Occurred Intr Enable */ +#define EMC_NFINTE_ERRE (1 << 0) /* Error Occurred Interrupt */ + +/* NAND Flash RS Error Report Register */ +#define EMC_NFERR_INDEX_BIT 16 /* Error Symbol Index */ +#define EMC_NFERR_INDEX_MASK (0x1ff << EMC_NFERR_INDEX_BIT) +#define EMC_NFERR_MASK_BIT 0 /* Error Symbol Value */ +#define EMC_NFERR_MASK_MASK (0x1ff << EMC_NFERR_MASK_BIT) + + +/* DRAM Control Register */ +#define EMC_DMCR_BW_BIT 31 +#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) +#define EMC_DMCR_CA_BIT 26 +#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) +#define EMC_DMCR_RMODE (1 << 25) +#define EMC_DMCR_RFSH (1 << 24) +#define EMC_DMCR_MRSET (1 << 23) +#define EMC_DMCR_RA_BIT 20 +#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) + #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) + #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) + #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) +#define EMC_DMCR_BA_BIT 19 +#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) +#define EMC_DMCR_PDM (1 << 18) +#define EMC_DMCR_EPIN (1 << 17) +#define EMC_DMCR_TRAS_BIT 13 +#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) +#define EMC_DMCR_RCD_BIT 11 +#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) +#define EMC_DMCR_TPC_BIT 8 +#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) +#define EMC_DMCR_TRWL_BIT 5 +#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) +#define EMC_DMCR_TRC_BIT 2 +#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) +#define EMC_DMCR_TCL_BIT 0 +#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) + +/* Refresh Time Control/Status Register */ +#define EMC_RTCSR_CMF (1 << 7) +#define EMC_RTCSR_CKS_BIT 0 +#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) + +/* SDRAM Bank Address Configuration Register */ +#define EMC_DMAR_BASE_BIT 8 +#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) +#define EMC_DMAR_MASK_BIT 0 +#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) + +/* Mode Register of SDRAM bank 0 */ +#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ +#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ +#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) + #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) +#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ +#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) + #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) + #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) + #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) +#define EMC_SDMR_BT_BIT 3 /* Burst Type */ +#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) + #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ + #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ +#define EMC_SDMR_BL_BIT 0 /* Burst Length */ +#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) + +#define EMC_SDMR_CAS2_16BIT \ + (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) +#define EMC_SDMR_CAS2_32BIT \ + (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) +#define EMC_SDMR_CAS3_16BIT \ + (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) +#define EMC_SDMR_CAS3_32BIT \ + (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) + + +/************************************************************************* + * CIM + *************************************************************************/ +#define CIM_CFG (CIM_BASE + 0x0000) +#define CIM_CTRL (CIM_BASE + 0x0004) +#define CIM_STATE (CIM_BASE + 0x0008) +#define CIM_IID (CIM_BASE + 0x000C) +#define CIM_RXFIFO (CIM_BASE + 0x0010) +#define CIM_DA (CIM_BASE + 0x0020) +#define CIM_FA (CIM_BASE + 0x0024) +#define CIM_FID (CIM_BASE + 0x0028) +#define CIM_CMD (CIM_BASE + 0x002C) + +#define REG_CIM_CFG REG32(CIM_CFG) +#define REG_CIM_CTRL REG32(CIM_CTRL) +#define REG_CIM_STATE REG32(CIM_STATE) +#define REG_CIM_IID REG32(CIM_IID) +#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) +#define REG_CIM_DA REG32(CIM_DA) +#define REG_CIM_FA REG32(CIM_FA) +#define REG_CIM_FID REG32(CIM_FID) +#define REG_CIM_CMD REG32(CIM_CMD) + +/* CIM Configuration Register (CIM_CFG) */ + +#define CIM_CFG_INV_DAT (1 << 15) +#define CIM_CFG_VSP (1 << 14) +#define CIM_CFG_HSP (1 << 13) +#define CIM_CFG_PCP (1 << 12) +#define CIM_CFG_DUMMY_ZERO (1 << 9) +#define CIM_CFG_EXT_VSYNC (1 << 8) +#define CIM_CFG_PACK_BIT 4 +#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) +#define CIM_CFG_DSM_BIT 0 +#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) + #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ + #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ + #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ + #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ + +/* CIM Control Register (CIM_CTRL) */ + +#define CIM_CTRL_MCLKDIV_BIT 24 +#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) +#define CIM_CTRL_FRC_BIT 16 +#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) + #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ + #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ + #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ + #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ + #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ + #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ + #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ + #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ + #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ + #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ + #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ + #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ + #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ + #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ + #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ + #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ +#define CIM_CTRL_VDDM (1 << 13) +#define CIM_CTRL_DMA_SOFM (1 << 12) +#define CIM_CTRL_DMA_EOFM (1 << 11) +#define CIM_CTRL_DMA_STOPM (1 << 10) +#define CIM_CTRL_RXF_TRIGM (1 << 9) +#define CIM_CTRL_RXF_OFM (1 << 8) +#define CIM_CTRL_RXF_TRIG_BIT 4 +#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) + #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ + #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ + #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ + #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ + #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ + #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ + #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ + #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ +#define CIM_CTRL_DMA_EN (1 << 2) +#define CIM_CTRL_RXF_RST (1 << 1) +#define CIM_CTRL_ENA (1 << 0) + +/* CIM State Register (CIM_STATE) */ + +#define CIM_STATE_DMA_SOF (1 << 6) +#define CIM_STATE_DMA_EOF (1 << 5) +#define CIM_STATE_DMA_STOP (1 << 4) +#define CIM_STATE_RXF_OF (1 << 3) +#define CIM_STATE_RXF_TRIG (1 << 2) +#define CIM_STATE_RXF_EMPTY (1 << 1) +#define CIM_STATE_VDD (1 << 0) + +/* CIM DMA Command Register (CIM_CMD) */ + +#define CIM_CMD_SOFINT (1 << 31) +#define CIM_CMD_EOFINT (1 << 30) +#define CIM_CMD_STOP (1 << 28) +#define CIM_CMD_LEN_BIT 0 +#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) + + +/************************************************************************* + * SADC (Smart A/D Controller) + *************************************************************************/ + +#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ +#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ +#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ +#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ +#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ +#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ +#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ +#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ +#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ + +#define REG_SADC_ENA REG8(SADC_ENA) +#define REG_SADC_CFG REG32(SADC_CFG) +#define REG_SADC_CTRL REG8(SADC_CTRL) +#define REG_SADC_STATE REG8(SADC_STATE) +#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) +#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) +#define REG_SADC_TSDAT REG32(SADC_TSDAT) +#define REG_SADC_BATDAT REG16(SADC_BATDAT) +#define REG_SADC_SADDAT REG16(SADC_SADDAT) + +/* ADC Enable Register */ +#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ +#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ +#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ +#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ + +/* ADC Configure Register */ +#define SADC_CFG_EXIN (1 << 30) +#define SADC_CFG_CLKOUT_NUM_BIT 16 +#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) +#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ +#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ +#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) + #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) + #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) + #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) +#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ +#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) +#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ +#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) +#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ +#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ +#define SADC_CFG_CMD_BIT 0 /* ADC Command */ +#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) + #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ + #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ + #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ + #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ + #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ + #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ + #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ + #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ + #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ + #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ + #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ + #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ + #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ + +/* ADC Control Register */ +#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ +#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ +#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ +#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ +#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ + +/* ADC Status Register */ +#define SADC_STATE_TSBUSY (1 << 7) /* TS A/D is working */ +#define SADC_STATE_PBATBUSY (1 << 6) /* PBAT A/D is working */ +#define SADC_STATE_SBUSY (1 << 5) /* SADCIN A/D is working */ +#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ +#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ +#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ +#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ +#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ + +/* ADC Touch Screen Data Register */ +#define SADC_TSDAT_DATA0_BIT 0 +#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) +#define SADC_TSDAT_TYPE0 (1 << 15) +#define SADC_TSDAT_DATA1_BIT 16 +#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) +#define SADC_TSDAT_TYPE1 (1 << 31) + + +/************************************************************************* + * SLCD (Smart LCD Controller) + *************************************************************************/ + +#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ +#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ +#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ +#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ +#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */ + +#define REG_SLCD_CFG REG32(SLCD_CFG) +#define REG_SLCD_CTRL REG8(SLCD_CTRL) +#define REG_SLCD_STATE REG8(SLCD_STATE) +#define REG_SLCD_DATA REG32(SLCD_DATA) +#define REG_SLCD_FIFO REG32(SLCD_FIFO) + +/* SLCD Configure Register */ +#define SLCD_CFG_BURST_BIT 14 +#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT) + #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT) + #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT) +#define SLCD_CFG_DWIDTH_BIT 10 +#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT) +#define SLCD_CFG_CWIDTH_16BIT (0 << 8) +#define SLCD_CFG_CWIDTH_8BIT (1 << 8) +#define SLCD_CFG_CWIDTH_18BIT (2 << 8) +#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) +#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) +#define SLCD_CFG_RS_CMD_LOW (0 << 3) +#define SLCD_CFG_RS_CMD_HIGH (1 << 3) +#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) +#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) +#define SLCD_CFG_TYPE_PARALLEL (0 << 0) +#define SLCD_CFG_TYPE_SERIAL (1 << 0) + +/* SLCD Control Register */ +#define SLCD_CTRL_DMA_EN (1 << 0) + +/* SLCD Status Register */ +#define SLCD_STATE_BUSY (1 << 0) + +/* SLCD Data Register */ +#define SLCD_DATA_RS_DATA (0 << 31) +#define SLCD_DATA_RS_COMMAND (1 << 31) + +/* SLCD FIFO Register */ +#define SLCD_FIFO_RS_DATA (0 << 31) +#define SLCD_FIFO_RS_COMMAND (1 << 31) + + +/************************************************************************* + * LCD (LCD Controller) + *************************************************************************/ +#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ +#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ +#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ +#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ +#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ +#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ +#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ +#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ +#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ +#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ +#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ +#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ +#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ +#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ +#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ +#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ +#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ +#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ +#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ +#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ +#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ + +#define REG_LCD_CFG REG32(LCD_CFG) +#define REG_LCD_VSYNC REG32(LCD_VSYNC) +#define REG_LCD_HSYNC REG32(LCD_HSYNC) +#define REG_LCD_VAT REG32(LCD_VAT) +#define REG_LCD_DAH REG32(LCD_DAH) +#define REG_LCD_DAV REG32(LCD_DAV) +#define REG_LCD_PS REG32(LCD_PS) +#define REG_LCD_CLS REG32(LCD_CLS) +#define REG_LCD_SPL REG32(LCD_SPL) +#define REG_LCD_REV REG32(LCD_REV) +#define REG_LCD_CTRL REG32(LCD_CTRL) +#define REG_LCD_STATE REG32(LCD_STATE) +#define REG_LCD_IID REG32(LCD_IID) +#define REG_LCD_DA0 REG32(LCD_DA0) +#define REG_LCD_SA0 REG32(LCD_SA0) +#define REG_LCD_FID0 REG32(LCD_FID0) +#define REG_LCD_CMD0 REG32(LCD_CMD0) +#define REG_LCD_DA1 REG32(LCD_DA1) +#define REG_LCD_SA1 REG32(LCD_SA1) +#define REG_LCD_FID1 REG32(LCD_FID1) +#define REG_LCD_CMD1 REG32(LCD_CMD1) + +/* LCD Configure Register */ +#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ +#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) + #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) + #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) +#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ +#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ +#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ +#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ +#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ +#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ +#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ +#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ +#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ +#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ +#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ +#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ +#define LCD_CFG_HSP (1 << 11) /* HSYNC pority:0-active high,1-active low */ +#define LCD_CFG_PCP (1 << 10) /* PCLK pority:0-rising,1-falling */ +#define LCD_CFG_DEP (1 << 9) /* DE pority:0-active high,1-active low */ +#define LCD_CFG_VSP (1 << 8) /* VSYNC pority:0-rising,1-falling */ +#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ +#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) +#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ + #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ + #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ + #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ +#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ +#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ + #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) + /* JZ47XX defines */ + #define LCD_CFG_MODE_SHARP_HR (1 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_CFG_MODE_BIT) + + + +/* Vertical Synchronize Register */ +#define LCD_VSYNC_VPS_BIT 16 /* VSYNC pulse start in line clock, fixed to 0 */ +#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT) +#define LCD_VSYNC_VPE_BIT 0 /* VSYNC pulse end in line clock */ +#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT) + +/* Horizontal Synchronize Register */ +#define LCD_HSYNC_HPS_BIT 16 /* HSYNC pulse start position in dot clock */ +#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT) +#define LCD_HSYNC_HPE_BIT 0 /* HSYNC pulse end position in dot clock */ +#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT) + +/* Virtual Area Setting Register */ +#define LCD_VAT_HT_BIT 16 /* Horizontal Total size in dot clock */ +#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT) +#define LCD_VAT_VT_BIT 0 /* Vertical Total size in dot clock */ +#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT) + +/* Display Area Horizontal Start/End Point Register */ +#define LCD_DAH_HDS_BIT 16 /* Horizontal display area start in dot clock */ +#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT) +#define LCD_DAH_HDE_BIT 0 /* Horizontal display area end in dot clock */ +#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT) + +/* Display Area Vertical Start/End Point Register */ +#define LCD_DAV_VDS_BIT 16 /* Vertical display area start in line clock */ +#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT) +#define LCD_DAV_VDE_BIT 0 /* Vertical display area end in line clock */ +#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT) + +/* PS Signal Setting */ +#define LCD_PS_PSS_BIT 16 /* PS signal start position in dot clock */ +#define LCD_PS_PSS_MASK (0xffff << LCD_PS_PSS_BIT) +#define LCD_PS_PSE_BIT 0 /* PS signal end position in dot clock */ +#define LCD_PS_PSE_MASK (0xffff << LCD_PS_PSE_BIT) + +/* CLS Signal Setting */ +#define LCD_CLS_CLSS_BIT 16 /* CLS signal start position in dot clock */ +#define LCD_CLS_CLSS_MASK (0xffff << LCD_CLS_CLSS_BIT) +#define LCD_CLS_CLSE_BIT 0 /* CLS signal end position in dot clock */ +#define LCD_CLS_CLSE_MASK (0xffff << LCD_CLS_CLSE_BIT) + +/* SPL Signal Setting */ +#define LCD_SPL_SPLS_BIT 16 /* SPL signal start position in dot clock */ +#define LCD_SPL_SPLS_MASK (0xffff << LCD_SPL_SPLS_BIT) +#define LCD_SPL_SPLE_BIT 0 /* SPL signal end position in dot clock */ +#define LCD_SPL_SPLE_MASK (0xffff << LCD_SPL_SPLE_BIT) + +/* REV Signal Setting */ +#define LCD_REV_REVS_BIT 16 /* REV signal start position in dot clock */ +#define LCD_REV_REVS_MASK (0xffff << LCD_REV_REVS_BIT) + +/* LCD Control Register */ +#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ +#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) + #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ + #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ + #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ +#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode */ +#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode */ +#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ +#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ +#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) + #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ + #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ + #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ +#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ +#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) +#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ +#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ +#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ +#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ +#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ +#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ +#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ +#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ +#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ +#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ +#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ +#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ +#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) + #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ + #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ + #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ + #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ + #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ + #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ + +/* LCD Status Register */ +#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ +#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ +#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ +#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ +#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ +#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ +#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ + +/* DMA Command Register */ +#define LCD_CMD_SOFINT (1 << 31) +#define LCD_CMD_EOFINT (1 << 30) +#define LCD_CMD_PAL (1 << 28) +#define LCD_CMD_LEN_BIT 0 +#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT) + + +/************************************************************************* + * USB Device + *************************************************************************/ +#define USB_BASE UDC_BASE + +#define USB_REG_FADDR (USB_BASE + 0x00) /* Function Address 8-bit */ +#define USB_REG_POWER (USB_BASE + 0x01) /* Power Managemetn 8-bit */ +#define USB_REG_INTRIN (USB_BASE + 0x02) /* Interrupt IN 16-bit */ +#define USB_REG_INTROUT (USB_BASE + 0x04) /* Interrupt OUT 16-bit */ +#define USB_REG_INTRINE (USB_BASE + 0x06) /* Intr IN enable 16-bit */ +#define USB_REG_INTROUTE (USB_BASE + 0x08) /* Intr OUT enable 16-bit */ +#define USB_REG_INTRUSB (USB_BASE + 0x0a) /* Interrupt USB 8-bit */ +#define USB_REG_INTRUSBE (USB_BASE + 0x0b) /* Interrupt USB Enable 8-bit */ +#define USB_REG_FRAME (USB_BASE + 0x0c) /* Frame number 16-bit */ +#define USB_REG_INDEX (USB_BASE + 0x0e) /* Index register 8-bit */ +#define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ + +#define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ +#define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ +#define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ +#define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ +#define USB_REG_OUTMAXP (USB_BASE + 0x14) /* EP1 OUT Max Pkt Size 16-bit */ +#define USB_REG_OUTCSR (USB_BASE + 0x16) /* EP1 OUT CSR LSB 8/16bit */ +#define USB_REG_OUTCSRH (USB_BASE + 0x17) /* EP1 OUT CSR MSB 8-bit */ +#define USB_REG_OUTCOUNT (USB_BASE + 0x18) /* bytes in EP0/1 OUT FIFO 16-bit */ + +#define USB_FIFO_EP0 (USB_BASE + 0x20) +#define USB_FIFO_EP1 (USB_BASE + 0x24) +#define USB_FIFO_EP2 (USB_BASE + 0x28) + +#define USB_REG_EPINFO (USB_BASE + 0x78) /* Endpoint information */ +#define USB_REG_RAMINFO (USB_BASE + 0x79) /* RAM information */ + +#define USB_REG_INTR (USB_BASE + 0x200) /* DMA pending interrupts */ +#define USB_REG_CNTL1 (USB_BASE + 0x204) /* DMA channel 1 control */ +#define USB_REG_ADDR1 (USB_BASE + 0x208) /* DMA channel 1 AHB memory addr */ +#define USB_REG_COUNT1 (USB_BASE + 0x20c) /* DMA channel 1 byte count */ +#define USB_REG_CNTL2 (USB_BASE + 0x214) /* DMA channel 2 control */ +#define USB_REG_ADDR2 (USB_BASE + 0x218) /* DMA channel 2 AHB memory addr */ +#define USB_REG_COUNT2 (USB_BASE + 0x21c) /* DMA channel 2 byte count */ + + +/* Power register bit masks */ +#define USB_POWER_SUSPENDM 0x01 +#define USB_POWER_RESUME 0x04 +#define USB_POWER_HSMODE 0x10 +#define USB_POWER_HSENAB 0x20 +#define USB_POWER_SOFTCONN 0x40 + +/* Interrupt register bit masks */ +#define USB_INTR_SUSPEND 0x01 +#define USB_INTR_RESUME 0x02 +#define USB_INTR_RESET 0x04 + +#define USB_INTR_EP0 0x0001 +#define USB_INTR_INEP1 0x0002 +#define USB_INTR_INEP2 0x0004 +#define USB_INTR_OUTEP1 0x0002 + +/* CSR0 bit masks */ +#define USB_CSR0_OUTPKTRDY 0x01 +#define USB_CSR0_INPKTRDY 0x02 +#define USB_CSR0_SENTSTALL 0x04 +#define USB_CSR0_DATAEND 0x08 +#define USB_CSR0_SETUPEND 0x10 +#define USB_CSR0_SENDSTALL 0x20 +#define USB_CSR0_SVDOUTPKTRDY 0x40 +#define USB_CSR0_SVDSETUPEND 0x80 + +/* Endpoint CSR register bits */ +#define USB_INCSRH_AUTOSET 0x80 +#define USB_INCSRH_ISO 0x40 +#define USB_INCSRH_MODE 0x20 +#define USB_INCSRH_DMAREQENAB 0x10 +#define USB_INCSRH_DMAREQMODE 0x04 +#define USB_INCSR_CDT 0x40 +#define USB_INCSR_SENTSTALL 0x20 +#define USB_INCSR_SENDSTALL 0x10 +#define USB_INCSR_FF 0x08 +#define USB_INCSR_UNDERRUN 0x04 +#define USB_INCSR_FFNOTEMPT 0x02 +#define USB_INCSR_INPKTRDY 0x01 +#define USB_OUTCSRH_AUTOCLR 0x80 +#define USB_OUTCSRH_ISO 0x40 +#define USB_OUTCSRH_DMAREQENAB 0x20 +#define USB_OUTCSRH_DNYT 0x10 +#define USB_OUTCSRH_DMAREQMODE 0x08 +#define USB_OUTCSR_CDT 0x80 +#define USB_OUTCSR_SENTSTALL 0x40 +#define USB_OUTCSR_SENDSTALL 0x20 +#define USB_OUTCSR_FF 0x10 +#define USB_OUTCSR_DATAERR 0x08 +#define USB_OUTCSR_OVERRUN 0x04 +#define USB_OUTCSR_FFFULL 0x02 +#define USB_OUTCSR_OUTPKTRDY 0x01 + +/* Testmode register bits */ +#define USB_TEST_SE0NAK 0x01 +#define USB_TEST_J 0x02 +#define USB_TEST_K 0x04 +#define USB_TEST_PACKET 0x08 + +/* DMA control bits */ +#define USB_CNTL_ENA 0x01 +#define USB_CNTL_DIR_IN 0x02 +#define USB_CNTL_MODE_1 0x04 +#define USB_CNTL_INTR_EN 0x08 +#define USB_CNTL_EP(n) ((n) << 4) +#define USB_CNTL_BURST_0 (0 << 9) +#define USB_CNTL_BURST_4 (1 << 9) +#define USB_CNTL_BURST_8 (2 << 9) +#define USB_CNTL_BURST_16 (3 << 9) + +#endif /* __JZ4740_REGS_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/serial.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/serial.h new file mode 100644 index 000000000..c4819b982 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/serial.h @@ -0,0 +1,30 @@ +/* + * linux/include/asm-mips/mach-jz4740/serial.h + * + * Ingenic's JZ4740 common include. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_BOARD_SERIAL_H__ +#define __ASM_BOARD_SERIAL_H__ + +#ifndef CONFIG_SERIAL_MANY_PORTS +#undef RS_TABLE_SIZE +#define RS_TABLE_SIZE 1 +#endif + +#define JZ_BASE_BAUD (12000000/16) + +#define JZ_SERIAL_PORT_DEFNS \ + { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ + .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ + .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, + +#endif /* __ASM_BORAD_SERIAL_H__ */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/war.h b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/war.h new file mode 100644 index 000000000..3a5bc17e2 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/include/asm/mach-jz4740/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H +#define __ASM_MIPS_MACH_JZ4740_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/Makefile b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/Makefile new file mode 100644 index 000000000..ac4d3cd2d --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for the Ingenic JZ4740. +# + +# Object file lists. + +obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ + platform.o i2c.o + +obj-$(CONFIG_PROC_FS) += proc.o + +# board specific support + +obj-$(CONFIG_JZ4740_PAVO) += board-pavo.o +obj-$(CONFIG_JZ4740_LEO) += board-leo.o +obj-$(CONFIG_JZ4740_LYRA) += board-lyra.o +obj-$(CONFIG_JZ4725_DIPPER) += board-dipper.o +obj-$(CONFIG_JZ4720_VIRGO) += board-virgo.o + +# PM support + +obj-$(CONFIG_PM) +=pm.o + +# CPU Frequency scaling support + +obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/cpufreq.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/cpufreq.c new file mode 100644 index 000000000..d646a1e2e --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/cpufreq.c @@ -0,0 +1,602 @@ +/* + * linux/arch/mips/jz4740/cpufreq.c + * + * cpufreq driver for JZ4740 + * + * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. + * Author: + * + * 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 +#include +#include + +#include + +#include +#include + +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ + "cpufreq-jz4740", msg) + +#undef CHANGE_PLL + +#define PLL_UNCHANGED 0 +#define PLL_GOES_UP 1 +#define PLL_GOES_DOWN 2 + +#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) + +/* Saved the boot-time parameters */ +static struct { + /* SDRAM parameters */ + unsigned int mclk; /* memory clock, KHz */ + unsigned int tras; /* RAS pulse width, cycles of mclk */ + unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ + unsigned int tpc; /* RAS Precharge time, cycles of mclk */ + unsigned int trwl; /* Write Precharge Time, cycles of mclk */ + unsigned int trc; /* RAS Cycle Time, cycles of mclk */ + unsigned int rtcor; /* Refresh Time Constant */ + unsigned int sdram_initialized; + + /* LCD parameters */ + unsigned int lcd_clk; /* LCD clock, Hz */ + unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ + unsigned int lcd_clks_initialized; +} boot_config; + +struct jz4740_freq_percpu_info { + struct cpufreq_frequency_table table[7]; +}; + +static struct jz4740_freq_percpu_info jz4740_freq_table; + +/* + * This contains the registers value for an operating point. + * If only part of a register needs to change then there is + * a mask value for that register. + * When going to a new operating point the current register + * value is ANDed with the ~mask and ORed with the new value. + */ +struct dpm_regs { + u32 cpccr; /* Clock Freq Control Register */ + u32 cpccr_mask; /* Clock Freq Control Register mask */ + u32 cppcr; /* PLL1 Control Register */ + u32 cppcr_mask; /* PLL1 Control Register mask */ + u32 pll_up_flag; /* New PLL freq is higher than current or not */ +}; + +extern jz_clocks_t jz_clocks; + +static void jz_update_clocks(void) +{ + /* Next clocks must be updated if we have changed + * the PLL or divisors. + */ + jz_clocks.cclk = __cpm_get_cclk(); + jz_clocks.hclk = __cpm_get_hclk(); + jz_clocks.mclk = __cpm_get_mclk(); + jz_clocks.pclk = __cpm_get_pclk(); + jz_clocks.lcdclk = __cpm_get_lcdclk(); + jz_clocks.pixclk = __cpm_get_pixclk(); + jz_clocks.i2sclk = __cpm_get_i2sclk(); + jz_clocks.usbclk = __cpm_get_usbclk(); + jz_clocks.mscclk = __cpm_get_mscclk(); +} + +static void +jz_init_boot_config(void) +{ + if (!boot_config.lcd_clks_initialized) { + /* the first time to scale pll */ + boot_config.lcd_clk = __cpm_get_lcdclk(); + boot_config.lcdpix_clk = __cpm_get_pixclk(); + boot_config.lcd_clks_initialized = 1; + } + + if (!boot_config.sdram_initialized) { + /* the first time to scale frequencies */ + unsigned int dmcr, rtcor; + unsigned int tras, rcd, tpc, trwl, trc; + + dmcr = REG_EMC_DMCR; + rtcor = REG_EMC_RTCOR; + + tras = (dmcr >> 13) & 0x7; + rcd = (dmcr >> 11) & 0x3; + tpc = (dmcr >> 8) & 0x7; + trwl = (dmcr >> 5) & 0x3; + trc = (dmcr >> 2) & 0x7; + + boot_config.mclk = __cpm_get_mclk() / 1000; + boot_config.tras = tras + 4; + boot_config.rcd = rcd + 1; + boot_config.tpc = tpc + 1; + boot_config.trwl = trwl + 1; + boot_config.trc = trc * 2 + 1; + boot_config.rtcor = rtcor; + + boot_config.sdram_initialized = 1; + } +} + +static void jz_update_dram_rtcor(unsigned int new_mclk) +{ + unsigned int rtcor; + + new_mclk /= 1000; + rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; + rtcor--; + + if (rtcor < 1) rtcor = 1; + if (rtcor > 255) rtcor = 255; + + REG_EMC_RTCOR = rtcor; + REG_EMC_RTCNT = rtcor; +} + +static void jz_update_dram_dmcr(unsigned int new_mclk) +{ + unsigned int dmcr; + unsigned int tras, rcd, tpc, trwl, trc; + unsigned int valid_time, new_time; /* ns */ + + new_mclk /= 1000; + tras = boot_config.tras * new_mclk / boot_config.mclk; + rcd = boot_config.rcd * new_mclk / boot_config.mclk; + tpc = boot_config.tpc * new_mclk / boot_config.mclk; + trwl = boot_config.trwl * new_mclk / boot_config.mclk; + trc = boot_config.trc * new_mclk / boot_config.mclk; + + /* Validation checking */ + valid_time = (boot_config.tras * 1000000) / boot_config.mclk; + new_time = (tras * 1000000) / new_mclk; + if (new_time < valid_time) tras += 1; + + valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; + new_time = (rcd * 1000000) / new_mclk; + if (new_time < valid_time) rcd += 1; + + valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; + new_time = (tpc * 1000000) / new_mclk; + if (new_time < valid_time) tpc += 1; + + valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; + new_time = (trwl * 1000000) / new_mclk; + if (new_time < valid_time) trwl += 1; + + valid_time = (boot_config.trc * 1000000) / boot_config.mclk; + new_time = (trc * 1000000) / new_mclk; + if (new_time < valid_time) trc += 2; + + tras = (tras < 4) ? 4: tras; + tras = (tras > 11) ? 11: tras; + tras -= 4; + + rcd = (rcd < 1) ? 1: rcd; + rcd = (rcd > 4) ? 4: rcd; + rcd -= 1; + + tpc = (tpc < 1) ? 1: tpc; + tpc = (tpc > 8) ? 8: tpc; + tpc -= 1; + + trwl = (trwl < 1) ? 1: trwl; + trwl = (trwl > 4) ? 4: trwl; + trwl -= 1; + + trc = (trc < 1) ? 1: trc; + trc = (trc > 15) ? 15: trc; + trc /= 2; + + dmcr = REG_EMC_DMCR; + + dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); + dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); + + REG_EMC_DMCR = dmcr; +} + +static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) +{ + /* No risk, no fun: run with interrupts on! */ + if (new_mclk > cur_mclk) { + /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL + * and TRC of DMCR before changing the frequency. + */ + jz_update_dram_dmcr(new_mclk); + } else { + /* We're going SLOWER: first update RTCOR value + * before changing the frequency. + */ + jz_update_dram_rtcor(new_mclk); + } +} + +static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) +{ + /* No risk, no fun: run with interrupts on! */ + if (new_mclk > cur_mclk) { + /* We're going FASTER, so update RTCOR + * after changing the frequency + */ + jz_update_dram_rtcor(new_mclk); + } else { + /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL + * and TRC of DMCR after changing the frequency. + */ + jz_update_dram_dmcr(new_mclk); + } +} + +static void jz_scale_divisors(struct dpm_regs *regs) +{ + unsigned int cpccr; + unsigned int cur_mclk, new_mclk; + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + unsigned int tmp = 0, wait = PLL_WAIT_500NS; + + cpccr = REG_CPM_CPCCR; + cpccr &= ~((unsigned long)regs->cpccr_mask); + cpccr |= regs->cpccr; + cpccr |= CPM_CPCCR_CE; /* update immediately */ + + cur_mclk = __cpm_get_mclk(); + new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; + + /* Update some DRAM parameters before changing frequency */ + jz_update_dram_prev(cur_mclk, new_mclk); + + /* update register to change the clocks. + * align this code to a cache line. + */ + __asm__ __volatile__( + ".set noreorder\n\t" + ".align 5\n" + "sw %1,0(%0)\n\t" + "li %3,0\n\t" + "1:\n\t" + "bne %3,%2,1b\n\t" + "addi %3, 1\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set reorder\n\t" + : + : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); + + /* Update some other DRAM parameters after changing frequency */ + jz_update_dram_post(cur_mclk, new_mclk); +} + +#ifdef CHANGE_PLL +/* Maintain the LCD clock and pixel clock */ +static void jz_scale_lcd_divisors(struct dpm_regs *regs) +{ + unsigned int new_pll, new_lcd_div, new_lcdpix_div; + unsigned int cpccr; + unsigned int tmp = 0, wait = PLL_WAIT_500NS; + + if (!boot_config.lcd_clks_initialized) return; + + new_pll = __cpm_get_pllout(); + new_lcd_div = new_pll / boot_config.lcd_clk; + new_lcdpix_div = new_pll / boot_config.lcdpix_clk; + + if (new_lcd_div < 1) + new_lcd_div = 1; + if (new_lcd_div > 16) + new_lcd_div = 16; + + if (new_lcdpix_div < 1) + new_lcdpix_div = 1; + if (new_lcdpix_div > 512) + new_lcdpix_div = 512; + +// REG_CPM_CPCCR2 = new_lcdpix_div - 1; + + cpccr = REG_CPM_CPCCR; + cpccr &= ~CPM_CPCCR_LDIV_MASK; + cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); + cpccr |= CPM_CPCCR_CE; /* update immediately */ + + /* update register to change the clocks. + * align this code to a cache line. + */ + __asm__ __volatile__( + ".set noreorder\n\t" + ".align 5\n" + "sw %1,0(%0)\n\t" + "li %3,0\n\t" + "1:\n\t" + "bne %3,%2,1b\n\t" + "addi %3, 1\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set reorder\n\t" + : + : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); +} + +static void jz_scale_pll(struct dpm_regs *regs) +{ + unsigned int cppcr; + unsigned int cur_mclk, new_mclk, new_pll; + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + int od[] = {1, 2, 2, 4}; + + cppcr = REG_CPM_CPPCR; + cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); + regs->cppcr &= ~CPM_CPPCR_PLLEN; + cppcr |= (regs->cppcr | 0xff); + + /* Update some DRAM parameters before changing frequency */ + new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); + cur_mclk = __cpm_get_mclk(); + new_mclk = new_pll / div[(REG_CPM_CPCCR>>CPM_CPCCR_MDIV_BIT) & 0xf]; + + /* + * Update some SDRAM parameters + */ + jz_update_dram_prev(cur_mclk, new_mclk); + + /* + * Update PLL, align code to cache line. + */ + cppcr |= CPM_CPPCR_PLLEN; + __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" (CPM_CPPCR), "r" (cppcr)); + + /* Update some other DRAM parameters after changing frequency */ + jz_update_dram_post(cur_mclk, new_mclk); +} +#endif + +static void jz4740_transition(struct dpm_regs *regs) +{ + /* + * Get and save some boot-time conditions. + */ + jz_init_boot_config(); + +#ifdef CHANGE_PLL + /* + * Disable LCD before scaling pll. + * LCD and LCD pixel clocks should not be changed even if the PLL + * output frequency has been changed. + */ + REG_LCD_CTRL &= ~LCD_CTRL_ENA; + + /* + * Stop module clocks before scaling PLL + */ + __cpm_stop_eth(); + __cpm_stop_aic(1); + __cpm_stop_aic(2); +#endif + + /* ... add more as necessary */ + + if (regs->pll_up_flag == PLL_GOES_UP) { + /* the pll frequency is going up, so change dividors first */ + jz_scale_divisors(regs); +#ifdef CHANGE_PLL + jz_scale_pll(regs); +#endif + } + else if (regs->pll_up_flag == PLL_GOES_DOWN) { + /* the pll frequency is going down, so change pll first */ +#ifdef CHANGE_PLL + jz_scale_pll(regs); +#endif + jz_scale_divisors(regs); + } + else { + /* the pll frequency is unchanged, so change divisors only */ + jz_scale_divisors(regs); + } + +#ifdef CHANGE_PLL + /* + * Restart module clocks before scaling PLL + */ + __cpm_start_eth(); + __cpm_start_aic(1); + __cpm_start_aic(2); + + /* ... add more as necessary */ + + /* Scale the LCD divisors after scaling pll */ + if (regs->pll_up_flag != PLL_UNCHANGED) { + jz_scale_lcd_divisors(regs); + } + + /* Enable LCD controller */ + REG_LCD_CTRL &= ~LCD_CTRL_DIS; + REG_LCD_CTRL |= LCD_CTRL_ENA; +#endif + + /* Update system clocks */ + jz_update_clocks(); +} + +extern unsigned int idle_times; +static unsigned int jz4740_freq_get(unsigned int cpu) +{ + return (__cpm_get_cclk() / 1000); +} + +static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) +{ + int n2FR[33] = { + 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 9 + }; + int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ + unsigned int div_of_cclk, new_freq, i; + + regs->pll_up_flag = PLL_UNCHANGED; + regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; + + new_freq = jz4740_freq_table.table[index].frequency; + + do { + div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); + } while (div_of_cclk==0); + + if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { + for(i = 1; i<4; i++) { + div[i] = 3; + } + } else { + for(i = 1; i<4; i++) { + div[i] = 2; + } + } + + for(i = 0; i<4; i++) { + div[i] *= div_of_cclk; + } + + dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); + + regs->cpccr = + (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | + (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | + (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | + (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); + + return div_of_cclk; +} + +static void jz4740_set_cpu_divider_index(unsigned int cpu, unsigned int index) +{ + unsigned long divisor, old_divisor; + struct cpufreq_freqs freqs; + struct dpm_regs regs; + + old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); + divisor = index_to_divisor(index, ®s); + + freqs.old = __cpm_get_cclk() / 1000; + freqs.new = __cpm_get_pllout() / (1000 * divisor); + freqs.cpu = cpu; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + if (old_divisor != divisor) + jz4740_transition(®s); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +} + +static int jz4740_freq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int new_index = 0; + + if (cpufreq_frequency_table_target(policy, + &jz4740_freq_table.table[0], + target_freq, relation, &new_index)) + return -EINVAL; + + jz4740_set_cpu_divider_index(policy->cpu, new_index); + + dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); + + return 0; +} + +static int jz4740_freq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, + &jz4740_freq_table.table[0]); +} + +static int __init jz4740_cpufreq_driver_init(struct cpufreq_policy *policy) +{ + + struct cpufreq_frequency_table *table = &jz4740_freq_table.table[0]; + unsigned int MAX_FREQ; + + dprintk(KERN_INFO "Jz4740 cpufreq driver\n"); + + if (policy->cpu != 0) + return -EINVAL; + + policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + policy->cpuinfo.min_freq = MAX_FREQ/8; + policy->cpuinfo.max_freq = MAX_FREQ; + policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ + + table[0].index = 0; + table[0].frequency = MAX_FREQ/8; + table[1].index = 1; + table[1].frequency = MAX_FREQ/6; + table[2].index = 2; + table[2].frequency = MAX_FREQ/4; + table[3].index = 3; + table[3].frequency = MAX_FREQ/3; + table[4].index = 4; + table[4].frequency = MAX_FREQ/2; + table[5].index = 5; + table[5].frequency = MAX_FREQ; + table[6].index = 6; + table[6].frequency = CPUFREQ_TABLE_END; + +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS + cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ +#endif + + return cpufreq_frequency_table_cpuinfo(policy, table); +} + +static struct cpufreq_driver cpufreq_jz4740_driver = { +// .flags = CPUFREQ_STICKY, + .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("Regen "); +MODULE_DESCRIPTION("cpufreq driver for Jz4740"); +MODULE_LICENSE("GPL"); + diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/dma.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/dma.c new file mode 100644 index 000000000..dd5055e59 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/dma.c @@ -0,0 +1,768 @@ +/* + * linux/arch/mips/jz4740/dma.c + * + * Support functions for the JZ4740 internal DMA channels. + * No-descriptor transfer only. + * Descriptor transfer should also call jz_request_dma() to get a free + * channel and call jz_free_dma() to free the channel. And driver should + * build the DMA descriptor and setup the DMA channel by itself. + * + * Copyright (C) 2006 Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * A note on resource allocation: + * + * All drivers needing DMA channels, should allocate and release them + * through the public routines `jz_request_dma()' and `jz_free_dma()'. + * + * In order to avoid problems, all processes should allocate resources in + * the same sequence and release them in the reverse order. + * + * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. + * When releasing them, first release the IRQ, then release the DMA. The + * main reason for this order is that, if you are requesting the DMA buffer + * done interrupt, you won't know the irq number until the DMA channel is + * returned from jz_request_dma(). + */ + +struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, +}; + +// Device FIFO addresses and default DMA modes +static const struct { + unsigned int fifo_addr; + unsigned int dma_mode; + unsigned int dma_source; +} dma_dev_table[DMA_ID_MAX] = { + {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, + {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, + {CPHYSADDR(SSI_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT}, + {CPHYSADDR(SSI_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSIIN}, + {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, + {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, + {CPHYSADDR(MSC_TXFIFO), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT}, + {CPHYSADDR(MSC_RXFIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSCIN}, + {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, + {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, + {}, +}; + + +int jz_dma_read_proc(char *buf, char **start, off_t fpos, + int length, int *eof, void *data) +{ + int i, len = 0; + struct jz_dma_chan *chan; + + for (i = 0; i < MAX_DMA_NUM; i++) { + if ((chan = get_dma_chan(i)) != NULL) { + len += sprintf(buf + len, "%2d: %s\n", + i, chan->dev_str); + } + } + + if (fpos >= len) { + *start = buf; + *eof = 1; + return 0; + } + *start = buf + fpos; + if ((len -= fpos) > length) + return length; + *eof = 1; + return len; +} + + +void dump_jz_dma_channel(unsigned int dmanr) +{ + struct jz_dma_chan *chan; + + if (dmanr > MAX_DMA_NUM) + return; + chan = &jz_dma_table[dmanr]; + + printk("DMA%d Registers:\n", dmanr); + printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR); + printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); + printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); + printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); + printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); + printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); + printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); + printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); + printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR); +} + + +/** + * jz_request_dma - dynamically allcate an idle DMA channel to return + * @dev_id: the specified dma device id or DMA_ID_RAW_SET + * @dev_str: the specified dma device string name + * @irqhandler: the irq handler, or NULL + * @irqflags: the irq handler flags + * @irq_dev_id: the irq handler device id for shared irq + * + * Finds a free channel, and binds the requested device to it. + * Returns the allocated channel number, or negative on error. + * Requests the DMA done IRQ if irqhandler != NULL. + * +*/ +/*int jz_request_dma(int dev_id, const char *dev_str, + void (*irqhandler)(int, void *, struct pt_regs *), + unsigned long irqflags, + void *irq_dev_id) +*/ + +int jz_request_dma(int dev_id, const char *dev_str, + irqreturn_t (*irqhandler)(int, void *), + unsigned long irqflags, + void *irq_dev_id) +{ + struct jz_dma_chan *chan; + int i, ret; + + if (dev_id < 0 || dev_id >= DMA_ID_MAX) + return -EINVAL; + + for (i = 0; i < MAX_DMA_NUM; i++) { + if (jz_dma_table[i].dev_id < 0) + break; + } + if (i == MAX_DMA_NUM) /* no free channel */ + return -ENODEV; + + /* we got a free channel */ + chan = &jz_dma_table[i]; + + if (irqhandler) { + chan->irq = IRQ_DMA_0 + i; // allocate irq number + chan->irq_dev = irq_dev_id; + if ((ret = request_irq(chan->irq, irqhandler, irqflags, + dev_str, chan->irq_dev))) { + chan->irq = -1; + chan->irq_dev = NULL; + return ret; + } + } else { + chan->irq = -1; + chan->irq_dev = NULL; + } + + // fill it in + chan->io = i; + chan->dev_id = dev_id; + chan->dev_str = dev_str; + chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; + chan->mode = dma_dev_table[dev_id].dma_mode; + chan->source = dma_dev_table[dev_id].dma_source; + + return i; +} + +void jz_free_dma(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) { + printk("Trying to free DMA%d\n", dmanr); + return; + } + + disable_dma(dmanr); + if (chan->irq) + free_irq(chan->irq, chan->irq_dev); + + chan->irq = -1; + chan->irq_dev = NULL; + chan->dev_id = -1; +} + +void jz_set_dma_dest_width(int dmanr, int nbit) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + chan->mode &= ~DMAC_DCMD_DWDH_MASK; + switch (nbit) { + case 8: + chan->mode |= DMAC_DCMD_DWDH_8; + break; + case 16: + chan->mode |= DMAC_DCMD_DWDH_16; + break; + case 32: + chan->mode |= DMAC_DCMD_DWDH_32; + break; + } +} + +void jz_set_dma_src_width(int dmanr, int nbit) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + chan->mode &= ~DMAC_DCMD_SWDH_MASK; + switch (nbit) { + case 8: + chan->mode |= DMAC_DCMD_SWDH_8; + break; + case 16: + chan->mode |= DMAC_DCMD_SWDH_16; + break; + case 32: + chan->mode |= DMAC_DCMD_SWDH_32; + break; + } +} + +void jz_set_dma_block_size(int dmanr, int nbyte) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + chan->mode &= ~DMAC_DCMD_DS_MASK; + switch (nbyte) { + case 1: + chan->mode |= DMAC_DCMD_DS_8BIT; + break; + case 2: + chan->mode |= DMAC_DCMD_DS_16BIT; + break; + case 4: + chan->mode |= DMAC_DCMD_DS_32BIT; + break; + case 16: + chan->mode |= DMAC_DCMD_DS_16BYTE; + break; + case 32: + chan->mode |= DMAC_DCMD_DS_32BYTE; + break; + } +} + +unsigned int jz_get_dma_command(int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + return chan->mode; +} + +/** + * jz_set_dma_mode - do the raw settings for the specified DMA channel + * @dmanr: the specified DMA channel + * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE + * @dma_mode: dma raw mode + * @dma_source: dma raw request source + * @fifo_addr: dma raw device fifo address + * + * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call + * jz_set_dma_mode() rather than set_dma_mode() if you work with + * and external request dma device. + * + * NOTE: Don not dynamically allocate dma channel if one external request + * dma device will occupy this channel. +*/ +int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, + unsigned int dma_mode, unsigned int dma_source, + unsigned int fifo_addr) +{ + int dev_id, i; + struct jz_dma_chan *chan; + + if (dmanr > MAX_DMA_NUM) + return -ENODEV; + for (i = 0; i < MAX_DMA_NUM; i++) { + if (jz_dma_table[i].dev_id < 0) + break; + } + if (i == MAX_DMA_NUM) + return -ENODEV; + + chan = &jz_dma_table[dmanr]; + dev_id = chan->dev_id; + if (dev_id > 0) { + printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", + __FUNCTION__, dmanr); + return -ENODEV; + } + + /* clone it from the dynamically allocated. */ + if (i != dmanr) { + chan->irq = jz_dma_table[i].irq; + chan->irq_dev = jz_dma_table[i].irq_dev; + chan->dev_str = jz_dma_table[i].dev_str; + jz_dma_table[i].irq = 0; + jz_dma_table[i].irq_dev = NULL; + jz_dma_table[i].dev_id = -1; + } + chan->dev_id = DMA_ID_RAW_SET; + chan->io = dmanr; + chan->fifo_addr = fifo_addr; + chan->mode = dma_mode; + chan->source = dma_source; + + set_dma_mode(dmanr, dma_mode); + + return dmanr; +} + +void enable_dma(unsigned int dmanr) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); + REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ + __dmac_enable_channel(dmanr); + if (chan->irq) + __dmac_channel_enable_irq(dmanr); +} + +#define DMA_DISABLE_POLL 0x10000 + +void disable_dma(unsigned int dmanr) +{ + int i; + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + if (!__dmac_channel_enabled(dmanr)) + return; + + for (i = 0; i < DMA_DISABLE_POLL; i++) + if (__dmac_channel_transmit_end_detected(dmanr)) + break; +#if 0 + if (i == DMA_DISABLE_POLL) + printk(KERN_INFO "disable_dma: poll expired!\n"); +#endif + + __dmac_disable_channel(dmanr); + if (chan->irq) + __dmac_channel_disable_irq(dmanr); +} + +/* Note: DMA_MODE_MASK is simulated by sw */ +void set_dma_mode(unsigned int dmanr, unsigned int mode) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); + mode &= DMA_MODE_MASK; + if (mode == DMA_MODE_READ) { + chan->mode |= DMAC_DCMD_DAI; + chan->mode &= ~DMAC_DCMD_SAI; + } else if (mode == DMA_MODE_WRITE) { + chan->mode |= DMAC_DCMD_SAI; + chan->mode &= ~DMAC_DCMD_DAI; + } else { + printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); + } + REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; + REG_DMAC_DRSR(chan->io) = chan->source; +} + +void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) +{ + unsigned int mode; + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + mode = chan->mode & DMA_MODE_MASK; + if (mode == DMA_MODE_READ) { + REG_DMAC_DSAR(chan->io) = chan->fifo_addr; + REG_DMAC_DTAR(chan->io) = phyaddr; + } else if (mode == DMA_MODE_WRITE) { + REG_DMAC_DSAR(chan->io) = phyaddr; + REG_DMAC_DTAR(chan->io) = chan->fifo_addr; + } else + printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); +} + +void set_dma_count(unsigned int dmanr, unsigned int bytecnt) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + int dma_ds[] = {4, 1, 2, 16, 32}; + unsigned int ds; + + if (!chan) + return; + + ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; + REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count +} + +unsigned int get_dma_residue(unsigned int dmanr) +{ + unsigned int count, ds; + int dma_ds[] = {4, 1, 2, 16, 32}; + struct jz_dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return 0; + + ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; + count = REG_DMAC_DTCR(chan->io); + count = count * dma_ds[ds]; + + return count; +} + +void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + switch (audio_fmt) { + case AFMT_U8: + /* burst mode : 32BIT */ + break; + case AFMT_S16_LE: + /* burst mode : 16BYTE */ + if (mode == DMA_MODE_READ) { + chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; + chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); + mode &= DMA_MODE_MASK; + chan->mode |= DMAC_DCMD_DAI; + chan->mode &= ~DMAC_DCMD_SAI; + } else if (mode == DMA_MODE_WRITE) { + chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; + chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); + mode &= DMA_MODE_MASK; + chan->mode |= DMAC_DCMD_SAI; + chan->mode &= ~DMAC_DCMD_DAI; + } else + printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); + + REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; + REG_DMAC_DRSR(chan->io) = chan->source; + break; + } +} + +void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) +{ + struct jz_dma_chan *chan = get_dma_chan(dmanr); + + if (!chan) + return; + + switch (audio_fmt) { + case 8: + /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ + break; + case 16: + /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ + if (mode == DMA_MODE_READ) { + chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; + chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); + mode &= DMA_MODE_MASK; + chan->mode |= DMAC_DCMD_DAI; + chan->mode &= ~DMAC_DCMD_SAI; + } else if (mode == DMA_MODE_WRITE) { + chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; + chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); + mode &= DMA_MODE_MASK; + chan->mode |= DMAC_DCMD_SAI; + chan->mode &= ~DMAC_DCMD_DAI; + } else + printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); + + REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; + REG_DMAC_DRSR(chan->io) = chan->source; + break; + } +} + +#undef JZ4740_DMAC_TEST_ENABLE + +#ifdef JZ4740_DMAC_TEST_ENABLE + +/* + * DMA test: external address <--> external address + */ +#define TEST_DMA_SIZE 16*1024 + +static jz_dma_desc *dma_desc; + +static int dma_chan; +static dma_addr_t dma_desc_phys_addr; +static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; + +static int dma_check_result(void *src, void *dst, int size) +{ + unsigned int addr1, addr2, i, err = 0; + + addr1 = (unsigned int)src; + addr2 = (unsigned int)dst; + + for (i = 0; i < size; i += 4) { + if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { + err++; + printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); + } + addr1 += 4; + addr2 += 4; + } + printk("check DMA result err=%d\n", err); + return err; +} + +static void jz4740_dma_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + printk("jz4740_dma_irq %d\n", irq); + + REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ + + if (__dmac_channel_transmit_halt_detected(dma_chan)) { + printk("DMA HALT\n"); + __dmac_channel_clear_transmit_halt(dma_chan); + } + + if (__dmac_channel_address_error_detected(dma_chan)) { + printk("DMA ADDR ERROR\n"); + __dmac_channel_clear_address_error(dma_chan); + } + + if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { + printk("DMA DESC INVALID\n"); + __dmac_channel_clear_descriptor_invalid(dma_chan); + } + + if (__dmac_channel_count_terminated_detected(dma_chan)) { + printk("DMA CT\n"); + __dmac_channel_clear_count_terminated(dma_chan); + } + + if (__dmac_channel_transmit_end_detected(dma_chan)) { + printk("DMA TT\n"); + __dmac_channel_clear_transmit_end(dma_chan); + dump_jz_dma_channel(dma_chan); + dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); + } + + /* free buffers */ + printk("free DMA buffers\n"); + free_pages(dma_src_addr, 2); + free_pages(dma_dst_addr, 2); + + if (dma_desc) + free_pages((unsigned int)dma_desc, 0); + + /* free dma */ + jz_free_dma(dma_chan); +} + +void dma_nodesc_test(void) +{ + unsigned int addr, i; + + printk("dma_nodesc_test\n"); + + /* Request DMA channel and setup irq handler */ + dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq, + SA_INTERRUPT, NULL); + if (dma_chan < 0) { + printk("Setup irq failed\n"); + return; + } + + printk("Requested DMA channel = %d\n", dma_chan); + + /* Allocate DMA buffers */ + dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ + dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ + + dma_src_phys_addr = CPHYSADDR(dma_src_addr); + dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); + + printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", + dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); + + /* Prepare data for source buffer */ + addr = (unsigned int)dma_src_addr; + for (i = 0; i < TEST_DMA_SIZE; i += 4) { + *(volatile unsigned int *)addr = addr; + addr += 4; + } + dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); + + /* Init target buffer */ + memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); + dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); + + /* Init DMA module */ + printk("Starting DMA\n"); + REG_DMAC_DMACR = 0; + REG_DMAC_DCCSR(dma_chan) = 0; + REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; + REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; + REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; + REG_DMAC_DTCR(dma_chan) = 512; + REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; + REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; + REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ + + printk("DMA started. IMR=%08x\n", REG_INTC_IMR); +} + +void dma_desc_test(void) +{ + unsigned int next, addr, i; + static jz_dma_desc *desc; + + printk("dma_desc_test\n"); + + /* Request DMA channel and setup irq handler */ + dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq, + SA_INTERRUPT, NULL); + if (dma_chan < 0) { + printk("Setup irq failed\n"); + return; + } + + printk("Requested DMA channel = %d\n", dma_chan); + + /* Allocate DMA buffers */ + dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ + dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ + + dma_src_phys_addr = CPHYSADDR(dma_src_addr); + dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); + + printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", + dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); + + /* Prepare data for source buffer */ + addr = (unsigned int)dma_src_addr; + for (i = 0; i < TEST_DMA_SIZE; i += 4) { + *(volatile unsigned int *)addr = addr; + addr += 4; + } + dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); + + /* Init target buffer */ + memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); + dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); + + /* Allocate DMA descriptors */ + dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); + dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); + + printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); + + /* Setup DMA descriptors */ + desc = dma_desc; + next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; + + desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; + desc->dsadr = dma_src_phys_addr; /* DMA source address */ + desc->dtadr = dma_dst_phys_addr; /* DMA target address */ + desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ + + desc++; + next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; + + desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; + desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ + desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ + desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ + + desc++; + next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; + + desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; + desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ + desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ + desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ + + desc++; + next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; + + desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; + desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ + desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ + desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ + + dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); + + /* Setup DMA descriptor address */ + REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; + + /* Setup request source */ + REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; + + /* Setup DMA channel control/status register */ + REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ + + /* Enable DMA */ + REG_DMAC_DMACR = DMAC_DMACR_DMAE; + + /* DMA doorbell set -- start DMA now ... */ + REG_DMAC_DMADBSR = 1 << dma_chan; + + printk("DMA started. IMR=%08x\n", REG_INTC_IMR); +} + +#endif + +//EXPORT_SYMBOL_NOVERS(jz_dma_table); +EXPORT_SYMBOL(jz_dma_table); +EXPORT_SYMBOL(jz_request_dma); +EXPORT_SYMBOL(jz_free_dma); +EXPORT_SYMBOL(jz_set_dma_src_width); +EXPORT_SYMBOL(jz_set_dma_dest_width); +EXPORT_SYMBOL(jz_set_dma_block_size); +EXPORT_SYMBOL(jz_set_dma_mode); +EXPORT_SYMBOL(set_dma_mode); +EXPORT_SYMBOL(jz_set_oss_dma); +EXPORT_SYMBOL(jz_set_alsa_dma); +EXPORT_SYMBOL(set_dma_addr); +EXPORT_SYMBOL(set_dma_count); +EXPORT_SYMBOL(get_dma_residue); +EXPORT_SYMBOL(enable_dma); +EXPORT_SYMBOL(disable_dma); +EXPORT_SYMBOL(dump_jz_dma_channel); diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/gpio.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/gpio.c new file mode 100644 index 000000000..59e767c60 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/gpio.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * JZ74xx platform GPIO 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define JZ_GPIO_BASE_A (32*0) +#define JZ_GPIO_BASE_B (32*1) +#define JZ_GPIO_BASE_C (32*2) +#define JZ_GPIO_BASE_D (32*3) + +#define JZ_GPIO_NUM_A 32 +#define JZ_GPIO_NUM_B 32 +#define JZ_GPIO_NUM_C 31 +#define JZ_GPIO_NUM_D 28 + +#define JZ_IRQ_GPIO_BASE_A JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_A +#define JZ_IRQ_GPIO_BASE_B JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_B +#define JZ_IRQ_GPIO_BASE_C JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_C +#define JZ_IRQ_GPIO_BASE_D JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_D + +#define JZ_IRQ_GPIO_A(num) (num < JZ_GPIO_NUM_A ? JZ_IRQ_GPIO_BASE_A + num : -EINVAL) +#define JZ_IRQ_GPIO_B(num) (num < JZ_GPIO_NUM_B ? JZ_IRQ_GPIO_BASE_B + num : -EINVAL) +#define JZ_IRQ_GPIO_C(num) (num < JZ_GPIO_NUM_C ? JZ_IRQ_GPIO_BASE_C + num : -EINVAL) +#define JZ_IRQ_GPIO_D(num) (num < JZ_GPIO_NUM_D ? JZ_IRQ_GPIO_BASE_D + num : -EINVAL) + + +#define CHIP_TO_REG(chip, reg) (jz_gpio_base + (((chip)->base) << 3) + reg) +#define CHIP_TO_PIN_REG(chip) CHIP_TO_REG(chip, 0x00) +#define CHIP_TO_DATA_REG(chip) CHIP_TO_REG(chip, 0x10) +#define CHIP_TO_DATA_SET_REG(chip) CHIP_TO_REG(chip, 0x14) +#define CHIP_TO_DATA_CLEAR_REG(chip) CHIP_TO_REG(chip, 0x18) +#define CHIP_TO_PULL_REG(chip) CHIP_TO_REG(chip, 0x30) +#define CHIP_TO_PULL_SET_REG(chip) CHIP_TO_REG(chip, 0x34) +#define CHIP_TO_PULL_CLEAR_REG(chip) CHIP_TO_REG(chip, 0x38) +#define CHIP_TO_DATA_SELECT_REG(chip) CHIP_TO_REG(chip, 0x50) +#define CHIP_TO_DATA_SELECT_SET_REG(chip) CHIP_TO_REG(chip, 0x54) +#define CHIP_TO_DATA_SELECT_CLEAR_REG(chip) CHIP_TO_REG(chip, 0x58) +#define CHIP_TO_DATA_DIRECION_REG(chip) CHIP_TO_REG(chip, 0x60) +#define CHIP_TO_DATA_DIRECTION_SET_REG(chip) CHIP_TO_REG(chip, 0x64) +#define CHIP_TO_DATA_DIRECTION_CLEAR_REG(chip) CHIP_TO_REG(chip, 0x68) + +#define GPIO_TO_REG(gpio, reg) (jz_gpio_base + ((gpio >> 5) << 8) + reg) +#define GPIO_TO_PULL_REG(gpio) GPIO_TO_REG(gpio, 0x30) +#define GPIO_TO_PULL_SET_REG(gpio) GPIO_TO_REG(gpio, 0x34) +#define GPIO_TO_PULL_CLEAR_REG(gpio) GPIO_TO_REG(gpio, 0x38) + +static void __iomem *jz_gpio_base; +static spinlock_t jz_gpio_lock; + +struct jz_gpio_chip { + unsigned int irq_base; + struct gpio_chip gpio_chip; + struct irq_chip irq_chip; +}; + +void jz_gpio_enable_pullup(unsigned gpio) +{ + writel(BIT(gpio & 0x1f), GPIO_TO_PULL_CLEAR_REG(gpio)); +} +EXPORT_SYMBOL_GPL(jz_gpio_enable_pullup); + +void jz_gpio_disable_pullup(unsigned gpio) +{ + writel(BIT(gpio & 0x1f), GPIO_TO_PULL_SET_REG(gpio)); +} +EXPORT_SYMBOL_GPL(jz_gpio_disable_pullup); + +void jz_gpio_set_function(unsigned gpio, unsigned function) +{ +} +EXPORT_SYMBOL_GPL(jz_gpio_set_function); + + +static int jz_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ + return !!(readl(CHIP_TO_PIN_REG(chip)) & BIT(gpio)); +} + +static void jz_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) +{ + uint32_t __iomem *reg = CHIP_TO_DATA_SET_REG(chip) + ((!value) << 2); + writel(BIT(gpio), reg); +} + +static int jz_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) +{ + writel(BIT(gpio), CHIP_TO_DATA_DIRECTION_SET_REG(chip)); + jz_gpio_set_value(chip, gpio, value); + + return 0; +} + +static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + writel(BIT(gpio), CHIP_TO_DATA_DIRECTION_CLEAR_REG(chip)); + + return 0; +} + + +#define IRQ_TO_GPIO(irq) (irq - JZ_IRQ_GPIO(0)) +#define IRQ_TO_BIT(irq) BIT(IRQ_TO_GPIO(irq) & 0x1f) + + +#define IRQ_TO_REG(irq, reg) GPIO_TO_REG(IRQ_TO_GPIO(irq), reg) +#define IRQ_TO_MASK_REG(irq) IRQ_TO_REG(irq, 0x20) +#define IRQ_TO_MASK_SET_REG(irq) IRQ_TO_REG(irq, 0x24) +#define IRQ_TO_MASK_CLEAR_REG(irq) IRQ_TO_REG(irq, 0x28) +#define IRQ_TO_SELECT_REG(irq) IRQ_TO_REG(irq, 0x50) +#define IRQ_TO_SELECT_SET_REG(irq) IRQ_TO_REG(irq, 0x54) +#define IRQ_TO_SELECT_CLEAR_REG(irq) IRQ_TO_REG(irq, 0x58) +#define IRQ_TO_DIRECTION_REG(irq) IRQ_TO_REG(irq, 0x60) +#define IRQ_TO_DIRECTION_SET_REG(irq) IRQ_TO_REG(irq, 0x64) +#define IRQ_TO_DIRECTION_CLEAR_REG(irq) IRQ_TO_REG(irq, 0x68) +#define IRQ_TO_TRIGGER_REG(irq) IRQ_TO_REG(irq, 0x70) +#define IRQ_TO_TRIGGER_SET_REG(irq) IRQ_TO_REG(irq, 0x74) +#define IRQ_TO_TRIGGER_CLEAR_REG(irq) IRQ_TO_REG(irq, 0x78) +#define IRQ_TO_FLAG_REG(irq) IRQ_TO_REG(irq, 0x80) +#define IRQ_TO_FLAG_CLEAR_REG(irq) IRQ_TO_REG(irq, 0x14) + + +static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) +{ + uint32_t flag; + unsigned int gpio_irq; + unsigned int gpio_bank; + + gpio_bank = IRQ_GPIO0 - irq; + + flag = readl(jz_gpio_base + (gpio_bank << 8) + 0x80); + + gpio_irq = ffs(flag); + + gpio_irq += (gpio_bank << 5) + JZ_IRQ_GPIO(0) - 1; + + generic_handle_irq(gpio_irq); +}; + +/* TODO: Check if function is gpio */ +static unsigned int jz_gpio_irq_startup(unsigned int irq) +{ + writel(IRQ_TO_BIT(irq), IRQ_TO_SELECT_SET_REG(irq)); + spin_lock(&jz_gpio_lock); + writel(IRQ_TO_BIT(irq), IRQ_TO_MASK_CLEAR_REG(irq)); + spin_unlock(&jz_gpio_lock); + return 0; +} + +static void jz_gpio_irq_shutdown(unsigned int irq) +{ + spin_lock(&jz_gpio_lock); + writel(IRQ_TO_BIT(irq), IRQ_TO_MASK_SET_REG(irq)); + spin_unlock(&jz_gpio_lock); + /* Set direction to input */ + writel(IRQ_TO_BIT(irq), IRQ_TO_DIRECTION_CLEAR_REG(irq)); + writel(IRQ_TO_BIT(irq), IRQ_TO_SELECT_CLEAR_REG(irq)); +} + +static void jz_gpio_irq_mask(unsigned int irq) +{ + writel(IRQ_TO_BIT(irq), IRQ_TO_MASK_SET_REG(irq)); +}; + +static void jz_gpio_irq_unmask(unsigned int irq) +{ + writel(IRQ_TO_BIT(irq), IRQ_TO_MASK_CLEAR_REG(irq)); +}; + +static void jz_gpio_irq_ack(unsigned int irq) +{ + writel(IRQ_TO_BIT(irq), IRQ_TO_FLAG_CLEAR_REG(irq)); +}; + +static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + uint32_t mask; + spin_lock(&jz_gpio_lock); + + mask = readl(IRQ_TO_MASK_REG(irq)); + + writel(IRQ_TO_BIT(irq), IRQ_TO_MASK_CLEAR_REG(irq)); + + switch(flow_type) { + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_BOTH: + writel(IRQ_TO_BIT(irq), IRQ_TO_DIRECTION_SET_REG(irq)); + writel(IRQ_TO_BIT(irq), IRQ_TO_TRIGGER_SET_REG(irq)); + break; + case IRQ_TYPE_EDGE_FALLING: + writel(IRQ_TO_BIT(irq), IRQ_TO_DIRECTION_CLEAR_REG(irq)); + writel(IRQ_TO_BIT(irq), IRQ_TO_TRIGGER_SET_REG(irq)); + break; + case IRQ_TYPE_LEVEL_HIGH: + writel(IRQ_TO_BIT(irq), IRQ_TO_DIRECTION_SET_REG(irq)); + writel(IRQ_TO_BIT(irq), IRQ_TO_TRIGGER_CLEAR_REG(irq)); + break; + case IRQ_TYPE_LEVEL_LOW: + writel(IRQ_TO_BIT(irq), IRQ_TO_DIRECTION_CLEAR_REG(irq)); + writel(IRQ_TO_BIT(irq), IRQ_TO_TRIGGER_CLEAR_REG(irq)); + break; + default: + return -EINVAL; + } + + writel(mask, IRQ_TO_MASK_SET_REG(irq)); + + spin_unlock(&jz_gpio_lock); + + return 0; +} + +int gpio_to_irq(unsigned gpio) +{ + return JZ_IRQ_GPIO(0) + gpio; +} +EXPORT_SYMBOL_GPL(gpio_to_irq); + +int irq_to_gpio(unsigned gpio) +{ + return IRQ_TO_GPIO(gpio); +} +EXPORT_SYMBOL_GPL(irq_to_gpio); + +#define JZ_GPIO_CHIP(_bank) { \ + .irq_base = JZ_IRQ_GPIO_BASE_ ## _bank, \ + .gpio_chip = { \ + .label = "Bank " # _bank, \ + .owner = THIS_MODULE, \ + .set = jz_gpio_set_value, \ + .get = jz_gpio_get_value, \ + .direction_output = jz_gpio_direction_output, \ + .direction_input = jz_gpio_direction_input, \ + .base = JZ_GPIO_BASE_ ## _bank, \ + .ngpio = JZ_GPIO_NUM_ ## _bank, \ + }, \ + .irq_chip = { \ + .name = "GPIO Bank " # _bank, \ + .mask = jz_gpio_irq_mask, \ + .unmask = jz_gpio_irq_unmask, \ + .ack = jz_gpio_irq_ack, \ + .startup = jz_gpio_irq_startup, \ + .shutdown = jz_gpio_irq_shutdown, \ + .set_type = jz_gpio_irq_set_type, \ + }, \ +} + +static struct jz_gpio_chip jz_gpio_chips[] = { + JZ_GPIO_CHIP(A), + JZ_GPIO_CHIP(B), + JZ_GPIO_CHIP(C), + JZ_GPIO_CHIP(D), +}; + +__init int jz_gpiolib_init(void) +{ + struct jz_gpio_chip *chip = jz_gpio_chips; + int i, irq; + + jz_gpio_base = ioremap(0x10010000, 0x400); + + for (i = 0; i < ARRAY_SIZE(jz_gpio_chips); ++i, ++chip) { + gpiochip_add(&chip->gpio_chip); + enable_irq(JZ_IRQ_INTC_GPIO(i)); + set_irq_chained_handler(JZ_IRQ_INTC_GPIO(i), jz_gpio_irq_demux_handler); + for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; + ++irq) + set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq); + } + + printk("JZ GPIO initalized\n"); + + return 0; +} diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/i2c.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/i2c.c new file mode 100644 index 000000000..3080fdfa8 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/i2c.c @@ -0,0 +1,273 @@ +/* + * linux/arch/mips/jz4740/i2c.c + * + * Jz4740 I2C routines. + * + * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. + * Author: + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include + +#include + +/* I2C protocol */ +#define I2C_READ 1 +#define I2C_WRITE 0 + +#define TIMEOUT 1000 + +/* + * I2C bus protocol basic routines + */ +static int i2c_put_data(unsigned char data) +{ + unsigned int timeout = TIMEOUT*10; + + __i2c_write(data); + __i2c_set_drf(); + while (__i2c_check_drf() != 0); + while (!__i2c_transmit_ended()); + while (!__i2c_received_ack() && timeout) + timeout--; + + if (timeout) + return 0; + else + return -ETIMEDOUT; +} + +#ifdef CONFIG_JZ_TPANEL_ATA2508 +static int i2c_put_data_nack(unsigned char data) +{ + unsigned int timeout = TIMEOUT*10; + + __i2c_write(data); + __i2c_set_drf(); + while (__i2c_check_drf() != 0); + while (!__i2c_transmit_ended()); + while (timeout--); + return 0; +} +#endif + +static int i2c_get_data(unsigned char *data, int ack) +{ + int timeout = TIMEOUT*10; + + if (!ack) + __i2c_send_nack(); + else + __i2c_send_ack(); + + while (__i2c_check_drf() == 0 && timeout) + timeout--; + + if (timeout) { + if (!ack) + __i2c_send_stop(); + *data = __i2c_read(); + __i2c_clear_drf(); + return 0; + } else + return -ETIMEDOUT; +} + +/* + * I2C interface + */ +void i2c_open(void) +{ + __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ + __i2c_enable(); +} + +void i2c_close(void) +{ + udelay(300); /* wait for STOP goes over. */ + __i2c_disable(); +} + +void i2c_setclk(unsigned int i2cclk) +{ + __i2c_set_clk(jz_clocks.extalclk, i2cclk); +} + +int i2c_lseek(unsigned char device, unsigned char offset) +{ + __i2c_send_nack(); /* Master does not send ACK, slave sends it */ + __i2c_send_start(); + if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) + goto device_err; + if (i2c_put_data(offset) < 0) + goto address_err; + return 0; + device_err: + printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); + __i2c_send_stop(); + return -ENODEV; + address_err: + printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); + __i2c_send_stop(); + return -EREMOTEIO; +} + +int i2c_read(unsigned char device, unsigned char *buf, + unsigned char address, int count) +{ + int cnt = count; + int timeout = 5; + +L_try_again: + + if (timeout < 0) + goto L_timeout; + + __i2c_send_nack(); /* Master does not send ACK, slave sends it */ + __i2c_send_start(); + if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) + goto device_werr; + if (i2c_put_data(address) < 0) + goto address_err; + + __i2c_send_start(); + if (i2c_put_data( (device << 1) | I2C_READ ) < 0) + goto device_rerr; + __i2c_send_ack(); /* Master sends ACK for continue reading */ + while (cnt) { + if (cnt == 1) { + if (i2c_get_data(buf, 0) < 0) + break; + } else { + if (i2c_get_data(buf, 1) < 0) + break; + } + cnt--; + buf++; + } + + __i2c_send_stop(); + return count - cnt; + device_rerr: + device_werr: + address_err: + timeout --; + __i2c_send_stop(); + goto L_try_again; + +L_timeout: + __i2c_send_stop(); + printk("Read I2C device 0x%2x failed.\n", device); + return -ENODEV; +} + +int i2c_write(unsigned char device, unsigned char *buf, + unsigned char address, int count) +{ + int cnt = count; + int cnt_in_pg; + int timeout = 5; + unsigned char *tmpbuf; + unsigned char tmpaddr; + + __i2c_send_nack(); /* Master does not send ACK, slave sends it */ + + W_try_again: + if (timeout < 0) + goto W_timeout; + + cnt = count; + tmpbuf = (unsigned char *)buf; + tmpaddr = address; + + start_write_page: + cnt_in_pg = 0; + __i2c_send_start(); + if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) + goto device_err; +#ifdef CONFIG_JZ_TPANEL_ATA2508 + if (address == 0xff) { + if (i2c_put_data_nack(tmpaddr) < 0) + goto address_err; + while (cnt) { + if (++cnt_in_pg > 8) { + __i2c_send_stop(); + mdelay(1); + tmpaddr += 8; + goto start_write_page; + } + if (i2c_put_data_nack(*tmpbuf) < 0) + break; + cnt--; + tmpbuf++; + } + } + else { + + if (i2c_put_data(tmpaddr) < 0) + goto address_err; + while (cnt) { + if (++cnt_in_pg > 8) { + __i2c_send_stop(); + mdelay(1); + tmpaddr += 8; + goto start_write_page; + } + if (i2c_put_data(*tmpbuf) < 0) + break; + cnt--; + tmpbuf++; + } + } +#else + if (i2c_put_data(tmpaddr) < 0) + goto address_err; + while (cnt) { + if (++cnt_in_pg > 8) { + __i2c_send_stop(); + mdelay(1); + tmpaddr += 8; + goto start_write_page; + } + if (i2c_put_data(*tmpbuf) < 0) + break; + cnt--; + tmpbuf++; + } +#endif + __i2c_send_stop(); + return count - cnt; + device_err: + address_err: + timeout--; + __i2c_send_stop(); + goto W_try_again; + + W_timeout: + printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); + __i2c_send_stop(); + return -ENODEV; +} + +EXPORT_SYMBOL(i2c_open); +EXPORT_SYMBOL(i2c_close); +EXPORT_SYMBOL(i2c_setclk); +EXPORT_SYMBOL(i2c_read); +EXPORT_SYMBOL(i2c_write); diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/irq.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/irq.c new file mode 100644 index 000000000..b4ccf2a79 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/irq.c @@ -0,0 +1,150 @@ +/* + * linux/arch/mips/jz4740/irq.c + * + * JZ4740 interrupt routines. + * + * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. + * Author: + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static void __iomem *jz_intc_base; + +#define JZ_REG_BASE_INTC 0x10001000 + +#define JZ_REG_INTC_STATUS 0x00 +#define JZ_REG_INTC_MASK 0x04 +#define JZ_REG_INTC_SET_MASK 0x08 +#define JZ_REG_INTC_CLEAR_MASK 0x0c +#define JZ_REG_INTC_PENDING 0x10 + +/* + * INTC irq type + */ + +static void intc_irq_unmask(unsigned int irq) +{ + writel(BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK); +} + +static void intc_irq_mask(unsigned int irq) +{ + writel(BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK); +} + +static void intc_irq_ack(unsigned int irq) +{ + writel(BIT(irq), jz_intc_base + JZ_REG_INTC_PENDING); +} + +static void intc_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + intc_irq_unmask(irq); + } +} + +static struct irq_chip intc_irq_type = { + .name = "INTC", + .mask = intc_irq_mask, + .unmask = intc_irq_unmask, + .ack = intc_irq_ack, + .end = intc_irq_end, +}; + +/* + * DMA irq type + */ + +static void enable_dma_irq(unsigned int irq) +{ + __intc_unmask_irq(IRQ_DMAC); + __dmac_channel_enable_irq(irq - IRQ_DMA_0); +} + +static void disable_dma_irq(unsigned int irq) +{ + __dmac_channel_disable_irq(irq - IRQ_DMA_0); +} + +static void mask_and_ack_dma_irq(unsigned int irq) +{ + __intc_ack_irq(IRQ_DMAC); + __dmac_channel_disable_irq(irq - IRQ_DMA_0); +} + +static void end_dma_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + enable_dma_irq(irq); + } +} + +static struct irq_chip dma_irq_type = { + .name = "DMA", + .unmask = enable_dma_irq, + .mask = disable_dma_irq, + .ack = mask_and_ack_dma_irq, + .end = end_dma_irq, +}; + +//---------------------------------------------------------------------- + +void __init arch_init_irq(void) +{ + int i; + + clear_c0_status(0xff04); /* clear ERL */ + set_c0_status(0x0400); /* set IP2 */ + + jz_intc_base = ioremap(JZ_REG_BASE_INTC, 0x14); + + for (i = 0; i < 32; i++) { + intc_irq_mask(i); + set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq); + } + + + /* Set up DMAC irq + */ + for (i = 0; i < NUM_DMA; i++) { + disable_dma_irq(IRQ_DMA_0 + i); + set_irq_chip_and_handler(IRQ_DMA_0 + i, &dma_irq_type, handle_level_irq); + } + +} + +asmlinkage void plat_irq_dispatch(void) +{ + uint32_t irq_reg; + + irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); + + if (irq_reg) + do_IRQ(ffs(irq_reg) - 1); +} diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/platform.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/platform.c new file mode 100644 index 000000000..a02aec138 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/platform.c @@ -0,0 +1,340 @@ +/* + * Platform device support for Jz4740 SoC. + * + * Copyright 2007, + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* OHCI (USB full speed host controller) */ +static struct resource jz_usb_ohci_resources[] = { + [0] = { + .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap + .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_UHC, + .end = IRQ_UHC, + .flags = IORESOURCE_IRQ, + }, +}; + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = ~(u32)0; + +static struct platform_device jz_usb_ohci_device = { + .name = "jz-ohci", + .id = 0, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), + .resource = jz_usb_ohci_resources, +}; + +/*** LCD controller ***/ +static struct resource jz_lcd_resources[] = { + [0] = { + .start = CPHYSADDR(LCD_BASE), + .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_LCD, + .end = IRQ_LCD, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 jz_lcd_dmamask = ~(u32)0; + +static struct platform_device jz_lcd_device = { + .name = "jz-lcd", + .id = 0, + .dev = { + .dma_mask = &jz_lcd_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(jz_lcd_resources), + .resource = jz_lcd_resources, +}; + +/* UDC (USB gadget controller) */ +static struct resource jz_usb_gdt_resources[] = { + [0] = { + .start = CPHYSADDR(UDC_BASE), + .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_UDC, + .end = IRQ_UDC, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 udc_dmamask = ~(u32)0; + +static struct platform_device jz_usb_gdt_device = { + .name = "jz-udc", + .id = 0, + .dev = { + .dma_mask = &udc_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), + .resource = jz_usb_gdt_resources, +}; + +/** MMC/SD controller **/ +static struct resource jz_mmc_resources[] = { + [0] = { + .start = CPHYSADDR(MSC_BASE), + .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_MSC, + .end = IRQ_MSC, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 jz_mmc_dmamask = ~(u32)0; + +static struct platform_device jz_mmc_device = { + .name = "jz-mmc", + .id = 0, + .dev = { + .dma_mask = &jz_mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(jz_mmc_resources), + .resource = jz_mmc_resources, +}; + +/** I2C controller **/ +static struct resource jz_i2c_resources[] = { + [0] = { + .start = CPHYSADDR(I2C_BASE), + .end = CPHYSADDR(I2C_BASE) + 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_I2C, + .end = IRQ_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 jz_i2c_dmamask = ~(u32)0; + +static struct platform_device jz_i2c_device = { + .name = "jz_i2c", + .id = 0, + .dev = { + .dma_mask = &jz_i2c_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(jz_i2c_resources), + .resource = jz_i2c_resources, +}; + +static struct resource jz_nand_resources[] = { + [0] = { + .start = CPHYSADDR(EMC_BASE), + .end = CPHYSADDR(EMC_BASE) + 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct nand_ecclayout qi_lb60_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 = 0, + .length = 6}, + {.offset = 42, + .length = 22}} +}; + +static struct mtd_partition qi_lb60_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 = 20 * 0x100000, + }, + { .name = "NAND DATA partition", + .offset = 100 * 0x100000, + .size = 20 * 0x100000, + }, +}; + +static struct jz_nand_platform_data jz_nand_platform_data = { + .num_partitions = ARRAY_SIZE(qi_lb60_partitions), + .partitions = qi_lb60_partitions, + .ecc_layout = &qi_lb60_ecclayout, + .busy_gpio = 94, +}; + +static struct platform_device jz_nand_device = { + .name = "jz4740-nand", + .num_resources = ARRAY_SIZE(jz_nand_resources), + .resource = jz_nand_resources, + .dev = { + .platform_data = &jz_nand_platform_data, + } +}; +#define KEEP_UART_ALIVE + +#define KEY_QI_QI KEY_F9 +#define KEY_QI_UPBIG KEY_F10 +#define KEY_QI_DOWNBIG KEY_F11 +#define KEY_QI_UPRED KEY_F12 +#define KEY_QI_VOLUP KEY_F13 +#define KEY_QI_VOLDOWN KEY_F14 + +static const uint32_t qi_lb60_keymap[] = { + KEY(0, 0, KEY_F1), /* S2 */ + KEY(0, 1, KEY_F2), /* S3 */ + KEY(0, 2, KEY_F3), /* S4 */ + KEY(0, 3, KEY_F4), /* S5 */ + KEY(0, 4, KEY_F5), /* S6 */ + KEY(0, 5, KEY_F6), /* S7 */ + KEY(0, 6, KEY_F7), /* S8 */ + + KEY(1, 0, KEY_Q), /* S10 */ + KEY(1, 1, KEY_W), /* S11 */ + KEY(1, 2, KEY_E), /* S12 */ + KEY(1, 3, KEY_R), /* S13 */ + KEY(1, 4, KEY_T), /* S14 */ + KEY(1, 5, KEY_Y), /* S15 */ + KEY(1, 6, KEY_U), /* S16 */ + KEY(1, 7, KEY_I), /* S17 */ + KEY(2, 0, KEY_A), /* S18 */ + KEY(2, 1, KEY_S), /* S19 */ + KEY(2, 2, KEY_D), /* S20 */ + KEY(2, 3, KEY_F), /* S21 */ + KEY(2, 4, KEY_G), /* S22 */ + KEY(2, 5, KEY_H), /* S23 */ + KEY(2, 6, KEY_J), /* S24 */ + KEY(2, 7, KEY_K), /* S25 */ + KEY(3, 0, KEY_ESC), /* S26 */ + KEY(3, 1, KEY_Z), /* S27 */ + KEY(3, 2, KEY_X), /* S28 */ + KEY(3, 3, KEY_C), /* S29 */ + KEY(3, 4, KEY_V), /* S30 */ + KEY(3, 5, KEY_B), /* S31 */ + KEY(3, 6, KEY_N), /* S32 */ + KEY(3, 7, KEY_M), /* S33 */ + KEY(4, 0, KEY_TAB), /* S34 */ + KEY(4, 1, KEY_QI_DOWNBIG), /* S35 */ + KEY(4, 2, KEY_BACKSLASH), /* S36 */ + KEY(4, 3, KEY_APOSTROPHE), /* S37 */ + KEY(4, 4, KEY_COMMA), /* S38 */ + KEY(4, 5, KEY_DOT), /* S39 */ + KEY(4, 6, KEY_SLASH), /* S40 */ + KEY(4, 7, KEY_UP), /* S41 */ + KEY(5, 0, KEY_O), /* S42 */ + KEY(5, 1, KEY_L), /* S43 */ + KEY(5, 2, KEY_EQUAL), /* S44 */ + KEY(5, 3, KEY_QI_UPRED), /* S45 */ + KEY(5, 4, KEY_SPACE), /* S46 */ + KEY(5, 5, KEY_QI_QI), /* S47 */ + KEY(5, 6, KEY_LEFTCTRL), /* S48 */ + KEY(5, 7, KEY_LEFT), /* S49 */ + KEY(6, 0, KEY_F8), /* S50 */ + KEY(6, 1, KEY_P), /* S51 */ + KEY(6, 2, KEY_BACKSPACE),/* S52 */ + KEY(6, 3, KEY_ENTER), /* S53 */ + KEY(6, 4, KEY_QI_VOLUP), /* S54 */ + KEY(6, 5, KEY_QI_VOLDOWN), /* S55 */ + KEY(6, 6, KEY_DOWN), /* S56 */ + KEY(6, 7, KEY_RIGHT), /* S57 */ + +#ifndef KEEP_UART_ALIVE + KEY(7, 0, KEY_QI_UPBIG), /* S58 */ + KEY(7, 1, KEY_LEFTALT), /* S59 */ + KEY(7, 2, KEY_FN), /* S60 */ +#endif +}; + +static const struct matrix_keymap_data qi_lb60_keymap_data = { + .keymap = qi_lb60_keymap, + .keymap_size = ARRAY_SIZE(qi_lb60_keymap), +}; + +static const unsigned int qi_lb60_keypad_cols[] = { + 74, 75, 76, 77, 78, 79, 80, 81, +}; + +static const unsigned int qi_lb60_keypad_rows[] = { + 114, 115, 116, 117, 118, 119, 120, +#ifndef KEEP_UART_ALIVE + 122, +#endif +}; + +static struct matrix_keypad_platform_data qi_lb60_pdata = { + .keymap_data = &qi_lb60_keymap_data, + .col_gpios = qi_lb60_keypad_cols, + .row_gpios = qi_lb60_keypad_rows, + .num_col_gpios = ARRAY_SIZE(qi_lb60_keypad_cols), + .num_row_gpios = ARRAY_SIZE(qi_lb60_keypad_rows), + .col_scan_delay_us = 10, + .debounce_ms = 10, + .wakeup = 1, + .active_low = 1, +}; + +static struct platform_device qi_lb60_keypad = { + .name = "matrix-keypad", + .id = -1, + .dev = { + .platform_data = &qi_lb60_pdata, + }, +}; + +/* All */ +static struct platform_device *jz_platform_devices[] __initdata = { + &jz_usb_ohci_device, + &jz_lcd_device, + &jz_usb_gdt_device, + &jz_mmc_device, + &jz_nand_device, + &jz_i2c_device, + &qi_lb60_keypad, +}; + +static int __init jz_platform_init(void) +{ + return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); +} + +arch_initcall(jz_platform_init); diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/pm.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/pm.c new file mode 100644 index 000000000..c90709147 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/pm.c @@ -0,0 +1,410 @@ +/* + * linux/arch/mips/jz4740/common/pm.c + * + * JZ4740 Power Management Routines + * + * Copyright (C) 2006 Ingenic Semiconductor Inc. + * Author: + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG +//#define DEBUG +#ifdef DEBUG +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif + +#define GPIO_WAKEUP 125 /* set SW7(GPIO 125) as WAKEUP key */ + +/* + * __gpio_as_sleep set all pins to pull-disable, and set all pins as input + * except sdram, nand flash pins and the pins which can be used as CS1_N + * to CS4_N for chip select. + */ +#define __gpio_as_sleep() \ +do { \ + REG_GPIO_PXFUNC(1) = ~0x9ff9ffff; \ + REG_GPIO_PXSELC(1) = ~0x9ff9ffff; \ + REG_GPIO_PXDIRC(1) = ~0x9ff9ffff; \ + REG_GPIO_PXPES(1) = 0xffffffff; \ + REG_GPIO_PXFUNC(2) = ~0x37000000; \ + REG_GPIO_PXSELC(2) = ~0x37000000; \ + REG_GPIO_PXDIRC(2) = ~0x37000000; \ + REG_GPIO_PXPES(2) = 0xffffffff; \ + REG_GPIO_PXFUNC(3) = 0xffffffff; \ + REG_GPIO_PXSELC(3) = 0xffffffff; \ + REG_GPIO_PXDIRC(3) = 0xffffffff; \ + REG_GPIO_PXPES(3) = 0xffffffff; \ +} while (0) + +static int jz_pm_do_hibernate(void) +{ + + /* Mask all interrupts */ + REG_INTC_IMSR = 0xffffffff; + + /* + * RTC Wakeup or 1Hz interrupt can be enabled or disabled + * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). + */ + + /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ + while (!(REG_RTC_RCR & RTC_RCR_WRDY)); + REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); + + /* Set reset pin low-level assertion time after wakeup: must > 60ms */ + while (!(REG_RTC_RCR & RTC_RCR_WRDY)); + REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ + + /* Scratch pad register to be reserved */ + while (!(REG_RTC_RCR & RTC_RCR_WRDY)); + REG_RTC_HSPR = 0x12345678; + + /* clear wakeup status register */ + while (!(REG_RTC_RCR & RTC_RCR_WRDY)); + REG_RTC_HWRSR = 0x0; + + /* Put CPU to power down mode */ + while (!(REG_RTC_RCR & RTC_RCR_WRDY)); + REG_RTC_HCR = RTC_HCR_PD; + + while (!(REG_RTC_RCR & RTC_RCR_WRDY)); + while(1); + + /* We can't get here */ + return 0; +} + +/* NOTES: + * 1: Pins that are floated (NC) should be set as input and pull-enable. + * 2: Pins that are pull-up or pull-down by outside should be set as input + * and pull-disable. + * 3: Pins that are connected to a chip except sdram and nand flash + * should be set as input and pull-disable, too. + */ +static void jz_board_do_sleep(unsigned long *ptr) +{ + unsigned char i; + + /* Print messages of GPIO registers for debug */ + for(i=0;i<4;i++) { + dprintk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ + REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ + REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); + } + + /* Save GPIO registers */ + for(i = 1; i < 4; i++) { + *ptr++ = REG_GPIO_PXFUN(i); + *ptr++ = REG_GPIO_PXSEL(i); + *ptr++ = REG_GPIO_PXDIR(i); + *ptr++ = REG_GPIO_PXPE(i); + *ptr++ = REG_GPIO_PXIM(i); + *ptr++ = REG_GPIO_PXDAT(i); + *ptr++ = REG_GPIO_PXTRG(i); + } + + /* + * Set all pins to pull-disable, and set all pins as input except + * sdram, nand flash pins and the pins which can be used as CS1_N + * to CS4_N for chip select. + */ + __gpio_as_sleep(); + + /* + * Set proper status for GPB25 to GPB28 which can be used as CS1_N to CS4_N. + * Keep the pins' function used for chip select(CS) here according to your + * system to avoid chip select crashing with sdram when resuming from sleep mode. + */ + +#if defined(CONFIG_JZ4740_PAVO) + /* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */ + + /* GPB26/CS2_N is connected to nand flash, needn't be changed. */ + + /* GPB27/CS3_N is used as EXT_INT for CS8900 on debug board, it should be set as input.*/ + __gpio_as_input(32+27); + + /* GPB28/CS4_N is used as cs8900's chip select, shouldn't be changed. */ +#endif + + /* + * Enable pull for NC pins here according to your system + */ + +#if defined(CONFIG_JZ4740_PAVO) + /* GPB30-27 <-> J1: WE_N RD_N CS4_N EXT_INT */ + for(i=27;i<31;i++) { + __gpio_enable_pull(32+i); + } + + /* GPC27<-> WAIT_N */ + __gpio_enable_pull(32*2+27); + + /* GPD16<->SD_WP; GPD13-10<->MSC_D0-3; GPD9<->MSC_CMD; GPD8<->MSC_CLK */ + __gpio_enable_pull(32*3+16); + for(i=8;i<14;i++) { + __gpio_enable_pull(32*3+i); + } +#endif + + /* + * If you must set some GPIOs as output to high level or low level, + * you can set them here, using: + * __gpio_as_output(n); + * __gpio_set_pin(n); or __gpio_clear_pin(n); + */ + +#if defined(CONFIG_JZ4740_PAVO) + /* GPD16 which is used as AMPEN_N should be set to high to disable audio amplifier */ + __gpio_set_pin(32*3+4); +#endif + +#ifdef DEBUG + /* Keep uart0 function for printing debug message */ + __gpio_as_uart0(); + + /* Print messages of GPIO registers for debug */ + for(i=0;i<4;i++) { + dprintk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ + REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ + REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); + } +#endif +} + +static void jz_board_do_resume(unsigned long *ptr) +{ + unsigned char i; + + /* Restore GPIO registers */ + for(i = 1; i < 4; i++) { + REG_GPIO_PXFUNS(i) = *ptr; + REG_GPIO_PXFUNC(i) = ~(*ptr++); + + REG_GPIO_PXSELS(i) = *ptr; + REG_GPIO_PXSELC(i) = ~(*ptr++); + + REG_GPIO_PXDIRS(i) = *ptr; + REG_GPIO_PXDIRC(i) = ~(*ptr++); + + REG_GPIO_PXPES(i) = *ptr; + REG_GPIO_PXPEC(i) = ~(*ptr++); + + REG_GPIO_PXIMS(i)=*ptr; + REG_GPIO_PXIMC(i)=~(*ptr++); + + REG_GPIO_PXDATS(i)=*ptr; + REG_GPIO_PXDATC(i)=~(*ptr++); + + REG_GPIO_PXTRGS(i)=*ptr; + REG_GPIO_PXTRGC(i)=~(*ptr++); + } + + /* Print messages of GPIO registers for debug */ + for(i=0;i<4;i++) { + dprintk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ + REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ + REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); + } +} + + + +static int jz_pm_do_sleep(void) +{ + unsigned long delta; + unsigned long nfcsr = REG_EMC_NFCSR; + unsigned long scr = REG_CPM_SCR; + unsigned long imr = REG_INTC_IMR; + unsigned long sadc = REG_SADC_ENA; + unsigned long sleep_gpio_save[7*3]; + + /* Preserve current time */ + delta = xtime.tv_sec - REG_RTC_RSR; + + /* Disable nand flash */ + REG_EMC_NFCSR = ~0xff; + + /* stop sadc */ + REG_SADC_ENA &= ~0x7; + while((REG_SADC_ENA & 0x7) != 0); + udelay(100); + + /*stop udc and usb*/ + REG_CPM_SCR &= ~( 1<<6 | 1<<7); + REG_CPM_SCR |= 0<<6 | 1<<7; + + /* Sleep on-board modules */ + jz_board_do_sleep(sleep_gpio_save); + + /* Mask all interrupts */ + REG_INTC_IMSR = 0xffffffff; + + /* Just allow following interrupts to wakeup the system. + * Note: modify this according to your system. + */ + + /* enable RTC alarm */ + __intc_unmask_irq(IRQ_RTC); +#if 0 + /* make system wake up after n seconds by RTC alarm */ + unsigned int v, n; + n = 10; + while (!__rtc_write_ready()); + __rtc_enable_alarm(); + while (!__rtc_write_ready()); + __rtc_enable_alarm_irq(); + while (!__rtc_write_ready()); + v = __rtc_get_second(); + while (!__rtc_write_ready()); + __rtc_set_alarm_second(v+n); +#endif + + /* WAKEUP key */ + __gpio_as_irq_rise_edge(GPIO_WAKEUP); + __gpio_unmask_irq(GPIO_WAKEUP); + __intc_unmask_irq(IRQ_GPIO3); /* IRQ_GPIOn depends on GPIO_WAKEUP */ + + /* Enter SLEEP mode */ + REG_CPM_LCR &= ~CPM_LCR_LPM_MASK; + REG_CPM_LCR |= CPM_LCR_LPM_SLEEP; + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); + + /* Restore to IDLE mode */ + REG_CPM_LCR &= ~CPM_LCR_LPM_MASK; + REG_CPM_LCR |= CPM_LCR_LPM_IDLE; + + /* Restore nand flash control register */ + REG_EMC_NFCSR = nfcsr; + + /* Restore interrupts */ + REG_INTC_IMSR = imr; + REG_INTC_IMCR = ~imr; + + /* Restore sadc */ + REG_SADC_ENA = sadc; + + /* Resume on-board modules */ + jz_board_do_resume(sleep_gpio_save); + + /* Restore sleep control register */ + REG_CPM_SCR = scr; + + /* Restore current time */ + xtime.tv_sec = REG_RTC_RSR + delta; + + return 0; +} + +/* Put CPU to HIBERNATE mode */ +int jz_pm_hibernate(void) +{ + printk("Put CPU into hibernate mode.\n"); + return jz_pm_do_hibernate(); +} + +#ifndef CONFIG_JZ_POWEROFF +static irqreturn_t pm_irq_handler (int irq, void *dev_id) +{ + return IRQ_HANDLED; +} +#endif + +/* Put CPU to SLEEP mode */ +int jz_pm_sleep(void) +{ + int retval; + +#ifndef CONFIG_JZ_POWEROFF + if ((retval = request_irq (IRQ_GPIO_0 + GPIO_WAKEUP, pm_irq_handler, IRQF_DISABLED, + "PM", NULL))) { + printk ("PM could not get IRQ for GPIO_WAKEUP\n"); + return retval; + } +#endif + printk("Put CPU into sleep mode.\n"); + retval = jz_pm_do_sleep(); + +#ifndef CONFIG_JZ_POWEROFF + free_irq (IRQ_GPIO_0 + GPIO_WAKEUP, NULL); +#endif + + return retval; +} + + +/* + * valid states, only support standby(sleep) and mem(hibernate) + */ +static int jz_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + default: + return 0; + } +} + +/* + * Jz CPU enter save power mode + */ +static int jz_pm_enter(suspend_state_t state) +{ + if (state == PM_SUSPEND_STANDBY) + jz_pm_sleep(); + else + jz_pm_hibernate(); + return 0; +} + + +static struct platform_suspend_ops jz_pm_ops = { + .valid = jz_pm_valid, + .enter = jz_pm_enter, +}; + + +/* + * Initialize power interface + */ +int __init jz_pm_init(void) +{ + printk("Power Management for JZ\n"); + + suspend_set_ops(&jz_pm_ops); + return 0; + +} + +//module_init(jz_pm_init); + diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c new file mode 100644 index 000000000..e9c5df3f6 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c @@ -0,0 +1,873 @@ +/* + * linux/arch/mips/jz4740/proc.c + * + * /proc/jz/ procfs for jz4740 on-chip modules. + * + * Copyright (C) 2006 Ingenic Semiconductor Inc. + * Author: + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG 1 +#undef DEBUG + + +struct proc_dir_entry *proc_jz_root; + + +/* + * EMC Modules + */ +static int emc_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); + len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); + len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); + len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); + len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); + return len; +} + +/* + * Power Manager Module + */ +static int pmc_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + unsigned long lcr = REG_CPM_LCR; + unsigned long clkgr = REG_CPM_CLKGR; + + len += sprintf (page+len, "Low Power Mode : %s\n", + ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? + "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? + "SLEEP" : "HIBERNATE")); + len += sprintf (page+len, "Doze Mode : %s\n", + (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); + if (lcr & CPM_LCR_DOZE_ON) + len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); + len += sprintf (page+len, "IPU : %s\n", + (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); + len += sprintf (page+len, "DMAC : %s\n", + (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); + len += sprintf (page+len, "UHC : %s\n", + (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); + len += sprintf (page+len, "UDC : %s\n", + (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); + len += sprintf (page+len, "LCD : %s\n", + (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); + len += sprintf (page+len, "CIM : %s\n", + (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); + len += sprintf (page+len, "SADC : %s\n", + (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); + len += sprintf (page+len, "MSC : %s\n", + (clkgr & CPM_CLKGR_MSC) ? "stopped" : "running"); + len += sprintf (page+len, "AIC1 : %s\n", + (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); + len += sprintf (page+len, "AIC2 : %s\n", + (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); + len += sprintf (page+len, "SSI : %s\n", + (clkgr & CPM_CLKGR_SSI) ? "stopped" : "running"); + len += sprintf (page+len, "I2C : %s\n", + (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); + len += sprintf (page+len, "RTC : %s\n", + (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); + len += sprintf (page+len, "TCU : %s\n", + (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); + len += sprintf (page+len, "UART1 : %s\n", + (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); + len += sprintf (page+len, "UART0 : %s\n", + (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); + return len; +} + +static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) +{ + REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); + return count; +} + +/* + * Clock Generation Module + */ +#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 +#define TO_KHZ(x) (x/1000),(x%1000)/10 + +static int cgm_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ + unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ + unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + unsigned int od[4] = {1, 2, 2, 4}; + + len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); + len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); + len += sprintf (page+len, "PLL : %s\n", + (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); + len += sprintf (page+len, "m:n:o : %d:%d:%d\n", + __cpm_get_pllm() + 2, + __cpm_get_plln() + 2, + od[__cpm_get_pllod()] + ); + len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", + div[__cpm_get_cdiv()], + div[__cpm_get_hdiv()], + div[__cpm_get_mdiv()], + div[__cpm_get_pdiv()] + ); + len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); + len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); + len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); + len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); + len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); + len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); + len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); + len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); + len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); + len += sprintf (page+len, "MSCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk())); + len += sprintf (page+len, "EXTALCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); + len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); + + return len; +} + +static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) +{ + REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); + return count; +} + + +/* USAGE: + * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. + * echo FF > /proc/jz/ipu // 255, free all buffer + * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx + * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) + * echo 0 > /proc/jz/ipu // debug, print ipu_buf + * od -X /proc/jz/ipu // read mem addr + */ + +typedef struct _ipu_buf { + unsigned int addr; /* phys addr */ + unsigned int page_shift; +} ipu_buf_t; + +#define IPU_BUF_MAX 4 /* 4 buffers */ + +static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; +static int ipu_buf_cnt = 0; +static unsigned char g_asid=0; + +extern void local_flush_tlb_all(void); + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") +void show_tlb(void) +{ +#define ASID_MASK 0xFF + + unsigned long flags; + unsigned int old_ctx; + unsigned int entry; + unsigned int entrylo0, entrylo1, entryhi; + unsigned int pagemask; + + local_irq_save(flags); + + /* Save old context */ + old_ctx = (read_c0_entryhi() & 0xff); + + printk("TLB content:\n"); + entry = 0; + while(entry < 32) { + write_c0_index(entry); + BARRIER; + tlb_read(); + BARRIER; + entryhi = read_c0_entryhi(); + entrylo0 = read_c0_entrylo0(); + entrylo1 = read_c0_entrylo1(); + pagemask = read_c0_pagemask(); + printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); + printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); + printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); + + printk("\t\tpagemask=0x%08x", pagemask); + printk("\tentryhi=0x%08x\n", entryhi); + printk("\t\tentrylo0=0x%08x", entrylo0); + printk("\tentrylo1=0x%08x\n", entrylo1); + + entry++; + } + BARRIER; + write_c0_entryhi(old_ctx); + + local_irq_restore(flags); +} + +static void ipu_add_wired_entry(unsigned long pid, + unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + struct task_struct *g, *p; + + /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ + wired = read_c0_wired(); + if (wired) return; + + do_each_thread(g, p) { + if (p->pid == pid ) + g_asid = p->mm->context[0]; + } while_each_thread(g, p); + + local_irq_save(flags); + + entrylo0 = entrylo0 >> 6; /* PFN */ + entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ + + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & 0xff; + old_pagemask = read_c0_pagemask(); + write_c0_wired(wired + 1); + write_c0_index(wired); + BARRIER; + entryhi &= ~0xff; /* new add, 20070906 */ + entryhi |= g_asid; /* new add, 20070906 */ +// entryhi |= old_ctx; /* new add, 20070906 */ + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + write_c0_entryhi(old_ctx); + BARRIER; + write_c0_pagemask(old_pagemask); + local_flush_tlb_all(); + local_irq_restore(flags); +#if defined(DEBUG) + printk("\nold_ctx=%03d\n", old_ctx); + + show_tlb(); +#endif +} + +static void ipu_del_wired_entry( void ) +{ + unsigned long flags; + unsigned long wired; + + /* Free all lock entry */ + local_irq_save(flags); + wired = read_c0_wired(); + if (wired) + write_c0_wired(0); + local_irq_restore(flags); +} + +static inline void ipu_buf_get( unsigned int page_shift ) +{ + unsigned char * virt_addr; + int i; + for ( i=0; i< IPU_BUF_MAX; ++i ) { + if ( ipu_buf[i].addr == 0 ) { + break; + } + } + + if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { + printk("Error, no free ipu buffer.\n"); + return ; + } + + virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); + + if ( virt_addr ) { + ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); + ipu_buf[ipu_buf_cnt].page_shift = page_shift; + + for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ + printk("no free buffer.\n"); + *pint = 0; + } + else + *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ + len += sizeof(unsigned int); + +#if defined(DEBUG) + show_tlb(); +#endif + return len; + +} + +static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) +{ + unsigned int val ; + int cnt,i; + char buf[12]; + unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; +#if defined(DEBUG) + printk("ipu write count=%u\n", count); +#endif + if (count == (8*5+1)) { + for (i=0;i<12;i++) buf[i]=0; + strncpy(buf, buffer+8*0, 8); + pid = simple_strtoul(buf, 0, 16); + for (i=0;i<12;i++) buf[i]=0; + strncpy(buf, buffer+8*1, 8); + entrylo0 = simple_strtoul(buf, 0, 16); + for (i=0;i<12;i++) buf[i]=0; + strncpy(buf, buffer+8*2, 8); + entrylo1 = simple_strtoul(buf, 0, 16); + for (i=0;i<12;i++) buf[i]=0; + strncpy(buf, buffer+8*3, 8); + entryhi = simple_strtoul(buf, 0, 16); + for (i=0;i<12;i++) buf[i]=0; + strncpy(buf, buffer+8*4, 8); + pagemask = simple_strtoul(buf, 0, 16); + +#if defined(DEBUG) + printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", + pid, entrylo0, entrylo1, entryhi, pagemask); +#endif + ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); + return 41; + } else if ( count <= 8+1 ) { + for (i=0;i<12;i++) buf[i]=0; + strncpy(buf, buffer, 8); + val = simple_strtoul(buf, 0, 16); + } else if (count == 44) { + for (i = 0; i < 12; i++) + buf[i] = 0; + strncpy(buf, buffer, 10); + pid = simple_strtoul(buf, 0, 16); + for (i = 0; i < 12; i++) + buf[i] = 0; + strncpy(buf, buffer + 11, 10); + entryhi = simple_strtoul(buf, 0, 16);//vaddr + for (i = 0; i < 12; i++) + buf[i] = 0; + strncpy(buf, buffer + 22, 10); + entrylo0 = simple_strtoul(buf, 0, 16);//paddr + for (i = 0; i < 12; i++) + buf[i] = 0; + strncpy(buf, buffer + 33, 10); + pagemask = simple_strtoul(buf, 0, 16); + pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ + ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); + return 44; + } else { + printk("ipu write count error, count=%d\n.", (unsigned int)count); + return -1; + } + + /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ + if ( val == 0 ) { /* debug, print ipu_buf info */ + for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages + * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx + * echo FF > /proc/jz/ipu // FF, free all buffers + * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer + */ + +//#define DEBUG_IMEM 1 + +#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ + +static unsigned int jz_imem_base; /* physical base address of ipu memory */ + +static unsigned int allocated_phys_addr = 0; + +/* + * Allocated buffer list + */ +typedef struct imem_list { + unsigned int phys_start; /* physical start addr */ + unsigned int phys_end; /* physical end addr */ + struct imem_list *next; +} imem_list_t; + +static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ + +#ifdef DEBUG_IMEM +static void dump_imem_list(void) +{ + struct imem_list *imem; + + printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); + imem = imem_list_head; + while (imem) { + printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); + imem = imem->next; + } +} +#endif + +/* allocate 2^order pages inside the 4MB memory */ +static int imem_alloc(unsigned int order) +{ + int alloc_ok = 0; + unsigned int start, end; + unsigned int size = (1 << order) * PAGE_SIZE; + struct imem_list *imem, *imemn, *imemp; + + allocated_phys_addr = 0; + + start = jz_imem_base; + end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; + + imem = imem_list_head; + while (imem) { + if ((imem->phys_start - start) >= size) { + /* we got a valid address range */ + alloc_ok = 1; + break; + } + + start = imem->phys_end + 1; + imem = imem->next; + } + + if (!alloc_ok) { + if ((end - start) >= size) + alloc_ok = 1; + } + + if (alloc_ok) { + end = start + size - 1; + allocated_phys_addr = start; + + /* add to imem_list, up sorted by phys_start */ + imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); + if (!imemn) { + return -ENOMEM; + } + imemn->phys_start = start; + imemn->phys_end = end; + imemn->next = NULL; + + if (!imem_list_head) + imem_list_head = imemn; + else { + imem = imemp = imem_list_head; + while (imem) { + if (start < imem->phys_start) { + break; + } + + imemp = imem; + imem = imem->next; + } + + if (imem == imem_list_head) { + imem_list_head = imemn; + imemn->next = imem; + } + else { + imemn->next = imemp->next; + imemp->next = imemn; + } + } + } + +#ifdef DEBUG_IMEM + dump_imem_list(); +#endif + return 0; +} + +static void imem_free(unsigned int phys_addr) +{ + struct imem_list *imem, *imemp; + + imem = imemp = imem_list_head; + while (imem) { + if (phys_addr == imem->phys_start) { + if (imem == imem_list_head) { + imem_list_head = imem->next; + } + else { + imemp->next = imem->next; + } + + kfree(imem); + break; + } + + imemp = imem; + imem = imem->next; + } + +#ifdef DEBUG_IMEM + dump_imem_list(); +#endif +} + +static void imem_free_all(void) +{ + struct imem_list *imem; + + imem = imem_list_head; + while (imem) { + kfree(imem); + imem = imem->next; + } + + imem_list_head = NULL; + + allocated_phys_addr = 0; + +#ifdef DEBUG_IMEM + dump_imem_list(); +#endif +} + +/* + * Return the allocated buffer address and the max order of free buffer + */ +static int imem_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + unsigned int start_addr, end_addr, max_order, max_size; + struct imem_list *imem; + + unsigned int *tmp = (unsigned int *)(page + len); + + start_addr = jz_imem_base; + end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; + + if (!imem_list_head) + max_size = end_addr - start_addr; + else { + max_size = 0; + imem = imem_list_head; + while (imem) { + if (max_size < (imem->phys_start - start_addr)) + max_size = imem->phys_start - start_addr; + + start_addr = imem->phys_end + 1; + imem = imem->next; + } + + if (max_size < (end_addr - start_addr)) + max_size = end_addr - start_addr; + } + + if (max_size > 0) { + max_order = get_order(max_size); + if (((1 << max_order) * PAGE_SIZE) > max_size) + max_order--; + } + else { + max_order = 0xffffffff; /* No any free buffer */ + } + + *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ + *tmp = max_order; /* max order of current free buffers */ + + len += 2 * sizeof(unsigned int); + + return len; +} + +static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) +{ + unsigned int val; + + val = simple_strtoul(buffer, 0, 16); + + if (val == 0xff) { + /* free all memory */ + imem_free_all(); + ipu_del_wired_entry(); + } + else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { + /* allocate 2^val pages */ + imem_alloc(val); + } + else { + /* free buffer which phys_addr is val */ + imem_free(val); + } + + return count; +} + +/* + * /proc/jz/xxx entry + * + */ +static int __init jz_proc_init(void) +{ + struct proc_dir_entry *res; + unsigned int virt_addr, i; + + proc_jz_root = proc_mkdir("jz", 0); + + /* External Memory Controller */ + res = create_proc_entry("emc", 0644, proc_jz_root); + if (res) { + res->read_proc = emc_read_proc; + res->write_proc = NULL; + res->data = NULL; + } + + /* Power Management Controller */ + res = create_proc_entry("pmc", 0644, proc_jz_root); + if (res) { + res->read_proc = pmc_read_proc; + res->write_proc = pmc_write_proc; + res->data = NULL; + } + + /* Clock Generation Module */ + res = create_proc_entry("cgm", 0644, proc_jz_root); + if (res) { + res->read_proc = cgm_read_proc; + res->write_proc = cgm_write_proc; + res->data = NULL; + } + + /* Image process unit */ + res = create_proc_entry("ipu", 0644, proc_jz_root); + if (res) { + res->read_proc = ipu_read_proc; + res->write_proc = ipu_write_proc; + res->data = NULL; + } + + /* udc hotplug */ + res = create_proc_entry("udc", 0644, proc_jz_root); + if (res) { + res->read_proc = udc_read_proc; + res->write_proc = NULL; + res->data = NULL; + } + + /* mmc hotplug */ + res = create_proc_entry("mmc", 0644, proc_jz_root); + if (res) { + res->read_proc = mmc_read_proc; + res->write_proc = NULL; + res->data = NULL; + } + + /* + * Reserve a 4MB memory for IPU on JZ4740. + */ + jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); + if (jz_imem_base) { + /* imem (IPU memory management) */ + res = create_proc_entry("imem", 0644, proc_jz_root); + if (res) { + res->read_proc = imem_read_proc; + res->write_proc = imem_write_proc; + res->data = NULL; + } + + /* Set page reserved */ + virt_addr = jz_imem_base; + for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { + SetPageReserved(virt_to_page((void *)virt_addr)); + virt_addr += PAGE_SIZE; + } + + /* Convert to physical address */ + jz_imem_base = virt_to_phys((void *)jz_imem_base); + + printk("Total %dMB memory at 0x%x was reserved for IPU\n", + (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); + } + + return 0; +} + +__initcall(jz_proc_init); diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/prom.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/prom.c new file mode 100644 index 000000000..406893976 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/prom.c @@ -0,0 +1,198 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PROM library initialisation code, supports YAMON and U-Boot. + * + * Copyright 2000, 2001, 2006 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/xx files. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include +#include + +/* #define DEBUG_CMDLINE */ + +int prom_argc; +char **prom_argv, **prom_envp; + +char * prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + if (prom_argc > 1) + *cp = '\0'; + +} + + +char *prom_getenv(char *envname) +{ +#if 0 + /* + * Return a pointer to the given environment variable. + * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". + */ + + char **env = prom_envp; + int i = strlen(envname); + int yamon = (*env && strchr(*env, '=') == NULL); + + while (*env) { + if (yamon) { + if (strcmp(envname, *env++) == 0) + return *env; + } else { + if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') + return *env + i + 1; + } + env++; + } +#endif + return NULL; +} + +inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + if(c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; /* foo */ +} + +inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for(i = 0; i < 6; i++) { + unsigned char num; + + if((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + printk("ethaddr not set in boot prom\n"); + return -1; + } + str2eaddr(ethernet_addr, ethaddr_str); + +#if 0 + { + int i; + + printk("get_ethernet_addr: "); + for (i=0; i<5; i++) + printk("%02x:", (unsigned char)*(ethernet_addr+i)); + printk("%02x\n", *(ethernet_addr+i)); + } +#endif + + return 0; +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int) fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; + + mips_machtype = MACH_INGENIC_JZ4740; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +/* used by early printk */ +void prom_putchar(char c) +{ + volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR); + volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR); + + /* Wait for fifo to shift out some bytes */ + while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); + + *uart_tdr = (u8)c; +} + +const char *get_system_type(void) +{ + return "JZ4740"; +} + +EXPORT_SYMBOL(prom_getcmdline); +EXPORT_SYMBOL(get_ethernet_addr); +EXPORT_SYMBOL(str2eaddr); diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/reset.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/reset.c new file mode 100644 index 000000000..83577d868 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/reset.c @@ -0,0 +1,46 @@ +/* + * linux/arch/mips/jz4740/reset.c + * + * JZ4740 reset routines. + * + * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. + * Author: + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +void jz_restart(char *command) +{ + printk("Restarting after 4 ms\n"); + REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; + REG_WDT_TCNT = 0; + REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ + REG_TCU_TSCR = TCU_TSSR_WDTSC; /* enable wdt clock */ + REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ + while (1); +} + +void jz_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void jz_power_off(void) +{ + jz_halt(); +} diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/setup.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/setup.c new file mode 100644 index 000000000..564ed273e --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/setup.c @@ -0,0 +1,188 @@ +/* + * linux/arch/mips/jz4740/common/setup.c + * + * JZ4740 common setup routines. + * + * Copyright (C) 2006 Ingenic Semiconductor Inc. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PM +#include +#endif + +#ifdef CONFIG_PC_KEYB +#include +#endif + +jz_clocks_t jz_clocks; + +extern char * __init prom_getcmdline(void); +extern void __init jz_board_setup(void); +extern void jz_restart(char *); +extern void jz_halt(void); +extern void jz_power_off(void); +extern void jz_time_init(void); + +static void __init sysclocks_setup(void) +{ +#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ + jz_clocks.cclk = __cpm_get_cclk(); + jz_clocks.hclk = __cpm_get_hclk(); + jz_clocks.pclk = __cpm_get_pclk(); + jz_clocks.mclk = __cpm_get_mclk(); + jz_clocks.lcdclk = __cpm_get_lcdclk(); + jz_clocks.pixclk = __cpm_get_pixclk(); + jz_clocks.i2sclk = __cpm_get_i2sclk(); + jz_clocks.usbclk = __cpm_get_usbclk(); + jz_clocks.mscclk = __cpm_get_mscclk(); + jz_clocks.extalclk = __cpm_get_extalclk(); + jz_clocks.rtcclk = __cpm_get_rtcclk(); +#else + +#define FPGACLK 8000000 + + jz_clocks.cclk = FPGACLK; + jz_clocks.hclk = FPGACLK; + jz_clocks.pclk = FPGACLK; + jz_clocks.mclk = FPGACLK; + jz_clocks.lcdclk = FPGACLK; + jz_clocks.pixclk = FPGACLK; + jz_clocks.i2sclk = FPGACLK; + jz_clocks.usbclk = FPGACLK; + jz_clocks.mscclk = FPGACLK; + jz_clocks.extalclk = FPGACLK; + jz_clocks.rtcclk = FPGACLK; +#endif + + printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", + (jz_clocks.cclk + 500000) / 1000000, + (jz_clocks.hclk + 500000) / 1000000, + (jz_clocks.pclk + 500000) / 1000000, + (jz_clocks.mclk + 500000) / 1000000); +} + +static void __init soc_cpm_setup(void) +{ + /* Start all module clocks + */ + __cpm_start_all(); + + /* Enable CKO to external memory */ + __cpm_enable_cko(); + + /* CPU enters IDLE mode when executing 'wait' instruction */ + __cpm_idle_mode(); + + /* Setup system clocks */ + sysclocks_setup(); +} + +static void __init soc_harb_setup(void) +{ +// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ +// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ +// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ +} + +static void __init soc_emc_setup(void) +{ +} + +static void __init soc_dmac_setup(void) +{ + __dmac_enable_module(); +} + +static void __init jz_soc_setup(void) +{ + soc_cpm_setup(); + soc_harb_setup(); + soc_emc_setup(); + soc_dmac_setup(); +} + +static void __init jz_serial_setup(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct uart_port s; + REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ + memset(&s, 0, sizeof(s)); + s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + s.iotype = SERIAL_IO_MEM; + s.regshift = 2; + s.uartclk = jz_clocks.extalclk ; + + s.line = 0; + s.membase = (u8 *)UART0_BASE; + s.irq = IRQ_UART0; + if (early_serial_setup(&s) != 0) { + printk(KERN_ERR "Serial ttyS0 setup failed!\n"); + } + + s.line = 1; + s.membase = (u8 *)UART1_BASE; + s.irq = IRQ_UART1; + if (early_serial_setup(&s) != 0) { + printk(KERN_ERR "Serial ttyS1 setup failed!\n"); + } +#endif +} + +void __init plat_mem_setup(void) +{ + char *argptr; + + argptr = prom_getcmdline(); + + /* IO/MEM resources. Which will be the addtion value in `inX' and + * `outX' macros defined in asm/io.h */ + set_io_port_base(0); + ioport_resource.start = 0x00000000; + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0x00000000; + iomem_resource.end = 0xffffffff; + + _machine_restart = jz_restart; + _machine_halt = jz_halt; + pm_power_off = jz_power_off; +#ifdef CONFIG_PM + jz_pm_init(); +#endif + jz_soc_setup(); + jz_serial_setup(); + jz_board_setup(); +} + diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/time.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/time.c new file mode 100644 index 000000000..71f1291be --- /dev/null +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/time.c @@ -0,0 +1,159 @@ +/* + * linux/arch/mips/jz4740/time.c + * + * Setting up the clock on the JZ4740 boards. + * + * Copyright (C) 2008 Ingenic Semiconductor Inc. + * Author: + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ +#include +#include +#include +#include + +#include +#include + +/* This is for machines which generate the exact clock. */ + +#define JZ_TIMER_CHAN 0 +#define JZ_TIMER_IRQ IRQ_TCU0 + +#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ + +static struct clocksource clocksource_jz; /* Jz clock source */ +static struct clock_event_device jz_clockevent_device; /* Jz clock event */ + +void (*jz_timer_callback)(void); + +static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = dev_id; + + REG_TCU_TFCR = 1 << JZ_TIMER_CHAN; /* ACK timer */ + + if (jz_timer_callback) + jz_timer_callback(); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static struct irqaction jz_irqaction = { + .handler = jz_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .name = "jz-timerirq", +}; + + +cycle_t jz_get_cycles(void) +{ + /* convert jiffes to jz timer cycles */ + return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_TCNT(JZ_TIMER_CHAN)); +} + +static struct clocksource clocksource_jz = { + .name = "jz_clocksource", + .rating = 300, + .read = jz_get_cycles, + .mask = 0xFFFF, + .shift = 10, + .flags = CLOCK_SOURCE_WATCHDOG, +}; + +static int __init jz_clocksource_init(void) +{ + clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); + clocksource_register(&clocksource_jz); + return 0; +} + +static int jz_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + return 0; +} + +static void jz_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device jz_clockevent_device = { + .name = "jz-clockenvent", + .features = CLOCK_EVT_FEAT_PERIODIC, +// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ + + /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ + .mult = 1, + .rating = 300, + .irq = JZ_TIMER_IRQ, + .set_mode = jz_set_mode, + .set_next_event = jz_set_next_event, +}; + +static void __init jz_clockevent_init(void) +{ + struct clock_event_device *cd = &jz_clockevent_device; + unsigned int cpu = smp_processor_id(); + + cd->cpumask = cpumask_of(cpu); + clockevents_register_device(cd); +} + +static void __init jz_timer_setup(void) +{ + jz_clocksource_init(); /* init jz clock source */ + jz_clockevent_init(); /* init jz clock event */ + + /* + * Make irqs happen for the system timer + */ + jz_irqaction.dev_id = &jz_clockevent_device; + setup_irq(JZ_TIMER_IRQ, &jz_irqaction); +} + + +void __init plat_time_init(void) +{ + unsigned int latch; + /* Init timer */ + latch = ( JZ_TIMER_CLOCK + (HZ>>1)) / HZ; + + REG_TCU_TCSR(JZ_TIMER_CHAN) = TCU_TCSR_PRESCALE16 | TCU_TCSR_EXT_EN; + REG_TCU_TCNT(JZ_TIMER_CHAN) = 0; + REG_TCU_TDHR(JZ_TIMER_CHAN) = 0; + REG_TCU_TDFR(JZ_TIMER_CHAN) = latch; + + REG_TCU_TMSR = (1 << (JZ_TIMER_CHAN + 16)); /* mask half irq */ + REG_TCU_TMCR = (1 << JZ_TIMER_CHAN); /* unmask full irq */ + REG_TCU_TSCR = (1 << JZ_TIMER_CHAN); /* enable timer clock */ + REG_TCU_TESR = (1 << JZ_TIMER_CHAN); /* start counting up */ + + jz_timer_setup(); +} diff --git a/target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.c b/target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.c new file mode 100755 index 000000000..7b653feb9 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.c @@ -0,0 +1,995 @@ +/* + * linux/drivers/mmc/jz_mmc.c - JZ SD/MMC driver + * + * Copyright (C) 2005 - 2008 Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "jz_mmc.h" + +#define DRIVER_NAME "jz-mmc" + +#define NR_SG 1 + +#if defined(CONFIG_SOC_JZ4725) || defined(CONFIG_SOC_JZ4720) +#undef USE_DMA +#else +#define USE_DMA +#endif + +struct jz_mmc_host { + struct mmc_host *mmc; + spinlock_t lock; + struct { + int len; + int dir; + } dma; + struct { + int index; + int offset; + int len; + } pio; + int irq; + unsigned int clkrt; + unsigned int cmdat; + unsigned int imask; + unsigned int power_mode; + struct jz_mmc_platform_data *pdata; + struct mmc_request *mrq; + struct mmc_command *cmd; + struct mmc_data *data; + dma_addr_t sg_dma; + struct jzsoc_dma_desc *sg_cpu; + unsigned int dma_len; + unsigned int dma_dir; + struct pm_dev *pmdev; +}; + +static int r_type = 0; + +#define MMC_IRQ_MASK() \ +do { \ + REG_MSC_IMASK = 0xff; \ + REG_MSC_IREG = 0xff; \ +} while (0) + +static int rxdmachan = 0; +static int txdmachan = 0; +static int mmc_slot_enable = 0; + +/* Stop the MMC clock and wait while it happens */ +static inline int jz_mmc_stop_clock(void) +{ + int timeout = 1000; + + REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; + while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) { + timeout--; + if (timeout == 0) + return 0; + udelay(1); + } + return MMC_NO_ERROR; +} + +/* Start the MMC clock and operation */ +static inline int jz_mmc_start_clock(void) +{ + REG_MSC_STRPCL = + MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; + return MMC_NO_ERROR; +} + +static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate) +{ + u32 clkrt; + u32 clk_src = is_sd ? 24000000 : 20000000; + + clkrt = 0; + while (rate < clk_src) { + clkrt++; + clk_src >>= 1; + } + return clkrt; +} + +/* Select the MMC clock frequency */ +static int jz_mmc_set_clock(u32 rate) +{ + int clkrt; + + jz_mmc_stop_clock(); + __cpm_select_msc_clk(1); /* select clock source from CPM */ + clkrt = jz_mmc_calc_clkrt(1, rate); + REG_MSC_CLKRT = clkrt; + return MMC_NO_ERROR; +} + +static void jz_mmc_enable_irq(struct jz_mmc_host *host, unsigned int mask) +{ + unsigned long flags; + spin_lock_irqsave(&host->lock, flags); + host->imask &= ~mask; + REG_MSC_IMASK = host->imask; + spin_unlock_irqrestore(&host->lock, flags); +} + +static void jz_mmc_disable_irq(struct jz_mmc_host *host, unsigned int mask) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->imask |= mask; + REG_MSC_IMASK = host->imask; + spin_unlock_irqrestore(&host->lock, flags); +} + +void jz_set_dma_block_size(int dmanr, int nbyte); + +#ifdef USE_DMA +static inline void +jz_mmc_start_dma(int chan, unsigned long phyaddr, int count, int mode) +{ + unsigned long flags; + + flags = claim_dma_lock(); + disable_dma(chan); + clear_dma_ff(chan); + jz_set_dma_block_size(chan, 32); + set_dma_mode(chan, mode); + set_dma_addr(chan, phyaddr); + set_dma_count(chan, count + 31); + enable_dma(chan); + release_dma_lock(flags); +} + +static irqreturn_t jz_mmc_dma_rx_callback(int irq, void *devid) +{ + int chan = rxdmachan; + + disable_dma(chan); + if (__dmac_channel_address_error_detected(chan)) { + printk(KERN_DEBUG "%s: DMAC address error.\n", + __FUNCTION__); + __dmac_channel_clear_address_error(chan); + } + if (__dmac_channel_transmit_end_detected(chan)) { + __dmac_channel_clear_transmit_end(chan); + } + return IRQ_HANDLED; +} +static irqreturn_t jz_mmc_dma_tx_callback(int irq, void *devid) +{ + int chan = txdmachan; + + disable_dma(chan); + if (__dmac_channel_address_error_detected(chan)) { + printk(KERN_DEBUG "%s: DMAC address error.\n", + __FUNCTION__); + __dmac_channel_clear_address_error(chan); + } + if (__dmac_channel_transmit_end_detected(chan)) { + __dmac_channel_clear_transmit_end(chan); + } + return IRQ_HANDLED; +} + +/* Prepare DMA to start data transfer from the MMC card */ +static void jz_mmc_rx_setup_data(struct jz_mmc_host *host, + struct mmc_data *data) +{ + unsigned int nob = data->blocks; + int channelrx = rxdmachan; + int i; + u32 size; + + if (data->flags & MMC_DATA_STREAM) + nob = 0xffff; + + REG_MSC_NOB = nob; + REG_MSC_BLKLEN = data->blksz; + size = nob * data->blksz; + + if (data->flags & MMC_DATA_READ) { + host->dma.dir = DMA_FROM_DEVICE; + } else { + host->dma.dir = DMA_TO_DEVICE; + } + + host->dma.len = + dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + host->dma.dir); + + for (i = 0; i < host->dma.len; i++) { + host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); + host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); + dma_cache_wback_inv((unsigned long) + CKSEG0ADDR(sg_dma_address(data->sg)) + + data->sg->offset, + host->sg_cpu[i].dcmd); + jz_mmc_start_dma(channelrx, host->sg_cpu[i].dtadr, + host->sg_cpu[i].dcmd, DMA_MODE_READ); + } +} + +/* Prepare DMA to start data transfer from the MMC card */ +static void jz_mmc_tx_setup_data(struct jz_mmc_host *host, + struct mmc_data *data) +{ + unsigned int nob = data->blocks; + int channeltx = txdmachan; + int i; + u32 size; + + if (data->flags & MMC_DATA_STREAM) + nob = 0xffff; + + REG_MSC_NOB = nob; + REG_MSC_BLKLEN = data->blksz; + size = nob * data->blksz; + + if (data->flags & MMC_DATA_READ) { + host->dma.dir = DMA_FROM_DEVICE; + } else { + host->dma.dir = DMA_TO_DEVICE; + } + + host->dma.len = + dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + host->dma.dir); + + for (i = 0; i < host->dma.len; i++) { + host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); + host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); + dma_cache_wback_inv((unsigned long) + CKSEG0ADDR(sg_dma_address(data->sg)) + + data->sg->offset, + host->sg_cpu[i].dcmd); + jz_mmc_start_dma(channeltx, host->sg_cpu[i].dtadr, + host->sg_cpu[i].dcmd, DMA_MODE_WRITE); + } +} +#else +static void jz_mmc_receive_pio(struct jz_mmc_host *host) +{ + + struct mmc_data *data = 0; + int sg_len = 0, max = 0, count = 0; + u32 *buf = 0; + struct scatterlist *sg; + unsigned int nob; + + data = host->mrq->data; + nob = data->blocks; + REG_MSC_NOB = nob; + REG_MSC_BLKLEN = data->blksz; + + max = host->pio.len; + if (host->pio.index < host->dma.len) { + sg = &data->sg[host->pio.index]; + buf = sg_virt(sg) + host->pio.offset; + + /* This is the space left inside the buffer */ + sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; + /* Check to if we need less then the size of the sg_buffer */ + if (sg_len < max) max = sg_len; + } + max = max / 4; + for(count = 0; count < max; count++) { + while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY) + ; + *buf++ = REG_MSC_RXFIFO; + } + host->pio.len -= count; + host->pio.offset += count; + + if (sg_len && count == sg_len) { + host->pio.index++; + host->pio.offset = 0; + } +} + +static void jz_mmc_send_pio(struct jz_mmc_host *host) +{ + + struct mmc_data *data = 0; + int sg_len, max, count = 0; + u32 *wbuf = 0; + struct scatterlist *sg; + unsigned int nob; + + data = host->mrq->data; + nob = data->blocks; + + REG_MSC_NOB = nob; + REG_MSC_BLKLEN = data->blksz; + + /* This is the pointer to the data buffer */ + sg = &data->sg[host->pio.index]; + wbuf = sg_virt(sg) + host->pio.offset; + + /* This is the space left inside the buffer */ + sg_len = data->sg[host->pio.index].length - host->pio.offset; + + /* Check to if we need less then the size of the sg_buffer */ + max = (sg_len > host->pio.len) ? host->pio.len : sg_len; + max = max / 4; + for(count = 0; count < max; count++ ) { + while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL) + ; + REG_MSC_TXFIFO = *wbuf++; + } + + host->pio.len -= count; + host->pio.offset += count; + + if (count == sg_len) { + host->pio.index++; + host->pio.offset = 0; + } +} + +static int +jz_mmc_prepare_data(struct jz_mmc_host *host, struct mmc_data *data) +{ + int datalen = data->blocks * data->blksz; + + host->dma.dir = DMA_BIDIRECTIONAL; + host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma.dir); + if (host->dma.len == 0) + return -ETIMEDOUT; + + host->pio.index = 0; + host->pio.offset = 0; + host->pio.len = datalen; + return 0; +} +#endif + +static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat); + +static void jz_mmc_finish_request(struct jz_mmc_host *host, struct mmc_request *mrq) +{ + jz_mmc_stop_clock(); + host->mrq = NULL; + host->cmd = NULL; + host->data = NULL; + mmc_request_done(host->mmc, mrq); +} + +static void jz_mmc_start_cmd(struct jz_mmc_host *host, + struct mmc_command *cmd, unsigned int cmdat) +{ + u32 timeout = 0x3fffff; + unsigned int stat; + struct jz_mmc_host *hst = host; + WARN_ON(host->cmd != NULL); + host->cmd = cmd; + + /* stop MMC clock */ + jz_mmc_stop_clock(); + + /* mask interrupts */ + REG_MSC_IMASK = 0xff; + + /* clear status */ + REG_MSC_IREG = 0xff; + + if (cmd->flags & MMC_RSP_BUSY) + cmdat |= MSC_CMDAT_BUSY; + +#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) + switch (RSP_TYPE(mmc_resp_type(cmd))) { + case RSP_TYPE(MMC_RSP_R1): /* r1,r1b, r6, r7 */ + cmdat |= MSC_CMDAT_RESPONSE_R1; + r_type = 1; + break; + case RSP_TYPE(MMC_RSP_R3): + cmdat |= MSC_CMDAT_RESPONSE_R3; + r_type = 1; + break; + case RSP_TYPE(MMC_RSP_R2): + cmdat |= MSC_CMDAT_RESPONSE_R2; + r_type = 2; + break; + default: + break; + } + REG_MSC_CMD = cmd->opcode; + + /* Set argument */ +#ifdef CONFIG_JZ_MMC_BUS_1 + if (cmd->opcode == 6) { + /* set 1 bit sd card bus*/ + if (cmd->arg ==2) + REG_MSC_ARG = 0; + + /* set 1 bit mmc card bus*/ + if (cmd->arg == 0x3b70101) + REG_MSC_ARG = 0x3b70001; + } else + REG_MSC_ARG = cmd->arg; +#else + REG_MSC_ARG = cmd->arg; +#endif + + /* Set command */ + REG_MSC_CMDAT = cmdat; + + /* Send command */ + jz_mmc_start_clock(); + + while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)) + ; + + REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear irq flag */ + if (cmd->opcode == 12) { + while (timeout-- && !(REG_MSC_IREG & MSC_IREG_PRG_DONE)) + ; + REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ + } + if (!mmc_slot_enable) { + /* It seems that MSC can't report the MSC_STAT_TIME_OUT_RES when + * card was removed. We force to return here. + */ + cmd->error = -ETIMEDOUT; + jz_mmc_finish_request(hst, hst->mrq); + return; + } + + if (SD_IO_SEND_OP_COND == cmd->opcode) { + /* + * Don't support SDIO card currently. + */ + cmd->error = -ETIMEDOUT; + jz_mmc_finish_request(hst, hst->mrq); + return; + } + + /* Check for status */ + stat = REG_MSC_STAT; + jz_mmc_cmd_done(hst, stat); + if (host->data) { + if (cmd->opcode == MMC_WRITE_BLOCK || cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) +#ifdef USE_DMA + jz_mmc_tx_setup_data(host, host->data); +#else + jz_mmc_send_pio(host); + else + jz_mmc_receive_pio(host); +#endif + } +} + +static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat) +{ + struct mmc_command *cmd = host->cmd; + int i, temp[16]; + u8 *buf; + u32 data, v, w1, w2; + + if (!cmd) + return 0; + + host->cmd = NULL; + buf = (u8 *) temp; + switch (r_type) { + case 1: + { + data = REG_MSC_RES; + buf[0] = (data >> 8) & 0xff; + buf[1] = data & 0xff; + data = REG_MSC_RES; + buf[2] = (data >> 8) & 0xff; + buf[3] = data & 0xff; + data = REG_MSC_RES; + buf[4] = data & 0xff; + cmd->resp[0] = + buf[1] << 24 | buf[2] << 16 | buf[3] << 8 | + buf[4]; + break; + } + case 2: + { + data = REG_MSC_RES; + v = data & 0xffff; + for (i = 0; i < 4; i++) { + data = REG_MSC_RES; + w1 = data & 0xffff; + data = REG_MSC_RES; + w2 = data & 0xffff; + cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; + v = w2; + } + break; + } + case 0: + break; + } + if (stat & MSC_STAT_TIME_OUT_RES) { + printk("MSC_STAT_TIME_OUT_RES\n"); + cmd->error = -ETIMEDOUT; + } else if (stat & MSC_STAT_CRC_RES_ERR && cmd->flags & MMC_RSP_CRC) { + printk("MSC_STAT_CRC\n"); + if (cmd->opcode == MMC_ALL_SEND_CID || + cmd->opcode == MMC_SEND_CSD || + cmd->opcode == MMC_SEND_CID) { + /* a bogus CRC error can appear if the msb of + the 15 byte response is a one */ + if ((cmd->resp[0] & 0x80000000) == 0) + cmd->error = -EILSEQ; + } + } + /* + * Did I mention this is Sick. We always need to + * discard the upper 8 bits of the first 16-bit word. + */ + if (host->data && cmd->error == 0) + jz_mmc_enable_irq(host, MSC_IMASK_DATA_TRAN_DONE); + else + jz_mmc_finish_request(host, host->mrq); + + return 1; +} + +static int jz_mmc_data_done(struct jz_mmc_host *host, unsigned int stat) +{ + struct mmc_data *data = host->data; + + if (!data) + return 0; + REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ + jz_mmc_stop_clock(); + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, + host->dma_dir); + if (stat & MSC_STAT_TIME_OUT_READ) { + printk("MMC/SD timeout, MMC_STAT 0x%x\n", stat); + data->error = -ETIMEDOUT; + } else if (REG_MSC_STAT & + (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR)) { + printk("MMC/SD CRC error, MMC_STAT 0x%x\n", stat); + data->error = -EILSEQ; + } + /* + * There appears to be a hardware design bug here. There seems to + * be no way to find out how much data was transferred to the card. + * This means that if there was an error on any block, we mark all + * data blocks as being in error. + */ + if (data->error == 0) + data->bytes_xfered = data->blocks * data->blksz; + else + data->bytes_xfered = 0; + + jz_mmc_disable_irq(host, MSC_IMASK_DATA_TRAN_DONE); + host->data = NULL; + if (host->mrq->stop) { + jz_mmc_stop_clock(); + jz_mmc_start_cmd(host, host->mrq->stop, 0); + } else { + jz_mmc_finish_request(host, host->mrq); + } + return 1; +} + +static void jz_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct jz_mmc_host *host = mmc_priv(mmc); + unsigned int cmdat; + + /* stop MMC clock */ + jz_mmc_stop_clock(); + + /* Save current request for the future processing */ + host->mrq = mrq; + host->data = mrq->data; + cmdat = host->cmdat; + host->cmdat &= ~MSC_CMDAT_INIT; + + if (mrq->data) { + cmdat &= ~MSC_CMDAT_BUSY; +#ifdef USE_DMA + if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) + + cmdat |= + MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | + MSC_CMDAT_DMA_EN; + else { +#ifdef CONFIG_JZ_MMC_BUS_1 + cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; + cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | + MSC_CMDAT_DMA_EN; +#else + cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; +#endif + } + if (mrq->data->flags & MMC_DATA_WRITE) + cmdat |= MSC_CMDAT_WRITE; + + if (mrq->data->flags & MMC_DATA_STREAM) + cmdat |= MSC_CMDAT_STREAM_BLOCK; + if (mrq->cmd->opcode != MMC_WRITE_BLOCK + && mrq->cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) + jz_mmc_rx_setup_data(host, mrq->data); +#else /*USE_DMA*/ + + if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) + cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; + else { +#ifdef CONFIG_JZ_MMC_BUS_1 + cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; + cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; +#else + cmdat |= MSC_CMDAT_DATA_EN; +#endif + } + if (mrq->data->flags & MMC_DATA_WRITE) + cmdat |= MSC_CMDAT_WRITE; + + if (mrq->data->flags & MMC_DATA_STREAM) + cmdat |= MSC_CMDAT_STREAM_BLOCK; + jz_mmc_prepare_data(host, host->data); +#endif /*USE_DMA*/ + } + jz_mmc_start_cmd(host, mrq->cmd, cmdat); +} + +static irqreturn_t jz_mmc_irq(int irq, void *devid) +{ + struct jz_mmc_host *host = devid; + unsigned int ireg; + int handled = 0; + + ireg = REG_MSC_IREG; + + if (ireg) { + unsigned stat = REG_MSC_STAT; + if (ireg & MSC_IREG_DATA_TRAN_DONE) + handled |= jz_mmc_data_done(host, stat); + } + return IRQ_RETVAL(handled); +} + +/* Returns true if MMC slot is empty */ +static int jz_mmc_slot_is_empty(int slot) +{ + int empty; + + empty = (__msc_card_detected(slot) == 0) ? 1 : 0; + + if (empty) { + /* wait for card insertion */ +#ifdef CONFIG_MIPS_JZ4740_LYRA + __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); +#else + __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); +#endif + } else { + /* wait for card removal */ +#ifdef CONFIG_MIPS_JZ4740_LYRA + __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); +#else + __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); +#endif + } + + return empty; +} + +static irqreturn_t jz_mmc_detect_irq(int irq, void *devid) +{ + struct jz_mmc_host *host = (struct jz_mmc_host *) devid; + + if (jz_mmc_slot_is_empty(0)) { + mmc_slot_enable = 0; + mmc_detect_change(host->mmc, 50); + } else { + mmc_slot_enable = 1; + mmc_detect_change(host->mmc, 50); + } + return IRQ_HANDLED; +} + +static int jz_mmc_get_ro(struct mmc_host *mmc) +{ + struct jz_mmc_host *host = mmc_priv(mmc); + + if (host->pdata && host->pdata->get_ro) + return host->pdata->get_ro(mmc_dev(mmc)); + /* Host doesn't support read only detection so assume writeable */ + return 0; +} + +/* set clock and power */ +static void jz_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct jz_mmc_host *host = mmc_priv(mmc); + + if (ios->clock) + jz_mmc_set_clock(ios->clock); + else + jz_mmc_stop_clock(); + + if (host->power_mode != ios->power_mode) { + host->power_mode = ios->power_mode; + + if (ios->power_mode == MMC_POWER_ON) + host->cmdat |= CMDAT_INIT; + } + + if ((ios->bus_width == MMC_BUS_WIDTH_4) || (ios->bus_width == MMC_BUS_WIDTH_8)) + host->cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; + else + host->cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; +} + +static const struct mmc_host_ops jz_mmc_ops = { + .request = jz_mmc_request, + .get_ro = jz_mmc_get_ro, + .set_ios = jz_mmc_set_ios, +}; + +static int jz_mmc_probe(struct platform_device *pdev) +{ + int retval; + struct mmc_host *mmc; + struct jz_mmc_host *host = NULL; + int irq; + struct resource *r; + + __gpio_as_msc(); + __msc_init_io(); + __msc_enable_power(); + + __msc_reset(); + + /* On reset, stop MMC clock */ + jz_mmc_stop_clock(); + + MMC_IRQ_MASK(); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!r || irq < 0) + return -ENXIO; + + r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); + if (!r) + return -EBUSY; + + mmc = mmc_alloc_host(sizeof(struct jz_mmc_host), &pdev->dev); + if (!mmc) { + retval = -ENOMEM; + goto out; + } + mmc->ops = &jz_mmc_ops; + mmc->f_min = MMC_CLOCK_SLOW; + mmc->f_max = SD_CLOCK_FAST; + /* + * We can do SG-DMA, but we don't because we never know how much + * data we successfully wrote to the card. + */ + mmc->max_phys_segs = NR_SG; + /* + * Our hardware DMA can handle a maximum of one page per SG entry. + */ + mmc->max_seg_size = PAGE_SIZE; + /* + * Block length register is 10 bits. + */ + mmc->max_blk_size = 1023; + /* + * Block count register is 16 bits. + */ + mmc->max_blk_count = 65535; + host = mmc_priv(mmc); + host->mmc = mmc; + host->pdata = pdev->dev.platform_data; + mmc->ocr_avail = host->pdata ? + host->pdata->ocr_mask : MMC_VDD_32_33 | MMC_VDD_33_34; + host->mmc->caps = + MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED + | MMC_CAP_MMC_HIGHSPEED; + /* + *MMC_CAP_4_BIT_DATA (1 << 0) The host can do 4 bit transfers + * + */ + host->sg_cpu = + dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, + GFP_KERNEL); + if (!host->sg_cpu) { + retval = -ENOMEM; + goto out; + } + spin_lock_init(&host->lock); + host->irq = IRQ_MSC; + host->imask = 0xff; + /* + * Ensure that the host controller is shut down, and setup + * with our defaults. + */ + retval = request_irq(IRQ_MSC, jz_mmc_irq, 0, "MMC/SD", host); + if (retval) { + printk(KERN_ERR "MMC/SD: can't request MMC/SD IRQ\n"); + return retval; + } + jz_mmc_slot_is_empty(0); + /* Request card detect interrupt */ + + retval = request_irq(MSC_HOTPLUG_IRQ, jz_mmc_detect_irq, 0, //SA_INTERRUPT, + "MMC card detect", host); + if (retval) { + printk(KERN_ERR "MMC/SD: can't request card detect IRQ\n"); + goto err1; + } +#ifdef USE_DMA + /* Request MMC Rx DMA channel */ + rxdmachan = + jz_request_dma(DMA_ID_MSC_RX, "MMC Rx", jz_mmc_dma_rx_callback, + 0, host); + if (rxdmachan < 0) { + printk(KERN_ERR "jz_request_dma failed for MMC Rx\n"); + goto err2; + } + + /* Request MMC Tx DMA channel */ + txdmachan = + jz_request_dma(DMA_ID_MSC_TX, "MMC Tx", jz_mmc_dma_tx_callback, + 0, host); + if (txdmachan < 0) { + printk(KERN_ERR "jz_request_dma failed for MMC Tx\n"); + goto err3; + } +#endif + platform_set_drvdata(pdev, mmc); + mmc_add_host(mmc); + printk("JZ SD/MMC card driver registered\n"); + + /* Detect card during initialization */ +#ifdef CONFIG_SOC_JZ4740 + if (!jz_mmc_slot_is_empty(0)) { + mmc_slot_enable = 1; + mmc_detect_change(host->mmc, 0); + } +#endif + return 0; + +err1:free_irq(IRQ_MSC, &host); +#ifdef USE_DMA + err2:jz_free_dma(rxdmachan); + err3:jz_free_dma(txdmachan); +#endif +out: + if (host) { + if (host->sg_cpu) + dma_free_coherent(&pdev->dev, PAGE_SIZE, + host->sg_cpu, host->sg_dma); + } + if (mmc) + mmc_free_host(mmc); + return -1; +} + +static int jz_mmc_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (mmc) { + struct jz_mmc_host *host = mmc_priv(mmc); + + if (host->pdata && host->pdata->exit) + host->pdata->exit(&pdev->dev, mmc); + + mmc_remove_host(mmc); + + jz_mmc_stop_clock(); + __msc_disable_power(); + jz_free_dma(rxdmachan); + jz_free_dma(txdmachan); + free_irq(IRQ_MSC, host); + mmc_free_host(mmc); + } + return 0; +} + +#ifdef CONFIG_PM +pm_message_t state; +static int jz_mmc_suspend(struct platform_device *dev, pm_message_t state) +{ + struct mmc_host *mmc = platform_get_drvdata(dev); + int ret = 0; + + __msc_disable_power(); + if (mmc) + ret = mmc_suspend_host(mmc, state); + + return ret; +} + +static int jz_mmc_resume(struct platform_device *dev) +{ + struct mmc_host *mmc = platform_get_drvdata(dev); + int ret = 0; +#if 0 + /*for sandisk BB0807011816D and other strange cards*/ + int i; + + for(i = 104; i < 110; i++) + __gpio_as_input(i); + + /* perhaps you should mdelay more */ + mdelay(1000); + __gpio_as_msc(); +#endif + __msc_init_io(); + __msc_enable_power(); + __msc_reset(); + + if (!jz_mmc_slot_is_empty(0)) { + mmc_slot_enable = 1; + mmc_detect_change(mmc, 10); + } + + if (mmc) + ret = mmc_resume_host(mmc); + + return ret; +} +#else +#define jz_mmc_suspend NULL +#define jz_mmc_resume NULL +#endif + +static struct platform_driver jz_mmc_driver = { + .probe = jz_mmc_probe, + .remove = jz_mmc_remove, + .suspend = jz_mmc_suspend, + .resume = jz_mmc_resume, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init jz_mmc_init(void) +{ + return platform_driver_register(&jz_mmc_driver); +} + +static void __exit jz_mmc_exit(void) +{ + platform_driver_unregister(&jz_mmc_driver); +} + +module_init(jz_mmc_init); +module_exit(jz_mmc_exit); + +MODULE_DESCRIPTION("JZ47XX SD/Multimedia Card Interface Driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.h b/target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.h new file mode 100755 index 000000000..c733529b7 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/mmc/host/jz_mmc.h @@ -0,0 +1,65 @@ +#ifndef __JZ_MMC_H__ +#define __JZ_MMC_H__ + +#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ +#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ +#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ +#define MMC_NO_ERROR 0 +/* Extra MMC commands for state control */ +/* Use negative numbers to disambiguate */ +#define MMC_CIM_RESET -1 +#define MMC_SET_CLOCK 100 + +typedef struct jzsoc_dma_desc { + volatile u32 ddadr; /* Points to the next descriptor + flags */ + volatile u32 dsadr; /* DSADR value for the current transfer */ + volatile u32 dtadr; /* DTADR value for the current transfer */ + volatile u32 dcmd; /* DCMD value for the current transfer */ +} jzsoc_dma_desc; + + + + +#include + +struct device; +struct mmc_host; + +struct jz_mmc_platform_data { + unsigned int ocr_mask; /* available voltages */ + unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ + int (*init)(struct device *, irq_handler_t , void *); + int (*get_ro)(struct device *); + void (*setpower)(struct device *, unsigned int); + void (*exit)(struct device *, void *); +}; + +//extern void pxa_set_mci_info(struct pxamci_platform_data *info); + + + +#define SZ_1K 0x00000400 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 + +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 + +#define SZ_1G 0x40000000 +#define SZ_2G 0x80000000 + + +#endif /* __JZ_MMC_H__ */ diff --git a/target/linux/xburst/files-2.6.31/drivers/mtd/nand/jz4740_nand.c b/target/linux/xburst/files-2.6.31/drivers/mtd/nand/jz4740_nand.c new file mode 100644 index 000000000..113bceda6 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/mtd/nand/jz4740_nand.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * JZ4720/JZ4740 SoC NAND controller 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. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#define JZ_REG_NAND_CTRL 0x50 +#define JZ_REG_NAND_ECC_CTRL 0x100 +#define JZ_REG_NAND_DATA 0x104 +#define JZ_REG_NAND_PAR0 0x108 +#define JZ_REG_NAND_PAR1 0x10C +#define JZ_REG_NAND_PAR2 0x110 +#define JZ_REG_NAND_IRQ_STAT 0x114 +#define JZ_REG_NAND_IRQ_CTRL 0x118 +#define JZ_REG_NAND_ERR(x) (0x11C + (x << 2)) + +#define JZ_NAND_ECC_CTRL_PAR_READY BIT(4) +#define JZ_NAND_ECC_CTRL_ENCODING BIT(3) +#define JZ_NAND_ECC_CTRL_RS BIT(2) +#define JZ_NAND_ECC_CTRL_RESET BIT(1) +#define JZ_NAND_ECC_CTRL_ENABLE BIT(0) + +#define JZ_NAND_STATUS_ERR_COUNT (BIT(31) | BIT(30) | BIT(29)) +#define JZ_NAND_STATUS_PAD_FINISH BIT(4) +#define JZ_NAND_STATUS_DEC_FINISH BIT(3) +#define JZ_NAND_STATUS_ENC_FINISH BIT(2) +#define JZ_NAND_STATUS_UNCOR_ERROR BIT(1) +#define JZ_NAND_STATUS_ERROR BIT(0) + +#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT(x << 1) +#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT((x << 1) + 1) + +#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000) +#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000) +#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000) + +struct jz_nand { + struct mtd_info mtd; + struct nand_chip chip; + void __iomem *base; + struct resource *mem; + + struct jz_nand_platform_data *pdata; +}; + +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_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; + + if (ctrl & NAND_CTRL_CHANGE) { + BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE)); + if (ctrl & NAND_ALE) + chip->IO_ADDR_W = JZ_NAND_ADDR_ADDR; + else if (ctrl & NAND_CLE) + chip->IO_ADDR_W = JZ_NAND_CMD_ADDR; + else + chip->IO_ADDR_W = JZ_NAND_DATA_ADDR; + + reg = readl(nand->base + JZ_REG_NAND_CTRL); + if ( ctrl & NAND_NCE ) + reg |= JZ_NAND_CTRL_ASSERT_CHIP(0); + else + reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0); + writel(reg, nand->base + JZ_REG_NAND_CTRL); + } + if (dat != NAND_CMD_NONE) + writeb(dat, chip->IO_ADDR_W); +} + +static int jz_nand_dev_ready(struct mtd_info *mtd) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + return gpio_get_value_cansleep(nand->pdata->busy_gpio); +} + +static void jz_nand_hwctl(struct mtd_info *mtd, int mode) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + uint32_t reg; + + + writel(0, nand->base + JZ_REG_NAND_IRQ_STAT); + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + + reg |= JZ_NAND_ECC_CTRL_RESET; + reg |= JZ_NAND_ECC_CTRL_ENABLE; + reg |= JZ_NAND_ECC_CTRL_RS; + + switch(mode) { + case NAND_ECC_READ: + reg &= ~JZ_NAND_ECC_CTRL_ENCODING; + break; + case NAND_ECC_WRITE: + reg |= JZ_NAND_ECC_CTRL_ENCODING; + break; + default: + break; + } + + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); +} + +static int jz_nand_calculate_ecc_rs(struct mtd_info* mtd, const uint8_t* dat, + uint8_t *ecc_code) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + uint32_t reg, status; + int i; + + do { + status = readl(nand->base + JZ_REG_NAND_IRQ_STAT); + } while(!(status & JZ_NAND_STATUS_ENC_FINISH)); + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg &= ~JZ_NAND_ECC_CTRL_ENABLE; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + for (i = 0; i < 9; ++i) { + ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i); + } + + return 0; +} + +static void correct_data(uint8_t *dat, int index, int mask) +{ + int offset = index & 0x7; + uint16_t data; + printk("correct: "); + + index += (index >> 3); + + data = dat[index]; + data |= dat[index+1] << 8; + + printk("0x%x -> ", data); + + mask ^= (data >> offset) & 0x1ff; + data &= ~(0x1ff << offset); + data |= (mask << offset); + + printk("0x%x\n", data); + + dat[index] = data & 0xff; + dat[index+1] = (data >> 8) & 0xff; +} + +static int jz_nand_correct_ecc_rs(struct mtd_info* mtd, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + int i, error_count, index; + uint32_t reg, status, error; + + for(i = 0; i < 9; ++i) { + if (read_ecc[i] != 0xff) + break; + } + if (i == 9) { + for (i = 0; i < nand->chip.ecc.size; ++i) { + if (dat[i] != 0xff) + break; + } + if (i == nand->chip.ecc.size) + return 0; + } + + for(i = 0; i < 9; ++i) + writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i); + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg |= JZ_NAND_ECC_CTRL_PAR_READY; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + do { + status = readl(nand->base + JZ_REG_NAND_IRQ_STAT); + } while (!(status & JZ_NAND_STATUS_DEC_FINISH)); + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg &= ~JZ_NAND_ECC_CTRL_ENABLE; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + + if (status & JZ_NAND_STATUS_ERROR) { + if (status & JZ_NAND_STATUS_UNCOR_ERROR) { + printk("uncorreclteble ecc:"); + for(i = 0; i < 9; ++i) + printk(" 0x%x", read_ecc[i]); + printk("\n"); + printk("uncorreclteble data:"); + for(i = 0; i < 32; ++i) + printk(" 0x%x", dat[i]); + printk("\n"); + return -1; + } + + error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29; + + printk("error_count: %d %x\n", error_count, status); + + for(i = 0;i < error_count; ++i) { + error = readl(nand->base + JZ_REG_NAND_ERR(i)); + index = ((error >> 16) & 0x1ff) - 1; + if (index >= 0 && index < 512) { + correct_data(dat, index, error & 0x1ff); + } + } + + return error_count; + } + + return 0; +} + + + +#ifdef CONFIG_MTD_CMDLINE_PARTS +static const char *part_probes[] = {"cmdline", NULL}; +#endif + +static int __devinit jz_nand_probe(struct platform_device *pdev) +{ + int ret; + struct jz_nand *nand; + struct nand_chip *chip; + struct mtd_info *mtd; + struct jz_nand_platform_data *pdata = pdev->dev.platform_data; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *partition_info; + int num_partitions = 0; +#endif + + nand = kzalloc(sizeof(*nand), GFP_KERNEL); + if (!nand) { + dev_err(&pdev->dev, "Failed to allocate device structure.\n"); + return -ENOMEM; + } + + nand->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!nand->mem) { + dev_err(&pdev->dev, "Failed to get platform mmio memory\n"); + ret = -ENOENT; + goto err_free; + } + + nand->mem = request_mem_region(nand->mem->start, resource_size(nand->mem), + pdev->name); + + if (!nand->mem) { + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + ret = -EBUSY; + goto err_free; + } + + nand->base = ioremap(nand->mem->start, resource_size(nand->mem)); + + if (!nand->base) { + dev_err(&pdev->dev, "Faild to ioremap mmio memory region\n"); + ret = -EBUSY; + goto err_release_mem; + } + + if (pdata && gpio_is_valid(pdata->busy_gpio)) { + ret = gpio_request(pdata->busy_gpio, "jz nand busy line"); + if (ret) { + dev_err(&pdev->dev, "Failed to request busy gpio %d: %d\n", + pdata->busy_gpio, ret); + goto err_iounmap; + } + } + + mtd = &nand->mtd; + chip = &nand->chip; + mtd->priv = chip; + mtd->owner = THIS_MODULE; + mtd->name = "jz4740-nand"; + + chip->ecc.hwctl = jz_nand_hwctl; + + chip->ecc.calculate = jz_nand_calculate_ecc_rs; + chip->ecc.correct = jz_nand_correct_ecc_rs; + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = 512; + chip->ecc.bytes = 9; + if (pdata) + chip->ecc.layout = pdata->ecc_layout; + + chip->chip_delay = 50; + chip->cmd_ctrl = jz_nand_cmd_ctrl; + + if (pdata && gpio_is_valid(pdata->busy_gpio)) + chip->dev_ready = jz_nand_dev_ready; + + chip->IO_ADDR_R = JZ_NAND_DATA_ADDR; + chip->IO_ADDR_W = JZ_NAND_DATA_ADDR; + + nand->pdata = pdata; + platform_set_drvdata(pdev, nand); + + ret = nand_scan(mtd, 1); + if (ret) { + dev_err(&pdev->dev, "Failed to scan nand\n"); + goto err_gpio_free; + } +#ifdef CONFIG_MTD_PARTITIONS +#ifdef CONFIG_MTD_CMDLINE_PARTS + num_partitions = parse_mtd_partitions(mtd, part_probes, + &partition_info, 0); + if (num_partitions <= 0 && pdata) { + num_partitions = pdata->num_partitions; + partition_info = pdata->partitions; + } +#else + if (pdata) { + num_partitions = pdata->num_partitions; + partition_info = pdata->partitions; + } +#endif + + if (num_partitions > 0) + ret = add_mtd_partitions(mtd, partition_info, num_partitions); + else +#endif + ret = add_mtd_device(mtd); + + if (ret) { + dev_err(&pdev->dev, "Failed to add mtd device\n"); + goto err_nand_release; + } + + dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n"); + + return 0; +err_nand_release: + nand_release(&nand->mtd); +err_gpio_free: + platform_set_drvdata(pdev, NULL); + gpio_free(pdata->busy_gpio); +err_iounmap: + iounmap(nand->base); +err_release_mem: + release_mem_region(nand->mem->start, resource_size(nand->mem)); +err_free: + kfree(nand); + return ret; +} + +static void __devexit jz_nand_remove(struct platform_device *pdev) +{ + struct jz_nand *nand = platform_get_drvdata(pdev); + + nand_release(&nand->mtd); + + iounmap(nand->base); + + release_mem_region(nand->mem->start, resource_size(nand->mem)); + + platform_set_drvdata(pdev, NULL); + kfree(nand); +} + +struct platform_driver jz_nand_driver = { + .probe = jz_nand_probe, + .remove = __devexit_p(jz_nand_probe), + .driver = { + .name = "jz4740-nand", + .owner = THIS_MODULE, + }, +}; + +static int __init jz_nand_init(void) +{ + return platform_driver_register(&jz_nand_driver); +} +module_init(jz_nand_init); + +static void __exit jz_nand_exit(void) +{ + platform_driver_unregister(&jz_nand_driver); +} +module_exit(jz_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("NAND controller driver for JZ4720/JZ4740 SoC"); +MODULE_ALIAS("platform:jz4740-nand"); +MODULE_ALIAS("platform:jz4720-nand"); diff --git a/target/linux/xburst/files-2.6.31/drivers/power/jz_battery.c b/target/linux/xburst/files-2.6.31/drivers/power/jz_battery.c new file mode 100755 index 000000000..80b37472e --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/power/jz_battery.c @@ -0,0 +1,298 @@ +/* + * linux/drivers/power/jz_battery + * + * Battery measurement code for Ingenic JZ SOC. + * + * based on tosa_battery.c + * + * Copyright (C) 2008 Marek Vasut + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_POWER_SUPPLY_DEBUG +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) while(0){} +#endif + +#define JZ_BAT_MAX_VOLTAGE 4200000 // uV +#define JZ_BAT_MIN_VOLTAGE 3600000 + +static DEFINE_MUTEX(bat_lock); +struct workqueue_struct *monitor_wqueue; +struct delayed_work bat_work; +struct mutex work_lock; + +int bat_status = POWER_SUPPLY_STATUS_DISCHARGING; + +extern unsigned int jz_read_battery(void); + + +/********************************************************************* + * Power + *********************************************************************/ + +static int jz_get_power_prop(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + if (psy->type == POWER_SUPPLY_TYPE_MAINS) + val->intval = !__gpio_get_pin(GPIO_DC_DETE_N); + else + val->intval = __gpio_get_pin(GPIO_USB_DETE); + break; + default: + return -EINVAL; + } + + return 0; +} + +static enum power_supply_property jz_power_props[] = { + POWER_SUPPLY_PROP_ONLINE, +}; + +static struct power_supply jz_ac = { + .name = "ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = jz_power_props, + .num_properties = ARRAY_SIZE(jz_power_props), + .get_property = jz_get_power_prop, +}; + +static struct power_supply jz_usb = { + .name = "usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = jz_power_props, + .num_properties = ARRAY_SIZE(jz_power_props), + .get_property = jz_get_power_prop, +}; + + +/********************************************************************* + * Battery properties + *********************************************************************/ + +static unsigned long jz_read_bat(struct power_supply *bat_ps) +{ + unsigned long val; + if (CFG_PBAT_DIV == 1) + val = (((unsigned long long)jz_read_battery() * 7500000)) >> 12; + else + val = (((unsigned long long)jz_read_battery() * CFG_PBAT_DIV * 2500000)) >> 12; + dprintk("--raw_batter_vol=%d uV\n", val); + return val; +} + +static int jz_bat_get_property(struct power_supply *bat_ps, + enum power_supply_property psp, + union power_supply_propval *val) +{ + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = bat_status; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case POWER_SUPPLY_PROP_HEALTH: + if(jz_read_bat(bat_ps) < 3600000) { + dprintk("--battery dead\n"); + val->intval = POWER_SUPPLY_HEALTH_DEAD; + } else { + dprintk("--battery good\n"); + val->intval = POWER_SUPPLY_HEALTH_GOOD; + } + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = (jz_read_bat(bat_ps) - 3600000) * 100 / (4200000 - 3600000); + if (val->intval > 100) + val->intval = 100; + dprintk("--battery_capacity=%d\%\n",val->intval); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = jz_read_bat(bat_ps); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = JZ_BAT_MAX_VOLTAGE; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = JZ_BAT_MIN_VOLTAGE; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 1; + break; + case POWER_SUPPLY_PROP_TEMP: + case POWER_SUPPLY_PROP_VOL: + val->intval = 0; // reading TEMP and VOL aren't supported + break; + default: + return -EINVAL; + } + return 0; +} + +static void jz_bat_external_power_changed(struct power_supply *bat_ps) +{ + cancel_delayed_work(&bat_work); + queue_delayed_work(monitor_wqueue, &bat_work, HZ/10); +} + +static char *status_text[] = { + [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown", + [POWER_SUPPLY_STATUS_CHARGING] = "Charging", + [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging", + [POWER_SUPPLY_STATUS_NOT_CHARGING] = "Not charging", +}; + +static void jz_bat_update(struct power_supply *bat_ps) +{ + int old_status = bat_status; + static unsigned long old_batt_vol = 0; + unsigned long batt_vol = jz_read_bat(bat_ps); + mutex_lock(&work_lock); + + if(!__gpio_get_pin(GPIO_CHARG_STAT_N)) + bat_status = POWER_SUPPLY_STATUS_CHARGING; + else { + bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + } + + dprintk("--battery status=%s\n", status_text[bat_status]); + if ((old_status != bat_status) || + (old_batt_vol - batt_vol > 50000)) { + pr_debug("%s %s -> %s\n", bat_ps->name, + status_text[old_status], + status_text[bat_status]); + power_supply_changed(bat_ps); + } + + old_batt_vol = batt_vol; + mutex_unlock(&work_lock); +} + +static enum power_supply_property jz_bat_main_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOL, +}; + +struct power_supply bat_ps = { + .name = "battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = jz_bat_main_props, + .num_properties = ARRAY_SIZE(jz_bat_main_props), + .get_property = jz_bat_get_property, + .external_power_changed = jz_bat_external_power_changed, + .use_for_apm = 1, +}; + +static void jz_bat_work(struct work_struct *work) +{ + const int interval = HZ * 6; + + jz_bat_update(&bat_ps); + queue_delayed_work(monitor_wqueue, &bat_work, interval); +} + +#ifdef CONFIG_PM +static int jz_bat_suspend(struct platform_device *dev, pm_message_t state) +{ + bat_status = POWER_SUPPLY_STATUS_UNKNOWN; + + return 0; +} + +static int jz_bat_resume(struct platform_device *dev) +{ + bat_status = POWER_SUPPLY_STATUS_UNKNOWN; + cancel_delayed_work(&bat_work); + queue_delayed_work(monitor_wqueue, &bat_work, HZ/10); + + return 0; +} +#else +#define jz_bat_suspend NULL +#define jz_bat_resume NULL +#endif + +static int __devinit jz_bat_probe(struct platform_device *dev) +{ + int ret = 0; + printk("JZ battery init.\n"); + mutex_init(&work_lock); + + INIT_DELAYED_WORK(&bat_work, jz_bat_work); + + __gpio_disable_pull(GPIO_USB_DETE); + + power_supply_register(&dev->dev, &jz_ac); + power_supply_register(&dev->dev, &jz_usb); + + ret = power_supply_register(&dev->dev, &bat_ps); + if (!ret) { + monitor_wqueue = create_singlethread_workqueue("jz_battery"); + if (!monitor_wqueue) { + return -ESRCH; + } + queue_delayed_work(monitor_wqueue, &bat_work, HZ * 1); + } + + return ret; +} + +static int __devexit jz_bat_remove(struct platform_device *dev) +{ + power_supply_unregister(&bat_ps); + return 0; +} + +static struct platform_driver jz_bat_driver = { + .driver.name = "jz-battery", + .driver.owner = THIS_MODULE, + .probe = jz_bat_probe, + .remove = __devexit_p(jz_bat_remove), + .suspend = jz_bat_suspend, + .resume = jz_bat_resume, +}; + +static int __init jz_bat_init(void) +{ + platform_device_register_simple("jz-battery", 0, NULL, 0); + return platform_driver_register(&jz_bat_driver); +} + +static void __exit jz_bat_exit(void) +{ + platform_driver_unregister(&jz_bat_driver); +} + +module_init(jz_bat_init); +module_exit(jz_bat_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marek Vasut "); +MODULE_DESCRIPTION("Palm T|X battery driver"); diff --git a/target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.c b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.c new file mode 100755 index 000000000..4946ae8cc --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.c @@ -0,0 +1,2297 @@ +/* + * linux/drivers/usb/gadget/jz4740_udc.c + * + * Ingenic JZ4740 on-chip high speed USB device controller + * + * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* + * This device has ep0, two bulk-in/interrupt-in endpoints, and one bulk-out endpoint. + * + * - Endpoint numbering is fixed: ep0, ep1in-int, ep2in-bulk, ep1out-bulk. + * - DMA works with bulk-in (channel 1) and bulk-out (channel 2) endpoints. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "jz4740_udc.h" + +#include "udc_hotplug.h" + +//#define DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) +//#define DEBUG(fmt,args...) printk(fmt , ## args) +//#define DEBUG_EP0(fmt,args...) printk(fmt , ## args) +//#define DEBUG_SETUP(fmt,args...) printk(fmt , ## args) + +#ifndef DEBUG +# define DEBUG(fmt,args...) do {} while(0) +#endif +#ifndef DEBUG_EP0 +# define NO_STATES +# define DEBUG_EP0(fmt,args...) do {} while(0) +#endif +#ifndef DEBUG_SETUP +# define DEBUG_SETUP(fmt,args...) do {} while(0) +#endif + +static unsigned int udc_debug = 0; /* 0: normal mode, 1: test udc cable type mode */ + +module_param(udc_debug, int, 0); +MODULE_PARM_DESC(udc_debug, "test udc cable or power type"); + +static unsigned int use_dma = 1; /* 1: use DMA, 0: use PIO */ + +module_param(use_dma, int, 0); +MODULE_PARM_DESC(use_dma, "DMA mode enable flag"); + +/* + * Local definintions. + */ + +#define DRIVER_VERSION "13-Mar-2008" +#define DRIVER_DESC "JZ4740 USB Device Controller" + +static const char gadget_name [] = "ingenic_hsusb"; + +struct jz4740_udc *the_controller; + +static const char driver_name [] = "ingenic_hsusb"; +static const char driver_desc [] = DRIVER_DESC; +static const char ep0name[] = "ep0"; + +#ifndef NO_STATES +static char *state_names[] = { + "WAIT_FOR_SETUP", + "DATA_STATE_XMIT", + "DATA_STATE_NEED_ZLP", + "WAIT_FOR_OUT_STATUS", + "DATA_STATE_RECV" +}; +#endif + +/* + * Local declarations. + */ +static int jz4740_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc); +static int jz4740_ep_disable(struct usb_ep *_ep); +static struct usb_request *jz4740_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags); +static void jz4740_free_request(struct usb_ep *_ep, struct usb_request *_req); + +static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags); +static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req); +static int jz4740_set_halt(struct usb_ep *_ep, int value); +static int jz4740_fifo_status(struct usb_ep *_ep); +static void jz4740_fifo_flush(struct usb_ep *_ep); + +static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep); +static void jz4740_handle_ep0(struct jz4740_udc *dev, u32 intr); + +static void done(struct jz4740_ep *ep, struct jz4740_request *req, + int status); +static void pio_irq_enable(struct jz4740_ep *ep); +static void pio_irq_disable(struct jz4740_ep *ep); +static void stop_activity(struct jz4740_udc *dev, + struct usb_gadget_driver *driver); +static void nuke(struct jz4740_ep *ep, int status); +static void flush(struct jz4740_ep *ep); +static void udc_enable(struct jz4740_udc *dev); +static void udc_set_address(struct jz4740_udc *dev, unsigned char address); +static void jz4740_udc_release (struct device *dev) {} + +extern void *dma_alloc_noncoherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); +extern void dma_free_noncoherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +static struct usb_ep_ops jz4740_ep_ops = { + .enable = jz4740_ep_enable, + .disable = jz4740_ep_disable, + + .alloc_request = jz4740_alloc_request, + .free_request = jz4740_free_request, + + .queue = jz4740_queue, + .dequeue = jz4740_dequeue, + + .set_halt = jz4740_set_halt, + .fifo_status = jz4740_fifo_status, + .fifo_flush = jz4740_fifo_flush, + +}; + +/*-------------------------------------------------------------------------*/ + +/* inline functions of register read/write/set/clear */ + +static __inline__ u8 usb_readb(u32 port) +{ + return *(volatile u8 *)port; +} + +static __inline__ u16 usb_readw(u32 port) +{ + return *(volatile u16 *)port; +} + +static __inline__ u32 usb_readl(u32 port) +{ + return *(volatile u32 *)port; +} + +static __inline__ void usb_writeb(u32 port, u8 val) +{ + *(volatile u8 *)port = val; +} + +static __inline__ void usb_writew(u32 port, u16 val) +{ + *(volatile u16 *)port = val; +} + +static __inline__ void usb_writel(u32 port, u32 val) +{ + *(volatile u32 *)port = val; +} + +static __inline__ void usb_setb(u32 port, u8 val) +{ + volatile u8 *ioport = (volatile u8 *)(port); + *ioport = (*ioport) | val; +} + +static __inline__ void usb_setw(u32 port, u16 val) +{ + volatile u16 *ioport = (volatile u16 *)(port); + *ioport = (*ioport) | val; +} + +static __inline__ void usb_setl(u32 port, u32 val) +{ + volatile u32 *ioport = (volatile u32 *)(port); + *ioport = (*ioport) | val; +} + +static __inline__ void usb_clearb(u32 port, u8 val) +{ + volatile u8 *ioport = (volatile u8 *)(port); + *ioport = (*ioport) & ~val; +} + +static __inline__ void usb_clearw(u32 port, u16 val) +{ + volatile u16 *ioport = (volatile u16 *)(port); + *ioport = (*ioport) & ~val; +} + +static __inline__ void usb_clearl(u32 port, u32 val) +{ + volatile u32 *ioport = (volatile u32 *)(port); + *ioport = (*ioport) & ~val; +} + +/*-------------------------------------------------------------------------*/ + +static __inline__ int write_packet(struct jz4740_ep *ep, + struct jz4740_request *req, int max) +{ + u8 *buf; + int length, nlong, nbyte; + volatile u32 *fifo = (volatile u32 *)ep->fifo; + + buf = req->req.buf + req->req.actual; + prefetch(buf); + + length = req->req.length - req->req.actual; + length = min(length, max); + req->req.actual += length; + + DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo); + + nlong = length >> 2; + nbyte = length & 0x3; + while (nlong--) { + *fifo = *((u32 *)buf); + buf += 4; + } + while (nbyte--) { + *((volatile u8 *)fifo) = *buf++; + } + + return length; +} + +static __inline__ int read_packet(struct jz4740_ep *ep, + struct jz4740_request *req, int count) +{ + u8 *buf; + int length, nlong, nbyte; + volatile u32 *fifo = (volatile u32 *)ep->fifo; + + buf = req->req.buf + req->req.actual; + prefetchw(buf); + + length = req->req.length - req->req.actual; + length = min(length, count); + req->req.actual += length; + + DEBUG("Read %d, fifo %p\n", length, fifo); + + nlong = length >> 2; + nbyte = length & 0x3; + while (nlong--) { + *((u32 *)buf) = *fifo; + buf += 4; + } + while (nbyte--) { + *buf++ = *((volatile u8 *)fifo); + } + + return length; +} + +/*-------------------------------------------------------------------------*/ + +/* + * udc_disable - disable USB device controller + */ +static void udc_disable(struct jz4740_udc *dev) +{ + DEBUG("%s, %p\n", __FUNCTION__, dev); + +#if 0 + /* UDC state is incorrect. - Added by River */ + if (dev->state != UDC_STATE_DISABLE) + return; +#endif + udc_set_address(dev, 0); + + /* Disable interrupts */ + usb_writew(USB_REG_INTRINE, 0); + usb_writew(USB_REG_INTROUTE, 0); + usb_writeb(USB_REG_INTRUSBE, 0); + + /* Disable DMA */ + usb_writel(USB_REG_CNTL1, 0); + usb_writel(USB_REG_CNTL2, 0); + + /* Disconnect from usb */ + usb_clearb(USB_REG_POWER, USB_POWER_SOFTCONN); + + /* Disable the USB PHY */ +#ifdef CONFIG_SOC_JZ4740 + REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; +#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) + REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE; +#endif + + dev->ep0state = WAIT_FOR_SETUP; + dev->gadget.speed = USB_SPEED_UNKNOWN; + + return; +} + +/* + * udc_reinit - initialize software state + */ +static void udc_reinit(struct jz4740_udc *dev) +{ + u32 i; + + DEBUG("%s, %p\n", __FUNCTION__, dev); + + /* device/ep0 records init */ + INIT_LIST_HEAD(&dev->gadget.ep_list); + INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); + dev->ep0state = WAIT_FOR_SETUP; + + for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { + struct jz4740_ep *ep = &dev->ep[i]; + + if (i != 0) + list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); + + INIT_LIST_HEAD(&ep->queue); + ep->desc = 0; + ep->stopped = 0; + ep->pio_irqs = 0; + } +} + +/* until it's enabled, this UDC should be completely invisible + * to any USB host. + */ +static void udc_enable(struct jz4740_udc *dev) +{ + int i; + + DEBUG("%s, %p\n", __FUNCTION__, dev); + + /* UDC state is incorrect - Added by River */ + if (dev->state != UDC_STATE_ENABLE) + return; + + dev->gadget.speed = USB_SPEED_UNKNOWN; + + /* Flush FIFO for each */ + for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { + struct jz4740_ep *ep = &dev->ep[i]; + + usb_set_index(ep_index(ep)); + flush(ep); + } + + /* Set this bit to allow the UDC entering low-power mode when + * there are no actions on the USB bus. + * UDC still works during this bit was set. + */ + __cpm_stop_udc(); + + /* Enable the USB PHY */ +#ifdef CONFIG_SOC_JZ4740 + REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; +#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) + REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE; +#endif + + /* Disable interrupts */ + usb_writew(USB_REG_INTRINE, 0); + usb_writew(USB_REG_INTROUTE, 0); + usb_writeb(USB_REG_INTRUSBE, 0); + + /* Enable interrupts */ + usb_setw(USB_REG_INTRINE, USB_INTR_EP0); + usb_setb(USB_REG_INTRUSBE, USB_INTR_RESET); + /* Don't enable rest of the interrupts */ + /* usb_setw(USB_REG_INTRINE, USB_INTR_INEP1 | USB_INTR_INEP2); + usb_setw(USB_REG_INTROUTE, USB_INTR_OUTEP1); */ + + /* Enable SUSPEND */ + /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ + + /* Enable HS Mode */ + usb_setb(USB_REG_POWER, USB_POWER_HSENAB); + + /* Let host detect UDC: + * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this + * transistor on and pull the USBDP pin HIGH. + */ + usb_setb(USB_REG_POWER, USB_POWER_SOFTCONN); + + return; +} + +/*-------------------------------------------------------------------------*/ + +/* keeping it simple: + * - one bus driver, initted first; + * - one function driver, initted second + */ + +/* + * Register entry point for the peripheral controller driver. + */ + +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + struct jz4740_udc *dev = the_controller; + int retval; + + if (!driver + || !driver->bind + || !driver->unbind || !driver->disconnect || !driver->setup) + { + printk("\n-EINVAL"); + return -EINVAL; + } + if (!dev) + { + printk("\n-ENODEV"); + return -ENODEV; + } + if (dev->driver) + { + printk("\n-EBUSY"); + return -EBUSY; + } + + /* hook up the driver */ + dev->driver = driver; + retval = driver->bind(&dev->gadget); + if (retval) { + DEBUG("%s: bind to driver %s --> error %d\n", dev->gadget.name, + driver->driver.name, retval); + dev->driver = 0; + return retval; + } + + /* then enable host detection and ep0; and we're ready + * for set_configuration as well as eventual disconnect. + */ + udc_enable(dev); + DEBUG("%s: registered gadget driver '%s'\n", dev->gadget.name, + driver->driver.name); + + return 0; +} + +EXPORT_SYMBOL(usb_gadget_register_driver); + + +static void stop_activity(struct jz4740_udc *dev, + struct usb_gadget_driver *driver) +{ + int i; + + DEBUG("%s\n", __FUNCTION__); + + /* don't disconnect drivers more than once */ + if (dev->gadget.speed == USB_SPEED_UNKNOWN) + driver = 0; + dev->gadget.speed = USB_SPEED_UNKNOWN; + + /* prevent new request submissions, kill any outstanding requests */ + for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { + struct jz4740_ep *ep = &dev->ep[i]; + + ep->stopped = 1; + + usb_set_index(ep_index(ep)); + nuke(ep, -ESHUTDOWN); + } + + /* report disconnect; the driver is already quiesced */ + if (driver) { + spin_unlock(&dev->lock); + driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } + + /* re-init driver-visible data structures */ + udc_reinit(dev); +} + + +/* + * Unregister entry point for the peripheral controller driver. + */ +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct jz4740_udc *dev = the_controller; + unsigned long flags; + + if (!dev) + return -ENODEV; + if (!driver || driver != dev->driver) + return -EINVAL; + + spin_lock_irqsave(&dev->lock, flags); + dev->driver = 0; + stop_activity(dev, driver); + spin_unlock_irqrestore(&dev->lock, flags); + + driver->unbind(&dev->gadget); + + udc_disable(dev); + + DEBUG("unregistered driver '%s'\n", driver->driver.name); + + return 0; +} + +EXPORT_SYMBOL(usb_gadget_unregister_driver); + +/*-------------------------------------------------------------------------*/ + +/* + * Starting DMA using mode 1 + */ +static void kick_dma(struct jz4740_ep *ep, struct jz4740_request *req) +{ + u32 count = req->req.length; + u32 physaddr = virt_to_phys((void *)req->req.buf); + + usb_set_index(ep_index(ep)); + if (ep_is_in(ep)) { /* Bulk-IN transfer using DMA channel 1 */ + ep->reg_addr = USB_REG_ADDR1; + + dma_cache_wback_inv((unsigned long)req->req.buf, count); + + pio_irq_enable(ep); + + usb_writeb(USB_REG_INCSRH, + USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE); + + usb_writel(USB_REG_ADDR1, physaddr); + usb_writel(USB_REG_COUNT1, count); + usb_writel(USB_REG_CNTL1, USB_CNTL_ENA | USB_CNTL_DIR_IN | USB_CNTL_MODE_1 | + USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep))); + } + else { /* Bulk-OUT transfer using DMA channel 2 */ + ep->reg_addr = USB_REG_ADDR2; + + dma_cache_wback_inv((unsigned long)req->req.buf, count); + + pio_irq_enable(ep); + + usb_setb(USB_REG_OUTCSRH, + USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); + + usb_writel(USB_REG_ADDR2, physaddr); + usb_writel(USB_REG_COUNT2, count); + usb_writel(USB_REG_CNTL2, USB_CNTL_ENA | USB_CNTL_MODE_1 | + USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep))); + } +} + +/*-------------------------------------------------------------------------*/ + +/** Write request to FIFO (max write == maxp size) + * Return: 0 = still running, 1 = completed, negative = errno + * NOTE: INDEX register must be set for EP + */ +static int write_fifo(struct jz4740_ep *ep, struct jz4740_request *req) +{ + u32 max, csr; + u32 physaddr = virt_to_phys((void *)req->req.buf); + + max = le16_to_cpu(ep->desc->wMaxPacketSize); + + if (use_dma) { + u32 dma_count; + + /* DMA interrupt generated due to the last packet loaded into the FIFO */ + + dma_count = usb_readl(ep->reg_addr) - physaddr; + req->req.actual += dma_count; + + if (dma_count % max) { + /* If the last packet is less than MAXP, set INPKTRDY manually */ + usb_setb(ep->csr, USB_INCSR_INPKTRDY); + } + + done(ep, req, 0); + if (list_empty(&ep->queue)) { + pio_irq_disable(ep); + return 1; + } + else { + /* advance the request queue */ + req = list_entry(ep->queue.next, struct jz4740_request, queue); + kick_dma(ep, req); + return 0; + } + } + + /* + * PIO mode handling starts here ... + */ + + csr = usb_readb(ep->csr); + + if (!(csr & USB_INCSR_FFNOTEMPT)) { + unsigned count; + int is_last, is_short; + + count = write_packet(ep, req, max); + usb_setb(ep->csr, USB_INCSR_INPKTRDY); + + /* last packet is usually short (or a zlp) */ + if (unlikely(count != max)) + is_last = is_short = 1; + else { + if (likely(req->req.length != req->req.actual) + || req->req.zero) + is_last = 0; + else + is_last = 1; + /* interrupt/iso maxpacket may not fill the fifo */ + is_short = unlikely(max < ep_maxpacket(ep)); + } + + DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__, + ep->ep.name, count, + is_last ? "/L" : "", is_short ? "/S" : "", + req->req.length - req->req.actual, req); + + /* requests complete when all IN data is in the FIFO */ + if (is_last) { + done(ep, req, 0); + if (list_empty(&ep->queue)) { + pio_irq_disable(ep); + } + return 1; + } + } else { + DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep)); + } + + return 0; +} + +/** Read to request from FIFO (max read == bytes in fifo) + * Return: 0 = still running, 1 = completed, negative = errno + * NOTE: INDEX register must be set for EP + */ +static int read_fifo(struct jz4740_ep *ep, struct jz4740_request *req) +{ + u32 csr; + unsigned count, is_short; + u32 physaddr = virt_to_phys((void *)req->req.buf); + + if (use_dma) { + u32 dma_count; + + /* DMA interrupt generated due to a packet less than MAXP loaded into the FIFO */ + + dma_count = usb_readl(ep->reg_addr) - physaddr; + req->req.actual += dma_count; + + /* Disable interrupt and DMA */ + pio_irq_disable(ep); + usb_writel(USB_REG_CNTL2, 0); + + /* Read all bytes from this packet */ + count = usb_readw(USB_REG_OUTCOUNT); + count = read_packet(ep, req, count); + + if (count) { + /* If the last packet is greater than zero, clear OUTPKTRDY manually */ + usb_clearb(ep->csr, USB_OUTCSR_OUTPKTRDY); + } + done(ep, req, 0); + + if (!list_empty(&ep->queue)) { + /* advance the request queue */ + req = list_entry(ep->queue.next, struct jz4740_request, queue); + kick_dma(ep, req); + } + + return 1; + } + + /* + * PIO mode handling starts here ... + */ + + /* make sure there's a packet in the FIFO. */ + csr = usb_readb(ep->csr); + if (!(csr & USB_OUTCSR_OUTPKTRDY)) { + DEBUG("%s: Packet NOT ready!\n", __FUNCTION__); + return -EINVAL; + } + + /* read all bytes from this packet */ + count = usb_readw(USB_REG_OUTCOUNT); + + is_short = (count < ep->ep.maxpacket); + + count = read_packet(ep, req, count); + + DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n", + ep->ep.name, csr, count, + is_short ? "/S" : "", req, req->req.actual, req->req.length); + + /* Clear OutPktRdy */ + usb_clearb(ep->csr, USB_OUTCSR_OUTPKTRDY); + + /* completion */ + if (is_short || req->req.actual == req->req.length) { + done(ep, req, 0); + + if (list_empty(&ep->queue)) + pio_irq_disable(ep); + return 1; + } + + /* finished that packet. the next one may be waiting... */ + return 0; +} + +/* + * done - retire a request; caller blocked irqs + * INDEX register is preserved to keep same + */ +static void done(struct jz4740_ep *ep, struct jz4740_request *req, int status) +{ + unsigned int stopped = ep->stopped; + u32 index; + + DEBUG("%s, %p\n", __FUNCTION__, ep); + list_del_init(&req->queue); + + if (likely(req->req.status == -EINPROGRESS)) + req->req.status = status; + else + status = req->req.status; + + if (status && status != -ESHUTDOWN) + DEBUG("complete %s req %p stat %d len %u/%u\n", + ep->ep.name, &req->req, status, + req->req.actual, req->req.length); + + /* don't modify queue heads during completion callback */ + ep->stopped = 1; + /* Read current index (completion may modify it) */ + index = usb_readb(USB_REG_INDEX); + + spin_unlock(&ep->dev->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&ep->dev->lock); + + /* Restore index */ + usb_set_index(index); + ep->stopped = stopped; +} + +/** Enable EP interrupt */ +static void pio_irq_enable(struct jz4740_ep *ep) +{ + DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT"); + + if (ep_is_in(ep)) { + switch (ep_index(ep)) { + case 1: + usb_setw(USB_REG_INTRINE, USB_INTR_INEP1); + break; + case 2: + usb_setw(USB_REG_INTRINE, USB_INTR_INEP2); + break; + default: + DEBUG("Unknown endpoint: %d\n", ep_index(ep)); + break; + } + } + else { + switch (ep_index(ep)) { + case 1: + usb_setw(USB_REG_INTROUTE, USB_INTR_OUTEP1); + break; + default: + DEBUG("Unknown endpoint: %d\n", ep_index(ep)); + break; + } + } +} + +/** Disable EP interrupt */ +static void pio_irq_disable(struct jz4740_ep *ep) +{ + DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT"); + + if (ep_is_in(ep)) { + switch (ep_index(ep)) { + case 1: + usb_clearw(USB_REG_INTRINE, USB_INTR_INEP1); + break; + case 2: + usb_clearw(USB_REG_INTRINE, USB_INTR_INEP2); + break; + default: + DEBUG("Unknown endpoint: %d\n", ep_index(ep)); + break; + } + } + else { + switch (ep_index(ep)) { + case 1: + usb_clearw(USB_REG_INTROUTE, USB_INTR_OUTEP1); + break; + default: + DEBUG("Unknown endpoint: %d\n", ep_index(ep)); + break; + } + } +} + +/* + * nuke - dequeue ALL requests + */ +static void nuke(struct jz4740_ep *ep, int status) +{ + struct jz4740_request *req; + + DEBUG("%s, %p\n", __FUNCTION__, ep); + + /* Flush FIFO */ + flush(ep); + + /* called with irqs blocked */ + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, struct jz4740_request, queue); + done(ep, req, status); + } + + /* Disable IRQ if EP is enabled (has descriptor) */ + if (ep->desc) + pio_irq_disable(ep); +} + +/** Flush EP FIFO + * NOTE: INDEX register must be set before this call + */ +static void flush(struct jz4740_ep *ep) +{ + DEBUG("%s, %p\n", __FUNCTION__, ep); + + switch (ep->ep_type) { + case ep_control: + break; + + case ep_bulk_in: + case ep_interrupt: + usb_setb(ep->csr, USB_INCSR_FF); + break; + + case ep_bulk_out: + usb_setb(ep->csr, USB_OUTCSR_FF); + break; + } +} + +/** + * jz4740_in_epn - handle IN interrupt + */ +static void jz4740_in_epn(struct jz4740_udc *dev, u32 ep_idx, u32 intr) +{ + u32 csr; + struct jz4740_ep *ep = &dev->ep[ep_idx + 1]; + struct jz4740_request *req; + + usb_set_index(ep_index(ep)); + + csr = usb_readb(ep->csr); + DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr); + + if (csr & USB_INCSR_SENTSTALL) { + DEBUG("USB_INCSR_SENTSTALL\n"); + usb_clearb(ep->csr, USB_INCSR_SENTSTALL); + return; + } + + if (!ep->desc) { + DEBUG("%s: NO EP DESC\n", __FUNCTION__); + return; + } + + if (list_empty(&ep->queue)) + req = 0; + else + req = list_entry(ep->queue.next, struct jz4740_request, queue); + + DEBUG("req: %p\n", req); + + if (!req) + return; + + write_fifo(ep, req); +} + +/* + * Bulk OUT (recv) + */ +static void jz4740_out_epn(struct jz4740_udc *dev, u32 ep_idx, u32 intr) +{ + struct jz4740_ep *ep = &dev->ep[ep_idx]; + struct jz4740_request *req; + + DEBUG("%s: %d\n", __FUNCTION__, ep_idx); + + usb_set_index(ep_index(ep)); + if (ep->desc) { + u32 csr; + + if (use_dma) { + /* DMA starts here ... */ + if (list_empty(&ep->queue)) + req = 0; + else + req = list_entry(ep->queue.next, struct jz4740_request, queue); + + if (req) + read_fifo(ep, req); + return; + } + + /* + * PIO mode starts here ... + */ + + while ((csr = usb_readb(ep->csr)) & + (USB_OUTCSR_OUTPKTRDY | USB_OUTCSR_SENTSTALL)) { + DEBUG("%s: %x\n", __FUNCTION__, csr); + + if (csr & USB_OUTCSR_SENTSTALL) { + DEBUG("%s: stall sent, flush fifo\n", + __FUNCTION__); + /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */ + flush(ep); + } else if (csr & USB_OUTCSR_OUTPKTRDY) { + if (list_empty(&ep->queue)) + req = 0; + else + req = + list_entry(ep->queue.next, + struct jz4740_request, + queue); + + if (!req) { + DEBUG("%s: NULL REQ %d\n", + __FUNCTION__, ep_idx); + break; + } else { + read_fifo(ep, req); + } + } + } + } else { + /* Throw packet away.. */ + printk("%s: ep %p ep_indx %d No descriptor?!?\n", __FUNCTION__, ep, ep_idx); + flush(ep); + } +} + +static int jz4740_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) +{ + struct jz4740_ep *ep; + struct jz4740_udc *dev; + unsigned long flags; + u32 max, csrh = 0; + + ep = container_of(_ep, struct jz4740_ep, ep); + if (!_ep || !desc || ep->desc || _ep->name == ep0name + || desc->bDescriptorType != USB_DT_ENDPOINT + || ep->bEndpointAddress != desc->bEndpointAddress) { + DEBUG("%s, bad ep or descriptor\n", __FUNCTION__); + return -EINVAL; + } + + /* xfer types must match, except that interrupt ~= bulk */ + if (ep->bmAttributes != desc->bmAttributes + && ep->bmAttributes != USB_ENDPOINT_XFER_BULK + && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { + DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name); + return -EINVAL; + } + + dev = ep->dev; + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { + DEBUG("%s, bogus device state\n", __FUNCTION__); + return -ESHUTDOWN; + } + + max = le16_to_cpu(desc->wMaxPacketSize); + + /* Configure the endpoint */ + usb_set_index(desc->bEndpointAddress & 0x0F); + if (ep_is_in(ep)) { + usb_writew(USB_REG_INMAXP, max); + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: + csrh &= ~USB_INCSRH_ISO; + break; + case USB_ENDPOINT_XFER_ISOC: + csrh |= USB_INCSRH_ISO; + break; + } + usb_writeb(USB_REG_INCSRH, csrh); + } + else { + usb_writew(USB_REG_OUTMAXP, max); + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: + csrh &= ~USB_OUTCSRH_ISO; + break; + case USB_ENDPOINT_XFER_INT: + csrh &= ~USB_OUTCSRH_ISO; + csrh |= USB_OUTCSRH_DNYT; + break; + case USB_ENDPOINT_XFER_ISOC: + csrh |= USB_OUTCSRH_ISO; + break; + } + usb_writeb(USB_REG_OUTCSRH, csrh); + } + + spin_lock_irqsave(&ep->dev->lock, flags); + + ep->stopped = 0; + ep->desc = desc; + ep->pio_irqs = 0; + ep->ep.maxpacket = max; + + spin_unlock_irqrestore(&ep->dev->lock, flags); + + /* Reset halt state (does flush) */ + jz4740_set_halt(_ep, 0); + + DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name); + + return 0; +} + +/** Disable EP + * NOTE: Sets INDEX register + */ +static int jz4740_ep_disable(struct usb_ep *_ep) +{ + struct jz4740_ep *ep; + unsigned long flags; + + DEBUG("%s, %p\n", __FUNCTION__, _ep); + + ep = container_of(_ep, struct jz4740_ep, ep); + if (!_ep || !ep->desc) { + DEBUG("%s, %s not enabled\n", __FUNCTION__, + _ep ? ep->ep.name : NULL); + return -EINVAL; + } + + spin_lock_irqsave(&ep->dev->lock, flags); + + usb_set_index(ep_index(ep)); + + /* Nuke all pending requests (does flush) */ + nuke(ep, -ESHUTDOWN); + + /* Disable ep IRQ */ + pio_irq_disable(ep); + + ep->desc = 0; + ep->stopped = 1; + + spin_unlock_irqrestore(&ep->dev->lock, flags); + + DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name); + return 0; +} + +static struct usb_request *jz4740_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) +{ + struct jz4740_request *req; + + DEBUG("%s, %p\n", __FUNCTION__, ep); + + req = kzalloc(sizeof(*req), gfp_flags); + if (!req) + return 0; + + INIT_LIST_HEAD(&req->queue); + + return &req->req; +} + +static void jz4740_free_request(struct usb_ep *ep, struct usb_request *_req) +{ + struct jz4740_request *req; + + DEBUG("%s, %p\n", __FUNCTION__, ep); + + req = container_of(_req, struct jz4740_request, req); + WARN_ON(!list_empty(&req->queue)); + kfree(req); +} + +/*--------------------------------------------------------------------*/ + +/** Queue one request + * Kickstart transfer if needed + * NOTE: Sets INDEX register + */ +static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req, + gfp_t gfp_flags) +{ + struct jz4740_request *req; + struct jz4740_ep *ep; + struct jz4740_udc *dev; + unsigned long flags; + + DEBUG("%s, %p\n", __FUNCTION__, _ep); + + req = container_of(_req, struct jz4740_request, req); + if (unlikely + (!_req || !_req->complete || !_req->buf + || !list_empty(&req->queue))) { + DEBUG("%s, bad params\n", __FUNCTION__); + return -EINVAL; + } + + ep = container_of(_ep, struct jz4740_ep, ep); + if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { + DEBUG("%s, bad ep\n", __FUNCTION__); + return -EINVAL; + } + + dev = ep->dev; + if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { + DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver); + return -ESHUTDOWN; + } + + DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, + _req->buf); + + spin_lock_irqsave(&dev->lock, flags); + + _req->status = -EINPROGRESS; + _req->actual = 0; + + /* kickstart this i/o queue? */ + DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue), + ep->stopped); + if (list_empty(&ep->queue) && likely(!ep->stopped)) { + u32 csr; + + if (unlikely(ep_index(ep) == 0)) { + /* EP0 */ + list_add_tail(&req->queue, &ep->queue); + jz4740_ep0_kick(dev, ep); + req = 0; + } else if (use_dma) { + /* DMA */ + kick_dma(ep, req); + } + /* PIO */ + else if (ep_is_in(ep)) { + /* EP1 & EP2 */ + usb_set_index(ep_index(ep)); + csr = usb_readb(ep->csr); + pio_irq_enable(ep); + if (!(csr & USB_INCSR_FFNOTEMPT)) { + if (write_fifo(ep, req) == 1) + req = 0; + } + } else { + /* EP1 */ + usb_set_index(ep_index(ep)); + csr = usb_readb(ep->csr); + pio_irq_enable(ep); + if (csr & USB_OUTCSR_OUTPKTRDY) { + if (read_fifo(ep, req) == 1) + req = 0; + } + } + } + + /* pio or dma irq handler advances the queue. */ + if (likely(req != 0)) + list_add_tail(&req->queue, &ep->queue); + + spin_unlock_irqrestore(&dev->lock, flags); + + return 0; +} + +/* dequeue JUST ONE request */ +static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct jz4740_ep *ep; + struct jz4740_request *req; + unsigned long flags; + + DEBUG("%s, %p\n", __FUNCTION__, _ep); + + ep = container_of(_ep, struct jz4740_ep, ep); + if (!_ep || ep->ep.name == ep0name) + return -EINVAL; + + spin_lock_irqsave(&ep->dev->lock, flags); + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) { + spin_unlock_irqrestore(&ep->dev->lock, flags); + return -EINVAL; + } + done(ep, req, -ECONNRESET); + + spin_unlock_irqrestore(&ep->dev->lock, flags); + return 0; +} + +/** Halt specific EP + * Return 0 if success + * NOTE: Sets INDEX register to EP ! + */ +static int jz4740_set_halt(struct usb_ep *_ep, int value) +{ + struct jz4740_ep *ep; + unsigned long flags; + + ep = container_of(_ep, struct jz4740_ep, ep); + if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { + DEBUG("%s, bad ep\n", __FUNCTION__); + return -EINVAL; + } + + usb_set_index(ep_index(ep)); + + DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value); + + spin_lock_irqsave(&ep->dev->lock, flags); + + if (ep_index(ep) == 0) { + /* EP0 */ + usb_setb(USB_REG_CSR0, USB_CSR0_SENDSTALL); + } else if (ep_is_in(ep)) { + u32 csr = usb_readb(ep->csr); + if (value && ((csr & USB_INCSR_FFNOTEMPT) + || !list_empty(&ep->queue))) { + /* + * Attempts to halt IN endpoints will fail (returning -EAGAIN) + * if any transfer requests are still queued, or if the controller + * FIFO still holds bytes that the host hasnÂ’t collected. + */ + spin_unlock_irqrestore(&ep->dev->lock, flags); + DEBUG + ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n", + (csr & USB_INCSR_FFNOTEMPT), + !list_empty(&ep->queue)); + return -EAGAIN; + } + flush(ep); + if (value) { + usb_setb(ep->csr, USB_INCSR_SENDSTALL); + } + else { + usb_clearb(ep->csr, USB_INCSR_SENDSTALL); + usb_setb(ep->csr, USB_INCSR_CDT); + } + } else { + + flush(ep); + if (value) { + usb_setb(ep->csr, USB_OUTCSR_SENDSTALL); + } + else { + usb_clearb(ep->csr, USB_OUTCSR_SENDSTALL); + usb_setb(ep->csr, USB_OUTCSR_CDT); + } + } + + if (value) { + ep->stopped = 1; + } else { + ep->stopped = 0; + } + + spin_unlock_irqrestore(&ep->dev->lock, flags); + + DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS"); + + return 0; +} + +/** Return bytes in EP FIFO + * NOTE: Sets INDEX register to EP + */ +static int jz4740_fifo_status(struct usb_ep *_ep) +{ + u32 csr; + int count = 0; + struct jz4740_ep *ep; + + ep = container_of(_ep, struct jz4740_ep, ep); + if (!_ep) { + DEBUG("%s, bad ep\n", __FUNCTION__); + return -ENODEV; + } + + DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep)); + + /* LPD can't report unclaimed bytes from IN fifos */ + if (ep_is_in(ep)) + return -EOPNOTSUPP; + + usb_set_index(ep_index(ep)); + + csr = usb_readb(ep->csr); + if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN || + csr & 0x1) { + count = usb_readw(USB_REG_OUTCOUNT); + } + + return count; +} + +/** Flush EP FIFO + * NOTE: Sets INDEX register to EP + */ +static void jz4740_fifo_flush(struct usb_ep *_ep) +{ + struct jz4740_ep *ep; + + ep = container_of(_ep, struct jz4740_ep, ep); + if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { + DEBUG("%s, bad ep\n", __FUNCTION__); + return; + } + + usb_set_index(ep_index(ep)); + flush(ep); +} + +/****************************************************************/ +/* End Point 0 related functions */ +/****************************************************************/ + +/* return: 0 = still running, 1 = completed, negative = errno */ +static int write_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req) +{ + u32 max; + unsigned count; + int is_last; + + max = ep_maxpacket(ep); + + count = write_packet(ep, req, max); + + /* last packet is usually short (or a zlp) */ + if (unlikely(count != max)) + is_last = 1; + else { + if (likely(req->req.length != req->req.actual) || req->req.zero) + is_last = 0; + else + is_last = 1; + } + + DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__, + ep->ep.name, count, + is_last ? "/L" : "", req->req.length - req->req.actual, req); + + /* requests complete when all IN data is in the FIFO */ + if (is_last) { + done(ep, req, 0); + return 1; + } + + return 0; +} + +static __inline__ int jz4740_fifo_read(struct jz4740_ep *ep, + unsigned char *cp, int max) +{ + int bytes; + int count = usb_readw(USB_REG_OUTCOUNT); + volatile u8 *fifo = (volatile u8 *)ep->fifo; + + if (count > max) + count = max; + bytes = count; + while (count--) + *cp++ = *fifo; + return bytes; +} + +static __inline__ void jz4740_fifo_write(struct jz4740_ep *ep, + unsigned char *cp, int count) +{ + volatile u8 *fifo = (volatile u8 *)ep->fifo; + DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count); + while (count--) + *fifo = *cp++; +} + +static int read_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req) +{ + u32 csr; + u8 *buf; + unsigned bufferspace, count, is_short; + volatile u8 *fifo = (volatile u8 *)ep->fifo; + + DEBUG_EP0("%s\n", __FUNCTION__); + + csr = usb_readb(USB_REG_CSR0); + if (!(csr & USB_CSR0_OUTPKTRDY)) + return 0; + + buf = req->req.buf + req->req.actual; + prefetchw(buf); + bufferspace = req->req.length - req->req.actual; + + /* read all bytes from this packet */ + if (likely(csr & USB_CSR0_OUTPKTRDY)) { + count = usb_readw(USB_REG_OUTCOUNT); + req->req.actual += min(count, bufferspace); + } else /* zlp */ + count = 0; + + is_short = (count < ep->ep.maxpacket); + DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n", + ep->ep.name, csr, count, + is_short ? "/S" : "", req, req->req.actual, req->req.length); + + while (likely(count-- != 0)) { + u8 byte = (u8) (*fifo & 0xff); + + if (unlikely(bufferspace == 0)) { + /* this happens when the driver's buffer + * is smaller than what the host sent. + * discard the extra data. + */ + if (req->req.status != -EOVERFLOW) + DEBUG_EP0("%s overflow %d\n", ep->ep.name, + count); + req->req.status = -EOVERFLOW; + } else { + *buf++ = byte; + bufferspace--; + } + } + + /* completion */ + if (is_short || req->req.actual == req->req.length) { + done(ep, req, 0); + return 1; + } + + /* finished that packet. the next one may be waiting... */ + return 0; +} + +/** + * udc_set_address - set the USB address for this device + * @address: + * + * Called from control endpoint function after it decodes a set address setup packet. + */ +static void udc_set_address(struct jz4740_udc *dev, unsigned char address) +{ + DEBUG_EP0("%s: %d\n", __FUNCTION__, address); + + dev->usb_address = address; + usb_writeb(USB_REG_FADDR, address); +} + +/* + * DATA_STATE_RECV (USB_CSR0_OUTPKTRDY) + * - if error + * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits + * - else + * set USB_CSR0_SVDOUTPKTRDY bit + if last set USB_CSR0_DATAEND bit + */ +static void jz4740_ep0_out(struct jz4740_udc *dev, u32 csr) +{ + struct jz4740_request *req; + struct jz4740_ep *ep = &dev->ep[0]; + int ret; + + DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); + + if (list_empty(&ep->queue)) + req = 0; + else + req = list_entry(ep->queue.next, struct jz4740_request, queue); + + if (req) { + if (req->req.length == 0) { + DEBUG_EP0("ZERO LENGTH OUT!\n"); +/* usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); */ + usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY)); + dev->ep0state = WAIT_FOR_SETUP; + return; + } + ret = read_fifo_ep0(ep, req); + if (ret) { + /* Done! */ + DEBUG_EP0("%s: finished, waiting for status\n", + __FUNCTION__); + usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); + dev->ep0state = WAIT_FOR_SETUP; + } else { + /* Not done yet.. */ + DEBUG_EP0("%s: not finished\n", __FUNCTION__); + usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); + } + } else { + DEBUG_EP0("NO REQ??!\n"); + } +} + +/* + * DATA_STATE_XMIT + */ +static int jz4740_ep0_in(struct jz4740_udc *dev, u32 csr) +{ + struct jz4740_request *req; + struct jz4740_ep *ep = &dev->ep[0]; + int ret, need_zlp = 0; + + DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); + + if (list_empty(&ep->queue)) + req = 0; + else + req = list_entry(ep->queue.next, struct jz4740_request, queue); + + if (!req) { + DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__); + return 0; + } + + if (req->req.length == 0) { + usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); + dev->ep0state = WAIT_FOR_SETUP; + return 1; + } + + if (req->req.length - req->req.actual == EP0_MAXPACKETSIZE) { + /* Next write will end with the packet size, */ + /* so we need zero-length-packet */ + need_zlp = 1; + } + + ret = write_fifo_ep0(ep, req); + + if (ret == 1 && !need_zlp) { + /* Last packet */ + DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__); + + usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); + dev->ep0state = WAIT_FOR_SETUP; + } else { + DEBUG_EP0("%s: not finished\n", __FUNCTION__); + usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); + } + + if (need_zlp) { + DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__); + usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); + dev->ep0state = DATA_STATE_NEED_ZLP; + } + + return 1; +} + +#if 1 +static int jz4740_handle_get_status(struct jz4740_udc *dev, + struct usb_ctrlrequest *ctrl) +{ + struct jz4740_ep *ep0 = &dev->ep[0]; + struct jz4740_ep *qep; + int reqtype = (ctrl->bRequestType & USB_RECIP_MASK); + u16 val = 0; + + if (reqtype == USB_RECIP_INTERFACE) { + /* This is not supported. + * And according to the USB spec, this one does nothing.. + * Just return 0 + */ + DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n"); + } else if (reqtype == USB_RECIP_DEVICE) { + DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n"); + val |= (1 << 0); /* Self powered */ + /*val |= (1<<1); *//* Remote wakeup */ + } else if (reqtype == USB_RECIP_ENDPOINT) { + int ep_num = (ctrl->wIndex & ~USB_DIR_IN); + + DEBUG_SETUP + ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n", + ep_num, ctrl->wLength); + + if (ctrl->wLength > 2 || ep_num > 3) + return -EOPNOTSUPP; + + qep = &dev->ep[ep_num]; + if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0) + && ep_index(qep) != 0) { + return -EOPNOTSUPP; + } + + usb_set_index(ep_index(qep)); + + /* Return status on next IN token */ + switch (qep->ep_type) { + case ep_control: + val = + (usb_readb(qep->csr) & USB_CSR0_SENDSTALL) == + USB_CSR0_SENDSTALL; + break; + case ep_bulk_in: + case ep_interrupt: + val = + (usb_readb(qep->csr) & USB_INCSR_SENDSTALL) == + USB_INCSR_SENDSTALL; + break; + case ep_bulk_out: + val = + (usb_readb(qep->csr) & USB_OUTCSR_SENDSTALL) == + USB_OUTCSR_SENDSTALL; + break; + } + + /* Back to EP0 index */ + usb_set_index(0); + + DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num, + ctrl->wIndex, val); + } else { + DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype); + return -EOPNOTSUPP; + } + + /* Clear "out packet ready" */ + usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); + /* Put status to FIFO */ + jz4740_fifo_write(ep0, (u8 *) & val, sizeof(val)); + /* Issue "In packet ready" */ + usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); + + return 0; +} +#endif + +/* + * WAIT_FOR_SETUP (OUTPKTRDY) + * - read data packet from EP0 FIFO + * - decode command + * - if error + * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits + * - else + * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND bits + */ +static void jz4740_ep0_setup(struct jz4740_udc *dev, u32 csr) +{ + struct jz4740_ep *ep = &dev->ep[0]; + struct usb_ctrlrequest ctrl; + int i; + + DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr); + + /* Nuke all previous transfers */ + nuke(ep, -EPROTO); + + /* read control req from fifo (8 bytes) */ + jz4740_fifo_read(ep, (unsigned char *)&ctrl, 8); + + DEBUG_SETUP("SETUP %02x.%02x v%04x i%04x l%04x\n", + ctrl.bRequestType, ctrl.bRequest, + ctrl.wValue, ctrl.wIndex, ctrl.wLength); + + /* Set direction of EP0 */ + if (likely(ctrl.bRequestType & USB_DIR_IN)) { + ep->bEndpointAddress |= USB_DIR_IN; + } else { + ep->bEndpointAddress &= ~USB_DIR_IN; + } + + /* Handle some SETUP packets ourselves */ + switch (ctrl.bRequest) { + case USB_REQ_SET_ADDRESS: + if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) + break; + + DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue); + udc_set_address(dev, ctrl.wValue); + usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); + return; + + case USB_REQ_SET_CONFIGURATION: + if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) + break; + + DEBUG_SETUP("USB_REQ_SET_CONFIGURATION (%d)\n", ctrl.wValue); + usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); + + /* Enable RESUME and SUSPEND interrupts */ + usb_setb(USB_REG_INTRUSBE, (USB_INTR_RESUME | USB_INTR_SUSPEND)); + break; + + case USB_REQ_SET_INTERFACE: + if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) + break; + + DEBUG_SETUP("USB_REQ_SET_INTERFACE (%d)\n", ctrl.wValue); + usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); + break; + +#if 1 + case USB_REQ_GET_STATUS: + if (jz4740_handle_get_status(dev, &ctrl) == 0) + return; +#endif + + case USB_REQ_CLEAR_FEATURE: + case USB_REQ_SET_FEATURE: + if (ctrl.bRequestType == USB_RECIP_ENDPOINT) { + struct jz4740_ep *qep; + int ep_num = (ctrl.wIndex & 0x0f); + + /* Support only HALT feature */ + if (ctrl.wValue != 0 || ctrl.wLength != 0 + || ep_num > 3 || ep_num < 1) + break; + + qep = &dev->ep[ep_num]; + spin_unlock(&dev->lock); + if (ctrl.bRequest == USB_REQ_SET_FEATURE) { + DEBUG_SETUP("SET_FEATURE (%d)\n", + ep_num); + jz4740_set_halt(&qep->ep, 1); + } else { + DEBUG_SETUP("CLR_FEATURE (%d)\n", + ep_num); + jz4740_set_halt(&qep->ep, 0); + } + spin_lock(&dev->lock); + + usb_set_index(0); + + /* Reply with a ZLP on next IN token */ + usb_setb(USB_REG_CSR0, + (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); + return; + } + break; + + default: + break; + } + + /* gadget drivers see class/vendor specific requests, + * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION}, + * and more. + */ + if (likely((u32)dev->driver)) { + /* device-2-host (IN) or no data setup command, process immediately */ + spin_unlock(&dev->lock); + + i = dev->driver->setup(&dev->gadget, &ctrl); + spin_lock(&dev->lock); + + if (unlikely(i < 0)) { + /* setup processing failed, force stall */ + DEBUG_SETUP + (" --> ERROR: gadget setup FAILED (stalling), setup returned %d\n", + i); + usb_set_index(0); + usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL)); + + /* ep->stopped = 1; */ + dev->ep0state = WAIT_FOR_SETUP; + } + else { + DEBUG_SETUP("gadget driver setup ok (%d)\n", ctrl.wLength); + if (!ctrl.wLength) { + usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); + } + } + } +} + +/* + * DATA_STATE_NEED_ZLP + */ +static void jz4740_ep0_in_zlp(struct jz4740_udc *dev, u32 csr) +{ + DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); + + usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); + dev->ep0state = WAIT_FOR_SETUP; +} + +/* + * handle ep0 interrupt + */ +static void jz4740_handle_ep0(struct jz4740_udc *dev, u32 intr) +{ + struct jz4740_ep *ep = &dev->ep[0]; + u32 csr; + + /* Set index 0 */ + usb_set_index(0); + csr = usb_readb(USB_REG_CSR0); + + DEBUG_EP0("%s: csr = %x state = \n", __FUNCTION__, csr);//, state_names[dev->ep0state]); + + /* + * if SENT_STALL is set + * - clear the SENT_STALL bit + */ + if (csr & USB_CSR0_SENTSTALL) { + DEBUG_EP0("%s: USB_CSR0_SENTSTALL is set: %x\n", __FUNCTION__, csr); + usb_clearb(USB_REG_CSR0, USB_CSR0_SENDSTALL | USB_CSR0_SENTSTALL); + nuke(ep, -ECONNABORTED); + dev->ep0state = WAIT_FOR_SETUP; + return; + } + + /* + * if a transfer is in progress && INPKTRDY and OUTPKTRDY are clear + * - fill EP0 FIFO + * - if last packet + * - set IN_PKT_RDY | DATA_END + * - else + * set IN_PKT_RDY + */ + if (!(csr & (USB_CSR0_INPKTRDY | USB_CSR0_OUTPKTRDY))) { + DEBUG_EP0("%s: INPKTRDY and OUTPKTRDY are clear\n", + __FUNCTION__); + + switch (dev->ep0state) { + case DATA_STATE_XMIT: + DEBUG_EP0("continue with DATA_STATE_XMIT\n"); + jz4740_ep0_in(dev, csr); + return; + case DATA_STATE_NEED_ZLP: + DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n"); + jz4740_ep0_in_zlp(dev, csr); + return; + default: + /* Stall? */ +// DEBUG_EP0("Odd state!! state = %s\n", +// state_names[dev->ep0state]); + dev->ep0state = WAIT_FOR_SETUP; + /* nuke(ep, 0); */ + /* usb_setb(ep->csr, USB_CSR0_SENDSTALL); */ +// break; + return; + } + } + + /* + * if SETUPEND is set + * - abort the last transfer + * - set SERVICED_SETUP_END_BIT + */ + if (csr & USB_CSR0_SETUPEND) { + DEBUG_EP0("%s: USB_CSR0_SETUPEND is set: %x\n", __FUNCTION__, csr); + + usb_setb(USB_REG_CSR0, USB_CSR0_SVDSETUPEND); + nuke(ep, 0); + dev->ep0state = WAIT_FOR_SETUP; + } + + /* + * if USB_CSR0_OUTPKTRDY is set + * - read data packet from EP0 FIFO + * - decode command + * - if error + * set SVDOUTPKTRDY | DATAEND | SENDSTALL bits + * - else + * set SVDOUTPKTRDY | DATAEND bits + */ + if (csr & USB_CSR0_OUTPKTRDY) { + + DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__, + csr); + + switch (dev->ep0state) { + case WAIT_FOR_SETUP: + DEBUG_EP0("WAIT_FOR_SETUP\n"); + jz4740_ep0_setup(dev, csr); + break; + + case DATA_STATE_RECV: + DEBUG_EP0("DATA_STATE_RECV\n"); + jz4740_ep0_out(dev, csr); + break; + + default: + /* send stall? */ + DEBUG_EP0("strange state!! 2. send stall? state = %d\n", + dev->ep0state); + break; + } + } +} + +static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep) +{ + u32 csr; + + usb_set_index(0); + csr = usb_readb(USB_REG_CSR0); + + DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); + + /* Clear "out packet ready" */ + usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); + + if (ep_is_in(ep)) { + dev->ep0state = DATA_STATE_XMIT; + jz4740_ep0_in(dev, csr); + } else { + dev->ep0state = DATA_STATE_RECV; + jz4740_ep0_out(dev, csr); + } +} + +/** Handle USB RESET interrupt + */ +static void jz4740_reset_irq(struct jz4740_udc *dev) +{ + dev->gadget.speed = (usb_readb(USB_REG_POWER) & USB_POWER_HSMODE) ? + USB_SPEED_HIGH : USB_SPEED_FULL; + + DEBUG_SETUP("%s: address = %d, speed = %s\n", __FUNCTION__, dev->usb_address, + (dev->gadget.speed == USB_SPEED_HIGH) ? "HIGH":"FULL" ); +} + +/* + * jz4740 usb device interrupt handler. + */ +static irqreturn_t jz4740_udc_irq(int irq, void *_dev) +{ + struct jz4740_udc *dev = _dev; + + u32 intr_usb = usb_readb(USB_REG_INTRUSB) & 0x7; /* mask SOF */ + u32 intr_in = usb_readw(USB_REG_INTRIN); + u32 intr_out = usb_readw(USB_REG_INTROUT); + u32 intr_dma = usb_readb(USB_REG_INTR); + + if (!intr_usb && !intr_in && !intr_out && !intr_dma) + return IRQ_HANDLED; + + DEBUG("intr_out = %x intr_in=%x intr_usb=%x\n", + intr_out, intr_in, intr_usb); + + spin_lock(&dev->lock); + + /* Check for resume from suspend mode */ + if ((intr_usb & USB_INTR_RESUME) && + (usb_readb(USB_REG_INTRUSBE) & USB_INTR_RESUME)) { + DEBUG("USB resume\n"); + dev->driver->resume(&dev->gadget); /* We have suspend(), so we must have resume() too. */ + } + + /* Check for system interrupts */ + if (intr_usb & USB_INTR_RESET) { + DEBUG("USB reset\n"); +#ifdef CONFIG_USB_JZ_UDC_HOTPLUG + udc_hotplug_do_keep_alive(); +#endif + if (udc_debug) { + /* We have tested the cable type, disable module and + * disconnect from host right now. + */ + udc_disable(dev); + spin_unlock(&dev->lock); + return IRQ_HANDLED; + } + jz4740_reset_irq(dev); + } + + /* Check for endpoint 0 interrupt */ + if (intr_in & USB_INTR_EP0) { + DEBUG("USB_INTR_EP0 (control)\n"); + jz4740_handle_ep0(dev, intr_in); + } + + /* Check for Bulk-IN DMA interrupt */ + if (intr_dma & 0x1) { + int ep_num; + ep_num = (usb_readl(USB_REG_CNTL1) >> 4) & 0xf; + jz4740_in_epn(dev, ep_num, intr_in); + } + + /* Check for Bulk-OUT DMA interrupt */ + if (intr_dma & 0x2) { + int ep_num; + ep_num = (usb_readl(USB_REG_CNTL2) >> 4) & 0xf; + jz4740_out_epn(dev, ep_num, intr_out); + } + + /* Check for each configured endpoint interrupt */ + if (intr_in & USB_INTR_INEP1) { + DEBUG("USB_INTR_INEP1\n"); + jz4740_in_epn(dev, 1, intr_in); + } + + if (intr_in & USB_INTR_INEP2) { + DEBUG("USB_INTR_INEP2\n"); + jz4740_in_epn(dev, 2, intr_in); + } + + if (intr_out & USB_INTR_OUTEP1) { + DEBUG("USB_INTR_OUTEP1\n"); + jz4740_out_epn(dev, 1, intr_out); + } + + /* Check for suspend mode */ + if ((intr_usb & USB_INTR_SUSPEND) && + (usb_readb(USB_REG_INTRUSBE) & USB_INTR_SUSPEND)) { + DEBUG("USB suspend\n"); + dev->driver->suspend(&dev->gadget); + /* Host unloaded from us, can do something, such as flushing + the NAND block cache etc. */ + } + +#ifdef CONFIG_USB_JZ_UDC_HOTPLUG + udc_hotplug_do_keep_alive(); +#endif + + spin_unlock(&dev->lock); + return IRQ_HANDLED; +} + + + +/*-------------------------------------------------------------------------*/ + +/* Common functions - Added by River */ +static struct jz4740_udc udc_dev; + +static inline struct jz4740_udc *gadget_to_udc(struct usb_gadget *gadget) +{ + return container_of(gadget, struct jz4740_udc, gadget); +} +/* End added */ + +static int jz4740_udc_get_frame(struct usb_gadget *_gadget) +{ + DEBUG("%s, %p\n", __FUNCTION__, _gadget); + return usb_readw(USB_REG_FRAME); +} + +static int jz4740_udc_wakeup(struct usb_gadget *_gadget) +{ + /* host may not have enabled remote wakeup */ + /*if ((UDCCS0 & UDCCS0_DRWF) == 0) + return -EHOSTUNREACH; + udc_set_mask_UDCCR(UDCCR_RSM); */ + return -ENOTSUPP; +} + +static int jz4740_udc_pullup(struct usb_gadget *_gadget, int on) +{ + + struct jz4740_udc *udc = gadget_to_udc(_gadget); + + unsigned long flags; + + local_irq_save(flags); + + if (on) { + udc->state = UDC_STATE_ENABLE; + udc_enable(udc); + }else{ + udc->state = UDC_STATE_DISABLE; + udc_disable(udc); + } + + local_irq_restore(flags); + + return 0; +} + +static const struct usb_gadget_ops jz4740_udc_ops = { + .get_frame = jz4740_udc_get_frame, + .wakeup = jz4740_udc_wakeup, + .pullup = jz4740_udc_pullup, + /* current versions must always be self-powered */ +}; + +/*-------------------------------------------------------------------------*/ + +static struct jz4740_udc udc_dev = { + .usb_address = 0, + .gadget = { + .ops = &jz4740_udc_ops, + .ep0 = &udc_dev.ep[0].ep, + .name = driver_name, + .dev = { + .bus_id = "gadget", + }, + }, + + /* control endpoint */ + .ep[0] = { + .ep = { + .name = ep0name, + .ops = &jz4740_ep_ops, + .maxpacket = EP0_MAXPACKETSIZE, + }, + .dev = &udc_dev, + + .bEndpointAddress = 0, + .bmAttributes = 0, + + .ep_type = ep_control, + .fifo = USB_FIFO_EP0, + .csr = USB_REG_CSR0, + }, + + /* bulk out endpoint */ + .ep[1] = { + .ep = { + .name = "ep1out-bulk", + .ops = &jz4740_ep_ops, + .maxpacket = EPBULK_MAXPACKETSIZE, + }, + .dev = &udc_dev, + + .bEndpointAddress = 1, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + + .ep_type = ep_bulk_out, + .fifo = USB_FIFO_EP1, + .csr = USB_REG_OUTCSR, + }, + + /* bulk in endpoint */ + .ep[2] = { + .ep = { + .name = "ep1in-bulk", + .ops = &jz4740_ep_ops, + .maxpacket = EPBULK_MAXPACKETSIZE, + }, + .dev = &udc_dev, + + .bEndpointAddress = USB_DIR_IN | 1, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + + .ep_type = ep_bulk_in, + .fifo = USB_FIFO_EP1, + .csr = USB_REG_INCSR, + }, + + /* interrupt in endpoint */ + .ep[3] = { + .ep = { + .name = "ep2in-int", + .ops = &jz4740_ep_ops, + .maxpacket = EPINTR_MAXPACKETSIZE, + }, + .dev = &udc_dev, + + .bEndpointAddress = USB_DIR_IN | 2, + .bmAttributes = USB_ENDPOINT_XFER_INT, + + .ep_type = ep_interrupt, + .fifo = USB_FIFO_EP2, + .csr = USB_REG_INCSR, + }, +}; + +static int jz4740_udc_probe(struct platform_device *pdev) +{ + struct jz4740_udc *dev = &udc_dev; + int rc; + + DEBUG("%s\n", __FUNCTION__); + + spin_lock_init(&dev->lock); + the_controller = dev; + + dev->dev = &pdev->dev; +// device_initialize(&dev->gadget.dev); /* device_register() will do this. In Linux-2.6.27 re-initializing a kobject will cause a warning. */ + dev->gadget.dev.parent = &pdev->dev; + +// strcpy (dum->gadget.dev.bus_id, "gadget"); + dev->gadget.dev.release = jz4740_udc_release; + if ((rc = device_register (&dev->gadget.dev)) < 0) + return rc; + platform_set_drvdata(pdev, dev); + + udc_disable(dev); + udc_reinit(dev); + + /* irq setup */ + if (request_irq(IRQ_UDC, jz4740_udc_irq, IRQF_DISABLED,//SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, + driver_name, dev) != 0) { + printk(KERN_INFO "request UDC interrupt %d failed\n", IRQ_UDC); + return -EBUSY; + } + + printk(KERN_INFO "%s\n", driver_desc); + printk(KERN_INFO "version: " DRIVER_VERSION "\n"); + + return 0; +} + +static int jz4740_udc_remove(struct platform_device *pdev) +{ + struct jz4740_udc *dev = platform_get_drvdata(pdev); + DEBUG("%s: %p\n", __FUNCTION__, dev); + + if (dev->driver) + return -EBUSY; + + udc_disable(dev); +#ifdef UDC_PROC_FILE + remove_proc_entry(proc_node_name, NULL); +#endif + + free_irq(IRQ_UDC, dev); + platform_set_drvdata(pdev, 0); + device_unregister(&dev->gadget.dev); + the_controller = 0; + + return 0; +} + +static struct platform_driver udc_driver = { + .probe = jz4740_udc_probe, + .remove = jz4740_udc_remove, + .suspend = NULL, + .resume = NULL, + .driver = { + .name = (char *) driver_name, + .owner = THIS_MODULE, + }, +}; + + + +static struct platform_device the_udc_pdev = { + .name = (char *) gadget_name, + .id = -1, + .dev = { + .release = jz4740_udc_release, + }, +}; + + +/*-------------------------------------------------------------------------*/ + +static int __init udc_init (void) +{ + platform_driver_register(&udc_driver); + return platform_device_register (&the_udc_pdev); +} + +static void __exit udc_exit (void) +{ + platform_driver_unregister(&udc_driver); + platform_device_unregister(&the_udc_pdev); +} + +module_init(udc_init); +module_exit(udc_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Wei Jianli "); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.h b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.h new file mode 100755 index 000000000..88e04a7b9 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/jz4740_udc.h @@ -0,0 +1,121 @@ +/* + * linux/drivers/usb/gadget/jz4740_udc.h + * + * Ingenic JZ4740 on-chip high speed USB device controller + * + * Copyright (C) 2006 Ingenic Semiconductor Inc. + * Author: + * + * 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 __USB_GADGET_JZ4740_H__ +#define __USB_GADGET_JZ4740_H__ + +/*-------------------------------------------------------------------------*/ + +// Max packet size +#define EP0_MAXPACKETSIZE 64 +#define EPBULK_MAXPACKETSIZE 512 +#define EPINTR_MAXPACKETSIZE 64 + +#define UDC_MAX_ENDPOINTS 4 + +/*-------------------------------------------------------------------------*/ + +typedef enum ep_type { + ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt +} ep_type_t; + +struct jz4740_ep { + struct usb_ep ep; + struct jz4740_udc *dev; + + const struct usb_endpoint_descriptor *desc; + struct list_head queue; + unsigned long pio_irqs; + + u8 stopped; + u8 bEndpointAddress; + u8 bmAttributes; + + ep_type_t ep_type; + u32 fifo; + u32 csr; + + u32 reg_addr; +}; + +struct jz4740_request { + struct usb_request req; + struct list_head queue; +}; + +enum ep0state { + WAIT_FOR_SETUP, /* between STATUS ack and SETUP report */ + DATA_STATE_XMIT, /* data tx stage */ + DATA_STATE_NEED_ZLP, /* data tx zlp stage */ + WAIT_FOR_OUT_STATUS, /* status stages */ + DATA_STATE_RECV, /* data rx stage */ +}; + +/* For function binding with UDC Disable - Added by River */ +typedef enum { + UDC_STATE_ENABLE = 0, + UDC_STATE_DISABLE, +}udc_state_t; + +struct jz4740_udc { + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + struct device *dev; + spinlock_t lock; + + enum ep0state ep0state; + struct jz4740_ep ep[UDC_MAX_ENDPOINTS]; + + unsigned char usb_address; + + /* UDC state - Added by River */ + udc_state_t state; +}; + +extern struct jz4740_udc *the_controller; + +#define ep_is_in(EP) (((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN) +#define ep_maxpacket(EP) ((EP)->ep.maxpacket) +#define ep_index(EP) ((EP)->bEndpointAddress&0xF) +#define usb_set_index(i) (REG8(USB_REG_INDEX) = (i)) + +/*-------------------------------------------------------------------------*/ + +/* 2.5 stuff that's sometimes missing in 2.4 */ + +#ifndef container_of +#define container_of list_entry +#endif + +#ifndef likely +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +#ifndef BUG_ON +#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) +#endif + +#ifndef WARN_ON +#define WARN_ON(x) do { } while (0) +#endif + +#ifndef IRQ_NONE +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#endif /* __USB_GADGET_JZ4740_H__ */ diff --git a/target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug.h b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug.h new file mode 100644 index 000000000..b7cb81e36 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug.h @@ -0,0 +1,50 @@ +/* + * Ingenic USB Device Contoller Hotplug External Interfaces + */ + +#ifndef __UDC_HOTPLUG_H__ +#define __UDC_HOTPLUG_H__ + +#include + +typedef enum { + BROADCAST_TYPE_STATE = 0, + BROADCAST_TYPE_EVENT, +}udc_hotplug_broadcast_type_t; + +typedef enum { + EVENT_STATE_OFFLINE = 0, + EVENT_STATE_ONLINE, +}udc_hotplug_event_state_t; + +typedef enum { + EVENT_TYPE_USB = 0, + EVENT_TYPE_CABLE, +}udc_hotplug_event_type_t; + +enum { + EVENT_FLAG_UDC_PHY_TOUCHED = 0, +}; + +typedef struct { + udc_hotplug_event_type_t type; + udc_hotplug_event_state_t state; + unsigned long flags; +}udc_hotplug_event_t; + +/* Register notifier */ +int udc_hotplug_register_notifier(struct notifier_block *n, int request_state); + +/* Unregister notifier */ +int udc_hotplug_unregister_notifier(struct notifier_block *n); + +/* Start keep alive */ +int udc_hotplug_start_keep_alive(unsigned long timer_interval_in_jiffies, unsigned long counter_limit); + +/* Do keep alive */ +void udc_hotplug_do_keep_alive(void); + +/* Stop keep alive */ +void udc_hotplug_stop_keep_alive(void); + +#endif /* Define __UDC_HOTPLUG_H__ */ diff --git a/target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug_core.c b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug_core.c new file mode 100644 index 000000000..e4e324da6 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/usb/gadget/udc_hotplug_core.c @@ -0,0 +1,836 @@ +/* + * Ingenic USB Device Controller Hotplug Core Function + * Detection mechanism and code are based on the old version of udc_hotplug.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "udc_hotplug.h" + +#define PFX "jz_hotplug_udc" + +#define D(msg, fmt...) \ +// printk(KERN_ERR PFX": %s(): "msg, __func__, ##fmt); + +/* HAVE_DETECT_SYNC + Provide a lock like seqlock keep the synchronization between the start and the end of a detection, + If the lock seems not synchronous(new interrupt comes, when doing our detection) in the end of a detection, + the result of the detection is discarded. No event will be broadcast, and the detection will be restarted. + + Use to filter out more significant events when the interrupt is too noisy. +*/ + +//#define HAVE_DETECT_SYNC 1 + +#if defined (HAVE_DETECT_SYNC) +#define NR_RESTART_TIMES 3 +#define NR_JIFFIES_SLEEP_BEFORE_RESTART 7 +#endif + +#define NR_GPIO_STABLE_TIMES 50 +#define NR_JIFFIES_USB_DETECT_WAIT 11 + +#define DEFAULT_KEEP_ALIVE_TIMER_INTERVAL (2 * HZ) +#define DEFAULT_KEEP_ALIVE_COUNTER_LIMIT 2 + +#define UDC_HOTPLUG_PIN GPIO_UDC_HOTPLUG +#define UDC_HOTPLUG_IRQ (IRQ_GPIO_0 + UDC_HOTPLUG_PIN) + +/* UDC State bits */ +enum { + /* Online state. */ + BIT_CABLE_ONLINE = 0, + BIT_USB_ONLINE, + + /* State changed ?*/ + BIT_CABLE_CHANGE, + BIT_USB_CHANGE, + + /* What detection will be done ? */ + BIT_DO_CABLE_DETECT, + BIT_DO_USB_DETECT, + + /* What detection is requested ? */ + BIT_REQUEST_CABLE_DETECT, + BIT_REQUEST_USB_DETECT, + + /* Indicate whether a detection is finisned. */ + BIT_USB_DETECT_DONE, + BIT_CABLE_DETECT_DONE, + + BIT_UDC_PHY_TOUCHED, + + /* Keep alive */ + BIT_KEEP_ALIVE, + BIT_KEEP_ALIVE_TIMEOUT, +}; + +struct uh_data { + /* Notifier */ + struct blocking_notifier_head notifier_head; + + /* Thread */ + struct task_struct *kthread; + + /* Wait queue */ + wait_queue_head_t kthread_wq; /* Kernel thread sleep here. */ + wait_queue_head_t wq; /* Others sleep here. */ + + /* UDC State */ + unsigned long state; + + /* Current Event */ + udc_hotplug_event_t cur_uh_event; + +#if defined (HAVE_DETECT_SYNC) + /* Sync seq */ + unsigned long irq_sync_seq; + unsigned long our_sync_seq; +#endif + + /* Keep alive */ + struct timer_list keep_alive_timer; + + unsigned long keep_alive_counter_limit; + unsigned long keep_alive_timer_interval; + unsigned long keep_alive_counter; +}; + +static struct uh_data *g_puh_data = NULL; + +#if defined (HAVE_DETECT_SYNC) +/* Seq sync function */ + +static inline int is_seq_sync(struct uh_data *uh) +{ + return (uh->our_sync_seq == uh->irq_sync_seq); +} + +static inline void reset_seq(struct uh_data *uh) +{ + uh->our_sync_seq = uh->irq_sync_seq = 0; + + return; +} + +static inline void sync_seq(struct uh_data *uh) +{ + uh->our_sync_seq = uh->irq_sync_seq; + + return; +} +#endif + +/* Call kernel thread to detect. */ +static inline void start_detect(struct uh_data *uh) +{ + D("called.\n"); + +#if defined (HAVE_DETECT_SYNC) + uh->irq_sync_seq ++; +#endif + + wake_up_process(uh->kthread); + + return; +} + +static void wait_gpio_pin_stable(struct uh_data *uh) +{ + unsigned long pin = 0; + int i = 1; + + pin = __gpio_get_pin(UDC_HOTPLUG_PIN); + + while (i < NR_GPIO_STABLE_TIMES) { + if (__gpio_get_pin(UDC_HOTPLUG_PIN) != pin) { + pin = __gpio_get_pin(UDC_HOTPLUG_PIN); + i = 1; + }else + i++; + + sleep_on_timeout(&uh->wq, 1); + } + + return; +} + +/* Do cable detection */ +static void cable_detect(struct uh_data *uh) +{ + D("Wait pin stable.\n"); + + /* Wait GPIO pin stable first. */ + wait_gpio_pin_stable(uh); + + if (__gpio_get_pin(UDC_HOTPLUG_PIN)) { + D("Cable online.\n"); + + if (!test_and_set_bit(BIT_CABLE_ONLINE, &uh->state)) { + D("Cable state change to online.\n"); + + set_bit(BIT_CABLE_CHANGE, &uh->state); + } + }else { + D("Cable offline.\n"); + + /* Clear keep alive bit. */ + clear_bit(BIT_KEEP_ALIVE, &uh->state); + + if (test_and_clear_bit(BIT_CABLE_ONLINE, &uh->state)) { + D("Cable state change to offline.\n"); + + set_bit(BIT_CABLE_CHANGE, &uh->state); + } + } + + set_bit(BIT_CABLE_DETECT_DONE, &uh->state); + + return; +} + +/* Really do USB detection */ +static int do_usb_detect(struct uh_data *uh) +{ + u32 intr_usb; + int rv; + + D("called.\n"); + + __intc_mask_irq(IRQ_UDC); + + /* Now enable PHY to start detect */ +#ifdef CONFIG_SOC_JZ4740 + REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; +#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) + REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE; +#endif + /* Clear IRQs */ + REG16(USB_REG_INTRINE) = 0; + REG16(USB_REG_INTROUTE) = 0; + REG8(USB_REG_INTRUSBE) = 0; + + /* disable UDC IRQs first */ + REG16(USB_REG_INTRINE) = 0; + REG16(USB_REG_INTROUTE) = 0; + REG8(USB_REG_INTRUSBE) = 0; + + /* Disable DMA */ + REG32(USB_REG_CNTL1) = 0; + REG32(USB_REG_CNTL2) = 0; + + /* Enable HS Mode */ + REG8(USB_REG_POWER) |= USB_POWER_HSENAB; + /* Enable soft connect */ + REG8(USB_REG_POWER) |= USB_POWER_SOFTCONN; + + D("enable phy! %x %x %x %x %x\n", + REG8(USB_REG_POWER), + REG_CPM_OPCR, + REG16(USB_REG_INTRINE), + REG16(USB_REG_INTROUTE), + REG8(USB_REG_INTRUSBE)); + + /* Wait a moment. */ + sleep_on_timeout(&uh->wq, NR_JIFFIES_USB_DETECT_WAIT); + + intr_usb = REG8(USB_REG_INTRUSB); + if ((intr_usb & USB_INTR_RESET) || + (intr_usb & USB_INTR_RESUME) || + (intr_usb & USB_INTR_SUSPEND)) + { + rv = 1; + } + else + { + rv = 0; + } + + /* Detect finish ,clean every thing */ + /* Disconnect from usb */ + REG8(USB_REG_POWER) &= ~USB_POWER_SOFTCONN; + /* Disable the USB PHY */ +#ifdef CONFIG_SOC_JZ4740 + REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; +#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) + REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE; +#endif + /* Clear IRQs */ + REG16(USB_REG_INTRINE) = 0; + REG16(USB_REG_INTROUTE) = 0; + REG8(USB_REG_INTRUSBE) = 0; + __intc_ack_irq(IRQ_UDC); + __intc_unmask_irq(IRQ_UDC); + + mdelay(1); + + return rv; +} + +/* Do USB bus protocol detection */ +static void usb_detect(struct uh_data *uh) +{ + int rv = 0; + + D("Called.\n"); + + /* If the cable has already been offline, we just pass the real USB detection. */ + if (test_bit(BIT_CABLE_ONLINE, &uh->state)) { + + D("Do real detection.\n"); + + rv = do_usb_detect(uh); + set_bit(BIT_UDC_PHY_TOUCHED, &uh->state); + }else{ + clear_bit(BIT_UDC_PHY_TOUCHED, &uh->state); + D("No need to do real detection.\n"); + } + + if (rv) { + if (!test_and_set_bit(BIT_USB_ONLINE, &uh->state)) + set_bit(BIT_USB_CHANGE, &uh->state); + }else{ + /* Clear keep alive bit. */ + clear_bit(BIT_KEEP_ALIVE, &uh->state); + + if (test_and_clear_bit(BIT_USB_ONLINE, &uh->state)) + set_bit(BIT_USB_CHANGE, &uh->state); + } + + set_bit(BIT_USB_DETECT_DONE, &uh->state); + return; +} + +/* USB is active ? */ +static int usb_is_active(void) +{ + unsigned long tmp; + + tmp = REG16(USB_REG_FRAME); + + mdelay(2); /* USB 1.1 Frame length is 1ms, USB 2.0 HS Frame length is 125us */ + + rmb(); + + return tmp == REG16(USB_REG_FRAME) ? 0 : 1; +} + +/* Broadcast event to notifier */ +static void do_broadcast_event(struct uh_data *uh) +{ + udc_hotplug_event_t *e = &uh->cur_uh_event; + + /* Collect Information */ + if (test_and_clear_bit(BIT_CABLE_CHANGE, &uh->state)) { + e->type = EVENT_TYPE_CABLE; + e->state = (test_bit(BIT_CABLE_ONLINE, &uh->state)) ? EVENT_STATE_ONLINE: EVENT_STATE_OFFLINE; + e->flags = 0; + + D("Broadcast cable event -> State: %s.\n", (e->state == EVENT_STATE_ONLINE ? "Online" : "Offline")); + + /* Kick chain. */ + blocking_notifier_call_chain(&uh->notifier_head, BROADCAST_TYPE_EVENT, e); + } + + if (test_and_clear_bit(BIT_USB_CHANGE, &uh->state)) { + e->type = EVENT_TYPE_USB; + e->state = (test_bit(BIT_USB_ONLINE, &uh->state)) ? EVENT_STATE_ONLINE : EVENT_STATE_OFFLINE; + e->flags = 0; + + if (test_bit(BIT_UDC_PHY_TOUCHED, &uh->state)) { + set_bit(EVENT_FLAG_UDC_PHY_TOUCHED, &e->flags); + } + + D("Broadcast USB event -> State: %s.\n", (e->state == EVENT_STATE_ONLINE ? "Online" : "Offline")); + + /* Kick chain. */ + blocking_notifier_call_chain(&uh->notifier_head, BROADCAST_TYPE_EVENT, e); + } + + return; +} + +/* Handle pending request */ +static inline void handle_request(struct uh_data *uh) +{ + if (test_and_clear_bit(BIT_REQUEST_CABLE_DETECT, &uh->state)) + set_bit(BIT_DO_CABLE_DETECT, &uh->state); + + if (test_and_clear_bit(BIT_REQUEST_USB_DETECT, &uh->state)) + set_bit(BIT_DO_USB_DETECT, &uh->state); + + return; +} + +/* Have pending request ? */ +static inline int pending_request(struct uh_data *uh) +{ + if (test_bit(BIT_REQUEST_CABLE_DETECT, &uh->state) || test_bit(BIT_REQUEST_USB_DETECT, &uh->state)) + return 1; + else + return 0; +} + +#if defined (HAVE_DETECT_SYNC) +static void prepare_restart(struct uh_data *uh, wait_queue_head_t *wq) +{ + + D("Called.\n"); + + if (test_bit(BIT_CABLE_DETECT_DONE, &uh->state)) + set_bit(BIT_DO_CABLE_DETECT, &uh->state); + + if (test_bit(BIT_USB_DETECT_DONE, &uh->state)) + set_bit(BIT_DO_USB_DETECT, &uh->state); + + sleep_on_timeout(wq, NR_JIFFIES_SLEEP_BEFORE_RESTART); + + sync_seq(uh); + + return; +} + +/* Called from kernel thread */ +static void udc_pnp_detect(struct uh_data *uh) +{ + int nr_restart = 0; + + D("Do UDC detection.\n"); + + while (nr_restart != NR_RESTART_TIMES) { + /* Do cable detection ? */ + if (test_bit(BIT_DO_CABLE_DETECT, &uh->state)) { + D("Do cable detection.\n"); + + cable_detect(uh); + } + + /* Need restart ? */ + if (!is_seq_sync(uh)) { + nr_restart ++; + + prepare_restart(uh, &uh->wq); + continue; + } + + /* Do USB detection ? */ + if (test_bit(BIT_DO_USB_DETECT, &uh->state)) { + D("Do USB detection.\n"); + + usb_detect(uh); + } + + /* Need restart ? */ + if (!is_seq_sync(uh)) { + nr_restart ++; + + prepare_restart(uh, &uh->wq); + continue; + } + + /* Done */ + D("Done.\n"); + + clear_bit(BIT_DO_CABLE_DETECT, &uh->state); + clear_bit(BIT_DO_USB_DETECT, &uh->state); + + break; + } + + return; +} + +static inline void broadcast_event(struct uh_data *uh) +{ + /* Sync ? */ + if (is_seq_sync(uh)) { + D("Sync -> Broadcast event.\n"); + + do_broadcast_event(uh); + }else{ + D("Not sync -> Prepare restarting.\n"); + + prepare_restart(uh, &uh->kthread_wq); + } +} + +static inline void udc_pnp_thread_sleep(struct uh_data *uh) +{ + /* Sync ? -> Sleep. */ + if ( !pending_request(uh) || is_seq_sync(uh)) { + D("Sleep.\n"); + + sleep_on(&uh->kthread_wq); + } + + return; +} + +#else /* !HAVE_DETECT_SYNC */ + +/* Called from kernel thread */ +static void udc_pnp_detect(struct uh_data *uh) +{ + D("Do UDC detection.\n"); + + /* Do cable detection ? */ + if (test_bit(BIT_DO_CABLE_DETECT, &uh->state)) { + D("Do cable detection.\n"); + + cable_detect(uh); + } + + /* Do USB detection ? */ + if (test_bit(BIT_DO_USB_DETECT, &uh->state)) { + D("Do USB detection.\n"); + + usb_detect(uh); + } + + /* Done */ + D("Done.\n"); + + clear_bit(BIT_DO_CABLE_DETECT, &uh->state); + clear_bit(BIT_DO_USB_DETECT, &uh->state); + + return; +} + +static inline void broadcast_event(struct uh_data *uh) +{ + D("Broadcast event.\n"); + + do_broadcast_event(uh); + + return; +} + +static inline void udc_pnp_thread_sleep(struct uh_data *uh) +{ + if (!pending_request(uh)) { + D("Sleep.\n"); + + sleep_on(&uh->kthread_wq); + } + + return; +} +#endif /* HAVE_DETECT_SYNC */ + +/* Kernel thread */ +static int udc_pnp_thread(void *data) +{ + struct uh_data *uh = (struct uh_data *)data; + + while (!kthread_should_stop()) { + /* Sleep. */ + udc_pnp_thread_sleep(uh); + + D("Running.\n"); + + if (kthread_should_stop()) + break; + +#if defined (HAVE_DETECT_SYNC) + /* Sync */ + sync_seq(uh); +#endif + + D("Will do UDC detection.\n"); + + handle_request(uh); + + /* Do detect */ + udc_pnp_detect(uh); + + D("Done.\n"); + + /* Broadcast event. */ + broadcast_event(uh); + } + + D("Exit.\n"); + + return 0; +} + +static irqreturn_t udc_pnp_irq(int irq, void *dev_id) +{ + struct uh_data *uh = (struct uh_data *)dev_id; + + D("called.\n"); + + /* clear interrupt pending status */ + __gpio_ack_irq(UDC_HOTPLUG_PIN); + + set_bit(BIT_REQUEST_CABLE_DETECT, &uh->state); + set_bit(BIT_REQUEST_USB_DETECT, &uh->state); + + start_detect(uh); + + return IRQ_HANDLED; +} + +static void __init init_gpio(struct uh_data *uh) +{ + /* get current pin level */ + __gpio_disable_pull(UDC_HOTPLUG_PIN); + __gpio_as_input(UDC_HOTPLUG_PIN); + udelay(1); + + cable_detect(uh); + + /* Because of every plug IN/OUT action will casue more than one interrupt, + So whether rising trigger or falling trigger method can both start the detection. + */ + + __gpio_as_irq_rise_edge(UDC_HOTPLUG_PIN); + + if (test_bit(BIT_CABLE_ONLINE, &uh->state)) { + D("Cable Online -> Do start detection.\n"); + + set_bit(BIT_REQUEST_CABLE_DETECT, &uh->state); + set_bit(BIT_REQUEST_USB_DETECT, &uh->state); + + start_detect(uh); + }else{ + D("Cable Offline.\n"); + } + + return; +} + +/* ---------------------------------------------------------------------------------- */ +/* Export routines */ +static void udc_hotplug_keep_alive_timer_func(unsigned long data) +{ + struct uh_data *uh = (struct uh_data *)data; + + D("Timer running.\n"); + + /* Decrease the counter. */ + if (test_bit(BIT_KEEP_ALIVE, &uh->state) && !(--uh->keep_alive_counter)) { + + if (!usb_is_active()) { + D("Timeout.\n"); + + set_bit(BIT_KEEP_ALIVE_TIMEOUT, &uh->state); + + clear_bit(BIT_USB_ONLINE, &uh->state); + set_bit(BIT_USB_CHANGE, &uh->state); + + /* No detection needed. We just want to broadcast our event. */ + start_detect(uh); + } + } + + /* Set next active time. */ + if (test_bit(BIT_KEEP_ALIVE, &uh->state) && !test_bit(BIT_KEEP_ALIVE_TIMEOUT, &uh->state)) + mod_timer(&uh->keep_alive_timer, uh->keep_alive_timer_interval + jiffies); + else + D("Timer will stop.\n"); + + return; +} + +int udc_hotplug_register_notifier(struct notifier_block *n, int request_state) +{ + struct uh_data *uh = g_puh_data; + + udc_hotplug_event_t e; + + D("Register notifier: 0x%p.\n", (void *)n); + + /* Notifer will be registered is requesting current state. */ + if (request_state) { + + BUG_ON(!n->notifier_call); + + /* Cable State */ + e.type = EVENT_TYPE_CABLE; + e.state = (test_bit(BIT_CABLE_ONLINE, &uh->state)) ? EVENT_STATE_ONLINE: EVENT_STATE_OFFLINE; + + n->notifier_call(n, BROADCAST_TYPE_STATE, &e); + + /* USB State */ + e.type = EVENT_TYPE_USB; + e.state = (test_bit(BIT_CABLE_ONLINE, &uh->state)) ? EVENT_STATE_ONLINE: EVENT_STATE_OFFLINE; + + n->notifier_call(n, BROADCAST_TYPE_STATE, &e); + } + + return blocking_notifier_chain_register(&uh->notifier_head, n); + +}EXPORT_SYMBOL(udc_hotplug_register_notifier); + +int udc_hotplug_unregister_notifier(struct notifier_block *n) +{ + struct uh_data *uh = g_puh_data; + + D("Unregister notifier: 0x%p.\n", (void *)n); + + return blocking_notifier_chain_unregister(&uh->notifier_head, n); + +}EXPORT_SYMBOL(udc_hotplug_unregister_notifier); + +/* Start keep alive, 0 - Use default value */ +int udc_hotplug_start_keep_alive(unsigned long timer_interval_in_jiffies, unsigned long counter_limit) +{ + struct uh_data *uh = g_puh_data; + + /* Already started. */ + if (test_and_set_bit(BIT_KEEP_ALIVE, &uh->state)) + return 0; + + if (timer_interval_in_jiffies) + uh->keep_alive_timer_interval = timer_interval_in_jiffies; + else + uh->keep_alive_timer_interval = DEFAULT_KEEP_ALIVE_TIMER_INTERVAL; + + if (counter_limit) + uh->keep_alive_counter_limit = counter_limit; + else + uh->keep_alive_counter_limit = DEFAULT_KEEP_ALIVE_COUNTER_LIMIT; + + uh->keep_alive_counter = uh->keep_alive_counter_limit; + + /* Active our timer. */ + return mod_timer(&uh->keep_alive_timer, 3 + jiffies); + +}EXPORT_SYMBOL(udc_hotplug_start_keep_alive); + +void udc_hotplug_do_keep_alive(void) +{ + struct uh_data *uh = g_puh_data; + + D("Keep alive.\n"); + + /* Reset counter */ + uh->keep_alive_counter = uh->keep_alive_counter_limit; + + /* We are alive again. */ + if (test_and_clear_bit(BIT_KEEP_ALIVE_TIMEOUT, &uh->state)) { + D("Reactive timer.\n"); + + /* Active timer. */ + set_bit(BIT_KEEP_ALIVE, &uh->state); + mod_timer(&uh->keep_alive_timer, 3 + jiffies); + } + + return; +}EXPORT_SYMBOL(udc_hotplug_do_keep_alive); + +void udc_hotplug_stop_keep_alive(void) +{ + struct uh_data *uh = g_puh_data; + + clear_bit(BIT_KEEP_ALIVE, &uh->state); + + return; + +}EXPORT_SYMBOL(udc_hotplug_stop_keep_alive); + +/* ----------------------------------------------------------------------------- */ + +/* + * Module init and exit + */ +static int __init udc_hotplug_init(void) +{ + struct uh_data *uh; + + unsigned long status = 0; + + int rv; + + g_puh_data = (struct uh_data *)kzalloc(sizeof(struct uh_data), GFP_KERNEL); + if (!g_puh_data) { + printk(KERN_ERR PFX": Failed to allocate memory.\n"); + return -ENOMEM; + } + + uh = g_puh_data; + + set_bit(1, &status); + + BLOCKING_INIT_NOTIFIER_HEAD(&uh->notifier_head); + + init_waitqueue_head(&uh->kthread_wq); + init_waitqueue_head(&uh->wq); + + init_timer(&uh->keep_alive_timer); + + uh->keep_alive_timer.function = udc_hotplug_keep_alive_timer_func; + uh->keep_alive_timer.expires = jiffies - 1; /* Add a stopped timer */ + uh->keep_alive_timer.data = (unsigned long)uh; + + add_timer(&uh->keep_alive_timer); + +#if defined (HAVE_DETECT_SYNC) + reset_seq(uh); +#endif + + /* Create pnp thread and register IRQ */ + uh->kthread = kthread_run(udc_pnp_thread, uh, "kudcd"); + if (IS_ERR(uh->kthread)) { + printk(KERN_ERR PFX": Failed to create system monitor thread.\n"); + rv = PTR_ERR(uh->kthread); + goto err; + } + + set_bit(2, &status); + + rv = request_irq(UDC_HOTPLUG_IRQ, udc_pnp_irq, IRQF_DISABLED, "udc_pnp", uh); + if (rv) { + printk(KERN_ERR PFX": Could not get udc hotplug irq %d\n", UDC_HOTPLUG_IRQ); + goto err; + } + + init_gpio(uh); + +#if defined (HAVE_DETECT_SYNC) + printk(KERN_ERR PFX": Registered(HAVE_DETECT_SYNC).\n"); +#else + printk(KERN_ERR PFX": Registered.\n"); +#endif + return 0; + +err: + if (test_bit(2, &status)) { + kthread_stop(uh->kthread); + } + + if (test_bit(1, &status)) { + kfree(g_puh_data); + } + + return rv; +} + +static void __exit udc_hotplug_exit(void) +{ + free_irq(UDC_HOTPLUG_IRQ, g_puh_data); + + kthread_stop(g_puh_data->kthread); + + kfree(g_puh_data); + + return; +} + +module_init(udc_hotplug_init); +module_exit(udc_hotplug_exit); + +MODULE_AUTHOR("River Wang "); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.c b/target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.c new file mode 100755 index 000000000..41f092848 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.c @@ -0,0 +1,1334 @@ +/* + * linux/drivers/video/jzslcd.c -- Ingenic On-Chip Smart LCD frame buffer device + * + * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "console/fbcon.h" + +#include "jz4740_slcd.h" + +#undef DEBUG +//#define DEBUG +#ifdef DEBUG +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif + +#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) +#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) +#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) +#ifdef DEBUG +#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) +#else +#define print_dbg(f, arg...) do {} while (0) +#endif + +static jz_dma_desc slcd_palette_desc __attribute__ ((aligned (16))); +static jz_dma_desc slcd_frame_desc __attribute__ ((aligned (16))); + +static int dma_chan; +static dma_addr_t slcd_frame_desc_phys_addr, slcd_palette_desc_phys_addr; + +static unsigned char non_link_desp = 0; +static unsigned char is_set_reg = 0; +struct lcd_cfb_info { + struct fb_info fb; + struct display_switch *dispsw; + signed int currcon; + int func_use_count; + + struct { + u16 red, green, blue; + } palette[NR_PALETTE]; +#ifdef CONFIG_PM + struct pm_dev *pm; +#endif +}; + +struct slcd_reg_info { + unsigned int cmd; + unsigned int data; +}; +static struct slcd_reg_info reg_buf; +static struct lcd_cfb_info *jzslcd_info; + +struct jzfb_info { + unsigned int cfg; /* panel mode and pin usage etc. */ + unsigned int w; + unsigned int h; + unsigned int bpp; /* bit per pixel */ + unsigned int bus; + unsigned int pclk; /* pixel clk */ + +}; + +static struct jzfb_info jzfb = { +#ifdef CONFIG_JZ_SLCD_LGDP4551 + SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, + 400, 240, 16, 8, 16000000 /*16 bpp, 8 bus*/ +// 240, 400, 18, 8, 16000000 /*18 bpp, 8 bus*/ +// 400, 240, 18, 8, 16000000 /*18 bpp, 8 bus*/ +#endif + +#ifdef CONFIG_JZ_SLCD_SPFD5420A + SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, + 400, 240, 18, 18, 16000000 /*18 bpp, 18 bus*/ +#endif +}; + + +static volatile unsigned char *slcd_palette; +static volatile unsigned char *slcd_frame; + +//extern struct display fb_display[MAX_NR_CONSOLES]; +static irqreturn_t slcd_dma_irq(int irq, void *dev_id); + + +static void Mcupanel_RegSet(UINT32 cmd, UINT32 data) +{ + switch (jzfb.bus) { + case 8: + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); + break; + case 9: + data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); + data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; + break; + case 16: + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); + break; + case 18: + cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); + data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); + break; + default: + printk("Don't support %d bit Bus\n", jzfb.bus ); + break; + } +} + +/* Sent a command withou data */ +static void Mcupanel_Command(UINT32 cmd) { + switch (jzfb.bus) { + case 8: + case 9: + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); + break; + case 16: + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); + break; + case 18: + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); + break; + default: + printk("Don't support %d bit Bus\n", jzfb.bus ); + break; + } +} + +/* Set the start address of screen, for example (0, 0) */ +#ifdef CONFIG_JZ_SLCD_LGDP4551 +static void Mcupanel_SetAddr(UINT16 x, UINT16 y) +{ + Mcupanel_RegSet(0x20,x) ; + udelay(1); + Mcupanel_RegSet(0x21,y) ; + udelay(1); + Mcupanel_Command(0x22); + +} +#endif +#ifdef CONFIG_JZ_SLCD_SPFD5420A +void Mcupanel_SetAddr(u32 x, u32 y) //u32 +{ + Mcupanel_RegSet(0x200,x) ; + udelay(1); + Mcupanel_RegSet(0x201,y) ; + udelay(1); + Mcupanel_Command(0x202); + +} + +#endif + +static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int jzfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + unsigned short *ptr, ctmp; + + print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); + if (regno >= NR_PALETTE) + return 1; + + cfb->palette[regno].red = red ; + cfb->palette[regno].green = green; + cfb->palette[regno].blue = blue; + if (cfb->fb.var.bits_per_pixel <= 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + + red &= 0xff; + green &= 0xff; + blue &= 0xff; + } + switch (cfb->fb.var.bits_per_pixel) { + case 1: + case 2: + case 4: + case 8: + /* RGB 565 */ + if (((red >> 3) == 0) && ((red >> 2) != 0)) + red = 1 << 3; + if (((blue >> 3) == 0) && ((blue >> 2) != 0)) + blue = 1 << 3; + ctmp = ((red >> 3) << 11) + | ((green >> 2) << 5) | (blue >> 3); + + ptr = (unsigned short *)slcd_palette; + ptr = (unsigned short *)(((u32)ptr)|0xa0000000); + ptr[regno] = ctmp; + + break; + + case 15: + if (regno < 16) + ((u32 *)cfb->fb.pseudo_palette)[regno] = + ((red >> 3) << 10) | + ((green >> 3) << 5) | + (blue >> 3); + break; + case 16: + if (regno < 16) { + ((u32 *)cfb->fb.pseudo_palette)[regno] = + ((red >> 3) << 11) | + ((green >> 2) << 5) | + (blue >> 3); + } + break; + case 18: + case 24: + case 32: + if (regno < 16) + ((u32 *)cfb->fb.pseudo_palette)[regno] = + (red << 16) | + (green << 8) | + (blue << 0); + +/* if (regno < 16) { + unsigned val; + val = chan_to_field(red, &cfb->fb.var.red); + val |= chan_to_field(green, &cfb->fb.var.green); + val |= chan_to_field(blue, &cfb->fb.var.blue); + ((u32 *)cfb->fb.pseudo_palette)[regno] = val; + } +*/ + + break; + } + return 0; +} + +static int jzfb_ioctl (struct fb_info *info, unsigned int cmd, unsigned long arg ) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + + switch (cmd) { + case FBIOSETBACKLIGHT: + __slcd_set_backlight_level(arg); /* We support 8 levels here. */ + break; + case FBIODISPON: + __slcd_display_on(); + break; + case FBIODISPOFF: + __slcd_display_off(); + break; + case FBIO_REFRESH_ALWAYS: + dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); + if (slcd_frame_desc.dcmd & DMAC_DCMD_LINK) + printk("The Smart LCD refreshes automatically. Option is omitted!\n"); + else { + dprintk("OPEN DMAC_DCMD_LINK \n"); + slcd_frame_desc.dcmd &= ~DMAC_DCMD_TIE; + slcd_frame_desc.dcmd |= DMAC_DCMD_LINK; + dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); + REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_TIE; + __dmac_channel_set_doorbell(dma_chan); + } + break; + case FBIO_REFRESH_EVENTS: + dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); + if (!(slcd_frame_desc.dcmd & DMAC_DCMD_LINK)) + printk("The Smart LCD is refreshed by envents. Option is omitted!\n"); + else { + non_link_desp = 1; + REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; + REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; + } + break; + case FBIO_DO_REFRESH: + + dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); + if (slcd_frame_desc.dcmd & DMAC_DCMD_LINK) + printk("The Smart LCD can refresh automatically. Option is omitted!\n"); + else { + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + __dmac_channel_set_doorbell(dma_chan); + } + break; + case FBIO_SET_REG: + if (copy_from_user(®_buf, argp, sizeof(reg_buf))) + return -EFAULT; + is_set_reg = 1; + REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; + REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; + break; + default: + break; + } + + return ret; +} + +/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ +static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + unsigned long start; + unsigned long off; + u32 len; + + off = vma->vm_pgoff << PAGE_SHIFT; + //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); + + /* frame buffer memory */ + start = cfb->fb.fix.smem_start; + len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); + start &= PAGE_MASK; + + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + off += start; + + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ + +#if 1 + pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; +// pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ + pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Through */ +#endif + + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { + return -EAGAIN; + } + return 0; +} + +/* checks var and eventually tweaks it to something supported, + * DO NOT MODIFY PAR */ +static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + print_dbg("jzfb_check_var"); + return 0; +} + + +/* + * set the video mode according to info->var + */ +static int jzfb_set_par(struct fb_info *info) +{ +// print_dbg("jzfb_set_par"); + printk("jzfb_set_par"); + return 0; +} + + +/* + * (Un)Blank the display. + * Fix me: should we use VESA value? + */ +static int jzfb_blank(int blank_mode, struct fb_info *info) +{ + + dprintk("fb_blank %d %p", blank_mode, info); + + switch (blank_mode) { + + case FB_BLANK_UNBLANK: + /* Turn on panel */ + break; + + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + /* Turn off panel */ + break; + default: + break; + + } + return 0; +} + +/* + * pan display + */ +static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + int dy; + + if (!var || !cfb) { + return -EINVAL; + } + + if (var->xoffset - cfb->fb.var.xoffset) { + /* No support for X panning for now! */ + return -EINVAL; + } + + dy = var->yoffset - cfb->fb.var.yoffset; + print_dbg("var.yoffset: %d", dy); + if (dy) { + + print_dbg("Panning screen of %d lines", dy); +// slcd_frame_desc->databuf += (cfb->fb.fix.line_length * dy); +// slcd_frame_desc->dsadr += (cfb->fb.fix.line_length * dy); + /* TODO: Wait for current frame to finished */ + } + + return 0; +} + + +/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ +static struct fb_ops jzfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = jzfb_setcolreg, + .fb_check_var = jzfb_check_var, + .fb_set_par = jzfb_set_par, + .fb_blank = jzfb_blank, + .fb_pan_display = jzfb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_mmap = jzfb_mmap, + .fb_ioctl = jzfb_ioctl, +}; + +static int jzfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + //struct display *display; + int chgvar = 0; + + var->height = jzfb.h ; + var->width = jzfb.w ; + var->bits_per_pixel = jzfb.bpp; + + var->vmode = FB_VMODE_NONINTERLACED; + var->activate = cfb->fb.var.activate; + var->xres = var->width; + var->yres = var->height; + var->xres_virtual = var->width; + var->yres_virtual = var->height; + var->xoffset = 0; + var->yoffset = 0; + var->pixclock = 0; + var->left_margin = 0; + var->right_margin = 0; + var->upper_margin = 0; + var->lower_margin = 0; + var->hsync_len = 0; + var->vsync_len = 0; + var->sync = 0; + var->activate &= ~FB_ACTIVATE_TEST; + + /* + * CONUPDATE and SMOOTH_XPAN are equal. However, + * SMOOTH_XPAN is only used internally by fbcon. + */ + if (var->vmode & FB_VMODE_CONUPDATE) { + var->vmode |= FB_VMODE_YWRAP; + var->xoffset = cfb->fb.var.xoffset; + var->yoffset = cfb->fb.var.yoffset; + } + + if (var->activate & FB_ACTIVATE_TEST) + return 0; + + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) + return -EINVAL; + + if (cfb->fb.var.xres != var->xres) + chgvar = 1; + if (cfb->fb.var.yres != var->yres) + chgvar = 1; + if (cfb->fb.var.xres_virtual != var->xres_virtual) + chgvar = 1; + if (cfb->fb.var.yres_virtual != var->yres_virtual) + chgvar = 1; + if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) + chgvar = 1; + + //display = fb_display + con; + + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + + switch(var->bits_per_pixel){ + case 1: /* Mono */ + cfb->fb.fix.visual = FB_VISUAL_MONO01; + cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; + break; + case 2: /* Mono */ + var->red.offset = 0; + var->red.length = 2; + var->green.offset = 0; + var->green.length = 2; + var->blue.offset = 0; + var->blue.length = 2; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; + break; + case 4: /* PSEUDOCOLOUR*/ + var->red.offset = 0; + var->red.length = 4; + var->green.offset = 0; + var->green.length = 4; + var->blue.offset = 0; + var->blue.length = 4; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->fb.fix.line_length = var->xres / 2; + break; + case 8: /* PSEUDOCOLOUR, 256 */ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->fb.fix.line_length = var->xres ; + break; + case 15: /* DIRECTCOLOUR, 32k */ + var->bits_per_pixel = 15; + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + + cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; + cfb->fb.fix.line_length = var->xres_virtual * 2; + break; + case 16: /* DIRECTCOLOUR, 64k */ + var->bits_per_pixel = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + cfb->fb.fix.line_length = var->xres_virtual * 2; + break; + case 18: + case 24: + case 32: + /* DIRECTCOLOUR, 256 */ + var->bits_per_pixel = 32; + + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + cfb->fb.fix.line_length = var->xres_virtual * 4; + break; + + default: /* in theory this should never happen */ + printk(KERN_WARNING "%s: don't support for %dbpp\n", + cfb->fb.fix.id, var->bits_per_pixel); + break; + } + + cfb->fb.var = *var; + cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; + + /* + * If we are setting all the virtual consoles, also set the + * defaults used to create new consoles. + */ + fb_set_cmap(&cfb->fb.cmap, &cfb->fb); + dprintk("jzfb_set_var: after fb_set_cmap...\n"); + + return 0; +} + +static struct lcd_cfb_info * jzfb_alloc_fb_info(void) +{ + struct lcd_cfb_info *cfb; + + cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); + + if (!cfb) + return NULL; + + jzslcd_info = cfb; + + memset(cfb, 0, sizeof(struct lcd_cfb_info) ); + + cfb->currcon = -1; + + + strcpy(cfb->fb.fix.id, "jz-slcd"); + cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + cfb->fb.fix.type_aux = 0; + cfb->fb.fix.xpanstep = 1; + cfb->fb.fix.ypanstep = 1; + cfb->fb.fix.ywrapstep = 0; + cfb->fb.fix.accel = FB_ACCEL_NONE; + + cfb->fb.var.nonstd = 0; + cfb->fb.var.activate = FB_ACTIVATE_NOW; + cfb->fb.var.height = -1; + cfb->fb.var.width = -1; + cfb->fb.var.accel_flags = FB_ACCELF_TEXT; + + cfb->fb.fbops = &jzfb_ops; + cfb->fb.flags = FBINFO_FLAG_DEFAULT; + + cfb->fb.pseudo_palette = (void *)(cfb + 1); + + switch (jzfb.bpp) { + case 1: + fb_alloc_cmap(&cfb->fb.cmap, 4, 0); + break; + case 2: + fb_alloc_cmap(&cfb->fb.cmap, 8, 0); + break; + case 4: + fb_alloc_cmap(&cfb->fb.cmap, 32, 0); + break; + case 8: + + default: + fb_alloc_cmap(&cfb->fb.cmap, 256, 0); + break; + } + dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); + + return cfb; +} + +/* + * Map screen memory + */ +static int jzfb_map_smem(struct lcd_cfb_info *cfb) +{ + struct page * map = NULL; + unsigned char *tmp; + unsigned int page_shift, needroom, t; + + t = jzfb.bpp; + if (jzfb.bpp == 15) + t = 16; + if (jzfb.bpp == 18 || jzfb.bpp == 24) + t = 32; + needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; + + for (page_shift = 0; page_shift < 12; page_shift++) + if ((PAGE_SIZE << page_shift) >= needroom) + break; + + slcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); + slcd_frame = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); + if ((!slcd_palette) || (!slcd_frame)) + return -ENOMEM; + + memset((void *)slcd_palette, 0, PAGE_SIZE); + memset((void *)slcd_frame, 0, PAGE_SIZE << page_shift); + + map = virt_to_page(slcd_palette); + set_bit(PG_reserved, &map->flags); + + for (tmp=(unsigned char *)slcd_frame; + tmp < slcd_frame + (PAGE_SIZE << page_shift); + tmp += PAGE_SIZE) { + map = virt_to_page(tmp); + set_bit(PG_reserved, &map->flags); + } + + cfb->fb.fix.smem_start = virt_to_phys((void *)slcd_frame); + + cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); + + cfb->fb.screen_base = + (unsigned char *)(((unsigned int)slcd_frame & 0x1fffffff) | 0xa0000000); + + if (!cfb->fb.screen_base) { + printk("%s: unable to map screen memory\n", cfb->fb.fix.id); + return -ENOMEM; + } + + return 0; +} + +static void jzfb_free_fb_info(struct lcd_cfb_info *cfb) +{ + if (cfb) { + fb_alloc_cmap(&cfb->fb.cmap, 0, 0); + kfree(cfb); + } +} + +static void jzfb_unmap_smem(struct lcd_cfb_info *cfb) +{ + struct page * map = NULL; + unsigned char *tmp; + unsigned int page_shift, needroom, t; + + t = jzfb.bpp; + if (jzfb.bpp == 18 || jzfb.bpp == 24) + t = 32; + if (jzfb.bpp == 15) + t = 16; + needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; + for (page_shift = 0; page_shift < 12; page_shift++) + if ((PAGE_SIZE << page_shift) >= needroom) + break; + + if (cfb && cfb->fb.screen_base) { + iounmap(cfb->fb.screen_base); + cfb->fb.screen_base = NULL; + release_mem_region(cfb->fb.fix.smem_start, + cfb->fb.fix.smem_len); + } + + if (slcd_palette) { + map = virt_to_page(slcd_palette); + clear_bit(PG_reserved, &map->flags); + free_pages((int)slcd_palette, 0); + } + + if (slcd_frame) { + + for (tmp=(unsigned char *)slcd_frame; + tmp < slcd_frame + (PAGE_SIZE << page_shift); + tmp += PAGE_SIZE) { + map = virt_to_page(tmp); + clear_bit(PG_reserved, &map->flags); + } + + free_pages((int)slcd_frame, page_shift); + } +} + +static void slcd_descriptor_init(void) +{ + int i; + int frm_size, pal_size; + unsigned int next; + unsigned int slcd_frame_src_phys_addr, slcd_palette_src_phys_addr, slcd_dma_dst_phys_addr; + + i = jzfb.bpp; + if (i == 18 || i == 24) + i = 32; + if (i == 15) + i = 16; + + switch (jzfb.bpp) { + case 1: + pal_size = 4; + break; + case 2: + pal_size = 8; + break; + case 4: + pal_size = 32; + break; + case 8: + default: + pal_size = 512; + } + + frm_size = jzfb.w * jzfb.h * jzfb.bpp / 8; + + /*Offset of next descriptor*/ + slcd_frame_desc_phys_addr = (dma_addr_t)CPHYSADDR((unsigned long)(&slcd_frame_desc)); + slcd_palette_desc_phys_addr = (dma_addr_t)CPHYSADDR((unsigned long)(&slcd_palette_desc)); + + /*Soure address and Target address*/ + slcd_palette_src_phys_addr = (unsigned int)virt_to_phys(slcd_palette); + slcd_frame_src_phys_addr = (unsigned int)virt_to_phys(slcd_frame); + slcd_dma_dst_phys_addr = (unsigned int)CPHYSADDR(SLCD_FIFO); + next = slcd_frame_desc_phys_addr >> 4; + + /* Prepare Palette Descriptor */ + slcd_palette_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 + | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V + | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; + switch (slcd_palette_desc.dcmd & DMAC_DCMD_DS_MASK) { + case DMAC_DCMD_DS_32BYTE: + pal_size /= 32; + break; + case DMAC_DCMD_DS_16BYTE: + pal_size /= 16; + break; + case DMAC_DCMD_DS_32BIT: + pal_size /= 4; + break; + case DMAC_DCMD_DS_16BIT: + pal_size /= 2; + break; + case DMAC_DCMD_DS_8BIT: + default: + break; + } + + slcd_palette_desc.dsadr = (unsigned int)virt_to_phys(slcd_palette); /* DMA source address */ + slcd_palette_desc.dtadr = (unsigned int)CPHYSADDR(SLCD_FIFO); /* DMA target address */ + slcd_palette_desc.ddadr = (volatile unsigned int)((next << 24) | (pal_size & 0xffffff)); /* offset and size*/ + dma_cache_wback((unsigned long)(&slcd_palette_desc), 16); + + /*Prepare Frame Descriptor in memory*/ + switch (jzfb.bpp) { + case 8 ... 16: + slcd_frame_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 + | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V + | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; + break; + + case 17 ... 32: + slcd_frame_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 + | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V + | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; + break; + } + switch (slcd_frame_desc.dcmd & DMAC_DCMD_DS_MASK) { + case DMAC_DCMD_DS_32BYTE: + frm_size /= 32; + break; + case DMAC_DCMD_DS_16BYTE: + frm_size /= 16; + break; + case DMAC_DCMD_DS_32BIT: + frm_size /= 4; + break; + case DMAC_DCMD_DS_16BIT: + frm_size /= 2; + break; + case DMAC_DCMD_DS_8BIT: + default: + break; + } + + slcd_frame_desc.dsadr = slcd_frame_src_phys_addr; /* DMA source address */ + slcd_frame_desc.dtadr = slcd_dma_dst_phys_addr; /* DMA target address */ + slcd_frame_desc.ddadr = (volatile unsigned int)((next << 24) | (frm_size & 0xffffff)); /* offset and size*/ + dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); +} + +void slcd_hw_init(void) +{ + unsigned int val, pclk; + int pll_div; + + REG_LCD_CFG &= ~LCD_CFG_LCDPIN_MASK; + REG_LCD_CFG |= LCD_CFG_LCDPIN_SLCD; + + if ((jzfb.bpp == 18) | (jzfb.bpp == 24)) + jzfb.bpp = 32; + + /* Configure SLCD module for initialize smart lcd registers*/ + switch (jzfb.bus) { + case 8: + REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 + | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW + | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING + | SLCD_CFG_TYPE_PARALLEL; + __gpio_as_slcd_8bit(); + break; + case 9: + REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 + | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW + | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING + | SLCD_CFG_TYPE_PARALLEL; + __gpio_as_slcd_9bit(); + break; + case 16: + REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_16 + | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW + | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING + | SLCD_CFG_TYPE_PARALLEL; + __gpio_as_slcd_16bit(); + break; + case 18: + REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_18 + | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW + | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING + | SLCD_CFG_TYPE_PARALLEL; + __gpio_as_slcd_18bit(); + break; + default: + printk("Error: Don't support BUS %d!\n", jzfb.bus); + break; + } + + REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; + __cpm_stop_lcd(); + pclk = jzfb.pclk; + pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */ + pll_div = pll_div ? 1 : 2 ; + val = ( __cpm_get_pllout()/pll_div ) / pclk; + val--; + if ( val > 0x1ff ) { + printk("CPM_LPCDR too large, set it to 0x1ff\n"); + val = 0x1ff; + } + __cpm_set_pixdiv(val); + + REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ + + jz_clocks.pixclk = __cpm_get_pixclk(); + jz_clocks.lcdclk = __cpm_get_lcdclk(); + printk("SLCDC: PixClock:%d LcdClock:%d\n", + jz_clocks.pixclk, jz_clocks.lcdclk); + + __cpm_start_lcd(); + udelay(1000); + __slcd_display_pin_init(); + __slcd_special_on(); + + /* Configure SLCD module for transfer data to smart lcd GRAM*/ + switch (jzfb.bus) { + case 8: + switch (jzfb.bpp) { + case 8: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; + break; + case 15: + case 16: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; + break; + case 17 ... 32: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; + break; + default: + printk("The BPP %d is not supported\n", jzfb.bpp); + break; + } + break; + case 9: + switch (jzfb.bpp) { + case 8: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; + break; + case 15 ... 16: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; + break; + case 17 ... 32: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_9_x2; + break; + default: + printk("The BPP %d is not supported\n", jzfb.bpp); + break; + } + break; + case 16: + switch (jzfb.bpp) { + case 8: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; + break; + case 15 ... 16: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; + break; + case 17 ... 32: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; + break; + default: + printk("The BPP %d is not supported\n", jzfb.bpp); + break; + } + break; + case 18: + switch (jzfb.bpp) { + case 8: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; + break; + case 15: + case 16: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; + break; + case 17 ... 32: + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_18; + break; + default: + printk("The BPP %d is not supported\n", jzfb.bpp); + break; + } + break; + default: + printk("Error: The BUS %d is not supported\n", jzfb.bus); + break; + } + dprintk("SLCD_CFG=0x%x\n", REG_SLCD_CFG); +} + +static irqreturn_t slcd_dma_irq(int irq, void *dev_id) +{ + + if (__dmac_channel_transmit_halt_detected(dma_chan)) { + dprintk("DMA HALT\n"); + __dmac_channel_clear_transmit_halt(dma_chan); + } + + if (__dmac_channel_address_error_detected(dma_chan)) { + dprintk("DMA ADDR ERROR\n"); + __dmac_channel_clear_address_error(dma_chan); + } + + if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { + dprintk("DMA DESC INVALID\n"); + __dmac_channel_clear_descriptor_invalid(dma_chan); + } + + if (__dmac_channel_count_terminated_detected(dma_chan)) { + dprintk("DMA CT\n"); + __dmac_channel_clear_count_terminated(dma_chan); + if(is_set_reg){ + printk("Close DMAC_DCMD_LINK \n"); + REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; + } + if (non_link_desp) { + printk("Close DMAC_DCMD_LINK \n"); + /*Set to Non-Link Descriptor*/ + REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; + } + } + + if (__dmac_channel_transmit_end_detected(dma_chan)) { + printk("DMA TT\n"); + __dmac_channel_clear_transmit_end(dma_chan); + if (non_link_desp) { + slcd_frame_desc.dcmd |= DMAC_DCMD_TIE; + slcd_frame_desc.dcmd &= ~DMAC_DCMD_LINK; + dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); + non_link_desp = 0; + } + if (is_set_reg) { + is_set_reg = 0; + while (REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE; /* disable DMA */ + REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ + REG_SLCD_CTRL = 0; + + /* + *add operation here + */ + Mcupanel_RegSet(reg_buf.cmd, reg_buf.data); + Mcupanel_Command(0x0022);/*Write Data to GRAM */ + mdelay(100); + REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; + REG_DMAC_DMACR = DMAC_DMACR_DMAE; + REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; + __dmac_channel_set_doorbell(dma_chan); + } + } + return IRQ_HANDLED; +} + +static int slcd_dma_init(void) +{ + /* Request DMA channel and setup irq handler */ + dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", slcd_dma_irq, 0, NULL); + if (dma_chan < 0) { + printk("Request DMA Failed\n"); + return -1; + } + printk("DMA channel %d is requested by SLCD!\n", dma_chan); + + /*Init the SLCD DMA and Enable*/ + REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_SLCD; + REG_DMAC_DMACR = DMAC_DMACR_DMAE; + REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /*Descriptor Transfer*/ + + if (jzfb.bpp <= 8) + REG_DMAC_DDA(dma_chan) = slcd_palette_desc_phys_addr; + else + REG_DMAC_DDA(dma_chan) = slcd_frame_desc_phys_addr; + + /* DMA doorbell set -- start DMA now ... */ + __dmac_channel_set_doorbell(dma_chan); + return 0; +} + +#ifdef CONFIG_PM + +/* + * Suspend the LCDC. + */ +static int jzfb_suspend(void) +{ + + __slcd_close_backlight(); + __dmac_disable_channel(dma_chan); + __slcd_dma_disable(); /* Quick Disable */ + __slcd_special_off(); + __cpm_stop_lcd(); + return 0; +} + +/* + * Resume the LCDC. + */ + +static int jzfb_resume(void) +{ + __cpm_start_lcd(); + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + switch (jzfb.bpp) { + case 8: + /* DATA 8-bit once*/ + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; + break; + case 15: + case 16: + case 18: + case 24: + case 32: + /* DATA 8-bit twice*/ + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; + break; + default: + REG_SLCD_CFG = SLCD_CFG_DWIDTH_8_x2; + break; + } + __slcd_display_pin_init(); + __slcd_special_on(); + + if (jzfb.bpp == 32) { + /* DATA 8-bit three time*/ + REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; + REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; + } + __slcd_dma_enable(); + udelay(100); + __dmac_enable_channel(dma_chan); + __dmac_channel_set_doorbell(dma_chan); + mdelay(200); + __slcd_set_backlight_level(80); + return 0; +} + +/* + * Power management hook. Note that we won't be called from IRQ context, + * unlike the blank functions above, so we may sleep. + */ +static int jzslcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) +{ + int ret; + struct lcd_cfb_info *cfb = pm_dev->data; + + if (!cfb) return -EINVAL; + + switch (req) { + case PM_SUSPEND: + ret = jzfb_suspend(); + break; + + case PM_RESUME: + ret = jzfb_resume(); + break; + + default: + ret = -EINVAL; + break; + } + return ret; +} +#else +#define jzfb_suspend NULL +#define jzfb_resume NULL +#endif /* CONFIG_PM */ +static int __init jzslcd_fb_init(void) +{ + + struct lcd_cfb_info *cfb; + int err = 0; + + /*the parameters of slcd*/ + cfb = jzfb_alloc_fb_info(); + if (!cfb) + goto failed; + + err = jzfb_map_smem(cfb); + if (err) + goto failed; + jzfb_set_var(&cfb->fb.var, -1, &cfb->fb); + + slcd_hw_init(); + + err = register_framebuffer(&cfb->fb); + if (err < 0) { + printk("jzslcd_fb_init(): slcd register framebuffer err.\n"); + goto failed; + } + + printk("fb%d: %s frame buffer device, using %dK of video memory\n", + cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); + + slcd_descriptor_init(); + err = slcd_dma_init(); + if (err != 0) { + printk("SLCD Init DMA Fail!\n"); + return err; + } + mdelay(100); + __slcd_set_backlight_level(80); + +#ifdef CONFIG_PM + /* + * Note that the console registers this as well, but we want to + * power down the display prior to sleeping. + */ +//struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback); + + cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzslcd_pm_callback); + if (cfb->pm) + cfb->pm->data = cfb; + +#endif + return 0; + +failed: + jzfb_unmap_smem(cfb); + jzfb_free_fb_info(cfb); + + return err; +} + +#if 0 +static int jzfb_remove(struct device *dev) +{ + struct lcd_cfb_info *cfb = dev_get_drvdata(dev); + jzfb_unmap_smem(cfb); + jzfb_free_fb_info(cfb); + return 0; +} +#endif + +#if 0 +static struct device_driver jzfb_driver = { + .name = "jz-slcd", + .bus = &platform_bus_type, + .probe = jzfb_probe, + .remove = jzfb_remove, + .suspend = jzfb_suspend, + .resume = jzfb_resume, +}; +#endif + +static void __exit jzslcd_fb_cleanup(void) +{ + //driver_unregister(&jzfb_driver); + //jzfb_remove(); +} + +module_init(jzslcd_fb_init); +module_exit(jzslcd_fb_cleanup); + +MODULE_DESCRIPTION("JzSOC SLCD Controller driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.h b/target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.h new file mode 100644 index 000000000..84754f654 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/video/jz4740_slcd.h @@ -0,0 +1,376 @@ +/* + * linux/drivers/video/jzslcd.h -- Ingenic On-Chip SLCD frame buffer device + * + * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __JZSLCD_H__ +#define __JZSLCD_H__ + +#define UINT16 unsigned short +#define UINT32 unsigned int + +#define NR_PALETTE 256 +/* Jz LCDFB supported I/O controls. */ +#define FBIOSETBACKLIGHT 0x4688 +#define FBIODISPON 0x4689 +#define FBIODISPOFF 0x468a +#define FBIORESET 0x468b +#define FBIOPRINT_REG 0x468c +#define FBIO_REFRESH_ALWAYS 0x468d +#define FBIO_REFRESH_EVENTS 0x468e +#define FBIO_DO_REFRESH 0x468f +#define FBIO_SET_REG 0x4690 + +#ifdef CONFIG_JZ_SLCD_LGDP4551 +#define PIN_CS_N (32*2+18) /* Chip select :SLCD_WR: GPC18 */ +#define PIN_RESET_N (32*2+21) /* LCD reset :SLCD_RST: GPC21*/ +#define PIN_RS_N (32*2+19) + +#define __slcd_special_pin_init() \ +do { \ + __gpio_as_output(PIN_CS_N); \ + __gpio_as_output(PIN_RESET_N); \ + __gpio_clear_pin(PIN_CS_N); /* Clear CS */\ + mdelay(100); \ +} while(0) + +#define __slcd_special_on() \ +do { /* RESET# */ \ + __gpio_set_pin(PIN_RESET_N); \ + mdelay(10); \ + __gpio_clear_pin(PIN_RESET_N); \ + mdelay(10); \ + __gpio_set_pin(PIN_RESET_N); \ + mdelay(100); \ + Mcupanel_RegSet(0x0015,0x0050); \ + Mcupanel_RegSet(0x0011,0x0000); \ + Mcupanel_RegSet(0x0010,0x3628); \ + Mcupanel_RegSet(0x0012,0x0002); \ + Mcupanel_RegSet(0x0013,0x0E47); \ + udelay(100); \ + Mcupanel_RegSet(0x0012,0x0012); \ + udelay(100); \ + Mcupanel_RegSet(0x0010,0x3620); \ + Mcupanel_RegSet(0x0013,0x2E47); \ + udelay(50); \ + Mcupanel_RegSet(0x0030,0x0000); \ + Mcupanel_RegSet(0x0031,0x0502); \ + Mcupanel_RegSet(0x0032,0x0307); \ + Mcupanel_RegSet(0x0033,0x0304); \ + Mcupanel_RegSet(0x0034,0x0004); \ + Mcupanel_RegSet(0x0035,0x0401); \ + Mcupanel_RegSet(0x0036,0x0707); \ + Mcupanel_RegSet(0x0037,0x0303); \ + Mcupanel_RegSet(0x0038,0x1E02); \ + Mcupanel_RegSet(0x0039,0x1E02); \ + Mcupanel_RegSet(0x0001,0x0000); \ + Mcupanel_RegSet(0x0002,0x0300); \ + if (jzfb.bpp == 16) \ + Mcupanel_RegSet(0x0003,0x10B8); /*8-bit system interface two transfers + up:0x10B8 down:0x1088 left:0x1090 right:0x10a0*/ \ + else \ + if (jzfb.bpp == 32)\ + Mcupanel_RegSet(0x0003,0xD0B8);/*8-bit system interface three transfers,666 + up:0xD0B8 down:0xD088 left:0xD090 right:0xD0A0*/ \ + Mcupanel_RegSet(0x0008,0x0204);\ + Mcupanel_RegSet(0x000A,0x0008);\ + Mcupanel_RegSet(0x0060,0x3100);\ + Mcupanel_RegSet(0x0061,0x0001);\ + Mcupanel_RegSet(0x0090,0x0052);\ + Mcupanel_RegSet(0x0092,0x000F);\ + Mcupanel_RegSet(0x0093,0x0001);\ + Mcupanel_RegSet(0x009A,0x0008);\ + Mcupanel_RegSet(0x00A3,0x0010);\ + Mcupanel_RegSet(0x0050,0x0000);\ + Mcupanel_RegSet(0x0051,0x00EF);\ + Mcupanel_RegSet(0x0052,0x0000);\ + Mcupanel_RegSet(0x0053,0x018F);\ + /*===Display_On_Function=== */ \ + Mcupanel_RegSet(0x0007,0x0001);\ + Mcupanel_RegSet(0x0007,0x0021);\ + Mcupanel_RegSet(0x0007,0x0023);\ + Mcupanel_RegSet(0x0007,0x0033);\ + Mcupanel_RegSet(0x0007,0x0133);\ + Mcupanel_Command(0x0022);/*Write Data to GRAM */ \ + udelay(1); \ + Mcupanel_SetAddr(0,0); \ + mdelay(100); \ +} while (0) + +#define __slcd_special_off() \ +do { \ +} while(0) +#endif /*CONFIG_JZ_SLCD_LGDP4551_xxBUS*/ + +#ifdef CONFIG_JZ_SLCD_SPFD5420A + + //#define PIN_CS_N (32*2+18) // Chip select //GPC18; +#define PIN_CS_N (32*2+22) // Chip select //GPC18; +#define PIN_RESET_N (32*1+18) // LCD reset //GPB18; +#define PIN_RS_N (32*2+19) // LCD RS //GPC19; +#define PIN_POWER_N (32*3+0) //Power off //GPD0; +#define PIN_FMARK_N (32*3+1) //fmark //GPD1; + +#define GAMMA() \ +do { \ + Mcupanel_RegSet(0x0300,0x0101); \ + Mcupanel_RegSet(0x0301,0x0b27); \ + Mcupanel_RegSet(0x0302,0x132a); \ + Mcupanel_RegSet(0x0303,0x2a13); \ + Mcupanel_RegSet(0x0304,0x270b); \ + Mcupanel_RegSet(0x0305,0x0101); \ + Mcupanel_RegSet(0x0306,0x1205); \ + Mcupanel_RegSet(0x0307,0x0512); \ + Mcupanel_RegSet(0x0308,0x0005); \ + Mcupanel_RegSet(0x0309,0x0003); \ + Mcupanel_RegSet(0x030a,0x0f04); \ + Mcupanel_RegSet(0x030b,0x0f00); \ + Mcupanel_RegSet(0x030c,0x000f); \ + Mcupanel_RegSet(0x030d,0x040f); \ + Mcupanel_RegSet(0x030e,0x0300); \ + Mcupanel_RegSet(0x030f,0x0500); \ + /*** secorrect gamma2 ***/ \ + Mcupanel_RegSet(0x0400,0x3500); \ + Mcupanel_RegSet(0x0401,0x0001); \ + Mcupanel_RegSet(0x0404,0x0000); \ + Mcupanel_RegSet(0x0500,0x0000); \ + Mcupanel_RegSet(0x0501,0x0000); \ + Mcupanel_RegSet(0x0502,0x0000); \ + Mcupanel_RegSet(0x0503,0x0000); \ + Mcupanel_RegSet(0x0504,0x0000); \ + Mcupanel_RegSet(0x0505,0x0000); \ + Mcupanel_RegSet(0x0600,0x0000); \ + Mcupanel_RegSet(0x0606,0x0000); \ + Mcupanel_RegSet(0x06f0,0x0000); \ + Mcupanel_RegSet(0x07f0,0x5420); \ + Mcupanel_RegSet(0x07f3,0x288a); \ + Mcupanel_RegSet(0x07f4,0x0022); \ + Mcupanel_RegSet(0x07f5,0x0001); \ + Mcupanel_RegSet(0x07f0,0x0000); \ +} while(0) + +#define __slcd_special_on() \ +do { \ + __gpio_set_pin(PIN_RESET_N); \ + mdelay(10); \ + __gpio_clear_pin(PIN_RESET_N); \ + mdelay(10); \ + __gpio_set_pin(PIN_RESET_N); \ + mdelay(100); \ + if (jzfb.bus == 18) {\ + Mcupanel_RegSet(0x0606,0x0000); \ + udelay(10); \ + Mcupanel_RegSet(0x0007,0x0001); \ + udelay(10); \ + Mcupanel_RegSet(0x0110,0x0001); \ + udelay(10); \ + Mcupanel_RegSet(0x0100,0x17b0); \ + Mcupanel_RegSet(0x0101,0x0147); \ + Mcupanel_RegSet(0x0102,0x019d); \ + Mcupanel_RegSet(0x0103,0x8600); \ + Mcupanel_RegSet(0x0281,0x0010); \ + udelay(10); \ + Mcupanel_RegSet(0x0102,0x01bd); \ + udelay(10); \ + /************initial************/\ + Mcupanel_RegSet(0x0000,0x0000); \ + Mcupanel_RegSet(0x0001,0x0000); \ + Mcupanel_RegSet(0x0002,0x0400); \ + Mcupanel_RegSet(0x0003,0x1288); /*up:0x1288 down:0x12B8 left:0x1290 right:0x12A0*/ \ + Mcupanel_RegSet(0x0006,0x0000); \ + Mcupanel_RegSet(0x0008,0x0503); \ + Mcupanel_RegSet(0x0009,0x0001); \ + Mcupanel_RegSet(0x000b,0x0010); \ + Mcupanel_RegSet(0x000c,0x0000); \ + Mcupanel_RegSet(0x000f,0x0000); \ + Mcupanel_RegSet(0x0007,0x0001); \ + Mcupanel_RegSet(0x0010,0x0010); \ + Mcupanel_RegSet(0x0011,0x0202); \ + Mcupanel_RegSet(0x0012,0x0300); \ + Mcupanel_RegSet(0x0020,0x021e); \ + Mcupanel_RegSet(0x0021,0x0202); \ + Mcupanel_RegSet(0x0022,0x0100); \ + Mcupanel_RegSet(0x0090,0x0000); \ + Mcupanel_RegSet(0x0092,0x0000); \ + Mcupanel_RegSet(0x0100,0x16b0); \ + Mcupanel_RegSet(0x0101,0x0147); \ + Mcupanel_RegSet(0x0102,0x01bd); \ + Mcupanel_RegSet(0x0103,0x2c00); \ + Mcupanel_RegSet(0x0107,0x0000); \ + Mcupanel_RegSet(0x0110,0x0001); \ + Mcupanel_RegSet(0x0210,0x0000); \ + Mcupanel_RegSet(0x0211,0x00ef); \ + Mcupanel_RegSet(0x0212,0x0000); \ + Mcupanel_RegSet(0x0213,0x018f); \ + Mcupanel_RegSet(0x0280,0x0000); \ + Mcupanel_RegSet(0x0281,0x0001); \ + Mcupanel_RegSet(0x0282,0x0000); \ + GAMMA(); \ + Mcupanel_RegSet(0x0007,0x0173); \ + } else { \ + Mcupanel_RegSet(0x0600, 0x0001); /*soft reset*/ \ + mdelay(10); \ + Mcupanel_RegSet(0x0600, 0x0000); /*soft reset*/ \ + mdelay(10); \ + Mcupanel_RegSet(0x0606, 0x0000); /*i80-i/F Endian Control*/ \ + /*===User setting=== */ \ + Mcupanel_RegSet(0x0001, 0x0000);/* Driver Output Control-----0x0100 SM(bit10) | 0x400*/ \ + Mcupanel_RegSet(0x0002, 0x0100); /*LCD Driving Wave Control 0x0100 */ \ + if (jzfb.bpp == 16) \ + Mcupanel_RegSet(0x0003, 0x50A8);/*Entry Mode 0x1030*/ \ + else /*bpp = 18*/ \ + Mcupanel_RegSet(0x0003, 0x1010 | 0xC8); /*Entry Mode 0x1030*/ \ + /*#endif */ \ + Mcupanel_RegSet(0x0006, 0x0000); /*Outline Sharpening Control*/\ + Mcupanel_RegSet(0x0008, 0x0808); /*Sets the number of lines for front/back porch period*/\ + Mcupanel_RegSet(0x0009, 0x0001); /*Display Control 3 */\ + Mcupanel_RegSet(0x000B, 0x0010); /*Low Power Control*/\ + Mcupanel_RegSet(0x000C, 0x0000); /*External Display Interface Control 1 /*0x0001*/\ + Mcupanel_RegSet(0x000F, 0x0000); /*External Display Interface Control 2 */\ + Mcupanel_RegSet(0x0400, 0xB104);/*Base Image Number of Line---GS(bit15) | 0x8000*/ \ + Mcupanel_RegSet(0x0401, 0x0001); /*Base Image Display 0x0001*/\ + Mcupanel_RegSet(0x0404, 0x0000); /*Base Image Vertical Scroll Control 0x0000*/\ + Mcupanel_RegSet(0x0500, 0x0000); /*Partial Image 1: Display Position*/\ + Mcupanel_RegSet(0x0501, 0x0000); /*RAM Address (Start Line Address) */\ + Mcupanel_RegSet(0x0502, 0x018f); /*RAM Address (End Line Address) */ \ + Mcupanel_RegSet(0x0503, 0x0000); /*Partial Image 2: Display Position RAM Address*/\ + Mcupanel_RegSet(0x0504, 0x0000); /*RAM Address (Start Line Address) */\ + Mcupanel_RegSet(0x0505, 0x0000); /*RAM Address (End Line Address)*/\ + /*Panel interface control===*/\ + Mcupanel_RegSet(0x0010, 0x0011); /*Division Ratio,Clocks per Line 14 */\ + mdelay(10); \ + Mcupanel_RegSet(0x0011, 0x0202); /*Division Ratio,Clocks per Line*/\ + Mcupanel_RegSet(0x0012, 0x0300); /*Sets low power VCOM drive period. */\ + mdelay(10); \ + Mcupanel_RegSet(0x0020, 0x021e); /*Panel Interface Control 4 */\ + Mcupanel_RegSet(0x0021, 0x0202); /*Panel Interface Control 5 */\ + Mcupanel_RegSet(0x0022, 0x0100); /*Panel Interface Control 6*/\ + Mcupanel_RegSet(0x0090, 0x0000); /*Frame Marker Control */\ + Mcupanel_RegSet(0x0092, 0x0000); /*MDDI Sub-display Control */\ + /*===Gamma setting=== */\ + Mcupanel_RegSet(0x0300, 0x0101); /*γ Control*/\ + Mcupanel_RegSet(0x0301, 0x0000); /*γ Control*/\ + Mcupanel_RegSet(0x0302, 0x0016); /*γ Control*/\ + Mcupanel_RegSet(0x0303, 0x2913); /*γ Control*/\ + Mcupanel_RegSet(0x0304, 0x260B); /*γ Control*/\ + Mcupanel_RegSet(0x0305, 0x0101); /*γ Control*/\ + Mcupanel_RegSet(0x0306, 0x1204); /*γ Control*/\ + Mcupanel_RegSet(0x0307, 0x0415); /*γ Control*/\ + Mcupanel_RegSet(0x0308, 0x0205); /*γ Control*/\ + Mcupanel_RegSet(0x0309, 0x0303); /*γ Control*/\ + Mcupanel_RegSet(0x030a, 0x0E05); /*γ Control*/\ + Mcupanel_RegSet(0x030b, 0x0D01); /*γ Control*/\ + Mcupanel_RegSet(0x030c, 0x010D); /*γ Control*/\ + Mcupanel_RegSet(0x030d, 0x050E); /*γ Control*/\ + Mcupanel_RegSet(0x030e, 0x0303); /*γ Control*/\ + Mcupanel_RegSet(0x030f, 0x0502); /*γ Control*/\ + /*===Power on sequence===*/\ + Mcupanel_RegSet(0x0007, 0x0001); /*Display Control 1*/\ + Mcupanel_RegSet(0x0110, 0x0001); /*Power supply startup enable bit*/\ + Mcupanel_RegSet(0x0112, 0x0060); /*Power Control 7*/\ + Mcupanel_RegSet(0x0100, 0x16B0); /*Power Control 1 */\ + Mcupanel_RegSet(0x0101, 0x0115); /*Power Control 2*/\ + Mcupanel_RegSet(0x0102, 0x0119); /*Starts VLOUT3,Sets the VREG1OUT.*/\ + mdelay(50); \ + Mcupanel_RegSet(0x0103, 0x2E00); /*set the amplitude of VCOM*/\ + mdelay(50);\ + Mcupanel_RegSet(0x0282, 0x0093);/*0x008E);/*0x0093); /*VCOMH voltage*/\ + Mcupanel_RegSet(0x0281, 0x000A); /*Selects the factor of VREG1OUT to generate VCOMH. */\ + Mcupanel_RegSet(0x0102, 0x01BE); /*Starts VLOUT3,Sets the VREG1OUT.*/\ + mdelay(10);\ + /*Address */\ + Mcupanel_RegSet(0x0210, 0x0000); /*Window Horizontal RAM Address Start*/\ + Mcupanel_RegSet(0x0211, 0x00ef); /*Window Horizontal RAM Address End*/\ + Mcupanel_RegSet(0x0212, 0x0000); /*Window Vertical RAM Address Start*/\ + Mcupanel_RegSet(0x0213, 0x018f); /*Window Vertical RAM Address End */\ + Mcupanel_RegSet(0x0200, 0x0000); /*RAM Address Set (Horizontal Address)*/\ + Mcupanel_RegSet(0x0201, 0x018f); /*RAM Address Set (Vertical Address)*/ \ + /*===Display_On_Function===*/\ + Mcupanel_RegSet(0x0007, 0x0021); /*Display Control 1 */\ + mdelay(50); /*40*/\ + Mcupanel_RegSet(0x0007, 0x0061); /*Display Control 1 */\ + mdelay(50); /*100*/\ + Mcupanel_RegSet(0x0007, 0x0173); /*Display Control 1 */\ + mdelay(50); /*300*/\ + }\ + Mcupanel_Command(0x0202); /*Write Data to GRAM */ \ + udelay(10);\ + Mcupanel_SetAddr(0,0);\ + udelay(100);\ +} while(0) + +#define __slcd_special_pin_init() \ +do { \ + __gpio_as_output(PIN_CS_N); \ + __gpio_as_output(PIN_RESET_N); \ + __gpio_clear_pin(PIN_CS_N); /* Clear CS */ \ + __gpio_as_output(PIN_POWER_N); \ + mdelay(100); \ +} while(0) + +#endif /*CONFIG_JZ_SLCD_SPFD5420A*/ + +#ifndef __slcd_special_pin_init +#define __slcd_special_pin_init() +#endif +#ifndef __slcd_special_on +#define __slcd_special_on() +#endif +#ifndef __slcd_special_off +#define __slcd_special_off() +#endif + +/* + * Platform specific definition + */ +#if defined(CONFIG_SOC_JZ4740) +#if defined(CONFIG_JZ4740_PAVO) +#define GPIO_PWM 123 /* GP_D27 */ +#define PWM_CHN 4 /* pwm channel */ +#define PWM_FULL 101 +/* 100 level: 0,1,...,100 */ +#define __slcd_set_backlight_level(n)\ +do { \ + __gpio_as_output(32*3+27); \ + __gpio_set_pin(32*3+27); \ +} while (0) + +#define __slcd_close_backlight() \ +do { \ + __gpio_as_output(GPIO_PWM); \ + __gpio_clear_pin(GPIO_PWM); \ +} while (0) + +#else + +#define __slcd_set_backlight_level(n) +#define __slcd_close_backlight() + +#endif /* #if defined(CONFIG_MIPS_JZ4740_PAVO) */ + +#define __slcd_display_pin_init() \ +do { \ + __slcd_special_pin_init(); \ +} while (0) + +#define __slcd_display_on() \ +do { \ + __slcd_special_on(); \ + __slcd_set_backlight_level(80); \ +} while (0) + +#define __slcd_display_off() \ +do { \ + __slcd_special_off(); \ + __slcd_close_backlight(); \ +} while (0) + +#endif /* CONFIG_SOC_JZ4740 */ +#endif /*__JZSLCD_H__*/ + diff --git a/target/linux/xburst/files-2.6.31/drivers/video/jz_auo_a043fl01v2.h b/target/linux/xburst/files-2.6.31/drivers/video/jz_auo_a043fl01v2.h new file mode 100644 index 000000000..00a572899 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/video/jz_auo_a043fl01v2.h @@ -0,0 +1,129 @@ +/* + * linux/drivers/video/jz_auo_a043fl01v2.h -- Ingenic LCD driver + */ + +#ifndef __JZ_AUO_A043FL01V2_H__ +#define __JZ_AUO_A043FL01V2_H__ + +#if defined(CONFIG_JZ4750_APUS) /* board pavo */ + #define SPEN (32*3+29) /*LCD_CS*/ + #define SPCK (32*3+26) /*LCD_SCL*/ + #define SPDA (32*3+27) /*LCD_SDA*/ + #define LCD_DISP_N (32*4+25) /*LCD_DISP_N use for lcd reset*/ +#elif defined(CONFIG_JZ4750_FUWA) /* board fuwa */ + #define SPEN (32*3+29) /*LCD_CS*/ + #define SPCK (32*3+26) /*LCD_SCL*/ + #define SPDA (32*3+27) /*LCD_SDA*/ + #define LCD_DISP_N (32*5+2) /*LCD_DISP_N use for lcd reset*/ +#elif defined(CONFIG_JZ4750D_CETUS) /* board cetus */ + #define SPEN (32*5+13) /*LCD_CS*/ + #define SPCK (32*5+10) /*LCD_SCL*/ + #define SPDA (32*5+11) /*LCD_SDA*/ + #define LCD_DISP_N (32*4+18) /*LCD_DISP_N use for lcd reset*/ +#else +#error "driver/video/Jzlcd.h, please define SPI pins on your board." +#endif + +#define __spi_write_reg(reg, val) \ + do { \ + unsigned char no; \ + unsigned short value; \ + unsigned char a=0; \ + unsigned char b=0; \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + a=reg; \ + b=val; \ + __gpio_set_pin(SPEN); \ + __gpio_clear_pin(SPCK); \ + udelay(50); \ + __gpio_clear_pin(SPDA); \ + __gpio_clear_pin(SPEN); \ + udelay(50); \ + value=((a<<8)|(b&0xFF)); \ + for(no=0;no<16;no++) \ + { \ + if((value&0x8000)==0x8000){ \ + __gpio_set_pin(SPDA);} \ + else{ \ + __gpio_clear_pin(SPDA); } \ + udelay(50); \ + __gpio_set_pin(SPCK); \ + value=(value<<1); \ + udelay(50); \ + __gpio_clear_pin(SPCK); \ + } \ + __gpio_set_pin(SPEN); \ + udelay(400); \ + } while (0) +#define __spi_read_reg(reg,val) \ + do{ \ + unsigned char no; \ + unsigned short value; \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + value = ((reg << 0) | (1 << 7)); \ + val = 0; \ + __gpio_as_output(SPDA); \ + __gpio_set_pin(SPEN); \ + __gpio_clear_pin(SPCK); \ + udelay(50); \ + __gpio_clear_pin(SPDA); \ + __gpio_clear_pin(SPEN); \ + udelay(50); \ + for (no = 0; no < 16; no++ ) { \ + udelay(50); \ + if(no < 8) \ + { \ + if (value & 0x80) /* send data */ \ + __gpio_set_pin(SPDA); \ + else \ + __gpio_clear_pin(SPDA); \ + udelay(50); \ + __gpio_set_pin(SPCK); \ + value = (value << 1); \ + udelay(50); \ + __gpio_clear_pin(SPCK); \ + if(no == 7) \ + __gpio_as_input(SPDA); \ + } \ + else \ + { \ + udelay(100); \ + __gpio_set_pin(SPCK); \ + udelay(50); \ + val = (val << 1); \ + val |= __gpio_get_pin(SPDA); \ + __gpio_clear_pin(SPCK); \ + } \ + } \ + __gpio_as_output(SPDA); \ + __gpio_set_pin(SPEN); \ + udelay(400); \ + } while(0) + +#define __lcd_special_pin_init() \ + do { \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + __gpio_as_output(LCD_DISP_N); \ + __gpio_clear_pin(LCD_DISP_N); \ + } while (0) +#define __lcd_special_on() \ + do { \ + udelay(50);\ + __gpio_clear_pin(LCD_DISP_N); \ + udelay(100); \ + __gpio_set_pin(LCD_DISP_N); \ +} while (0) + + #define __lcd_special_off() \ + do { \ + __gpio_clear_pin(LCD_DISP_N); \ + } while (0) + +#endif /* __JZ_AUO_A043FL01V2_H__ */ + diff --git a/target/linux/xburst/files-2.6.31/drivers/video/jz_toppoly_td043mgeb1.h b/target/linux/xburst/files-2.6.31/drivers/video/jz_toppoly_td043mgeb1.h new file mode 100644 index 000000000..44fc61691 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/video/jz_toppoly_td043mgeb1.h @@ -0,0 +1,157 @@ +#ifndef __JZ_TOPPOLY_TD043MGEB1_H__ +#define __JZ_TOPPOLY_TD043MGEB1_H__ + +#include + +#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD043MGEB1) || defined(CONFIG_JZ4750_ANDROID_LCD_TOPPOLY_TD043MGEB1) +#if defined(CONFIG_JZ4750_APUS) /* board FuWa */ + #define SPEN (32*3+29) /*LCD_CS*/ + #define SPCK (32*3+26) /*LCD_SCL*/ + #define SPDA (32*3+27) /*LCD_SDA*/ + #define LCD_RET (32*4+23) /*LCD_DISP_N use for lcd reset*/ + #define LCD_STBY (32*4+25) /*LCD_STBY, use for lcd standby*/ +#else +#error "driver/video/jz_toppoly_td043mgeb1.h, please define SPI pins on your board." +#endif + +#define __spi_write_reg(reg, val) \ + do { \ + unsigned char no; \ + unsigned short value; \ + unsigned char a=0; \ + unsigned char b=0; \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + a=reg; \ + b=val; \ + __gpio_set_pin(SPEN); \ + __gpio_clear_pin(SPCK); \ + udelay(500); \ + __gpio_clear_pin(SPDA); \ + __gpio_clear_pin(SPEN); \ + udelay(500); \ + value=((a<<10)|(b&0xFF)); \ + for(no=0;no<16;no++) \ + { \ + if((value&0x8000)==0x8000){ \ + __gpio_set_pin(SPDA);} \ + else{ \ + __gpio_clear_pin(SPDA); } \ + udelay(500); \ + __gpio_set_pin(SPCK); \ + value=(value<<1); \ + udelay(500); \ + __gpio_clear_pin(SPCK); \ + } \ + __gpio_set_pin(SPEN); \ + udelay(4000); \ + } while (0) +#define __spi_read_reg(reg,val) \ + do{ \ + unsigned char no; \ + unsigned short value; \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + value = ((reg << 2) | (1 << 1)); \ + val = 0; \ + __gpio_as_output(SPDA); \ + __gpio_set_pin(SPEN); \ + __gpio_clear_pin(SPCK); \ + udelay(50); \ + __gpio_clear_pin(SPDA); \ + __gpio_clear_pin(SPEN); \ + udelay(50); \ + for (no = 0; no < 16; no++ ) { \ + udelay(50); \ + if(no < 8) \ + { \ + if (value & 0x80) /* send data */ \ + __gpio_set_pin(SPDA); \ + else \ + __gpio_clear_pin(SPDA); \ + udelay(50); \ + __gpio_set_pin(SPCK); \ + value = (value << 1); \ + udelay(50); \ + __gpio_clear_pin(SPCK); \ + if(no == 7) \ + __gpio_as_input(SPDA); \ + } \ + else \ + { \ + udelay(100); \ + __gpio_set_pin(SPCK); \ + udelay(50); \ + val = (val << 1); \ + val |= __gpio_get_pin(SPDA); \ + __gpio_clear_pin(SPCK); \ + } \ + } \ + __gpio_as_output(SPDA); \ + __gpio_set_pin(SPEN); \ + udelay(400); \ + } while(0) + +#define __lcd_special_pin_init() \ + do { \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + __gpio_as_output(LCD_STBY); \ + __gpio_as_output(LCD_RET); \ + udelay(500); \ + __gpio_clear_pin(LCD_RET); \ + udelay(1000); \ + __gpio_set_pin(LCD_RET); \ + udelay(1000); \ + } while (0) + +#define __lcd_special_on() \ + do { \ + __gpio_set_pin(LCD_STBY); \ + udelay(1000); \ + __spi_write_reg(0x02, 0x07); \ + __spi_write_reg(0x03, 0x5F); \ + __spi_write_reg(0x04, 0x17); \ + __spi_write_reg(0x05, 0x20); \ + __spi_write_reg(0x06, 0x08); \ + __spi_write_reg(0x07, 0x20); \ + __spi_write_reg(0x08, 0x20); \ + __spi_write_reg(0x09, 0x20); \ + __spi_write_reg(0x0A, 0x20); \ + __spi_write_reg(0x0B, 0x20); \ + __spi_write_reg(0x0C, 0x20); \ + __spi_write_reg(0x0D, 0x22); \ + __spi_write_reg(0x0E, 0x2F); \ + __spi_write_reg(0x0F, 0x2f); \ + __spi_write_reg(0x10, 0x2F); \ + __spi_write_reg(0x11, 0x15); \ + __spi_write_reg(0x12, 0xaa); \ + __spi_write_reg(0x13, 0xFF); \ + __spi_write_reg(0x14, 0x86); \ + __spi_write_reg(0x15, 0x8e); \ + __spi_write_reg(0x16, 0xd6); \ + __spi_write_reg(0x17, 0xfe); \ + __spi_write_reg(0x18, 0x28); \ + __spi_write_reg(0x19, 0x52); \ + __spi_write_reg(0x1A, 0x7c); \ + __spi_write_reg(0x1B, 0xe9); \ + __spi_write_reg(0x1C, 0x42); \ + __spi_write_reg(0x1D, 0x88); \ + __spi_write_reg(0x1E, 0xb8); \ + __spi_write_reg(0x1F, 0xff); \ + __spi_write_reg(0x20, 0xf0); \ + __spi_write_reg(0x21, 0xf0); \ + __spi_write_reg(0x22, 0x08); \ + } while (0) + +#define __lcd_special_off() \ + do { \ + __gpio_clear_pin(LCD_STBY); \ + } while (0) + +#endif /* LCD_TOPPOLY_TD043MGEB1 */ + +#endif /* __JZ_TOPPOLY_TD043MGEB1_H__ */ diff --git a/target/linux/xburst/files-2.6.31/drivers/video/jzlcd.c b/target/linux/xburst/files-2.6.31/drivers/video/jzlcd.c new file mode 100755 index 000000000..6df943965 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/video/jzlcd.c @@ -0,0 +1,1538 @@ +/* + * linux/drivers/video/jzlcd.c -- Ingenic On-Chip LCD frame buffer device + * + * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "console/fbcon.h" + +#include "jzlcd.h" + +#define DRIVER_NAME "jz-lcd" + +#undef DEBUG +//#define DEBUG +#ifdef DEBUG +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif + +#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) +#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) +#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) +#ifdef DEBUG +#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) +#else +#define print_dbg(f, arg...) do {} while (0) +#endif + +struct lcd_cfb_info { + struct fb_info fb; + struct display_switch *dispsw; + signed int currcon; + int func_use_count; + + struct { + u16 red, green, blue; + } palette[NR_PALETTE]; +#ifdef CONFIG_PM + struct pm_dev *pm; +#endif +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + struct task_struct *rotate_daemon_thread; +#endif +}; + +static struct lcd_cfb_info *jzlcd_info; + +struct jzfb_info { + unsigned int cfg; /* panel mode and pin usage etc. */ + unsigned int w; + unsigned int h; + unsigned int bpp; /* bit per pixel */ + unsigned int fclk; /* frame clk */ + unsigned int hsw; /* hsync width, in pclk */ + unsigned int vsw; /* vsync width, in line count */ + unsigned int elw; /* end of line, in pclk */ + unsigned int blw; /* begin of line, in pclk */ + unsigned int efw; /* end of frame, in line count */ + unsigned int bfw; /* begin of frame, in line count */ +}; + +static struct jzfb_info jzfb = { +#if defined(CONFIG_JZLCD_SHARP_LQ035Q7) + MODE_TFT_SHARP | PCLK_N | VSYNC_N, + 240, 320, 16, 60, 1, 2, 1, 2, 0, 6 +#endif +#if defined(CONFIG_JZLCD_SAMSUNG_LTS350Q1) + MODE_TFT_SAMSUNG | PCLK_N, + 240, 320, 16, 60, 1, 2, (254-240), 0, 7, 0 +#endif +#if defined(CONFIG_JZLCD_SAMSUNG_LTV350QVF04) + MODE_TFT_GEN | HSYNC_N | VSYNC_N, + 320, 240, 16, 70, 19, 4, 20, 14, 18, 6 +#endif +#if defined(CONFIG_JZLCD_SAMSUNG_LTP400WQF01) + MODE_TFT_GEN | HSYNC_N | VSYNC_N, + 480, 272, 16, 60, 41, 10, 2, 2, 2, 2 +#endif + +#if defined(CONFIG_JZLCD_SAMSUNG_LTP400WQF02) + /* MODE_TFT_18BIT: JZ4740@ version */ + MODE_TFT_GEN | MODE_TFT_18BIT | HSYNC_N | VSYNC_N, + 480, 272, 32, 60, 41, 10, 2, 2, 2, 2 +#endif +#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW) + MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, + 320, 240, 16, 85, 30, 3, 38, 20, 11, 8 +#endif +#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL) + MODE_8BIT_SERIAL_TFT | HSYNC_N | VSYNC_N | PCLK_N, + /* serial mode 280 lines, parallel mode 240 lines */ + 320, 280, 32, 60, (30*3), 3, (20*3), (38*3), 46, 23 +#endif +#if defined(CONFIG_JZLCD_AUO_A030FL01_V1) + MODE_TFT_GEN | MODE_TFT_18BIT | HSYNC_N | VSYNC_N, + 480, 272, 32, 60, 39, 10, 8, 4, 4, 2 +#endif +#if defined(CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E) + MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N | DE_N, + 320, 240, 16, 60, 3, 3, 3, 3, 3, 85 /* 320x240 */ +#endif +#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) && defined(CONFIG_JZ4740_PAVO) + MODE_TFT_GEN | HSYNC_N | VSYNC_N | MODE_TFT_18BIT | PCLK_N, +// 320, 240, 18, 110, 1, 1, 10, 50, 10, 13 + 320, 240, 18, 80, 1, 1, 10, 50, 10, 13 +#endif +#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) && !(defined(CONFIG_JZ4740_PAVO)) + MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, + 320, 240, 16, 110, 1, 1, 10, 50, 10, 13 +#endif +#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) + MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N, + 320, 240, 32, 60, 1, 1, 10, 50, 10, 13 +#endif +#if defined(CONFIG_JZLCD_HYNIX_HT10X21) + MODE_TFT_GEN | PCLK_N, + 1024, 768, 16, 45, 1, 1, 75, 0, 3, 0 +#endif +#if defined(CONFIG_JZLCD_TOSHIBA_LTM084P363) + MODE_TFT_GEN | PCLK_N, + 800, 600, 16, 50, 1, 2, 199, 0, 2, 0 +#endif +#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42) + MODE_TFT_SHARP | PCLK_N, + 800, 600, 16, 40, 1, 1, 255, 0, 34, 0 +#endif +#if defined(CONFIG_JZLCD_CSTN_800x600) + MODE_STN_COLOR_DUAL | STN_DAT_PIN8, + 800, 600, 16, 30, 8, 1, 0, 0, 0, 0 +#endif +#if defined(CONFIG_JZLCD_CSTN_320x240) + MODE_STN_COLOR_SINGLE | STN_DAT_PIN8, + 320, 240, 16, 120, 8, 1, 8, 0, 0, 0 +#endif +#if defined(CONFIG_JZLCD_MSTN_640x480) + MODE_STN_MONO_DUAL | STN_DAT_PIN4, + 640, 480, 8, 110, 4, 1, 4, 0, 0, 0 +#endif +#if defined(CONFIG_JZLCD_MSTN_320x240) + MODE_STN_MONO_SINGLE | STN_DAT_PIN4, + 320, 240, 8, 110, 4, 1, 4, 0, 0, 0 +#endif +#if defined(CONFIG_JZLCD_MSTN_480x320) + MODE_STN_MONO_SINGLE | STN_DAT_PIN8 +#if defined(CONFIG_JZLCD_MSTN_INVERSE) + | DATA_INVERSE +#endif + , 480, 320, 8, 65, 8, 1, 8, 0, 0, 0 +#endif + +#if defined(CONFIG_JZLCD_MSTN_240x128) + MODE_STN_MONO_SINGLE | STN_DAT_PIN1 +#if defined(CONFIG_JZLCD_MSTN_INVERSE) + | DATA_INVERSE +#endif + , 240, 128, 8, 100, 1, 1, 1, 0, 0, 0 +#endif +}; + +static struct lcd_desc *lcd_desc_base; +static struct lcd_desc *lcd_palette_desc; +static struct lcd_desc *lcd_frame_desc0; +static struct lcd_desc *lcd_frame_desc1; + +static unsigned char *lcd_palette; +static unsigned char *lcd_frame[CONFIG_JZLCD_FRAMEBUFFER_MAX]; +struct jz_lcd_buffer_addrs_t jz_lcd_buffer_addrs; +//extern struct display fb_display[MAX_NR_CONSOLES]; +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) +static unsigned char *lcd_frame_user_fb; +/* default rotate angle */ +static volatile int rotate_angle = CONFIG_JZLCD_FRAMEBUFFER_DEFAULT_ROTATE_ANGLE; +#endif + +#ifdef DEBUG +static void print_regs(void) /* debug */ +{ + printk("REG_LCD_CFG:\t0x%8.8x\n", REG_LCD_CFG); + printk("REG_LCD_VSYNC:\t0x%8.8x\n", REG_LCD_VSYNC); + printk("REG_LCD_HSYNC:\t0x%8.8x\n", REG_LCD_HSYNC); + printk("REG_LCD_VAT:\t0x%8.8x\n", REG_LCD_VAT); + printk("REG_LCD_DAH:\t0x%8.8x\n", REG_LCD_DAH); + printk("REG_LCD_DAV:\t0x%8.8x\n", REG_LCD_DAV); + printk("REG_LCD_PS:\t0x%8.8x\n", REG_LCD_PS); + printk("REG_LCD_CLS:\t0x%8.8x\n", REG_LCD_CLS); + printk("REG_LCD_SPL:\t0x%8.8x\n", REG_LCD_SPL); + printk("REG_LCD_REV:\t0x%8.8x\n", REG_LCD_REV); + printk("REG_LCD_CTRL:\t0x%8.8x\n", REG_LCD_CTRL); + printk("REG_LCD_STATE:\t0x%8.8x\n", REG_LCD_STATE); + printk("REG_LCD_IID:\t0x%8.8x\n", REG_LCD_IID); + printk("REG_LCD_DA0:\t0x%8.8x\n", REG_LCD_DA0); + printk("REG_LCD_SA0:\t0x%8.8x\n", REG_LCD_SA0); + printk("REG_LCD_FID0:\t0x%8.8x\n", REG_LCD_FID0); + printk("REG_LCD_CMD0:\t0x%8.8x\n", REG_LCD_CMD0); + + printk("==================================\n"); + printk("REG_LCD_VSYNC:\t%d:%d\n", REG_LCD_VSYNC>>16, REG_LCD_VSYNC&0xfff); + printk("REG_LCD_HSYNC:\t%d:%d\n", REG_LCD_HSYNC>>16, REG_LCD_HSYNC&0xfff); + printk("REG_LCD_VAT:\t%d:%d\n", REG_LCD_VAT>>16, REG_LCD_VAT&0xfff); + printk("REG_LCD_DAH:\t%d:%d\n", REG_LCD_DAH>>16, REG_LCD_DAH&0xfff); + printk("REG_LCD_DAV:\t%d:%d\n", REG_LCD_DAV>>16, REG_LCD_DAV&0xfff); + printk("==================================\n"); + +} +#else +#define print_regs() +#endif + +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) +static int jzfb_rotate_daemon_thread(void *info) +{ + int i,j; + struct fb_info *fb = &jzlcd_info->fb; + + while (!kthread_should_stop()) { +#if (CONFIG_JZLCD_FRAMEBUFFER_BPP == 8) + unsigned char *plcd_frame = (unsigned char *)lcd_frame[0]; + unsigned char *pfb = (unsigned char *) (fb->screen_base); +#elif (CONFIG_JZLCD_FRAMEBUFFER_BPP == 16) + unsigned short *plcd_frame = (unsigned short *)lcd_frame[0]; + unsigned short *pfb = (unsigned short *) (fb->screen_base); +#elif (CONFIG_JZLCD_FRAMEBUFFER_BPP == 32) + unsigned int *plcd_frame = (unsigned int *)lcd_frame[0]; + unsigned int *pfb = (unsigned int *) (fb->screen_base); +#else +#error "ERROR, rotate not support this bpp." +#endif + switch ( rotate_angle ) { + case FB_ROTATE_UR: + printk("%s, Warning, this shouldn't reache\n", __FUNCTION__); + ssleep(1); + break; + case FB_ROTATE_UD: /* cost about 30ms, can be accelrated by dma in the future */ + plcd_frame += jzfb.w*jzfb.h -1; + for (i=0;ivar.height+1; i++) { + for (j=1; j < fb->var.width+1; j++) + plcd_frame[j*fb->var.height-i] = *pfb++; + } + msleep(100); /* sleep 100ms */ + break; + case FB_ROTATE_CCW: /* cost about 80ms */ + for (i=0;ivar.height;i++) { + for ( j=fb->var.width-1;j>=0;j--) + plcd_frame[j*fb->var.height+i] = *pfb++; + } + msleep(100); /* sleep 100ms */ + break; + default: /* FB_ROTATE_UR */ + dprintk("Unknown rotate(%d) type\n", rotate_angle); + ssleep(1); + } + + dma_cache_wback_inv((unsigned int)(lcd_frame_user_fb), fb->fix.smem_len); + } + return 0; +} +/* + * rotate param angle: + * 0: FB_ROTATE_UR, 0'C + * 1: FB_ROTATE_CW, 90'C + * 2: FB_ROTATE_UD, 180'C + * 3: FB_ROTATE_CCW, 270'C + */ +static int jzfb_rotate_change( int angle ) +{ + struct fb_info *fb = &jzlcd_info->fb; + + /* clear frame buffer */ + memset((void*)lcd_frame_user_fb, 0x00, fb->fix.smem_len); + switch ( angle ) { + case FB_ROTATE_UR: + fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.w; + fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.h; + /* change lcd controller's data buffer to lcd_frame_user_fb*/ + lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame_user_fb); + if ( rotate_angle != FB_ROTATE_UR ) + kthread_stop(jzlcd_info->rotate_daemon_thread); + rotate_angle = angle; + break; + case FB_ROTATE_UD: + case FB_ROTATE_CW: + case FB_ROTATE_CCW: + if ( angle == FB_ROTATE_UD ) { + fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.w; + fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.h; + } + else { /* CW, CCW */ + fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.h; + fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.w; + } + /* change lcd controller's data buffer to lcd_frame[0]*/ + lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame[0]); + if ( rotate_angle == FB_ROTATE_UR || \ + jzlcd_info->rotate_daemon_thread == NULL) + jzlcd_info->rotate_daemon_thread = kthread_run( jzfb_rotate_daemon_thread, jzlcd_info, "%s", "jzlcd-rotate-daemon"); /* start rotate daemon */ + rotate_angle = angle; + break; + default: + printk("Invalid angle(%d)\n", (unsigned int)angle); + } + fb->fix.line_length = fb->var.xres * CONFIG_JZLCD_FRAMEBUFFER_BPP/8; + dma_cache_wback_inv((unsigned int)(lcd_frame_desc0), sizeof(struct lcd_desc)); + return 0; +} + +void jzfb_fb_rotate(struct fb_info *fbi, int angle) +{ + jzfb_rotate_change( angle/90 ); +} +#endif /* #if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ + +static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int jzfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + unsigned short *ptr, ctmp; + +// print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); + if (regno >= NR_PALETTE) + return 1; + + cfb->palette[regno].red = red ; + cfb->palette[regno].green = green; + cfb->palette[regno].blue = blue; + if (cfb->fb.var.bits_per_pixel <= 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + + red &= 0xff; + green &= 0xff; + blue &= 0xff; + } + switch (cfb->fb.var.bits_per_pixel) { + case 1: + case 2: + case 4: + case 8: + if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { + ctmp = (77L * red + 150L * green + 29L * blue) >> 8; + ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | + (ctmp >> 3); + } else { + /* RGB 565 */ + if (((red >> 3) == 0) && ((red >> 2) != 0)) + red = 1 << 3; + if (((blue >> 3) == 0) && ((blue >> 2) != 0)) + blue = 1 << 3; + ctmp = ((red >> 3) << 11) + | ((green >> 2) << 5) | (blue >> 3); + } + + ptr = (unsigned short *)lcd_palette; + ptr = (unsigned short *)(((u32)ptr)|0xa0000000); + ptr[regno] = ctmp; + + break; + + case 15: + if (regno < 16) + ((u32 *)cfb->fb.pseudo_palette)[regno] = + ((red >> 3) << 10) | + ((green >> 3) << 5) | + (blue >> 3); + break; + case 16: + if (regno < 16) { + ((u32 *)cfb->fb.pseudo_palette)[regno] = + ((red >> 3) << 11) | + ((green >> 2) << 5) | + (blue >> 3); + } + break; + case 18: + case 24: + case 32: + if (regno < 16) + ((u32 *)cfb->fb.pseudo_palette)[regno] = + (red << 16) | + (green << 8) | + (blue << 0); + +/* if (regno < 16) { + unsigned val; + val = chan_to_field(red, &cfb->fb.var.red); + val |= chan_to_field(green, &cfb->fb.var.green); + val |= chan_to_field(blue, &cfb->fb.var.blue); + ((u32 *)cfb->fb.pseudo_palette)[regno] = val; + } +*/ + + break; + } + return 0; +} + + +static int jzfb_ioctl (struct fb_info *fb, unsigned int cmd, unsigned long arg ) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + + switch (cmd) { + case FBIOSETBACKLIGHT: + __lcd_set_backlight_level(arg); /* We support 8 levels here. */ + break; + case FBIODISPON: + __lcd_display_on(); + break; + case FBIODISPOFF: + __lcd_display_off(); + break; + case FBIOPRINT_REGS: + print_regs(); + break; + case FBIOGETBUFADDRS: + if ( copy_to_user(argp, &jz_lcd_buffer_addrs, + sizeof(struct jz_lcd_buffer_addrs_t)) ) + return -EFAULT; + break; +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + case FBIOROTATE: + ret = jzfb_rotate_change(arg); + break; +#endif /* defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ + default: + printk("Warn: Command(%x) not support\n", cmd); + ret = -1; + break; + } + return ret; + +} + +/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ +static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + unsigned long start; + unsigned long off; + u32 len; + + off = vma->vm_pgoff << PAGE_SHIFT; + //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); + + /* frame buffer memory */ + start = cfb->fb.fix.smem_start; + len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); + start &= PAGE_MASK; + + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + off += start; + + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ + +#if 1 + pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; + pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ +// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Through */ +#endif + + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { + return -EAGAIN; + } + return 0; +} + +/* checks var and eventually tweaks it to something supported, + * DO NOT MODIFY PAR */ +static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + print_dbg("jzfb_check_var"); + return 0; +} + + +/* + * set the video mode according to info->var + */ +static int jzfb_set_par(struct fb_info *info) +{ + print_dbg("jzfb_set_par"); + return 0; +} + + +/* + * (Un)Blank the display. + * Fix me: should we use VESA value? + */ +static int jzfb_blank(int blank_mode, struct fb_info *info) +{ + + dprintk("fb_blank %d %p", blank_mode, info); + + switch (blank_mode) { + + case FB_BLANK_UNBLANK: + //case FB_BLANK_NORMAL: + /* Turn on panel */ + __lcd_set_ena(); + __lcd_display_on(); + break; + + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: +#if 0 + /* Turn off panel */ + __lcd_set_dis(); + __lcd_display_off(); +#endif + break; + default: + break; + + } + return 0; +} + +/* + * pan display + */ +static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + int dy; + + if (!var || !cfb) { + return -EINVAL; + } + + if (var->xoffset - cfb->fb.var.xoffset) { + /* No support for X panning for now! */ + return -EINVAL; + } + + dy = var->yoffset - cfb->fb.var.yoffset; + print_dbg("var.yoffset: %d", dy); + if (dy) { + + print_dbg("Panning screen of %d lines", dy); + + lcd_frame_desc0->databuf += (cfb->fb.fix.line_length * dy); + /* TODO: Wait for current frame to finished */ + } + + return 0; +} + + +/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ +static struct fb_ops jzfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = jzfb_setcolreg, + .fb_check_var = jzfb_check_var, + .fb_set_par = jzfb_set_par, + .fb_blank = jzfb_blank, + .fb_pan_display = jzfb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_mmap = jzfb_mmap, + .fb_ioctl = jzfb_ioctl, +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + .fb_rotate = jzfb_fb_rotate, +#endif +}; + +static int jzfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; + int chgvar = 0; + + var->height = jzfb.h ; + var->width = jzfb.w ; + var->bits_per_pixel = jzfb.bpp; + + var->vmode = FB_VMODE_NONINTERLACED; + var->activate = cfb->fb.var.activate; + var->xres = var->width; + var->yres = var->height; + var->xres_virtual = var->width; + var->yres_virtual = var->height; + var->xoffset = 0; + var->yoffset = 0; + var->pixclock = 0; + var->left_margin = 0; + var->right_margin = 0; + var->upper_margin = 0; + var->lower_margin = 0; + var->hsync_len = 0; + var->vsync_len = 0; + var->sync = 0; + var->activate &= ~FB_ACTIVATE_TEST; + + /* + * CONUPDATE and SMOOTH_XPAN are equal. However, + * SMOOTH_XPAN is only used internally by fbcon. + */ + if (var->vmode & FB_VMODE_CONUPDATE) { + var->vmode |= FB_VMODE_YWRAP; + var->xoffset = cfb->fb.var.xoffset; + var->yoffset = cfb->fb.var.yoffset; + } + + if (var->activate & FB_ACTIVATE_TEST) + return 0; + + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) + return -EINVAL; + + if (cfb->fb.var.xres != var->xres) + chgvar = 1; + if (cfb->fb.var.yres != var->yres) + chgvar = 1; + if (cfb->fb.var.xres_virtual != var->xres_virtual) + chgvar = 1; + if (cfb->fb.var.yres_virtual != var->yres_virtual) + chgvar = 1; + if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) + chgvar = 1; + + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + + switch(var->bits_per_pixel){ + case 1: /* Mono */ + cfb->fb.fix.visual = FB_VISUAL_MONO01; + cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; + break; + case 2: /* Mono */ + var->red.offset = 0; + var->red.length = 2; + var->green.offset = 0; + var->green.length = 2; + var->blue.offset = 0; + var->blue.length = 2; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; + break; + case 4: /* PSEUDOCOLOUR*/ + var->red.offset = 0; + var->red.length = 4; + var->green.offset = 0; + var->green.length = 4; + var->blue.offset = 0; + var->blue.length = 4; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->fb.fix.line_length = var->xres / 2; + break; + case 8: /* PSEUDOCOLOUR, 256 */ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->fb.fix.line_length = var->xres ; + break; + case 15: /* DIRECTCOLOUR, 32k */ + var->bits_per_pixel = 15; + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + + cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; + cfb->fb.fix.line_length = var->xres_virtual * 2; + break; + case 16: /* DIRECTCOLOUR, 64k */ + var->bits_per_pixel = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + cfb->fb.fix.line_length = var->xres_virtual * 2; + break; + case 18: + case 24: + case 32: + /* DIRECTCOLOUR, 16M */ + var->bits_per_pixel = 32; + + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + cfb->fb.fix.line_length = var->xres_virtual * 4; + break; + + default: /* in theory this should never happen */ + printk(KERN_WARNING "%s: don't support for %dbpp\n", + cfb->fb.fix.id, var->bits_per_pixel); + break; + } + + cfb->fb.var = *var; + cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; + + /* + * Update the old var. The fbcon drivers still use this. + * Once they are using cfb->fb.var, this can be dropped. + * --rmk + */ + //display->var = cfb->fb.var; + /* + * If we are setting all the virtual consoles, also set the + * defaults used to create new consoles. + */ + fb_set_cmap(&cfb->fb.cmap, &cfb->fb); + dprintk("jzfb_set_var: after fb_set_cmap...\n"); + + return 0; +} + +static struct lcd_cfb_info * jzfb_alloc_fb_info(void) +{ + struct lcd_cfb_info *cfb; + + cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); + + if (!cfb) + return NULL; + + jzlcd_info = cfb; + + memset(cfb, 0, sizeof(struct lcd_cfb_info) ); + + cfb->currcon = -1; + + + strcpy(cfb->fb.fix.id, "jz-lcd"); + cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + cfb->fb.fix.type_aux = 0; + cfb->fb.fix.xpanstep = 1; + cfb->fb.fix.ypanstep = 1; + cfb->fb.fix.ywrapstep = 0; + cfb->fb.fix.accel = FB_ACCEL_NONE; + + cfb->fb.var.nonstd = 0; + cfb->fb.var.activate = FB_ACTIVATE_NOW; + cfb->fb.var.height = -1; + cfb->fb.var.width = -1; + cfb->fb.var.accel_flags = FB_ACCELF_TEXT; + + cfb->fb.fbops = &jzfb_ops; + cfb->fb.flags = FBINFO_FLAG_DEFAULT; + + cfb->fb.pseudo_palette = (void *)(cfb + 1); + + switch (jzfb.bpp) { + case 1: + fb_alloc_cmap(&cfb->fb.cmap, 4, 0); + break; + case 2: + fb_alloc_cmap(&cfb->fb.cmap, 8, 0); + break; + case 4: + fb_alloc_cmap(&cfb->fb.cmap, 32, 0); + break; + case 8: + + default: + fb_alloc_cmap(&cfb->fb.cmap, 256, 0); + break; + } + dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); + + return cfb; +} + +/* + * Map screen memory + */ +static int jzfb_map_smem(struct lcd_cfb_info *cfb) +{ + struct page * map = NULL; + unsigned char *tmp; + unsigned int page_shift, needroom, t; +#if defined(CONFIG_SOC_JZ4740) + if (jzfb.bpp == 18 || jzfb.bpp == 24) + t = 32; + else + t = jzfb.bpp; +#else + if (jzfb.bpp == 15) + t = 16; + else + t = jzfb.bpp; +#endif + + needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; + for (page_shift = 0; page_shift < 12; page_shift++) + if ((PAGE_SIZE << page_shift) >= needroom) + break; + + /* lcd_palette room total 4KB: + * 0 -- 512: lcd palette + * 1024 -- [1024+16*3]: lcd descripters + * [1024+16*3] -- 4096: reserved + */ + lcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); + if ((!lcd_palette)) + return -ENOMEM; + + memset((void *)lcd_palette, 0, PAGE_SIZE); + map = virt_to_page(lcd_palette); + set_bit(PG_reserved, &map->flags); + lcd_desc_base = (struct lcd_desc *)(lcd_palette + 1024); + + jz_lcd_buffer_addrs.fb_num = CONFIG_JZLCD_FRAMEBUFFER_MAX; + printk("jzlcd use %d framebuffer:\n", CONFIG_JZLCD_FRAMEBUFFER_MAX); + /* alloc frame buffer space */ + for ( t = 0; t < CONFIG_JZLCD_FRAMEBUFFER_MAX; t++ ) { + lcd_frame[t] = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); + if ((!lcd_frame[t])) { + printk("no mem for fb[%d]\n", t); + return -ENOMEM; + } +// memset((void *)lcd_frame[t], 0, PAGE_SIZE << page_shift); + for (tmp=(unsigned char *)lcd_frame[t]; + tmp < lcd_frame[t] + (PAGE_SIZE << page_shift); + tmp += PAGE_SIZE) { + map = virt_to_page(tmp); + set_bit(PG_reserved, &map->flags); + } + jz_lcd_buffer_addrs.fb_phys_addr[t] = virt_to_phys((void *)lcd_frame[t]); + printk("jzlcd fb[%d] phys addr =0x%08x\n", + t, jz_lcd_buffer_addrs.fb_phys_addr[t]); + } +#if !defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + cfb->fb.fix.smem_start = virt_to_phys((void *)lcd_frame[0]); + cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); + cfb->fb.screen_base = + (unsigned char *)(((unsigned int)lcd_frame[0] & 0x1fffffff) | 0xa0000000); +#else /* Framebuffer rotate */ + lcd_frame_user_fb = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); + if ((!lcd_frame_user_fb)) { + printk("no mem for fb[%d]\n", t); + return -ENOMEM; + } + memset((void *)lcd_frame_user_fb, 0, PAGE_SIZE << page_shift); + for (tmp=(unsigned char *)lcd_frame_user_fb; + tmp < lcd_frame_user_fb + (PAGE_SIZE << page_shift); + tmp += PAGE_SIZE) { + map = virt_to_page(tmp); + set_bit(PG_reserved, &map->flags); + } + + printk("Rotate userfb phys addr =0x%08x\n", + (unsigned int)virt_to_phys((void *)lcd_frame_user_fb)); + cfb->fb.fix.smem_start = virt_to_phys((void *)lcd_frame_user_fb); + cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); + cfb->fb.screen_base = (unsigned char *)(((unsigned int)lcd_frame_user_fb & 0x1fffffff) | 0xa0000000); + +#endif /* #if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ + if (!cfb->fb.screen_base) { + printk("%s: unable to map screen memory\n", cfb->fb.fix.id); + return -ENOMEM; + } + + return 0; +} + +static void jzfb_free_fb_info(struct lcd_cfb_info *cfb) +{ + if (cfb) { + fb_alloc_cmap(&cfb->fb.cmap, 0, 0); + kfree(cfb); + } +} + +static void jzfb_unmap_smem(struct lcd_cfb_info *cfb) +{ + struct page * map = NULL; + unsigned char *tmp; + unsigned int page_shift, needroom, t; +#if defined(CONFIG_SOC_JZ4740) + if (jzfb.bpp == 18 || jzfb.bpp == 24) + t = 32; + else + t = jzfb.bpp; +#else + if (jzfb.bpp == 15) + t = 16; + else + t = jzfb.bpp; +#endif + needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; + for (page_shift = 0; page_shift < 12; page_shift++) + if ((PAGE_SIZE << page_shift) >= needroom) + break; + + if (cfb && cfb->fb.screen_base) { + iounmap(cfb->fb.screen_base); + cfb->fb.screen_base = NULL; + release_mem_region(cfb->fb.fix.smem_start, + cfb->fb.fix.smem_len); + } + + if (lcd_palette) { + map = virt_to_page(lcd_palette); + clear_bit(PG_reserved, &map->flags); + free_pages((int)lcd_palette, 0); + } + + for ( t=0; t < CONFIG_JZLCD_FRAMEBUFFER_MAX; t++ ) { + if (lcd_frame[t]) { + for (tmp=(unsigned char *)lcd_frame[t]; + tmp < lcd_frame[t] + (PAGE_SIZE << page_shift); + tmp += PAGE_SIZE) { + map = virt_to_page(tmp); + clear_bit(PG_reserved, &map->flags); + } + free_pages((int)lcd_frame[t], page_shift); + } + } +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + if (lcd_frame_user_fb) { + for (tmp=(unsigned char *)lcd_frame_user_fb; + tmp < lcd_frame_user_fb + (PAGE_SIZE << page_shift); + tmp += PAGE_SIZE) { + map = virt_to_page(tmp); + clear_bit(PG_reserved, &map->flags); + } + free_pages((int)lcd_frame_user_fb, page_shift); + } + +#endif +} + +static void lcd_descriptor_init(void) +{ + int i; + unsigned int pal_size; + unsigned int frm_size, ln_size; + unsigned char dual_panel = 0; + + i = jzfb.bpp; +#if defined(CONFIG_SOC_JZ4740) + if (i == 18 || i == 24) + i = 32; +#else + if (i == 15) + i = 16; +#endif + frm_size = (jzfb.w*jzfb.h*i)>>3; + ln_size = (jzfb.w*i)>>3; + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { + dual_panel = 1; + frm_size >>= 1; + } + + frm_size = frm_size / 4; + ln_size = ln_size / 4; + + switch (jzfb.bpp) { + case 1: + pal_size = 4; + break; + case 2: + pal_size = 8; + break; + case 4: + pal_size = 32; + break; + case 8: + default: + pal_size = 512; + } + + pal_size /= 4; + + lcd_frame_desc0 = lcd_desc_base + 0; + lcd_frame_desc1 = lcd_desc_base + 1; + lcd_palette_desc = lcd_desc_base + 2; + + jz_lcd_buffer_addrs.lcd_desc_phys_addr = (unsigned int)virt_to_phys(lcd_frame_desc0); + + /* Palette Descriptor */ + lcd_palette_desc->next_desc = (int)virt_to_phys(lcd_frame_desc0); + lcd_palette_desc->databuf = (int)virt_to_phys((void *)lcd_palette); + lcd_palette_desc->frame_id = (unsigned int)0xdeadbeaf; + lcd_palette_desc->cmd = pal_size|LCD_CMD_PAL; /* Palette Descriptor */ + + /* Frame Descriptor 0 */ + if (jzfb.bpp <= 8) + lcd_frame_desc0->next_desc = (int)virt_to_phys(lcd_palette_desc); + else + lcd_frame_desc0->next_desc = (int)virt_to_phys(lcd_frame_desc0); + lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame[0]); + lcd_frame_desc0->frame_id = (unsigned int)0xbeafbeaf; + lcd_frame_desc0->cmd = LCD_CMD_SOFINT | LCD_CMD_EOFINT | frm_size; + dma_cache_wback_inv((unsigned int)(lcd_palette_desc),0x10); + dma_cache_wback_inv((unsigned int)(lcd_frame_desc0),0x10); + + if (!(dual_panel)) + return; + + /* Frame Descriptor 1 */ + lcd_frame_desc1->next_desc = (int)virt_to_phys(lcd_frame_desc1); + lcd_frame_desc1->databuf = virt_to_phys((void *)(lcd_frame[0] + frm_size * 4)); + lcd_frame_desc1->frame_id = (unsigned int)0xdeaddead; + lcd_frame_desc1->cmd = LCD_CMD_SOFINT | LCD_CMD_EOFINT | frm_size; + dma_cache_wback_inv((unsigned int)(lcd_frame_desc1),0x10); +} + +static int lcd_hw_init(void) +{ + unsigned int val = 0; + unsigned int pclk; + unsigned int stnH; + int ret = 0; + + /* Setting Control register */ + switch (jzfb.bpp) { + case 1: + val |= LCD_CTRL_BPP_1; + break; + case 2: + val |= LCD_CTRL_BPP_2; + break; + case 4: + val |= LCD_CTRL_BPP_4; + break; + case 8: + val |= LCD_CTRL_BPP_8; + break; + case 15: + val |= LCD_CTRL_RGB555; + case 16: + val |= LCD_CTRL_BPP_16; + break; +#if defined(CONFIG_SOC_JZ4740) + case 17 ... 32: + val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */ + break; +#endif + default: + printk("The BPP %d is not supported\n", jzfb.bpp); + val |= LCD_CTRL_BPP_16; + break; + } + + switch (jzfb.cfg & MODE_MASK) { + case MODE_STN_MONO_DUAL: + case MODE_STN_COLOR_DUAL: + case MODE_STN_MONO_SINGLE: + case MODE_STN_COLOR_SINGLE: + switch (jzfb.bpp) { + case 1: + case 2: + val |= LCD_CTRL_FRC_2; + break; + case 4: + val |= LCD_CTRL_FRC_4; + break; + case 8: + default: + val |= LCD_CTRL_FRC_16; + break; + } + break; + } + + val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ + + switch (jzfb.cfg & MODE_MASK) { + case MODE_STN_MONO_DUAL: + case MODE_STN_COLOR_DUAL: + case MODE_STN_MONO_SINGLE: + case MODE_STN_COLOR_SINGLE: + switch (jzfb.cfg & STN_DAT_PINMASK) { +#define align2(n) (n)=((((n)+1)>>1)<<1) +#define align4(n) (n)=((((n)+3)>>2)<<2) +#define align8(n) (n)=((((n)+7)>>3)<<3) + case STN_DAT_PIN1: + /* Do not adjust the hori-param value. */ + break; + case STN_DAT_PIN2: + align2(jzfb.hsw); + align2(jzfb.elw); + align2(jzfb.blw); + break; + case STN_DAT_PIN4: + align4(jzfb.hsw); + align4(jzfb.elw); + align4(jzfb.blw); + break; + case STN_DAT_PIN8: + align8(jzfb.hsw); + align8(jzfb.elw); + align8(jzfb.blw); + break; + } + break; + } + + val |= 1 << 26; /* Output FIFO underrun protection */ + REG_LCD_CTRL = val; + + switch (jzfb.cfg & MODE_MASK) { + case MODE_STN_MONO_DUAL: + case MODE_STN_COLOR_DUAL: + case MODE_STN_MONO_SINGLE: + case MODE_STN_COLOR_SINGLE: + if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) + stnH = jzfb.h >> 1; + else + stnH = jzfb.h; + + REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; + REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw); + + /* Screen setting */ + REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw); + REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w); + REG_LCD_DAV = (0 << 16) | (stnH); + + /* AC BIAs signal */ + REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw); + + break; + + case MODE_TFT_GEN: + case MODE_TFT_SHARP: + case MODE_TFT_CASIO: + case MODE_TFT_SAMSUNG: + case MODE_8BIT_SERIAL_TFT: + case MODE_TFT_18BIT: + REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; +#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42) + REG_LCD_DAV = (0 << 16) | ( jzfb.h ); +#else + REG_LCD_DAV = ((jzfb.vsw + jzfb.bfw) << 16) | (jzfb.vsw + jzfb.bfw + jzfb.h); +#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ + REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw); + REG_LCD_HSYNC = (0 << 16) | jzfb.hsw; + REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w); + break; + } + + switch (jzfb.cfg & MODE_MASK) { + case MODE_TFT_SAMSUNG: + { + unsigned int total, tp_s, tp_e, ckv_s, ckv_e; + unsigned int rev_s, rev_e, inv_s, inv_e; + total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; + tp_s = jzfb.blw + jzfb.w + 1; + tp_e = tp_s + 1; + ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); + ckv_e = tp_s + total; + rev_s = tp_s - 11; /* -11.5 clk */ + rev_e = rev_s + total; + inv_s = tp_s; + inv_e = inv_s + total; + REG_LCD_CLS = (tp_s << 16) | tp_e; + REG_LCD_PS = (ckv_s << 16) | ckv_e; + REG_LCD_SPL = (rev_s << 16) | rev_e; + REG_LCD_REV = (inv_s << 16) | inv_e; + jzfb.cfg |= STFT_REVHI | STFT_SPLHI; + break; + } + case MODE_TFT_SHARP: + { + unsigned int total, cls_s, cls_e, ps_s, ps_e; + unsigned int spl_s, spl_e, rev_s, rev_e; + total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; +#if !defined(CONFIG_JZLCD_INNOLUX_AT080TN42) + spl_s = 1; + spl_e = spl_s + 1; + cls_s = 0; + cls_e = total - 60; /* > 4us (pclk = 80ns) */ + ps_s = cls_s; + ps_e = cls_e; + rev_s = total - 40; /* > 3us (pclk = 80ns) */ + rev_e = rev_s + total; + jzfb.cfg |= STFT_PSHI; +#else /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ + spl_s = total - 5; /* LD */ + spl_e = total - 3; + cls_s = 32; /* CKV */ + cls_e = 145; + ps_s = 0; /* OEV */ + ps_e = 45; + rev_s = 0; /* POL */ + rev_e = 0; +#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ + REG_LCD_SPL = (spl_s << 16) | spl_e; + REG_LCD_CLS = (cls_s << 16) | cls_e; + REG_LCD_PS = (ps_s << 16) | ps_e; + REG_LCD_REV = (rev_s << 16) | rev_e; + break; + } + case MODE_TFT_CASIO: + break; + } + + /* Configure the LCD panel */ + REG_LCD_CFG = jzfb.cfg; + + /* Timing setting */ + __cpm_stop_lcd(); + + val = jzfb.fclk; /* frame clk */ + + if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) { + pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ + } + else { + /* serial mode: Hsync period = 3*Width_Pixel */ + pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) * + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ + } + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) + pclk = (pclk * 3); + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) + pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4); + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) + pclk >>= 1; +#if defined(CONFIG_SOC_JZ4730) + val = __cpm_get_pllout() / pclk; + REG_CPM_CFCR2 = val - 1; + val = __cpm_get_pllout() / (pclk * 4); + val = __cpm_divisor_encode(val); + __cpm_set_lcdclk_div(val); + REG_CPM_CFCR |= CPM_CFCR_UPE; +#elif defined(CONFIG_SOC_JZ4740) + val = ( __cpm_get_pllout2()) / pclk; + val--; + if ( val > 0x3ff ) { + printk("pixel clock divid is too large, set it to 0x3ff\n"); + val = 0x3ff; + } + __cpm_set_pixdiv(val); + + val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ + val =__cpm_get_pllout() / val; + if ( val > 0x1f ) { + printk("lcd clock divide is too large, set it to 0x1f\n"); + val = 0x1f; + } + __cpm_set_ldiv( val ); + REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ + +#else + printk("drivers/video/Jzlcd.c, CONFIG_MIPS, please set chip type.\n"); +#endif /*#ifdef CONFIG_MIPS_JZ4730 */ + + jz_clocks.pixclk = __cpm_get_pixclk(); + jz_clocks.lcdclk = __cpm_get_lcdclk(); + printk("LCDC: PixClock:%d LcdClock:%d\n", + jz_clocks.pixclk, jz_clocks.lcdclk); + + __cpm_start_lcd(); + udelay(1000); + return ret; +} + +static irqreturn_t lcd_interrupt_handler(int irq, void *dev_id) +{ + unsigned int state; + + state = REG_LCD_STATE; + + if (state & LCD_STATE_EOF) /* End of frame */ + REG_LCD_STATE = state & ~LCD_STATE_EOF; + + if (state & LCD_STATE_IFU0) { + dprintk("InFiFo0 underrun\n"); + REG_LCD_STATE = state & ~LCD_STATE_IFU0; + } + + if (state & LCD_STATE_OFU) { /* Out fifo underrun */ + REG_LCD_STATE = state & ~LCD_STATE_OFU; + dprintk("Out FiFo underrun.\n"); + } + return IRQ_HANDLED; +} + +#ifdef CONFIG_PM + +/* + * Suspend the LCDC. + */ +static int jzfb_suspend(struct platform_device *pdev, pm_message_t state) +{ + __lcd_clr_ena(); /* Quick Disable */ + __lcd_display_off(); + __cpm_stop_lcd(); + + return 0; +} + +/* + * Resume the LCDC. + */ +#ifdef CONFIG_SOC_JZ4730 +static int jzfb_resume(struct platform_device *pdev, pm_message_t state) +{ + __cpm_start_lcd(); + + __lcd_display_pin_init(); + + __lcd_display_on(); + + lcd_hw_init(); + + if (jzfb.bpp <= 8) + REG_LCD_DA0 = virt_to_phys(lcd_palette_desc); + else + REG_LCD_DA0 = virt_to_phys(lcd_frame_desc0); + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) + REG_LCD_DA1 = virt_to_phys(lcd_frame_desc1); + + __lcd_set_ena(); + return 0; +} + +#else +/* + * Resume the LCDC. + */ +static int jzfb_resume(struct platform_device *pdev, pm_message_t state) +{ + __cpm_start_lcd(); + __gpio_set_pin(GPIO_DISP_OFF_N); + __lcd_special_on(); + __lcd_set_ena(); + mdelay(200); + __lcd_set_backlight_level(80); + + return 0; +} +#endif /* CONFIG_MIPS_JZ4730 */ +#else /* CONFIG_PM */ +#define jzfb_suspend NULL +#define jzfb_resume NULL +#endif /* CONFIG_PM */ + +static int __init jzfb_probe(struct platform_device *pdev) +{ + struct lcd_cfb_info *cfb; + int err = 0; + + /* In special mode, we only need init special pin, + * as general lcd pin has init in uboot */ +#if defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) + switch (jzfb.cfg & MODE_MASK) { + case LCD_CFG_MODE_SPECIAL_TFT_1: + case LCD_CFG_MODE_SPECIAL_TFT_2: + case LCD_CFG_MODE_SPECIAL_TFT_3: + __gpio_as_lcd_special(); + break; + default: + ; + } +#endif + __lcd_display_pin_init(); + + cfb = jzfb_alloc_fb_info(); + if (!cfb) + goto failed; + + err = jzfb_map_smem(cfb); + if (err) + goto failed; + + jzfb_set_var(&cfb->fb.var, -1, &cfb->fb); + + lcd_descriptor_init(); + + err = lcd_hw_init(); + if (err) + goto failed; + + if (jzfb.bpp <= 8) + REG_LCD_DA0 = virt_to_phys(lcd_palette_desc); + else + REG_LCD_DA0 = virt_to_phys(lcd_frame_desc0); + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) + REG_LCD_DA1 = virt_to_phys(lcd_frame_desc1); + + __lcd_set_ena(); + + if (request_irq(IRQ_LCD, lcd_interrupt_handler, IRQF_DISABLED, + "lcd", 0)) { + err = -EBUSY; + goto failed; + } + + __lcd_enable_ofu_intr(); /* enable OutFifo underrun */ +// __lcd_enable_ifu0_intr(); /* needn't enable InFifo underrun */ + +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + jzfb_rotate_change(rotate_angle); + /* sleep n??? */ +#endif + err = register_framebuffer(&cfb->fb); + if (err < 0) { + dprintk("jzfb_init(): register framebuffer err.\n"); + goto failed; + } + + printk("fb%d: %s frame buffer device, using %dK of video memory\n", + cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); + + __lcd_display_on(); + + return 0; + +failed: + jzfb_unmap_smem(cfb); + jzfb_free_fb_info(cfb); + + return err; +} + +static int jzfb_remove(struct device *dev) +{ + struct lcd_cfb_info *cfb = dev_get_drvdata(dev); + jzfb_unmap_smem(cfb); + jzfb_free_fb_info(cfb); + return 0; +} + +static struct platform_driver jz_lcd_driver = { + .probe = jzfb_probe, + .remove = jzfb_remove, +#ifdef CONFIG_PM + .suspend = jzfb_suspend, + .resume = jzfb_resume, +#endif + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init jzfb_init(void) +{ + return platform_driver_register(&jz_lcd_driver); +} + +static void __exit jzfb_cleanup(void) +{ +#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) + kthread_stop(jzlcd_info->rotate_daemon_thread); +#endif + platform_driver_unregister(&jz_lcd_driver); +} + +module_init(jzfb_init); +module_exit(jzfb_cleanup); + +MODULE_DESCRIPTION("JzSOC LCD Controller driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/drivers/video/jzlcd.h b/target/linux/xburst/files-2.6.31/drivers/video/jzlcd.h new file mode 100755 index 000000000..3676b9bc6 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/drivers/video/jzlcd.h @@ -0,0 +1,791 @@ +/* + * linux/drivers/video/jzlcd.h -- Ingenic On-Chip LCD frame buffer device + * + * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#ifndef __JZLCD_H__ +#define __JZLCD_H__ + +#include + +#define NR_PALETTE 256 + +struct lcd_desc{ + unsigned int next_desc; /* LCDDAx */ + unsigned int databuf; /* LCDSAx */ + unsigned int frame_id; /* LCDFIDx */ + unsigned int cmd; /* LCDCMDx */ +}; + +#define MODE_MASK 0x0f +#define MODE_TFT_GEN 0x00 +#define MODE_TFT_SHARP 0x01 +#define MODE_TFT_CASIO 0x02 +#define MODE_TFT_SAMSUNG 0x03 +#define MODE_CCIR656_NONINT 0x04 +#define MODE_CCIR656_INT 0x05 +#define MODE_STN_COLOR_SINGLE 0x08 +#define MODE_STN_MONO_SINGLE 0x09 +#define MODE_STN_COLOR_DUAL 0x0a +#define MODE_STN_MONO_DUAL 0x0b +#define MODE_8BIT_SERIAL_TFT 0x0c + +#define MODE_TFT_18BIT (1<<7) + +#define STN_DAT_PIN1 (0x00 << 4) +#define STN_DAT_PIN2 (0x01 << 4) +#define STN_DAT_PIN4 (0x02 << 4) +#define STN_DAT_PIN8 (0x03 << 4) +#define STN_DAT_PINMASK STN_DAT_PIN8 + +#define STFT_PSHI (1 << 15) +#define STFT_CLSHI (1 << 14) +#define STFT_SPLHI (1 << 13) +#define STFT_REVHI (1 << 12) + +#define SYNC_MASTER (0 << 16) +#define SYNC_SLAVE (1 << 16) + +#define DE_P (0 << 9) +#define DE_N (1 << 9) + +#define PCLK_P (0 << 10) +#define PCLK_N (1 << 10) + +#define HSYNC_P (0 << 11) +#define HSYNC_N (1 << 11) + +#define VSYNC_P (0 << 8) +#define VSYNC_N (1 << 8) + +#define DATA_NORMAL (0 << 17) +#define DATA_INVERSE (1 << 17) + + +/* Jz LCDFB supported I/O controls. */ +#define FBIOSETBACKLIGHT 0x4688 +#define FBIODISPON 0x4689 +#define FBIODISPOFF 0x468a +#define FBIORESET 0x468b +#define FBIOPRINT_REGS 0x468c +#define FBIOGETBUFADDRS 0x468d +#define FBIOROTATE 0x46a0 /* rotated fb */ + +struct jz_lcd_buffer_addrs_t { + int fb_num; + unsigned int lcd_desc_phys_addr; + unsigned int fb_phys_addr[CONFIG_JZLCD_FRAMEBUFFER_MAX]; +}; + + +/* + * LCD panel specific definition + */ +#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW) + +#if defined(CONFIG_JZ4730_PMP) +#define LCD_RESET_PIN 63 +#endif + +#define __lcd_special_on() \ +do { \ + __gpio_set_pin(LCD_RESET_PIN); \ + __gpio_as_output(LCD_RESET_PIN); \ + __gpio_clear_pin(LCD_RESET_PIN); \ + udelay(100); \ + __gpio_set_pin(LCD_RESET_PIN); \ +} while (0) + +#endif /* CONFIG_JZLCD_TRULY_TFTG320240DTSW */ + +#if defined(CONFIG_JZLCD_SAMSUNG_LTV350QVF04) + +#if defined(CONFIG_JZ4730_FPRINT) +#define PortSDI 60 +#define PortSCL 61 +#define PortCS 62 +#define PortRST 63 +#define PortSht 64 +#endif + +#if defined(CONFIG_JZ4730_GPS) +#define PortSDI 74 +#define PortSCL 72 +#define PortCS 73 +#define PortRST 60 +#define PortSht 59 +#endif + +#ifndef PortSDI +#define PortSDI 0 +#endif +#ifndef PortSCL +#define PortSCL 0 +#endif +#ifndef PortCS +#define PortCS 0 +#endif +#ifndef PortRST +#define PortRST 0 +#endif +#ifndef PortSht +#define PortSht 0 +#endif + +#define __lcd_special_pin_init() \ +do { \ + __gpio_as_output(PortSDI); /* SDI */\ + __gpio_as_output(PortSCL); /* SCL */ \ + __gpio_as_output(PortCS); /* CS */ \ + __gpio_as_output(PortRST); /* Reset */ \ + __gpio_as_output(PortSht); /* Shut Down # */ \ + __gpio_set_pin(PortCS); \ + __gpio_set_pin(PortSCL); \ + __gpio_set_pin(PortSDI); \ +} while (0) + +#define __spi_out(val) \ +do { \ + int __i__; \ + unsigned int _t_ = (val); \ + __gpio_clear_pin(PortCS); \ + udelay(25); \ + for (__i__ = 0; __i__ < 24; __i__++ ) { \ + __gpio_clear_pin(PortSCL); \ + if (_t_ & 0x800000) \ + __gpio_set_pin(PortSDI); \ + else \ + __gpio_clear_pin(PortSDI); \ + _t_ <<= 1; \ + udelay(25); \ + __gpio_set_pin(PortSCL); \ + udelay(25); \ + } \ + __gpio_set_pin(PortCS); \ + udelay(25); \ + __gpio_set_pin(PortSDI); \ + udelay(25); \ + __gpio_set_pin(PortSCL); \ +} while (0) + +#define __spi_id_op_data(rs, rw, val) \ + __spi_out((0x1d<<18)|((rs)<<17)|((rw)<<16)|(val)) + +#define __spi_write_reg(reg, val) \ +do { \ + __spi_id_op_data(0, 0, (reg)); \ + __spi_id_op_data(1, 0, (val)); \ +} while (0) + +#define __lcd_special_on() \ +do { \ + __gpio_set_pin(PortSht); \ + __gpio_clear_pin(PortRST); \ + mdelay(10); \ + __gpio_set_pin(PortRST); \ + mdelay(1); \ + __spi_write_reg(0x09, 0); \ + mdelay(10); \ + __spi_write_reg(0x09, 0x4000); \ + __spi_write_reg(0x0a, 0x2000); \ + mdelay(40); \ + __spi_write_reg(0x09, 0x4055); \ + mdelay(50); \ + __spi_write_reg(0x01, 0x409d); \ + __spi_write_reg(0x02, 0x0204); \ + __spi_write_reg(0x03, 0x0100); \ + __spi_write_reg(0x04, 0x3000); \ + __spi_write_reg(0x05, 0x4003); \ + __spi_write_reg(0x06, 0x000a); \ + __spi_write_reg(0x07, 0x0021); \ + __spi_write_reg(0x08, 0x0c00); \ + __spi_write_reg(0x10, 0x0103); \ + __spi_write_reg(0x11, 0x0301); \ + __spi_write_reg(0x12, 0x1f0f); \ + __spi_write_reg(0x13, 0x1f0f); \ + __spi_write_reg(0x14, 0x0707); \ + __spi_write_reg(0x15, 0x0307); \ + __spi_write_reg(0x16, 0x0707); \ + __spi_write_reg(0x17, 0x0000); \ + __spi_write_reg(0x18, 0x0004); \ + __spi_write_reg(0x19, 0x0000); \ + mdelay(60); \ + __spi_write_reg(0x09, 0x4a55); \ + __spi_write_reg(0x05, 0x5003); \ +} while (0) + +#define __lcd_special_off() \ +do { \ + __spi_write_reg(0x09, 0x4055); \ + __spi_write_reg(0x05, 0x4003); \ + __spi_write_reg(0x0a, 0x0000); \ + mdelay(10); \ + __spi_write_reg(0x09, 0x4000); \ + __gpio_clear_pin(PortSht); \ +} while (0) + +#endif /* CONFIG_JZLCD_SAMSUNG_LTV350QVF04 */ + +#if defined(CONFIG_JZLCD_AUO_A030FL01_V1) +#if defined(CONFIG_JZ4740_PAVO) /* board pavo */ + #define SPEN (32*1+18) /*LCD_CS*/ + #define SPCK (32*1+17) /*LCD_SCL*/ + #define SPDA (32*2+12) /*LCD_SDA*/ + #define LCD_RET (32*2+23) /*use for lcd reset*/ +#elif defined(CONFIG_JZ4740_LYRA) /* board lyra */ + #define SPEN (32*3+19) //LCD_CS + #define SPCK (32*3+18) //LCD_SCL + #define SPDA (32*3+20) //LCD_SDA + #define LCD_RET (32*3+31) //use for lcd reset +#else +#error "driver/video/Jzlcd.h, please define SPI pins on your board." +#endif + +#define __spi_write_reg(reg, val) \ + do { \ + unsigned char no; \ + unsigned short value; \ + unsigned char a=0; \ + unsigned char b=0; \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + a=reg; \ + b=val; \ + __gpio_set_pin(SPEN); \ + __gpio_clear_pin(SPCK); \ + udelay(50); \ + __gpio_clear_pin(SPDA); \ + __gpio_clear_pin(SPEN); \ + udelay(50); \ + value=((a<<8)|(b&0xFF)); \ + for(no=0;no<16;no++) \ + { \ + if((value&0x8000)==0x8000){ \ + __gpio_set_pin(SPDA);} \ + else{ \ + __gpio_clear_pin(SPDA); } \ + udelay(400); \ + __gpio_set_pin(SPCK); \ + value=(value<<1); \ + udelay(50); \ + __gpio_clear_pin(SPCK); \ + } \ + __gpio_set_pin(SPEN); \ + udelay(400); \ + } while (0) +#define __spi_read_reg(reg,val) \ + do{ \ + unsigned char no; \ + unsigned short value; \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + value = ((reg << 0) | (1 << 7)); \ + val = 0; \ + __gpio_as_output(SPDA); \ + __gpio_set_pin(SPEN); \ + __gpio_set_pin(SPCK); \ + udelay(1); \ + __gpio_clear_pin(SPDA); \ + __gpio_clear_pin(SPEN); \ + udelay(1); \ + for (no = 0; no < 16; no++ ) { \ + __gpio_clear_pin(SPCK); \ + udelay(1); \ + if(no < 8) \ + { \ + if (value & 0x80) /* send data */ \ + __gpio_set_pin(SPDA); \ + else \ + __gpio_clear_pin(SPDA); \ + value = (value << 1); \ + udelay(1); \ + __gpio_set_pin(SPCK); \ + udelay(1); \ + } \ + else \ + { \ + __gpio_as_input(SPDA); \ + udelay(1); \ + __gpio_set_pin(SPCK); \ + udelay(1); \ + val = (val << 1); \ + val |= __gpio_get_pin(SPDA); \ + udelay(1); \ + } \ + udelay(400); \ + } \ + __gpio_as_output(SPDA); \ + __gpio_set_pin(SPEN); \ + udelay(400); \ + } while(0) + +#define __lcd_special_pin_init() \ + do { \ + __gpio_as_output(SPEN); /* use SPDA */ \ + __gpio_as_output(SPCK); /* use SPCK */ \ + __gpio_as_output(SPDA); /* use SPDA */ \ + __gpio_as_output(LCD_RET); \ + udelay(50); \ + __gpio_clear_pin(LCD_RET); \ + udelay(100); \ + __gpio_set_pin(LCD_RET); \ + } while (0) +#define __lcd_special_on() \ + do { \ + udelay(50); \ + __gpio_clear_pin(LCD_RET); \ + udelay(100); \ + __gpio_set_pin(LCD_RET); \ + __spi_write_reg(0x0D, 0x44); \ + __spi_write_reg(0x0D, 0x4D); \ + __spi_write_reg(0x0B, 0x06); \ + __spi_write_reg(0x40, 0xC0); \ + __spi_write_reg(0x42, 0x43); \ + __spi_write_reg(0x44, 0x28); \ + __spi_write_reg(0x0D, 0x4F); \ +} while (0) + + #define __lcd_special_off() \ + do { \ + __spi_write_reg(0x04, 0x4C); \ + } while (0) + +#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ + +//#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) +#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) || defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) + +#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) /* board pmp */ +#define MODE 0xcd /* 24bit parellel RGB */ +#endif +#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) +#define MODE 0xc9 /* 8bit serial RGB */ +#endif + +#if defined(CONFIG_JZ4730_PMP) + #define SPEN 60 //LCD_SPL + #define SPCK 61 //LCD_CLS + #define SPDA 62 //LCD_PS + #define LCD_RET 63 //LCD_REV //use for lcd reset +#elif defined(CONFIG_JZ4740_LEO) /* board leo */ + #define SPEN (32*1+18) //LCD_SPL + #define SPCK (32*1+17) //LCD_CLS + #define SPDA (32*2+22) //LCD_PS + #define LCD_RET (32*2+23) //LCD_REV //use for lcd reset +#elif defined(CONFIG_JZ4740_PAVO) /* board pavo */ + #define SPEN (32*1+18) //LCD_SPL + #define SPCK (32*1+17) //LCD_CLS + #define SPDA (32*2+12) //LCD_D12 + #define LCD_RET (32*2+23) //LCD_REV, GPC23 +#if 0 /*old driver*/ + #define SPEN (32*1+18) //LCD_SPL + #define SPCK (32*1+17) //LCD_CLS + #define SPDA (32*2+12) //LCD_D12 + #define LCD_RET (32*3+27) //PWM4 //use for lcd reset +#endif +#else +#error "driver/video/Jzlcd.h, please define SPI pins on your board." +#endif + + #define __spi_write_reg1(reg, val) \ + do { \ + unsigned char no;\ + unsigned short value;\ + unsigned char a=0;\ + unsigned char b=0;\ + a=reg;\ + b=val;\ + __gpio_set_pin(SPEN);\ + __gpio_set_pin(SPCK);\ + __gpio_clear_pin(SPDA);\ + __gpio_clear_pin(SPEN);\ + udelay(25);\ + value=((a<<8)|(b&0xFF));\ + for(no=0;no<16;no++)\ + {\ + __gpio_clear_pin(SPCK);\ + if((value&0x8000)==0x8000)\ + __gpio_set_pin(SPDA);\ + else\ + __gpio_clear_pin(SPDA);\ + udelay(25);\ + __gpio_set_pin(SPCK);\ + value=(value<<1); \ + udelay(25);\ + }\ + __gpio_set_pin(SPEN);\ + udelay(100);\ + } while (0) + + #define __spi_write_reg(reg, val) \ + do {\ + __spi_write_reg1((reg<<2|2), val); \ + udelay(100); \ + }while(0) + + #define __lcd_special_pin_init() \ + do { \ + __gpio_as_output(SPEN); /* use SPDA */\ + __gpio_as_output(SPCK); /* use SPCK */\ + __gpio_as_output(SPDA); /* use SPDA */\ + __gpio_as_output(LCD_RET);\ + udelay(50);\ + __gpio_clear_pin(LCD_RET);\ + mdelay(150);\ + __gpio_set_pin(LCD_RET);\ + } while (0) + + #define __lcd_special_on() \ + do { \ + udelay(50);\ + __gpio_clear_pin(LCD_RET);\ + mdelay(150);\ + __gpio_set_pin(LCD_RET);\ + mdelay(10);\ + __spi_write_reg(0x00, 0x03); \ + __spi_write_reg(0x01, 0x40); \ + __spi_write_reg(0x02, 0x11); \ + __spi_write_reg(0x03, MODE); /* mode */ \ + __spi_write_reg(0x04, 0x32); \ + __spi_write_reg(0x05, 0x0e); \ + __spi_write_reg(0x07, 0x03); \ + __spi_write_reg(0x08, 0x08); \ + __spi_write_reg(0x09, 0x32); \ + __spi_write_reg(0x0A, 0x88); \ + __spi_write_reg(0x0B, 0xc6); \ + __spi_write_reg(0x0C, 0x20); \ + __spi_write_reg(0x0D, 0x20); \ + } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level + +/* __spi_write_reg(0x02, 0x03); \ + __spi_write_reg(0x06, 0x40); \ + __spi_write_reg(0x0a, 0x11); \ + __spi_write_reg(0x0e, 0xcd); \ + __spi_write_reg(0x12, 0x32); \ + __spi_write_reg(0x16, 0x0e); \ + __spi_write_reg(0x1e, 0x03); \ + __spi_write_reg(0x22, 0x08); \ + __spi_write_reg(0x26, 0x40); \ + __spi_write_reg(0x2a, 0x88); \ + __spi_write_reg(0x2e, 0x88); \ + __spi_write_reg(0x32, 0x20); \ + __spi_write_reg(0x36, 0x20); \ +*/ +// } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level + + #define __lcd_special_off() \ + do { \ + __spi_write_reg(0x00, 0x03); \ + } while (0) + +#endif /* CONFIG_JZLCD_FOXCONN_PT035TN01 or CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL */ + + +#ifndef __lcd_special_pin_init +#define __lcd_special_pin_init() +#endif +#ifndef __lcd_special_on +#define __lcd_special_on() +#endif +#ifndef __lcd_special_off +#define __lcd_special_off() +#endif + + +/* + * Platform specific definition + */ + +#if defined(CONFIG_JZ4730_GPS) + +#define __lcd_set_backlight_level(n) \ +do { \ + ; \ +} while (0) + +#define __lcd_display_pin_init() \ +do { \ + __lcd_special_pin_init(); \ + __gpio_as_output(94); /* PWM0 pin */ \ + __gpio_as_output(95); /* PWM1 pin */ \ +} while (0) + +#define __lcd_display_on() \ +do { \ + __lcd_special_on(); \ + __gpio_set_pin(94); /* PWM0 pin */ \ + __gpio_set_pin(95); /* PWM1 pin */ \ + __lcd_set_backlight_level(8); \ +} while (0) + +#define __lcd_display_off() \ +do { \ + __lcd_special_off(); \ +} while (0) + +#endif /* CONFIG_JZ4730_GPS */ + +#if defined(CONFIG_JZ4730_FPRINT) + +#define __lcd_set_backlight_level(n) \ +do { \ + REG_PWM_DUT(0) = n; \ + REG_PWM_PER(0) = 7; \ + REG_PWM_CTR(0) = 0x81; \ +} while (0) + +#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) + +#define __lcd_display_pin_init() \ +do { \ + __lcd_special_pin_init();\ + __gpio_as_pwm();\ + __lcd_set_backlight_level(8);\ +} while (0) + +#define __lcd_display_on() \ +do { \ + __lcd_set_backlight_level(8); \ + __lcd_special_on();\ +} while (0) + +#define __lcd_display_off() \ +do { \ + __lcd_set_backlight_level(0); \ + __lcd_special_off();\ +} while (0) + +#else + +#define __lcd_display_pin_init() \ +do { \ + __gpio_as_output(GPIO_DISP_OFF_N); \ + __gpio_as_pwm(); \ + __lcd_set_backlight_level(8); \ +} while (0) + +#define __lcd_display_on() \ +do { \ + __lcd_set_backlight_level(8); \ + __gpio_set_pin(GPIO_DISP_OFF_N); \ +} while (0) + +#define __lcd_display_off() \ +do { \ + __lcd_set_backlight_level(0); \ + __gpio_clear_pin(GPIO_DISP_OFF_N); \ +} while (0) +#endif + +#endif /* CONFIG_JZ4730_FPRINT */ + +#if defined(CONFIG_JZ4730_LIBRA) + +#define __lcd_set_backlight_level(n) \ +do { \ +} while (0) + +#define __lcd_display_pin_init() \ +do { \ + __lcd_special_pin_init(); \ + __gpio_clear_pin(100); \ + __gpio_as_output(100); \ + __gpio_as_output(94); \ + __gpio_as_output(95); \ + __lcd_set_backlight_level(8); \ +} while (0) + +#define __lcd_display_on() \ +do { \ + __lcd_special_on(); \ + __gpio_set_pin(100); \ + __gpio_set_pin(94); \ + __gpio_set_pin(95); \ +} while (0) + +#define __lcd_display_off() \ +do { \ + __lcd_special_off(); \ + __gpio_clear_pin(100); \ + __gpio_clear_pin(94); \ + __gpio_clear_pin(95); \ +} while (0) + +#endif /* CONFIG_JZ4730_LIBRA */ + +#if defined(CONFIG_JZ4730_PMP) + +#define __lcd_set_backlight_level(n) \ +do { \ + REG_PWM_DUT(0) = n; \ + REG_PWM_PER(0) = 7; \ + REG_PWM_CTR(0) = 0x81; \ +} while (0) + +#define __lcd_display_pin_init() \ +do { \ + __gpio_as_output(GPIO_DISP_OFF_N); \ + __gpio_as_pwm(); \ + __lcd_set_backlight_level(10); \ + __lcd_special_pin_init(); \ +} while (0) + +#define __lcd_display_on() \ +do { \ + __lcd_special_on(); \ + __lcd_set_backlight_level(8); \ + __gpio_set_pin(GPIO_DISP_OFF_N); \ +} while (0) + +#define __lcd_display_off() \ +do { \ + __lcd_special_off(); \ + __lcd_set_backlight_level(0); \ + __gpio_clear_pin(GPIO_DISP_OFF_N); \ +} while (0) + +#endif /* CONFIG_JZ4730_PMP */ + +/*#if defined(CONFIG_JZ4740_LEO) || defined(CONFIG_JZ4740_PAVO)*/ +#if defined(CONFIG_SOC_JZ4740) +#if defined(CONFIG_JZ4740_PAVO) || defined(CONFIG_JZ4740_LYRA) +#define GPIO_PWM 123 /* GP_D27 */ +#define PWM_CHN 4 /* pwm channel */ +#define PWM_FULL 101 +/* 100 level: 0,1,...,100 */ +#define __lcd_set_backlight_level(n)\ +do { \ +__gpio_as_output(32*3+27); \ +__gpio_set_pin(32*3+27); \ +} while (0) + +#define __lcd_close_backlight() \ +do { \ +__gpio_as_output(GPIO_PWM); \ +__gpio_clear_pin(GPIO_PWM); \ +} while (0) + +#elif defined(CONFIG_JZ4720_VIRGO) +#define GPIO_PWM 119 /* GP_D23 */ +#define PWM_CHN 0 /* pwm channel */ +#define PWM_FULL 101 +/* 100 level: 0,1,...,100 */ +/*#define __lcd_set_backlight_level(n) \ +do { \ + __gpio_as_pwm(0); \ + __tcu_disable_pwm_output(PWM_CHN); \ + __tcu_stop_counter(PWM_CHN); \ + __tcu_init_pwm_output_high(PWM_CHN); \ + __tcu_set_pwm_output_shutdown_abrupt(PWM_CHN); \ + __tcu_select_clk_div1(PWM_CHN); \ + __tcu_mask_full_match_irq(PWM_CHN); \ + __tcu_mask_half_match_irq(PWM_CHN); \ + __tcu_set_count(PWM_CHN,0); \ + __tcu_set_full_data(PWM_CHN,__cpm_get_extalclk()/1000); \ + __tcu_set_half_data(PWM_CHN,__cpm_get_extalclk()/1000*n/100); \ + __tcu_enable_pwm_output(PWM_CHN); \ + __tcu_select_extalclk(PWM_CHN); \ + __tcu_start_counter(PWM_CHN); \ +} while (0) +*/ + +#define __lcd_set_backlight_level(n) \ +do { \ + __gpio_as_output(GPIO_PWM); \ + __gpio_set_pin(GPIO_PWM); \ +} while (0) + +#define __lcd_close_backlight() \ +do { \ +__gpio_as_output(GPIO_PWM); \ +__gpio_clear_pin(GPIO_PWM); \ +} while (0) + +#else +#define __lcd_set_backlight_level(n) +#define __lcd_close_backlight() + +#endif /* #if defined(CONFIG_MIPS_JZ4740_PAVO) */ + +#define __lcd_display_pin_init() \ +do { \ + __gpio_as_output(GPIO_DISP_OFF_N); \ + __cpm_start_tcu(); \ + __lcd_special_pin_init(); \ +} while (0) +/* __lcd_set_backlight_level(100); \*/ +#define __lcd_display_on() \ +do { \ + __gpio_set_pin(GPIO_DISP_OFF_N); \ + __lcd_special_on(); \ + __lcd_set_backlight_level(80); \ +} while (0) + +#define __lcd_display_off() \ +do { \ + __lcd_special_off(); \ + __lcd_close_backlight(); \ + __gpio_clear_pin(GPIO_DISP_OFF_N); \ +} while (0) + +#endif /* CONFIG_MIPS_JZ4740_LEO */ + +#if defined(CONFIG_JZLCD_MSTN_240x128) + +#if 0 /* The final version does not use software emulation of VCOM. */ + +#define GPIO_VSYNC 59 +#define GPIO_VCOM 90 + +#define REG_VCOM REG_GPIO_GPDR((GPIO_VCOM>>5)) +#define VCOM_BIT (1 << (GPIO_VCOM & 0x1f)) +static unsigned int vcom_static; +static void vsync_irq(int irq, void *dev_id, struct pt_regs *reg) +{ + vcom_static = REG_VCOM; + vcom_static ^= VCOM_BIT; + REG_VCOM = vcom_static; +} + +#define __lcd_display_pin_init() \ + __gpio_as_irq_rise_edge(GPIO_VSYNC); \ + __gpio_as_output(GPIO_VCOM); \ + { \ + static int inited = 0; \ + if (!inited) { \ + inited = 1; \ + if (request_irq(IRQ_GPIO_0 + GPIO_VSYNC, vsync_irq, SA_INTERRUPT, \ + "vsync", 0)) { \ + err = -EBUSY; \ + goto failed; \ + }}} + +#endif + +/* We uses AC BIAs pin to generate VCOM signal, so above code should be removed. + */ +#endif +/***************************************************************************** + * LCD display pin dummy macros + *****************************************************************************/ +#ifndef __lcd_display_pin_init +#define __lcd_display_pin_init() +#endif +#ifndef __lcd_display_on +#define __lcd_display_on() +#endif +#ifndef __lcd_display_off +#define __lcd_display_off() +#endif +#ifndef __lcd_set_backlight_level +#define __lcd_set_backlight_level(n) +#endif + +#endif /* __JZLCD_H__ */ diff --git a/target/linux/xburst/files-2.6.31/include/linux/mtd/jz4740_nand.h b/target/linux/xburst/files-2.6.31/include/linux/mtd/jz4740_nand.h new file mode 100644 index 000000000..66d60d1a9 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/include/linux/mtd/jz4740_nand.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * JZ4720/JZ4740 SoC NAND controller 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 __JZ_NAND_H__ +#define __JZ_NAND_H__ + +#include +#include + +struct jz_nand_platform_data { + int num_partitions; + struct mtd_partition *partitions; + + struct nand_ecclayout *ecc_layout; + + unsigned int busy_gpio; +}; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.c b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.c new file mode 100755 index 000000000..a8cba3835 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.c @@ -0,0 +1,725 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../jz4740/jz4740-pcm.h" +#include "jzcodec.h" + +#define AUDIO_NAME "jzcodec" +#define JZCODEC_VERSION "1.0" + +/* + * Debug + */ + +#define JZCODEC_DEBUG 0 + +#ifdef JZCODEC_DEBUG +#define dbg(format, arg...) \ + printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif +#define err(format, arg...) \ + printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) +#define info(format, arg...) \ + printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) +#define warn(format, arg...) \ + printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) + +struct snd_soc_codec_device soc_codec_dev_jzcodec; + +/* codec private data */ +struct jzcodec_priv { + unsigned int sysclk; +}; + +/* + * jzcodec register cache + */ +static u32 jzcodec_reg[JZCODEC_CACHEREGNUM / 2]; + +/* + * codec register is 16 bits width in ALSA, so we define array to store 16 bits configure paras + */ +static u16 jzcodec_reg_LH[JZCODEC_CACHEREGNUM]; + +/* + * read jzcodec register cache + */ +static inline unsigned int jzcodec_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + if (reg >= JZCODEC_CACHEREGNUM) + return -1; + return cache[reg]; +} + +/* + * write jzcodec register cache + */ +static inline void jzcodec_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, u16 value) +{ + u16 *cache = codec->reg_cache; + u32 reg_val; + + if (reg >= JZCODEC_CACHEREGNUM) { + return; + } + + cache[reg] = value; + /* update internal codec register value */ + switch (reg) { + case 0: + case 1: + reg_val = cache[0] & 0xffff; + reg_val = reg_val | (cache[1] << 16); + jzcodec_reg[0] = reg_val; + break; + case 2: + case 3: + reg_val = cache[2] & 0xffff; + reg_val = reg_val | (cache[3] << 16); + jzcodec_reg[1] = reg_val; + break; + } +} + +/* + * write to the jzcodec register space + */ +static int jzcodec_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + jzcodec_write_reg_cache(codec, reg, value); + if(codec->hw_write) + codec->hw_write(&value, NULL, reg); + return 0; +} + +static int jzcodec_reset(struct snd_soc_codec *codec) +{ + u16 val; + + val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); + val = val | 0x1; + jzcodec_write(codec, ICODEC_1_LOW, val); + mdelay(1); + + val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); + val = val & ~0x1; + jzcodec_write(codec, ICODEC_1_LOW, val); + mdelay(1); + + return 0; +} + +static const struct snd_kcontrol_new jzcodec_snd_controls[] = { + + //SOC_DOUBLE_R("Master Playback Volume", 1, 1, 0, 3, 0), + SOC_DOUBLE_R("Master Playback Volume", ICODEC_2_LOW, ICODEC_2_LOW, 0, 3, 0), + //SOC_DOUBLE_R("MICBG", ICODEC_2_LOW, ICODEC_2_LOW, 4, 3, 0), + //SOC_DOUBLE_R("Line", 2, 2, 0, 31, 0), + SOC_DOUBLE_R("Line", ICODEC_2_HIGH, ICODEC_2_HIGH, 0, 31, 0), +}; + +/* add non dapm controls */ +static int jzcodec_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(jzcodec_snd_controls); i++) { + if ((err = snd_ctl_add(codec->card, + snd_soc_cnew(&jzcodec_snd_controls[i], codec, NULL))) < 0) + return err; + } + + return 0; +} + +static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("LOUT"), + SND_SOC_DAPM_OUTPUT("LHPOUT"), + SND_SOC_DAPM_OUTPUT("ROUT"), + SND_SOC_DAPM_OUTPUT("RHPOUT"), + SND_SOC_DAPM_INPUT("MICIN"), + SND_SOC_DAPM_INPUT("RLINEIN"), + SND_SOC_DAPM_INPUT("LLINEIN"), +}; + +static const char *intercon[][3] = { + /* output mixer */ + {"Output Mixer", "Line Bypass Switch", "Line Input"}, + {"Output Mixer", "HiFi Playback Switch", "DAC"}, + {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, + + /* outputs */ + {"RHPOUT", NULL, "Output Mixer"}, + {"ROUT", NULL, "Output Mixer"}, + {"LHPOUT", NULL, "Output Mixer"}, + {"LOUT", NULL, "Output Mixer"}, + + /* input mux */ + {"Input Mux", "Line In", "Line Input"}, + {"Input Mux", "Mic", "Mic Bias"}, + {"ADC", NULL, "Input Mux"}, + + /* inputs */ + {"Line Input", NULL, "LLINEIN"}, + {"Line Input", NULL, "RLINEIN"}, + {"Mic Bias", NULL, "MICIN"}, + + /* terminator */ + {NULL, NULL, NULL}, +}; + +static int jzcodec_add_widgets(struct snd_soc_codec *codec) +{ + int i,cnt; + + cnt = ARRAY_SIZE(jzcodec_dapm_widgets); + for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) { + snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]); + } +#if 1 + /* set up audio path interconnects */ + for(i = 0; intercon[i][0] != NULL; i++) { + snd_soc_dapm_connect_input(codec, intercon[i][0], + intercon[i][1], intercon[i][2]); + } +#endif + snd_soc_dapm_new_widgets(codec); + return 0; +} + +static int jzcodec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); + +#if 0 + /* bit size. codec side */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + } +#endif + /* sample rate */ + reg_val = reg_val & ~(0xf << 8); + + switch (params_rate(params)) { + case 8000: + reg_val |= (0x0 << 8); + break; + case 11025: + reg_val |= (0x1 << 8); + break; + case 12000: + reg_val |= (0x2 << 8); + break; + case 16000: + reg_val |= (0x3 << 8); + break; + case 22050: + reg_val |= (0x4 << 8); + break; + case 24000: + reg_val |= (0x5 << 8); + break; + case 32000: + reg_val |= (0x6 << 8); + break; + case 44100: + reg_val |= (0x7 << 8); + break; + case 48000: + reg_val |= (0x8 << 8); + break; + default: + printk(" invalid rate :0x%08x\n",params_rate(params)); + } + + jzcodec_write(codec, ICODEC_2_LOW, reg_val); + return 0; +} + +static int jzcodec_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + u16 val; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + //case SNDRV_PCM_TRIGGER_RESUME: + //case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + val = 0x7302; + jzcodec_write(codec, ICODEC_1_LOW, val); + val = 0x0003; + jzcodec_write(codec, ICODEC_1_HIGH, val); + mdelay(2); + val = 0x6000; + jzcodec_write(codec, ICODEC_1_LOW, val); + val = 0x0300; + jzcodec_write(codec, ICODEC_1_HIGH, val); + mdelay(2); + val = 0x2000; + jzcodec_write(codec, ICODEC_1_LOW, val); + val = 0x0300; + jzcodec_write(codec, ICODEC_1_HIGH, val); + } else { + val = 0x4300; + jzcodec_write(codec, ICODEC_1_LOW, val); + val = 0x1402; + jzcodec_write(codec, ICODEC_1_HIGH, val); + } + break; + + case SNDRV_PCM_TRIGGER_STOP: + //case SNDRV_PCM_TRIGGER_SUSPEND: + //case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + val = 0x3300; + jzcodec_write(codec, ICODEC_1_LOW, val); + val = 0x0003; + jzcodec_write(codec, ICODEC_1_HIGH, val); + } else { + val = 0x3300; + jzcodec_write(codec, ICODEC_1_LOW, val); + val = 0x0003; + jzcodec_write(codec, ICODEC_1_HIGH, val); + } + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static int jzcodec_pcm_prepare(struct snd_pcm_substream *substream) +{ + /*struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; */ + + return 0; +} + +static void jzcodec_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + + /* deactivate */ + if (!codec->active) { + udelay(50); + } +} + +static int jzcodec_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); + + if (mute != 0) + mute = 1; + if (mute) + reg_val = reg_val | (0x1 << 14); + else + reg_val = reg_val & ~(0x1 << 14); + + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + return 0; +} + +static int jzcodec_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct jzcodec_priv *jzcodec = codec->private_data; + + jzcodec->sysclk = freq; + return 0; +} +/* + * Set's ADC and Voice DAC format. called by pavo_hw_params() in pavo.c + */ +static int jzcodec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + + /* set master/slave audio interface. codec side */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + /* set master mode for codec */ + break; + case SND_SOC_DAIFMT_CBS_CFS: + /* set slave mode for codec */ + break; + default: + return -EINVAL; + } + + /* interface format . set some parameter for codec side */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + /* set I2S mode for codec */ + break; + case SND_SOC_DAIFMT_RIGHT_J: + /* set right J mode */ + break; + case SND_SOC_DAIFMT_LEFT_J: + /* set left J mode */ + break; + case SND_SOC_DAIFMT_DSP_A: + /* set dsp A mode */ + break; + case SND_SOC_DAIFMT_DSP_B: + /* set dsp B mode */ + break; + default: + return -EINVAL; + } + + /* clock inversion. codec side */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + break; + case SND_SOC_DAIFMT_IB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + break; + default: + return -EINVAL; + } + + /* jzcodec_write(codec, 0, val); */ + return 0; +} +#if 1 +static int jzcodec_dapm_event(struct snd_soc_codec *codec, int event) +{ +/* u16 reg_val; */ + + switch (event) { + case SNDRV_CTL_POWER_D0: /* full On */ + /* vref/mid, osc on, dac unmute */ + /* u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); */ + /* jzcodec_write(codec, 0, val); */ + break; + case SNDRV_CTL_POWER_D1: /* partial On */ + case SNDRV_CTL_POWER_D2: /* partial On */ + break; + case SNDRV_CTL_POWER_D3hot: /* Off, with power */ + /* everything off except vref/vmid, */ + /*reg_val = 0x0800; + jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x0017; + jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); + REG_ICDC_CDCCR1 = jzcodec_reg[0]; + mdelay(2); + reg_val = 0x2102; + jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x001f; + jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); + REG_ICDC_CDCCR1 = jzcodec_reg[0]; + mdelay(2); + reg_val = 0x3302; + jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x0003; + jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); + REG_ICDC_CDCCR1 = jzcodec_reg[0];*/ + break; + case SNDRV_CTL_POWER_D3cold: /* Off, without power */ + /* everything off, dac mute, inactive */ + /*reg_val = 0x2302; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x001b; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val); + mdelay(1); + reg_val = 0x2102; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x001b; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val);*/ + break; + } + //codec->dapm_state = event; + return 0; +} +#endif + +#define JZCODEC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000) + +#define JZCODEC_FORMATS (SNDRV_PCM_FORMAT_S8 | SNDRV_PCM_FMTBIT_S16_LE) + +struct snd_soc_dai jzcodec_dai = { + .name = "JZCODEC", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = JZCODEC_RATES, + .formats = JZCODEC_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = JZCODEC_RATES, + .formats = JZCODEC_FORMATS,}, + .ops = { + .trigger = jzcodec_pcm_trigger, + .prepare = jzcodec_pcm_prepare, + .hw_params = jzcodec_hw_params, + .shutdown = jzcodec_shutdown, + }, + .dai_ops = { + .digital_mute = jzcodec_mute, + .set_sysclk = jzcodec_set_dai_sysclk, + .set_fmt = jzcodec_set_dai_fmt, + } +}; +EXPORT_SYMBOL_GPL(jzcodec_dai); + +#ifdef CONFIG_PM +static u16 jzcodec_reg_pm[JZCODEC_CACHEREGNUM]; +static int jzcodec_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); + jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH); + jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); + jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); + + jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); + return 0; +} + +static int jzcodec_resume(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + u16 reg_val; + + jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); + reg_val = jzcodec_reg_pm[ICODEC_1_LOW]; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = jzcodec_reg_pm[ICODEC_1_HIGH]; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val); + reg_val = jzcodec_reg_pm[ICODEC_2_LOW]; + jzcodec_write(codec, ICODEC_2_LOW, reg_val); + reg_val = jzcodec_reg_pm[ICODEC_2_HIGH]; + jzcodec_write(codec, ICODEC_2_HIGH, reg_val); + + jzcodec_dapm_event(codec, codec->suspend_dapm_state); + return 0; +} +#else +#define jzcodec_suspend NULL +#define jzcodec_resume NULL +#endif +/* + * initialise the JZCODEC driver + * register the mixer and dsp interfaces with the kernel + */ +static int jzcodec_init(struct snd_soc_device *socdev) +{ + struct snd_soc_codec *codec = socdev->codec; + int reg, ret = 0; + u16 reg_val; + + for (reg = 0; reg < JZCODEC_CACHEREGNUM / 2; reg++) { + switch (reg) { + case 0: + jzcodec_reg[reg] = REG_ICDC_CDCCR1; + jzcodec_reg_LH[ICODEC_1_LOW] = jzcodec_reg[reg] & 0xffff; + jzcodec_reg_LH[ICODEC_1_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; + break; + case 1: + jzcodec_reg[reg] = REG_ICDC_CDCCR2; + jzcodec_reg_LH[ICODEC_2_LOW] = jzcodec_reg[reg] & 0xffff; + jzcodec_reg_LH[ICODEC_2_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; + break; + } + } + + codec->name = "JZCODEC"; + codec->owner = THIS_MODULE; + codec->read = jzcodec_read_reg_cache; + codec->write = jzcodec_write; + //codec->dapm_event = jzcodec_dapm_event; + codec->dai = &jzcodec_dai; + codec->num_dai = 1; + codec->reg_cache_size = sizeof(jzcodec_reg_LH); + codec->reg_cache = kmemdup(jzcodec_reg_LH, sizeof(jzcodec_reg_LH), GFP_KERNEL); + if (codec->reg_cache == NULL) + return -ENOMEM; + + jzcodec_reset(codec); + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "jzcodec: failed to create pcms\n"); + goto pcm_err; + } + + /* power on device */ + jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); + + /* clear suspend bit of jz4740 internal codec */ + reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); + reg_val = reg_val & ~(0x2); + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + /* set vol bits */ + reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); + reg_val = reg_val | 0x3; + jzcodec_write(codec, ICODEC_2_LOW, reg_val); + /* set line in capture gain bits */ + reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); + reg_val = reg_val | 0x1f; + jzcodec_write(codec, ICODEC_2_HIGH, reg_val); + /* set mic boost gain bits */ + reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); + reg_val = reg_val | (0x3 << 4); + jzcodec_write(codec, ICODEC_2_LOW, reg_val); + mdelay(5); + reg_val = 0x3300; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x0003; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val); + jzcodec_add_controls(codec); + jzcodec_add_widgets(codec); + + ret = snd_soc_register_card(socdev); + if (ret < 0) { + printk(KERN_ERR "jzcodec: failed to register card\n"); + goto card_err; + } + return ret; + +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + kfree(codec->reg_cache); + return ret; +} + +static struct snd_soc_device *jzcodec_socdev; + +static int write_codec_reg(u16 * add, char * name, int reg) +{ + switch (reg) { + case 0: + case 1: + REG_ICDC_CDCCR1 = jzcodec_reg[0]; + break; + case 2: + case 3: + REG_ICDC_CDCCR2 = jzcodec_reg[1]; + break; + } + return 0; +} + +static int jzcodec_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + struct jzcodec_priv *jzcodec; + int ret = 0; + + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; + + jzcodec = kzalloc(sizeof(struct jzcodec_priv), GFP_KERNEL); + if (jzcodec == NULL) { + kfree(codec); + return -ENOMEM; + } + + codec->private_data = jzcodec; + socdev->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + jzcodec_socdev = socdev; + + /* Add other interfaces here ,no I2C connection */ + codec->hw_write = (hw_write_t)write_codec_reg; + ret = jzcodec_init(jzcodec_socdev); + + if (ret < 0) { + codec = jzcodec_socdev->codec; + err("failed to initialise jzcodec\n"); + kfree(codec); + } + + return ret; +} + +/* power down chip */ +static int jzcodec_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec->control_data) + jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); + kfree(codec->private_data); + kfree(codec); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_jzcodec = { + .probe = jzcodec_probe, + .remove = jzcodec_remove, + .suspend = jzcodec_suspend, + .resume = jzcodec_resume, +}; + +EXPORT_SYMBOL_GPL(soc_codec_dev_jzcodec); + +MODULE_DESCRIPTION("ASoC JZCODEC driver"); +MODULE_AUTHOR("Richard"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.h b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.h new file mode 100755 index 000000000..785613278 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzcodec.h @@ -0,0 +1,22 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _ICODEC_H +#define _ICODEC_H + +/* jzcodec register space */ +#define ICODEC_1_LOW 0x00 /* bit0 -- bit15 in CDCCR1 */ +#define ICODEC_1_HIGH 0x01 /* bit16 -- bit31 in CDCCR1 */ +#define ICODEC_2_LOW 0x02 /* bit0 -- bit16 in CDCCR2 */ +#define ICODEC_2_HIGH 0x03 /* bit16 -- bit31 in CDCCR2 */ + +#define JZCODEC_CACHEREGNUM 4 +#define JZCODEC_SYSCLK 0 + +extern struct snd_soc_dai jzcodec_dai; +extern struct snd_soc_codec_device soc_codec_dev_jzcodec; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.c b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.c new file mode 100755 index 000000000..d849f148c --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.c @@ -0,0 +1,981 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../jz4750/jz4750-pcm.h" +#include "jzdlv.h" + +#define AUDIO_NAME "jzdlv" +#define JZDLV_VERSION "1.0" + +/* + * Debug + */ + +#define JZDLV_DEBUG 0 + +#ifdef JZDLV_DEBUG +#define dbg(format, arg...) \ + printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif +#define err(format, arg...) \ + printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) +#define info(format, arg...) \ + printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) +#define warn(format, arg...) \ + printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) + +struct snd_soc_codec_device soc_codec_dev_jzdlv; + +/* codec private data */ +struct jzdlv_priv { + unsigned int sysclk; +}; + +/* + * jzdlv register cache + */ +static u16 jzdlv_reg[JZDLV_CACHEREGNUM]; + +int read_codec_file(int addr) +{ + while (__icdc_rgwr_ready()); + __icdc_set_addr(addr); + mdelay(1); + return(__icdc_get_value()); +} + +static void printk_codec_files(void) +{ + int cnt, val; + + //printk("\n"); +#if 0 + printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); + printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); + printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); + printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); + printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); + printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); + printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); + printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); +#endif + for (cnt = 0; cnt < JZDLV_CACHEREGNUM ; cnt++) { + val = read_codec_file(cnt); + jzdlv_reg[cnt] = val; + //printk(" ( %d : 0x%x ) ",cnt ,jzdlv_reg[cnt]); + } + //printk("\n"); +} + +void write_codec_file(int addr, int val) +{ + while (__icdc_rgwr_ready()); + __icdc_set_addr(addr); + __icdc_set_cmd(val); /* write */ + mdelay(1); + __icdc_set_rgwr(); + mdelay(1); + //jzdlv_reg[addr] = val; +} + +int write_codec_file_bit(int addr, int bitval, int mask_bit) +{ + int val; + while (__icdc_rgwr_ready()); + __icdc_set_addr(addr); + mdelay(1); + val = __icdc_get_value(); /* read */ + + val &= ~(1 << mask_bit); + if (bitval == 1) + val |= 1 << mask_bit; +#if 0 + while (__icdc_rgwr_ready()); + __icdc_set_addr(addr); + __icdc_set_cmd(val); /* write */ + mdelay(1); + __icdc_set_rgwr(); + mdelay(1); +#else + write_codec_file(addr, val); +#endif + while (__icdc_rgwr_ready()); + __icdc_set_addr(addr); + val = __icdc_get_value(); /* read */ + + if (((val >> mask_bit) & bitval) == bitval) + return 1; + else + return 0; +} + +/* + * read jzdlv register cache + */ +static inline unsigned int jzdlv_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + if (reg >= JZDLV_CACHEREGNUM) + return -1; + return cache[reg]; +} + +static inline unsigned int jzdlv_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + u8 data; + data = reg; + if (codec->hw_write(codec->control_data, &data, 1) != 1) + return -EIO; + + if (codec->hw_read(codec->control_data, &data, 1) != 1) + return -EIO; + + return data; +} + +/* + * write jzdlv register cache + */ +static inline void jzdlv_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, u16 value) +{ + u16 *cache = codec->reg_cache; + + if (reg >= JZDLV_CACHEREGNUM) { + return; + } + + cache[reg] = value; + +} + +/* + * write to the jzdlv register space + */ +static int jzdlv_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + jzdlv_write_reg_cache(codec, reg, value); + if(codec->hw_write) + codec->hw_write(&value, NULL, reg); + return 0; +} + +static const char *jzdlv_input_select[] = {"Line In", "Mic"}; +static const char *jzdlv_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; + +static const struct soc_enum jzdlv_enum[] = { + SOC_ENUM_SINGLE(0x04, 2, 2, jzdlv_input_select), + SOC_ENUM_SINGLE(0x05, 1, 4, jzdlv_deemph), +}; + +/* set Audio data replay */ +void set_audio_data_replay(void) +{ + write_codec_file(9, 0xff); + write_codec_file(8, 0x20);// only CCMC + mdelay(10); + + /* DAC path */ + write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 + write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 + write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 + + write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 + write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 + + write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 + mdelay(100); + write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 + write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 + write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 + mdelay(100); + write_codec_file_bit(1, 0, 5);//DAC_MUTE->0 +} + +/* unset Audio data replay */ +void unset_audio_data_replay(void) +{ + write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 + mdelay(200); + write_codec_file_bit(5, 1, 6);//SB_OUT->1 + write_codec_file_bit(5, 1, 7);//SB_DAC->1 + write_codec_file_bit(5, 1, 4);//SB_MIX->1 + write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 + write_codec_file_bit(6, 1, 1);//SB->1 + + write_codec_file(9, 0xff); + write_codec_file(8, 0x3f); +} + +/* set Record MIC input audio without playback */ +static void set_record_mic_input_audio_without_playback(void) +{ + /* ADC path for MIC IN */ + write_codec_file_bit(1, 1, 2); + write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 + //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 + + write_codec_file(22, 0x40);//mic 1 + write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 + write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 + write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 + write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 + + write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 + write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 + write_codec_file_bit(6, 1, 3);// gain set + + write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 + mdelay(100); + write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 + write_codec_file(1, 0x4); +} + +/* unset Record MIC input audio without playback */ +static void unset_record_mic_input_audio_without_playback(void) +{ + /* ADC path for MIC IN */ + write_codec_file_bit(5, 1, 4);//SB_ADC->1 + write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 + write_codec_file(22, 0xc0);//CR3.SB_MIC1 +} + +#if 0 +static irqreturn_t aic_codec_irq(int irq, void *dev_id) +{ + u8 file_9 = read_codec_file(9); + u8 file_8 = read_codec_file(8); + + //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); + if ((file_9 & 0x1f) == 0x10) { + // have hp short circuit + write_codec_file(8, 0x3f);//mask all interrupt + write_codec_file_bit(5, 1, 6);//SB_OUT->1 + mdelay(300); + while ((read_codec_file(9) & 0x4) != 0x4); + while ((read_codec_file(9) & 0x10) == 0x10) { + write_codec_file(9, 0x10); + } + write_codec_file_bit(5, 0, 6);//SB_OUT->0 + mdelay(300); + while ((read_codec_file(9) & 0x8) != 0x8); + write_codec_file(9, file_9); + write_codec_file(8, file_8); + + return IRQ_HANDLED; + } + + if (file_9 & 0x8) + ramp_up_end = jiffies; + else if (file_9 & 0x4) + ramp_down_end = jiffies; + else if (file_9 & 0x2) + gain_up_end = jiffies; + else if (file_9 & 0x1) + gain_down_end = jiffies; + + write_codec_file(9, file_9); + if (file_9 & 0xf) + wake_up(&pop_wait_queue); + while (REG_ICDC_RGDATA & 0x100); + + return IRQ_HANDLED; +} +#else +static irqreturn_t aic_codec_irq(int irq, void *dev_id) +{ + u8 file_9 = read_codec_file(9); + u8 file_8 = read_codec_file(8); + + //printk("--- 1 8:0x%x 9:0x%x ---\n",file_8,file_9); + if ((file_9 & 0x1f) == 0x10) { + write_codec_file(8, 0x3f); + write_codec_file_bit(5, 1, 6);//SB_OUT->1 + mdelay(300); + while ((read_codec_file(9) & 0x4) != 0x4); + while ((read_codec_file(9) & 0x10) == 0x10) { + write_codec_file(9, 0x10); + } + write_codec_file_bit(5, 0, 6);//SB_OUT->0 + mdelay(300); + while ((read_codec_file(9) & 0x8) != 0x8); + write_codec_file(9, file_9); + write_codec_file(8, file_8); + + return IRQ_HANDLED; + } + /*if (file_9 & 0x8) + ramp_up_end = jiffies; + else if (file_9 & 0x4) + ramp_down_end = jiffies; + else if (file_9 & 0x2) + gain_up_end = jiffies; + else if (file_9 & 0x1) + gain_down_end = jiffies;*/ + + write_codec_file(9, file_9); + /*if (file_9 & 0xf) + wake_up(&pop_wait_queue);*/ + while (REG_ICDC_RGDATA & 0x100); + + return IRQ_HANDLED; +} +#endif + +static int jzdlv_reset(struct snd_soc_codec *codec) +{ + /* reset DLV codec. from hibernate mode to sleep mode */ + write_codec_file(0, 0xf); + write_codec_file_bit(6, 0, 0); + write_codec_file_bit(6, 0, 1); + mdelay(200); + //write_codec_file(0, 0xf); + write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 + write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 + mdelay(10);//wait for stability + + return 0; +} + + +#if 0 +static int jzdlv_sync(struct snd_soc_codec *codec) +{ + u16 *cache = codec->reg_cache; + int i, r = 0; + + for (i = 0; i < JZDLV_CACHEREGNUM; i++) + r |= jzdlv_write(codec, i, cache[i]); + + return r; +}; +#endif + +static const struct snd_kcontrol_new jzdlv_snd_controls[] = { + + //SOC_DOUBLE_R("Master Playback Volume", 1, 1, 0, 3, 0), + SOC_DOUBLE_R("Master Playback Volume", DLV_CGR8, DLV_CGR9, 0, 31, 0), + //SOC_DOUBLE_R("MICBG", ICODEC_2_LOW, ICODEC_2_LOW, 4, 3, 0), + //SOC_DOUBLE_R("Line", 2, 2, 0, 31, 0), + SOC_DOUBLE_R("Line", DLV_CGR10, DLV_CGR10, 0, 15, 0), +}; + +/* add non dapm controls */ +static int jzdlv_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(jzdlv_snd_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&jzdlv_snd_controls[i], codec, NULL)); + if (err < 0) + return err; + } + + return 0; +} + +/* Output Mixer */ +static const struct snd_kcontrol_new jzdlv_output_mixer_controls[] = { +SOC_DAPM_SINGLE("Line Bypass Switch", 0x04, 3, 1, 0), +SOC_DAPM_SINGLE("Mic Sidetone Switch", 0x04, 5, 1, 0), +SOC_DAPM_SINGLE("HiFi Playback Switch", 0x04, 4, 1, 0), +}; + +/* Input mux */ +static const struct snd_kcontrol_new jzdlv_input_mux_controls = +SOC_DAPM_ENUM("Input Select", jzdlv_enum[0]); + +static const struct snd_soc_dapm_widget jzdlv_dapm_widgets[] = { +SND_SOC_DAPM_MIXER("Output Mixer", 0x06, 4, 1, + &jzdlv_output_mixer_controls[0], + ARRAY_SIZE(jzdlv_output_mixer_controls)), +//SND_SOC_DAPM_DAC("DAC", "HiFi Playback", 0x06, 3, 1), +SND_SOC_DAPM_OUTPUT("LOUT"), +SND_SOC_DAPM_OUTPUT("LHPOUT"), +SND_SOC_DAPM_OUTPUT("ROUT"), +SND_SOC_DAPM_OUTPUT("RHPOUT"), +//SND_SOC_DAPM_ADC("ADC", "HiFi Capture", 0x06, 2, 1), +SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &jzdlv_input_mux_controls), +SND_SOC_DAPM_PGA("Line Input", 0x06, 0, 1, NULL, 0), +SND_SOC_DAPM_MICBIAS("Mic Bias", 0x06, 1, 1), +SND_SOC_DAPM_INPUT("MICIN"), +SND_SOC_DAPM_INPUT("RLINEIN"), +SND_SOC_DAPM_INPUT("LLINEIN"), +}; + + +static const struct snd_soc_dapm_route intercon[] = { + /* output mixer */ + {"Output Mixer", "Line Bypass Switch", "Line Input"}, + {"Output Mixer", "HiFi Playback Switch", "DAC"}, + {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, + + /* outputs */ + {"RHPOUT", NULL, "Output Mixer"}, + {"ROUT", NULL, "Output Mixer"}, + {"LHPOUT", NULL, "Output Mixer"}, + {"LOUT", NULL, "Output Mixer"}, + + /* input mux */ + {"Input Mux", "Line In", "Line Input"}, + {"Input Mux", "Mic", "Mic Bias"}, + {"ADC", NULL, "Input Mux"}, + + /* inputs */ + {"Line Input", NULL, "LLINEIN"}, + {"Line Input", NULL, "RLINEIN"}, + {"Mic Bias", NULL, "MICIN"}, +}; + +static void init_codec(void) +{ + /* reset DLV codec. from hibernate mode to sleep mode */ + write_codec_file(0, 0xf); + write_codec_file_bit(6, 0, 0); + write_codec_file_bit(6, 0, 1); + mdelay(200); + //write_codec_file(0, 0xf); + write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 + write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 + mdelay(10);//wait for stability +} + +static int jzdlv_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, jzdlv_dapm_widgets, + ARRAY_SIZE(jzdlv_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); + + snd_soc_dapm_new_widgets(codec); + return 0; +} + +static int jzdlv_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + int speed = 0; + int val = 0; + + /* sample channel */ + switch (params_channels(params)) { + case 1: + write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono + break; + case 2: + write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo + break; + } + /* sample rate */ + switch (params_rate(params)) { + case 8000: + speed = 10; + break; + case 9600: + speed = 9; + break; + case 11025: + speed = 8; + break; + case 12000: + speed = 7; + break; + case 16000: + speed = 6; + break; + case 22050: + speed = 5; + break; + case 24000: + speed = 4; + break; + case 32000: + speed = 3; + break; + case 44100: + speed = 2; + break; + case 48000: + speed = 1; + break; + case 96000: + speed = 0; + break; + default: + printk(" invalid rate :0x%08x\n",params_rate(params)); + } + + val = (speed << 4) | speed; + jzdlv_write(codec, DLV_CCR2, val); + + return 0; +} + +static int jzdlv_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + //struct snd_soc_pcm_runtime *rtd = substream->private_data; + //struct snd_soc_device *socdev = rtd->socdev; + //struct snd_soc_codec *codec = socdev->codec; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + //case SNDRV_PCM_TRIGGER_RESUME: + //case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + init_codec(); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + REG_AIC_I2SCR = 0x10; + mdelay(1); + set_audio_data_replay(); + mdelay(5); + write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 + __aic_flush_fifo(); + } else { + set_record_mic_input_audio_without_playback(); + mdelay(10); + REG_AIC_I2SCR = 0x10; + mdelay(20); + __aic_flush_fifo(); + write_codec_file_bit(5, 1, 7); + } + + break; + + case SNDRV_PCM_TRIGGER_STOP: + //case SNDRV_PCM_TRIGGER_SUSPEND: + //case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + unset_audio_data_replay(); + } else { + unset_record_mic_input_audio_without_playback(); + } + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static int jzdlv_pcm_prepare(struct snd_pcm_substream *substream) +{ + /*struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; */ + + return 0; +} + +static void jzdlv_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + + /* deactivate */ + if (!codec->active) { + udelay(50); + } +} + +static int jzdlv_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + u16 reg_val = jzdlv_read_reg_cache(codec, 2/*DLV_1_LOW*/); + + if (mute != 0) + mute = 1; + if (mute) + reg_val = reg_val | (0x1 << 14); + else + reg_val = reg_val & ~(0x1 << 14); + + //jzdlv_write(codec, DLV_1_LOW, reg_val); + return 0; +} + +static int jzdlv_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct jzdlv_priv *jzdlv = codec->private_data; + + jzdlv->sysclk = freq; + return 0; +} +/* + * Set's ADC and Voice DAC format. called by apus_hw_params() in apus.c + */ +static int jzdlv_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + /* struct snd_soc_codec *codec = codec_dai->codec; */ + + /* set master/slave audio interface. codec side */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + /* set master mode for codec */ + break; + case SND_SOC_DAIFMT_CBS_CFS: + /* set slave mode for codec */ + break; + default: + return -EINVAL; + } + + /* interface format . set some parameter for codec side */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + /* set I2S mode for codec */ + break; + case SND_SOC_DAIFMT_RIGHT_J: + /* set right J mode */ + break; + case SND_SOC_DAIFMT_LEFT_J: + /* set left J mode */ + break; + case SND_SOC_DAIFMT_DSP_A: + /* set dsp A mode */ + break; + case SND_SOC_DAIFMT_DSP_B: + /* set dsp B mode */ + break; + default: + return -EINVAL; + } + + /* clock inversion. codec side */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + break; + case SND_SOC_DAIFMT_IB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + break; + default: + return -EINVAL; + } + + /* jzcodec_write(codec, 0, val); */ + return 0; +} + +static int jzdlv_dapm_event(struct snd_soc_codec *codec, int event) +{ +/* u16 reg_val; */ + + switch (event) { + case SNDRV_CTL_POWER_D0: /* full On */ + /* vref/mid, osc on, dac unmute */ + /* u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); */ + /* jzcodec_write(codec, 0, val); */ + break; + case SNDRV_CTL_POWER_D1: /* partial On */ + case SNDRV_CTL_POWER_D2: /* partial On */ + break; + case SNDRV_CTL_POWER_D3hot: /* Off, with power */ + /* everything off except vref/vmid, */ + /*reg_val = 0x0800; + jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x0017; + jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); + REG_ICDC_CDCCR1 = jzcodec_reg[0]; + mdelay(2); + reg_val = 0x2102; + jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x001f; + jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); + REG_ICDC_CDCCR1 = jzcodec_reg[0]; + mdelay(2); + reg_val = 0x3302; + jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x0003; + jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); + REG_ICDC_CDCCR1 = jzcodec_reg[0];*/ + break; + case SNDRV_CTL_POWER_D3cold: /* Off, without power */ + /* everything off, dac mute, inactive */ + /*reg_val = 0x2302; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x001b; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val); + mdelay(1); + reg_val = 0x2102; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = 0x001b; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val);*/ + break; + } + //codec->dapm_state = event; + return 0; +} + +#define JZDLV_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_12000 |\ + SNDRV_PCM_RATE_24000) + +#define JZDLV_FORMATS (SNDRV_PCM_FORMAT_S8 | SNDRV_PCM_FMTBIT_S16_LE) + +struct snd_soc_dai jzdlv_dai = { + .name = "JZDLV", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = JZDLV_RATES, + .formats = JZDLV_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = JZDLV_RATES, + .formats = JZDLV_FORMATS,}, + .ops = { + .trigger = jzdlv_pcm_trigger, + .prepare = jzdlv_pcm_prepare, + .hw_params = jzdlv_hw_params, + .shutdown = jzdlv_shutdown, + }, + .dai_ops = { + .digital_mute = jzdlv_mute, + .set_sysclk = jzdlv_set_dai_sysclk, + .set_fmt = jzdlv_set_dai_fmt, + } +}; +EXPORT_SYMBOL_GPL(jzdlv_dai); + +#ifdef CONFIG_PM +static int jzdlv_suspend(struct platform_device *pdev, pm_message_t state) +{ +#if 0 + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); + jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH); + jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); + jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); + + jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); +#endif + return 0; +} + +static int jzdlv_resume(struct platform_device *pdev) +{ +#if 0 + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + u16 reg_val; + + jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); + reg_val = jzcodec_reg_pm[ICODEC_1_LOW]; + jzcodec_write(codec, ICODEC_1_LOW, reg_val); + reg_val = jzcodec_reg_pm[ICODEC_1_HIGH]; + jzcodec_write(codec, ICODEC_1_HIGH, reg_val); + reg_val = jzcodec_reg_pm[ICODEC_2_LOW]; + jzcodec_write(codec, ICODEC_2_LOW, reg_val); + reg_val = jzcodec_reg_pm[ICODEC_2_HIGH]; + jzcodec_write(codec, ICODEC_2_HIGH, reg_val); + + jzcodec_dapm_event(codec, codec->suspend_dapm_state); +#endif + return 0; +} +#else +#define jzdlv_suspend NULL +#define jzdlv_resume NULL +#endif +/* + * initialise the JZDLV driver + * register the mixer and dsp interfaces with the kernel + */ +static int jzdlv_init(struct snd_soc_device *socdev) +{ + struct snd_soc_codec *codec = socdev->codec; + int ret = 0, retval; + + /*REG_CPM_CPCCR &= ~(1 << 31); + REG_CPM_CPCCR &= ~(1 << 30);*/ + write_codec_file(0, 0xf); + + REG_AIC_I2SCR = 0x10; + __i2s_internal_codec(); + __i2s_as_slave(); + __i2s_select_i2s(); + __aic_select_i2s(); + __aic_reset(); + mdelay(10); + REG_AIC_I2SCR = 0x10; + mdelay(20); + + /* power on DLV */ + write_codec_file(8, 0x3f); + write_codec_file(9, 0xff); + mdelay(10); + + __cpm_start_idct(); + __cpm_start_db(); + __cpm_start_me(); + __cpm_start_mc(); + __cpm_start_ipu(); + + codec->name = "JZDLV"; + codec->owner = THIS_MODULE; + codec->read = jzdlv_read_reg_cache; + codec->write = jzdlv_write; + //codec->dapm_event = jzdlv_dapm_event; + codec->dai = &jzdlv_dai; + codec->num_dai = 1; + codec->reg_cache_size = sizeof(jzdlv_reg); + codec->reg_cache = kmemdup(jzdlv_reg, sizeof(jzdlv_reg), GFP_KERNEL); + if (codec->reg_cache == NULL) + return -ENOMEM; + + jzdlv_reset(codec); + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "jzdlv: failed to create pcms\n"); + goto pcm_err; + } + + /* power on device */ + jzdlv_dapm_event(codec, SNDRV_CTL_POWER_D3hot); + jzdlv_add_controls(codec); + jzdlv_add_widgets(codec); + ret = snd_soc_register_card(socdev); + if (ret < 0) { + printk(KERN_ERR "jzcodec: failed to register card\n"); + goto card_err; + } + + mdelay(10); + REG_AIC_I2SCR = 0x10; + mdelay(20); + /* power on DLV */ + write_codec_file(9, 0xff); + write_codec_file(8, 0x3f); + retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); + if (retval) { + printk("Could not get aic codec irq %d\n", IRQ_AIC); + return retval; + } + + printk_codec_files(); + + return ret; + +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + kfree(codec->reg_cache); + return ret; +} + +static struct snd_soc_device *jzdlv_socdev; + +static int write_codec_reg(u16 * add, char * name, int reg) +{ + write_codec_file(reg, *add); + return 0; +} + +static int jzdlv_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + struct jzdlv_priv *jzdlv; + int ret = 0; + + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; + + jzdlv = kzalloc(sizeof(struct jzdlv_priv), GFP_KERNEL); + if (jzdlv == NULL) { + kfree(codec); + return -ENOMEM; + } + + codec->private_data = jzdlv; + socdev->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + jzdlv_socdev = socdev; + + /* Add other interfaces here ,no I2C connection */ + codec->hw_write = (hw_write_t)write_codec_reg; + //codec->hw_read = (hw_read_t)read_codec_reg; + ret = jzdlv_init(jzdlv_socdev); + + if (ret < 0) { + codec = jzdlv_socdev->codec; + err("failed to initialise jzdlv\n"); + kfree(codec); + } + + return ret; +} + +/* power down chip */ +static int jzdlv_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec->control_data) + jzdlv_dapm_event(codec, SNDRV_CTL_POWER_D3cold); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); + kfree(codec->private_data); + kfree(codec); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_jzdlv = { + .probe = jzdlv_probe, + .remove = jzdlv_remove, + .suspend = jzdlv_suspend, + .resume = jzdlv_resume, +}; + +EXPORT_SYMBOL_GPL(soc_codec_dev_jzdlv); + +MODULE_DESCRIPTION("ASoC JZDLV driver"); +MODULE_AUTHOR("Richard"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.h b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.h new file mode 100755 index 000000000..13a294c2e --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/codecs/jzdlv.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _DLV_H +#define _DLV_H + +/* jzdlv register space */ + +#define DLV_AICR 0x00 +#define DLV_CR1 0x01 +#define DLV_CR2 0x02 +#define DLV_CCR1 0x03 +#define DLV_CCR2 0x04 +#define DLV_PMR1 0x05 +#define DLV_PMR2 0x06 +#define DLV_CRR 0x07 +#define DLV_ICR 0x08 +#define DLV_IFR 0x09 +#define DLV_CGR1 0x0a +#define DLV_CGR2 0x0b +#define DLV_CGR3 0x0c +#define DLV_CGR4 0x0d +#define DLV_CGR5 0x0e +#define DLV_CGR6 0x0f +#define DLV_CGR7 0x10 +#define DLV_CGR8 0x11 +#define DLV_CGR9 0x12 +#define DLV_CGR10 0x13 +#define DLV_TR1 0x14 +#define DLV_TR2 0x15 +#define DLV_CR3 0x16 +#define DLV_AGC1 0x17 +#define DLV_AGC2 0x18 +#define DLV_AGC3 0x19 +#define DLV_AGC4 0x1a +#define DLV_AGC5 0x1b + +#define JZDLV_CACHEREGNUM (DLV_AGC5+1) +#define JZDLV_SYSCLK 0 + +int read_codec_file(int addr); +int write_codec_file_bit(int addr, int bitval, int mask_bit); +void write_codec_file(int addr, int val); +extern struct snd_soc_dai jzdlv_dai; +extern struct snd_soc_codec_device soc_codec_dev_jzdlv; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/Kconfig b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/Kconfig new file mode 100755 index 000000000..0bfbffeee --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/Kconfig @@ -0,0 +1,34 @@ +config SND_JZ4740_SOC + tristate "SoC Audio for Ingenic jz4740 chip" + depends on (JZ4740_PAVO || JZ4725_DIPPER || JZ4720_VIRGO) && SND_SOC + help + Say Y or M if you want to add support for codecs attached to + the Jz4740 AC97, I2S or SSP interface. You will also need + to select the audio interfaces to support below. + +config SND_JZ4740_SOC_PAVO + tristate "SoC Audio support for Ingenic Jz4740 PAVO board" + depends on SND_JZ4740_SOC + help + Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 PAVO board. + +config SND_JZ4740_AC97 + tristate "select AC97 protocol and AC97 codec pcm core support" + depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO + select SND_AC97_CODEC + help + Say Y if you want to add AC97 protocol support for pcm core. + +config SND_JZ4740_SOC_AC97 + tristate "SoC Audio (AC97 protocol) for Ingenic jz4740 chip" + depends on SND_JZ4740_SOC && SND_JZ4740_AC97 && SND_JZ4740_SOC_PAVO + select AC97_BUS + select SND_SOC_AC97_BUS + help + Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4740 PAVO board. + +config SND_JZ4740_SOC_I2S + depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO + tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip" + help + Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 PAVO board. diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/Makefile b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/Makefile new file mode 100755 index 000000000..4c79b138b --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/Makefile @@ -0,0 +1,15 @@ +# +# Jz4740 Platform Support +# +snd-soc-jz4740-objs := jz4740-pcm.o +snd-soc-jz4740-ac97-objs := jz4740-ac97.o +snd-soc-jz4740-i2s-objs := jz4740-i2s.o + +obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o +obj-$(CONFIG_SND_JZ4740_SOC_AC97) += snd-soc-jz4740-ac97.o +obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o + +# Jz4740 Machine Support +snd-soc-pavo-objs := pavo.o + +obj-$(CONFIG_SND_JZ4740_SOC_PAVO) += snd-soc-pavo.o diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.c new file mode 100755 index 000000000..84da470e9 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.c @@ -0,0 +1,261 @@ +/* + * linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip. + * + * Author: Richard + * Created: Dec 02, 2007 + * Copyright: Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "jz4740-pcm.h" +#include "jz4740-ac97.h" + +static DEFINE_MUTEX(car_mutex); +static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); +static volatile long gsr_bits; + +static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97, + unsigned short reg) +{ + unsigned short val = -1; + volatile u32 *reg_addr; + + mutex_lock(&car_mutex); + +out: mutex_unlock(&car_mutex); + return val; +} + +static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg, + unsigned short val) +{ + volatile u32 *reg_addr; + + mutex_lock(&car_mutex); + + mutex_unlock(&car_mutex); +} + +static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97) +{ + gsr_bits = 0; +} + +static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97) +{ +} + +static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id) +{ + long status; + return IRQ_NONE; +} + +struct snd_ac97_bus_ops soc_ac97_ops = { + .read = jz4740_ac97_read, + .write = jz4740_ac97_write, + .warm_reset = jz4740_ac97_warm_reset, + .reset = jz4740_ac97_cold_reset, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = { + .name = "AC97 PCM Stereo out", + .dev_addr = __PREG(PCDR), + .drcmr = &DRCMRTXPCDR, + .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | + DCMD_BURST32 | DCMD_WIDTH4, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = { + .name = "AC97 PCM Stereo in", + .dev_addr = __PREG(PCDR), + .drcmr = &DRCMRRXPCDR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST32 | DCMD_WIDTH4, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = { + .name = "AC97 Aux PCM (Slot 5) Mono out", + .dev_addr = __PREG(MODR), + .drcmr = &DRCMRTXMODR, + .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | + DCMD_BURST16 | DCMD_WIDTH2, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = { + .name = "AC97 Aux PCM (Slot 5) Mono in", + .dev_addr = __PREG(MODR), + .drcmr = &DRCMRRXMODR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST16 | DCMD_WIDTH2, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = { + .name = "AC97 Mic PCM (Slot 6) Mono in", + .dev_addr = __PREG(MCDR), + .drcmr = &DRCMRRXMCDR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST16 | DCMD_WIDTH2, +}; + +#ifdef CONFIG_PM +static int jz4740_ac97_suspend(struct platform_device *pdev, + struct snd_soc_cpu_dai *dai) +{ + return 0; +} + +static int jz4740_ac97_resume(struct platform_device *pdev, + struct snd_soc_cpu_dai *dai) +{ + return 0; +} + +#else +#define jz4740_ac97_suspend NULL +#define jz4740_ac97_resume NULL +#endif + +static int jz4740_ac97_probe(struct platform_device *pdev) +{ + int ret; + + return 0; +} + +static void jz4740_ac97_remove(struct platform_device *pdev) +{ +} + +static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out; + else + cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in; + + return 0; +} + +static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out; + else + cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in; + + return 0; +} + +static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return -ENODEV; + else + cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in; + + return 0; +} + +#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +struct snd_soc_cpu_dai jz4740_ac97_dai[] = { +{ + .name = "jz4740-ac97", + .id = 0, + .type = SND_SOC_DAI_AC97, + .probe = jz4740_ac97_probe, + .remove = jz4740_ac97_remove, + .suspend = jz4740_ac97_suspend, + .resume = jz4740_ac97_resume, + .playback = { + .stream_name = "AC97 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .stream_name = "AC97 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = jz4740_ac97_hw_params,}, +}, +{ + .name = "jz4740-ac97-aux", + .id = 1, + .type = SND_SOC_DAI_AC97, + .playback = { + .stream_name = "AC97 Aux Playback", + .channels_min = 1, + .channels_max = 1, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .stream_name = "AC97 Aux Capture", + .channels_min = 1, + .channels_max = 1, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = jz4740_ac97_hw_aux_params,}, +}, +{ + .name = "jz4740-ac97-mic", + .id = 2, + .type = SND_SOC_DAI_AC97, + .capture = { + .stream_name = "AC97 Mic Capture", + .channels_min = 1, + .channels_max = 1, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = jz4740_ac97_hw_mic_params,}, +}, +}; + +EXPORT_SYMBOL_GPL(jz4740_ac97_dai); +EXPORT_SYMBOL_GPL(soc_ac97_ops); + +MODULE_AUTHOR("Richard"); +MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.h b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.h new file mode 100755 index 000000000..e80e2a0ad --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-ac97.h @@ -0,0 +1,21 @@ +/* + * linux/sound/soc/jz4740/jz4740-ac97.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _JZ4740_AC97_H +#define _JZ4740_AC97_H + +#define JZ4740_DAI_AC97_HIFI 0 +#define JZ4740_DAI_AC97_AUX 1 +#define JZ4740_DAI_AC97_MIC 2 + +extern struct snd_soc_cpu_dai jz4740_ac97_dai[3]; + +/* platform data */ +extern struct snd_ac97_bus_ops jz4740_ac97_ops; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.c new file mode 100755 index 000000000..27f6b62ef --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.c @@ -0,0 +1,297 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jz4740-pcm.h" +#include "jz4740-i2s.h" + +static struct jz4740_dma_client jz4740_dma_client_out = { + .name = "I2S PCM Stereo out" +}; + +static struct jz4740_dma_client jz4740_dma_client_in = { + .name = "I2S PCM Stereo in" +}; + +static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_out = { + .client = &jz4740_dma_client_out, + .channel = DMA_ID_AIC_TX, + .dma_addr = AIC_DR, + .dma_size = 2, +}; + +static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_in = { + .client = &jz4740_dma_client_in, + .channel = DMA_ID_AIC_RX, + .dma_addr = AIC_DR, + .dma_size = 2, +}; + +static int jz4740_i2s_startup(struct snd_pcm_substream *substream) +{ + /*struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/ + + return 0; +} + +static int jz4740_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + /* 1 : ac97 , 0 : i2s */ + break; + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* 0 : slave */ + break; + case SND_SOC_DAIFMT_CBM_CFS: + /* 1 : master */ + break; + default: + break; + } + + return 0; +} + +/* +* Set Jz4740 Clock source +*/ +static int jz4740_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + return 0; +} + +static void jz4740_snd_tx_ctrl(int on) +{ + if (on) { + /* enable replay */ + __i2s_enable_transmit_dma(); + __i2s_enable_replay(); + __i2s_enable(); + + } else { + /* disable replay & capture */ + __i2s_disable_replay(); + __i2s_disable_record(); + __i2s_disable_receive_dma(); + __i2s_disable_transmit_dma(); + __i2s_disable(); + } +} + +static void jz4740_snd_rx_ctrl(int on) +{ + if (on) { + /* enable capture */ + __i2s_enable_receive_dma(); + __i2s_enable_record(); + __i2s_enable(); + + } else { + /* disable replay & capture */ + __i2s_disable_replay(); + __i2s_disable_record(); + __i2s_disable_receive_dma(); + __i2s_disable_transmit_dma(); + __i2s_disable(); + } +} + +static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + //struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + int channels = params_channels(params); + + jz4740_snd_rx_ctrl(0); + jz4740_snd_rx_ctrl(0); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + //cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out; + rtd->dai->cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out; + if (channels == 1) + __aic_enable_mono2stereo(); + else + __aic_disable_mono2stereo(); + } else + rtd->dai->cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_in; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + __i2s_set_transmit_trigger(4); + __i2s_set_receive_trigger(3); + __i2s_set_oss_sample_size(8); + __i2s_set_iss_sample_size(8); + break; + case SNDRV_PCM_FORMAT_S16_LE: + /* playback sample:16 bits, burst:16 bytes */ + __i2s_set_transmit_trigger(4); + /* capture sample:16 bits, burst:16 bytes */ + __i2s_set_receive_trigger(3); + __i2s_set_oss_sample_size(16); + __i2s_set_iss_sample_size(16); + break; + } + + return 0; +} + +static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + jz4740_snd_rx_ctrl(1); + else + jz4740_snd_tx_ctrl(1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + jz4740_snd_rx_ctrl(0); + else + jz4740_snd_tx_ctrl(0); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + } else { + } + + return; +} + +static int jz4740_i2s_probe(struct platform_device *pdev) +{ + __i2s_internal_codec(); + __i2s_as_slave(); + __i2s_select_i2s(); + __aic_select_i2s(); + mdelay(2); + + __i2s_disable(); + __i2s_reset(); + mdelay(2); + + __i2s_disable(); + __i2s_internal_codec(); + __i2s_as_slave(); + __i2s_select_i2s(); + __aic_select_i2s(); + __i2s_set_oss_sample_size(16); + __i2s_set_iss_sample_size(16); + __aic_play_lastsample(); + + __i2s_disable_record(); + __i2s_disable_replay(); + __i2s_disable_loopback(); + __i2s_set_transmit_trigger(7); + __i2s_set_receive_trigger(7); + + jz4740_snd_tx_ctrl(0); + jz4740_snd_rx_ctrl(0); + + return 0; +} + +#ifdef CONFIG_PM +static int jz4740_i2s_suspend(struct platform_device *dev, + struct snd_soc_dai *dai) +{ + if (!dai->active) + return 0; + + return 0; +} + +static int jz4740_i2s_resume(struct platform_device *pdev, + struct snd_soc_dai *dai) +{ + if (!dai->active) + return 0; + + return 0; +} + +#else +#define jz4740_i2s_suspend NULL +#define jz4740_i2s_resume NULL +#endif + +#define JZ4740_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000) + +struct snd_soc_dai jz4740_i2s_dai = { + .name = "jz4740-i2s", + .id = 0, + .type = SND_SOC_DAI_I2S, + .probe = jz4740_i2s_probe, + .suspend = jz4740_i2s_suspend, + .resume = jz4740_i2s_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = JZ4740_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = JZ4740_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .startup = jz4740_i2s_startup, + .shutdown = jz4740_i2s_shutdown, + .trigger = jz4740_i2s_trigger, + .hw_params = jz4740_i2s_hw_params,}, + .dai_ops = { + .set_fmt = jz4740_i2s_set_dai_fmt, + .set_sysclk = jz4740_i2s_set_dai_sysclk, + }, +}; + +EXPORT_SYMBOL_GPL(jz4740_i2s_dai); + +/* Module information */ +MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn"); +MODULE_DESCRIPTION("jz4740 I2S SoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.h b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.h new file mode 100755 index 000000000..7c38f8d9f --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-i2s.h @@ -0,0 +1,18 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _JZ4740_I2S_H +#define _JZ4740_I2S_H + +/* jz4740 DAI ID's */ +#define JZ4740_DAI_I2S 0 + +/* I2S clock */ +#define JZ4740_I2S_SYSCLK 0 + +extern struct snd_soc_dai jz4740_i2s_dai; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.c new file mode 100755 index 000000000..6787f6c95 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.c @@ -0,0 +1,689 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "jz4740-pcm.h" + +static long sum_bytes = 0; +static int first_transfer = 0; +static int printk_flag = 0; +static int tran_bit = 0; +#ifdef CONFIG_SND_OSSEMUL +static int hw_params_cnt = 0; +#endif + +struct jz4740_dma_buf_aic { + struct jz4740_dma_buf_aic *next; + int size; /* buffer size in bytes */ + dma_addr_t data; /* start of DMA data */ + dma_addr_t ptr; /* where the DMA got to [1] */ + void *id; /* client's id */ +}; + +struct jz4740_runtime_data { + spinlock_t lock; + int state; + int aic_dma_flag; /* start dma transfer or not */ + unsigned int dma_loaded; + unsigned int dma_limit; + unsigned int dma_period; + dma_addr_t dma_start; + dma_addr_t dma_pos; + dma_addr_t dma_end; + struct jz4740_pcm_dma_params *params; + + dma_addr_t user_cur_addr; /* user current write buffer start address */ + unsigned int user_cur_len; /* user current write buffer length */ + + /* buffer list and information */ + struct jz4740_dma_buf_aic *curr; /* current dma buffer */ + struct jz4740_dma_buf_aic *next; /* next buffer to load */ + struct jz4740_dma_buf_aic *end; /* end of queue */ + +}; + +/* identify hardware playback capabilities */ +static const struct snd_pcm_hardware jz4740_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S8, + .rates = SNDRV_PCM_RATE_8000_48000/*0x3fe*/, + .rate_min = 8000, + .rate_min = 48000, + .channels_min = 1,//2 + .channels_max = 2, + .buffer_bytes_max = 128 * 1024,//16 * 1024 + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = PAGE_SIZE * 2, + .periods_min = 2, + .periods_max = 128,//16, + .fifo_size = 32, +}; + +/* jz4740__dma_buf_enqueue + * + * queue an given buffer for dma transfer. + * + * data the physical address of the buffer data + * size the size of the buffer in bytes + * +*/ +static int jz4740_dma_buf_enqueue(struct jz4740_runtime_data *prtd, dma_addr_t data, int size) +{ + struct jz4740_dma_buf_aic *aic_buf; + + aic_buf = kzalloc(sizeof(struct jz4740_dma_buf_aic), GFP_KERNEL); + if (aic_buf == NULL) { + printk("aic buffer allocate failed,no memory!\n"); + return -ENOMEM; + } + aic_buf->next = NULL; + aic_buf->data = aic_buf->ptr = data; + aic_buf->size = size; + if( prtd->curr == NULL) { + prtd->curr = aic_buf; + prtd->end = aic_buf; + prtd->next = NULL; + } else { + if (prtd->end == NULL) + printk("prtd->end is NULL\n"); + prtd->end->next = aic_buf; + prtd->end = aic_buf; + } + + /* if necessary, update the next buffer field */ + if (prtd->next == NULL) + prtd->next = aic_buf; + + return 0; +} + + +void audio_start_dma(struct jz4740_runtime_data *prtd, int mode) +{ + unsigned long flags; + struct jz4740_dma_buf_aic *aic_buf; + int channel; + printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__); + switch (mode) { + case DMA_MODE_WRITE: + /* free cur aic_buf */ + if (first_transfer == 1) { + first_transfer = 0; + } else { + aic_buf = prtd->curr; + if (aic_buf != NULL) { + prtd->curr = aic_buf->next; + prtd->next = aic_buf->next; + aic_buf->next = NULL; + kfree(aic_buf); + aic_buf = NULL; + } + } + + aic_buf = prtd->next; + channel = prtd->params->channel; + if (aic_buf) { + flags = claim_dma_lock(); + disable_dma(channel); + jz_set_alsa_dma(channel, mode, tran_bit); + set_dma_addr(channel, aic_buf->data); + set_dma_count(channel, aic_buf->size); + enable_dma(channel); + release_dma_lock(flags); + prtd->aic_dma_flag |= AIC_START_DMA; + } else { + printk("next buffer is NULL for playback\n"); + prtd->aic_dma_flag &= ~AIC_START_DMA; + return; + } + break; + case DMA_MODE_READ: + /* free cur aic_buf */ + if (first_transfer == 1) { + first_transfer = 0; + } else { + aic_buf = prtd->curr; + if (aic_buf != NULL) { + prtd->curr = aic_buf->next; + prtd->next = aic_buf->next; + aic_buf->next = NULL; + kfree(aic_buf); + aic_buf = NULL; + } + } + + aic_buf = prtd->next; + channel = prtd->params->channel; + + if (aic_buf) { + flags = claim_dma_lock(); + disable_dma(channel); + jz_set_alsa_dma(channel, mode, tran_bit); + set_dma_addr(channel, aic_buf->data); + set_dma_count(channel, aic_buf->size); + enable_dma(channel); + release_dma_lock(flags); + prtd->aic_dma_flag |= AIC_START_DMA; + } else { + printk("next buffer is NULL for capture\n"); + prtd->aic_dma_flag &= ~AIC_START_DMA; + return; + } + break; + } + /* dump_jz_dma_channel(channel); */ +} + +/* + * place a dma buffer onto the queue for the dma system to handle. +*/ +static void jz4740_pcm_enqueue(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd = runtime->private_data; + /*struct snd_dma_buffer *buf = &substream->dma_buffer;*/ + dma_addr_t pos = prtd->dma_pos; + int ret; + + while (prtd->dma_loaded < prtd->dma_limit) { + unsigned long len = prtd->dma_period; + + if ((pos + len) > prtd->dma_end) { + len = prtd->dma_end - pos; + } + ret = jz4740_dma_buf_enqueue(prtd, pos, len); + if (ret == 0) { + prtd->dma_loaded++; + pos += prtd->dma_period; + if (pos >= prtd->dma_end) + pos = prtd->dma_start; + } else + break; + } + + prtd->dma_pos = pos; +} + +/* + * call the function:jz4740_pcm_dma_irq() after DMA has transfered the current buffer + */ +static irqreturn_t jz4740_pcm_dma_irq(int dma_ch, void *dev_id) +{ + struct snd_pcm_substream *substream = dev_id; + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd = runtime->private_data; + /*struct jz4740_dma_buf_aic *aic_buf = prtd->curr;*/ + int channel = prtd->params->channel; + unsigned long flags; + + disable_dma(channel); + prtd->aic_dma_flag &= ~AIC_START_DMA; + /* must clear TT bit in DCCSR to avoid interrupt again */ + if (__dmac_channel_transmit_end_detected(channel)) { + __dmac_channel_clear_transmit_end(channel); + } + if (__dmac_channel_transmit_halt_detected(channel)) { + __dmac_channel_clear_transmit_halt(channel); + } + + if (__dmac_channel_address_error_detected(channel)) { + __dmac_channel_clear_address_error(channel); + } + + if (substream) + snd_pcm_period_elapsed(substream); + + spin_lock(&prtd->lock); + prtd->dma_loaded--; + if (prtd->state & ST_RUNNING) { + jz4740_pcm_enqueue(substream); + } + spin_unlock(&prtd->lock); + + local_irq_save(flags); + if (prtd->state & ST_RUNNING) { + if (prtd->dma_loaded) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + audio_start_dma(prtd, DMA_MODE_WRITE); + else + audio_start_dma(prtd, DMA_MODE_READ); + } + } + local_irq_restore(flags); + return IRQ_HANDLED; +} + +/* some parameter about DMA operation */ +static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct jz4740_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; + size_t totbytes = params_buffer_bytes(params); + int ret; + +#ifdef CONFIG_SND_OSSEMUL + if (hw_params_cnt) + return 0; + else + hw_params_cnt++ ; +#endif + + if (!dma) + return 0; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + tran_bit = 8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + tran_bit = 16; + break; + } + + /* prepare DMA */ + prtd->params = dma; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = jz_request_dma(DMA_ID_AIC_TX, prtd->params->client->name, + jz4740_pcm_dma_irq, IRQF_DISABLED, substream); + if (ret < 0) + return ret; + prtd->params->channel = ret; + } else { + ret = jz_request_dma(DMA_ID_AIC_RX, prtd->params->client->name, + jz4740_pcm_dma_irq, IRQF_DISABLED, substream); + if (ret < 0) + return ret; + prtd->params->channel = ret; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + runtime->dma_bytes = totbytes; + + spin_lock_irq(&prtd->lock); + prtd->dma_loaded = 0; + prtd->aic_dma_flag = 0; + prtd->dma_limit = runtime->hw.periods_min; + prtd->dma_period = params_period_bytes(params); + prtd->dma_start = runtime->dma_addr; + prtd->dma_pos = prtd->dma_start; + prtd->dma_end = prtd->dma_start + totbytes; + prtd->curr = NULL; + prtd->next = NULL; + prtd->end = NULL; + sum_bytes = 0; + first_transfer = 1; + printk_flag = 0; + + __dmac_disable_descriptor(prtd->params->channel); + __dmac_channel_disable_irq(prtd->params->channel); + spin_unlock_irq(&prtd->lock); + + return ret; +} + +static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct jz4740_runtime_data *prtd = substream->runtime->private_data; + + snd_pcm_set_runtime_buffer(substream, NULL); + if (prtd->params) { + jz_free_dma(prtd->params->channel); + prtd->params = NULL; + } + + return 0; +} + +/* set some dma para for playback/capture */ +static int jz4740_dma_ctrl(int channel) +{ + + disable_dma(channel); + + /* must clear TT bit in DCCSR to avoid interrupt again */ + if (__dmac_channel_transmit_end_detected(channel)) { + __dmac_channel_clear_transmit_end(channel); + } + if (__dmac_channel_transmit_halt_detected(channel)) { + __dmac_channel_clear_transmit_halt(channel); + } + + if (__dmac_channel_address_error_detected(channel)) { + __dmac_channel_clear_address_error(channel); + } + + return 0; + +} + +static int jz4740_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct jz4740_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + + /* return if this is a bufferless transfer e.g */ + if (!prtd->params) + return 0; + + /* flush the DMA channel and DMA channel bit check */ + jz4740_dma_ctrl(prtd->params->channel); + prtd->dma_loaded = 0; + prtd->dma_pos = prtd->dma_start; + + /* enqueue dma buffers */ + jz4740_pcm_enqueue(substream); + + return ret; + +} + +static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd = runtime->private_data; + + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + prtd->state |= ST_RUNNING; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + audio_start_dma(prtd, DMA_MODE_WRITE); + } else { + audio_start_dma(prtd, DMA_MODE_READ); + } + + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + prtd->state &= ~ST_RUNNING; + break; + + case SNDRV_PCM_TRIGGER_RESUME: + printk(" RESUME \n"); + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + printk(" RESTART \n"); + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static snd_pcm_uframes_t +jz4740_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd = runtime->private_data; + struct jz4740_dma_buf_aic *aic_buf = prtd->curr; + long count,res; + + dma_addr_t ptr; + snd_pcm_uframes_t x; + int channel = prtd->params->channel; + + spin_lock(&prtd->lock); +#if 1 + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + res = ptr - prtd->dma_start; + } else { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + res = ptr - prtd->dma_start; + } + +# else + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + REG_DMAC_DSAR(channel) = ptr; + res = ptr - prtd->dma_start; + } else { + ptr = REG_DMAC_DSAR(channel); + if (ptr == 0x0) + printk("\ndma address is 00000000 in running!\n"); + res = ptr - prtd->dma_start; + } + } else { + if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + REG_DMAC_DTAR(channel) = ptr; + res = ptr - prtd->dma_start; + } else { + ptr = REG_DMAC_DTAR(channel); + if (ptr == 0x0) + printk("\ndma address is 00000000 in running!\n"); + res = ptr - prtd->dma_start; + } + } +#endif + spin_unlock(&prtd->lock); + x = bytes_to_frames(runtime, res); + if (x == runtime->buffer_size) + x = 0; + + return x; +} + +static int jz4740_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd; + +#ifdef CONFIG_SND_OSSEMUL + hw_params_cnt = 0; +#endif + snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); + prtd = kzalloc(sizeof(struct jz4740_runtime_data), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + spin_lock_init(&prtd->lock); + + runtime->private_data = prtd; + REG_AIC_I2SCR = 0x10; + return 0; +} + +static int jz4740_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4740_runtime_data *prtd = runtime->private_data; + struct jz4740_dma_buf_aic *aic_buf = NULL; + +#ifdef CONFIG_SND_OSSEMUL + hw_params_cnt = 0; +#endif + + if (prtd) + aic_buf = prtd->curr; + + while (aic_buf != NULL) { + prtd->curr = aic_buf->next; + prtd->next = aic_buf->next; + aic_buf->next = NULL; + kfree(aic_buf); + aic_buf = NULL; + aic_buf = prtd->curr; + } + + if (prtd) { + prtd->curr = NULL; + prtd->next = NULL; + prtd->end = NULL; + kfree(prtd); + } + + return 0; +} + +static int jz4740_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma)//include/linux/mm.h +{ + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long start; + unsigned long off; + u32 len; + int ret = -ENXIO; + + off = vma->vm_pgoff << PAGE_SHIFT; + start = runtime->dma_addr; + + len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes); + start &= PAGE_MASK; + + if ((vma->vm_end - vma->vm_start + off) > len) { + return -EINVAL; + } + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO; + +#if defined(CONFIG_MIPS32) + pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; + pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; + /* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */ +#endif + ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + + return ret; +} + +struct snd_pcm_ops jz4740_pcm_ops = { + .open = jz4740_pcm_open, + .close = jz4740_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = jz4740_pcm_hw_params, + .hw_free = jz4740_pcm_hw_free, + .prepare = jz4740_pcm_prepare, + .trigger = jz4740_pcm_trigger, + .pointer = jz4740_pcm_pointer, + .mmap = jz4740_pcm_mmap, +}; + +static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = jz4740_pcm_hardware.buffer_bytes_max; + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + + /*buf->area = dma_alloc_coherent(pcm->card->dev, size, + &buf->addr, GFP_KERNEL);*/ + buf->area = dma_alloc_noncoherent(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + buf->bytes = size; + return 0; +} + +static void jz4740_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_noncoherent(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} + +static u64 jz4740_pcm_dmamask = DMA_32BIT_MASK; + +int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, + struct snd_pcm *pcm) +{ + int ret = 0; + + if (!card->dev->dma_mask) + card->dev->dma_mask = &jz4740_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = DMA_32BIT_MASK; + + if (dai->playback.channels_min) { + ret = jz4740_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + goto out; + } + + if (dai->capture.channels_min) { + ret = jz4740_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + goto out; + } + out: + + return ret; +} + +struct snd_soc_platform jz4740_soc_platform = { + .name = "jz4740-audio", + .pcm_ops = &jz4740_pcm_ops, + .pcm_new = jz4740_pcm_new, + .pcm_free = jz4740_pcm_free_dma_buffers, +}; + +EXPORT_SYMBOL_GPL(jz4740_soc_platform); + +MODULE_AUTHOR("Richard"); +MODULE_DESCRIPTION("Ingenic Jz4740 PCM DMA module"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.h b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.h new file mode 100755 index 000000000..68ea842d1 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/jz4740-pcm.h @@ -0,0 +1,33 @@ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _JZ4740_PCM_H +#define _JZ4740_PCM_H + +#include + +#define ST_RUNNING (1<<0) +#define ST_OPENED (1<<1) + +#define AIC_START_DMA (1<<0) +#define AIC_END_DMA (1<<1) + +struct jz4740_dma_client { + char *name; +}; + +struct jz4740_pcm_dma_params { + struct jz4740_dma_client *client; /* stream identifier */ + int channel; /* Channel ID */ + dma_addr_t dma_addr; + int dma_size; /* Size of the DMA transfer */ +}; + +/* platform data */ +extern struct snd_soc_platform jz4740_soc_platform; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4740/pavo.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/pavo.c new file mode 100755 index 000000000..a364cfa45 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4740/pavo.c @@ -0,0 +1,364 @@ +/* + * pavo.c -- SoC audio for PAVO + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../codecs/jzcodec.h" +#include "jz4740-pcm.h" +#include "jz4740-i2s.h" + +#define PAVO_HP 0 +#define PAVO_MIC 1 +#define PAVO_LINE 2 +#define PAVO_HEADSET 3 +#define PAVO_HP_OFF 4 +#define PAVO_SPK_ON 0 +#define PAVO_SPK_OFF 1 + + /* audio clock in Hz - rounded from 12.235MHz */ +#define PAVO_AUDIO_CLOCK 12288000 + +static int pavo_jack_func; +static int pavo_spk_func; + +unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) +{ + unsigned short gpio_bit = 0; + + return gpio_bit; +} + +unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) +{ + unsigned short gpio_bit = 0; + + return gpio_bit; +} + +static void pavo_ext_control(struct snd_soc_codec *codec) +{ + int spk = 0, mic = 0, line = 0, hp = 0, hs = 0; + + /* set up jack connection */ + switch (pavo_jack_func) { + case PAVO_HP: + hp = 1; + /* set = unmute headphone */ + //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); + //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + break; + case PAVO_MIC: + mic = 1; + /* reset = mute headphone */ + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + break; + case PAVO_LINE: + line = 1; + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + break; + case PAVO_HEADSET: + hs = 1; + mic = 1; + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); + //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + break; + } + + if (pavo_spk_func == PAVO_SPK_ON) + spk = 1; + +#if 0 + /* set the enpoints to their new connetion states */ + snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk); + snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic); + snd_soc_dapm_set_endpoint(codec, "Line Jack", line); + snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp); + snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs); + + /* signal a DAPM event */ + snd_soc_dapm_sync_endpoints(codec); +#endif +} + +static int pavo_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->socdev->codec; + + /* check the jack status at stream startup */ + pavo_ext_control(codec); + return 0; +} + +/* we need to unmute the HP at shutdown as the mute burns power on pavo */ +static void pavo_shutdown(struct snd_pcm_substream *substream) +{ + /*struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->socdev->codec;*/ + + return; +} + +static int pavo_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret = 0; + + /* set codec DAI configuration */ + ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* set the codec system clock for DAC and ADC */ + ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZCODEC_SYSCLK, 111, + SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* set the I2S system clock as input (unused) */ + ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4740_I2S_SYSCLK, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops pavo_ops = { + .startup = pavo_startup, + .hw_params = pavo_hw_params, + .shutdown = pavo_shutdown, +}; + +static int pavo_get_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = pavo_jack_func; + return 0; +} + +static int pavo_set_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (pavo_jack_func == ucontrol->value.integer.value[0]) + return 0; + + pavo_jack_func = ucontrol->value.integer.value[0]; + pavo_ext_control(codec); + return 1; +} + +static int pavo_get_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = pavo_spk_func; + return 0; +} + +static int pavo_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (pavo_spk_func == ucontrol->value.integer.value[0]) + return 0; + + pavo_spk_func = ucontrol->value.integer.value[0]; + pavo_ext_control(codec); + return 1; +} + +static int pavo_amp_event(struct snd_soc_dapm_widget *w, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + //set_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON); + ; + else + //reset_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON); + ; + + return 0; +} + +static int pavo_mic_event(struct snd_soc_dapm_widget *w, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); + ; + else + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); + ; + + return 0; +} + +/* pavo machine dapm widgets */ +static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = { +SND_SOC_DAPM_HP("Headphone Jack", NULL), +SND_SOC_DAPM_MIC("Mic Jack",pavo_mic_event), +SND_SOC_DAPM_SPK("Ext Spk", pavo_amp_event), +SND_SOC_DAPM_LINE("Line Jack", NULL), +SND_SOC_DAPM_HP("Headset Jack", NULL), +}; + +/* pavo machine audio map (connections to the codec pins) */ +static const char *audio_map[][3] = { + + /* headset Jack - in = micin, out = LHPOUT*/ + {"Headset Jack", NULL, "LHPOUT"}, + + /* headphone connected to LHPOUT1, RHPOUT1 */ + {"Headphone Jack", NULL, "LHPOUT"}, + {"Headphone Jack", NULL, "RHPOUT"}, + + /* speaker connected to LOUT, ROUT */ + {"Ext Spk", NULL, "ROUT"}, + {"Ext Spk", NULL, "LOUT"}, + + /* mic is connected to MICIN (via right channel of headphone jack) */ + {"MICIN", NULL, "Mic Jack"}, + + /* Same as the above but no mic bias for line signals */ + {"MICIN", NULL, "Line Jack"}, + + {NULL, NULL, NULL}, +}; + +static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", + "Off"}; +static const char *spk_function[] = {"On", "Off"}; +static const struct soc_enum pavo_enum[] = { + SOC_ENUM_SINGLE_EXT(5, jack_function), + SOC_ENUM_SINGLE_EXT(2, spk_function), +}; + +static const struct snd_kcontrol_new jzcodec_pavo_controls[] = { + SOC_ENUM_EXT("Jack Function", pavo_enum[0], pavo_get_jack, + pavo_set_jack), + SOC_ENUM_EXT("Speaker Function", pavo_enum[1], pavo_get_spk, + pavo_set_spk), +}; + +/* + * Pavo for a jzcodec as connected on jz4740 Device + */ +static int pavo_jzcodec_init(struct snd_soc_codec *codec) +{ + int i, err; + +#if 0 + snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); + snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); +#endif + /* Add pavo specific controls */ + for (i = 0; i < ARRAY_SIZE(jzcodec_pavo_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&jzcodec_pavo_controls[i],codec, NULL)); + if (err < 0) + return err; + } + + /* Add pavo specific widgets */ + for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) { + snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]); + } +#if 0 + /* Set up pavo specific audio path audio_map */ + for(i = 0; audio_map[i][0] != NULL; i++) { + snd_soc_dapm_connect_input(codec, audio_map[i][0], + audio_map[i][1], audio_map[i][2]); + } + + snd_soc_dapm_sync_endpoints(codec); +#endif + return 0; +} + +/* pavo digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link pavo_dai = { + .name = "JZCODEC", + .stream_name = "JZCODEC", + .cpu_dai = &jz4740_i2s_dai, + .codec_dai = &jzcodec_dai, + .init = pavo_jzcodec_init, + .ops = &pavo_ops, +}; + +/* pavo audio machine driver */ +static struct snd_soc_machine snd_soc_machine_pavo = { + .name = "Pavo", + .dai_link = &pavo_dai, + .num_links = 1, +}; + +/* pavo audio subsystem */ +static struct snd_soc_device pavo_snd_devdata = { + .machine = &snd_soc_machine_pavo, + .platform = &jz4740_soc_platform, + .codec_dev = &soc_codec_dev_jzcodec, + //.codec_data +}; + +static struct platform_device *pavo_snd_device; + +static int __init pavo_init(void) +{ + int ret; + + pavo_snd_device = platform_device_alloc("soc-audio", -1); + + if (!pavo_snd_device) + return -ENOMEM; + + platform_set_drvdata(pavo_snd_device, &pavo_snd_devdata); + pavo_snd_devdata.dev = &pavo_snd_device->dev; + ret = platform_device_add(pavo_snd_device); + + if (ret) + platform_device_put(pavo_snd_device); + + return ret; +} + +static void __exit pavo_exit(void) +{ + platform_device_unregister(pavo_snd_device); +} + +module_init(pavo_init); +module_exit(pavo_exit); + +/* Module information */ +MODULE_AUTHOR("Richard"); +MODULE_DESCRIPTION("ALSA SoC Pavo"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/Kconfig b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/Kconfig new file mode 100755 index 000000000..23e270b94 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/Kconfig @@ -0,0 +1,34 @@ +config SND_JZ4750_SOC + tristate "SoC Audio for Ingenic jz4750 chip" + depends on (JZ4750_APUS || JZ4750_FUWA || JZ4750D_CETUS) && SND_SOC + help + Say Y or M if you want to add support for codecs attached to + the Jz4750 AC97, I2S or SSP interface. You will also need + to select the audio interfaces to support below. + +config SND_JZ4750_SOC_APUS + tristate "SoC Audio support for Ingenic Jz4750 APUS board" + depends on SND_JZ4750_SOC + help + Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4750 APUS board. + +config SND_JZ4750_AC97 + tristate "select AC97 protocol and AC97 codec pcm core support" + depends on SND_JZ4750_SOC && SND_JZ4750_SOC_APUS + select SND_AC97_CODEC + help + Say Y if you want to add AC97 protocol support for pcm core. + +config SND_JZ4750_SOC_AC97 + tristate "SoC Audio (AC97 protocol) for Ingenic jz4750 chip" + depends on SND_JZ4750_SOC && SND_JZ4750_AC97 && SND_JZ4750_SOC_APUS + select AC97_BUS + select SND_SOC_AC97_BUS + help + Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4750 APUS board. + +config SND_JZ4750_SOC_I2S + depends on SND_JZ4750_SOC && SND_JZ4750_SOC_APUS + tristate "SoC Audio (I2S protocol) for Ingenic jz4750 chip" + help + Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4750 APUS board. diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/Makefile b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/Makefile new file mode 100755 index 000000000..ba5cbfaa7 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/Makefile @@ -0,0 +1,15 @@ +# +# Jz4750 Platform Support +# +snd-soc-jz4750-objs := jz4750-pcm.o +snd-soc-jz4750-ac97-objs := jz4750-ac97.o +snd-soc-jz4750-i2s-objs := jz4750-i2s.o + +obj-$(CONFIG_SND_JZ4750_SOC) += snd-soc-jz4750.o +obj-$(CONFIG_SND_JZ4750_SOC_AC97) += snd-soc-jz4750-ac97.o +obj-$(CONFIG_SND_JZ4750_SOC_I2S) += snd-soc-jz4750-i2s.o + +# Jz4750 Machine Support +snd-soc-apus-objs := apus.o + +obj-$(CONFIG_SND_JZ4750_SOC_APUS) += snd-soc-apus.o diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/apus.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/apus.c new file mode 100755 index 000000000..a9862d5bc --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/apus.c @@ -0,0 +1,405 @@ +/* + * apus.c -- SoC audio for APUS + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../codecs/jzdlv.h" +#include "jz4750-pcm.h" +#include "jz4750-i2s.h" + +//static struct snd_soc_machine apus; + +#define APUS_HP 0 +#define APUS_MIC 1 +#define APUS_LINE 2 +#define APUS_HEADSET 3 +#define APUS_HP_OFF 4 +#define APUS_SPK_ON 0 +#define APUS_SPK_OFF 1 + +static int apus_jack_func; +static int apus_spk_func; + +unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) +{ + unsigned short gpio_bit = 0; + + return gpio_bit; +} + +unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) +{ + unsigned short gpio_bit = 0; + + return gpio_bit; +} + +static void apus_ext_control(struct snd_soc_codec *codec) +{ + int spk = 0, mic = 0, line = 0, hp = 0, hs = 0; + + /* set up jack connection */ + switch (apus_jack_func) { + case APUS_HP: + hp = 1; + snd_soc_dapm_disable_pin(codec, "Mic Jack"); + snd_soc_dapm_disable_pin(codec, "Line Jack"); + snd_soc_dapm_enable_pin(codec, "Headphone Jack"); + snd_soc_dapm_disable_pin(codec, "Headset Jack"); + break; + case APUS_MIC: + mic = 1; + snd_soc_dapm_enable_pin(codec, "Mic Jack"); + snd_soc_dapm_disable_pin(codec, "Line Jack"); + snd_soc_dapm_disable_pin(codec, "Headphone Jack"); + snd_soc_dapm_disable_pin(codec, "Headset Jack"); + break; + case APUS_LINE: + line = 1; + snd_soc_dapm_disable_pin(codec, "Mic Jack"); + snd_soc_dapm_enable_pin(codec, "Line Jack"); + snd_soc_dapm_disable_pin(codec, "Headphone Jack"); + snd_soc_dapm_disable_pin(codec, "Headset Jack"); + break; + case APUS_HEADSET: + hs = 1; + mic = 1; + snd_soc_dapm_enable_pin(codec, "Mic Jack"); + snd_soc_dapm_disable_pin(codec, "Line Jack"); + snd_soc_dapm_disable_pin(codec, "Headphone Jack"); + snd_soc_dapm_enable_pin(codec, "Headset Jack"); + break; + } + + if (apus_spk_func == APUS_SPK_ON) + spk = 1; + + if (apus_spk_func == APUS_SPK_ON) + snd_soc_dapm_enable_pin(codec, "Ext Spk"); + else + snd_soc_dapm_disable_pin(codec, "Ext Spk"); + + /* signal a DAPM event */ + snd_soc_dapm_sync(codec); +} + +static int apus_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->socdev->codec; + + /* check the jack status at stream startup */ + apus_ext_control(codec); + return 0; +} + +/* we need to unmute the HP at shutdown as the mute burns power on apus */ +static int apus_shutdown(struct snd_pcm_substream *substream) +{ + /*struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->socdev->codec;*/ + + return 0; +} + +static int apus_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret = 0; + + /* set codec DAI configuration */ + /*ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);*/ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + /*ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);*/ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* set the codec system clock for DAC and ADC */ + /*ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZDLV_SYSCLK, 111, + SND_SOC_CLOCK_IN);*/ + ret = snd_soc_dai_set_sysclk(codec_dai, JZDLV_SYSCLK, 111, + SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* set the I2S system clock as input (unused) */ + /*ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4750_I2S_SYSCLK, 0, + SND_SOC_CLOCK_IN);*/ + ret = snd_soc_dai_set_sysclk(cpu_dai, JZ4750_I2S_SYSCLK, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops apus_ops = { + .startup = apus_startup, + .hw_params = apus_hw_params, + .shutdown = apus_shutdown, +}; + +static int apus_get_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = apus_jack_func; + return 0; +} + +static int apus_set_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (apus_jack_func == ucontrol->value.integer.value[0]) + return 0; + + apus_jack_func = ucontrol->value.integer.value[0]; + apus_ext_control(codec); + return 1; +} + +static int apus_get_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = apus_spk_func; + return 0; +} + +static int apus_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (apus_spk_func == ucontrol->value.integer.value[0]) + return 0; + + apus_spk_func = ucontrol->value.integer.value[0]; + apus_ext_control(codec); + return 1; +} + +static int apus_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + //set_scoop_gpio(&corgiscoop_device.dev, APUS_SCP_APM_ON); + ; + else + //reset_scoop_gpio(&corgiscoop_device.dev, APUS_SCP_APM_ON); + ; + + return 0; +} + +static int apus_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); + ; + else + //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); + ; + + return 0; +} + +static int jzdlv_get_reg(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + //int reg = kcontrol->private_value & 0xFF; + //int shift = (kcontrol->private_value >> 8) & 0x0F; + //int mask = (kcontrol->private_value >> 16) & 0xFF; + + //ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; + return 0; +} + +static int jzdlv_set_reg(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + //int reg = kcontrol->private_value & 0xFF; + //int shift = (kcontrol->private_value >> 8) & 0x0F; + //int mask = (kcontrol->private_value >> 16) & 0xFF; + + /*if (((lm4857_regs[reg] >> shift) & mask) == + ucontrol->value.integer.value[0]) + return 0; + + lm4857_regs[reg] &= ~(mask << shift); + lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift; + lm4857_write_regs();*/ + return 1; +} + +/* apus machine dapm widgets */ +static const struct snd_soc_dapm_widget jzdlv_dapm_widgets[] = { +SND_SOC_DAPM_HP("Headphone Jack", NULL), +SND_SOC_DAPM_MIC("Mic Jack",apus_mic_event), +SND_SOC_DAPM_SPK("Ext Spk", apus_amp_event), +SND_SOC_DAPM_LINE("Line Jack", NULL), +SND_SOC_DAPM_HP("Headset Jack", NULL), +}; + +/* apus machine audio map (connections to the codec pins) */ +static const struct snd_soc_dapm_route audio_map[] = { + + /* headset Jack - in = micin, out = LHPOUT*/ + {"Headset Jack", NULL, "LHPOUT"}, + + /* headphone connected to LHPOUT1, RHPOUT1 */ + {"Headphone Jack", NULL, "LHPOUT"}, + {"Headphone Jack", NULL, "RHPOUT"}, + + /* speaker connected to LOUT, ROUT */ + {"Ext Spk", NULL, "ROUT"}, + {"Ext Spk", NULL, "LOUT"}, + + /* mic is connected to MICIN (via right channel of headphone jack) */ + {"MICIN", NULL, "Mic Jack"}, + + /* Same as the above but no mic bias for line signals */ + {"MICIN", NULL, "Line Jack"}, +}; + +static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", + "Off"}; +static const char *spk_function[] = {"On", "Off"}; +static const struct soc_enum apus_enum[] = { + SOC_ENUM_SINGLE_EXT(5, jack_function), + SOC_ENUM_SINGLE_EXT(2, spk_function), +}; + + +static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0); +//static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0); + +static const struct snd_kcontrol_new jzdlv_apus_controls[] = { +/* SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", 1, 0, 31, 0, + jzdlv_get_reg, jzdlv_set_reg, stereo_tlv),*/ + SOC_SINGLE_EXT_TLV("PCM", 1, 0, 31, 0, + jzdlv_get_reg, jzdlv_set_reg, stereo_tlv), + SOC_SINGLE_EXT_TLV("Capture", 2, 0, 31, 0, + jzdlv_get_reg, jzdlv_set_reg, stereo_tlv), +/* SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0, + lm4857_get_reg, lm4857_set_reg, mono_tlv),*/ + + SOC_ENUM_EXT("Jack Function", apus_enum[0], apus_get_jack,apus_set_jack), + SOC_ENUM_EXT("Speaker Function", apus_enum[1], apus_get_spk,apus_set_spk), +}; + +/* + * Apus for a jzdlv as connected on jz4750 Device + */ +static int apus_jzdlv_init(struct snd_soc_codec *codec) +{ + int i, err; + + snd_soc_dapm_disable_pin(codec, "LLINEIN"); + snd_soc_dapm_disable_pin(codec, "RLINEIN"); + + /* Add apus specific controls */ + for (i = 0; i < ARRAY_SIZE(jzdlv_apus_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&jzdlv_apus_controls[i],codec, NULL)); + if (err < 0) + return err; + } + + /* Add apus specific widgets */ + snd_soc_dapm_new_controls(codec, jzdlv_dapm_widgets, + ARRAY_SIZE(jzdlv_dapm_widgets)); + + /* Set up apus specific audio path audio_map */ + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_sync(codec); + + return 0; +} + +/* apus digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link apus_dai = { + .name = "JZDLV", + .stream_name = "JZDLV", + .cpu_dai = &jz4750_i2s_dai, + .codec_dai = &jzdlv_dai, + .init = apus_jzdlv_init, + .ops = &apus_ops, +}; + +/* apus audio machine driver */ +static struct snd_soc_machine snd_soc_machine_apus = { + .name = "Apus", + .dai_link = &apus_dai, + .num_links = 1, +}; + +/* apus audio subsystem */ +static struct snd_soc_device apus_snd_devdata = { + .machine = &snd_soc_machine_apus, + .platform = &jz4750_soc_platform, + .codec_dev = &soc_codec_dev_jzdlv, + //.codec_data +}; + +static struct platform_device *apus_snd_device; + +static int __init apus_init(void) +{ + int ret; + + apus_snd_device = platform_device_alloc("soc-audio", -1); + + if (!apus_snd_device) + return -ENOMEM; + + platform_set_drvdata(apus_snd_device, &apus_snd_devdata); + apus_snd_devdata.dev = &apus_snd_device->dev; + ret = platform_device_add(apus_snd_device); + + if (ret) + platform_device_put(apus_snd_device); + + return ret; +} + +static void __exit apus_exit(void) +{ + platform_device_unregister(apus_snd_device); +} + +module_init(apus_init); +module_exit(apus_exit); + +/* Module information */ +MODULE_AUTHOR("Richard"); +MODULE_DESCRIPTION("ALSA SoC Apus"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.c new file mode 100755 index 000000000..84da470e9 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.c @@ -0,0 +1,261 @@ +/* + * linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip. + * + * Author: Richard + * Created: Dec 02, 2007 + * Copyright: Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "jz4740-pcm.h" +#include "jz4740-ac97.h" + +static DEFINE_MUTEX(car_mutex); +static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); +static volatile long gsr_bits; + +static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97, + unsigned short reg) +{ + unsigned short val = -1; + volatile u32 *reg_addr; + + mutex_lock(&car_mutex); + +out: mutex_unlock(&car_mutex); + return val; +} + +static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg, + unsigned short val) +{ + volatile u32 *reg_addr; + + mutex_lock(&car_mutex); + + mutex_unlock(&car_mutex); +} + +static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97) +{ + gsr_bits = 0; +} + +static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97) +{ +} + +static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id) +{ + long status; + return IRQ_NONE; +} + +struct snd_ac97_bus_ops soc_ac97_ops = { + .read = jz4740_ac97_read, + .write = jz4740_ac97_write, + .warm_reset = jz4740_ac97_warm_reset, + .reset = jz4740_ac97_cold_reset, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = { + .name = "AC97 PCM Stereo out", + .dev_addr = __PREG(PCDR), + .drcmr = &DRCMRTXPCDR, + .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | + DCMD_BURST32 | DCMD_WIDTH4, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = { + .name = "AC97 PCM Stereo in", + .dev_addr = __PREG(PCDR), + .drcmr = &DRCMRRXPCDR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST32 | DCMD_WIDTH4, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = { + .name = "AC97 Aux PCM (Slot 5) Mono out", + .dev_addr = __PREG(MODR), + .drcmr = &DRCMRTXMODR, + .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | + DCMD_BURST16 | DCMD_WIDTH2, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = { + .name = "AC97 Aux PCM (Slot 5) Mono in", + .dev_addr = __PREG(MODR), + .drcmr = &DRCMRRXMODR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST16 | DCMD_WIDTH2, +}; + +static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = { + .name = "AC97 Mic PCM (Slot 6) Mono in", + .dev_addr = __PREG(MCDR), + .drcmr = &DRCMRRXMCDR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST16 | DCMD_WIDTH2, +}; + +#ifdef CONFIG_PM +static int jz4740_ac97_suspend(struct platform_device *pdev, + struct snd_soc_cpu_dai *dai) +{ + return 0; +} + +static int jz4740_ac97_resume(struct platform_device *pdev, + struct snd_soc_cpu_dai *dai) +{ + return 0; +} + +#else +#define jz4740_ac97_suspend NULL +#define jz4740_ac97_resume NULL +#endif + +static int jz4740_ac97_probe(struct platform_device *pdev) +{ + int ret; + + return 0; +} + +static void jz4740_ac97_remove(struct platform_device *pdev) +{ +} + +static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out; + else + cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in; + + return 0; +} + +static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out; + else + cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in; + + return 0; +} + +static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return -ENODEV; + else + cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in; + + return 0; +} + +#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +struct snd_soc_cpu_dai jz4740_ac97_dai[] = { +{ + .name = "jz4740-ac97", + .id = 0, + .type = SND_SOC_DAI_AC97, + .probe = jz4740_ac97_probe, + .remove = jz4740_ac97_remove, + .suspend = jz4740_ac97_suspend, + .resume = jz4740_ac97_resume, + .playback = { + .stream_name = "AC97 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .stream_name = "AC97 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = jz4740_ac97_hw_params,}, +}, +{ + .name = "jz4740-ac97-aux", + .id = 1, + .type = SND_SOC_DAI_AC97, + .playback = { + .stream_name = "AC97 Aux Playback", + .channels_min = 1, + .channels_max = 1, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .stream_name = "AC97 Aux Capture", + .channels_min = 1, + .channels_max = 1, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = jz4740_ac97_hw_aux_params,}, +}, +{ + .name = "jz4740-ac97-mic", + .id = 2, + .type = SND_SOC_DAI_AC97, + .capture = { + .stream_name = "AC97 Mic Capture", + .channels_min = 1, + .channels_max = 1, + .rates = JZ4740_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = jz4740_ac97_hw_mic_params,}, +}, +}; + +EXPORT_SYMBOL_GPL(jz4740_ac97_dai); +EXPORT_SYMBOL_GPL(soc_ac97_ops); + +MODULE_AUTHOR("Richard"); +MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.h b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.h new file mode 100755 index 000000000..cd116e9f3 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-ac97.h @@ -0,0 +1,21 @@ +/* + * linux/sound/soc/jz4750/jz4750-ac97.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _JZ4750_AC97_H +#define _JZ4750_AC97_H + +#define JZ4750_DAI_AC97_HIFI 0 +#define JZ4750_DAI_AC97_AUX 1 +#define JZ4750_DAI_AC97_MIC 2 + +extern struct snd_soc_cpu_dai jz4750_ac97_dai[3]; + +/* platform data */ +extern struct snd_ac97_bus_ops jz4750_ac97_ops; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.c new file mode 100755 index 000000000..a1a49936a --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.c @@ -0,0 +1,311 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jz4750-pcm.h" +#include "jz4750-i2s.h" +#include "../codecs/jzdlv.h" + +static struct jz4750_dma_client jz4750_dma_client_out = { + .name = "I2S PCM Stereo out" +}; + +static struct jz4750_dma_client jz4750_dma_client_in = { + .name = "I2S PCM Stereo in" +}; + +static struct jz4750_pcm_dma_params jz4750_i2s_pcm_stereo_out = { + .client = &jz4750_dma_client_out, + .channel = DMA_ID_AIC_TX, + .dma_addr = AIC_DR, + .dma_size = 2, +}; + +static struct jz4750_pcm_dma_params jz4750_i2s_pcm_stereo_in = { + .client = &jz4750_dma_client_in, + .channel = DMA_ID_AIC_RX, + .dma_addr = AIC_DR, + .dma_size = 2, +}; + +static int jz4750_i2s_startup(struct snd_pcm_substream *substream) +{ + /*struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/ + + return 0; +} + +static int jz4750_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + /* 1 : ac97 , 0 : i2s */ + break; + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* 0 : slave */ + break; + case SND_SOC_DAIFMT_CBM_CFS: + /* 1 : master */ + break; + default: + break; + } + + return 0; +} + +/* +* Set Jz4750 Clock source +*/ +static int jz4750_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + return 0; +} + +static void jz4750_snd_tx_ctrl(int on) +{ + if (on) { + /* enable replay */ + __i2s_enable_transmit_dma(); + __i2s_enable_replay(); + __i2s_enable(); + + } else { + /* disable replay & capture */ + __i2s_disable_replay(); + __i2s_disable_record(); + __i2s_disable_receive_dma(); + __i2s_disable_transmit_dma(); + __i2s_disable(); + } +} + +static void jz4750_snd_rx_ctrl(int on) +{ + if (on) { + /* enable capture */ + __i2s_enable_receive_dma(); + __i2s_enable_record(); + __i2s_enable(); + + } else { + /* disable replay & capture */ + __i2s_disable_replay(); + __i2s_disable_record(); + __i2s_disable_receive_dma(); + __i2s_disable_transmit_dma(); + __i2s_disable(); + } +} + +static int jz4750_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + //struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + int channels = params_channels(params); + + jz4750_snd_rx_ctrl(0); + jz4750_snd_rx_ctrl(0); + write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + //cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_out; + rtd->dai->cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_out; + if (channels == 1) + __aic_enable_mono2stereo(); + else + __aic_disable_mono2stereo(); + } else + rtd->dai->cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_in; + +#if 1 + switch (channels) { + case 1: + write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono + break; + case 2: + write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo + break; + } +#endif + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + __i2s_set_transmit_trigger(4); + __i2s_set_receive_trigger(3); + __i2s_set_oss_sample_size(8); + __i2s_set_iss_sample_size(8); + break; + case SNDRV_PCM_FORMAT_S16_LE: + /* playback sample:16 bits, burst:16 bytes */ + __i2s_set_transmit_trigger(4); + /* capture sample:16 bits, burst:16 bytes */ + __i2s_set_receive_trigger(3); + __i2s_set_oss_sample_size(16); + __i2s_set_iss_sample_size(16); + /* DAC path and ADC path */ + write_codec_file(2, 0x00); + break; + } + + return 0; +} + +static int jz4750_i2s_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + jz4750_snd_rx_ctrl(1); + else + jz4750_snd_tx_ctrl(1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + jz4750_snd_rx_ctrl(0); + else + jz4750_snd_tx_ctrl(0); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static void jz4750_i2s_shutdown(struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + } else { + } + + return; +} + +static int jz4750_i2s_probe(struct platform_device *pdev) +{ + __i2s_internal_codec(); + __i2s_as_slave(); + __i2s_select_i2s(); + __aic_select_i2s(); + mdelay(2); + + __i2s_disable(); + mdelay(2); + REG_AIC_I2SCR = 0x10; + __i2s_disable(); + __i2s_internal_codec(); + __i2s_as_slave(); + __i2s_select_i2s(); + __aic_select_i2s(); + __i2s_set_oss_sample_size(16); + __i2s_set_iss_sample_size(16); + __aic_play_lastsample(); + + __i2s_disable_record(); + __i2s_disable_replay(); + __i2s_disable_loopback(); + __i2s_set_transmit_trigger(7); + __i2s_set_receive_trigger(7); + + jz4750_snd_tx_ctrl(0); + jz4750_snd_rx_ctrl(0); + + return 0; +} + +#ifdef CONFIG_PM +static int jz4750_i2s_suspend(struct platform_device *dev, + struct snd_soc_dai *dai) +{ + if (!dai->active) + return 0; + + return 0; +} + +static int jz4750_i2s_resume(struct platform_device *pdev, + struct snd_soc_dai *dai) +{ + if (!dai->active) + return 0; + + return 0; +} + +#else +#define jz4750_i2s_suspend NULL +#define jz4750_i2s_resume NULL +#endif + +#define JZ4750_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000) + +struct snd_soc_dai jz4750_i2s_dai = { + .name = "jz4750-i2s", + .id = 0, + .type = SND_SOC_DAI_I2S, + .probe = jz4750_i2s_probe, + .suspend = jz4750_i2s_suspend, + .resume = jz4750_i2s_resume, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = JZ4750_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = JZ4750_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .startup = jz4750_i2s_startup, + .shutdown = jz4750_i2s_shutdown, + .trigger = jz4750_i2s_trigger, + .hw_params = jz4750_i2s_hw_params,}, + .dai_ops = { + .set_fmt = jz4750_i2s_set_dai_fmt, + .set_sysclk = jz4750_i2s_set_dai_sysclk, + }, +}; + +EXPORT_SYMBOL_GPL(jz4750_i2s_dai); + +/* Module information */ +MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn"); +MODULE_DESCRIPTION("jz4750 I2S SoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.h b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.h new file mode 100755 index 000000000..f4f97dc55 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-i2s.h @@ -0,0 +1,18 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _JZ4750_I2S_H +#define _JZ4750_I2S_H + +/* jz4750 DAI ID's */ +#define JZ4750_DAI_I2S 0 + +/* I2S clock */ +#define JZ4750_I2S_SYSCLK 0 + +extern struct snd_soc_dai jz4750_i2s_dai; + +#endif diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.c b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.c new file mode 100755 index 000000000..4f7bad2d8 --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.c @@ -0,0 +1,687 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "jz4750-pcm.h" + +static long sum_bytes = 0; +static int first_transfer = 0; +static int printk_flag = 0; +static int tran_bit = 0; +#ifdef CONFIG_SND_OSSEMUL +static int hw_params_cnt = 0; +#endif + +struct jz4750_dma_buf_aic { + struct jz4750_dma_buf_aic *next; + int size; /* buffer size in bytes */ + dma_addr_t data; /* start of DMA data */ + dma_addr_t ptr; /* where the DMA got to [1] */ + void *id; /* client's id */ +}; + +struct jz4750_runtime_data { + spinlock_t lock; + int state; + int aic_dma_flag; /* start dma transfer or not */ + unsigned int dma_loaded; + unsigned int dma_limit; + unsigned int dma_period; + dma_addr_t dma_start; + dma_addr_t dma_pos; + dma_addr_t dma_end; + struct jz4750_pcm_dma_params *params; + + dma_addr_t user_cur_addr; /* user current write buffer start address */ + unsigned int user_cur_len; /* user current write buffer length */ + + /* buffer list and information */ + struct jz4750_dma_buf_aic *curr; /* current dma buffer */ + struct jz4750_dma_buf_aic *next; /* next buffer to load */ + struct jz4750_dma_buf_aic *end; /* end of queue */ + +}; + +/* identify hardware playback capabilities */ +static const struct snd_pcm_hardware jz4750_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S8, + .rates = SNDRV_PCM_RATE_8000_96000/*0x3fe*/, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1,//2 + .channels_max = 2, + .buffer_bytes_max = 128 * 1024,//16 * 1024 + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = PAGE_SIZE * 2, + .periods_min = 2, + .periods_max = 128,//16, + .fifo_size = 32, +}; + +/* jz4750__dma_buf_enqueue + * + * queue an given buffer for dma transfer. + * + * data the physical address of the buffer data + * size the size of the buffer in bytes + * +*/ +static int jz4750_dma_buf_enqueue(struct jz4750_runtime_data *prtd, dma_addr_t data, int size) +{ + struct jz4750_dma_buf_aic *aic_buf; + + aic_buf = kzalloc(sizeof(struct jz4750_dma_buf_aic), GFP_KERNEL); + if (aic_buf == NULL) { + printk("aic buffer allocate failed,no memory!\n"); + return -ENOMEM; + } + aic_buf->next = NULL; + aic_buf->data = aic_buf->ptr = data; + aic_buf->size = size; + if( prtd->curr == NULL) { + prtd->curr = aic_buf; + prtd->end = aic_buf; + prtd->next = NULL; + } else { + if (prtd->end == NULL) + printk("prtd->end is NULL\n"); + prtd->end->next = aic_buf; + prtd->end = aic_buf; + } + + /* if necessary, update the next buffer field */ + if (prtd->next == NULL) + prtd->next = aic_buf; + + return 0; +} + +void audio_start_dma(struct jz4750_runtime_data *prtd, int mode) +{ + unsigned long flags; + struct jz4750_dma_buf_aic *aic_buf; + int channel; + + switch (mode) { + case DMA_MODE_WRITE: + /* free cur aic_buf */ + if (first_transfer == 1) { + first_transfer = 0; + } else { + aic_buf = prtd->curr; + if (aic_buf != NULL) { + prtd->curr = aic_buf->next; + prtd->next = aic_buf->next; + aic_buf->next = NULL; + kfree(aic_buf); + aic_buf = NULL; + } + } + + aic_buf = prtd->next; + channel = prtd->params->channel; + if (aic_buf) { + flags = claim_dma_lock(); + disable_dma(channel); + jz_set_alsa_dma(channel, mode, tran_bit); + set_dma_addr(channel, aic_buf->data); + set_dma_count(channel, aic_buf->size); + enable_dma(channel); + release_dma_lock(flags); + prtd->aic_dma_flag |= AIC_START_DMA; + } else { + printk("next buffer is NULL for playback\n"); + prtd->aic_dma_flag &= ~AIC_START_DMA; + return; + } + break; + case DMA_MODE_READ: + /* free cur aic_buf */ + if (first_transfer == 1) { + first_transfer = 0; + } else { + aic_buf = prtd->curr; + if (aic_buf != NULL) { + prtd->curr = aic_buf->next; + prtd->next = aic_buf->next; + aic_buf->next = NULL; + kfree(aic_buf); + aic_buf = NULL; + } + } + + aic_buf = prtd->next; + channel = prtd->params->channel; + + if (aic_buf) { + flags = claim_dma_lock(); + disable_dma(channel); + jz_set_alsa_dma(channel, mode, tran_bit); + set_dma_addr(channel, aic_buf->data); + set_dma_count(channel, aic_buf->size); + enable_dma(channel); + release_dma_lock(flags); + prtd->aic_dma_flag |= AIC_START_DMA; + } else { + printk("next buffer is NULL for capture\n"); + prtd->aic_dma_flag &= ~AIC_START_DMA; + return; + } + break; + } +} + +/* + * place a dma buffer onto the queue for the dma system to handle. +*/ +static void jz4750_pcm_enqueue(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd = runtime->private_data; + /*struct snd_dma_buffer *buf = &substream->dma_buffer;*/ + dma_addr_t pos = prtd->dma_pos; + int ret; + + while (prtd->dma_loaded < prtd->dma_limit) { + unsigned long len = prtd->dma_period; + + if ((pos + len) > prtd->dma_end) { + len = prtd->dma_end - pos; + } + ret = jz4750_dma_buf_enqueue(prtd, pos, len); + if (ret == 0) { + prtd->dma_loaded++; + pos += prtd->dma_period; + if (pos >= prtd->dma_end) + pos = prtd->dma_start; + } else + break; + } + + prtd->dma_pos = pos; +} + +/* + * call the function:jz4750_pcm_dma_irq() after DMA has transfered the current buffer + */ +static irqreturn_t jz4750_pcm_dma_irq(int dma_ch, void *dev_id) +{ + struct snd_pcm_substream *substream = dev_id; + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd = runtime->private_data; + /*struct jz4750_dma_buf_aic *aic_buf = prtd->curr;*/ + int channel = prtd->params->channel; + unsigned long flags; + + disable_dma(channel); + prtd->aic_dma_flag &= ~AIC_START_DMA; + /* must clear TT bit in DCCSR to avoid interrupt again */ + if (__dmac_channel_transmit_end_detected(channel)) { + __dmac_channel_clear_transmit_end(channel); + } + if (__dmac_channel_transmit_halt_detected(channel)) { + __dmac_channel_clear_transmit_halt(channel); + } + + if (__dmac_channel_address_error_detected(channel)) { + __dmac_channel_clear_address_error(channel); + } + if (substream) + snd_pcm_period_elapsed(substream); + + spin_lock(&prtd->lock); + prtd->dma_loaded--; + if (prtd->state & ST_RUNNING) { + jz4750_pcm_enqueue(substream); + } + spin_unlock(&prtd->lock); + + local_irq_save(flags); + if (prtd->state & ST_RUNNING) { + if (prtd->dma_loaded) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + audio_start_dma(prtd, DMA_MODE_WRITE); + else + audio_start_dma(prtd, DMA_MODE_READ); + } + } + local_irq_restore(flags); + return IRQ_HANDLED; +} + +/* some parameter about DMA operation */ +static int jz4750_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct jz4750_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; + size_t totbytes = params_buffer_bytes(params); + int ret; + +#ifdef CONFIG_SND_OSSEMUL + if (hw_params_cnt) + return 0; + else + hw_params_cnt++ ; +#endif + + if (!dma) + return 0; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + tran_bit = 8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + tran_bit = 16; + break; + } + + /* prepare DMA */ + prtd->params = dma; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = jz_request_dma(DMA_ID_AIC_TX, prtd->params->client->name, + jz4750_pcm_dma_irq, IRQF_DISABLED, substream); + if (ret < 0) + return ret; + prtd->params->channel = ret; + } else { + ret = jz_request_dma(DMA_ID_AIC_RX, prtd->params->client->name, + jz4750_pcm_dma_irq, IRQF_DISABLED, substream); + if (ret < 0) + return ret; + prtd->params->channel = ret; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + runtime->dma_bytes = totbytes; + + spin_lock_irq(&prtd->lock); + prtd->dma_loaded = 0; + prtd->aic_dma_flag = 0; + prtd->dma_limit = runtime->hw.periods_min; + prtd->dma_period = params_period_bytes(params); + prtd->dma_start = runtime->dma_addr; + prtd->dma_pos = prtd->dma_start; + prtd->dma_end = prtd->dma_start + totbytes; + prtd->curr = NULL; + prtd->next = NULL; + prtd->end = NULL; + sum_bytes = 0; + first_transfer = 1; + printk_flag = 0; + + __dmac_disable_descriptor(prtd->params->channel); + __dmac_channel_disable_irq(prtd->params->channel); + spin_unlock_irq(&prtd->lock); + + return ret; +} + +static int jz4750_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct jz4750_runtime_data *prtd = substream->runtime->private_data; + + snd_pcm_set_runtime_buffer(substream, NULL); + if (prtd->params) { + jz_free_dma(prtd->params->channel); + prtd->params = NULL; + } + + return 0; +} + +/* set some dma para for playback/capture */ +static int jz4750_dma_ctrl(int channel) +{ + disable_dma(channel); + + /* must clear TT bit in DCCSR to avoid interrupt again */ + if (__dmac_channel_transmit_end_detected(channel)) { + __dmac_channel_clear_transmit_end(channel); + } + if (__dmac_channel_transmit_halt_detected(channel)) { + __dmac_channel_clear_transmit_halt(channel); + } + + if (__dmac_channel_address_error_detected(channel)) { + __dmac_channel_clear_address_error(channel); + } + + return 0; + +} + +static int jz4750_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct jz4750_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + + /* return if this is a bufferless transfer e.g */ + if (!prtd->params) + return 0; + + /* flush the DMA channel and DMA channel bit check */ + jz4750_dma_ctrl(prtd->params->channel); + prtd->dma_loaded = 0; + prtd->dma_pos = prtd->dma_start; + + /* enqueue dma buffers */ + jz4750_pcm_enqueue(substream); + + return ret; + +} + +static int jz4750_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd = runtime->private_data; + + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + prtd->state |= ST_RUNNING; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + audio_start_dma(prtd, DMA_MODE_WRITE); + } else { + audio_start_dma(prtd, DMA_MODE_READ); + } + + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + prtd->state &= ~ST_RUNNING; + break; + + case SNDRV_PCM_TRIGGER_RESUME: + printk(" RESUME \n"); + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + printk(" RESTART \n"); + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static snd_pcm_uframes_t +jz4750_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd = runtime->private_data; + struct jz4750_dma_buf_aic *aic_buf = prtd->curr; + long count,res; + + dma_addr_t ptr; + snd_pcm_uframes_t x; + int channel = prtd->params->channel; + + spin_lock(&prtd->lock); +#if 1 + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + res = ptr - prtd->dma_start; + } else { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + res = ptr - prtd->dma_start; + } + +# else + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + REG_DMAC_DSAR(channel) = ptr; + res = ptr - prtd->dma_start; + } else { + ptr = REG_DMAC_DSAR(channel); + if (ptr == 0x0) + printk("\ndma address is 00000000 in running!\n"); + res = ptr - prtd->dma_start; + } + } else { + if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { + count = get_dma_residue(channel); + count = aic_buf->size - count; + ptr = aic_buf->data + count; + REG_DMAC_DTAR(channel) = ptr; + res = ptr - prtd->dma_start; + } else { + ptr = REG_DMAC_DTAR(channel); + if (ptr == 0x0) + printk("\ndma address is 00000000 in running!\n"); + res = ptr - prtd->dma_start; + } + } +#endif + spin_unlock(&prtd->lock); + x = bytes_to_frames(runtime, res); + if (x == runtime->buffer_size) + x = 0; + + return x; +} + +static int jz4750_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd; + +#ifdef CONFIG_SND_OSSEMUL + hw_params_cnt = 0; +#endif + REG_DMAC_DMACKE(0) = 0x3f; + REG_DMAC_DMACKE(1) = 0x3f; + snd_soc_set_runtime_hwparams(substream, &jz4750_pcm_hardware); + prtd = kzalloc(sizeof(struct jz4750_runtime_data), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + spin_lock_init(&prtd->lock); + + runtime->private_data = prtd; + + return 0; +} + +static int jz4750_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct jz4750_runtime_data *prtd = runtime->private_data; + struct jz4750_dma_buf_aic *aic_buf = NULL; + +#ifdef CONFIG_SND_OSSEMUL + hw_params_cnt = 0; +#endif + + if (prtd) + aic_buf = prtd->curr; + + while (aic_buf != NULL) { + prtd->curr = aic_buf->next; + prtd->next = aic_buf->next; + aic_buf->next = NULL; + kfree(aic_buf); + aic_buf = NULL; + aic_buf = prtd->curr; + } + + if (prtd) { + prtd->curr = NULL; + prtd->next = NULL; + prtd->end = NULL; + kfree(prtd); + } + + return 0; +} + +static int jz4750_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma)//include/linux/mm.h +{ + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long start; + unsigned long off; + u32 len; + int ret = -ENXIO; + + off = vma->vm_pgoff << PAGE_SHIFT; + start = runtime->dma_addr; + + len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes); + start &= PAGE_MASK; + + if ((vma->vm_end - vma->vm_start + off) > len) { + return -EINVAL; + } + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO; + +#if defined(CONFIG_MIPS32) + pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; + pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; + /* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */ +#endif + ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + + return ret; +} + +struct snd_pcm_ops jz4750_pcm_ops = { + .open = jz4750_pcm_open, + .close = jz4750_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = jz4750_pcm_hw_params, + .hw_free = jz4750_pcm_hw_free, + .prepare = jz4750_pcm_prepare, + .trigger = jz4750_pcm_trigger, + .pointer = jz4750_pcm_pointer, + .mmap = jz4750_pcm_mmap, +}; + +static int jz4750_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = jz4750_pcm_hardware.buffer_bytes_max; + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + + /*buf->area = dma_alloc_coherent(pcm->card->dev, size, + &buf->addr, GFP_KERNEL);*/ + buf->area = dma_alloc_noncoherent(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + buf->bytes = size; + return 0; +} + +static void jz4750_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_noncoherent(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} + +static u64 jz4750_pcm_dmamask = DMA_32BIT_MASK; + +int jz4750_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, + struct snd_pcm *pcm) +{ + int ret = 0; + + if (!card->dev->dma_mask) + card->dev->dma_mask = &jz4750_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = DMA_32BIT_MASK; + + if (dai->playback.channels_min) { + ret = jz4750_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + goto out; + } + + if (dai->capture.channels_min) { + ret = jz4750_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + goto out; + } + out: + + return ret; +} + +struct snd_soc_platform jz4750_soc_platform = { + .name = "jz4750-audio", + .pcm_ops = &jz4750_pcm_ops, + .pcm_new = jz4750_pcm_new, + .pcm_free = jz4750_pcm_free_dma_buffers, +}; + +EXPORT_SYMBOL_GPL(jz4750_soc_platform); + +MODULE_AUTHOR("Richard"); +MODULE_DESCRIPTION("Ingenic Jz4750 PCM DMA module"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.h b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.h new file mode 100755 index 000000000..d7d4f722b --- /dev/null +++ b/target/linux/xburst/files-2.6.31/sound/soc/jz4750/jz4750-pcm.h @@ -0,0 +1,33 @@ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _JZ4750_PCM_H +#define _JZ4750_PCM_H + +#include + +#define ST_RUNNING (1<<0) +#define ST_OPENED (1<<1) + +#define AIC_START_DMA (1<<0) +#define AIC_END_DMA (1<<1) + +struct jz4750_dma_client { + char *name; +}; + +struct jz4750_pcm_dma_params { + struct jz4750_dma_client *client; /* stream identifier */ + int channel; /* Channel ID */ + dma_addr_t dma_addr; + int dma_size; /* Size of the DMA transfer */ +}; + +/* platform data */ +extern struct snd_soc_platform jz4750_soc_platform; + +#endif diff --git a/target/linux/xburst/patches-2.6.31/0002-qi_lb60_support_patch b/target/linux/xburst/patches-2.6.31/0002-qi_lb60_support_patch deleted file mode 100644 index 1eaa44267..000000000 --- a/target/linux/xburst/patches-2.6.31/0002-qi_lb60_support_patch +++ /dev/null @@ -1,103429 +0,0 @@ -diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig -index 3ca0fe1..a86cdd5 100644 ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -19,6 +19,98 @@ choice - prompt "System type" - default SGI_IP22 - -+config JZ4740_QI_LB60 -+ bool "Ingenic JZ4740 QI_LB60 board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4740 -+ -+config JZ4730_PMP -+ bool "Ingenic JZ4730 PMP board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4730 -+ -+config JZ4740_PAVO -+ bool "Ingenic JZ4740 PAVO board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4740 -+ -+config JZ4740_LEO -+ bool "Ingenic JZ4740 LEO board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4740 -+ -+config JZ4740_LYRA -+ bool "Ingenic JZ4740 LYRA board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4740 -+ -+config JZ4725_DIPPER -+ bool "Ingenic JZ4725 DIPPER board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4740 -+ select SOC_JZ4725 -+ -+config JZ4720_VIRGO -+ bool "Ingenic JZ4720 VIRGO board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4740 -+ select SOC_JZ4720 -+ -+config JZ4750_FUWA -+ bool "Ingenic JZ4750 FUWA board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4750 -+ select JZ_FPGA -+ -+config JZ4750D_FUWA1 -+ bool "Ingenic JZ4750d FUWA1 board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4750D -+ select JZ_FPGA -+ -+config JZ4750_APUS -+ bool "Ingenic JZ4750 APUS board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4750 -+ -+config JZ4750D_CETUS -+ bool "Ingenic JZ4750d CETUS board" -+ select DMA_NONCOHERENT -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SOC_JZ4750D -+ - config MACH_ALCHEMY - bool "Alchemy processor based machines" - -@@ -671,6 +763,48 @@ source "arch/mips/cavium-octeon/Kconfig" - - endmenu - -+##################################################### -+# Ingenic SOC series -+##################################################### -+ -+config SOC_JZ4730 -+ bool -+ select JZSOC -+ -+config SOC_JZ4740 -+ bool -+ select JZSOC -+ -+config SOC_JZ4725 -+ bool -+ select JZSOC -+ -+config SOC_JZ4720 -+ bool -+ select JZSOC -+ -+config SOC_JZ4750 -+ bool -+ select JZSOC -+ -+config SOC_JZ4750D -+ bool -+ select JZSOC -+ -+config JZ_FPGA -+ bool -+ -+config JZSOC -+ bool -+ select JZRISC -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_SUPPORTS_32BIT_KERNEL -+ -+config JZRISC -+ bool -+ -+#################################################### -+ - config RWSEM_GENERIC_SPINLOCK - bool - default y -@@ -2055,6 +2189,14 @@ config PCI_DOMAINS - - source "drivers/pci/Kconfig" - -+# the value of (max order + 1) -+config FORCE_MAX_ZONEORDER -+ prompt "MAX_ZONEORDER" -+ int -+ default "12" -+ help -+ The max memory that can be allocated = 4KB * 2^(CONFIG_FORCE_MAX_ZONEORDER - 1) -+ - # - # ISA support is now enabled via select. Too many systems still have the one - # or other ISA chip on the board that users don't know about so don't expect -@@ -2164,6 +2306,23 @@ config BINFMT_ELF32 - - endmenu - -+menu "CPU Frequency scaling" -+ -+config CPU_FREQ_JZ -+ tristate "CPUfreq driver for JZ CPUs" -+ depends on JZSOC -+ default n -+ help -+ This enables the CPUfreq driver for JZ CPUs. -+ -+ If in doubt, say N. -+ -+if (CPU_FREQ_JZ) -+source "drivers/cpufreq/Kconfig" -+endif -+ -+endmenu -+ - menu "Power management options" - - config ARCH_HIBERNATION_POSSIBLE -diff --git a/arch/mips/Makefile b/arch/mips/Makefile -index 861da51..91f73c0 100644 ---- a/arch/mips/Makefile -+++ b/arch/mips/Makefile -@@ -180,6 +180,37 @@ cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 - load-$(CONFIG_AR7) += 0xffffffff94100000 - - # -+# Commond Ingenic JZ4730 series -+# -+core-$(CONFIG_SOC_JZ4730) += arch/mips/jz4730/ -+cflags-$(CONFIG_SOC_JZ4730) += -Iinclude/asm-mips/mach-jz4730 -+load-$(CONFIG_SOC_JZ4730) += 0xffffffff80010000 -+ -+# -+# Commond Ingenic JZ4740 series -+# -+ -+core-$(CONFIG_SOC_JZ4740) += arch/mips/jz4740/ -+cflags-$(CONFIG_SOC_JZ4740) += -Iinclude/asm-mips/mach-jz4740 -+load-$(CONFIG_SOC_JZ4740) += 0xffffffff80010000 -+ -+# -+# Commond Ingenic JZ4750 series -+# -+ -+core-$(CONFIG_SOC_JZ4750) += arch/mips/jz4750/ -+cflags-$(CONFIG_SOC_JZ4750) += -Iinclude/asm-mips/mach-jz4750 -+load-$(CONFIG_SOC_JZ4750) += 0xffffffff80010000 -+ -+# -+# Commond Ingenic JZ4750d series -+# -+ -+core-$(CONFIG_SOC_JZ4750D) += arch/mips/jz4750d/ -+cflags-$(CONFIG_SOC_JZ4750D) += -Iinclude/asm-mips/mach-jz4750d -+load-$(CONFIG_SOC_JZ4750D) += 0xffffffff80010000 -+ -+# - # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. - # - core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -@@ -711,6 +742,12 @@ makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1) - - all: $(all-y) - -+uImage: $(vmlinux-32) -+ +@$(call makeboot,$@) -+ -+zImage: $(vmlinux-32) -+ +@$(call makeboot,$@) -+ - vmlinux.bin: $(vmlinux-32) - +@$(call makeboot,$@) - -@@ -740,6 +777,7 @@ install: - - archclean: - @$(MAKE) $(clean)=arch/mips/boot -+ @$(MAKE) $(clean)=arch/mips/boot/compressed - @$(MAKE) $(clean)=arch/mips/lasat - - define archhelp -diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile -index 2a209d7..1cfce3e 100644 ---- a/arch/mips/boot/Makefile -+++ b/arch/mips/boot/Makefile -@@ -7,6 +7,9 @@ - # Copyright (C) 2004 Maciej W. Rozycki - # - -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80010000 -+ - # - # Some DECstations need all possible sections of an ECOFF executable - # -@@ -25,7 +28,7 @@ strip-flags = $(addprefix --remove-section=,$(drop-sections)) - - VMLINUX = vmlinux - --all: vmlinux.ecoff vmlinux.srec addinitrd -+all: vmlinux.ecoff vmlinux.srec addinitrd uImage zImage - - vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) - $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS) -@@ -42,8 +45,24 @@ vmlinux.srec: $(VMLINUX) - $(obj)/addinitrd: $(obj)/addinitrd.c - $(HOSTCC) -o $@ $^ - -+uImage: $(VMLINUX) vmlinux.bin -+ rm -f $(obj)/vmlinux.bin.gz -+ gzip -9 $(obj)/vmlinux.bin -+ mkimage -A mips -O linux -T kernel -C gzip \ -+ -a $(LOADADDR) -e $(shell sh ./$(obj)/tools/entry $(NM) $(VMLINUX) ) \ -+ -n 'Linux-$(KERNELRELEASE)' \ -+ -d $(obj)/vmlinux.bin.gz $(obj)/uImage -+ @echo ' Kernel: arch/mips/boot/$@ is ready' -+ -+zImage: -+ $(Q)$(MAKE) $(build)=$(obj)/compressed loadaddr=$(LOADADDR) $@ -+ @echo ' Kernel: arch/mips/boot/compressed/$@ is ready' -+ - clean-files += addinitrd \ - elf2ecoff \ - vmlinux.bin \ - vmlinux.ecoff \ -- vmlinux.srec -+ vmlinux.srec \ -+ vmlinux.bin.gz \ -+ uImage \ -+ zImage -diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile -new file mode 100644 -index 0000000..8c3ede2 ---- /dev/null -+++ b/arch/mips/boot/compressed/Makefile -@@ -0,0 +1,42 @@ -+# -+# linux/arch/mips/boot/compressed/Makefile -+# -+# create a compressed zImage from the original vmlinux -+# -+ -+targets := zImage vmlinuz vmlinux.bin.gz head.o misc.o piggy.o dummy.o -+ -+OBJS := $(obj)/head.o $(obj)/misc.o -+ -+LD_ARGS := -T $(obj)/ld.script -Ttext 0x80600000 -Bstatic -+OBJCOPY_ARGS := -O elf32-tradlittlemips -+ -+ENTRY := $(obj)/../tools/entry -+FILESIZE := $(obj)/../tools/filesize -+ -+drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options -+strip-flags = $(addprefix --remove-section=,$(drop-sections)) -+ -+ -+$(obj)/vmlinux.bin.gz: vmlinux -+ rm -f $(obj)/vmlinux.bin.gz -+ $(OBJCOPY) -O binary $(strip-flags) vmlinux $(obj)/vmlinux.bin -+ gzip -v9f $(obj)/vmlinux.bin -+ -+$(obj)/head.o: $(obj)/head.S $(obj)/vmlinux.bin.gz vmlinux -+ $(CC) $(KBUILD_AFLAGS) -Iinclude \ -+ -DIMAGESIZE=$(shell sh $(FILESIZE) $(obj)/vmlinux.bin.gz) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) vmlinux ) \ -+ -DLOADADDR=$(loadaddr) \ -+ -c -o $(obj)/head.o $< -+ -+$(obj)/vmlinuz: $(OBJS) $(obj)/ld.script $(obj)/vmlinux.bin.gz $(obj)/dummy.o -+ $(OBJCOPY) \ -+ --add-section=.image=$(obj)/vmlinux.bin.gz \ -+ --set-section-flags=.image=contents,alloc,load,readonly,data \ -+ $(obj)/dummy.o $(obj)/piggy.o -+ $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/piggy.o -+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap -+ -+zImage: $(obj)/vmlinuz -+ $(OBJCOPY) -O binary $(obj)/vmlinuz $(obj)/zImage -diff --git a/arch/mips/boot/compressed/dummy.c b/arch/mips/boot/compressed/dummy.c -new file mode 100644 -index 0000000..31dbf45 ---- /dev/null -+++ b/arch/mips/boot/compressed/dummy.c -@@ -0,0 +1,4 @@ -+int main(void) -+{ -+ return 0; -+} -diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S -new file mode 100644 -index 0000000..d9700eb ---- /dev/null -+++ b/arch/mips/boot/compressed/head.S -@@ -0,0 +1,85 @@ -+/* -+ * linux/arch/mips/boot/compressed/head.S -+ * -+ * Copyright (C) 2005-2008 Ingenic Semiconductor Inc. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+#define IndexWriteBack_D 0x01 -+ -+ .set noreorder -+ LEAF(startup) -+startup: -+ move s0, a0 /* Save the boot loader transfered args */ -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, _edata -+ la a1, _end -+1: sw zero, 0(a0) /* Clear BSS section */ -+ bne a1, a0, 1b -+ addu a0, 4 -+ -+ la sp, (.stack + 8192) -+ -+ la a0, __image_begin -+ la a1, IMAGESIZE -+ la a2, LOADADDR -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ move a0, s0 -+ move a1, s1 -+ move a2, s2 -+ move a3, s3 -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+2: -+ b 32 -+ END(startup) -+ -+ -+ LEAF(flushcaches) -+ la t0, 1f -+ la t1, 0xa0000000 -+ or t0, t0, t1 -+ jr t0 -+ nop -+1: -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+2: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 2b -+ addu k0, k0, 128 -+ la t0, 3f -+ jr t0 -+ nop -+3: -+ jr ra -+ nop -+ END(flushcaches) -+ -+ .comm .stack,4096*2,4 -diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script -new file mode 100644 -index 0000000..fcf8ba0 ---- /dev/null -+++ b/arch/mips/boot/compressed/ld.script -@@ -0,0 +1,151 @@ -+OUTPUT_ARCH(mips) -+ENTRY(startup) -+SECTIONS -+{ -+ /* Read-only sections, merged into text segment: */ -+ -+ .init : { *(.init) } =0 -+ .text : -+ { -+ _ftext = . ; -+ *(.text) -+ *(.rodata) -+ *(.rodata1) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ } =0 -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___dbe_table = .; /* Exception table for data bus errors */ -+ __dbe_table : { *(__dbe_table) } -+ __stop___dbe_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ _etext = .; -+ -+ . = ALIGN(8192); -+ .data.init_task : { *(.data.init_task) } -+ -+ /* Startup code */ -+ . = ALIGN(4096); -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ .data.init : { *(.data.init) } -+ . = ALIGN(16); -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ . = ALIGN(4096); /* Align double page for init_task_union */ -+ __init_end = .; -+ -+ . = ALIGN(4096); -+ .data.page_aligned : { *(.data.idt) } -+ -+ . = ALIGN(32); -+ .data.cacheline_aligned : { *(.data.cacheline_aligned) } -+ -+ .fini : { *(.fini) } =0 -+ .reginfo : { *(.reginfo) } -+ /* Adjust the address for the data segment. We want to adjust up to -+ the same address within the page on the next page up. It would -+ be more correct to do this: -+ . = .; -+ The current expression does not correctly handle the case of a -+ text segment ending precisely at the end of a page; it causes the -+ data segment to skip a page. The above expression does not have -+ this problem, but it will currently (2/95) cause BFD to allocate -+ a single segment, combining both text and data, for this case. -+ This will prevent the text segment from being shared among -+ multiple executions of the program; I think that is more -+ important than losing a page of the virtual address space (note -+ that no actual memory is lost; the page which is skipped can not -+ be referenced). */ -+ . = .; -+ .data : -+ { -+ _fdata = . ; -+ *(.data) -+ -+ /* Put the compressed image here, so bss is on the end. */ -+ __image_begin = .; -+ *(.image) -+ __image_end = .; -+ /* Align the initial ramdisk image (INITRD) on page boundaries. */ -+ . = ALIGN(4096); -+ __ramdisk_begin = .; -+ *(.initrd) -+ __ramdisk_end = .; -+ . = ALIGN(4096); -+ -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ _gp = . + 0x8000; -+ .lit8 : { *(.lit8) } -+ .lit4 : { *(.lit4) } -+ .ctors : { *(.ctors) } -+ .dtors : { *(.dtors) } -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ . = ALIGN(4); -+ _edata = .; -+ PROVIDE (edata = .); -+ -+ __bss_start = .; -+ _fbss = .; -+ .sbss : { *(.sbss) *(.scommon) } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ . = ALIGN(4); -+ _end = . ; -+ PROVIDE (end = .); -+ } -+ -+ /* Sections to be discarded */ -+ /DISCARD/ : -+ { -+ *(.text.exit) -+ *(.data.exit) -+ *(.exitcall.exit) -+ } -+ -+ /* This is the MIPS specific mdebug section. */ -+ .mdebug : { *(.mdebug) } -+ /* These are needed for ELF backends which have not yet been -+ converted to the new style linker. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ /* DWARF debug sections. -+ Symbols in the .debug DWARF section are relative to the beginning of the -+ section so we begin .debug at 0. It's not clear yet what needs to happen -+ for the others. */ -+ .debug 0 : { *(.debug) } -+ .debug_srcinfo 0 : { *(.debug_srcinfo) } -+ .debug_aranges 0 : { *(.debug_aranges) } -+ .debug_pubnames 0 : { *(.debug_pubnames) } -+ .debug_sfnames 0 : { *(.debug_sfnames) } -+ .line 0 : { *(.line) } -+ /* These must appear regardless of . */ -+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } -+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -+ .comment : { *(.comment) } -+ .note : { *(.note) } -+} -diff --git a/arch/mips/boot/compressed/misc.c b/arch/mips/boot/compressed/misc.c -new file mode 100644 -index 0000000..2309fee ---- /dev/null -+++ b/arch/mips/boot/compressed/misc.c -@@ -0,0 +1,242 @@ -+/* -+ * linux/arch/mips/boot/compressed/misc.c -+ * -+ * This is a collection of several routines from gzip-1.0.3 -+ * adapted for Linux. -+ * -+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 -+ * -+ * Adapted for JZSOC by Peter Wei, 2008 -+ * -+ */ -+ -+#define size_t int -+#define NULL 0 -+ -+/* -+ * gzip declarations -+ */ -+ -+#define OF(args) args -+#define STATIC static -+ -+#undef memset -+#undef memcpy -+#define memzero(s, n) memset ((s), 0, (n)) -+ -+typedef unsigned char uch; -+typedef unsigned short ush; -+typedef unsigned long ulg; -+ -+#define WSIZE 0x8000 /* Window size must be at least 32k, */ -+ /* and a power of two */ -+ -+static uch *inbuf; /* input buffer */ -+static uch window[WSIZE]; /* Sliding window buffer */ -+ -+static unsigned insize = 0; /* valid bytes in inbuf */ -+static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -+static unsigned outcnt = 0; /* bytes in output buffer */ -+ -+/* gzip flag byte */ -+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -+#define COMMENT 0x10 /* bit 4 set: file comment present */ -+#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -+#define RESERVED 0xC0 /* bit 6,7: reserved */ -+ -+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -+ -+/* Diagnostic functions */ -+#ifdef DEBUG -+# define Assert(cond,msg) {if(!(cond)) error(msg);} -+# define Trace(x) fprintf x -+# define Tracev(x) {if (verbose) fprintf x ;} -+# define Tracevv(x) {if (verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+static int fill_inbuf(void); -+static void flush_window(void); -+static void error(char *m); -+static void gzip_mark(void **); -+static void gzip_release(void **); -+ -+void* memset(void* s, int c, size_t n); -+void* memcpy(void* __dest, __const void* __src, size_t __n); -+ -+extern void flushcaches(void); /* defined in head.S */ -+ -+char *input_data; -+int input_len; -+ -+static long bytes_out = 0; -+static uch *output_data; -+static unsigned long output_ptr = 0; -+ -+ -+static void *malloc(int size); -+static void free(void *where); -+static void error(char *m); -+static void gzip_mark(void **); -+static void gzip_release(void **); -+ -+static void puts(const char *str) -+{ -+} -+ -+extern unsigned char _end[]; -+static unsigned long free_mem_ptr; -+static unsigned long free_mem_end_ptr; -+ -+#define HEAP_SIZE 0x10000 -+ -+#include "../../../../lib/inflate.c" -+ -+static void *malloc(int size) -+{ -+ void *p; -+ -+ if (size <0) error("Malloc error\n"); -+ if (free_mem_ptr == 0) error("Memory error\n"); -+ -+ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ -+ -+ p = (void *)free_mem_ptr; -+ free_mem_ptr += size; -+ -+ if (free_mem_ptr >= free_mem_end_ptr) -+ error("\nOut of memory\n"); -+ -+ return p; -+} -+ -+static void free(void *where) -+{ /* Don't care */ -+} -+ -+static void gzip_mark(void **ptr) -+{ -+ *ptr = (void *) free_mem_ptr; -+} -+ -+static void gzip_release(void **ptr) -+{ -+ free_mem_ptr = (long) *ptr; -+} -+ -+void* memset(void* s, int c, size_t n) -+{ -+ int i; -+ char *ss = (char*)s; -+ -+ for (i=0;i> 3; i > 0; i--) { -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ } -+ -+ if (__n & 1 << 2) { -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ *d++ = *s++; -+ } -+ -+ if (__n & 1 << 1) { -+ *d++ = *s++; -+ *d++ = *s++; -+ } -+ -+ if (__n & 1) -+ *d++ = *s++; -+ -+ return __dest; -+} -+ -+/* =========================================================================== -+ * Fill the input buffer. This is called only when the buffer is empty -+ * and at least one byte is really needed. -+ */ -+static int fill_inbuf(void) -+{ -+ if (insize != 0) { -+ error("ran out of input data\n"); -+ } -+ -+ inbuf = input_data; -+ insize = input_len; -+ inptr = 1; -+ return inbuf[0]; -+} -+ -+/* =========================================================================== -+ * Write the output window window[0..outcnt-1] and update crc and bytes_out. -+ * (Used for the decompressed data only.) -+ */ -+static void flush_window(void) -+{ -+ ulg c = crc; /* temporary variable */ -+ unsigned n; -+ uch *in, *out, ch; -+ -+ in = window; -+ out = &output_data[output_ptr]; -+ for (n = 0; n < outcnt; n++) { -+ ch = *out++ = *in++; -+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -+ } -+ crc = c; -+ bytes_out += (ulg)outcnt; -+ output_ptr += (ulg)outcnt; -+ outcnt = 0; -+} -+ -+static void error(char *x) -+{ -+ puts("\n\n"); -+ puts(x); -+ puts("\n\n -- System halted"); -+ -+ while(1); /* Halt */ -+} -+ -+void decompress_kernel(unsigned int imageaddr, unsigned int imagesize, unsigned int loadaddr) -+{ -+ input_data = (char *)imageaddr; -+ input_len = imagesize; -+ output_ptr = 0; -+ output_data = (uch *)loadaddr; -+ free_mem_ptr = (unsigned long)_end; -+ free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; -+ -+ makecrc(); -+ puts("Uncompressing Linux..."); -+ gunzip(); -+ flushcaches(); -+ puts("Ok, booting the kernel."); -+} -diff --git a/arch/mips/boot/tools/entry b/arch/mips/boot/tools/entry -new file mode 100644 -index 0000000..376e822 ---- /dev/null -+++ b/arch/mips/boot/tools/entry -@@ -0,0 +1,12 @@ -+#!/bin/sh -+ -+# grab the kernel_entry address from the vmlinux elf image -+entry=`$1 $2 | grep kernel_entry` -+ -+fs=`echo $entry | grep ffffffff` # check toolchain output -+ -+if [ -n "$fs" ]; then -+ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'` -+else -+ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'` -+fi -diff --git a/arch/mips/boot/tools/filesize b/arch/mips/boot/tools/filesize -new file mode 100644 -index 0000000..2142ad5 ---- /dev/null -+++ b/arch/mips/boot/tools/filesize -@@ -0,0 +1,7 @@ -+#!/bin/sh -+HOSTNAME=`uname` -+if [ "$HOSTNAME" = "Linux" ]; then -+echo `ls -l $1 | awk '{print $5}'` -+else -+echo `ls -l $1 | awk '{print $6}'` -+fi -diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h -index 610fe3a..8bcf713 100644 ---- a/arch/mips/include/asm/bootinfo.h -+++ b/arch/mips/include/asm/bootinfo.h -@@ -57,6 +57,14 @@ - #define MACH_MIKROTIK_RB532 0 /* Mikrotik RouterBoard 532 */ - #define MACH_MIKROTIK_RB532A 1 /* Mikrotik RouterBoard 532A */ - -+/* -+ * Valid machtype for group INGENIC -+ */ -+#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */ -+#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */ -+#define MACH_INGENIC_JZ4750 2 /* JZ4750 SOC */ -+#define MACH_INGENIC_JZ4750D 3 /* JZ4750D SOC */ -+ - #define CL_SIZE COMMAND_LINE_SIZE - - extern char *system_type; -diff --git a/arch/mips/jz4730/Makefile b/arch/mips/jz4730/Makefile -new file mode 100644 -index 0000000..d84b6b6 ---- /dev/null -+++ b/arch/mips/jz4730/Makefile -@@ -0,0 +1,22 @@ -+# -+# Makefile for the Ingenic JZ4730. -+# -+ -+# Object file lists. -+ -+obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -+ platform.o i2c.o -+ -+obj-$(CONFIG_PROC_FS) += proc.o -+ -+# board specific support -+ -+obj-$(CONFIG_JZ4730_PMP) += board-pmp.o -+ -+# CPU Frequency scaling support -+ -+obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -+ -+# PM support -+ -+obj-$(CONFIG_PM_LEGACY) +=pm.o sleep.o -diff --git a/arch/mips/jz4730/board-pmp.c b/arch/mips/jz4730/board-pmp.c -new file mode 100644 -index 0000000..00860c1 ---- /dev/null -+++ b/arch/mips/jz4730/board-pmp.c -@@ -0,0 +1,109 @@ -+/* -+ * linux/arch/mips/jz4730/board-pmp.c -+ * -+ * JZ4730 PMP board setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned int count = 0; -+ -+ count ++; -+ count &= 1; -+ if (count) -+ __gpio_set_pin(GPIO_LED_EN); -+ else -+ __gpio_clear_pin(GPIO_LED_EN); -+} -+ -+static void pmp_timer_ack(void) -+{ -+ static unsigned int count = 0; -+ count ++; -+ if (count % 100 == 0) { -+ count = 0; -+ dancing(); -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ __cpm_start_all(); -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Most of the gpios have been setup in the bootloader. -+ */ -+ -+ __harb_usb0_uhc(); -+ __gpio_as_dma(); -+ __gpio_as_eth(); -+ __gpio_as_usb(); -+ __gpio_as_lcd_master(); -+#if defined(CONFIG_I2S_AK4642EN) -+ __gpio_as_scc1(); -+#endif -+#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) -+ __gpio_as_ssi(); -+#endif -+ //__gpio_as_ac97(); -+#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) || defined(CONFIG_I2S_CS42L51) -+ __gpio_as_i2s_slave(); -+#endif -+ __gpio_as_cim(); -+ __gpio_as_msc(); -+ -+ __gpio_as_output(GPIO_LED_EN); -+ __gpio_set_pin(GPIO_LED_EN); -+ -+ __gpio_as_output(GPIO_DISP_OFF_N); -+ __gpio_set_pin(GPIO_DISP_OFF_N); -+ __gpio_as_output(GPIO_PWM0); -+ __gpio_set_pin(GPIO_PWM0); -+ -+ __gpio_as_input(GPIO_RTC_IRQ); -+ __gpio_as_output(GPIO_USB_CLK_EN); -+ __gpio_set_pin(GPIO_USB_CLK_EN); -+ -+ __gpio_as_input(GPIO_CHARG_STAT); -+ __gpio_disable_pull(GPIO_CHARG_STAT); -+ -+ __gpio_as_input(GPIO_UDC_HOTPLUG); -+ __gpio_disable_pull(GPIO_UDC_HOTPLUG); -+ __gpio_disable_pull(54); /* fixed ic bug, the pull of gpio pin 86 is as pin 54 */ -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4730 PMP board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = pmp_timer_ack; -+} -diff --git a/arch/mips/jz4730/cpufreq.c b/arch/mips/jz4730/cpufreq.c -new file mode 100644 -index 0000000..1bf4713 ---- /dev/null -+++ b/arch/mips/jz4730/cpufreq.c -@@ -0,0 +1,596 @@ -+ -+/* -+ * linux/arch/mips/jz4730/cpufreq.c -+ * -+ * cpufreq driver for JZ4730 -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -+ "cpufreq-jz4730", msg) -+ -+#undef CHANGE_PLL -+ -+#define PLL_UNCHANGED 0 -+#define PLL_GOES_UP 1 -+#define PLL_GOES_DOWN 2 -+ -+#define PLL_WAIT_500NS (500*(__cpm_get_iclk()/1000000000)) -+ -+/* Saved the boot-time parameters */ -+static struct { -+ /* SDRAM parameters */ -+ unsigned int mclk; /* memory clock, KHz */ -+ unsigned int tras; /* RAS pulse width, cycles of mclk */ -+ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -+ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -+ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -+ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -+ unsigned int rtcor; /* Refresh Time Constant */ -+ unsigned int sdram_initialized; -+ -+ /* LCD parameters */ -+ unsigned int lcd_clk; /* LCD clock, Hz */ -+ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -+ unsigned int lcd_clks_initialized; -+} boot_config; -+ -+struct jz4730_freq_percpu_info { -+ struct cpufreq_frequency_table table[7]; -+}; -+ -+static struct jz4730_freq_percpu_info jz4730_freq_table; -+ -+/* -+ * This contains the registers value for an operating point. -+ * If only part of a register needs to change then there is -+ * a mask value for that register. -+ * When going to a new operating point the current register -+ * value is ANDed with the ~mask and ORed with the new value. -+ */ -+struct dpm_regs { -+ u32 cfcr; /* Clock Freq Control Register */ -+ u32 cfcr_mask; /* Clock Freq Control Register mask */ -+ u32 cfcr2; /* Clock Freq Control Register 2 */ -+ u32 cfcr2_mask; /* Clock Freq Control Register 2 mask */ -+ u32 plcr1; /* PLL1 Control Register */ -+ u32 plcr1_mask; /* PLL1 Control Register mask */ -+ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -+}; -+ -+extern jz_clocks_t jz_clocks; -+ -+static void jz_update_clocks(void) -+{ -+ /* Next clocks must be updated if we have changed -+ * the PLL or divisors. -+ */ -+ jz_clocks.iclk = __cpm_get_iclk(); -+ jz_clocks.sclk = __cpm_get_sclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+} -+ -+static void -+jz_init_boot_config(void) -+{ -+ if (!boot_config.lcd_clks_initialized) { -+ /* the first time to scale pll */ -+ boot_config.lcd_clk = __cpm_get_lcdclk(); -+ boot_config.lcdpix_clk = __cpm_get_pixclk(); -+ boot_config.lcd_clks_initialized = 1; -+ } -+ -+ if (!boot_config.sdram_initialized) { -+ /* the first time to scale frequencies */ -+ unsigned int dmcr, rtcor; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ -+ dmcr = REG_EMC_DMCR; -+ rtcor = REG_EMC_RTCOR; -+ -+ tras = (dmcr >> 13) & 0x7; -+ rcd = (dmcr >> 11) & 0x3; -+ tpc = (dmcr >> 8) & 0x7; -+ trwl = (dmcr >> 5) & 0x3; -+ trc = (dmcr >> 2) & 0x7; -+ -+ boot_config.mclk = __cpm_get_mclk() / 1000; -+ boot_config.tras = tras + 4; -+ boot_config.rcd = rcd + 1; -+ boot_config.tpc = tpc + 1; -+ boot_config.trwl = trwl + 1; -+ boot_config.trc = trc * 2 + 1; -+ boot_config.rtcor = rtcor; -+ -+ boot_config.sdram_initialized = 1; -+ } -+} -+ -+static void jz_update_dram_rtcor(unsigned int new_mclk) -+{ -+ unsigned int rtcor; -+ -+ new_mclk /= 1000; -+ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -+ rtcor--; -+ -+ if (rtcor < 1) rtcor = 1; -+ if (rtcor > 255) rtcor = 255; -+ -+ REG_EMC_RTCOR = rtcor; -+ REG_EMC_RTCNT = rtcor; -+} -+ -+static void jz_update_dram_dmcr(unsigned int new_mclk) -+{ -+ unsigned int dmcr; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ unsigned int valid_time, new_time; /* ns */ -+ -+ new_mclk /= 1000; -+ tras = boot_config.tras * new_mclk / boot_config.mclk; -+ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -+ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -+ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -+ trc = boot_config.trc * new_mclk / boot_config.mclk; -+ -+ /* Validation checking */ -+ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -+ new_time = (tras * 1000000) / new_mclk; -+ if (new_time < valid_time) tras += 1; -+ -+ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -+ new_time = (rcd * 1000000) / new_mclk; -+ if (new_time < valid_time) rcd += 1; -+ -+ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -+ new_time = (tpc * 1000000) / new_mclk; -+ if (new_time < valid_time) tpc += 1; -+ -+ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -+ new_time = (trwl * 1000000) / new_mclk; -+ if (new_time < valid_time) trwl += 1; -+ -+ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -+ new_time = (trc * 1000000) / new_mclk; -+ if (new_time < valid_time) trc += 2; -+ -+ tras = (tras < 4) ? 4: tras; -+ tras = (tras > 11) ? 11: tras; -+ tras -= 4; -+ -+ rcd = (rcd < 1) ? 1: rcd; -+ rcd = (rcd > 4) ? 4: rcd; -+ rcd -= 1; -+ -+ tpc = (tpc < 1) ? 1: tpc; -+ tpc = (tpc > 8) ? 8: tpc; -+ tpc -= 1; -+ -+ trwl = (trwl < 1) ? 1: trwl; -+ trwl = (trwl > 4) ? 4: trwl; -+ trwl -= 1; -+ -+ trc = (trc < 1) ? 1: trc; -+ trc = (trc > 15) ? 15: trc; -+ trc /= 2; -+ -+ dmcr = REG_EMC_DMCR; -+ -+ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -+ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -+ -+ REG_EMC_DMCR = dmcr; -+} -+ -+static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR before changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } else { -+ /* We're going SLOWER: first update RTCOR value -+ * before changing the frequency. -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } -+} -+ -+static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so update RTCOR -+ * after changing the frequency -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } else { -+ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR after changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } -+} -+ -+static void jz_scale_divisors(struct dpm_regs *regs) -+{ -+ unsigned int cfcr; -+ unsigned int cur_mclk, new_mclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ cfcr = REG_CPM_CFCR; -+ cfcr &= ~((unsigned long)regs->cfcr_mask); -+ cfcr |= regs->cfcr; -+ cfcr |= CPM_CFCR_UPE; /* update immediately */ -+ -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = __cpm_get_pllout() / div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT]; -+ -+ /* Update some DRAM parameters before changing frequency */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+ -+#ifdef CHANGE_PLL -+/* Maintain the LCD clock and pixel clock */ -+static void jz_scale_lcd_divisors(struct dpm_regs *regs) -+{ -+ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -+ unsigned int cfcr; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ if (!boot_config.lcd_clks_initialized) return; -+ -+ new_pll = __cpm_get_pllout(); -+ new_lcd_div = new_pll / boot_config.lcd_clk; -+ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -+ -+ if (new_lcd_div < 1) -+ new_lcd_div = 1; -+ if (new_lcd_div > 16) -+ new_lcd_div = 16; -+ -+ if (new_lcdpix_div < 1) -+ new_lcdpix_div = 1; -+ if (new_lcdpix_div > 512) -+ new_lcdpix_div = 512; -+ -+ REG_CPM_CFCR2 = new_lcdpix_div - 1; -+ -+ cfcr = REG_CPM_CFCR; -+ cfcr &= ~CPM_CFCR_LFR_MASK; -+ cfcr |= ((new_lcd_div - 1) << CPM_CFCR_LFR_BIT); -+ cfcr |= CPM_CFCR_UPE; /* update immediately */ -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp)); -+} -+ -+static void jz_scale_pll(struct dpm_regs *regs) -+{ -+ unsigned int plcr1; -+ unsigned int cur_mclk, new_mclk, new_pll; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ int od[] = {1, 2, 2, 4}; -+ -+ plcr1 = REG_CPM_PLCR1; -+ plcr1 &= ~(regs->plcr1_mask | CPM_PLCR1_PLL1S | CPM_PLCR1_PLL1EN | CPM_PLCR1_PLL1ST_MASK); -+ regs->plcr1 &= ~CPM_PLCR1_PLL1EN; -+ plcr1 |= (regs->plcr1 | 0xff); -+ -+ /* Update some DRAM parameters before changing frequency */ -+ new_pll = JZ_EXTAL * ((plcr1>>23)+2) / ((((plcr1>>18)&0x1f)+2) * od[(plcr1>>16)&0x03]); -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = new_pll / div[(REG_CPM_CFCR>>16) & 0xf]; -+ -+ /* -+ * Update some SDRAM parameters -+ */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* -+ * Update PLL, align code to cache line. -+ */ -+ plcr1 |= CPM_PLCR1_PLL1EN; -+ __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" (CPM_PLCR1), "r" (plcr1)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+#endif -+ -+static void jz4730_transition(struct dpm_regs *regs) -+{ -+ /* -+ * Get and save some boot-time conditions. -+ */ -+ jz_init_boot_config(); -+ -+#ifdef CHANGE_PLL -+ /* -+ * Disable LCD before scaling pll. -+ * LCD and LCD pixel clocks should not be changed even if the PLL -+ * output frequency has been changed. -+ */ -+ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -+#endif -+ /* -+ * Stop module clocks before scaling PLL -+ */ -+ __cpm_stop_eth(); -+ __cpm_stop_aic_pclk(); -+ __cpm_stop_aic_bitclk(); -+ -+ /* ... add more as necessary */ -+ -+ if (regs->pll_up_flag == PLL_GOES_UP) { -+ /* the pll frequency is going up, so change dividors first */ -+ jz_scale_divisors(regs); -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ } -+ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -+ /* the pll frequency is going down, so change pll first */ -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ jz_scale_divisors(regs); -+ } -+ else { -+ /* the pll frequency is unchanged, so change divisors only */ -+ jz_scale_divisors(regs); -+ } -+ -+ /* -+ * Restart module clocks before scaling PLL -+ */ -+ __cpm_start_eth(); -+ __cpm_start_aic_pclk(); -+ __cpm_start_aic_bitclk(); -+ -+ /* ... add more as necessary */ -+ -+#ifdef CHANGE_PLL -+ /* Scale the LCD divisors after scaling pll */ -+ if (regs->pll_up_flag != PLL_UNCHANGED) { -+ jz_scale_lcd_divisors(regs); -+ } -+ -+ /* Enable LCD controller */ -+ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -+ REG_LCD_CTRL |= LCD_CTRL_ENA; -+#endif -+ -+ /* Update system clocks */ -+ jz_update_clocks(); -+} -+ -+extern unsigned int idle_times; -+static unsigned int jz4730_freq_get(unsigned int cpu) -+{ -+ return (__cpm_get_iclk() / 1000); -+} -+ -+static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -+{ -+ int n2FR[33] = { -+ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -+ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -+ 9 -+ }; -+ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -+ unsigned int div_of_cclk, new_freq, i; -+ -+ regs->pll_up_flag = PLL_UNCHANGED; -+ regs->cfcr_mask = CPM_CFCR_IFR_MASK | CPM_CFCR_SFR_MASK | CPM_CFCR_PFR_MASK | CPM_CFCR_MFR_MASK; -+ -+ new_freq = jz4730_freq_table.table[index].frequency; -+ -+ do { -+ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -+ } while (div_of_cclk==0); -+ -+ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -+ for(i = 1; i<4; i++) { -+ div[i] = 3; -+ } -+ } else { -+ for(i = 1; i<4; i++) { -+ div[i] = 2; -+ } -+ } -+ -+ for(i = 0; i<4; i++) { -+ div[i] *= div_of_cclk; -+ } -+ -+ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -+ -+ regs->cfcr = (n2FR[div[0]] << CPM_CFCR_IFR_BIT) | -+ (n2FR[div[1]] << CPM_CFCR_SFR_BIT) | -+ (n2FR[div[2]] << CPM_CFCR_PFR_BIT) | -+ (n2FR[div[3]] << CPM_CFCR_MFR_BIT); -+ -+ return div_of_cclk; -+} -+ -+static void jz4730_set_cpu_divider_index(unsigned int cpu, unsigned int index) -+{ -+ unsigned long divisor, old_divisor; -+ struct cpufreq_freqs freqs; -+ struct dpm_regs regs; -+ -+ old_divisor = __cpm_get_pllout() / __cpm_get_iclk(); -+ divisor = index_to_divisor(index, ®s); -+ -+ freqs.old = __cpm_get_iclk() / 1000; -+ freqs.new = __cpm_get_pllout() / (1000 * divisor); -+ freqs.cpu = cpu; -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -+ -+ if (old_divisor != divisor) -+ jz4730_transition(®s); -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -+} -+ -+static int jz4730_freq_target(struct cpufreq_policy *policy, -+ unsigned int target_freq, -+ unsigned int relation) -+{ -+ unsigned int new_index = 0; -+ -+ if (cpufreq_frequency_table_target(policy, -+ &jz4730_freq_table.table[0], -+ target_freq, relation, &new_index)) -+ return -EINVAL; -+ -+ jz4730_set_cpu_divider_index(policy->cpu, new_index); -+ -+ dprintk("new frequency is %d KHz (REG_CPM_CFCR:0x%x)\n", __cpm_get_iclk() / 1000, REG_CPM_CFCR); -+ -+ return 0; -+} -+ -+static int jz4730_freq_verify(struct cpufreq_policy *policy) -+{ -+ return cpufreq_frequency_table_verify(policy, -+ &jz4730_freq_table.table[0]); -+} -+ -+static int __init jz4730_cpufreq_driver_init(struct cpufreq_policy *policy) -+{ -+ -+ struct cpufreq_frequency_table *table = &jz4730_freq_table.table[0]; -+ unsigned int MAX_FREQ; -+ -+ dprintk(KERN_INFO "Jz4730 cpufreq driver\n"); -+ -+ if (policy->cpu != 0) -+ return -EINVAL; -+ -+ policy->cur = MAX_FREQ = __cpm_get_iclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -+ -+ policy->cpuinfo.min_freq = MAX_FREQ/8; -+ policy->cpuinfo.max_freq = MAX_FREQ; -+ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -+ -+ table[0].index = 0; -+ table[0].frequency = MAX_FREQ/8; -+ table[1].index = 1; -+ table[1].frequency = MAX_FREQ/6; -+ table[2].index = 2; -+ table[2].frequency = MAX_FREQ/4; -+ table[3].index = 3; -+ table[3].frequency = MAX_FREQ/3; -+ table[4].index = 4; -+ table[4].frequency = MAX_FREQ/2; -+ table[5].index = 5; -+ table[5].frequency = MAX_FREQ; -+ table[6].index = 6; -+ table[6].frequency = CPUFREQ_TABLE_END; -+ -+ return cpufreq_frequency_table_cpuinfo(policy, table); -+} -+ -+static struct cpufreq_driver cpufreq_jz4730_driver = { -+// .flags = CPUFREQ_STICKY, -+ .init = jz4730_cpufreq_driver_init, -+ .verify = jz4730_freq_verify, -+ .target = jz4730_freq_target, -+ .get = jz4730_freq_get, -+ .name = "jz4730", -+}; -+ -+static int __init jz4730_cpufreq_init(void) -+{ -+ return cpufreq_register_driver(&cpufreq_jz4730_driver); -+} -+ -+static void __exit jz4730_cpufreq_exit(void) -+{ -+ cpufreq_unregister_driver(&cpufreq_jz4730_driver); -+} -+ -+module_init(jz4730_cpufreq_init); -+module_exit(jz4730_cpufreq_exit); -+ -+MODULE_AUTHOR("Regen "); -+MODULE_DESCRIPTION("cpufreq driver for Jz4730"); -+MODULE_LICENSE("GPL"); -+ -diff --git a/arch/mips/jz4730/dma.c b/arch/mips/jz4730/dma.c -new file mode 100644 -index 0000000..ca7d549 ---- /dev/null -+++ b/arch/mips/jz4730/dma.c -@@ -0,0 +1,509 @@ -+/* -+ * linux/arch/mips/jz4730/dma.c -+ * -+ * JZ4730 DMA PC-like APIs. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * A note on resource allocation: -+ * -+ * All drivers needing DMA channels, should allocate and release them -+ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -+ * -+ * In order to avoid problems, all processes should allocate resources in -+ * the same sequence and release them in the reverse order. -+ * -+ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -+ * When releasing them, first release the IRQ, then release the DMA. The -+ * main reason for this order is that, if you are requesting the DMA buffer -+ * done interrupt, you won't know the irq number until the DMA channel is -+ * returned from jz_request_dma(). -+ */ -+ -+struct jz_dma_chan jz_dma_table[NUM_DMA] = { -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+}; -+ -+ -+// Device FIFO addresses and default DMA modes -+static const struct { -+ unsigned int fifo_addr; -+ unsigned int dma_mode; -+ unsigned int dma_source; -+} dma_dev_table[NUM_DMA_DEV] = { -+ {CPHYSADDR(UART0_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -+ {CPHYSADDR(UART0_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -+ {CPHYSADDR(UART1_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT}, -+ {CPHYSADDR(UART1_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART1IN}, -+ {CPHYSADDR(UART2_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT}, -+ {CPHYSADDR(UART2_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART2IN}, -+ {CPHYSADDR(UART3_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT}, -+ {CPHYSADDR(UART3_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART3IN}, -+ {CPHYSADDR(SSI_DR), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT}, -+ {CPHYSADDR(SSI_DR), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_SSIIN}, -+ {CPHYSADDR(MSC_TXFIFO), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT}, -+ {CPHYSADDR(MSC_RXFIFO), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_MSCIN}, -+ {CPHYSADDR(AIC_DR), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -+ {CPHYSADDR(AIC_DR), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -+ {0, DMA_AUTOINIT, 0}, -+}; -+ -+ -+int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data) -+{ -+ int i, len = 0; -+ struct jz_dma_chan *chan; -+ -+ for (i = 0; i < NUM_DMA; i++) { -+ if ((chan = get_dma_chan(i)) != NULL) { -+ len += sprintf(buf + len, "%2d: %s\n", -+ i, chan->dev_str); -+ } -+ } -+ -+ if (fpos >= len) { -+ *start = buf; -+ *eof = 1; -+ return 0; -+ } -+ *start = buf + fpos; -+ if ((len -= fpos) > length) -+ return length; -+ *eof = 1; -+ return len; -+} -+ -+ -+void dump_jz_dma_channel(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > NUM_DMA) -+ return; -+ chan = &jz_dma_table[dmanr]; -+ -+ printk(KERN_INFO "DMA%d Register Dump:\n", dmanr); -+ printk(KERN_INFO " DMACR= 0x%08x\n", REG_DMAC_DMACR); -+ printk(KERN_INFO " DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -+ printk(KERN_INFO " DDAR = 0x%08x\n", REG_DMAC_DDAR(dmanr)); -+ printk(KERN_INFO " DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -+ printk(KERN_INFO " DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -+ printk(KERN_INFO " DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -+} -+ -+ -+/** -+ * jz_request_dma - dynamically allcate an idle DMA channel to return -+ * @dev_id: the specified dma device id or DMA_ID_RAW_REQ -+ * @dev_str: the specified dma device string name -+ * @irqhandler: the irq handler, or NULL -+ * @irqflags: the irq handler flags -+ * @irq_dev_id: the irq handler device id for shared irq -+ * -+ * Finds a free channel, and binds the requested device to it. -+ * Returns the allocated channel number, or negative on error. -+ * Requests the DMA done IRQ if irqhandler != NULL. -+ * -+*/ -+int jz_request_dma(int dev_id, const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+{ -+ struct jz_dma_chan *chan; -+ int i, ret; -+ -+ if (dev_id < 0 || dev_id >= NUM_DMA_DEV) -+ return -EINVAL; -+ -+ for (i = 0; i < NUM_DMA; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == NUM_DMA) -+ return -ENODEV; -+ -+ chan = &jz_dma_table[i]; -+ -+ if (irqhandler) { -+ chan->irq = IRQ_DMA_0 + i; // see intc.h -+ chan->irq_dev = irq_dev_id; -+ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -+ dev_str, chan->irq_dev))) { -+ chan->irq = 0; -+ chan->irq_dev = NULL; -+ return ret; -+ } -+ } else { -+ chan->irq = 0; -+ chan->irq_dev = NULL; -+ } -+ -+ // fill it in -+ chan->io = i; -+ chan->dev_id = dev_id; -+ chan->dev_str = dev_str; -+ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -+ chan->mode = dma_dev_table[dev_id].dma_mode; -+ chan->source = dma_dev_table[dev_id].dma_source; -+ -+ return i; -+} -+ -+void jz_free_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) { -+ printk("Trying to free DMA%d\n", dmanr); -+ return; -+ } -+ -+ disable_dma(dmanr); -+ if (chan->irq) -+ free_irq(chan->irq, chan->irq_dev); -+ -+ chan->irq = 0; -+ chan->irq_dev = NULL; -+ chan->dev_id = -1; -+} -+ -+void jz_set_dma_dest_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ chan->mode &= ~DMAC_DCCSR_DWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCCSR_DWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCCSR_DWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCCSR_DWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_src_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ chan->mode &= ~DMAC_DCCSR_SWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCCSR_SWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCCSR_SWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCCSR_SWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_block_size(int dmanr, int nbyte) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ chan->mode &= ~DMAC_DCCSR_DS_MASK; -+ switch (nbyte) { -+ case 1: -+ chan->mode |= DMAC_DCCSR_DS_8b; -+ break; -+ case 2: -+ chan->mode |= DMAC_DCCSR_DS_16b; -+ break; -+ case 4: -+ chan->mode |= DMAC_DCCSR_DS_32b; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCCSR_DS_16B; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCCSR_DS_32B; -+ break; -+ } -+} -+ -+/** -+ * jz_set_dma_mode - do the raw settings for the specified DMA channel -+ * @dmanr: the specified DMA channel -+ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -+ * @dma_mode: dma raw mode -+ * @dma_source: dma raw request source -+ * @fifo_addr: dma raw device fifo address -+ * -+ * Ensure call jz_request_dma(DMA_ID_RAW_REQ, ...) first, then call -+ * jz_set_dma_mode() rather than set_dma_mode() if you work with -+ * and external request dma device. -+ * -+ * NOTE: Don not dynamically allocate dma channel if one external request -+ * dma device will occupy this channel. -+*/ -+int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -+ unsigned int dma_mode, unsigned int dma_source, -+ unsigned int fifo_addr) -+{ -+ int dev_id, i; -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > NUM_DMA) -+ return -ENODEV; -+ for (i = 0; i < NUM_DMA; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == NUM_DMA) -+ return -ENODEV; -+ -+ chan = &jz_dma_table[dmanr]; -+ dev_id = chan->dev_id; -+ if (dev_id > 0) { -+ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -+ __FUNCTION__, dmanr); -+ return -ENODEV; -+ } -+ -+ /* clone it from the dynamically allocated. */ -+ if (i != dmanr) { -+ chan->irq = jz_dma_table[i].irq; -+ chan->irq_dev = jz_dma_table[i].irq_dev; -+ chan->dev_str = jz_dma_table[i].dev_str; -+ jz_dma_table[i].irq = 0; -+ jz_dma_table[i].irq_dev = NULL; -+ jz_dma_table[i].dev_id = -1; -+ } -+ chan->dev_id = DMA_ID_RAW_SET; -+ chan->io = dmanr; -+ chan->fifo_addr = fifo_addr; -+ chan->mode = dma_mode; -+ chan->source = dma_source; -+ -+ set_dma_mode(dmanr, dma_mode); -+ -+ return dmanr; -+} -+ -+void enable_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ __dmac_enable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_enable_irq(dmanr); -+} -+ -+#define DMA_DISABLE_POLL 0x5000 -+ -+void disable_dma(unsigned int dmanr) -+{ -+ int i; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ if (!__dmac_channel_enabled(dmanr)) -+ return; -+ -+ for (i = 0; i < DMA_DISABLE_POLL; i++) -+ if (__dmac_channel_transmit_end_detected(dmanr)) -+ break; -+#if 0 -+ if (i == DMA_DISABLE_POLL) -+ printk(KERN_INFO "disable_dma: poll expired!\n"); -+#endif -+ -+ __dmac_disable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_disable_irq(dmanr); -+} -+ -+/* note: DMA_MODE_MASK is simulated by sw, DCCSR_MODE_MASK mask hw bits */ -+void set_dma_mode(unsigned int dmanr, unsigned int mode) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -+ mode &= DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ chan->mode |= DMAC_DCCSR_DAM; -+ chan->mode &= ~DMAC_DCCSR_SAM; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM; -+ chan->mode &= ~DMAC_DCCSR_DAM; -+ } else { -+ printk(KERN_DEBUG "set_dma_mode() support DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ } -+ REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+} -+ -+void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case AFMT_U8: -+ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -+ break; -+ case AFMT_S16_LE: -+ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCCSR_DAM; -+ chan->mode &= ~DMAC_DCCSR_SAM; -+ } else if (mode == DMA_MODE_WRITE) { -+ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM |DMAC_DCCSR_DAM); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM; -+ chan->mode &= ~DMAC_DCCSR_DAM; -+ } else -+ printk("jz_set_oss_dma() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case 8: -+ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -+ break; -+ case 16: -+ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCCSR_DAM; -+ chan->mode &= ~DMAC_DCCSR_SAM; -+ } else if (mode == DMA_MODE_WRITE) { -+ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM; -+ chan->mode &= ~DMAC_DCCSR_DAM; -+ } else -+ printk("jz_set_alsa_dma() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+void set_dma_addr(unsigned int dmanr, unsigned int a) -+{ -+ unsigned int mode; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ mode = chan->mode & DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -+ REG_DMAC_DDAR(chan->io) = a; -+ } else if (mode == DMA_MODE_WRITE) { -+ REG_DMAC_DSAR(chan->io) = a; -+ REG_DMAC_DDAR(chan->io) = chan->fifo_addr; -+ } else -+ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -+} -+ -+void set_dma_count(unsigned int dmanr, unsigned int count) -+{ -+ unsigned int mode; -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ mode = (chan->mode & DMAC_DCCSR_DS_MASK) >> DMAC_DCCSR_DS_BIT; -+ count = count / dma_ds[mode]; -+ REG_DMAC_DTCR(chan->io) = count; -+} -+ -+int get_dma_residue(unsigned int dmanr) -+{ -+ int count; -+ unsigned int mode; -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ -+ mode = (chan->mode & DMAC_DCCSR_DS_MASK) >> DMAC_DCCSR_DS_BIT; -+ count = REG_DMAC_DTCR(chan->io); -+ count = count * dma_ds[mode]; -+ -+ return count; -+} -+ -+EXPORT_SYMBOL(jz_dma_table); -+EXPORT_SYMBOL(jz_request_dma); -+EXPORT_SYMBOL(jz_free_dma); -+EXPORT_SYMBOL(jz_set_dma_src_width); -+EXPORT_SYMBOL(jz_set_dma_dest_width); -+EXPORT_SYMBOL(jz_set_dma_block_size); -+EXPORT_SYMBOL(jz_set_dma_mode); -+EXPORT_SYMBOL(set_dma_mode); -+EXPORT_SYMBOL(jz_set_oss_dma); -+EXPORT_SYMBOL(jz_set_alsa_dma); -+EXPORT_SYMBOL(set_dma_addr); -+EXPORT_SYMBOL(set_dma_count); -+EXPORT_SYMBOL(get_dma_residue); -+EXPORT_SYMBOL(enable_dma); -+EXPORT_SYMBOL(disable_dma); -+EXPORT_SYMBOL(dump_jz_dma_channel); -diff --git a/arch/mips/jz4730/i2c.c b/arch/mips/jz4730/i2c.c -new file mode 100644 -index 0000000..91f55a7 ---- /dev/null -+++ b/arch/mips/jz4730/i2c.c -@@ -0,0 +1,214 @@ -+/* -+ * linux/arch/mips/jz4730/i2c.c -+ * -+ * JZ4730 I2C APIs. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* I2C protocol */ -+#define I2C_READ 1 -+#define I2C_WRITE 0 -+ -+#define TIMEOUT 1000 -+ -+/* -+ * I2C bus protocol basic routines -+ */ -+static int i2c_put_data(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT * 10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (!__i2c_received_ack() && timeout) -+ timeout--; -+ -+ if (timeout) -+ return 0; -+ else -+ return -ETIMEDOUT; -+} -+ -+static int i2c_get_data(unsigned char *data, int ack) -+{ -+ int timeout = TIMEOUT*10; -+ -+ if (!ack) -+ __i2c_send_nack(); -+ else -+ __i2c_send_ack(); -+ -+ while (__i2c_check_drf() == 0 && timeout) -+ timeout--; -+ -+ if (timeout) { -+ if (!ack) -+ __i2c_send_stop(); -+ *data = __i2c_read(); -+ __i2c_clear_drf(); -+ return 0; -+ } else -+ return -ETIMEDOUT; -+} -+ -+/* -+ * I2C interface -+ */ -+void i2c_open(void) -+{ -+ __i2c_set_clk(jz_clocks.devclk, 10000); /* default 10 KHz */ -+ __i2c_enable(); -+} -+ -+void i2c_close(void) -+{ -+ udelay(300); /* wait for STOP goes over. */ -+ __i2c_disable(); -+} -+ -+void i2c_setclk(unsigned int i2cclk) -+{ -+ __i2c_set_clk(jz_clocks.devclk, i2cclk); -+} -+ -+int i2c_lseek(unsigned char device, unsigned char offset) -+{ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+ if (i2c_put_data(offset) < 0) -+ goto address_err; -+ return 0; -+ device_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+ address_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -+ __i2c_send_stop(); -+ return -EREMOTEIO; -+} -+ -+int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int timeout = 5; -+ -+L_try_again: -+ -+ if (timeout < 0) -+ goto L_timeout; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_werr; -+ if (i2c_put_data(address) < 0) -+ goto address_err; -+ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -+ goto device_rerr; -+ __i2c_send_ack(); /* Master sends ACK for continue reading */ -+ while (cnt) { -+ if (cnt == 1) { -+ if (i2c_get_data(buf, 0) < 0) -+ break; -+ } else { -+ if (i2c_get_data(buf, 1) < 0) -+ break; -+ } -+ cnt--; -+ buf++; -+ } -+ -+ __i2c_send_stop(); -+ return count - cnt; -+ device_rerr: -+ device_werr: -+ address_err: -+ timeout --; -+ __i2c_send_stop(); -+ goto L_try_again; -+ -+L_timeout: -+ __i2c_send_stop(); -+ printk("Read I2C device 0x%2x failed.\n", device); -+ return -ENODEV; -+} -+ -+int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int cnt_in_pg; -+ int timeout = 5; -+ unsigned char *tmpbuf; -+ unsigned char tmpaddr; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ -+ W_try_again: -+ if (timeout < 0) -+ goto W_timeout; -+ -+ cnt = count; -+ tmpbuf = (unsigned char *)buf; -+ tmpaddr = address; -+ -+ start_write_page: -+ cnt_in_pg = 0; -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ __i2c_send_stop(); -+ return count - cnt; -+ device_err: -+ address_err: -+ timeout--; -+ __i2c_send_stop(); -+ goto W_try_again; -+ -+ W_timeout: -+ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+} -+ -+EXPORT_SYMBOL(i2c_open); -+EXPORT_SYMBOL(i2c_close); -+EXPORT_SYMBOL(i2c_setclk); -+EXPORT_SYMBOL(i2c_read); -+EXPORT_SYMBOL(i2c_write); -diff --git a/arch/mips/jz4730/irq.c b/arch/mips/jz4730/irq.c -new file mode 100644 -index 0000000..658596f ---- /dev/null -+++ b/arch/mips/jz4730/irq.c -@@ -0,0 +1,266 @@ -+/* -+ * linux/arch/mips/jz4730/irq.c -+ * -+ * JZ4730 interrupt routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * INTC irq type -+ */ -+ -+static void enable_intc_irq(unsigned int irq) -+{ -+ __intc_unmask_irq(irq); -+} -+ -+static void disable_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+} -+ -+static void mask_and_ack_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+ __intc_ack_irq(irq); -+} -+ -+static void end_intc_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_intc_irq(irq); -+ } -+} -+ -+static unsigned int startup_intc_irq(unsigned int irq) -+{ -+ enable_intc_irq(irq); -+ return 0; -+} -+ -+static void shutdown_intc_irq(unsigned int irq) -+{ -+ disable_intc_irq(irq); -+} -+ -+static struct irq_chip intc_irq_type = { -+ .typename = "INTC", -+ .startup = startup_intc_irq, -+ .shutdown = shutdown_intc_irq, -+ .enable = enable_intc_irq, -+ .disable = disable_intc_irq, -+ .ack = mask_and_ack_intc_irq, -+ .end = end_intc_irq, -+}; -+ -+/* -+ * GPIO irq type -+ */ -+ -+static void enable_gpio_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if (irq < (IRQ_GPIO_0 + 32)) { -+ intc_irq = IRQ_GPIO0; -+ } -+ else if (irq < (IRQ_GPIO_0 + 64)) { -+ intc_irq = IRQ_GPIO1; -+ } -+ else if (irq < (IRQ_GPIO_0 + 96)) { -+ intc_irq = IRQ_GPIO2; -+ } -+ else { -+ intc_irq = IRQ_GPIO3; -+ } -+ -+ enable_intc_irq(intc_irq); -+ __gpio_unmask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void disable_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void mask_and_ack_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+ __gpio_ack_irq(irq - IRQ_GPIO_0); -+} -+ -+static void end_gpio_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_gpio_irq(irq); -+ } -+} -+ -+static unsigned int startup_gpio_irq(unsigned int irq) -+{ -+ enable_gpio_irq(irq); -+ return 0; -+} -+ -+static void shutdown_gpio_irq(unsigned int irq) -+{ -+ disable_gpio_irq(irq); -+} -+ -+static struct irq_chip gpio_irq_type = { -+ .typename = "GPIO", -+ .startup = startup_gpio_irq, -+ .shutdown = shutdown_gpio_irq, -+ .enable = enable_gpio_irq, -+ .disable = disable_gpio_irq, -+ .ack = mask_and_ack_gpio_irq, -+ .end = end_gpio_irq, -+}; -+ -+/* -+ * DMA irq type -+ */ -+ -+static void enable_dma_irq(unsigned int irq) -+{ -+ __intc_unmask_irq(IRQ_DMAC); -+ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -+} -+ -+static void disable_dma_irq(unsigned int irq) -+{ -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void mask_and_ack_dma_irq(unsigned int irq) -+{ -+ __intc_ack_irq(IRQ_DMAC); -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void end_dma_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_dma_irq(irq); -+ } -+} -+ -+static unsigned int startup_dma_irq(unsigned int irq) -+{ -+ enable_dma_irq(irq); -+ return 0; -+} -+ -+static void shutdown_dma_irq(unsigned int irq) -+{ -+ disable_dma_irq(irq); -+} -+ -+static struct irq_chip dma_irq_type = { -+ .typename = "DMA", -+ .startup = startup_dma_irq, -+ .shutdown = shutdown_dma_irq, -+ .enable = enable_dma_irq, -+ .disable = disable_dma_irq, -+ .ack = mask_and_ack_dma_irq, -+ .end = end_dma_irq, -+}; -+ -+//---------------------------------------------------------------------- -+ -+void __init arch_init_irq(void) -+{ -+ int i; -+ -+ clear_c0_status(0xff04); /* clear ERL */ -+ set_c0_status(0x0400); /* set IP2 */ -+ -+ /* Set up INTC irq -+ */ -+ for (i = 0; i < 32; i++) { -+ disable_intc_irq(i); -+ irq_desc[i].chip = &intc_irq_type; -+ } -+ -+ /* Set up DMAC irq -+ */ -+ for (i = 0; i < NUM_DMA; i++) { -+ disable_dma_irq(IRQ_DMA_0 + i); -+ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -+ } -+ -+ /* Set up GPIO irq -+ */ -+ for (i = 0; i < NUM_GPIO; i++) { -+ disable_gpio_irq(IRQ_GPIO_0 + i); -+ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -+ } -+} -+ -+static int plat_real_irq(int irq) -+{ -+ switch (irq) { -+ case IRQ_GPIO0: -+ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -+ break; -+ case IRQ_GPIO1: -+ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -+ break; -+ case IRQ_GPIO2: -+ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -+ break; -+ case IRQ_GPIO3: -+ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -+ break; -+ case IRQ_DMAC: -+ irq = __dmac_get_irq() + IRQ_DMA_0; -+ break; -+ } -+ -+ return irq; -+} -+ -+asmlinkage void plat_irq_dispatch(void) -+{ -+ int irq = 0; -+ static unsigned long intc_ipr = 0; -+ -+ intc_ipr |= REG_INTC_IPR; -+ -+ if (!intc_ipr) return; -+ -+ irq = ffs(intc_ipr) - 1; -+ intc_ipr &= ~(1< -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* OHCI (USB full speed host controller) */ -+static struct resource jz_usb_ohci_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -+ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UHC, -+ .end = IRQ_UHC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+/* The dmamask must be set for OHCI to work */ -+static u64 ohci_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_ohci_device = { -+ .name = "jz-ohci", -+ .id = 0, -+ .dev = { -+ .dma_mask = &ohci_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -+ .resource = jz_usb_ohci_resources, -+}; -+ -+/*** LCD controller ***/ -+static struct resource jz_lcd_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(LCD_BASE), -+ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_LCD, -+ .end = IRQ_LCD, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_lcd_dmamask = ~(u32)0; -+ -+static struct platform_device jz_lcd_device = { -+ .name = "jz-lcd", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_lcd_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_lcd_resources), -+ .resource = jz_lcd_resources, -+}; -+ -+/* UDC (USB gadget controller) */ -+static struct resource jz_usb_gdt_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UDC_BASE), -+ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UDC, -+ .end = IRQ_UDC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 udc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_gdt_device = { -+ .name = "jz-udc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &udc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -+ .resource = jz_usb_gdt_resources, -+}; -+ -+/** MMC/SD controller **/ -+static struct resource jz_mmc_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(MSC_BASE), -+ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_MSC, -+ .end = IRQ_MSC, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_mmc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_mmc_device = { -+ .name = "jz-mmc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_mmc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_mmc_resources), -+ .resource = jz_mmc_resources, -+}; -+ -+/* All */ -+static struct platform_device *jz_platform_devices[] __initdata = { -+ &jz_usb_ohci_device, -+ &jz_lcd_device, -+ &jz_usb_gdt_device, -+ &jz_mmc_device, -+}; -+ -+static int __init jz_platform_init(void) -+{ -+ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -+} -+ -+arch_initcall(jz_platform_init); -diff --git a/arch/mips/jz4730/pm.c b/arch/mips/jz4730/pm.c -new file mode 100644 -index 0000000..a46e9c3 ---- /dev/null -+++ b/arch/mips/jz4730/pm.c -@@ -0,0 +1,1098 @@ -+/* -+ * linux/arch/mips/jz4730/pm.c -+ * -+ * Jz4730 Power Management Routines -+ * -+ * Copyright 2005 Ingenic Semiconductor -+ * Wei Jianli -+ * Huang Lihong -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+extern void jz_cpu_suspend(void); -+extern void jz_cpu_resume(void); -+ -+static void jz_board_pm_suspend(void); -+ -+#define SAVE(x,s) sleep_save[SLEEP_SAVE_##x] = REG##s(x) -+#define RESTORE(x,s) REG##s(x) = sleep_save[SLEEP_SAVE_##x] -+ -+/* -+ * List of global jz4730 peripheral registers to preserve. -+ * More ones like core register and general purpose register values -+ * are preserved with the stack pointer in sleep.S. -+ */ -+enum { SLEEP_SAVE_START = 0, -+ -+ /* CPM */ -+ SLEEP_SAVE_CPM_MSCR, SLEEP_SAVE_CPM_PLCR1, -+ -+ /* WDT */ -+ SLEEP_SAVE_WDT_WTCNT, SLEEP_SAVE_WDT_WTCSR, -+ -+ /* OST */ -+ SLEEP_SAVE_OST_TER, -+ SLEEP_SAVE_OST_TCSR0, SLEEP_SAVE_OST_TCSR1, SLEEP_SAVE_OST_TCSR2, -+ SLEEP_SAVE_OST_TRDR0, SLEEP_SAVE_OST_TRDR1, SLEEP_SAVE_OST_TRDR2, -+ SLEEP_SAVE_OST_TCNT0, SLEEP_SAVE_OST_TCNT1, SLEEP_SAVE_OST_TCNT2, -+ -+ /* HARB */ -+ SLEEP_SAVE_HARB_HAPOR, SLEEP_SAVE_HARB_HMCTR, SLEEP_SAVE_HARB_HMLTR, -+ -+ /* EMC */ -+ SLEEP_SAVE_EMC_SMCR0, SLEEP_SAVE_EMC_SMCR1, SLEEP_SAVE_EMC_SMCR2, SLEEP_SAVE_EMC_SMCR3, -+ SLEEP_SAVE_EMC_SMCR4, SLEEP_SAVE_EMC_SMCR5, -+ -+ /* GPIO */ -+ SLEEP_SAVE_GPIO_GPDR0, SLEEP_SAVE_GPIO_GPDR1, SLEEP_SAVE_GPIO_GPDR2, SLEEP_SAVE_GPIO_GPDR3, -+ SLEEP_SAVE_GPIO_GPDIR0, SLEEP_SAVE_GPIO_GPDIR1, SLEEP_SAVE_GPIO_GPDIR2, SLEEP_SAVE_GPIO_GPDIR3, -+ SLEEP_SAVE_GPIO_GPODR0, SLEEP_SAVE_GPIO_GPODR1, SLEEP_SAVE_GPIO_GPODR2, SLEEP_SAVE_GPIO_GPODR3, -+ SLEEP_SAVE_GPIO_GPPUR0, SLEEP_SAVE_GPIO_GPPUR1, SLEEP_SAVE_GPIO_GPPUR2, SLEEP_SAVE_GPIO_GPPUR3, -+ SLEEP_SAVE_GPIO_GPALR0, SLEEP_SAVE_GPIO_GPALR1, SLEEP_SAVE_GPIO_GPALR2, SLEEP_SAVE_GPIO_GPALR3, -+ SLEEP_SAVE_GPIO_GPAUR0, SLEEP_SAVE_GPIO_GPAUR1, SLEEP_SAVE_GPIO_GPAUR2, SLEEP_SAVE_GPIO_GPAUR3, -+ SLEEP_SAVE_GPIO_GPIDLR0, SLEEP_SAVE_GPIO_GPIDLR1, SLEEP_SAVE_GPIO_GPIDLR2, SLEEP_SAVE_GPIO_GPIDLR3, -+ SLEEP_SAVE_GPIO_GPIDUR0, SLEEP_SAVE_GPIO_GPIDUR1, SLEEP_SAVE_GPIO_GPIDUR2, SLEEP_SAVE_GPIO_GPIDUR3, -+ SLEEP_SAVE_GPIO_GPIER0, SLEEP_SAVE_GPIO_GPIER1, SLEEP_SAVE_GPIO_GPIER2, SLEEP_SAVE_GPIO_GPIER3, -+ SLEEP_SAVE_GPIO_GPIMR0, SLEEP_SAVE_GPIO_GPIMR1, SLEEP_SAVE_GPIO_GPIMR2, SLEEP_SAVE_GPIO_GPIMR3, -+ SLEEP_SAVE_GPIO_GPFR0, SLEEP_SAVE_GPIO_GPFR1, SLEEP_SAVE_GPIO_GPFR2, SLEEP_SAVE_GPIO_GPFR3, -+ -+ /* UART(0-3) */ -+ SLEEP_SAVE_UART0_IER, SLEEP_SAVE_UART0_LCR, SLEEP_SAVE_UART0_MCR, SLEEP_SAVE_UART0_SPR, SLEEP_SAVE_UART0_DLLR, SLEEP_SAVE_UART0_DLHR, -+ SLEEP_SAVE_UART1_IER, SLEEP_SAVE_UART1_LCR, SLEEP_SAVE_UART1_MCR, SLEEP_SAVE_UART1_SPR, SLEEP_SAVE_UART1_DLLR, SLEEP_SAVE_UART1_DLHR, -+ SLEEP_SAVE_UART2_IER, SLEEP_SAVE_UART2_LCR, SLEEP_SAVE_UART2_MCR, SLEEP_SAVE_UART2_SPR, SLEEP_SAVE_UART2_DLLR, SLEEP_SAVE_UART2_DLHR, -+ SLEEP_SAVE_UART3_IER, SLEEP_SAVE_UART3_LCR, SLEEP_SAVE_UART3_MCR, SLEEP_SAVE_UART3_SPR, SLEEP_SAVE_UART3_DLLR, SLEEP_SAVE_UART3_DLHR, -+ -+ /* DMAC */ -+ SLEEP_SAVE_DMAC_DMACR, -+ SLEEP_SAVE_DMAC_DSAR0, SLEEP_SAVE_DMAC_DSAR1, SLEEP_SAVE_DMAC_DSAR2, SLEEP_SAVE_DMAC_DSAR3, SLEEP_SAVE_DMAC_DSAR4, SLEEP_SAVE_DMAC_DSAR5, SLEEP_SAVE_DMAC_DSAR6, SLEEP_SAVE_DMAC_DSAR7, -+ SLEEP_SAVE_DMAC_DDAR0, SLEEP_SAVE_DMAC_DDAR1, SLEEP_SAVE_DMAC_DDAR2, SLEEP_SAVE_DMAC_DDAR3, SLEEP_SAVE_DMAC_DDAR4, SLEEP_SAVE_DMAC_DDAR5, SLEEP_SAVE_DMAC_DDAR6, SLEEP_SAVE_DMAC_DDAR7, -+ SLEEP_SAVE_DMAC_DTCR0, SLEEP_SAVE_DMAC_DTCR1, SLEEP_SAVE_DMAC_DTCR2, SLEEP_SAVE_DMAC_DTCR3, SLEEP_SAVE_DMAC_DTCR4, SLEEP_SAVE_DMAC_DTCR5, SLEEP_SAVE_DMAC_DTCR6, SLEEP_SAVE_DMAC_DTCR7, -+ SLEEP_SAVE_DMAC_DRSR0, SLEEP_SAVE_DMAC_DRSR1, SLEEP_SAVE_DMAC_DRSR2, SLEEP_SAVE_DMAC_DRSR3, SLEEP_SAVE_DMAC_DRSR4, SLEEP_SAVE_DMAC_DRSR5, SLEEP_SAVE_DMAC_DRSR6, SLEEP_SAVE_DMAC_DRSR7, -+ SLEEP_SAVE_DMAC_DCCSR0, SLEEP_SAVE_DMAC_DCCSR1, SLEEP_SAVE_DMAC_DCCSR2, SLEEP_SAVE_DMAC_DCCSR3, SLEEP_SAVE_DMAC_DCCSR4, SLEEP_SAVE_DMAC_DCCSR5, SLEEP_SAVE_DMAC_DCCSR6, SLEEP_SAVE_DMAC_DCCSR7, -+ -+ /* INTC */ -+ SLEEP_SAVE_INTC_IPR, SLEEP_SAVE_INTC_ISR, SLEEP_SAVE_INTC_IMR, -+ -+ /* Checksum */ -+ SLEEP_SAVE_CKSUM, -+ -+ SLEEP_SAVE_SIZE -+}; -+ -+static unsigned long sleep_save[SLEEP_SAVE_SIZE]; -+ -+static int jz_pm_do_suspend(void) -+{ -+ unsigned long checksum = 0; -+ unsigned long imr = REG_INTC_IMR; -+ int i; -+ -+ printk("Put cpu into suspend mode.\n"); -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* Preserve current time */ -+ REG_RTC_RSR = xtime.tv_sec; -+ -+ REG_CPM_OCR |= CPM_OCR_SUSPEND_PHY0; /* suspend USB PHY 0 */ -+ REG_CPM_OCR |= CPM_OCR_SUSPEND_PHY1; /* suspend USB PHY 1 */ -+ REG_CPM_OCR |= CPM_OCR_EXT_RTC_CLK; /* select the external RTC clock (32.768KHz) */ -+ -+ /* Disable NAND ctroller */ -+ REG_EMC_NFCSR &= ~(EMC_NFCSR_NFE | EMC_NFCSR_FCE); -+ -+ /* -+ * Temporary solution. This won't be necessary once -+ * we move this support into the device drivers. -+ * Save the on-chip modules -+ */ -+ SAVE(UART0_LCR, 8); SAVE(UART0_MCR, 8); SAVE(UART0_SPR, 8); -+ REG8(UART0_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ SAVE(UART0_DLLR, 8); SAVE(UART0_DLHR, 8); -+ REG8(UART0_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ SAVE(UART0_IER, 8); -+ -+ SAVE(UART1_LCR, 8); SAVE(UART1_MCR, 8); SAVE(UART1_SPR, 8); -+ REG8(UART1_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ SAVE(UART1_DLLR, 8); SAVE(UART1_DLHR, 8); -+ REG8(UART1_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ SAVE(UART1_IER, 8); -+ -+ SAVE(UART2_LCR, 8); SAVE(UART2_MCR, 8); SAVE(UART2_SPR, 8); -+ REG8(UART2_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ SAVE(UART2_DLLR, 8); SAVE(UART2_DLHR, 8); -+ REG8(UART2_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ SAVE(UART2_IER, 8); -+ -+ SAVE(UART3_LCR, 8); SAVE(UART3_MCR, 8); SAVE(UART3_SPR, 8); -+ REG8(UART3_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ SAVE(UART3_DLLR, 8); SAVE(UART3_DLHR, 8); -+ REG8(UART3_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ SAVE(UART3_IER, 8); -+ -+ /* Save vital registers */ -+ -+ SAVE(OST_TER, 8); -+ SAVE(OST_TCSR0, 16); SAVE(OST_TCSR1, 16); SAVE(OST_TCSR2, 16); -+ SAVE(OST_TRDR0, 32); SAVE(OST_TRDR1, 32); SAVE(OST_TRDR2, 32); -+ SAVE(OST_TCNT0, 32); SAVE(OST_TCNT1, 32); SAVE(OST_TCNT2, 32); -+ -+ SAVE(HARB_HAPOR, 32); SAVE(HARB_HMCTR, 32); SAVE(HARB_HMLTR, 32); -+ -+ SAVE(EMC_SMCR0, 32); SAVE(EMC_SMCR1, 32); SAVE(EMC_SMCR2, 32); SAVE(EMC_SMCR3, 32); -+ SAVE(EMC_SMCR4, 32); SAVE(EMC_SMCR5, 32); -+ -+ SAVE(GPIO_GPDR0, 32); SAVE(GPIO_GPDR1, 32); SAVE(GPIO_GPDR2, 32); -+ SAVE(GPIO_GPDR3, 32); -+ SAVE(GPIO_GPDIR0, 32); SAVE(GPIO_GPDIR1, 32); SAVE(GPIO_GPDIR2, 32); -+ SAVE(GPIO_GPDIR3, 32); -+ SAVE(GPIO_GPODR0, 32); SAVE(GPIO_GPODR1, 32); SAVE(GPIO_GPODR2, 32); -+ SAVE(GPIO_GPODR3, 32); -+ SAVE(GPIO_GPPUR0, 32); SAVE(GPIO_GPPUR1, 32); SAVE(GPIO_GPPUR2, 32); -+ SAVE(GPIO_GPPUR3, 32); -+ SAVE(GPIO_GPALR0, 32); SAVE(GPIO_GPALR1, 32); SAVE(GPIO_GPALR2, 32); -+ SAVE(GPIO_GPALR3, 32); -+ SAVE(GPIO_GPAUR0, 32); SAVE(GPIO_GPAUR1, 32); SAVE(GPIO_GPAUR2, 32); -+ SAVE(GPIO_GPAUR3, 32); -+ SAVE(GPIO_GPIDLR0, 32); SAVE(GPIO_GPIDLR1, 32); SAVE(GPIO_GPIDLR2, 32); -+ SAVE(GPIO_GPIDLR3, 32); -+ SAVE(GPIO_GPIDUR0, 32); SAVE(GPIO_GPIDUR1, 32); SAVE(GPIO_GPIDUR2, 32); -+ SAVE(GPIO_GPIDUR3, 32); -+ SAVE(GPIO_GPIER0, 32); SAVE(GPIO_GPIER1, 32); SAVE(GPIO_GPIER2, 32); -+ SAVE(GPIO_GPIER3, 32); -+ SAVE(GPIO_GPIMR0, 32); SAVE(GPIO_GPIMR1, 32); SAVE(GPIO_GPIMR2, 32); -+ SAVE(GPIO_GPIMR3, 32); -+ SAVE(GPIO_GPFR0, 32); SAVE(GPIO_GPFR1, 32); SAVE(GPIO_GPFR2, 32); -+ SAVE(GPIO_GPFR3, 32); -+ -+ SAVE(DMAC_DMACR, 32); -+ SAVE(DMAC_DSAR0, 32); SAVE(DMAC_DSAR1, 32); SAVE(DMAC_DSAR2, 32); SAVE(DMAC_DSAR3, 32); SAVE(DMAC_DSAR4, 32); SAVE(DMAC_DSAR5, 32); SAVE(DMAC_DSAR6, 32); SAVE(DMAC_DSAR7, 32); -+ SAVE(DMAC_DDAR0, 32); SAVE(DMAC_DDAR1, 32); SAVE(DMAC_DDAR2, 32); SAVE(DMAC_DDAR3, 32); SAVE(DMAC_DDAR4, 32); SAVE(DMAC_DDAR5, 32); SAVE(DMAC_DDAR6, 32); SAVE(DMAC_DDAR7, 32); -+ SAVE(DMAC_DTCR0, 32); SAVE(DMAC_DTCR1, 32); SAVE(DMAC_DTCR2, 32); SAVE(DMAC_DTCR3, 32); SAVE(DMAC_DTCR4, 32); SAVE(DMAC_DTCR5, 32); SAVE(DMAC_DTCR6, 32); SAVE(DMAC_DTCR7, 32); -+ SAVE(DMAC_DRSR0, 32); SAVE(DMAC_DRSR1, 32); SAVE(DMAC_DRSR2, 32); SAVE(DMAC_DRSR3, 32); SAVE(DMAC_DRSR4, 32); SAVE(DMAC_DRSR5, 32); SAVE(DMAC_DRSR6, 32); SAVE(DMAC_DRSR7, 32); -+ SAVE(DMAC_DCCSR0, 32); SAVE(DMAC_DCCSR1, 32); SAVE(DMAC_DCCSR2, 32); SAVE(DMAC_DCCSR3, 32); SAVE(DMAC_DCCSR4, 32); SAVE(DMAC_DCCSR5, 32); SAVE(DMAC_DCCSR6, 32); SAVE(DMAC_DCCSR7, 32); -+ -+ SAVE(INTC_IPR, 32);SAVE(INTC_ISR, 32);SAVE(INTC_IMR, 32); -+ -+ SAVE(WDT_WTCNT, 32);SAVE(WDT_WTCSR, 8); -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* Save module clocks */ -+ SAVE(CPM_MSCR, 32); -+ -+ /* Save PLL */ -+ SAVE(CPM_PLCR1, 32); -+ -+ /* Stop module clocks */ -+ __cpm_stop_uart0(); -+ __cpm_stop_uart1(); -+ __cpm_stop_uart2(); -+ __cpm_stop_uart3(); -+ __cpm_stop_uhc(); -+ __cpm_stop_udc(); -+ __cpm_stop_eth(); -+ __cpm_stop_cim(); -+ __cpm_stop_kbc(); -+ __cpm_stop_scc(); -+ __cpm_stop_ssi(); -+ __cpm_stop_ost(); -+ -+ /* platform-specific pm routine */ -+ jz_board_pm_suspend(); -+ -+ /* Clear previous reset status */ -+ REG_CPM_RSTR &= ~(CPM_RSTR_HR | CPM_RSTR_WR | CPM_RSTR_SR); -+ -+ /* Set resume return address */ -+ REG_CPM_SPR = virt_to_phys(jz_cpu_resume); -+ -+ /* Before sleeping, calculate and save a checksum */ -+ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) -+ checksum += sleep_save[i]; -+ sleep_save[SLEEP_SAVE_CKSUM] = checksum; -+ -+ /* *** go zzz *** */ -+ jz_cpu_suspend(); -+#if 0 -+ /* after sleeping, validate the checksum */ -+ checksum = 0; -+ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) -+ checksum += sleep_save[i]; -+ -+ /* if invalid, display message and wait for a hardware reset */ -+ if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { -+ /** Add platform-specific message display codes here **/ -+ while (1); -+ } -+#endif -+ /* Restore PLL */ -+ RESTORE(CPM_PLCR1, 32); -+ -+ /* Restore module clocks */ -+ RESTORE(CPM_MSCR, 32); -+ -+ /* Ensure not to come back here if it wasn't intended */ -+ REG_CPM_SPR = 0; -+ -+ /* Restore registers */ -+ -+ RESTORE(GPIO_GPDR0, 32); RESTORE(GPIO_GPDR1, 32); RESTORE(GPIO_GPDR2, 32); -+ RESTORE(GPIO_GPDR3, 32); -+ RESTORE(GPIO_GPDIR0, 32); RESTORE(GPIO_GPDIR1, 32); RESTORE(GPIO_GPDIR2, 32); -+ RESTORE(GPIO_GPDIR3, 32); -+ RESTORE(GPIO_GPODR0, 32); RESTORE(GPIO_GPODR1, 32); RESTORE(GPIO_GPODR2, 32); -+ RESTORE(GPIO_GPODR3, 32); -+ RESTORE(GPIO_GPPUR0, 32); RESTORE(GPIO_GPPUR1, 32); RESTORE(GPIO_GPPUR2, 32); -+ RESTORE(GPIO_GPPUR3, 32); -+ RESTORE(GPIO_GPALR0, 32); RESTORE(GPIO_GPALR1, 32); RESTORE(GPIO_GPALR2, 32); -+ RESTORE(GPIO_GPALR3, 32); -+ RESTORE(GPIO_GPAUR0, 32); RESTORE(GPIO_GPAUR1, 32); RESTORE(GPIO_GPAUR2, 32); -+ RESTORE(GPIO_GPAUR3, 32); -+ RESTORE(GPIO_GPIDLR0, 32);RESTORE(GPIO_GPIDLR1, 32);RESTORE(GPIO_GPIDLR2, 32); -+ RESTORE(GPIO_GPIDLR3, 32); -+ RESTORE(GPIO_GPIDUR0, 32);RESTORE(GPIO_GPIDUR1, 32);RESTORE(GPIO_GPIDUR2, 32); -+ RESTORE(GPIO_GPIDUR3, 32); -+ RESTORE(GPIO_GPIER0, 32); RESTORE(GPIO_GPIER1, 32); RESTORE(GPIO_GPIER2, 32); -+ RESTORE(GPIO_GPIER3, 32); -+ RESTORE(GPIO_GPIMR0, 32); RESTORE(GPIO_GPIMR1, 32); RESTORE(GPIO_GPIMR2, 32); -+ RESTORE(GPIO_GPIMR3, 32); -+ RESTORE(GPIO_GPFR0, 32); RESTORE(GPIO_GPFR1, 32); RESTORE(GPIO_GPFR2, 32); -+ RESTORE(GPIO_GPFR3, 32); -+ -+ RESTORE(EMC_SMCR0, 32); RESTORE(EMC_SMCR1, 32); RESTORE(EMC_SMCR2, 32); RESTORE(EMC_SMCR3, 32); -+ RESTORE(EMC_SMCR4, 32); RESTORE(EMC_SMCR5, 32); -+ -+ RESTORE(HARB_HAPOR, 32); RESTORE(HARB_HMCTR, 32); RESTORE(HARB_HMLTR, 32); -+ -+ RESTORE(OST_TCNT0, 32); RESTORE(OST_TCNT1, 32); RESTORE(OST_TCNT2, 32); -+ RESTORE(OST_TRDR0, 32); RESTORE(OST_TRDR1, 32); RESTORE(OST_TRDR2, 32); -+ RESTORE(OST_TCSR0, 16); RESTORE(OST_TCSR1, 16); RESTORE(OST_TCSR2, 16); -+ RESTORE(OST_TER, 8); -+ -+ RESTORE(DMAC_DMACR, 32); -+ RESTORE(DMAC_DSAR0, 32); RESTORE(DMAC_DSAR1, 32); RESTORE(DMAC_DSAR2, 32); RESTORE(DMAC_DSAR3, 32); RESTORE(DMAC_DSAR4, 32); RESTORE(DMAC_DSAR5, 32); RESTORE(DMAC_DSAR6, 32); RESTORE(DMAC_DSAR7, 32); -+ RESTORE(DMAC_DDAR0, 32); RESTORE(DMAC_DDAR1, 32); RESTORE(DMAC_DDAR2, 32); RESTORE(DMAC_DDAR3, 32); RESTORE(DMAC_DDAR4, 32); RESTORE(DMAC_DDAR5, 32); RESTORE(DMAC_DDAR6, 32); RESTORE(DMAC_DDAR7, 32); -+ RESTORE(DMAC_DTCR0, 32); RESTORE(DMAC_DTCR1, 32); RESTORE(DMAC_DTCR2, 32); RESTORE(DMAC_DTCR3, 32); RESTORE(DMAC_DTCR4, 32); RESTORE(DMAC_DTCR5, 32); RESTORE(DMAC_DTCR6, 32); RESTORE(DMAC_DTCR7, 32); -+ RESTORE(DMAC_DRSR0, 32); RESTORE(DMAC_DRSR1, 32); RESTORE(DMAC_DRSR2, 32); RESTORE(DMAC_DRSR3, 32); RESTORE(DMAC_DRSR4, 32); RESTORE(DMAC_DRSR5, 32); RESTORE(DMAC_DRSR6, 32); RESTORE(DMAC_DRSR7, 32); -+ RESTORE(DMAC_DCCSR0, 32); RESTORE(DMAC_DCCSR1, 32); RESTORE(DMAC_DCCSR2, 32); RESTORE(DMAC_DCCSR3, 32); RESTORE(DMAC_DCCSR4, 32); RESTORE(DMAC_DCCSR5, 32); RESTORE(DMAC_DCCSR6, 32); RESTORE(DMAC_DCCSR7, 32); -+ -+ RESTORE(INTC_IPR, 32);RESTORE(INTC_ISR, 32);RESTORE(INTC_IMR, 32); -+ -+ REG_WDT_WTCNT = 0; RESTORE(WDT_WTCSR, 8); -+ -+ /* -+ * Temporary solution. This won't be necessary once -+ * we move this support into the device drivers. -+ * Restore the on-chip modules. -+ */ -+ -+ /* FIFO control reg, write-only */ -+ REG8(UART0_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -+ REG8(UART1_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -+ REG8(UART2_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -+ REG8(UART3_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -+ -+ REG8(UART0_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ RESTORE(UART0_DLLR, 8); RESTORE(UART0_DLHR, 8); -+ REG8(UART0_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ RESTORE(UART0_IER, 8); -+ RESTORE(UART0_MCR, 8); RESTORE(UART0_SPR, 8); RESTORE(UART0_LCR, 8); -+ -+ REG8(UART1_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ RESTORE(UART1_DLLR, 8); RESTORE(UART1_DLHR, 8); -+ REG8(UART1_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ RESTORE(UART1_IER, 8); -+ RESTORE(UART1_MCR, 8); RESTORE(UART1_SPR, 8); RESTORE(UART1_LCR, 8); -+ -+ REG8(UART2_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ RESTORE(UART2_DLLR, 8); RESTORE(UART2_DLHR, 8); -+ REG8(UART2_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ RESTORE(UART2_IER, 8); -+ RESTORE(UART2_MCR, 8); RESTORE(UART2_SPR, 8); RESTORE(UART2_LCR, 8); -+ -+ REG8(UART3_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -+ RESTORE(UART3_DLLR, 8); RESTORE(UART3_DLHR, 8); -+ REG8(UART3_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -+ RESTORE(UART3_IER, 8); -+ RESTORE(UART3_MCR, 8); RESTORE(UART3_SPR, 8); RESTORE(UART3_LCR, 8); -+ -+ REG_CPM_OCR &= ~CPM_OCR_SUSPEND_PHY0; /* resume USB PHY 0 */ -+ REG_CPM_OCR &= ~CPM_OCR_SUSPEND_PHY1; /* resume USB PHY 1 */ -+#if 0 -+ REG_CPM_OCR &= ~CPM_OCR_EXT_RTC_CLK; /* use internal RTC clock (JZ_EXTAL/128 Hz) */ -+#else -+ REG_CPM_OCR |= CPM_OCR_EXT_RTC_CLK; /* use external RTC clock (32.768 KHz) */ -+#endif -+ -+ /* Enable NAND ctroller */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE; -+ -+ /* Restore current time */ -+ xtime.tv_sec = REG_RTC_RSR; -+ -+ /* Restore interrupts */ -+ REG_INTC_IMSR = imr; -+ REG_INTC_IMCR = ~imr; -+ -+ return 0; -+} -+ -+/* NOTES: -+ * 1: Pins that are floated (NC) should be set as input and pull-enable. -+ * 2: Pins that are pull-up or pull-down by outside should be set as input -+ * and pull-disable. -+ * 3: Pins that are connected to a chipset should be set as pull-disable. -+ */ -+static void jz_board_pm_gpio_setup(void) -+{ -+ /* CIM_D0(IN)/PULL-UP/GP0 */ -+ __gpio_as_input(0); -+ __gpio_enable_pull(0); -+ -+ /* CIM_D1(IN)/PULL-UP/GP1 */ -+ __gpio_as_input(1); -+ __gpio_enable_pull(1); -+ -+ /* CIM_D2(IN)/PULL-UP/GP2 */ -+ __gpio_as_input(2); -+ __gpio_enable_pull(2); -+ -+ /* CIM_D3(IN)/PULL-UP/GP3 */ -+ __gpio_as_input(3); -+ __gpio_enable_pull(3); -+ -+ /* CIM_D4(IN)/PULL-DOWN/GP4 */ -+ __gpio_as_input(4); -+ __gpio_enable_pull(4); -+ -+ /* CIM_D5(IN)/PULL-DOWN/GP5 */ -+ __gpio_as_input(5); -+ __gpio_enable_pull(5); -+ -+ /* CIM_D6(IN)/PULL-DOWN/GP6 */ -+ __gpio_as_input(6); -+ __gpio_enable_pull(6); -+ -+ /* CIM_D7(IN)/PULL-DOWN/GP7 */ -+ __gpio_as_input(7); -+ __gpio_enable_pull(7); -+ -+ /* CIM_VSYNC(IN)/PULL-DOWN/GP8 */ -+ __gpio_as_input(8); -+ __gpio_enable_pull(8); -+ -+ /* CIM_HSYNC(IN)/PULL-UP/GP9 */ -+ __gpio_as_input(9); -+ __gpio_enable_pull(9); -+ -+ /* CIM_PCLK(IN)/PULL-DOWN/GP10 */ -+ __gpio_as_input(10); -+ __gpio_enable_pull(10); -+ -+ /* CIM_MCLK(OUT)/PULL-DOWN/GP11 */ -+ __gpio_as_input(11); -+ __gpio_enable_pull(11); -+ -+ /* DMA_DREQ0(IN)/CHIP_MODE/PULL-UP/GP12 */ -+ __gpio_as_input(12); -+ __gpio_enable_pull(12); -+ -+ /* DMA_DACK0(OUT)/PULL-UP/GP13 */ /* GPIO13 */ -+ __gpio_as_input(13); -+ __gpio_disable_pull(13); -+ -+ /* GP14 */ -+ /* GP15 */ -+ -+ /* RXD3(IN)/PULL-UP/GP16 */ -+ __gpio_as_input(16); -+ __gpio_enable_pull(16); -+ -+ /* CTS3(IN)/PULL-UP/GP17 */ -+ __gpio_as_input(17); -+ __gpio_enable_pull(17); -+ -+ /* GP18 */ -+ /* GP19 */ -+ /* GP20 */ -+ -+ /* TXD3(OUT)/PULL-UP/GP21 */ -+ __gpio_as_input(21); -+ __gpio_enable_pull(21); -+ -+ /* GP22 */ -+ -+ /* RTS3(OUT)/PULL-UP/GP23 */ -+ __gpio_as_input(23); -+ __gpio_enable_pull(23); -+ -+ /* RXD1(IN)/PULL-UP/GP24 */ /* IR_RXD */ -+ __gpio_as_input(24); -+ __gpio_enable_pull(24); -+ -+ /* TXD1(OUT)/PULL-UP/GP25 */ /* IR_TXD */ -+ __gpio_disable_pull(25); -+ __gpio_as_output(25); -+ __cpm_set_pin(25); -+ -+ /* DMA_AEN(OUT)/PULL-UP/GP26 */ /* CIM_PWD_N */ -+ __gpio_as_input(26); -+ __gpio_disable_pull(26); -+ -+ /* DMA_EOP(OUT)/PULL-UP/GP27 */ /* SW4 */ -+ __gpio_as_input(27); -+ __gpio_disable_pull(27); -+ -+ /* USB_CLK(IN)/PULL-UP/GP28 */ -+ __gpio_as_input(28); -+ __gpio_disable_pull(28); -+ -+ /* USB_PPWR0(OUT)/PULL-UP/GP29 */ /* USB_CLK_EN */ -+ __gpio_disable_pull(29); -+ __gpio_as_output(29); -+ __cpm_clear_pin(29); /* disable USB 48MHz clock */ -+ -+ /* GP30 */ -+ /* GP31 */ -+ -+ /* PS2_KCLK(IO)/PULL-UP/GP32 */ -+ __gpio_as_input(32); -+ __gpio_enable_pull(32); -+ -+ /* PS2_KDATA(IO)/PULL-UP/GP33 */ /* CIM_RST */ -+ __gpio_as_input(33); -+ __gpio_enable_pull(33); -+ -+ /* MSC_D0(IO)/PULL-UP/GP34 */ -+ __gpio_as_input(34); -+ __gpio_disable_pull(34); -+ -+ /* MSC_D1(IO)/PULL-UP/GP35 */ -+ __gpio_as_input(35); -+ __gpio_disable_pull(35); -+ -+ /* MSC_D2(IO)/PULL-UP/GP36 */ -+ __gpio_as_input(36); -+ __gpio_disable_pull(36); -+ -+ /* MSC_D3(IO)/PULL-UP/GP37 */ -+ __gpio_as_input(37); -+ __gpio_disable_pull(37); -+ -+ /* MSC_CMD(IO)/PULL-UP/GP38 */ -+ __gpio_as_input(38); -+ __gpio_disable_pull(38); -+ -+ /* MSC_CLK(OUT)/PULL-UP/GP39 */ -+ __gpio_as_input(39); -+ __gpio_enable_pull(39); -+ -+ /* LCD_D0(OUT)/PULL-UP/GP40 */ -+ __gpio_as_input(40); -+ __gpio_enable_pull(40); -+ -+ /* LCD_D1(OUT)/PULL-UP/GP41 */ -+ __gpio_as_input(41); -+ __gpio_enable_pull(41); -+ -+ /* LCD_D2(OUT)/PULL-UP/GP42 */ -+ __gpio_as_input(42); -+ __gpio_enable_pull(42); -+ -+ /* LCD_D3(OUT)/PULL-UP/GP43 */ -+ __gpio_as_input(43); -+ __gpio_enable_pull(43); -+ -+ /* LCD_D4(OUT)/PULL-UP/GP44 */ -+ __gpio_as_input(44); -+ __gpio_enable_pull(44); -+ -+ /* LCD_D5(OUT)/PULL-UP/GP45 */ -+ __gpio_as_input(45); -+ __gpio_enable_pull(45); -+ -+ /* LCD_D6(OUT)/PULL-UP/GP46 */ -+ __gpio_as_input(46); -+ __gpio_enable_pull(46); -+ -+ /* LCD_D7(OUT)/PULL-UP/GP47 */ -+ __gpio_as_input(47); -+ __gpio_enable_pull(47); -+ -+ /* LCD_D8(OUT)/PULL-DOWN/GP48 */ -+ __gpio_as_input(48); -+ __gpio_enable_pull(48); -+ -+ /* LCD_D9(OUT)/PULL-DOWN/GP49 */ -+ __gpio_as_input(49); -+ __gpio_enable_pull(49); -+ -+ /* LCD_D10(OUT)/PULL-DOWN/GP50 */ -+ __gpio_as_input(50); -+ __gpio_enable_pull(50); -+ -+ /* LCD_D11(OUT)/PULL-DOWN/GP51 */ -+ __gpio_as_input(51); -+ __gpio_enable_pull(51); -+ -+ /* LCD_D12(OUT)/PULL-DOWN/GP52 */ -+ __gpio_as_input(52); -+ __gpio_enable_pull(52); -+ -+ /* LCD_D13(OUT)/PULL-DOWN/GP53 */ -+ __gpio_as_input(53); -+ __gpio_enable_pull(53); -+ -+ /* LCD_D14(OUT)/PULL-DOWN/GP54 */ -+ __gpio_as_input(54); -+ __gpio_enable_pull(54); -+ -+ /* LCD_D15(OUT)/PULL-DOWN/GP55 */ -+ __gpio_as_input(55); -+ __gpio_enable_pull(55); -+ -+ /* LCD_VSYNC(IN)/PULL-DOWN/GP56 */ -+ __gpio_as_input(56); -+ __gpio_enable_pull(56); -+ -+ /* LCD_HSYNC(IN)/PULL-UP/GP57 */ -+ __gpio_as_input(57); -+ __gpio_enable_pull(57); -+ -+ /* LCD_PCLK(IN)/PULL-DOWN/GP58 */ -+ __gpio_as_input(58); -+ __gpio_enable_pull(58); -+ -+ /* LCD_DE(OUT)/PULL-DOWN/GP59 */ -+ __gpio_as_input(59); -+ __gpio_enable_pull(59); -+ -+ /* LCD_SPL(OUT)/PULL-UP/GP60 */ -+ __gpio_as_input(60); -+ __gpio_disable_pull(60); -+ -+ /* LCD_CLS(OUT)/PULL-UP/GP61 */ -+ __gpio_as_input(61); -+ __gpio_disable_pull(61); -+ -+ /* LCD_PS(OUT)/PULL-UP/GP62 */ -+ __gpio_as_input(62); -+ __gpio_disable_pull(62); -+ -+ /* LCD_REV(OUT)/PULL-UP/GP63 */ -+ __gpio_as_input(63); -+ __gpio_enable_pull(63); -+ -+ /* SCC0_DAT(IO)/PULL-UP/GP64 */ /* Keypad */ -+ __gpio_as_input(64); -+ __gpio_enable_pull(64); -+ -+ /* SCC1_DAT(IO)/PULL-UP/GP65 */ /* SW5 */ -+ __gpio_as_input(65); -+ __gpio_disable_pull(65); -+ -+ /* SCC0_CLK(OUT)/PULL-UP/GP66 */ /* PW_O */ -+ __gpio_disable_pull(66); -+ __gpio_as_output(66); -+ __cpm_set_pin(66); -+ -+ /* SCC1_CLK(OUT)/PULL-UP/GP67 */ /* SW6 */ -+ __gpio_as_input(67); -+ __gpio_disable_pull(67); -+ -+ /* SYS_CLK(OUT)/PULL-UP/GP68 */ /* I2S_CLK */ -+ __gpio_disable_pull(68); -+ -+ /* ACRESET_N(OUT)/PULL-UP/GP69 */ /* AK4642 PDN */ -+ __gpio_disable_pull(69); -+ __gpio_as_output(69); -+ __cpm_clear_pin(69); -+ -+ /* SDATA_OUT(OUT)/PULL-UP/GP70 */ /* I2S_DIN */ -+ __gpio_disable_pull(70); -+ -+ /* SDATA_IN(IN)/PULL-UP/GP71 */ /* I2S_DOUT */ -+ __gpio_disable_pull(71); -+ -+ /* SSI_CLK(OUT)/PULL-UP/GP72 */ /* SSI_CLK */ -+ __gpio_as_input(72); -+ __gpio_enable_pull(72); -+ -+ /* SSI_CE1_N(OUT)/PULL-UP/GP73 */ /* SSI_CE1_N */ -+ __gpio_as_input(73); -+ __gpio_enable_pull(73); -+ -+ /* SSI_DT(OUT)/PULL-UP/GP74 */ /* SSI_DT */ -+ __gpio_as_input(74); -+ __gpio_enable_pull(74); -+ -+ /* SSI_DR(IN)/PULL-UP/GP75 */ /* SSI_DR */ -+ __gpio_as_input(75); -+ __gpio_enable_pull(75); -+ -+ /* SSI_CE2_N(OUT)/SSI_GPC/PULL-UP/GP76 */ -+ __gpio_as_input(76); -+ __gpio_enable_pull(76); -+ -+ /* BITCLK_IN(IN)/PULL-UP/GP77 */ /* I2S_BITCLK */ -+ __gpio_disable_pull(77); -+ -+ /* SYNC_IN(IN)/PULL-UP/GP78 */ /* I2S_LRCIN */ -+ __gpio_disable_pull(78); -+ -+ /* FRE_N(OUT)/PULL-UP/GP79 */ -+ __gpio_enable_pull(79); -+ __gpio_as_input(79); -+ -+ /* FWE_N(OUT)/PULL-UP/GP80 */ -+ __gpio_enable_pull(80); -+ __gpio_as_input(80); -+ -+ /* FRB_N(IN)/PULL-UP/GP81 */ -+ __gpio_enable_pull(81); -+ __gpio_as_input(81); -+ -+ /* DCS1_N(OUT)/PULL-UP/GP82 */ /* SD_WP */ -+ __gpio_as_input(82); -+ __gpio_enable_pull(82); -+ -+ /* CS1_N(OUT)/PULL-UP/GP83 */ /* JACK_PLUG */ -+ __gpio_as_input(83); -+ __gpio_disable_pull(83); -+ -+ /* CS2_N(OUT)/PULL-UP/GP84 */ /* DC_DETE */ -+ __gpio_as_input(84); -+ __gpio_disable_pull(84); -+ -+ /* CS3_N(OUT)/PULL-UP/GP85 */ /* NAND CS# */ -+ __gpio_enable_pull(85); -+ __gpio_as_input(85); -+ -+ /* CS4_N/(OUT)PULL-UP/GP86 */ /* PULL_OFF */ -+ __gpio_disable_pull(86); -+ __gpio_as_output(86); -+// __cpm_set_pin(86); -+ __cpm_clear_pin(86); -+ -+ /* CS5_N(OUT)/PULL-UP/GP87 */ /* IR_SD */ -+ __gpio_as_input(87); -+ __gpio_disable_pull(87); -+ -+ /* INPACK_N(IN)/PULL-UP/GP88 */ /* SW7 */ -+ __gpio_as_input(88); -+ __gpio_disable_pull(88); -+ -+ /* BVD2(IN)/PULL-UP/GP89 */ /* SW8 */ -+ __gpio_as_input(89); -+ __gpio_disable_pull(89); -+ -+ /* PCE1_N(OUT)/PULL-UP/GP90 */ /* SD_CD_N */ -+ __gpio_as_input(90); -+ __gpio_enable_pull(90); -+ -+ /* PSKTSEL_N(OUT)/PULL-UP/GP91 */ /* SD_VCC_3V_EN_N */ -+ __gpio_disable_pull(91); -+ __gpio_as_output(91); -+ __cpm_clear_pin(91); -+ -+ /* IOIS16_N(IN)/PULL-UP/GP92 */ /* LED_EN */ -+ __gpio_disable_pull(92); -+ __gpio_as_output(92); -+ __cpm_clear_pin(92); -+ -+ /* PCE2_N(OUT)/PULL-UP/GP93 */ /* LCD_DISP_OFF_N */ -+ __gpio_disable_pull(93); -+ __gpio_as_input(93); -+ -+ /* PWM0(OUT)/PULL-UP/GP94 */ /* LCD backlight off */ -+ __gpio_disable_pull(94); -+ __gpio_as_output(94); -+ __cpm_clear_pin(94); -+ -+ /* PWM1(OUT)/PULL-UP/GP95 */ -+ __gpio_disable_pull(95); -+ __gpio_as_output(95); -+ __cpm_clear_pin(95); -+ -+ /* PRT(OUT)/PULL-UP/GP96 */ /* RTC_IRQ */ -+ __gpio_as_input(96); -+ __gpio_disable_pull(96); -+ -+ /* PRT(OUT)/PULL-UP/GP97 */ /* PW_I */ -+ __gpio_as_input(97); -+ __gpio_disable_pull(97); -+ -+ /* PRT(OUT)/PULL-UP/GP98 */ /* Keypad */ -+ __gpio_as_input(98); -+ __gpio_disable_pull(98); -+ -+ /* PRT(OUT)/PULL-UP/GP99 */ /* Keypad */ -+ __gpio_as_input(99); -+ __gpio_disable_pull(99); -+ -+ /* PRT(OUT)/PULL-UP/GP100 */ /* Keypad */ -+ __gpio_as_input(100); -+ __gpio_disable_pull(100); -+ -+ /* PRT(OUT)/PULL-UP/GP101 */ /* Keypad */ -+ __gpio_as_input(101); -+ __gpio_disable_pull(101); -+ -+ /* PRT(OUT)/PULL-UP/GP102 */ /* Keypad */ -+ __gpio_as_input(102); -+ __gpio_disable_pull(102); -+ -+ /* PRT(OUT)/PULL-UP/GP103 */ /* Keypad */ -+ __gpio_as_input(103); -+ __gpio_enable_pull(103); -+ -+ /* PRT(OUT)/PULL-UP/GP104 */ /* Keypad */ -+ __gpio_as_input(104); -+ __gpio_enable_pull(104); -+ -+ /* PRT(OUT)/PULL-UP/GP105 */ /* Keypad */ -+ __gpio_as_input(105); -+ __gpio_enable_pull(105); -+ -+ /* PRT(OUT)/PULL-UP/GP106 */ /* 5V_ON */ -+ __gpio_disable_pull(106); -+ __gpio_as_output(106); -+ __cpm_clear_pin(106); -+ -+ /* PRT(IN)/PULL-UP/GP107 */ /* GSM_BOOT */ -+ __gpio_as_input(107); -+ __gpio_enable_pull(107); -+ -+ /* PRT(IN)/PULL-UP/GP108 */ /* GSM_RESET */ -+ __gpio_as_input(108); -+ __gpio_enable_pull(108); -+ -+ /* PRT(IN)/PULL-UP/GP109 */ /* GSM_EN */ -+ __gpio_as_input(109); -+ __gpio_enable_pull(109); -+ -+ /* PRT(IN)/PULL-UP/GP110 */ /* GSM_RING */ -+ __gpio_as_input(110); -+ __gpio_enable_pull(110); -+ -+ /* PRT(IN)/UART2_RXD/PULL-UP/GP111 */ /* Keypad */ -+ __gpio_as_input(111); -+ __gpio_enable_pull(111); -+ -+ /* MII_TX_EN(OUT)/PULL-UP/GP112 */ -+ __gpio_as_input(112); -+ __gpio_enable_pull(112); -+ -+ /* MII_RX_DV(IN)/PULL-UP/GP113 */ -+ __gpio_as_input(113); -+ __gpio_enable_pull(113); -+ -+ /* MII_RX_ER(IN)/PULL-UP/GP114 */ -+ __gpio_as_input(114); -+ __gpio_enable_pull(114); -+ -+ /* MII_COL(IN)/PULL-UP/GP115 */ -+ __gpio_as_input(115); -+ __gpio_enable_pull(115); -+ -+ /* MII_CRS(IN)/PULL-UP/GP116 */ -+ __gpio_as_input(116); -+ __gpio_enable_pull(116); -+ -+ /* MII_TXD0(OUT)/PULL-UP/GP117 */ -+ __gpio_as_input(117); -+ __gpio_enable_pull(117); -+ -+ /* MII_TXD1(OUT)/PULL-UP/GP118 */ -+ __gpio_as_input(118); -+ __gpio_enable_pull(118); -+ -+ /* MII_TXD2(OUT)/PULL-UP/GP119 */ -+ __gpio_as_input(119); -+ __gpio_enable_pull(119); -+ -+ /* MII_TXD3(OUT)/PULL-UP/GP120 */ -+ __gpio_as_input(120); -+ __gpio_enable_pull(120); -+ -+ /* MII_RXD0(IN)/PULL-UP/GP121 */ -+ __gpio_as_input(121); -+ __gpio_enable_pull(121); -+ -+ /* MII_RXD1(IN)/PULL-UP/GP122 */ -+ __gpio_as_input(122); -+ __gpio_enable_pull(122); -+ -+ /* MII_RXD2(IN)/PULL-UP/GP123 */ -+ __gpio_as_input(123); -+ __gpio_enable_pull(123); -+ -+ /* MII_RXD3(IN)/PULL-UP/GP124 */ -+ __gpio_as_input(124); -+ __gpio_enable_pull(124); -+ -+ /* UART2_TXD(OUT)/PULL-UP/GP125 */ /* CHARG_STAT */ -+ __gpio_as_output(125); -+ __gpio_disable_pull(125); -+ __cpm_clear_pin(125); -+ -+ /* UART0_RXD(IN)/PULL-UP/GP126 */ -+ __gpio_as_input(126); -+ __gpio_enable_pull(126); -+ -+ /* UART0_TXD(OUT)/PULL-UP/GP127 */ -+ __gpio_as_input(127); -+ __gpio_enable_pull(127); -+} -+ -+/* -+ * In order to save power most, all gpio pins should be put to their -+ * proper states during low power mode. -+ */ -+static void jz_board_pm_suspend(void) -+{ -+ /* Setup the state of all the GPIO pins during low-power mode */ -+ jz_board_pm_gpio_setup(); -+ -+ /* Allow next interrupts to wakeup the system. -+ */ -+ REG_CPM_WER = 0; /* Clear all first */ -+ -+ /* RTC alarm */ -+ REG_CPM_WER |= 1 << 0; -+ REG_CPM_WRER |= 1 << 0; -+ REG_CPM_WFER |= 1 << 0; -+ __gpio_as_irq_rise_edge(96); -+ -+ /* Power_I key */ -+ REG_CPM_WER |= 1 << 1; -+ REG_CPM_WRER |= 1 << 1; -+ REG_CPM_WFER |= 1 << 1; -+ __gpio_as_irq_rise_edge(97); -+ -+ /* enable INTC irq */ -+ __intc_unmask_irq(IRQ_GPIO3); -+ -+#if 0 -+ /* Enable RTC alarm */ -+ REG_CPM_WER |= CPM_WER_WERTC; -+ REG_RTC_RGR = 32767; -+ REG_RTC_RCR &= ~RTC_RCR_AE; -+ REG_RTC_RSR = 0; -+ REG_RTC_RSAR = 30; -+ REG_RTC_RCR = RTC_RCR_AE | RTC_RCR_AIE | RTC_RCR_START; -+#endif -+} -+ -+/* -+ * We don't use sleep mode of jz4730 for it has bug, the suspend mode -+ * implemented by hibernate mode is used instead of it. -+ */ -+static int jz_pm_do_sleep(void) -+{ -+ printk("It was deprecated, please use /proc/sys/pm/suspend.\n"); -+#if 0 -+ unsigned long imr = REG_INTC_IMR; -+ -+ /* Preserve current time */ -+ REG_RTC_RSR = xtime.tv_sec; -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* Just allow next interrupts to wakeup the system. -+ * Note: modify this according to your system. -+ */ -+ /* RTC alarm */ -+ __gpio_as_irq_fall_edge(96); /* GPIO 96 */ -+ -+ /* POWER_I key */ -+ __gpio_as_irq_rise_edge(97); /* GPIO 97 */ -+ -+ /* Enable INTC */ -+ __intc_unmask_irq(IRQ_GPIO3); -+ -+ /* Disable modules e.g. LCD backlight */ -+ -+ /* Stop module clocks */ -+ __cpm_stop_uhc(); -+ -+ /* Enter SLEEP mode -+ * Put SDRAM into self-refresh mode. -+ */ -+ REG_CPM_LPCR &= ~CPM_LPCR_LPM_MASK; -+ REG_CPM_LPCR |= CPM_LPCR_LPM_SLEEP; -+ -+ __asm__(".set\tmips3\n\t" -+ ".set noreorder\n\t" -+ ".align 5\n\t" -+ "wait\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ ".set\tmips0"); -+ -+ /* Restore to IDLE mode */ -+ REG_CPM_LPCR &= ~CPM_LPCR_LPM_MASK; -+ REG_CPM_LPCR |= CPM_LPCR_LPM_IDLE; -+ -+ /* Restore clock of usb host */ -+ __cpm_start_uhc(); -+ -+ /* Restore interrupts */ -+ REG_INTC_IMSR = imr; -+ REG_INTC_IMCR = ~imr; -+ -+ /* Restore current time */ -+ xtime.tv_sec = REG_RTC_RSR; -+#endif -+ return 0; -+} -+ -+#define K0BASE KSEG0 -+void jz_flush_cache_all(void) -+{ -+ unsigned long addr; -+ -+ /* Clear CP0 TagLo */ -+ asm volatile ("mtc0 $0, $28\n\t"::); -+ -+ for (addr = K0BASE; addr < (K0BASE + 0x4000); addr += 32) { -+ asm volatile ( -+ ".set mips3\n\t" -+ " cache %0, 0(%1)\n\t" -+ ".set mips2\n\t" -+ : -+ : "I" (Index_Writeback_Inv_D), "r"(addr)); -+ -+ asm volatile ( -+ ".set mips3\n\t" -+ " cache %0, 0(%1)\n\t" -+ ".set mips2\n\t" -+ : -+ : "I" (Index_Store_Tag_I), "r"(addr)); -+ } -+ -+ asm volatile ("sync\n\t"::); -+ -+ /* invalidate BTB */ -+ 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" -+ ".set mips2\n\t" -+ : -+ : "r"(addr)); -+} -+ -+/* Put CPU to HIBERNATE mode */ -+int jz_pm_suspend(void) -+{ -+ int retval; -+ -+ pm_send_all(PM_SUSPEND, (void *)3); -+ -+ retval = jz_pm_do_suspend(); -+ -+ pm_send_all(PM_RESUME, (void *)0); -+ -+ return retval; -+} -+ -+#if 0 -+/* Put CPU to SLEEP mode */ -+int jz_pm_sleep(void) -+{ -+ return jz_pm_do_sleep(); -+} -+ -+/* Put CPU to IDLE mode, used for dpm in linux 2.4 */ -+void jz_pm_idle(void) -+{ -+ local_irq_disable(); -+ if (!need_resched()) { -+ local_irq_enable(); -+ cpu_wait(); -+ } -+} -+#endif -+ -+#ifdef CONFIG_SYSCTL -+ -+/* -+ * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6 -+ * when all the PM interfaces exist nicely. -+ */ -+#define CTL_PM_SUSPEND 1 -+#define CTL_PM_HIBERNATE 2 -+ -+/*---------------------------------------------------------------------------- -+ * Power Management sleep sysctl proc interface -+ * -+ * A write to /proc/sys/pm/suspend invokes this function -+ * which initiates a sleep. -+ *--------------------------------------------------------------------------*/ -+static int sysctl_jz_pm_sleep(void) -+{ -+ return jz_pm_suspend(); -+} -+ -+static struct ctl_table pm_table[] = -+{ -+ { -+ .ctl_name = CTL_UNNUMBERED, -+ .procname = "suspend", -+ .data = NULL, -+ .maxlen = 0, -+ .mode = 0600, -+ .proc_handler = &sysctl_jz_pm_sleep, -+ }, -+ { .ctl_name = 0} -+}; -+ -+static struct ctl_table pm_dir_table[] = -+{ -+ { -+ .ctl_name = CTL_UNNUMBERED, -+ .procname = "pm", -+ .mode = 0555, -+ .child = pm_table, -+ }, -+ { .ctl_name = 0} -+}; -+ -+#endif /* CONFIG_SYSCTL */ -+ -+/* -+ * Initialize power interface -+ */ -+static int __init jz_pm_init(void) -+{ -+ printk("Power Management for JZ\n"); -+ -+#ifdef CONFIG_SYSCTL -+ register_sysctl_table(pm_dir_table); -+#endif -+ -+ return 0; -+} -+ -+module_init(jz_pm_init); -diff --git a/arch/mips/jz4730/proc.c b/arch/mips/jz4730/proc.c -new file mode 100644 -index 0000000..49585bc ---- /dev/null -+++ b/arch/mips/jz4730/proc.c -@@ -0,0 +1,292 @@ -+/* -+ * linux/arch/mips/jz4730/proc.c -+ * -+ * /proc/jz/ procfs for on-chip peripherals. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+struct proc_dir_entry *proc_jz_root; -+ -+/* -+ * EMC Module -+ */ -+static int emc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+ len += sprintf (page+len, "BCR: 0x%08x\n", REG_EMC_BCR); -+ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4, REG_EMC_SMCR5); -+ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4, REG_EMC_SACR5); -+ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -+ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -+ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -+ len += sprintf (page+len, "DMAR(0-1): 0x%08x 0x%08x\n", REG_EMC_DMAR1, REG_EMC_DMAR2); -+ return len; -+} -+ -+/* -+ * Power Manager Module -+ */ -+static int pmc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned long lpcr = REG_CPM_LPCR; -+ unsigned long mscr = REG_CPM_MSCR; -+ -+ len += sprintf (page+len, "LPCR : 0x%08lx\n", lpcr); -+ len += sprintf (page+len, "Low Power Mode : %s\n", -+ ((lpcr & CPM_LPCR_LPM_MASK) == (CPM_LPCR_LPM_IDLE)) ? -+ "idle" : (((lpcr & CPM_LPCR_LPM_MASK) == (CPM_LPCR_LPM_SLEEP)) ? "sleep" : "hibernate")); -+ len += sprintf (page+len, "Doze Mode : %s\n", -+ (lpcr & CPM_LPCR_DOZE) ? "on" : "off"); -+ if (lpcr & CPM_LPCR_DOZE) -+ len += sprintf (page+len, " duty : %d\n", (int)((lpcr & CPM_LPCR_DUTY_MASK) >> CPM_LPCR_DUTY_BIT)); -+ len += sprintf (page+len, "CKO1 : %s\n", -+ (REG_CPM_CFCR & CPM_CFCR_CKOEN1) ? "enable" : "disable"); -+ len += sprintf (page+len, "UART0 : %s\n", -+ (mscr & CPM_MSCR_MSTP_UART0) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART1 : %s\n", -+ (mscr & CPM_MSCR_MSTP_UART1) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART2 : %s\n", -+ (mscr & CPM_MSCR_MSTP_UART2) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART3 : %s\n", -+ (mscr & CPM_MSCR_MSTP_UART3) ? "stopped" : "running"); -+ len += sprintf (page+len, "OST : %s\n", -+ (mscr & CPM_MSCR_MSTP_OST) ? "stopped" : "running"); -+ len += sprintf (page+len, "DMAC : %s\n", -+ (mscr & CPM_MSCR_MSTP_DMAC) ? "stopped" : "running"); -+ len += sprintf (page+len, "ETH : %s\n", -+ (mscr & CPM_MSCR_MSTP_ETH) ? "stopped" : "running"); -+ len += sprintf (page+len, "UHC/UDC : %s\n", -+ (mscr & CPM_MSCR_MSTP_UHC) ? "stopped" : "running"); -+ len += sprintf (page+len, "PWM0 : %s\n", -+ (mscr & CPM_MSCR_MSTP_PWM0) ? "stopped" : "running"); -+ len += sprintf (page+len, "PWM1 : %s\n", -+ (mscr & CPM_MSCR_MSTP_PWM1) ? "stopped" : "running"); -+ len += sprintf (page+len, "I2C : %s\n", -+ (mscr & CPM_MSCR_MSTP_I2C) ? "stopped" : "running"); -+ len += sprintf (page+len, "SSI : %s\n", -+ (mscr & CPM_MSCR_MSTP_SSI) ? "stopped" : "running"); -+ len += sprintf (page+len, "SCC : %s\n", -+ (mscr & CPM_MSCR_MSTP_SCC) ? "stopped" : "running"); -+ return len; -+} -+ -+static int pmc_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_MSCR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+/* -+ * Clock Generation Module -+ */ -+static int cgm_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int cfcr = REG_CPM_CFCR; -+ unsigned int plcr1 = REG_CPM_PLCR1; -+ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int od[4] = {1, 2, 2, 4}; -+ -+ -+ len += sprintf (page+len, "PLCR1 : 0x%08x\n", plcr1); -+ len += sprintf (page+len, "CFCR : 0x%08x\n", cfcr); -+ len += sprintf (page+len, "PLL : %s\n", -+ (plcr1 & CPM_PLCR1_PLL1EN) ? "ON" : "OFF"); -+ len += sprintf (page+len, "NF:NR:NO : %d:%d:%d\n", -+ __cpm_plcr1_fd() + 2, -+ __cpm_plcr1_rd() + 2, -+ od[__cpm_plcr1_od()] -+ ); -+ len += sprintf (page+len, "I:S:M:P : %d:%d:%d:%d\n", -+ div[(cfcr & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT], -+ div[(cfcr & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT], -+ div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT], -+ div[(cfcr & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT] -+ ); -+ len += sprintf (page+len, "PLL Freq : %d MHz\n", __cpm_get_pllout()/1000000); -+ len += sprintf (page+len, "ICLK : %d MHz\n", __cpm_get_iclk()/1000000); -+ len += sprintf (page+len, "SCLK : %d MHz\n", __cpm_get_sclk()/1000000); -+ len += sprintf (page+len, "MCLK : %d MHz\n", __cpm_get_mclk()/1000000); -+ len += sprintf (page+len, "PCLK : %d MHz\n", __cpm_get_pclk()/1000000); -+ len += sprintf (page+len, "DEVCLK : %d MHz\n", __cpm_get_devclk()/1000000); -+ len += sprintf (page+len, "RTCCLK : %d KHz\n", __cpm_get_rtcclk()/1000); -+ len += sprintf (page+len, "USBCLK : %d MHz\n", __cpm_get_usbclk()/1000000); -+#if defined(CONFIG_FB_JZ) -+ len += sprintf (page+len, "LCDCLK : %d MHz\n", __cpm_get_lcdclk()/1000000); -+ len += sprintf (page+len, "PIXCLK : %d MHz\n", __cpm_get_pixclk()/1000000); -+#endif -+ return len; -+} -+ -+static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CFCR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+/* -+ * WDT -+ */ -+static int wdt_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+ len += sprintf (page+len, "WDT_WTCSR : 0x%08x\n", REG_WDT_WTCSR); -+ len += sprintf (page+len, "WDT_WTCNT : 0x%08x\n", REG_WDT_WTCNT); -+ -+ return len; -+} -+ -+static int wdt_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned long cnt = simple_strtoul(buffer, 0, 16); -+ -+ REG_WDT_WTCNT = cnt; -+ REG_WDT_WTCSR = WDT_WTCSR_START; -+ -+ return count; -+} -+ -+/* -+ * PWM -+ */ -+ -+static int proc_jz_pwm_read_byte(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ return sprintf (page, "0x%02x\n", REG8(data)); -+} -+ -+static int proc_jz_pwm_read_word(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ return sprintf (page, "0x%04x\n", REG16(data)); -+} -+ -+static int proc_jz_pwm_write_byte(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG8(data) = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+static int proc_jz_pwm_write_word(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG16(data) = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+#define PWM_NUM 2 -+ -+static int jz_pwm_proc_init(void) -+{ -+ struct proc_dir_entry *proc_jz_pwm, *res; -+ char name[16]; -+ unsigned char i; -+ -+ for (i = 0; i < PWM_NUM; i++) { -+ sprintf(name, "pwm%d", i); -+ proc_jz_pwm = proc_mkdir(name, proc_jz_root); -+ res = create_proc_entry("control", 0600, proc_jz_pwm); -+ if ( res) { -+ res->read_proc = proc_jz_pwm_read_byte; -+ res->write_proc = proc_jz_pwm_write_byte; -+ if (i) -+ res->data = (void * )PWM_CTR(1); -+ else -+ res->data = (void * )PWM_CTR(0); -+ } -+ res = create_proc_entry("period", 0600, proc_jz_pwm); -+ if ( res) { -+ res->read_proc = proc_jz_pwm_read_word; -+ res->write_proc = proc_jz_pwm_write_word; -+ if (i) -+ res->data = (void *)PWM_PER(1); -+ else -+ res->data = (void *)PWM_PER(0); -+ } -+ res = create_proc_entry("duty", 0600, proc_jz_pwm); -+ if ( res) { -+ res->read_proc = proc_jz_pwm_read_word; -+ res->write_proc = proc_jz_pwm_write_word; -+ if (i) -+ res->data = (void * )PWM_DUT(1); -+ else -+ res->data = (void * )PWM_DUT(0); -+ } -+ } -+ return 0; -+} -+ -+/* -+ * /proc/jz/xxx entry -+ * -+ */ -+static int __init jz_proc_init(void) -+{ -+ struct proc_dir_entry *entry; -+ -+ /* create /proc/jz */ -+ proc_jz_root = proc_mkdir("jz", 0); -+ -+ /* create /proc/jz/emc */ -+ entry = create_proc_entry("emc", 0644, proc_jz_root); -+ if (entry) { -+ entry->read_proc = emc_read_proc; -+ entry->write_proc = NULL; -+ entry->data = NULL; -+ } -+ -+ /* create /proc/jz/pmc */ -+ entry = create_proc_entry("pmc", 0644, proc_jz_root); -+ if (entry) { -+ entry->read_proc = pmc_read_proc; -+ entry->write_proc = pmc_write_proc; -+ entry->data = NULL; -+ } -+ -+ /* create /proc/jz/cgm */ -+ entry = create_proc_entry("cgm", 0644, proc_jz_root); -+ if (entry) { -+ entry->read_proc = cgm_read_proc; -+ entry->write_proc = cgm_write_proc; -+ entry->data = NULL; -+ } -+ -+ /* create /proc/jz/wdt */ -+ entry = create_proc_entry("wdt", 0644, proc_jz_root); -+ if (entry) { -+ entry->read_proc = wdt_read_proc; -+ entry->write_proc = wdt_write_proc; -+ entry->data = NULL; -+ } -+ -+ /* PWM */ -+ jz_pwm_proc_init(); -+ -+ return 0; -+} -+ -+__initcall(jz_proc_init); -diff --git a/arch/mips/jz4730/prom.c b/arch/mips/jz4730/prom.c -new file mode 100644 -index 0000000..5a5f6b8 ---- /dev/null -+++ b/arch/mips/jz4730/prom.c -@@ -0,0 +1,198 @@ -+/* -+ * -+ * BRIEF MODULE DESCRIPTION -+ * PROM library initialisation code, supports YAMON and U-Boot. -+ * -+ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * ppopov@mvista.com or source@mvista.com -+ * -+ * This file was derived from Carsten Langgaard's -+ * arch/mips/mips-boards/xx files. -+ * -+ * Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* #define DEBUG_CMDLINE */ -+ -+int prom_argc; -+char **prom_argv, **prom_envp; -+ -+char * prom_getcmdline(void) -+{ -+ return &(arcs_cmdline[0]); -+} -+ -+void prom_init_cmdline(void) -+{ -+ char *cp; -+ int actr; -+ -+ actr = 1; /* Always ignore argv[0] */ -+ -+ cp = &(arcs_cmdline[0]); -+ while(actr < prom_argc) { -+ strcpy(cp, prom_argv[actr]); -+ cp += strlen(prom_argv[actr]); -+ *cp++ = ' '; -+ actr++; -+ } -+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -+ --cp; -+ if (prom_argc > 1) -+ *cp = '\0'; -+ -+} -+ -+ -+char *prom_getenv(char *envname) -+{ -+#if 0 -+ /* -+ * Return a pointer to the given environment variable. -+ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -+ */ -+ -+ char **env = prom_envp; -+ int i = strlen(envname); -+ int yamon = (*env && strchr(*env, '=') == NULL); -+ -+ while (*env) { -+ if (yamon) { -+ if (strcmp(envname, *env++) == 0) -+ return *env; -+ } else { -+ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -+ return *env + i + 1; -+ } -+ env++; -+ } -+#endif -+ return NULL; -+} -+ -+inline unsigned char str2hexnum(unsigned char c) -+{ -+ if(c >= '0' && c <= '9') -+ return c - '0'; -+ if(c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ if(c >= 'A' && c <= 'F') -+ return c - 'A' + 10; -+ return 0; /* foo */ -+} -+ -+inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; -+ -+ for(i = 0; i < 6; i++) { -+ unsigned char num; -+ -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} -+ -+int get_ethernet_addr(char *ethernet_addr) -+{ -+ char *ethaddr_str; -+ -+ ethaddr_str = prom_getenv("ethaddr"); -+ if (!ethaddr_str) { -+ printk("ethaddr not set in boot prom\n"); -+ return -1; -+ } -+ str2eaddr(ethernet_addr, ethaddr_str); -+ -+#if 0 -+ { -+ int i; -+ -+ printk("get_ethernet_addr: "); -+ for (i=0; i<5; i++) -+ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -+ printk("%02x\n", *(ethernet_addr+i)); -+ } -+#endif -+ -+ return 0; -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init prom_init(void) -+{ -+ unsigned char *memsize_str; -+ unsigned long memsize; -+ -+ prom_argc = (int) fw_arg0; -+ prom_argv = (char **) fw_arg1; -+ prom_envp = (char **) fw_arg2; -+ -+ mips_machtype = MACH_INGENIC_JZ4730; -+ -+ prom_init_cmdline(); -+ memsize_str = prom_getenv("memsize"); -+ if (!memsize_str) { -+ memsize = 0x04000000; -+ } else { -+ memsize = simple_strtol(memsize_str, NULL, 0); -+ } -+ add_memory_region(0, memsize, BOOT_MEM_RAM); -+} -+ -+/* used by early printk */ -+void prom_putchar(char c) -+{ -+ volatile u8 *uart_lsr = (volatile u8 *)(UART3_BASE + OFF_LSR); -+ volatile u8 *uart_tdr = (volatile u8 *)(UART3_BASE + OFF_TDR); -+ -+ /* Wait for fifo to shift out some bytes */ -+ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -+ -+ *uart_tdr = (u8)c; -+} -+ -+const char *get_system_type(void) -+{ -+ return "JZ4730"; -+} -+ -+EXPORT_SYMBOL(prom_getcmdline); -+EXPORT_SYMBOL(get_ethernet_addr); -+EXPORT_SYMBOL(str2eaddr); -diff --git a/arch/mips/jz4730/reset.c b/arch/mips/jz4730/reset.c -new file mode 100644 -index 0000000..4c9e20c ---- /dev/null -+++ b/arch/mips/jz4730/reset.c -@@ -0,0 +1,40 @@ -+/* -+ * linux/arch/mips/jz4730/reset.c -+ * -+ * JZ4730 reset routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+void jz_restart(char *command) -+{ -+ __wdt_set_count(0xffffffff-32); /* reset after 1/1024 s */ -+ __wdt_start(); -+ while (1); -+} -+ -+void jz_halt(void) -+{ -+ __wdt_set_count(0xffffffff-32); /* reset after 1/1024 s */ -+ __wdt_start(); -+ while (1); -+} -+ -+void jz_power_off(void) -+{ -+ jz_halt(); -+} -diff --git a/arch/mips/jz4730/setup.c b/arch/mips/jz4730/setup.c -new file mode 100644 -index 0000000..4594b56 ---- /dev/null -+++ b/arch/mips/jz4730/setup.c -@@ -0,0 +1,182 @@ -+/* -+ * linux/arch/mips/jz4730/setup.c -+ * -+ * JZ4730 CPU common setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_PC_KEYB -+#include -+#endif -+ -+jz_clocks_t jz_clocks; -+ -+extern char * __init prom_getcmdline(void); -+extern void __init jz_board_setup(void); -+extern void jz_restart(char *); -+extern void jz_halt(void); -+extern void jz_power_off(void); -+extern void jz_time_init(void); -+ -+static void __init sysclocks_setup(void) -+{ -+#ifndef CONFIG_JZ4730_URANUS -+ jz_clocks.iclk = __cpm_get_iclk(); -+ jz_clocks.sclk = __cpm_get_sclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.devclk = __cpm_get_devclk(); -+ jz_clocks.rtcclk = __cpm_get_rtcclk(); -+ jz_clocks.uartclk = __cpm_get_uartclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(); -+#else /* URANUS FPGA */ -+ -+#define FPGACLK 8000000 -+ -+ jz_clocks.iclk = FPGACLK; -+ jz_clocks.sclk = FPGACLK; -+ jz_clocks.mclk = FPGACLK; -+ jz_clocks.devclk = FPGACLK; -+ jz_clocks.rtcclk = FPGACLK; -+ jz_clocks.uartclk = FPGACLK; -+ jz_clocks.pixclk = FPGACLK; -+ jz_clocks.lcdclk = FPGACLK; -+ jz_clocks.usbclk = FPGACLK; -+ jz_clocks.i2sclk = FPGACLK; -+ jz_clocks.mscclk = FPGACLK; -+#endif -+ -+ printk("CPU clock: %dMHz, System clock: %dMHz, Memory clock: %dMHz, Peripheral clock: %dMHz\n", -+ (jz_clocks.iclk + 500000) / 1000000, -+ (jz_clocks.sclk + 500000) / 1000000, -+ (jz_clocks.mclk + 500000) / 1000000, -+ (jz_clocks.pclk + 500000) / 1000000); -+} -+ -+static void __init soc_cpm_setup(void) -+{ -+ __cpm_idle_mode(); -+ __cpm_enable_cko1(); -+ __cpm_start_all(); -+ -+ /* get system clocks */ -+ sysclocks_setup(); -+} -+ -+static void __init soc_harb_setup(void) -+{ -+// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -+ __harb_set_priority(0x08); /* DMAC>LCD>CIM>ETH>USB>CIM */ -+// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -+} -+ -+static void __init soc_emc_setup(void) -+{ -+} -+ -+static void __init soc_dmac_setup(void) -+{ -+ __dmac_enable_all_channels(); -+} -+ -+static void __init jz_soc_setup(void) -+{ -+ soc_cpm_setup(); -+ soc_harb_setup(); -+ soc_emc_setup(); -+ soc_dmac_setup(); -+} -+ -+static void __init jz_serial_setup(void) -+{ -+#ifdef CONFIG_SERIAL_8250 -+ struct uart_port s; -+ -+ memset(&s, 0, sizeof(s)); -+ -+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -+ s.iotype = UPIO_MEM; -+ s.regshift = 2; -+ s.uartclk = jz_clocks.uartclk; -+ -+ s.line = 0; -+ s.membase = (u8 *)UART0_BASE; -+ s.irq = IRQ_UART0; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -+ } -+ -+ s.line = 1; -+ s.membase = (u8 *)UART1_BASE; -+ s.irq = IRQ_UART1; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -+ } -+ -+ s.line = 2; -+ s.membase = (u8 *)UART2_BASE; -+ s.irq = IRQ_UART2; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS2 setup failed!\n"); -+ } -+ -+ s.line = 3; -+ s.membase = (u8 *)UART3_BASE; -+ s.irq = IRQ_UART3; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS3 setup failed!\n"); -+ } -+#endif -+} -+ -+void __init plat_mem_setup(void) -+{ -+ char *argptr; -+ -+ argptr = prom_getcmdline(); -+ -+ /* IO/MEM resources. */ -+ set_io_port_base(0); -+ ioport_resource.start = 0x00000000; -+ ioport_resource.end = 0xffffffff; -+ iomem_resource.start = 0x00000000; -+ iomem_resource.end = 0xffffffff; -+ -+ _machine_restart = jz_restart; -+ _machine_halt = jz_halt; -+ pm_power_off = jz_power_off; -+ -+ jz_soc_setup(); /* soc specific setup */ -+ jz_serial_setup(); /* serial port setup */ -+ jz_board_setup(); /* board specific setup */ -+} -diff --git a/arch/mips/jz4730/sleep.S b/arch/mips/jz4730/sleep.S -new file mode 100644 -index 0000000..9ee9e70 ---- /dev/null -+++ b/arch/mips/jz4730/sleep.S -@@ -0,0 +1,307 @@ -+/* -+ * linux/arch/mips/jz4730/sleep.S -+ * -+ * jz4730 Assembler Sleep/WakeUp Management Routines -+ * -+ * Copyright (C) 2005 Ingenic Semiconductor -+ * Author: -+ * -+ * 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 -+#include -+#include -+ -+ .text -+ .set noreorder -+ .set noat -+ -+ .extern jz_flush_cache_all -+ -+/* -+ * jz_cpu_suspend() -+ * -+ * Forces CPU into hibernate mode -+ */ -+ -+ .globl jz_cpu_suspend -+jz_cpu_suspend: -+ -+ /* save hi, lo and general registers except k0($26) and k1($27) (total 32) */ -+ move k0, sp -+ addiu k0, k0, -(32*4) -+ mfhi k1 -+ sw $0, 0(k0) -+ sw $1, 4(k0) -+ sw k1, 120(k0) /* hi */ -+ mflo k1 -+ sw $2, 8(k0) -+ sw $3, 12(k0) -+ sw k1, 124(k0) /* lo */ -+ sw $4, 16(k0) -+ sw $5, 20(k0) -+ sw $6, 24(k0) -+ sw $7, 28(k0) -+ sw $8, 32(k0) -+ sw $9, 36(k0) -+ sw $10, 40(k0) -+ sw $11, 44(k0) -+ sw $12, 48(k0) -+ sw $13, 52(k0) -+ sw $14, 56(k0) -+ sw $15, 60(k0) -+ sw $16, 64(k0) -+ sw $17, 68(k0) -+ sw $18, 72(k0) -+ sw $19, 76(k0) -+ sw $20, 80(k0) -+ sw $21, 84(k0) -+ sw $22, 88(k0) -+ sw $23, 92(k0) -+ sw $24, 96(k0) -+ sw $25, 100(k0) -+ sw $28, 104(k0) -+ sw $29, 108(k0) /* saved sp */ -+ sw $30, 112(k0) -+ sw $31, 116(k0) /* saved ra */ -+ move sp, k0 -+ -+ /* save CP0 registers and sp (total 26) */ -+ move k0, sp -+ addiu k0, k0, -(26*4) -+ -+ mfc0 $1, CP0_INDEX -+ mfc0 $2, CP0_RANDOM -+ mfc0 $3, CP0_ENTRYLO0 -+ mfc0 $4, CP0_ENTRYLO1 -+ mfc0 $5, CP0_CONTEXT -+ mfc0 $6, CP0_PAGEMASK -+ mfc0 $7, CP0_WIRED -+ mfc0 $8, CP0_BADVADDR -+ mfc0 $9, CP0_ENTRYHI -+ mfc0 $10, CP0_STATUS -+/* mfc0 $11, $12, 1*/ /* IntCtl */ -+ mfc0 $12, CP0_CAUSE -+ mfc0 $13, CP0_EPC -+/* mfc0 $14, $15, 1*/ /* EBase */ -+ mfc0 $15, CP0_CONFIG -+/* mfc0 $16, CP0_CONFIG, 7*/ /* Config 7 */ -+ mfc0 $17, CP0_LLADDR -+ mfc0 $18, CP0_WATCHLO -+ mfc0 $19, CP0_WATCHHI -+ mfc0 $20, CP0_DEBUG -+ mfc0 $21, CP0_DEPC -+ mfc0 $22, CP0_ECC -+ mfc0 $23, CP0_TAGLO -+ mfc0 $24, CP0_ERROREPC -+ mfc0 $25, CP0_DESAVE -+ -+ sw $1, 0(k0) -+ sw $2, 4(k0) -+ sw $3, 8(k0) -+ sw $4, 12(k0) -+ sw $5, 16(k0) -+ sw $6, 20(k0) -+ sw $7, 24(k0) -+ sw $8, 28(k0) -+ sw $9, 32(k0) -+ sw $10, 36(k0) -+ sw $11, 40(k0) -+ sw $12, 44(k0) -+ sw $13, 48(k0) -+ sw $14, 52(k0) -+ sw $15, 56(k0) -+ sw $16, 60(k0) -+ sw $17, 64(k0) -+ sw $18, 68(k0) -+ sw $19, 72(k0) -+ sw $20, 76(k0) -+ sw $21, 80(k0) -+ sw $22, 84(k0) -+ sw $23, 88(k0) -+ sw $24, 92(k0) -+ sw $25, 96(k0) -+ sw $29, 100(k0) /* saved sp */ -+ move sp, k0 -+ -+ /* preserve virtual address of stack */ -+ la k0, suspend_save_sp -+ sw sp, 0(k0) -+ -+ /* flush caches and write buffers */ -+ jal jz_flush_cache_all -+ nop -+ -+ /* set new sdram refresh constant */ -+ li t0, 1 -+ la t1, EMC_RTCOR -+ sh t0, 0(t1) -+ -+ /* disable PLL */ -+ la t0, CPM_PLCR1 -+ sw $0, 0(t0) -+ -+ /* put CPU to hibernate mode */ -+ la t0, CPM_LPCR -+ lw t1, 0(t0) -+ li t2, ~CPM_LPCR_LPM_MASK -+ and t1, t2 -+ ori t1, CPM_LPCR_LPM_HIBERNATE -+ -+ .align 5 -+ /* align execution to a cache line */ -+ j 1f -+ -+ .align 5 -+1: -+ /* all needed values are now in registers. -+ * These last instructions should be in cache -+ */ -+ nop -+ nop -+ -+ /* set hibernate mode */ -+ sw t1, 0(t0) -+ nop -+ -+ /* enter hibernate mode */ -+ .set mips3 -+ wait -+ nop -+ .set mips2 -+ -+2: j 2b /* loop waiting for suspended */ -+ nop -+ -+/* -+ * jz_cpu_resume() -+ * -+ * entry point from bootloader into kernel during resume -+ */ -+ -+ .align 5 -+ .globl jz_cpu_resume -+jz_cpu_resume: -+ /* clear SCR.HGP */ -+ la t0, CPM_SCR -+ lw t1, 0(t0) -+ li t2, ~CPM_SCR_HGP -+ and t1, t2 -+ sw t1, 0(t0) -+ -+ /* restore LPCR.LPM to IDLE mode */ -+ la t0, CPM_LPCR -+ lw t1, 0(t0) -+ li t2, ~CPM_LPCR_LPM_MASK -+ and t1, t2 -+ ori t1, CPM_LPCR_LPM_IDLE -+ sw t1, 0(t0) -+ -+ /* restore saved sp */ -+ la t0, suspend_save_sp -+ lw sp, 0(t0) -+ -+ /* restore CP0 registers */ -+ move k0, sp -+ lw $1, 0(k0) -+ lw $2, 4(k0) -+ lw $3, 8(k0) -+ lw $4, 12(k0) -+ lw $5, 16(k0) -+ lw $6, 20(k0) -+ lw $7, 24(k0) -+ lw $8, 28(k0) -+ lw $9, 32(k0) -+ lw $10, 36(k0) -+ lw $11, 40(k0) -+ lw $12, 44(k0) -+ lw $13, 48(k0) -+ lw $14, 52(k0) -+ lw $15, 56(k0) -+ lw $16, 60(k0) -+ lw $17, 64(k0) -+ lw $18, 68(k0) -+ lw $19, 72(k0) -+ lw $20, 76(k0) -+ lw $21, 80(k0) -+ lw $22, 84(k0) -+ lw $23, 88(k0) -+ lw $24, 92(k0) -+ lw $25, 96(k0) -+ lw $29, 100(k0) /* saved sp */ -+ -+ mtc0 $1, CP0_INDEX -+ mtc0 $2, CP0_RANDOM -+ mtc0 $3, CP0_ENTRYLO0 -+ mtc0 $4, CP0_ENTRYLO1 -+ mtc0 $5, CP0_CONTEXT -+ mtc0 $6, CP0_PAGEMASK -+ mtc0 $7, CP0_WIRED -+ mtc0 $8, CP0_BADVADDR -+ mtc0 $9, CP0_ENTRYHI -+ mtc0 $10, CP0_STATUS -+/* mtc0 $11, $12, 1*/ /* IntCtl */ -+ mtc0 $12, CP0_CAUSE -+ mtc0 $13, CP0_EPC -+/* mtc0 $14, $15, 1*/ /* EBase */ -+ mtc0 $15, CP0_CONFIG -+/* mtc0 $16, CP0_CONFIG, 7*/ /* Config 7 */ -+ mtc0 $17, CP0_LLADDR -+ mtc0 $18, CP0_WATCHLO -+ mtc0 $19, CP0_WATCHHI -+ mtc0 $20, CP0_DEBUG -+ mtc0 $21, CP0_DEPC -+ mtc0 $22, CP0_ECC -+ mtc0 $23, CP0_TAGLO -+ mtc0 $24, CP0_ERROREPC -+ mtc0 $25, CP0_DESAVE -+ -+ /* restore general registers */ -+ move k0, sp -+ lw k1, 120(k0) /* hi */ -+ lw $0, 0(k0) -+ lw $1, 4(k0) -+ mthi k1 -+ lw k1, 124(k0) /* lo */ -+ lw $2, 8(k0) -+ lw $3, 12(k0) -+ mtlo k1 -+ lw $4, 16(k0) -+ lw $5, 20(k0) -+ lw $6, 24(k0) -+ lw $7, 28(k0) -+ lw $8, 32(k0) -+ lw $9, 36(k0) -+ lw $10, 40(k0) -+ lw $11, 44(k0) -+ lw $12, 48(k0) -+ lw $13, 52(k0) -+ lw $14, 56(k0) -+ lw $15, 60(k0) -+ lw $16, 64(k0) -+ lw $17, 68(k0) -+ lw $18, 72(k0) -+ lw $19, 76(k0) -+ lw $20, 80(k0) -+ lw $21, 84(k0) -+ lw $22, 88(k0) -+ lw $23, 92(k0) -+ lw $24, 96(k0) -+ lw $25, 100(k0) -+ lw $28, 104(k0) -+ lw $29, 108(k0) /* saved sp */ -+ lw $30, 112(k0) -+ lw $31, 116(k0) /* saved ra */ -+ -+ /* return to caller */ -+ jr ra -+ nop -+ -+suspend_save_sp: -+ .word 0 /* preserve sp here */ -+ -+ .set reorder -diff --git a/arch/mips/jz4730/time.c b/arch/mips/jz4730/time.c -new file mode 100644 -index 0000000..806c7fe ---- /dev/null -+++ b/arch/mips/jz4730/time.c -@@ -0,0 +1,129 @@ -+/* -+ * linux/arch/mips/jz4730/time.c -+ * -+ * Setting up the clock on the JZ4730 boards. -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define JZ_TIMER_CHAN 0 -+#define JZ_TIMER_IRQ IRQ_OST0 -+#define JZ_TIMER_CLOCK JZ_EXTAL -+ -+static unsigned int timer_latch; -+ -+void (*jz_timer_callback)(void); -+ -+static void jz_set_mode(enum clock_event_mode mode, -+ struct clock_event_device *evt) -+{ -+ switch (mode) { -+ case CLOCK_EVT_MODE_PERIODIC: -+ break; -+ case CLOCK_EVT_MODE_ONESHOT: -+ case CLOCK_EVT_MODE_UNUSED: -+ case CLOCK_EVT_MODE_SHUTDOWN: -+ break; -+ case CLOCK_EVT_MODE_RESUME: -+ break; -+ } -+} -+ -+static struct clock_event_device jz_clockevent_device = { -+ .name = "jz-timer", -+ .features = CLOCK_EVT_FEAT_PERIODIC, -+ -+ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -+ -+ .rating = 300, -+ .irq = JZ_TIMER_IRQ, -+ .set_mode = jz_set_mode, -+}; -+ -+static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *cd = dev_id; -+ -+ __ost_clear_uf(JZ_TIMER_CHAN); /* ACK timer */ -+ -+ if (jz_timer_callback) -+ jz_timer_callback(); -+ -+ cd->event_handler(cd); -+ -+ return IRQ_HANDLED; -+} -+ -+static struct irqaction jz_irqaction = { -+ .handler = jz_timer_interrupt, -+ .flags = IRQF_DISABLED | IRQF_PERCPU, -+ .name = "jz-timer", -+}; -+ -+cycle_t jz_get_cycles(void) -+{ -+ unsigned int jz_timer_cnt; -+#if 0 /* clock source use pll, read directly */ -+ jz_timer_cnt = timer_latch - REG_OST_TCNT(JZ_TIMER_CHAN); -+#else /* clock source use RTCClock or Extall Clock, wait read ready */ -+ jz_timer_cnt = REG_OST_TCNT(JZ_TIMER_CHAN); /* dummy read */ -+ while ( __ost_is_busy(JZ_TIMER_CHAN) ) ; /* wait read ready */ -+ jz_timer_cnt = timer_latch - REG_OST_TCRB(JZ_TIMER_CHAN); -+#endif -+ -+ /* convert jiffes to jz timer cycles */ -+ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + jz_timer_cnt); -+} -+ -+static struct clocksource clocksource_jz = { -+ .name = "jz_clocksource", -+ .rating = 300, -+ .read = jz_get_cycles, -+ .mask = 0xFFFFFFFF, -+ .shift = 10, /* control clocksource.mult's accuracy */ -+ .flags = CLOCK_SOURCE_WATCHDOG, -+}; -+ -+static int __init jz_clocksource_init(void) -+{ -+ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -+ clocksource_register(&clocksource_jz); -+ return 0; -+} -+ -+static void __init jz_timer_setup(void) -+{ -+ struct clock_event_device *cd = &jz_clockevent_device; -+ struct irqaction *action = &jz_irqaction; -+ unsigned int cpu = smp_processor_id(); -+ -+ jz_clocksource_init(); -+ cd->cpumask = cpumask_of_cpu(cpu); -+ clockevents_register_device(cd); -+ action->dev_id = cd; -+ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -+} -+ -+void __init plat_time_init(void) -+{ -+ /* Init timer, timer clock soure use extal clock */ -+ timer_latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -+ __ost_set_mode(JZ_TIMER_CHAN, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL); -+ __ost_set_reload(JZ_TIMER_CHAN, timer_latch); -+ __ost_set_count(JZ_TIMER_CHAN, timer_latch); -+ __ost_enable_channel(JZ_TIMER_CHAN); -+ -+ jz_timer_setup(); -+} -diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile -new file mode 100644 -index 0000000..d32e7d0 ---- /dev/null -+++ b/arch/mips/jz4740/Makefile -@@ -0,0 +1,27 @@ -+# -+# Makefile for the Ingenic JZ4740. -+# -+ -+# Object file lists. -+ -+obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -+ platform.o i2c.o -+ -+obj-$(CONFIG_PROC_FS) += proc.o -+ -+# board specific support -+ -+obj-$(CONFIG_JZ4740_PAVO) += board-pavo.o -+obj-$(CONFIG_JZ4740_LEO) += board-leo.o -+obj-$(CONFIG_JZ4740_LYRA) += board-lyra.o -+obj-$(CONFIG_JZ4725_DIPPER) += board-dipper.o -+obj-$(CONFIG_JZ4720_VIRGO) += board-virgo.o -+obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o -+ -+# PM support -+ -+obj-$(CONFIG_PM_LEGACY) +=pm.o -+ -+# CPU Frequency scaling support -+ -+obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -diff --git a/arch/mips/jz4740/board-dipper.c b/arch/mips/jz4740/board-dipper.c -new file mode 100644 -index 0000000..ca30225 ---- /dev/null -+++ b/arch/mips/jz4740/board-dipper.c -@@ -0,0 +1,117 @@ -+/* -+ * linux/arch/mips/jz4740/board-dipper.c -+ * -+ * JZ4725 Dipper board setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+#if 0 -+static void dancing(void) -+{ -+ static unsigned int count = 0; -+ -+ count ++; -+ count &= 1; -+ -+ if (count) -+ __gpio_set_pin(GPIO_LED_EN); -+ else -+ __gpio_clear_pin(GPIO_LED_EN); -+} -+#endif -+ -+static void dipper_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+// dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4740/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Most of the GPIO pins should have been initialized by the boot-loader -+ */ -+ -+ /* -+ * Initialize MSC pins -+ */ -+ __gpio_as_msc(); -+ -+ /* -+ * Initialize Smart LCD pins -+ */ -+// __gpio_as_slcd_18bit(); -+ -+ /* -+ * Initialize SSI pins -+ */ -+ __gpio_as_ssi(); -+ -+ /* -+ * Initialize I2C pins -+ */ -+ __gpio_as_i2c(); -+ -+ /* -+ * Initialize Other pins -+ */ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -+ -+ __gpio_as_input(GPIO_SD_CD_N); -+ __gpio_disable_pull(GPIO_SD_CD_N); -+ -+ __gpio_as_input(GPIO_SD_WP); -+ __gpio_disable_pull(GPIO_SD_WP); -+ -+ __gpio_as_input(GPIO_DC_DETE_N); -+ __gpio_as_input(GPIO_CHARG_STAT_N); -+ __gpio_as_input(GPIO_USB_DETE); -+ -+ __gpio_as_output(GPIO_DISP_OFF_N); -+ -+// __gpio_as_output(GPIO_LED_EN); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4725 DIPPER board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = dipper_timer_callback; -+} -diff --git a/arch/mips/jz4740/board-leo.c b/arch/mips/jz4740/board-leo.c -new file mode 100644 -index 0000000..912636a ---- /dev/null -+++ b/arch/mips/jz4740/board-leo.c -@@ -0,0 +1,67 @@ -+/* -+ * linux/arch/mips/jz4740/board-leo.c -+ * -+ * JZ4740 LEO board setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned char slash[] = "\\|/-"; -+ static volatile unsigned char *p = (unsigned char *)0xb6000016; -+ static unsigned int count = 0; -+ *p = slash[count++]; -+ count &= 3; -+} -+ -+static void leo_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 10 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4740/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* All GPIO pins should have been initialized by the boot-loader */ -+} -+ -+void __init jz_board_setup(void) -+{ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ printk(" BOARD SETUP"); -+ jz_timer_callback = leo_timer_callback; -+} -diff --git a/arch/mips/jz4740/board-lyra.c b/arch/mips/jz4740/board-lyra.c -new file mode 100644 -index 0000000..ea56626 ---- /dev/null -+++ b/arch/mips/jz4740/board-lyra.c -@@ -0,0 +1,114 @@ -+/* -+ * linux/arch/mips/jz4740/board-lyra.c -+ * -+ * JZ4740 LYRA board setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned int count = 0; -+ -+ count ++; -+ count &= 1; -+ if (count) -+ __gpio_set_pin(GPIO_LED_EN); -+ else -+ __gpio_clear_pin(GPIO_LED_EN); -+} -+ -+static void lyra_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4740/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Most of the GPIO pins should have been initialized by the boot-loader -+ */ -+ -+ /* -+ * Initialize MSC pins -+ */ -+ __gpio_as_msc(); -+ -+ /* -+ * Initialize LCD pins -+ */ -+ __gpio_as_lcd_18bit(); -+ -+ /* -+ * Initialize SSI pins -+ */ -+ __gpio_as_ssi(); -+ -+ /* -+ * Initialize I2C pins -+ */ -+ __gpio_as_i2c(); -+ -+ /* -+ * Initialize Other pins -+ */ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -+ -+ __gpio_as_input(GPIO_SD_CD_N); -+ __gpio_disable_pull(GPIO_SD_CD_N); -+ -+ __gpio_as_input(GPIO_SD_WP); -+ __gpio_disable_pull(GPIO_SD_WP); -+ -+ __gpio_as_input(GPIO_DC_DETE_N); -+ __gpio_as_input(GPIO_CHARG_STAT_N); -+ __gpio_as_input(GPIO_USB_DETE); -+ -+ __gpio_as_output(GPIO_DISP_OFF_N); -+ -+ __gpio_as_output(GPIO_LED_EN); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4740 LYRA board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = lyra_timer_callback; -+} -diff --git a/arch/mips/jz4740/board-pavo.c b/arch/mips/jz4740/board-pavo.c -new file mode 100644 -index 0000000..e2a5509 ---- /dev/null -+++ b/arch/mips/jz4740/board-pavo.c -@@ -0,0 +1,114 @@ -+/* -+ * linux/arch/mips/jz4740/board-pavo.c -+ * -+ * JZ4740 PAVO board setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned int count = 0; -+ -+ count ++; -+ count &= 1; -+ if (count) -+ __gpio_set_pin(GPIO_LED_EN); -+ else -+ __gpio_clear_pin(GPIO_LED_EN); -+} -+ -+static void pavo_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4740/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Most of the GPIO pins should have been initialized by the boot-loader -+ */ -+ -+ /* -+ * Initialize MSC pins -+ */ -+ __gpio_as_msc(); -+ -+ /* -+ * Initialize LCD pins -+ */ -+ __gpio_as_lcd_18bit(); -+ -+ /* -+ * Initialize SSI pins -+ */ -+ __gpio_as_ssi(); -+ -+ /* -+ * Initialize I2C pins -+ */ -+ __gpio_as_i2c(); -+ -+ /* -+ * Initialize Other pins -+ */ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -+ -+ __gpio_as_input(GPIO_SD_CD_N); -+ __gpio_disable_pull(GPIO_SD_CD_N); -+ -+ __gpio_as_input(GPIO_SD_WP); -+ __gpio_disable_pull(GPIO_SD_WP); -+ -+ __gpio_as_input(GPIO_DC_DETE_N); -+ __gpio_as_input(GPIO_CHARG_STAT_N); -+ __gpio_as_input(GPIO_USB_DETE); -+ -+ __gpio_as_output(GPIO_DISP_OFF_N); -+ -+ __gpio_as_output(GPIO_LED_EN); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4740 PAVO board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = pavo_timer_callback; -+} -diff --git a/arch/mips/jz4740/board-virgo.c b/arch/mips/jz4740/board-virgo.c -new file mode 100644 -index 0000000..1429877 ---- /dev/null -+++ b/arch/mips/jz4740/board-virgo.c -@@ -0,0 +1,114 @@ -+/* -+ * linux/arch/mips/jz4740/board-virgo.c -+ * -+ * JZ4720 VIRGO board setup routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned int count = 0; -+ -+ count ++; -+ count &= 1; -+ if (count) -+ __gpio_set_pin(GPIO_LED_EN); -+ else -+ __gpio_clear_pin(GPIO_LED_EN); -+} -+ -+static void virgo_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4740/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Most of the GPIO pins should have been initialized by the boot-loader -+ */ -+ -+ /* -+ * Initialize MSC pins -+ */ -+ __gpio_as_msc(); -+ -+ /* -+ * Initialize LCD pins -+ */ -+// __gpio_as_lcd_18bit(); -+ -+ /* -+ * Initialize SSI pins -+ */ -+ __gpio_as_ssi(); -+ -+ /* -+ * Initialize I2C pins -+ */ -+ __gpio_as_i2c(); -+ -+ /* -+ * Initialize Other pins -+ */ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -+ -+ __gpio_as_input(GPIO_SD_CD_N); -+ __gpio_disable_pull(GPIO_SD_CD_N); -+ -+// __gpio_as_input(GPIO_SD_WP); -+// __gpio_disable_pull(GPIO_SD_WP); -+ -+ __gpio_as_input(GPIO_DC_DETE_N); -+// __gpio_as_input(GPIO_CHARG_STAT_N); -+ __gpio_as_input(GPIO_USB_DETE); -+ -+ __gpio_as_output(GPIO_DISP_OFF_N); -+ -+// __gpio_as_output(GPIO_LED_EN); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4720 VIRGO board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = virgo_timer_callback; -+} -diff --git a/arch/mips/jz4740/cpufreq.c b/arch/mips/jz4740/cpufreq.c -new file mode 100644 -index 0000000..d646a1e ---- /dev/null -+++ b/arch/mips/jz4740/cpufreq.c -@@ -0,0 +1,602 @@ -+/* -+ * linux/arch/mips/jz4740/cpufreq.c -+ * -+ * cpufreq driver for JZ4740 -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -+ "cpufreq-jz4740", msg) -+ -+#undef CHANGE_PLL -+ -+#define PLL_UNCHANGED 0 -+#define PLL_GOES_UP 1 -+#define PLL_GOES_DOWN 2 -+ -+#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) -+ -+/* Saved the boot-time parameters */ -+static struct { -+ /* SDRAM parameters */ -+ unsigned int mclk; /* memory clock, KHz */ -+ unsigned int tras; /* RAS pulse width, cycles of mclk */ -+ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -+ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -+ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -+ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -+ unsigned int rtcor; /* Refresh Time Constant */ -+ unsigned int sdram_initialized; -+ -+ /* LCD parameters */ -+ unsigned int lcd_clk; /* LCD clock, Hz */ -+ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -+ unsigned int lcd_clks_initialized; -+} boot_config; -+ -+struct jz4740_freq_percpu_info { -+ struct cpufreq_frequency_table table[7]; -+}; -+ -+static struct jz4740_freq_percpu_info jz4740_freq_table; -+ -+/* -+ * This contains the registers value for an operating point. -+ * If only part of a register needs to change then there is -+ * a mask value for that register. -+ * When going to a new operating point the current register -+ * value is ANDed with the ~mask and ORed with the new value. -+ */ -+struct dpm_regs { -+ u32 cpccr; /* Clock Freq Control Register */ -+ u32 cpccr_mask; /* Clock Freq Control Register mask */ -+ u32 cppcr; /* PLL1 Control Register */ -+ u32 cppcr_mask; /* PLL1 Control Register mask */ -+ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -+}; -+ -+extern jz_clocks_t jz_clocks; -+ -+static void jz_update_clocks(void) -+{ -+ /* Next clocks must be updated if we have changed -+ * the PLL or divisors. -+ */ -+ jz_clocks.cclk = __cpm_get_cclk(); -+ jz_clocks.hclk = __cpm_get_hclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(); -+} -+ -+static void -+jz_init_boot_config(void) -+{ -+ if (!boot_config.lcd_clks_initialized) { -+ /* the first time to scale pll */ -+ boot_config.lcd_clk = __cpm_get_lcdclk(); -+ boot_config.lcdpix_clk = __cpm_get_pixclk(); -+ boot_config.lcd_clks_initialized = 1; -+ } -+ -+ if (!boot_config.sdram_initialized) { -+ /* the first time to scale frequencies */ -+ unsigned int dmcr, rtcor; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ -+ dmcr = REG_EMC_DMCR; -+ rtcor = REG_EMC_RTCOR; -+ -+ tras = (dmcr >> 13) & 0x7; -+ rcd = (dmcr >> 11) & 0x3; -+ tpc = (dmcr >> 8) & 0x7; -+ trwl = (dmcr >> 5) & 0x3; -+ trc = (dmcr >> 2) & 0x7; -+ -+ boot_config.mclk = __cpm_get_mclk() / 1000; -+ boot_config.tras = tras + 4; -+ boot_config.rcd = rcd + 1; -+ boot_config.tpc = tpc + 1; -+ boot_config.trwl = trwl + 1; -+ boot_config.trc = trc * 2 + 1; -+ boot_config.rtcor = rtcor; -+ -+ boot_config.sdram_initialized = 1; -+ } -+} -+ -+static void jz_update_dram_rtcor(unsigned int new_mclk) -+{ -+ unsigned int rtcor; -+ -+ new_mclk /= 1000; -+ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -+ rtcor--; -+ -+ if (rtcor < 1) rtcor = 1; -+ if (rtcor > 255) rtcor = 255; -+ -+ REG_EMC_RTCOR = rtcor; -+ REG_EMC_RTCNT = rtcor; -+} -+ -+static void jz_update_dram_dmcr(unsigned int new_mclk) -+{ -+ unsigned int dmcr; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ unsigned int valid_time, new_time; /* ns */ -+ -+ new_mclk /= 1000; -+ tras = boot_config.tras * new_mclk / boot_config.mclk; -+ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -+ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -+ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -+ trc = boot_config.trc * new_mclk / boot_config.mclk; -+ -+ /* Validation checking */ -+ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -+ new_time = (tras * 1000000) / new_mclk; -+ if (new_time < valid_time) tras += 1; -+ -+ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -+ new_time = (rcd * 1000000) / new_mclk; -+ if (new_time < valid_time) rcd += 1; -+ -+ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -+ new_time = (tpc * 1000000) / new_mclk; -+ if (new_time < valid_time) tpc += 1; -+ -+ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -+ new_time = (trwl * 1000000) / new_mclk; -+ if (new_time < valid_time) trwl += 1; -+ -+ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -+ new_time = (trc * 1000000) / new_mclk; -+ if (new_time < valid_time) trc += 2; -+ -+ tras = (tras < 4) ? 4: tras; -+ tras = (tras > 11) ? 11: tras; -+ tras -= 4; -+ -+ rcd = (rcd < 1) ? 1: rcd; -+ rcd = (rcd > 4) ? 4: rcd; -+ rcd -= 1; -+ -+ tpc = (tpc < 1) ? 1: tpc; -+ tpc = (tpc > 8) ? 8: tpc; -+ tpc -= 1; -+ -+ trwl = (trwl < 1) ? 1: trwl; -+ trwl = (trwl > 4) ? 4: trwl; -+ trwl -= 1; -+ -+ trc = (trc < 1) ? 1: trc; -+ trc = (trc > 15) ? 15: trc; -+ trc /= 2; -+ -+ dmcr = REG_EMC_DMCR; -+ -+ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -+ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -+ -+ REG_EMC_DMCR = dmcr; -+} -+ -+static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR before changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } else { -+ /* We're going SLOWER: first update RTCOR value -+ * before changing the frequency. -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } -+} -+ -+static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so update RTCOR -+ * after changing the frequency -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } else { -+ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR after changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } -+} -+ -+static void jz_scale_divisors(struct dpm_regs *regs) -+{ -+ unsigned int cpccr; -+ unsigned int cur_mclk, new_mclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ cpccr = REG_CPM_CPCCR; -+ cpccr &= ~((unsigned long)regs->cpccr_mask); -+ cpccr |= regs->cpccr; -+ cpccr |= CPM_CPCCR_CE; /* update immediately */ -+ -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; -+ -+ /* Update some DRAM parameters before changing frequency */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+ -+#ifdef CHANGE_PLL -+/* Maintain the LCD clock and pixel clock */ -+static void jz_scale_lcd_divisors(struct dpm_regs *regs) -+{ -+ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -+ unsigned int cpccr; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ if (!boot_config.lcd_clks_initialized) return; -+ -+ new_pll = __cpm_get_pllout(); -+ new_lcd_div = new_pll / boot_config.lcd_clk; -+ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -+ -+ if (new_lcd_div < 1) -+ new_lcd_div = 1; -+ if (new_lcd_div > 16) -+ new_lcd_div = 16; -+ -+ if (new_lcdpix_div < 1) -+ new_lcdpix_div = 1; -+ if (new_lcdpix_div > 512) -+ new_lcdpix_div = 512; -+ -+// REG_CPM_CPCCR2 = new_lcdpix_div - 1; -+ -+ cpccr = REG_CPM_CPCCR; -+ cpccr &= ~CPM_CPCCR_LDIV_MASK; -+ cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); -+ cpccr |= CPM_CPCCR_CE; /* update immediately */ -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -+} -+ -+static void jz_scale_pll(struct dpm_regs *regs) -+{ -+ unsigned int cppcr; -+ unsigned int cur_mclk, new_mclk, new_pll; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ int od[] = {1, 2, 2, 4}; -+ -+ cppcr = REG_CPM_CPPCR; -+ cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); -+ regs->cppcr &= ~CPM_CPPCR_PLLEN; -+ cppcr |= (regs->cppcr | 0xff); -+ -+ /* Update some DRAM parameters before changing frequency */ -+ new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = new_pll / div[(REG_CPM_CPCCR>>CPM_CPCCR_MDIV_BIT) & 0xf]; -+ -+ /* -+ * Update some SDRAM parameters -+ */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* -+ * Update PLL, align code to cache line. -+ */ -+ cppcr |= CPM_CPPCR_PLLEN; -+ __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" (CPM_CPPCR), "r" (cppcr)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+#endif -+ -+static void jz4740_transition(struct dpm_regs *regs) -+{ -+ /* -+ * Get and save some boot-time conditions. -+ */ -+ jz_init_boot_config(); -+ -+#ifdef CHANGE_PLL -+ /* -+ * Disable LCD before scaling pll. -+ * LCD and LCD pixel clocks should not be changed even if the PLL -+ * output frequency has been changed. -+ */ -+ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -+ -+ /* -+ * Stop module clocks before scaling PLL -+ */ -+ __cpm_stop_eth(); -+ __cpm_stop_aic(1); -+ __cpm_stop_aic(2); -+#endif -+ -+ /* ... add more as necessary */ -+ -+ if (regs->pll_up_flag == PLL_GOES_UP) { -+ /* the pll frequency is going up, so change dividors first */ -+ jz_scale_divisors(regs); -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ } -+ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -+ /* the pll frequency is going down, so change pll first */ -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ jz_scale_divisors(regs); -+ } -+ else { -+ /* the pll frequency is unchanged, so change divisors only */ -+ jz_scale_divisors(regs); -+ } -+ -+#ifdef CHANGE_PLL -+ /* -+ * Restart module clocks before scaling PLL -+ */ -+ __cpm_start_eth(); -+ __cpm_start_aic(1); -+ __cpm_start_aic(2); -+ -+ /* ... add more as necessary */ -+ -+ /* Scale the LCD divisors after scaling pll */ -+ if (regs->pll_up_flag != PLL_UNCHANGED) { -+ jz_scale_lcd_divisors(regs); -+ } -+ -+ /* Enable LCD controller */ -+ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -+ REG_LCD_CTRL |= LCD_CTRL_ENA; -+#endif -+ -+ /* Update system clocks */ -+ jz_update_clocks(); -+} -+ -+extern unsigned int idle_times; -+static unsigned int jz4740_freq_get(unsigned int cpu) -+{ -+ return (__cpm_get_cclk() / 1000); -+} -+ -+static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -+{ -+ int n2FR[33] = { -+ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -+ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -+ 9 -+ }; -+ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -+ unsigned int div_of_cclk, new_freq, i; -+ -+ regs->pll_up_flag = PLL_UNCHANGED; -+ regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; -+ -+ new_freq = jz4740_freq_table.table[index].frequency; -+ -+ do { -+ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -+ } while (div_of_cclk==0); -+ -+ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -+ for(i = 1; i<4; i++) { -+ div[i] = 3; -+ } -+ } else { -+ for(i = 1; i<4; i++) { -+ div[i] = 2; -+ } -+ } -+ -+ for(i = 0; i<4; i++) { -+ div[i] *= div_of_cclk; -+ } -+ -+ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -+ -+ regs->cpccr = -+ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | -+ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | -+ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | -+ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); -+ -+ return div_of_cclk; -+} -+ -+static void jz4740_set_cpu_divider_index(unsigned int cpu, unsigned int index) -+{ -+ unsigned long divisor, old_divisor; -+ struct cpufreq_freqs freqs; -+ struct dpm_regs regs; -+ -+ old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); -+ divisor = index_to_divisor(index, ®s); -+ -+ freqs.old = __cpm_get_cclk() / 1000; -+ freqs.new = __cpm_get_pllout() / (1000 * divisor); -+ freqs.cpu = cpu; -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -+ -+ if (old_divisor != divisor) -+ jz4740_transition(®s); -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -+} -+ -+static int jz4740_freq_target(struct cpufreq_policy *policy, -+ unsigned int target_freq, -+ unsigned int relation) -+{ -+ unsigned int new_index = 0; -+ -+ if (cpufreq_frequency_table_target(policy, -+ &jz4740_freq_table.table[0], -+ target_freq, relation, &new_index)) -+ return -EINVAL; -+ -+ jz4740_set_cpu_divider_index(policy->cpu, new_index); -+ -+ dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); -+ -+ return 0; -+} -+ -+static int jz4740_freq_verify(struct cpufreq_policy *policy) -+{ -+ return cpufreq_frequency_table_verify(policy, -+ &jz4740_freq_table.table[0]); -+} -+ -+static int __init jz4740_cpufreq_driver_init(struct cpufreq_policy *policy) -+{ -+ -+ struct cpufreq_frequency_table *table = &jz4740_freq_table.table[0]; -+ unsigned int MAX_FREQ; -+ -+ dprintk(KERN_INFO "Jz4740 cpufreq driver\n"); -+ -+ if (policy->cpu != 0) -+ return -EINVAL; -+ -+ policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -+ -+ policy->cpuinfo.min_freq = MAX_FREQ/8; -+ policy->cpuinfo.max_freq = MAX_FREQ; -+ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -+ -+ table[0].index = 0; -+ table[0].frequency = MAX_FREQ/8; -+ table[1].index = 1; -+ table[1].frequency = MAX_FREQ/6; -+ table[2].index = 2; -+ table[2].frequency = MAX_FREQ/4; -+ table[3].index = 3; -+ table[3].frequency = MAX_FREQ/3; -+ table[4].index = 4; -+ table[4].frequency = MAX_FREQ/2; -+ table[5].index = 5; -+ table[5].frequency = MAX_FREQ; -+ table[6].index = 6; -+ table[6].frequency = CPUFREQ_TABLE_END; -+ -+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS -+ cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ -+#endif -+ -+ return cpufreq_frequency_table_cpuinfo(policy, table); -+} -+ -+static struct cpufreq_driver cpufreq_jz4740_driver = { -+// .flags = CPUFREQ_STICKY, -+ .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("Regen "); -+MODULE_DESCRIPTION("cpufreq driver for Jz4740"); -+MODULE_LICENSE("GPL"); -+ -diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c -new file mode 100644 -index 0000000..dd5055e ---- /dev/null -+++ b/arch/mips/jz4740/dma.c -@@ -0,0 +1,768 @@ -+/* -+ * linux/arch/mips/jz4740/dma.c -+ * -+ * Support functions for the JZ4740 internal DMA channels. -+ * No-descriptor transfer only. -+ * Descriptor transfer should also call jz_request_dma() to get a free -+ * channel and call jz_free_dma() to free the channel. And driver should -+ * build the DMA descriptor and setup the DMA channel by itself. -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * A note on resource allocation: -+ * -+ * All drivers needing DMA channels, should allocate and release them -+ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -+ * -+ * In order to avoid problems, all processes should allocate resources in -+ * the same sequence and release them in the reverse order. -+ * -+ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -+ * When releasing them, first release the IRQ, then release the DMA. The -+ * main reason for this order is that, if you are requesting the DMA buffer -+ * done interrupt, you won't know the irq number until the DMA channel is -+ * returned from jz_request_dma(). -+ */ -+ -+struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+ {dev_id:-1,}, -+}; -+ -+// Device FIFO addresses and default DMA modes -+static const struct { -+ unsigned int fifo_addr; -+ unsigned int dma_mode; -+ unsigned int dma_source; -+} dma_dev_table[DMA_ID_MAX] = { -+ {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -+ {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -+ {CPHYSADDR(SSI_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT}, -+ {CPHYSADDR(SSI_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSIIN}, -+ {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -+ {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -+ {CPHYSADDR(MSC_TXFIFO), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT}, -+ {CPHYSADDR(MSC_RXFIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSCIN}, -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, -+ {}, -+}; -+ -+ -+int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data) -+{ -+ int i, len = 0; -+ struct jz_dma_chan *chan; -+ -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if ((chan = get_dma_chan(i)) != NULL) { -+ len += sprintf(buf + len, "%2d: %s\n", -+ i, chan->dev_str); -+ } -+ } -+ -+ if (fpos >= len) { -+ *start = buf; -+ *eof = 1; -+ return 0; -+ } -+ *start = buf + fpos; -+ if ((len -= fpos) > length) -+ return length; -+ *eof = 1; -+ return len; -+} -+ -+ -+void dump_jz_dma_channel(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > MAX_DMA_NUM) -+ return; -+ chan = &jz_dma_table[dmanr]; -+ -+ printk("DMA%d Registers:\n", dmanr); -+ printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR); -+ printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -+ printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); -+ printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -+ printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -+ printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -+ printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); -+ printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); -+ printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR); -+} -+ -+ -+/** -+ * jz_request_dma - dynamically allcate an idle DMA channel to return -+ * @dev_id: the specified dma device id or DMA_ID_RAW_SET -+ * @dev_str: the specified dma device string name -+ * @irqhandler: the irq handler, or NULL -+ * @irqflags: the irq handler flags -+ * @irq_dev_id: the irq handler device id for shared irq -+ * -+ * Finds a free channel, and binds the requested device to it. -+ * Returns the allocated channel number, or negative on error. -+ * Requests the DMA done IRQ if irqhandler != NULL. -+ * -+*/ -+/*int jz_request_dma(int dev_id, const char *dev_str, -+ void (*irqhandler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+*/ -+ -+int jz_request_dma(int dev_id, const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+{ -+ struct jz_dma_chan *chan; -+ int i, ret; -+ -+ if (dev_id < 0 || dev_id >= DMA_ID_MAX) -+ return -EINVAL; -+ -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == MAX_DMA_NUM) /* no free channel */ -+ return -ENODEV; -+ -+ /* we got a free channel */ -+ chan = &jz_dma_table[i]; -+ -+ if (irqhandler) { -+ chan->irq = IRQ_DMA_0 + i; // allocate irq number -+ chan->irq_dev = irq_dev_id; -+ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -+ dev_str, chan->irq_dev))) { -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ return ret; -+ } -+ } else { -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ } -+ -+ // fill it in -+ chan->io = i; -+ chan->dev_id = dev_id; -+ chan->dev_str = dev_str; -+ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -+ chan->mode = dma_dev_table[dev_id].dma_mode; -+ chan->source = dma_dev_table[dev_id].dma_source; -+ -+ return i; -+} -+ -+void jz_free_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) { -+ printk("Trying to free DMA%d\n", dmanr); -+ return; -+ } -+ -+ disable_dma(dmanr); -+ if (chan->irq) -+ free_irq(chan->irq, chan->irq_dev); -+ -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ chan->dev_id = -1; -+} -+ -+void jz_set_dma_dest_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_DWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCMD_DWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_DWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_DWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_src_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_SWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCMD_SWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_SWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_SWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_block_size(int dmanr, int nbyte) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_DS_MASK; -+ switch (nbyte) { -+ case 1: -+ chan->mode |= DMAC_DCMD_DS_8BIT; -+ break; -+ case 2: -+ chan->mode |= DMAC_DCMD_DS_16BIT; -+ break; -+ case 4: -+ chan->mode |= DMAC_DCMD_DS_32BIT; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_DS_16BYTE; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_DS_32BYTE; -+ break; -+ } -+} -+ -+unsigned int jz_get_dma_command(int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ return chan->mode; -+} -+ -+/** -+ * jz_set_dma_mode - do the raw settings for the specified DMA channel -+ * @dmanr: the specified DMA channel -+ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -+ * @dma_mode: dma raw mode -+ * @dma_source: dma raw request source -+ * @fifo_addr: dma raw device fifo address -+ * -+ * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call -+ * jz_set_dma_mode() rather than set_dma_mode() if you work with -+ * and external request dma device. -+ * -+ * NOTE: Don not dynamically allocate dma channel if one external request -+ * dma device will occupy this channel. -+*/ -+int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -+ unsigned int dma_mode, unsigned int dma_source, -+ unsigned int fifo_addr) -+{ -+ int dev_id, i; -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > MAX_DMA_NUM) -+ return -ENODEV; -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == MAX_DMA_NUM) -+ return -ENODEV; -+ -+ chan = &jz_dma_table[dmanr]; -+ dev_id = chan->dev_id; -+ if (dev_id > 0) { -+ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -+ __FUNCTION__, dmanr); -+ return -ENODEV; -+ } -+ -+ /* clone it from the dynamically allocated. */ -+ if (i != dmanr) { -+ chan->irq = jz_dma_table[i].irq; -+ chan->irq_dev = jz_dma_table[i].irq_dev; -+ chan->dev_str = jz_dma_table[i].dev_str; -+ jz_dma_table[i].irq = 0; -+ jz_dma_table[i].irq_dev = NULL; -+ jz_dma_table[i].dev_id = -1; -+ } -+ chan->dev_id = DMA_ID_RAW_SET; -+ chan->io = dmanr; -+ chan->fifo_addr = fifo_addr; -+ chan->mode = dma_mode; -+ chan->source = dma_source; -+ -+ set_dma_mode(dmanr, dma_mode); -+ -+ return dmanr; -+} -+ -+void enable_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+ REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ -+ __dmac_enable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_enable_irq(dmanr); -+} -+ -+#define DMA_DISABLE_POLL 0x10000 -+ -+void disable_dma(unsigned int dmanr) -+{ -+ int i; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ if (!__dmac_channel_enabled(dmanr)) -+ return; -+ -+ for (i = 0; i < DMA_DISABLE_POLL; i++) -+ if (__dmac_channel_transmit_end_detected(dmanr)) -+ break; -+#if 0 -+ if (i == DMA_DISABLE_POLL) -+ printk(KERN_INFO "disable_dma: poll expired!\n"); -+#endif -+ -+ __dmac_disable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_disable_irq(dmanr); -+} -+ -+/* Note: DMA_MODE_MASK is simulated by sw */ -+void set_dma_mode(unsigned int dmanr, unsigned int mode) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else { -+ printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ } -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+} -+ -+void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) -+{ -+ unsigned int mode; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ mode = chan->mode & DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -+ REG_DMAC_DTAR(chan->io) = phyaddr; -+ } else if (mode == DMA_MODE_WRITE) { -+ REG_DMAC_DSAR(chan->io) = phyaddr; -+ REG_DMAC_DTAR(chan->io) = chan->fifo_addr; -+ } else -+ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -+} -+ -+void set_dma_count(unsigned int dmanr, unsigned int bytecnt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ unsigned int ds; -+ -+ if (!chan) -+ return; -+ -+ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -+ REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count -+} -+ -+unsigned int get_dma_residue(unsigned int dmanr) -+{ -+ unsigned int count, ds; -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ -+ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -+ count = REG_DMAC_DTCR(chan->io); -+ count = count * dma_ds[ds]; -+ -+ return count; -+} -+ -+void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case AFMT_U8: -+ /* burst mode : 32BIT */ -+ break; -+ case AFMT_S16_LE: -+ /* burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else -+ printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case 8: -+ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -+ break; -+ case 16: -+ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else -+ printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+#undef JZ4740_DMAC_TEST_ENABLE -+ -+#ifdef JZ4740_DMAC_TEST_ENABLE -+ -+/* -+ * DMA test: external address <--> external address -+ */ -+#define TEST_DMA_SIZE 16*1024 -+ -+static jz_dma_desc *dma_desc; -+ -+static int dma_chan; -+static dma_addr_t dma_desc_phys_addr; -+static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; -+ -+static int dma_check_result(void *src, void *dst, int size) -+{ -+ unsigned int addr1, addr2, i, err = 0; -+ -+ addr1 = (unsigned int)src; -+ addr2 = (unsigned int)dst; -+ -+ for (i = 0; i < size; i += 4) { -+ if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { -+ err++; -+ printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); -+ } -+ addr1 += 4; -+ addr2 += 4; -+ } -+ printk("check DMA result err=%d\n", err); -+ return err; -+} -+ -+static void jz4740_dma_irq(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ printk("jz4740_dma_irq %d\n", irq); -+ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ -+ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -+ printk("DMA HALT\n"); -+ __dmac_channel_clear_transmit_halt(dma_chan); -+ } -+ -+ if (__dmac_channel_address_error_detected(dma_chan)) { -+ printk("DMA ADDR ERROR\n"); -+ __dmac_channel_clear_address_error(dma_chan); -+ } -+ -+ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -+ printk("DMA DESC INVALID\n"); -+ __dmac_channel_clear_descriptor_invalid(dma_chan); -+ } -+ -+ if (__dmac_channel_count_terminated_detected(dma_chan)) { -+ printk("DMA CT\n"); -+ __dmac_channel_clear_count_terminated(dma_chan); -+ } -+ -+ if (__dmac_channel_transmit_end_detected(dma_chan)) { -+ printk("DMA TT\n"); -+ __dmac_channel_clear_transmit_end(dma_chan); -+ dump_jz_dma_channel(dma_chan); -+ dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); -+ } -+ -+ /* free buffers */ -+ printk("free DMA buffers\n"); -+ free_pages(dma_src_addr, 2); -+ free_pages(dma_dst_addr, 2); -+ -+ if (dma_desc) -+ free_pages((unsigned int)dma_desc, 0); -+ -+ /* free dma */ -+ jz_free_dma(dma_chan); -+} -+ -+void dma_nodesc_test(void) -+{ -+ unsigned int addr, i; -+ -+ printk("dma_nodesc_test\n"); -+ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq, -+ SA_INTERRUPT, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq failed\n"); -+ return; -+ } -+ -+ printk("Requested DMA channel = %d\n", dma_chan); -+ -+ /* Allocate DMA buffers */ -+ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ -+ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -+ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -+ -+ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -+ -+ /* Prepare data for source buffer */ -+ addr = (unsigned int)dma_src_addr; -+ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -+ *(volatile unsigned int *)addr = addr; -+ addr += 4; -+ } -+ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -+ -+ /* Init target buffer */ -+ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -+ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -+ -+ /* Init DMA module */ -+ printk("Starting DMA\n"); -+ REG_DMAC_DMACR = 0; -+ REG_DMAC_DCCSR(dma_chan) = 0; -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -+ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -+ REG_DMAC_DTCR(dma_chan) = 512; -+ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ -+ -+ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -+} -+ -+void dma_desc_test(void) -+{ -+ unsigned int next, addr, i; -+ static jz_dma_desc *desc; -+ -+ printk("dma_desc_test\n"); -+ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq, -+ SA_INTERRUPT, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq failed\n"); -+ return; -+ } -+ -+ printk("Requested DMA channel = %d\n", dma_chan); -+ -+ /* Allocate DMA buffers */ -+ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ -+ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -+ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -+ -+ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -+ -+ /* Prepare data for source buffer */ -+ addr = (unsigned int)dma_src_addr; -+ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -+ *(volatile unsigned int *)addr = addr; -+ addr += 4; -+ } -+ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -+ -+ /* Init target buffer */ -+ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -+ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -+ -+ /* Allocate DMA descriptors */ -+ dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); -+ dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); -+ -+ printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); -+ -+ /* Setup DMA descriptors */ -+ desc = dma_desc; -+ next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr; /* DMA target address */ -+ desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ -+ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ -+ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; -+ desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ -+ desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ -+ -+ dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); -+ -+ /* Setup DMA descriptor address */ -+ REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; -+ -+ /* Setup request source */ -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ -+ /* Setup DMA channel control/status register */ -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -+ -+ /* Enable DMA */ -+ REG_DMAC_DMACR = DMAC_DMACR_DMAE; -+ -+ /* DMA doorbell set -- start DMA now ... */ -+ REG_DMAC_DMADBSR = 1 << dma_chan; -+ -+ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -+} -+ -+#endif -+ -+//EXPORT_SYMBOL_NOVERS(jz_dma_table); -+EXPORT_SYMBOL(jz_dma_table); -+EXPORT_SYMBOL(jz_request_dma); -+EXPORT_SYMBOL(jz_free_dma); -+EXPORT_SYMBOL(jz_set_dma_src_width); -+EXPORT_SYMBOL(jz_set_dma_dest_width); -+EXPORT_SYMBOL(jz_set_dma_block_size); -+EXPORT_SYMBOL(jz_set_dma_mode); -+EXPORT_SYMBOL(set_dma_mode); -+EXPORT_SYMBOL(jz_set_oss_dma); -+EXPORT_SYMBOL(jz_set_alsa_dma); -+EXPORT_SYMBOL(set_dma_addr); -+EXPORT_SYMBOL(set_dma_count); -+EXPORT_SYMBOL(get_dma_residue); -+EXPORT_SYMBOL(enable_dma); -+EXPORT_SYMBOL(disable_dma); -+EXPORT_SYMBOL(dump_jz_dma_channel); -diff --git a/arch/mips/jz4740/i2c.c b/arch/mips/jz4740/i2c.c -new file mode 100644 -index 0000000..3080fdf ---- /dev/null -+++ b/arch/mips/jz4740/i2c.c -@@ -0,0 +1,273 @@ -+/* -+ * linux/arch/mips/jz4740/i2c.c -+ * -+ * Jz4740 I2C routines. -+ * -+ * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* I2C protocol */ -+#define I2C_READ 1 -+#define I2C_WRITE 0 -+ -+#define TIMEOUT 1000 -+ -+/* -+ * I2C bus protocol basic routines -+ */ -+static int i2c_put_data(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (!__i2c_received_ack() && timeout) -+ timeout--; -+ -+ if (timeout) -+ return 0; -+ else -+ return -ETIMEDOUT; -+} -+ -+#ifdef CONFIG_JZ_TPANEL_ATA2508 -+static int i2c_put_data_nack(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (timeout--); -+ return 0; -+} -+#endif -+ -+static int i2c_get_data(unsigned char *data, int ack) -+{ -+ int timeout = TIMEOUT*10; -+ -+ if (!ack) -+ __i2c_send_nack(); -+ else -+ __i2c_send_ack(); -+ -+ while (__i2c_check_drf() == 0 && timeout) -+ timeout--; -+ -+ if (timeout) { -+ if (!ack) -+ __i2c_send_stop(); -+ *data = __i2c_read(); -+ __i2c_clear_drf(); -+ return 0; -+ } else -+ return -ETIMEDOUT; -+} -+ -+/* -+ * I2C interface -+ */ -+void i2c_open(void) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -+ __i2c_enable(); -+} -+ -+void i2c_close(void) -+{ -+ udelay(300); /* wait for STOP goes over. */ -+ __i2c_disable(); -+} -+ -+void i2c_setclk(unsigned int i2cclk) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -+} -+ -+int i2c_lseek(unsigned char device, unsigned char offset) -+{ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+ if (i2c_put_data(offset) < 0) -+ goto address_err; -+ return 0; -+ device_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+ address_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -+ __i2c_send_stop(); -+ return -EREMOTEIO; -+} -+ -+int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int timeout = 5; -+ -+L_try_again: -+ -+ if (timeout < 0) -+ goto L_timeout; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_werr; -+ if (i2c_put_data(address) < 0) -+ goto address_err; -+ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -+ goto device_rerr; -+ __i2c_send_ack(); /* Master sends ACK for continue reading */ -+ while (cnt) { -+ if (cnt == 1) { -+ if (i2c_get_data(buf, 0) < 0) -+ break; -+ } else { -+ if (i2c_get_data(buf, 1) < 0) -+ break; -+ } -+ cnt--; -+ buf++; -+ } -+ -+ __i2c_send_stop(); -+ return count - cnt; -+ device_rerr: -+ device_werr: -+ address_err: -+ timeout --; -+ __i2c_send_stop(); -+ goto L_try_again; -+ -+L_timeout: -+ __i2c_send_stop(); -+ printk("Read I2C device 0x%2x failed.\n", device); -+ return -ENODEV; -+} -+ -+int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int cnt_in_pg; -+ int timeout = 5; -+ unsigned char *tmpbuf; -+ unsigned char tmpaddr; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ -+ W_try_again: -+ if (timeout < 0) -+ goto W_timeout; -+ -+ cnt = count; -+ tmpbuf = (unsigned char *)buf; -+ tmpaddr = address; -+ -+ start_write_page: -+ cnt_in_pg = 0; -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+#ifdef CONFIG_JZ_TPANEL_ATA2508 -+ if (address == 0xff) { -+ if (i2c_put_data_nack(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data_nack(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ } -+ else { -+ -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ } -+#else -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+#endif -+ __i2c_send_stop(); -+ return count - cnt; -+ device_err: -+ address_err: -+ timeout--; -+ __i2c_send_stop(); -+ goto W_try_again; -+ -+ W_timeout: -+ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+} -+ -+EXPORT_SYMBOL(i2c_open); -+EXPORT_SYMBOL(i2c_close); -+EXPORT_SYMBOL(i2c_setclk); -+EXPORT_SYMBOL(i2c_read); -+EXPORT_SYMBOL(i2c_write); -diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c -new file mode 100644 -index 0000000..98543c2 ---- /dev/null -+++ b/arch/mips/jz4740/irq.c -@@ -0,0 +1,265 @@ -+/* -+ * linux/arch/mips/jz4740/irq.c -+ * -+ * JZ4740 interrupt routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * INTC irq type -+ */ -+ -+static void enable_intc_irq(unsigned int irq) -+{ -+ __intc_unmask_irq(irq); -+} -+ -+static void disable_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+} -+ -+static void mask_and_ack_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+ __intc_ack_irq(irq); -+} -+ -+static void end_intc_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_intc_irq(irq); -+ } -+} -+ -+static unsigned int startup_intc_irq(unsigned int irq) -+{ -+ enable_intc_irq(irq); -+ return 0; -+} -+ -+static void shutdown_intc_irq(unsigned int irq) -+{ -+ disable_intc_irq(irq); -+} -+ -+static struct irq_chip intc_irq_type = { -+ .typename = "INTC", -+ .startup = startup_intc_irq, -+ .shutdown = shutdown_intc_irq, -+ .enable = enable_intc_irq, -+ .disable = disable_intc_irq, -+ .ack = mask_and_ack_intc_irq, -+ .end = end_intc_irq, -+}; -+ -+/* -+ * GPIO irq type -+ */ -+ -+static void enable_gpio_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if (irq < (IRQ_GPIO_0 + 32)) { -+ intc_irq = IRQ_GPIO0; -+ } -+ else if (irq < (IRQ_GPIO_0 + 64)) { -+ intc_irq = IRQ_GPIO1; -+ } -+ else if (irq < (IRQ_GPIO_0 + 96)) { -+ intc_irq = IRQ_GPIO2; -+ } -+ else { -+ intc_irq = IRQ_GPIO3; -+ } -+ -+ enable_intc_irq(intc_irq); -+ __gpio_unmask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void disable_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void mask_and_ack_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+ __gpio_ack_irq(irq - IRQ_GPIO_0); -+} -+ -+static void end_gpio_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_gpio_irq(irq); -+ } -+} -+ -+static unsigned int startup_gpio_irq(unsigned int irq) -+{ -+ enable_gpio_irq(irq); -+ return 0; -+} -+ -+static void shutdown_gpio_irq(unsigned int irq) -+{ -+ disable_gpio_irq(irq); -+} -+ -+static struct irq_chip gpio_irq_type = { -+ .typename = "GPIO", -+ .startup = startup_gpio_irq, -+ .shutdown = shutdown_gpio_irq, -+ .enable = enable_gpio_irq, -+ .disable = disable_gpio_irq, -+ .ack = mask_and_ack_gpio_irq, -+ .end = end_gpio_irq, -+}; -+ -+/* -+ * DMA irq type -+ */ -+ -+static void enable_dma_irq(unsigned int irq) -+{ -+ __intc_unmask_irq(IRQ_DMAC); -+ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -+} -+ -+static void disable_dma_irq(unsigned int irq) -+{ -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void mask_and_ack_dma_irq(unsigned int irq) -+{ -+ __intc_ack_irq(IRQ_DMAC); -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void end_dma_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_dma_irq(irq); -+ } -+} -+ -+static unsigned int startup_dma_irq(unsigned int irq) -+{ -+ enable_dma_irq(irq); -+ return 0; -+} -+ -+static void shutdown_dma_irq(unsigned int irq) -+{ -+ disable_dma_irq(irq); -+} -+ -+static struct irq_chip dma_irq_type = { -+ .typename = "DMA", -+ .startup = startup_dma_irq, -+ .shutdown = shutdown_dma_irq, -+ .enable = enable_dma_irq, -+ .disable = disable_dma_irq, -+ .ack = mask_and_ack_dma_irq, -+ .end = end_dma_irq, -+}; -+ -+//---------------------------------------------------------------------- -+ -+void __init arch_init_irq(void) -+{ -+ int i; -+ -+ clear_c0_status(0xff04); /* clear ERL */ -+ set_c0_status(0x0400); /* set IP2 */ -+ -+ /* Set up INTC irq -+ */ -+ for (i = 0; i < 32; i++) { -+ disable_intc_irq(i); -+ irq_desc[i].chip = &intc_irq_type; -+ } -+ -+ /* Set up DMAC irq -+ */ -+ for (i = 0; i < NUM_DMA; i++) { -+ disable_dma_irq(IRQ_DMA_0 + i); -+ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -+ } -+ -+ /* Set up GPIO irq -+ */ -+ for (i = 0; i < NUM_GPIO; i++) { -+ disable_gpio_irq(IRQ_GPIO_0 + i); -+ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -+ } -+} -+ -+static int plat_real_irq(int irq) -+{ -+ switch (irq) { -+ case IRQ_GPIO0: -+ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -+ break; -+ case IRQ_GPIO1: -+ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -+ break; -+ case IRQ_GPIO2: -+ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -+ break; -+ case IRQ_GPIO3: -+ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -+ break; -+ case IRQ_DMAC: -+ irq = __dmac_get_irq() + IRQ_DMA_0; -+ break; -+ } -+ -+ return irq; -+} -+ -+asmlinkage void plat_irq_dispatch(void) -+{ -+ int irq = 0; -+ static unsigned long intc_ipr = 0; -+ -+ intc_ipr |= REG_INTC_IPR; -+ -+ if (!intc_ipr) return; -+ -+ irq = ffs(intc_ipr) - 1; -+ intc_ipr &= ~(1< -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* OHCI (USB full speed host controller) */ -+static struct resource jz_usb_ohci_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -+ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UHC, -+ .end = IRQ_UHC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+/* The dmamask must be set for OHCI to work */ -+static u64 ohci_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_ohci_device = { -+ .name = "jz-ohci", -+ .id = 0, -+ .dev = { -+ .dma_mask = &ohci_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -+ .resource = jz_usb_ohci_resources, -+}; -+ -+/*** LCD controller ***/ -+static struct resource jz_lcd_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(LCD_BASE), -+ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_LCD, -+ .end = IRQ_LCD, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_lcd_dmamask = ~(u32)0; -+ -+static struct platform_device jz_lcd_device = { -+ .name = "jz-lcd", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_lcd_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_lcd_resources), -+ .resource = jz_lcd_resources, -+}; -+ -+/* UDC (USB gadget controller) */ -+static struct resource jz_usb_gdt_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UDC_BASE), -+ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UDC, -+ .end = IRQ_UDC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 udc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_gdt_device = { -+ .name = "jz-udc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &udc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -+ .resource = jz_usb_gdt_resources, -+}; -+ -+/** MMC/SD controller **/ -+static struct resource jz_mmc_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(MSC_BASE), -+ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_MSC, -+ .end = IRQ_MSC, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_mmc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_mmc_device = { -+ .name = "jz-mmc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_mmc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_mmc_resources), -+ .resource = jz_mmc_resources, -+}; -+ -+/** I2C controller **/ -+static struct resource jz_i2c_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(I2C_BASE), -+ .end = CPHYSADDR(I2C_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_I2C, -+ .end = IRQ_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_i2c_dmamask = ~(u32)0; -+ -+static struct platform_device jz_i2c_device = { -+ .name = "jz_i2c", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_i2c_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_i2c_resources), -+ .resource = jz_i2c_resources, -+}; -+ -+/* All */ -+static struct platform_device *jz_platform_devices[] __initdata = { -+ &jz_usb_ohci_device, -+ &jz_lcd_device, -+ &jz_usb_gdt_device, -+ &jz_mmc_device, -+ &jz_i2c_device, -+}; -+ -+static int __init jz_platform_init(void) -+{ -+ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -+} -+ -+arch_initcall(jz_platform_init); -diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c -new file mode 100644 -index 0000000..2c6cd83 ---- /dev/null -+++ b/arch/mips/jz4740/pm.c -@@ -0,0 +1,462 @@ -+/* -+ * linux/arch/mips/jz4740/common/pm.c -+ * -+ * JZ4740 Power Management Routines -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+ -+#define GPIO_WAKEUP 125 /* set SW7(GPIO 125) as WAKEUP key */ -+ -+/* -+ * __gpio_as_sleep set all pins to pull-disable, and set all pins as input -+ * except sdram, nand flash pins and the pins which can be used as CS1_N -+ * to CS4_N for chip select. -+ */ -+#define __gpio_as_sleep() \ -+do { \ -+ REG_GPIO_PXFUNC(1) = ~0x9ff9ffff; \ -+ REG_GPIO_PXSELC(1) = ~0x9ff9ffff; \ -+ REG_GPIO_PXDIRC(1) = ~0x9ff9ffff; \ -+ REG_GPIO_PXPES(1) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(2) = ~0x37000000; \ -+ REG_GPIO_PXSELC(2) = ~0x37000000; \ -+ REG_GPIO_PXDIRC(2) = ~0x37000000; \ -+ REG_GPIO_PXPES(2) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(3) = 0xffffffff; \ -+ REG_GPIO_PXSELC(3) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(3) = 0xffffffff; \ -+ REG_GPIO_PXPES(3) = 0xffffffff; \ -+} while (0) -+ -+static int jz_pm_do_hibernate(void) -+{ -+ printk("Put CPU into hibernate mode.\n"); -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* -+ * RTC Wakeup or 1Hz interrupt can be enabled or disabled -+ * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). -+ */ -+ -+ /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); -+ -+ /* Set reset pin low-level assertion time after wakeup: must > 60ms */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ -+ -+ /* Scratch pad register to be reserved */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HSPR = 0x12345678; -+ -+ /* clear wakeup status register */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HWRSR = 0x0; -+ -+ /* Put CPU to power down mode */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HCR = RTC_HCR_PD; -+ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ while(1); -+ -+ /* We can't get here */ -+ return 0; -+} -+ -+/* NOTES: -+ * 1: Pins that are floated (NC) should be set as input and pull-enable. -+ * 2: Pins that are pull-up or pull-down by outside should be set as input -+ * and pull-disable. -+ * 3: Pins that are connected to a chip except sdram and nand flash -+ * should be set as input and pull-disable, too. -+ */ -+static void jz_board_do_sleep(unsigned long *ptr) -+{ -+ unsigned char i; -+ -+ /* Print messages of GPIO registers for debug */ -+ for(i=0;i<4;i++) { -+ dprintk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ -+ REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ -+ REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); -+ } -+ -+ /* Save GPIO registers */ -+ for(i = 1; i < 4; i++) { -+ *ptr++ = REG_GPIO_PXFUN(i); -+ *ptr++ = REG_GPIO_PXSEL(i); -+ *ptr++ = REG_GPIO_PXDIR(i); -+ *ptr++ = REG_GPIO_PXPE(i); -+ *ptr++ = REG_GPIO_PXIM(i); -+ *ptr++ = REG_GPIO_PXDAT(i); -+ *ptr++ = REG_GPIO_PXTRG(i); -+ } -+ -+ /* -+ * Set all pins to pull-disable, and set all pins as input except -+ * sdram, nand flash pins and the pins which can be used as CS1_N -+ * to CS4_N for chip select. -+ */ -+ __gpio_as_sleep(); -+ -+ /* -+ * Set proper status for GPB25 to GPB28 which can be used as CS1_N to CS4_N. -+ * Keep the pins' function used for chip select(CS) here according to your -+ * system to avoid chip select crashing with sdram when resuming from sleep mode. -+ */ -+ -+#if defined(CONFIG_JZ4740_PAVO) -+ /* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */ -+ -+ /* GPB26/CS2_N is connected to nand flash, needn't be changed. */ -+ -+ /* GPB27/CS3_N is used as EXT_INT for CS8900 on debug board, it should be set as input.*/ -+ __gpio_as_input(32+27); -+ -+ /* GPB28/CS4_N is used as cs8900's chip select, shouldn't be changed. */ -+#endif -+ -+ /* -+ * Enable pull for NC pins here according to your system -+ */ -+ -+#if defined(CONFIG_JZ4740_PAVO) -+ /* GPB30-27 <-> J1: WE_N RD_N CS4_N EXT_INT */ -+ for(i=27;i<31;i++) { -+ __gpio_enable_pull(32+i); -+ } -+ -+ /* GPC27<-> WAIT_N */ -+ __gpio_enable_pull(32*2+27); -+ -+ /* GPD16<->SD_WP; GPD13-10<->MSC_D0-3; GPD9<->MSC_CMD; GPD8<->MSC_CLK */ -+ __gpio_enable_pull(32*3+16); -+ for(i=8;i<14;i++) { -+ __gpio_enable_pull(32*3+i); -+ } -+#endif -+ -+ /* -+ * If you must set some GPIOs as output to high level or low level, -+ * you can set them here, using: -+ * __gpio_as_output(n); -+ * __gpio_set_pin(n); or __gpio_clear_pin(n); -+ */ -+ -+#if defined(CONFIG_JZ4740_PAVO) -+ /* GPD16 which is used as AMPEN_N should be set to high to disable audio amplifier */ -+ __gpio_set_pin(32*3+4); -+#endif -+ -+#ifdef DEBUG -+ /* Keep uart0 function for printing debug message */ -+ __gpio_as_uart0(); -+ -+ /* Print messages of GPIO registers for debug */ -+ for(i=0;i<4;i++) { -+ dprintk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ -+ REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ -+ REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); -+ } -+#endif -+} -+ -+static void jz_board_do_resume(unsigned long *ptr) -+{ -+ unsigned char i; -+ -+ /* Restore GPIO registers */ -+ for(i = 1; i < 4; i++) { -+ REG_GPIO_PXFUNS(i) = *ptr; -+ REG_GPIO_PXFUNC(i) = ~(*ptr++); -+ -+ REG_GPIO_PXSELS(i) = *ptr; -+ REG_GPIO_PXSELC(i) = ~(*ptr++); -+ -+ REG_GPIO_PXDIRS(i) = *ptr; -+ REG_GPIO_PXDIRC(i) = ~(*ptr++); -+ -+ REG_GPIO_PXPES(i) = *ptr; -+ REG_GPIO_PXPEC(i) = ~(*ptr++); -+ -+ REG_GPIO_PXIMS(i)=*ptr; -+ REG_GPIO_PXIMC(i)=~(*ptr++); -+ -+ REG_GPIO_PXDATS(i)=*ptr; -+ REG_GPIO_PXDATC(i)=~(*ptr++); -+ -+ REG_GPIO_PXTRGS(i)=*ptr; -+ REG_GPIO_PXTRGC(i)=~(*ptr++); -+ } -+ -+ /* Print messages of GPIO registers for debug */ -+ for(i=0;i<4;i++) { -+ dprintk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ -+ REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ -+ REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); -+ } -+} -+ -+ -+ -+static int jz_pm_do_sleep(void) -+{ -+ unsigned long delta; -+ unsigned long nfcsr = REG_EMC_NFCSR; -+ unsigned long scr = REG_CPM_SCR; -+ unsigned long imr = REG_INTC_IMR; -+ unsigned long sadc = REG_SADC_ENA; -+ unsigned long sleep_gpio_save[7*3]; -+ -+ printk("Put CPU into sleep mode.\n"); -+ -+ /* Preserve current time */ -+ delta = xtime.tv_sec - REG_RTC_RSR; -+ -+ /* Disable nand flash */ -+ REG_EMC_NFCSR = ~0xff; -+ -+ /* stop sadc */ -+ REG_SADC_ENA &= ~0x7; -+ while((REG_SADC_ENA & 0x7) != 0); -+ udelay(100); -+ -+ /*stop udc and usb*/ -+ REG_CPM_SCR &= ~( 1<<6 | 1<<7); -+ REG_CPM_SCR |= 0<<6 | 1<<7; -+ -+ /* Sleep on-board modules */ -+ jz_board_do_sleep(sleep_gpio_save); -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* Just allow following interrupts to wakeup the system. -+ * Note: modify this according to your system. -+ */ -+ -+ /* enable RTC alarm */ -+ __intc_unmask_irq(IRQ_RTC); -+#if 0 -+ /* make system wake up after n seconds by RTC alarm */ -+ unsigned int v, n; -+ n = 10; -+ while (!__rtc_write_ready()); -+ __rtc_enable_alarm(); -+ while (!__rtc_write_ready()); -+ __rtc_enable_alarm_irq(); -+ while (!__rtc_write_ready()); -+ v = __rtc_get_second(); -+ while (!__rtc_write_ready()); -+ __rtc_set_alarm_second(v+n); -+#endif -+ -+ /* WAKEUP key */ -+ __gpio_as_irq_rise_edge(GPIO_WAKEUP); -+ __gpio_unmask_irq(GPIO_WAKEUP); -+ __intc_unmask_irq(IRQ_GPIO3); /* IRQ_GPIOn depends on GPIO_WAKEUP */ -+ -+ /* Enter SLEEP mode */ -+ REG_CPM_LCR &= ~CPM_LCR_LPM_MASK; -+ REG_CPM_LCR |= CPM_LCR_LPM_SLEEP; -+ __asm__(".set\tmips3\n\t" -+ "wait\n\t" -+ ".set\tmips0"); -+ -+ /* Restore to IDLE mode */ -+ REG_CPM_LCR &= ~CPM_LCR_LPM_MASK; -+ REG_CPM_LCR |= CPM_LCR_LPM_IDLE; -+ -+ /* Restore nand flash control register */ -+ REG_EMC_NFCSR = nfcsr; -+ -+ /* Restore interrupts */ -+ REG_INTC_IMSR = imr; -+ REG_INTC_IMCR = ~imr; -+ -+ /* Restore sadc */ -+ REG_SADC_ENA = sadc; -+ -+ /* Resume on-board modules */ -+ jz_board_do_resume(sleep_gpio_save); -+ -+ /* Restore sleep control register */ -+ REG_CPM_SCR = scr; -+ -+ /* Restore current time */ -+ xtime.tv_sec = REG_RTC_RSR + delta; -+ -+ return 0; -+} -+ -+/* Put CPU to HIBERNATE mode */ -+int jz_pm_hibernate(void) -+{ -+ return jz_pm_do_hibernate(); -+} -+ -+#ifndef CONFIG_JZ_POWEROFF -+static irqreturn_t pm_irq_handler (int irq, void *dev_id) -+{ -+ return IRQ_HANDLED; -+} -+#endif -+ -+/* Put CPU to SLEEP mode */ -+int jz_pm_sleep(void) -+{ -+ int retval; -+ -+#ifndef CONFIG_JZ_POWEROFF -+ if ((retval = request_irq (IRQ_GPIO_0 + GPIO_WAKEUP, pm_irq_handler, IRQF_DISABLED, -+ "PM", NULL))) { -+ printk ("PM could not get IRQ for GPIO_WAKEUP\n"); -+ return retval; -+ } -+#endif -+ -+ pm_send_all(PM_SUSPEND, (void *)3); -+ retval = jz_pm_do_sleep(); -+ pm_send_all(PM_RESUME, (void *)0); -+ -+#ifndef CONFIG_JZ_POWEROFF -+ free_irq (IRQ_GPIO_0 + GPIO_WAKEUP, NULL); -+#endif -+ -+ return retval; -+} -+ -+#if 0 -+/* Deprecated ,was used by dpm */ -+void jz_pm_idle(void) -+{ -+ local_irq_disable(); -+ if (!need_resched()) { -+ local_irq_enable(); -+ cpu_wait(); -+ } -+} -+#endif -+ -+#ifdef CONFIG_SYSCTL -+ -+/* -+ * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6 -+ * when all the PM interfaces exist nicely. -+ */ -+#define CTL_PM_SUSPEND 1 -+#define CTL_PM_HIBERNATE 2 -+ -+/*---------------------------------------------------------------------------- -+ * Power Management sleep sysctl proc interface -+ * -+ * A write to /proc/sys/pm/suspend invokes this function -+ * which initiates a sleep. -+ *--------------------------------------------------------------------------*/ -+static int sysctl_jz_pm_sleep(struct ctl_table *ctl, int write, struct file * filp, -+ void __user *buffer, size_t *lenp, loff_t *ppos) -+{ -+ return jz_pm_sleep(); -+} -+ -+/*---------------------------------------------------------------------------- -+ * Power Management sleep sysctl proc interface -+ * -+ * A write to /proc/sys/pm/hibernate invokes this function -+ * which initiates a poweroff. -+ *--------------------------------------------------------------------------*/ -+static int sysctl_jz_pm_hibernate(struct ctl_table *ctl, int write, struct file * filp, -+ void __user *buffer, size_t *lenp, loff_t *ppos) -+{ -+ return jz_pm_hibernate(); -+} -+ -+static struct ctl_table pm_table[] = -+{ -+ { -+ .ctl_name = CTL_UNNUMBERED, -+ .procname = "suspend", -+ .data = NULL, -+ .maxlen = 0, -+ .mode = 0600, -+ .proc_handler = &sysctl_jz_pm_sleep, -+ }, -+ { -+ .ctl_name = CTL_UNNUMBERED, -+ .procname = "hibernate", -+ .data = NULL, -+ .maxlen = 0, -+ .mode = 0600, -+ .proc_handler = &sysctl_jz_pm_hibernate, -+ }, -+ { .ctl_name = 0} -+}; -+ -+static struct ctl_table pm_dir_table[] = -+{ -+ { -+ .ctl_name = CTL_UNNUMBERED, -+ .procname = "pm", -+ .mode = 0555, -+ .child = pm_table, -+ }, -+ { .ctl_name = 0} -+}; -+ -+#endif /* CONFIG_SYSCTL */ -+ -+/* -+ * Initialize power interface -+ */ -+static int __init jz_pm_init(void) -+{ -+ printk("Power Management for JZ\n"); -+ -+#ifdef CONFIG_SYSCTL -+ register_sysctl_table(pm_dir_table); -+#endif -+ -+ return 0; -+} -+ -+module_init(jz_pm_init); -+ -diff --git a/arch/mips/jz4740/proc.c b/arch/mips/jz4740/proc.c -new file mode 100644 -index 0000000..af48bee ---- /dev/null -+++ b/arch/mips/jz4740/proc.c -@@ -0,0 +1,887 @@ -+/* -+ * linux/arch/mips/jz4740/proc.c -+ * -+ * /proc/jz/ procfs for jz4740 on-chip modules. -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#define DEBUG 1 -+#undef DEBUG -+ -+/* Define this to reserve total 4MB contineous physical memory for IPU. -+ * MPlayer will use IPU to optimize the decoding process. -+ * -+ * If you do not want to run the MPlayer, you can comment it. -+ */ -+#define CONFIG_RESERVE_IPU_MEM 1 -+ -+struct proc_dir_entry *proc_jz_root; -+ -+ -+/* -+ * EMC Modules -+ */ -+static int emc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); -+ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); -+ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -+ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -+ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -+ return len; -+} -+ -+/* -+ * Power Manager Module -+ */ -+static int pmc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned long lcr = REG_CPM_LCR; -+ unsigned long clkgr = REG_CPM_CLKGR; -+ -+ len += sprintf (page+len, "Low Power Mode : %s\n", -+ ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? -+ "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? -+ "SLEEP" : "HIBERNATE")); -+ len += sprintf (page+len, "Doze Mode : %s\n", -+ (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); -+ if (lcr & CPM_LCR_DOZE_ON) -+ len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); -+ len += sprintf (page+len, "IPU : %s\n", -+ (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); -+ len += sprintf (page+len, "DMAC : %s\n", -+ (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); -+ len += sprintf (page+len, "UHC : %s\n", -+ (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); -+ len += sprintf (page+len, "UDC : %s\n", -+ (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); -+ len += sprintf (page+len, "LCD : %s\n", -+ (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); -+ len += sprintf (page+len, "CIM : %s\n", -+ (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); -+ len += sprintf (page+len, "SADC : %s\n", -+ (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); -+ len += sprintf (page+len, "MSC : %s\n", -+ (clkgr & CPM_CLKGR_MSC) ? "stopped" : "running"); -+ len += sprintf (page+len, "AIC1 : %s\n", -+ (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); -+ len += sprintf (page+len, "AIC2 : %s\n", -+ (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); -+ len += sprintf (page+len, "SSI : %s\n", -+ (clkgr & CPM_CLKGR_SSI) ? "stopped" : "running"); -+ len += sprintf (page+len, "I2C : %s\n", -+ (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); -+ len += sprintf (page+len, "RTC : %s\n", -+ (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); -+ len += sprintf (page+len, "TCU : %s\n", -+ (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART1 : %s\n", -+ (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART0 : %s\n", -+ (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); -+ return len; -+} -+ -+static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+/* -+ * Clock Generation Module -+ */ -+#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 -+#define TO_KHZ(x) (x/1000),(x%1000)/10 -+ -+static int cgm_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ -+ unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ -+ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int od[4] = {1, 2, 2, 4}; -+ -+ len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); -+ len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); -+ len += sprintf (page+len, "PLL : %s\n", -+ (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); -+ len += sprintf (page+len, "m:n:o : %d:%d:%d\n", -+ __cpm_get_pllm() + 2, -+ __cpm_get_plln() + 2, -+ od[__cpm_get_pllod()] -+ ); -+ len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", -+ div[__cpm_get_cdiv()], -+ div[__cpm_get_hdiv()], -+ div[__cpm_get_mdiv()], -+ div[__cpm_get_pdiv()] -+ ); -+ len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); -+ len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); -+ len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); -+ len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); -+ len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); -+ len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); -+ len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); -+ len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); -+ len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); -+ len += sprintf (page+len, "MSCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk())); -+ len += sprintf (page+len, "EXTALCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); -+ len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); -+ -+ return len; -+} -+ -+static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+ -+/* -+ * UDC hotplug -+ */ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+extern int jz_udc_active; /* defined in drivers/char/jzchar/jz_udc_hotplug.c */ -+#endif -+ -+#ifndef GPIO_UDC_HOTPLUG -+#define GPIO_UDC_HOTPLUG 86 -+#endif -+ -+static int udc_read_proc(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+ if (__gpio_get_pin(GPIO_UDC_HOTPLUG)) { -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ -+ /* Cable has connected, wait for disconnection. */ -+ __gpio_as_irq_fall_edge(GPIO_UDC_HOTPLUG); -+ -+ if (jz_udc_active) -+ len += sprintf (page+len, "CONNECT_CABLE\n"); -+ else -+ len += sprintf (page+len, "CONNECT_POWER\n"); -+#else -+ len += sprintf (page+len, "CONNECT\n"); -+#endif -+ } -+ else { -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ /* Cable has disconnected, wait for connection. */ -+ __gpio_as_irq_rise_edge(GPIO_UDC_HOTPLUG); -+#endif -+ -+ len += sprintf (page+len, "REMOVE\n"); -+ } -+ -+ return len; -+} -+ -+/* -+ * MMC/SD hotplug -+ */ -+ -+#ifndef MSC_HOTPLUG_PIN -+#define MSC_HOTPLUG_PIN 90 -+#endif -+ -+static int mmc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+#if defined(CONFIG_JZ4740_LYRA) -+ if (!(__gpio_get_pin(MSC_HOTPLUG_PIN))) -+#else -+ if (__gpio_get_pin(MSC_HOTPLUG_PIN)) -+#endif -+ len += sprintf (page+len, "REMOVE\n"); -+ else -+ len += sprintf (page+len, "INSERT\n"); -+ -+ return len; -+} -+ -+#ifdef CONFIG_RESERVE_IPU_MEM -+ -+/* USAGE: -+ * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. -+ * echo FF > /proc/jz/ipu // 255, free all buffer -+ * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx -+ * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) -+ * echo 0 > /proc/jz/ipu // debug, print ipu_buf -+ * od -X /proc/jz/ipu // read mem addr -+ */ -+ -+typedef struct _ipu_buf { -+ unsigned int addr; /* phys addr */ -+ unsigned int page_shift; -+} ipu_buf_t; -+ -+#define IPU_BUF_MAX 4 /* 4 buffers */ -+ -+static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -+static int ipu_buf_cnt = 0; -+static unsigned char g_asid=0; -+ -+extern void local_flush_tlb_all(void); -+ -+/* CP0 hazard avoidance. */ -+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ -+ "nop; nop; nop; nop; nop; nop;\n\t" \ -+ ".set reorder\n\t") -+void show_tlb(void) -+{ -+#define ASID_MASK 0xFF -+ -+ unsigned long flags; -+ unsigned int old_ctx; -+ unsigned int entry; -+ unsigned int entrylo0, entrylo1, entryhi; -+ unsigned int pagemask; -+ -+ local_irq_save(flags); -+ -+ /* Save old context */ -+ old_ctx = (read_c0_entryhi() & 0xff); -+ -+ printk("TLB content:\n"); -+ entry = 0; -+ while(entry < 32) { -+ write_c0_index(entry); -+ BARRIER; -+ tlb_read(); -+ BARRIER; -+ entryhi = read_c0_entryhi(); -+ entrylo0 = read_c0_entrylo0(); -+ entrylo1 = read_c0_entrylo1(); -+ pagemask = read_c0_pagemask(); -+ printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); -+ printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); -+ printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); -+ -+ printk("\t\tpagemask=0x%08x", pagemask); -+ printk("\tentryhi=0x%08x\n", entryhi); -+ printk("\t\tentrylo0=0x%08x", entrylo0); -+ printk("\tentrylo1=0x%08x\n", entrylo1); -+ -+ entry++; -+ } -+ BARRIER; -+ write_c0_entryhi(old_ctx); -+ -+ local_irq_restore(flags); -+} -+ -+static void ipu_add_wired_entry(unsigned long pid, -+ unsigned long entrylo0, unsigned long entrylo1, -+ unsigned long entryhi, unsigned long pagemask) -+{ -+ unsigned long flags; -+ unsigned long wired; -+ unsigned long old_pagemask; -+ unsigned long old_ctx; -+ struct task_struct *g, *p; -+ -+ /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ -+ wired = read_c0_wired(); -+ if (wired) return; -+ -+ do_each_thread(g, p) { -+ if (p->pid == pid ) -+ g_asid = p->mm->context[0]; -+ } while_each_thread(g, p); -+ -+ local_irq_save(flags); -+ -+ entrylo0 = entrylo0 >> 6; /* PFN */ -+ entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ -+ -+ /* Save old context and create impossible VPN2 value */ -+ old_ctx = read_c0_entryhi() & 0xff; -+ old_pagemask = read_c0_pagemask(); -+ write_c0_wired(wired + 1); -+ write_c0_index(wired); -+ BARRIER; -+ entryhi &= ~0xff; /* new add, 20070906 */ -+ entryhi |= g_asid; /* new add, 20070906 */ -+// entryhi |= old_ctx; /* new add, 20070906 */ -+ write_c0_pagemask(pagemask); -+ write_c0_entryhi(entryhi); -+ write_c0_entrylo0(entrylo0); -+ write_c0_entrylo1(entrylo1); -+ BARRIER; -+ tlb_write_indexed(); -+ BARRIER; -+ -+ write_c0_entryhi(old_ctx); -+ BARRIER; -+ write_c0_pagemask(old_pagemask); -+ local_flush_tlb_all(); -+ local_irq_restore(flags); -+#if defined(DEBUG) -+ printk("\nold_ctx=%03d\n", old_ctx); -+ -+ show_tlb(); -+#endif -+} -+ -+static void ipu_del_wired_entry( void ) -+{ -+ unsigned long flags; -+ unsigned long wired; -+ -+ /* Free all lock entry */ -+ local_irq_save(flags); -+ wired = read_c0_wired(); -+ if (wired) -+ write_c0_wired(0); -+ local_irq_restore(flags); -+} -+ -+static inline void ipu_buf_get( unsigned int page_shift ) -+{ -+ unsigned char * virt_addr; -+ int i; -+ for ( i=0; i< IPU_BUF_MAX; ++i ) { -+ if ( ipu_buf[i].addr == 0 ) { -+ break; -+ } -+ } -+ -+ if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { -+ printk("Error, no free ipu buffer.\n"); -+ return ; -+ } -+ -+ virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ -+ if ( virt_addr ) { -+ ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); -+ ipu_buf[ipu_buf_cnt].page_shift = page_shift; -+ -+ for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ -+ printk("no free buffer.\n"); -+ *pint = 0; -+ } -+ else -+ *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ -+ len += sizeof(unsigned int); -+ -+#if defined(DEBUG) -+ show_tlb(); -+#endif -+ return len; -+ -+} -+ -+static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int val ; -+ int cnt,i; -+ char buf[12]; -+ unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -+#if defined(DEBUG) -+ printk("ipu write count=%u\n", count); -+#endif -+ if (count == (8*5+1)) { -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*0, 8); -+ pid = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*1, 8); -+ entrylo0 = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*2, 8); -+ entrylo1 = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*3, 8); -+ entryhi = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*4, 8); -+ pagemask = simple_strtoul(buf, 0, 16); -+ -+#if defined(DEBUG) -+ printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", -+ pid, entrylo0, entrylo1, entryhi, pagemask); -+#endif -+ ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); -+ return 41; -+ } else if ( count <= 8+1 ) { -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer, 8); -+ val = simple_strtoul(buf, 0, 16); -+ } else if (count == 44) { -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer, 10); -+ pid = simple_strtoul(buf, 0, 16); -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 11, 10); -+ entryhi = simple_strtoul(buf, 0, 16);//vaddr -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 22, 10); -+ entrylo0 = simple_strtoul(buf, 0, 16);//paddr -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 33, 10); -+ pagemask = simple_strtoul(buf, 0, 16); -+ pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ -+ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); -+ return 44; -+ } else { -+ printk("ipu write count error, count=%d\n.", (unsigned int)count); -+ return -1; -+ } -+ -+ /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ -+ if ( val == 0 ) { /* debug, print ipu_buf info */ -+ for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages -+ * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx -+ * echo FF > /proc/jz/ipu // FF, free all buffers -+ * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer -+ */ -+ -+//#define DEBUG_IMEM 1 -+ -+#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ -+ -+static unsigned int jz_imem_base; /* physical base address of ipu memory */ -+ -+static unsigned int allocated_phys_addr = 0; -+ -+/* -+ * Allocated buffer list -+ */ -+typedef struct imem_list { -+ unsigned int phys_start; /* physical start addr */ -+ unsigned int phys_end; /* physical end addr */ -+ struct imem_list *next; -+} imem_list_t; -+ -+static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ -+ -+#ifdef DEBUG_IMEM -+static void dump_imem_list(void) -+{ -+ struct imem_list *imem; -+ -+ printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); -+ imem = imem_list_head; -+ while (imem) { -+ printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); -+ imem = imem->next; -+ } -+} -+#endif -+ -+/* allocate 2^order pages inside the 4MB memory */ -+static int imem_alloc(unsigned int order) -+{ -+ int alloc_ok = 0; -+ unsigned int start, end; -+ unsigned int size = (1 << order) * PAGE_SIZE; -+ struct imem_list *imem, *imemn, *imemp; -+ -+ allocated_phys_addr = 0; -+ -+ start = jz_imem_base; -+ end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -+ -+ imem = imem_list_head; -+ while (imem) { -+ if ((imem->phys_start - start) >= size) { -+ /* we got a valid address range */ -+ alloc_ok = 1; -+ break; -+ } -+ -+ start = imem->phys_end + 1; -+ imem = imem->next; -+ } -+ -+ if (!alloc_ok) { -+ if ((end - start) >= size) -+ alloc_ok = 1; -+ } -+ -+ if (alloc_ok) { -+ end = start + size - 1; -+ allocated_phys_addr = start; -+ -+ /* add to imem_list, up sorted by phys_start */ -+ imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); -+ if (!imemn) { -+ return -ENOMEM; -+ } -+ imemn->phys_start = start; -+ imemn->phys_end = end; -+ imemn->next = NULL; -+ -+ if (!imem_list_head) -+ imem_list_head = imemn; -+ else { -+ imem = imemp = imem_list_head; -+ while (imem) { -+ if (start < imem->phys_start) { -+ break; -+ } -+ -+ imemp = imem; -+ imem = imem->next; -+ } -+ -+ if (imem == imem_list_head) { -+ imem_list_head = imemn; -+ imemn->next = imem; -+ } -+ else { -+ imemn->next = imemp->next; -+ imemp->next = imemn; -+ } -+ } -+ } -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+ return 0; -+} -+ -+static void imem_free(unsigned int phys_addr) -+{ -+ struct imem_list *imem, *imemp; -+ -+ imem = imemp = imem_list_head; -+ while (imem) { -+ if (phys_addr == imem->phys_start) { -+ if (imem == imem_list_head) { -+ imem_list_head = imem->next; -+ } -+ else { -+ imemp->next = imem->next; -+ } -+ -+ kfree(imem); -+ break; -+ } -+ -+ imemp = imem; -+ imem = imem->next; -+ } -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+} -+ -+static void imem_free_all(void) -+{ -+ struct imem_list *imem; -+ -+ imem = imem_list_head; -+ while (imem) { -+ kfree(imem); -+ imem = imem->next; -+ } -+ -+ imem_list_head = NULL; -+ -+ allocated_phys_addr = 0; -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+} -+ -+/* -+ * Return the allocated buffer address and the max order of free buffer -+ */ -+static int imem_read_proc(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int start_addr, end_addr, max_order, max_size; -+ struct imem_list *imem; -+ -+ unsigned int *tmp = (unsigned int *)(page + len); -+ -+ start_addr = jz_imem_base; -+ end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -+ -+ if (!imem_list_head) -+ max_size = end_addr - start_addr; -+ else { -+ max_size = 0; -+ imem = imem_list_head; -+ while (imem) { -+ if (max_size < (imem->phys_start - start_addr)) -+ max_size = imem->phys_start - start_addr; -+ -+ start_addr = imem->phys_end + 1; -+ imem = imem->next; -+ } -+ -+ if (max_size < (end_addr - start_addr)) -+ max_size = end_addr - start_addr; -+ } -+ -+ if (max_size > 0) { -+ max_order = get_order(max_size); -+ if (((1 << max_order) * PAGE_SIZE) > max_size) -+ max_order--; -+ } -+ else { -+ max_order = 0xffffffff; /* No any free buffer */ -+ } -+ -+ *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ -+ *tmp = max_order; /* max order of current free buffers */ -+ -+ len += 2 * sizeof(unsigned int); -+ -+ return len; -+} -+ -+static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int val; -+ -+ val = simple_strtoul(buffer, 0, 16); -+ -+ if (val == 0xff) { -+ /* free all memory */ -+ imem_free_all(); -+ ipu_del_wired_entry(); -+ } -+ else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { -+ /* allocate 2^val pages */ -+ imem_alloc(val); -+ } -+ else { -+ /* free buffer which phys_addr is val */ -+ imem_free(val); -+ } -+ -+ return count; -+} -+ -+#endif /* CONFIG_RESERVE_IPU_MEM */ -+ -+/* -+ * /proc/jz/xxx entry -+ * -+ */ -+static int __init jz_proc_init(void) -+{ -+ struct proc_dir_entry *res; -+#ifdef CONFIG_RESERVE_IPU_MEM -+ unsigned int virt_addr, i; -+#endif -+ -+ proc_jz_root = proc_mkdir("jz", 0); -+ -+ /* External Memory Controller */ -+ res = create_proc_entry("emc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = emc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* Power Management Controller */ -+ res = create_proc_entry("pmc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = pmc_read_proc; -+ res->write_proc = pmc_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Clock Generation Module */ -+ res = create_proc_entry("cgm", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = cgm_read_proc; -+ res->write_proc = cgm_write_proc; -+ res->data = NULL; -+ } -+ -+ /* udc hotplug */ -+ res = create_proc_entry("udc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = udc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* mmc hotplug */ -+ res = create_proc_entry("mmc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = mmc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+#ifdef CONFIG_RESERVE_IPU_MEM -+ /* Image process unit */ -+ res = create_proc_entry("ipu", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = ipu_read_proc; -+ res->write_proc = ipu_write_proc; -+ res->data = NULL; -+ } -+ -+ /* -+ * Reserve a 4MB memory for IPU on JZ4740. -+ */ -+ jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); -+ if (jz_imem_base) { -+ /* imem (IPU memory management) */ -+ res = create_proc_entry("imem", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = imem_read_proc; -+ res->write_proc = imem_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Set page reserved */ -+ virt_addr = jz_imem_base; -+ for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { -+ SetPageReserved(virt_to_page((void *)virt_addr)); -+ virt_addr += PAGE_SIZE; -+ } -+ -+ /* Convert to physical address */ -+ jz_imem_base = virt_to_phys((void *)jz_imem_base); -+ -+ printk("Total %dMB memory at 0x%x was reserved for IPU\n", -+ (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); -+ } -+#endif -+ -+ return 0; -+} -+ -+__initcall(jz_proc_init); -diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c -new file mode 100644 -index 0000000..4068939 ---- /dev/null -+++ b/arch/mips/jz4740/prom.c -@@ -0,0 +1,198 @@ -+/* -+ * -+ * BRIEF MODULE DESCRIPTION -+ * PROM library initialisation code, supports YAMON and U-Boot. -+ * -+ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * ppopov@mvista.com or source@mvista.com -+ * -+ * This file was derived from Carsten Langgaard's -+ * arch/mips/mips-boards/xx files. -+ * -+ * Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* #define DEBUG_CMDLINE */ -+ -+int prom_argc; -+char **prom_argv, **prom_envp; -+ -+char * prom_getcmdline(void) -+{ -+ return &(arcs_cmdline[0]); -+} -+ -+void prom_init_cmdline(void) -+{ -+ char *cp; -+ int actr; -+ -+ actr = 1; /* Always ignore argv[0] */ -+ -+ cp = &(arcs_cmdline[0]); -+ while(actr < prom_argc) { -+ strcpy(cp, prom_argv[actr]); -+ cp += strlen(prom_argv[actr]); -+ *cp++ = ' '; -+ actr++; -+ } -+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -+ --cp; -+ if (prom_argc > 1) -+ *cp = '\0'; -+ -+} -+ -+ -+char *prom_getenv(char *envname) -+{ -+#if 0 -+ /* -+ * Return a pointer to the given environment variable. -+ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -+ */ -+ -+ char **env = prom_envp; -+ int i = strlen(envname); -+ int yamon = (*env && strchr(*env, '=') == NULL); -+ -+ while (*env) { -+ if (yamon) { -+ if (strcmp(envname, *env++) == 0) -+ return *env; -+ } else { -+ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -+ return *env + i + 1; -+ } -+ env++; -+ } -+#endif -+ return NULL; -+} -+ -+inline unsigned char str2hexnum(unsigned char c) -+{ -+ if(c >= '0' && c <= '9') -+ return c - '0'; -+ if(c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ if(c >= 'A' && c <= 'F') -+ return c - 'A' + 10; -+ return 0; /* foo */ -+} -+ -+inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; -+ -+ for(i = 0; i < 6; i++) { -+ unsigned char num; -+ -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} -+ -+int get_ethernet_addr(char *ethernet_addr) -+{ -+ char *ethaddr_str; -+ -+ ethaddr_str = prom_getenv("ethaddr"); -+ if (!ethaddr_str) { -+ printk("ethaddr not set in boot prom\n"); -+ return -1; -+ } -+ str2eaddr(ethernet_addr, ethaddr_str); -+ -+#if 0 -+ { -+ int i; -+ -+ printk("get_ethernet_addr: "); -+ for (i=0; i<5; i++) -+ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -+ printk("%02x\n", *(ethernet_addr+i)); -+ } -+#endif -+ -+ return 0; -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init prom_init(void) -+{ -+ unsigned char *memsize_str; -+ unsigned long memsize; -+ -+ prom_argc = (int) fw_arg0; -+ prom_argv = (char **) fw_arg1; -+ prom_envp = (char **) fw_arg2; -+ -+ mips_machtype = MACH_INGENIC_JZ4740; -+ -+ prom_init_cmdline(); -+ memsize_str = prom_getenv("memsize"); -+ if (!memsize_str) { -+ memsize = 0x04000000; -+ } else { -+ memsize = simple_strtol(memsize_str, NULL, 0); -+ } -+ add_memory_region(0, memsize, BOOT_MEM_RAM); -+} -+ -+/* used by early printk */ -+void prom_putchar(char c) -+{ -+ volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR); -+ volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR); -+ -+ /* Wait for fifo to shift out some bytes */ -+ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -+ -+ *uart_tdr = (u8)c; -+} -+ -+const char *get_system_type(void) -+{ -+ return "JZ4740"; -+} -+ -+EXPORT_SYMBOL(prom_getcmdline); -+EXPORT_SYMBOL(get_ethernet_addr); -+EXPORT_SYMBOL(str2eaddr); -diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c -new file mode 100644 -index 0000000..83577d8 ---- /dev/null -+++ b/arch/mips/jz4740/reset.c -@@ -0,0 +1,46 @@ -+/* -+ * linux/arch/mips/jz4740/reset.c -+ * -+ * JZ4740 reset routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+void jz_restart(char *command) -+{ -+ printk("Restarting after 4 ms\n"); -+ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; -+ REG_WDT_TCNT = 0; -+ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ -+ REG_TCU_TSCR = TCU_TSSR_WDTSC; /* enable wdt clock */ -+ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ -+ while (1); -+} -+ -+void jz_halt(void) -+{ -+ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -+ -+ while (1) -+ __asm__(".set\tmips3\n\t" -+ "wait\n\t" -+ ".set\tmips0"); -+} -+ -+void jz_power_off(void) -+{ -+ jz_halt(); -+} -diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c -new file mode 100644 -index 0000000..e19f767 ---- /dev/null -+++ b/arch/mips/jz4740/setup.c -@@ -0,0 +1,182 @@ -+/* -+ * linux/arch/mips/jz4740/common/setup.c -+ * -+ * JZ4740 common setup routines. -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_PC_KEYB -+#include -+#endif -+ -+jz_clocks_t jz_clocks; -+ -+extern char * __init prom_getcmdline(void); -+extern void __init jz_board_setup(void); -+extern void jz_restart(char *); -+extern void jz_halt(void); -+extern void jz_power_off(void); -+extern void jz_time_init(void); -+ -+static void __init sysclocks_setup(void) -+{ -+#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ -+ jz_clocks.cclk = __cpm_get_cclk(); -+ jz_clocks.hclk = __cpm_get_hclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(); -+ jz_clocks.extalclk = __cpm_get_extalclk(); -+ jz_clocks.rtcclk = __cpm_get_rtcclk(); -+#else -+ -+#define FPGACLK 8000000 -+ -+ jz_clocks.cclk = FPGACLK; -+ jz_clocks.hclk = FPGACLK; -+ jz_clocks.pclk = FPGACLK; -+ jz_clocks.mclk = FPGACLK; -+ jz_clocks.lcdclk = FPGACLK; -+ jz_clocks.pixclk = FPGACLK; -+ jz_clocks.i2sclk = FPGACLK; -+ jz_clocks.usbclk = FPGACLK; -+ jz_clocks.mscclk = FPGACLK; -+ jz_clocks.extalclk = FPGACLK; -+ jz_clocks.rtcclk = FPGACLK; -+#endif -+ -+ printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", -+ (jz_clocks.cclk + 500000) / 1000000, -+ (jz_clocks.hclk + 500000) / 1000000, -+ (jz_clocks.pclk + 500000) / 1000000, -+ (jz_clocks.mclk + 500000) / 1000000); -+} -+ -+static void __init soc_cpm_setup(void) -+{ -+ /* Start all module clocks -+ */ -+ __cpm_start_all(); -+ -+ /* Enable CKO to external memory */ -+ __cpm_enable_cko(); -+ -+ /* CPU enters IDLE mode when executing 'wait' instruction */ -+ __cpm_idle_mode(); -+ -+ /* Setup system clocks */ -+ sysclocks_setup(); -+} -+ -+static void __init soc_harb_setup(void) -+{ -+// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -+} -+ -+static void __init soc_emc_setup(void) -+{ -+} -+ -+static void __init soc_dmac_setup(void) -+{ -+ __dmac_enable_module(); -+} -+ -+static void __init jz_soc_setup(void) -+{ -+ soc_cpm_setup(); -+ soc_harb_setup(); -+ soc_emc_setup(); -+ soc_dmac_setup(); -+} -+ -+static void __init jz_serial_setup(void) -+{ -+#ifdef CONFIG_SERIAL_8250 -+ struct uart_port s; -+ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ -+ memset(&s, 0, sizeof(s)); -+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -+ s.iotype = SERIAL_IO_MEM; -+ s.regshift = 2; -+ s.uartclk = jz_clocks.extalclk ; -+ -+ s.line = 0; -+ s.membase = (u8 *)UART0_BASE; -+ s.irq = IRQ_UART0; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -+ } -+ -+ s.line = 1; -+ s.membase = (u8 *)UART1_BASE; -+ s.irq = IRQ_UART1; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -+ } -+#endif -+} -+ -+void __init plat_mem_setup(void) -+{ -+ char *argptr; -+ -+ argptr = prom_getcmdline(); -+ -+ /* IO/MEM resources. Which will be the addtion value in `inX' and -+ * `outX' macros defined in asm/io.h */ -+ set_io_port_base(0); -+ ioport_resource.start = 0x00000000; -+ ioport_resource.end = 0xffffffff; -+ iomem_resource.start = 0x00000000; -+ iomem_resource.end = 0xffffffff; -+ -+ _machine_restart = jz_restart; -+ _machine_halt = jz_halt; -+ pm_power_off = jz_power_off; -+ -+ jz_soc_setup(); -+ jz_serial_setup(); -+ jz_board_setup(); -+} -+ -diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c -new file mode 100644 -index 0000000..a82b17c ---- /dev/null -+++ b/arch/mips/jz4740/time.c -@@ -0,0 +1,158 @@ -+/* -+ * linux/arch/mips/jz4740/time.c -+ * -+ * Setting up the clock on the JZ4740 boards. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* This is for machines which generate the exact clock. */ -+ -+#define JZ_TIMER_CHAN 0 -+#define JZ_TIMER_IRQ IRQ_TCU0 -+ -+#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ -+ -+static struct clocksource clocksource_jz; /* Jz clock source */ -+static struct clock_event_device jz_clockevent_device; /* Jz clock event */ -+ -+void (*jz_timer_callback)(void); -+ -+static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *cd = dev_id; -+ -+ REG_TCU_TFCR = 1 << JZ_TIMER_CHAN; /* ACK timer */ -+ -+ if (jz_timer_callback) -+ jz_timer_callback(); -+ -+ cd->event_handler(cd); -+ -+ return IRQ_HANDLED; -+} -+ -+static struct irqaction jz_irqaction = { -+ .handler = jz_timer_interrupt, -+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, -+ .name = "jz-timerirq", -+}; -+ -+ -+cycle_t jz_get_cycles(void) -+{ -+ /* convert jiffes to jz timer cycles */ -+ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_TCNT(JZ_TIMER_CHAN)); -+} -+ -+static struct clocksource clocksource_jz = { -+ .name = "jz_clocksource", -+ .rating = 300, -+ .read = jz_get_cycles, -+ .mask = 0xFFFF, -+ .shift = 10, -+ .flags = CLOCK_SOURCE_WATCHDOG, -+}; -+ -+static int __init jz_clocksource_init(void) -+{ -+ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -+ clocksource_register(&clocksource_jz); -+ return 0; -+} -+ -+static int jz_set_next_event(unsigned long evt, -+ struct clock_event_device *unused) -+{ -+ return 0; -+} -+ -+static void jz_set_mode(enum clock_event_mode mode, -+ struct clock_event_device *evt) -+{ -+ switch (mode) { -+ case CLOCK_EVT_MODE_PERIODIC: -+ break; -+ case CLOCK_EVT_MODE_ONESHOT: -+ case CLOCK_EVT_MODE_UNUSED: -+ case CLOCK_EVT_MODE_SHUTDOWN: -+ break; -+ case CLOCK_EVT_MODE_RESUME: -+ break; -+ } -+} -+ -+static struct clock_event_device jz_clockevent_device = { -+ .name = "jz-clockenvent", -+ .features = CLOCK_EVT_FEAT_PERIODIC, -+// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ -+ -+ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -+ .rating = 300, -+ .irq = JZ_TIMER_IRQ, -+ .set_mode = jz_set_mode, -+ .set_next_event = jz_set_next_event, -+}; -+ -+static void __init jz_clockevent_init(void) -+{ -+ struct clock_event_device *cd = &jz_clockevent_device; -+ unsigned int cpu = smp_processor_id(); -+ -+ cd->cpumask = cpumask_of_cpu(cpu); -+ clockevents_register_device(cd); -+} -+ -+static void __init jz_timer_setup(void) -+{ -+ jz_clocksource_init(); /* init jz clock source */ -+ jz_clockevent_init(); /* init jz clock event */ -+ -+ /* -+ * Make irqs happen for the system timer -+ */ -+ jz_irqaction.dev_id = &jz_clockevent_device; -+ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -+} -+ -+ -+void __init plat_time_init(void) -+{ -+ unsigned int latch; -+ /* Init timer */ -+ latch = ( JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -+ -+ REG_TCU_TCSR(JZ_TIMER_CHAN) = TCU_TCSR_PRESCALE16 | TCU_TCSR_EXT_EN; -+ REG_TCU_TCNT(JZ_TIMER_CHAN) = 0; -+ REG_TCU_TDHR(JZ_TIMER_CHAN) = 0; -+ REG_TCU_TDFR(JZ_TIMER_CHAN) = latch; -+ -+ REG_TCU_TMSR = (1 << (JZ_TIMER_CHAN + 16)); /* mask half irq */ -+ REG_TCU_TMCR = (1 << JZ_TIMER_CHAN); /* unmask full irq */ -+ REG_TCU_TSCR = (1 << JZ_TIMER_CHAN); /* enable timer clock */ -+ REG_TCU_TESR = (1 << JZ_TIMER_CHAN); /* start counting up */ -+ -+ jz_timer_setup(); -+} -diff --git a/arch/mips/jz4750/Makefile b/arch/mips/jz4750/Makefile -new file mode 100644 -index 0000000..a9c6c16 ---- /dev/null -+++ b/arch/mips/jz4750/Makefile -@@ -0,0 +1,23 @@ -+# -+# Makefile for the Ingenic JZ4750. -+# -+ -+# Object file lists. -+ -+obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -+ platform.o i2c.o -+ -+obj-$(CONFIG_PROC_FS) += proc.o -+ -+# board specific support -+ -+obj-$(CONFIG_JZ4750_FUWA) += board-fuwa.o -+obj-$(CONFIG_JZ4750_APUS) += board-apus.o -+ -+# PM support -+ -+obj-$(CONFIG_PM_LEGACY) +=pm.o -+ -+# CPU Frequency scaling support -+ -+obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -diff --git a/arch/mips/jz4750/board-apus.c b/arch/mips/jz4750/board-apus.c -new file mode 100644 -index 0000000..7347dfa ---- /dev/null -+++ b/arch/mips/jz4750/board-apus.c -@@ -0,0 +1,64 @@ -+/* -+ * linux/arch/mips/jz4750/board-apus.c -+ * -+ * JZ4750 APUS board setup routines. -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+} -+ -+static void apus_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4750/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ __gpio_as_pcm(); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4750 APUS board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = apus_timer_callback; -+} -diff --git a/arch/mips/jz4750/board-fuwa.c b/arch/mips/jz4750/board-fuwa.c -new file mode 100644 -index 0000000..c5aae06 ---- /dev/null -+++ b/arch/mips/jz4750/board-fuwa.c -@@ -0,0 +1,105 @@ -+/* -+ * linux/arch/mips/jz4750/board-fuwa.c -+ * -+ * JZ4750 FUWA board setup routines. -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned char slash[] = "\\|/-"; -+// static volatile unsigned char *p = (unsigned char *)0xb6000058; -+ static volatile unsigned char *p = (unsigned char *)0xb6000016; -+ static unsigned int count = 0; -+ *p = slash[count++]; -+ count &= 3; -+} -+ -+static void fuwa_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4750/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Initialize SDRAM pins -+ */ -+ -+ /* PORT A: D0 ~ D31 */ -+ REG_GPIO_PXFUNS(0) = 0xffffffff; -+ REG_GPIO_PXSELC(0) = 0xffffffff; -+ -+ /* PORT B: A0 ~ A16, DCS#, RAS#, CAS#, CKE#, RDWE#, CKO#, WE0# */ -+ REG_GPIO_PXFUNS(1) = 0x81f9ffff; -+ REG_GPIO_PXSELC(1) = 0x81f9ffff; -+ -+ /* PORT C: WE1#, WE2#, WE3# */ -+ REG_GPIO_PXFUNS(2) = 0x07000000; -+ REG_GPIO_PXSELC(2) = 0x07000000; -+ -+ -+ /* -+ * Initialize UART0 pins -+ */ -+ -+ /* PORT D: TXD/RXD */ -+ REG_GPIO_PXFUNS(3) = 0x06000000; -+ REG_GPIO_PXSELS(3) = 0x06000000; -+ -+ -+ /* -+ * Initialize LED pins -+ */ -+ __gpio_as_lcd_18bit(); -+ -+ /* CS2# */ -+ REG_GPIO_PXFUNS(1) = 0x04000000; -+ REG_GPIO_PXSELC(1) = 0x04000000; -+ -+ __gpio_as_pcm(); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4750 FUWA board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = fuwa_timer_callback; -+} -diff --git a/arch/mips/jz4750/board-slt50.c b/arch/mips/jz4750/board-slt50.c -new file mode 100644 -index 0000000..e8e20b4 ---- /dev/null -+++ b/arch/mips/jz4750/board-slt50.c -@@ -0,0 +1,64 @@ -+/* -+ * linux/arch/mips/jz4750/board-apus.c -+ * -+ * JZ4750 APUS board setup routines. -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+} -+ -+static void apus_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4750/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ __gpio_as_pcm(); -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4750 SLT_50 board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = apus_timer_callback; -+} -diff --git a/arch/mips/jz4750/cpufreq.c b/arch/mips/jz4750/cpufreq.c -new file mode 100644 -index 0000000..83f98b1 ---- /dev/null -+++ b/arch/mips/jz4750/cpufreq.c -@@ -0,0 +1,601 @@ -+/* -+ * linux/arch/mips/jz4750/cpufreq.c -+ * -+ * cpufreq driver for JZ4750 -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -+ "cpufreq-jz4750", msg) -+ -+#undef CHANGE_PLL -+ -+#define PLL_UNCHANGED 0 -+#define PLL_GOES_UP 1 -+#define PLL_GOES_DOWN 2 -+ -+#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) -+ -+/* Saved the boot-time parameters */ -+static struct { -+ /* SDRAM parameters */ -+ unsigned int mclk; /* memory clock, KHz */ -+ unsigned int tras; /* RAS pulse width, cycles of mclk */ -+ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -+ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -+ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -+ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -+ unsigned int rtcor; /* Refresh Time Constant */ -+ unsigned int sdram_initialized; -+ -+ /* LCD parameters */ -+ unsigned int lcd_clk; /* LCD clock, Hz */ -+ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -+ unsigned int lcd_clks_initialized; -+} boot_config; -+ -+struct jz4750_freq_percpu_info { -+ struct cpufreq_frequency_table table[7]; -+}; -+ -+static struct jz4750_freq_percpu_info jz4750_freq_table; -+ -+/* -+ * This contains the registers value for an operating point. -+ * If only part of a register needs to change then there is -+ * a mask value for that register. -+ * When going to a new operating point the current register -+ * value is ANDed with the ~mask and ORed with the new value. -+ */ -+struct dpm_regs { -+ u32 cpccr; /* Clock Freq Control Register */ -+ u32 cpccr_mask; /* Clock Freq Control Register mask */ -+ u32 cppcr; /* PLL1 Control Register */ -+ u32 cppcr_mask; /* PLL1 Control Register mask */ -+ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -+}; -+ -+extern jz_clocks_t jz_clocks; -+ -+static void jz_update_clocks(void) -+{ -+ /* Next clocks must be updated if we have changed -+ * the PLL or divisors. -+ */ -+ jz_clocks.cclk = __cpm_get_cclk(); -+ jz_clocks.hclk = __cpm_get_hclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(0); -+} -+ -+static void -+jz_init_boot_config(void) -+{ -+ if (!boot_config.lcd_clks_initialized) { -+ /* the first time to scale pll */ -+ boot_config.lcd_clk = __cpm_get_lcdclk(); -+ boot_config.lcdpix_clk = __cpm_get_pixclk(); -+ boot_config.lcd_clks_initialized = 1; -+ } -+ -+ if (!boot_config.sdram_initialized) { -+ /* the first time to scale frequencies */ -+ unsigned int dmcr, rtcor; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ -+ dmcr = REG_EMC_DMCR; -+ rtcor = REG_EMC_RTCOR; -+ -+ tras = (dmcr >> 13) & 0x7; -+ rcd = (dmcr >> 11) & 0x3; -+ tpc = (dmcr >> 8) & 0x7; -+ trwl = (dmcr >> 5) & 0x3; -+ trc = (dmcr >> 2) & 0x7; -+ -+ boot_config.mclk = __cpm_get_mclk() / 1000; -+ boot_config.tras = tras + 4; -+ boot_config.rcd = rcd + 1; -+ boot_config.tpc = tpc + 1; -+ boot_config.trwl = trwl + 1; -+ boot_config.trc = trc * 2 + 1; -+ boot_config.rtcor = rtcor; -+ -+ boot_config.sdram_initialized = 1; -+ } -+} -+ -+static void jz_update_dram_rtcor(unsigned int new_mclk) -+{ -+ unsigned int rtcor; -+ -+ new_mclk /= 1000; -+ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -+ rtcor--; -+ -+ if (rtcor < 1) rtcor = 1; -+ if (rtcor > 255) rtcor = 255; -+ -+ REG_EMC_RTCOR = rtcor; -+ REG_EMC_RTCNT = rtcor; -+} -+ -+static void jz_update_dram_dmcr(unsigned int new_mclk) -+{ -+ unsigned int dmcr; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ unsigned int valid_time, new_time; /* ns */ -+ -+ new_mclk /= 1000; -+ tras = boot_config.tras * new_mclk / boot_config.mclk; -+ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -+ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -+ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -+ trc = boot_config.trc * new_mclk / boot_config.mclk; -+ -+ /* Validation checking */ -+ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -+ new_time = (tras * 1000000) / new_mclk; -+ if (new_time < valid_time) tras += 1; -+ -+ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -+ new_time = (rcd * 1000000) / new_mclk; -+ if (new_time < valid_time) rcd += 1; -+ -+ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -+ new_time = (tpc * 1000000) / new_mclk; -+ if (new_time < valid_time) tpc += 1; -+ -+ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -+ new_time = (trwl * 1000000) / new_mclk; -+ if (new_time < valid_time) trwl += 1; -+ -+ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -+ new_time = (trc * 1000000) / new_mclk; -+ if (new_time < valid_time) trc += 2; -+ -+ tras = (tras < 4) ? 4: tras; -+ tras = (tras > 11) ? 11: tras; -+ tras -= 4; -+ -+ rcd = (rcd < 1) ? 1: rcd; -+ rcd = (rcd > 4) ? 4: rcd; -+ rcd -= 1; -+ -+ tpc = (tpc < 1) ? 1: tpc; -+ tpc = (tpc > 8) ? 8: tpc; -+ tpc -= 1; -+ -+ trwl = (trwl < 1) ? 1: trwl; -+ trwl = (trwl > 4) ? 4: trwl; -+ trwl -= 1; -+ -+ trc = (trc < 1) ? 1: trc; -+ trc = (trc > 15) ? 15: trc; -+ trc /= 2; -+ -+ dmcr = REG_EMC_DMCR; -+ -+ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -+ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -+ -+ REG_EMC_DMCR = dmcr; -+} -+ -+static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR before changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } else { -+ /* We're going SLOWER: first update RTCOR value -+ * before changing the frequency. -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } -+} -+ -+static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so update RTCOR -+ * after changing the frequency -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } else { -+ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR after changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } -+} -+ -+static void jz_scale_divisors(struct dpm_regs *regs) -+{ -+ unsigned int cpccr; -+ unsigned int cur_mclk, new_mclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ cpccr = REG_CPM_CPCCR; -+ cpccr &= ~((unsigned long)regs->cpccr_mask); -+ cpccr |= regs->cpccr; -+ cpccr |= CPM_CPCCR_CE; /* update immediately */ -+ -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; -+ -+ /* Update some DRAM parameters before changing frequency */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+ -+#ifdef CHANGE_PLL -+/* Maintain the LCD clock and pixel clock */ -+static void jz_scale_lcd_divisors(struct dpm_regs *regs) -+{ -+ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -+ unsigned int cpccr; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ if (!boot_config.lcd_clks_initialized) return; -+ -+ new_pll = __cpm_get_pllout(); -+ new_lcd_div = new_pll / boot_config.lcd_clk; -+ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -+ -+ if (new_lcd_div < 1) -+ new_lcd_div = 1; -+ if (new_lcd_div > 16) -+ new_lcd_div = 16; -+ -+ if (new_lcdpix_div < 1) -+ new_lcdpix_div = 1; -+ if (new_lcdpix_div > 512) -+ new_lcdpix_div = 512; -+ -+// REG_CPM_CPCCR2 = new_lcdpix_div - 1; -+ -+ cpccr = REG_CPM_CPCCR; -+ cpccr &= ~CPM_CPCCR_LDIV_MASK; -+ cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); -+ cpccr |= CPM_CPCCR_CE; /* update immediately */ -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -+} -+ -+static void jz_scale_pll(struct dpm_regs *regs) -+{ -+ unsigned int cppcr; -+ unsigned int cur_mclk, new_mclk, new_pll; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ int od[] = {1, 2, 2, 4}; -+ -+ cppcr = REG_CPM_CPPCR; -+ cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); -+ regs->cppcr &= ~CPM_CPPCR_PLLEN; -+ cppcr |= (regs->cppcr | 0xff); -+ -+ /* Update some DRAM parameters before changing frequency */ -+ new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf]; -+ -+ /* -+ * Update some SDRAM parameters -+ */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* -+ * Update PLL, align code to cache line. -+ */ -+ cppcr |= CPM_CPPCR_PLLEN; -+ __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" (CPM_CPPCR), "r" (cppcr)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+#endif -+ -+static void jz4750_transition(struct dpm_regs *regs) -+{ -+ /* -+ * Get and save some boot-time conditions. -+ */ -+ jz_init_boot_config(); -+ -+#ifdef CHANGE_PLL -+ /* -+ * Disable LCD before scaling pll. -+ * LCD and LCD pixel clocks should not be changed even if the PLL -+ * output frequency has been changed. -+ */ -+ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -+ -+ /* -+ * Stop module clocks before scaling PLL -+ */ -+ __cpm_stop_eth(); -+ __cpm_stop_aic(1); -+ __cpm_stop_aic(2); -+#endif -+ -+ /* ... add more as necessary */ -+ -+ if (regs->pll_up_flag == PLL_GOES_UP) { -+ /* the pll frequency is going up, so change dividors first */ -+ jz_scale_divisors(regs); -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ } -+ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -+ /* the pll frequency is going down, so change pll first */ -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ jz_scale_divisors(regs); -+ } -+ else { -+ /* the pll frequency is unchanged, so change divisors only */ -+ jz_scale_divisors(regs); -+ } -+ -+#ifdef CHANGE_PLL -+ /* -+ * Restart module clocks before scaling PLL -+ */ -+ __cpm_start_eth(); -+ __cpm_start_aic(1); -+ __cpm_start_aic(2); -+ -+ /* ... add more as necessary */ -+ -+ /* Scale the LCD divisors after scaling pll */ -+ if (regs->pll_up_flag != PLL_UNCHANGED) { -+ jz_scale_lcd_divisors(regs); -+ } -+ -+ /* Enable LCD controller */ -+ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -+ REG_LCD_CTRL |= LCD_CTRL_ENA; -+#endif -+ -+ /* Update system clocks */ -+ jz_update_clocks(); -+} -+ -+extern unsigned int idle_times; -+static unsigned int jz4750_freq_get(unsigned int cpu) -+{ -+ return (__cpm_get_cclk() / 1000); -+} -+ -+static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -+{ -+ int n2FR[33] = { -+ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -+ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -+ 9 -+ }; -+ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -+ unsigned int div_of_cclk, new_freq, i; -+ -+ regs->pll_up_flag = PLL_UNCHANGED; -+ regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; -+ -+ new_freq = jz4750_freq_table.table[index].frequency; -+ -+ do { -+ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -+ } while (div_of_cclk==0); -+ -+ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -+ for(i = 1; i<4; i++) { -+ div[i] = 3; -+ } -+ } else { -+ for(i = 1; i<4; i++) { -+ div[i] = 2; -+ } -+ } -+ -+ for(i = 0; i<4; i++) { -+ div[i] *= div_of_cclk; -+ } -+ -+ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -+ -+ regs->cpccr = -+ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | -+ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | -+ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | -+ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); -+ -+ return div_of_cclk; -+} -+ -+static void jz4750_set_cpu_divider_index(unsigned int cpu, unsigned int index) -+{ -+ unsigned long divisor, old_divisor; -+ struct cpufreq_freqs freqs; -+ struct dpm_regs regs; -+ -+ old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); -+ divisor = index_to_divisor(index, ®s); -+ -+ freqs.old = __cpm_get_cclk() / 1000; -+ freqs.new = __cpm_get_pllout() / (1000 * divisor); -+ freqs.cpu = cpu; -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -+ -+ if (old_divisor != divisor) -+ jz4750_transition(®s); -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -+} -+ -+static int jz4750_freq_target(struct cpufreq_policy *policy, -+ unsigned int target_freq, -+ unsigned int relation) -+{ -+ unsigned int new_index = 0; -+ -+ if (cpufreq_frequency_table_target(policy, -+ &jz4750_freq_table.table[0], -+ target_freq, relation, &new_index)) -+ return -EINVAL; -+ -+ jz4750_set_cpu_divider_index(policy->cpu, new_index); -+ -+ dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); -+ -+ return 0; -+} -+ -+static int jz4750_freq_verify(struct cpufreq_policy *policy) -+{ -+ return cpufreq_frequency_table_verify(policy, -+ &jz4750_freq_table.table[0]); -+} -+ -+static int __init jz4750_cpufreq_driver_init(struct cpufreq_policy *policy) -+{ -+ -+ struct cpufreq_frequency_table *table = &jz4750_freq_table.table[0]; -+ unsigned int MAX_FREQ; -+ -+ dprintk(KERN_INFO "Jz4750 cpufreq driver\n"); -+ -+ if (policy->cpu != 0) -+ return -EINVAL; -+ -+ policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -+ -+ policy->cpuinfo.min_freq = MAX_FREQ/8; -+ policy->cpuinfo.max_freq = MAX_FREQ; -+ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -+ -+ table[0].index = 0; -+ table[0].frequency = MAX_FREQ/8; -+ table[1].index = 1; -+ table[1].frequency = MAX_FREQ/6; -+ table[2].index = 2; -+ table[2].frequency = MAX_FREQ/4; -+ table[3].index = 3; -+ table[3].frequency = MAX_FREQ/3; -+ table[4].index = 4; -+ table[4].frequency = MAX_FREQ/2; -+ table[5].index = 5; -+ table[5].frequency = MAX_FREQ; -+ table[6].index = 6; -+ table[6].frequency = CPUFREQ_TABLE_END; -+ -+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS -+ cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ -+#endif -+ -+ return cpufreq_frequency_table_cpuinfo(policy, table); -+} -+ -+static struct cpufreq_driver cpufreq_jz4750_driver = { -+// .flags = CPUFREQ_STICKY, -+ .init = jz4750_cpufreq_driver_init, -+ .verify = jz4750_freq_verify, -+ .target = jz4750_freq_target, -+ .get = jz4750_freq_get, -+ .name = "jz4750", -+}; -+ -+static int __init jz4750_cpufreq_init(void) -+{ -+ return cpufreq_register_driver(&cpufreq_jz4750_driver); -+} -+ -+static void __exit jz4750_cpufreq_exit(void) -+{ -+ cpufreq_unregister_driver(&cpufreq_jz4750_driver); -+} -+ -+module_init(jz4750_cpufreq_init); -+module_exit(jz4750_cpufreq_exit); -+ -+MODULE_AUTHOR("Regen "); -+MODULE_DESCRIPTION("cpufreq driver for Jz4750"); -+MODULE_LICENSE("GPL"); -diff --git a/arch/mips/jz4750/dma.c b/arch/mips/jz4750/dma.c -new file mode 100644 -index 0000000..2508111 ---- /dev/null -+++ b/arch/mips/jz4750/dma.c -@@ -0,0 +1,836 @@ -+/* -+ * linux/arch/mips/jz4750/dma.c -+ * -+ * Support functions for the JZ4750 internal DMA channels. -+ * No-descriptor transfer only. -+ * Descriptor transfer should also call jz_request_dma() to get a free -+ * channel and call jz_free_dma() to free the channel. And driver should -+ * build the DMA descriptor and setup the DMA channel by itself. -+ * -+ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * A note on resource allocation: -+ * -+ * All drivers needing DMA channels, should allocate and release them -+ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -+ * -+ * In order to avoid problems, all processes should allocate resources in -+ * the same sequence and release them in the reverse order. -+ * -+ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -+ * When releasing them, first release the IRQ, then release the DMA. The -+ * main reason for this order is that, if you are requesting the DMA buffer -+ * done interrupt, you won't know the irq number until the DMA channel is -+ * returned from jz_request_dma(). -+ */ -+ -+struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { -+ {dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */ -+ {dev_id:-1,}, /* DMAC0 channel 1 */ -+ {dev_id:-1,}, /* DMAC0 channel 2 */ -+ {dev_id:-1,}, /* DMAC0 channel 3 */ -+ {dev_id:-1,}, /* DMAC0 channel 4 */ -+ {dev_id:-1,}, /* DMAC0 channel 5 */ -+ {dev_id:-1,}, /* DMAC1 channel 0 */ -+ {dev_id:-1,}, /* DMAC1 channel 1 */ -+ {dev_id:-1,}, /* DMAC1 channel 2 */ -+ {dev_id:-1,}, /* DMAC1 channel 3 */ -+ {dev_id:-1,}, /* DMAC1 channel 4 */ -+ {dev_id:-1,}, /* DMAC1 channel 5 */ -+}; -+ -+// Device FIFO addresses and default DMA modes -+static const struct { -+ unsigned int fifo_addr; -+ unsigned int dma_mode; -+ unsigned int dma_source; -+} dma_dev_table[DMA_ID_MAX] = { -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */ -+ {0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */ -+ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC}, -+ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC}, -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, -+// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN}, -+ {CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT}, -+ {CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN}, -+ {CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT}, -+ {CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN}, -+ {CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT}, -+ {CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN}, -+ {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -+ {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -+ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT}, -+ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN}, -+ {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -+ {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -+ {CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT}, -+ {CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN}, -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, -+ {SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */ -+ {CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */ -+ {CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */ -+ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT}, -+ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN}, -+ {CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT}, -+ {CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN}, -+ {}, -+}; -+ -+ -+int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data) -+{ -+ int i, len = 0; -+ struct jz_dma_chan *chan; -+ -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if ((chan = get_dma_chan(i)) != NULL) { -+ len += sprintf(buf + len, "%2d: %s\n", -+ i, chan->dev_str); -+ } -+ } -+ -+ if (fpos >= len) { -+ *start = buf; -+ *eof = 1; -+ return 0; -+ } -+ *start = buf + fpos; -+ if ((len -= fpos) > length) -+ return length; -+ *eof = 1; -+ return len; -+} -+ -+ -+void dump_jz_dma_channel(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > MAX_DMA_NUM) -+ return; -+ chan = &jz_dma_table[dmanr]; -+ -+ printk("DMA%d Registers:\n", dmanr); -+ printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM)); -+ printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -+ printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); -+ printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -+ printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -+ printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -+ printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); -+ printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); -+ printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM)); -+} -+ -+ -+/** -+ * jz_request_dma - dynamically allcate an idle DMA channel to return -+ * @dev_id: the specified dma device id or DMA_ID_RAW_SET -+ * @dev_str: the specified dma device string name -+ * @irqhandler: the irq handler, or NULL -+ * @irqflags: the irq handler flags -+ * @irq_dev_id: the irq handler device id for shared irq -+ * -+ * Finds a free channel, and binds the requested device to it. -+ * Returns the allocated channel number, or negative on error. -+ * Requests the DMA done IRQ if irqhandler != NULL. -+ * -+*/ -+/*int jz_request_dma(int dev_id, const char *dev_str, -+ void (*irqhandler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+*/ -+ -+int jz_request_dma(int dev_id, const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+{ -+ struct jz_dma_chan *chan; -+ int i, ret, chan0; -+ -+ if (dev_id < 0 || dev_id >= DMA_ID_MAX) -+ return -EINVAL; -+ -+ /* Because of a bug in DMA controller of jz4750, which causes auto -+ request and device request can't be allocated in a same DMA -+ controller, all device requests should be put in the second DMA -+ controller -+ */ -+ if (dev_id > DMA_ID_AUTO) -+ chan0 = 6; -+ else -+ chan0 = 0; -+ -+ for (i = chan0; i < MAX_DMA_NUM; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == MAX_DMA_NUM) /* no free channel */ -+ return -ENODEV; -+ -+ /* we got a free channel */ -+ chan = &jz_dma_table[i]; -+ -+ if (irqhandler) { -+ chan->irq = IRQ_DMA_0 + i; // allocate irq number -+ chan->irq_dev = irq_dev_id; -+ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -+ dev_str, chan->irq_dev))) { -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ return ret; -+ } -+ } else { -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ } -+ -+ // fill it in -+ chan->io = i; -+ chan->dev_id = dev_id; -+ chan->dev_str = dev_str; -+ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -+ chan->mode = dma_dev_table[dev_id].dma_mode; -+ chan->source = dma_dev_table[dev_id].dma_source; -+ -+ if (i < 6) -+ REG_DMAC_DMACKE(0) = 1 << i; -+ else -+ REG_DMAC_DMACKE(1) = 1 << (i - 6); -+ -+ return i; -+} -+ -+void jz_free_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) { -+ printk("Trying to free DMA%d\n", dmanr); -+ return; -+ } -+ -+ disable_dma(dmanr); -+ if (chan->irq) -+ free_irq(chan->irq, chan->irq_dev); -+ -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ chan->dev_id = -1; -+} -+ -+void jz_set_dma_dest_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_DWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCMD_DWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_DWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_DWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_src_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_SWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCMD_SWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_SWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_SWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_block_size(int dmanr, int nbyte) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_DS_MASK; -+ switch (nbyte) { -+ case 1: -+ chan->mode |= DMAC_DCMD_DS_8BIT; -+ break; -+ case 2: -+ chan->mode |= DMAC_DCMD_DS_16BIT; -+ break; -+ case 4: -+ chan->mode |= DMAC_DCMD_DS_32BIT; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_DS_16BYTE; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_DS_32BYTE; -+ break; -+ } -+} -+ -+unsigned int jz_get_dma_command(int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ return chan->mode; -+} -+ -+/** -+ * jz_set_dma_mode - do the raw settings for the specified DMA channel -+ * @dmanr: the specified DMA channel -+ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -+ * @dma_mode: dma raw mode -+ * @dma_source: dma raw request source -+ * @fifo_addr: dma raw device fifo address -+ * -+ * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call -+ * jz_set_dma_mode() rather than set_dma_mode() if you work with -+ * and external request dma device. -+ * -+ * NOTE: Don not dynamically allocate dma channel if one external request -+ * dma device will occupy this channel. -+*/ -+int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -+ unsigned int dma_mode, unsigned int dma_source, -+ unsigned int fifo_addr) -+{ -+ int dev_id, i; -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > MAX_DMA_NUM) -+ return -ENODEV; -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == MAX_DMA_NUM) -+ return -ENODEV; -+ -+ chan = &jz_dma_table[dmanr]; -+ dev_id = chan->dev_id; -+ if (dev_id > 0) { -+ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -+ __FUNCTION__, dmanr); -+ return -ENODEV; -+ } -+ -+ /* clone it from the dynamically allocated. */ -+ if (i != dmanr) { -+ chan->irq = jz_dma_table[i].irq; -+ chan->irq_dev = jz_dma_table[i].irq_dev; -+ chan->dev_str = jz_dma_table[i].dev_str; -+ jz_dma_table[i].irq = 0; -+ jz_dma_table[i].irq_dev = NULL; -+ jz_dma_table[i].dev_id = -1; -+ } -+ chan->dev_id = DMA_ID_RAW_SET; -+ chan->io = dmanr; -+ chan->fifo_addr = fifo_addr; -+ chan->mode = dma_mode; -+ chan->source = dma_source; -+ -+ set_dma_mode(dmanr, dma_mode); -+ -+ return dmanr; -+} -+ -+void enable_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+ REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ -+ __dmac_enable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_enable_irq(dmanr); -+} -+ -+#define DMA_DISABLE_POLL 0x10000 -+ -+void disable_dma(unsigned int dmanr) -+{ -+ int i; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ if (!__dmac_channel_enabled(dmanr)) -+ return; -+ -+ for (i = 0; i < DMA_DISABLE_POLL; i++) -+ if (__dmac_channel_transmit_end_detected(dmanr)) -+ break; -+#if 0 -+ if (i == DMA_DISABLE_POLL) -+ printk(KERN_INFO "disable_dma: poll expired!\n"); -+#endif -+ -+ __dmac_disable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_disable_irq(dmanr); -+} -+ -+/* Note: DMA_MODE_MASK is simulated by sw */ -+void set_dma_mode(unsigned int dmanr, unsigned int mode) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else { -+ printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ } -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+} -+ -+void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) -+{ -+ unsigned int mode; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ mode = chan->mode & DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -+ REG_DMAC_DTAR(chan->io) = phyaddr; -+ } else if (mode == DMA_MODE_WRITE) { -+ REG_DMAC_DSAR(chan->io) = phyaddr; -+ REG_DMAC_DTAR(chan->io) = chan->fifo_addr; -+ } else -+ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -+} -+ -+void set_dma_count(unsigned int dmanr, unsigned int bytecnt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ unsigned int ds; -+ -+ if (!chan) -+ return; -+ -+ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -+ REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count -+} -+ -+unsigned int get_dma_residue(unsigned int dmanr) -+{ -+ unsigned int count, ds; -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ -+ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -+ count = REG_DMAC_DTCR(chan->io); -+ count = count * dma_ds[ds]; -+ -+ return count; -+} -+ -+void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case AFMT_U8: -+ /* burst mode : 32BIT */ -+ break; -+ case AFMT_S16_LE: -+ /* burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ //chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else -+ printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case 8: -+ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -+ break; -+ case 16: -+ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else -+ printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+//#define JZ4750_DMAC_TEST_ENABLE -+#undef JZ4750_DMAC_TEST_ENABLE -+ -+#ifdef JZ4750_DMAC_TEST_ENABLE -+ -+/* -+ * DMA test: external address <--> external address -+ */ -+#define TEST_DMA_SIZE 16*1024 -+ -+static jz_dma_desc *dma_desc; -+ -+static int dma_chan; -+static dma_addr_t dma_desc_phys_addr; -+static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; -+ -+static int dma_check_result(void *src, void *dst, int size) -+{ -+ unsigned int addr1, addr2, i, err = 0; -+ -+ addr1 = (unsigned int)src; -+ addr2 = (unsigned int)dst; -+ -+ for (i = 0; i < size; i += 4) { -+ if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { -+ err++; -+ printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); -+ } -+ addr1 += 4; -+ addr2 += 4; -+ } -+ printk("check DMA result err=%d\n", err); -+ return err; -+} -+ -+static irqreturn_t jz4750_dma_irq(int irq, void *dev_id) -+{ -+ printk("jz4750_dma_irq %d\n", irq); -+ -+ -+ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -+ printk("DMA HALT\n"); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ __dmac_channel_clear_transmit_halt(dma_chan); -+ } -+ -+ if (__dmac_channel_address_error_detected(dma_chan)) { -+ printk("DMA ADDR ERROR\n"); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */ -+ REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */ -+ __dmac_channel_clear_address_error(dma_chan); -+ } -+ -+ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ printk("DMA DESC INVALID\n"); -+ __dmac_channel_clear_descriptor_invalid(dma_chan); -+ } -+ -+ if (__dmac_channel_count_terminated_detected(dma_chan)) { -+ printk("DMA CT\n"); -+ __dmac_channel_clear_count_terminated(dma_chan); -+ } -+ -+ if (__dmac_channel_transmit_end_detected(dma_chan)) { -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ printk("DMA TT\n"); -+ __dmac_channel_clear_transmit_end(dma_chan); -+ dump_jz_dma_channel(dma_chan); -+ dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+void dma_nodesc_test(void) -+{ -+ unsigned int addr, i; -+ -+ printk("dma_nodesc_test\n"); -+ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750_dma_irq, -+ IRQF_DISABLED, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq failed\n"); -+ return; -+ } -+ -+ printk("Requested DMA channel = %d\n", dma_chan); -+ -+ /* Allocate DMA buffers */ -+ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ -+ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -+ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -+ -+ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -+ -+ /* Prepare data for source buffer */ -+ addr = (unsigned int)dma_src_addr; -+ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -+ *(volatile unsigned int *)addr = addr; -+ addr += 4; -+ } -+ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -+ -+ /* Init target buffer */ -+ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -+ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -+ -+ /* Init DMA module */ -+ printk("Starting DMA\n"); -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0; -+ REG_DMAC_DCCSR(dma_chan) = 0; -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -+ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -+ REG_DMAC_DTCR(dma_chan) = 512; -+ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */ -+ -+ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -+ -+ /* wait a long time, ensure transfer end */ -+ printk("wait 3s...\n"); -+ mdelay(3000); /* wait 3s */ -+ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ /* free buffers */ -+ printk("free DMA buffers\n"); -+ free_pages(dma_src_addr, 2); -+ free_pages(dma_dst_addr, 2); -+ -+ if (dma_desc) -+ free_pages((unsigned int)dma_desc, 0); -+ -+ /* free dma */ -+ jz_free_dma(dma_chan); -+} -+ -+void dma_desc_test(void) -+{ -+ unsigned int next, addr, i; -+ static jz_dma_desc *desc; -+ -+ printk("dma_desc_test\n"); -+ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750_dma_irq, -+ IRQF_DISABLED, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq failed\n"); -+ return; -+ } -+ -+ printk("Requested DMA channel = %d\n", dma_chan); -+ -+ /* Allocate DMA buffers */ -+ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ -+ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -+ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -+ -+ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -+ -+ /* Prepare data for source buffer */ -+ addr = (unsigned int)dma_src_addr; -+ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -+ *(volatile unsigned int *)addr = addr; -+ addr += 4; -+ } -+ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -+ -+ /* Init target buffer */ -+ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -+ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -+ -+ /* Allocate DMA descriptors */ -+ dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); -+ dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); -+ -+ printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); -+ -+ /* Setup DMA descriptors */ -+ desc = dma_desc; -+ next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr; /* DMA target address */ -+ desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ -+ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ -+ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; -+ desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ -+ desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ -+ -+ dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); -+ -+ /* Setup DMA descriptor address */ -+ REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; -+ -+ /* Setup request source */ -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ -+ /* Setup DMA channel control/status register */ -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -+ -+ /* Enable DMA */ -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; -+ -+ /* DMA doorbell set -- start DMA now ... */ -+ REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan; -+ -+ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -+ /* wait a long time, ensure transfer end */ -+ printk("wait 3s...\n"); -+ mdelay(3000); /* wait 3s */ -+ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ /* free buffers */ -+ printk("free DMA buffers\n"); -+ free_pages(dma_src_addr, 2); -+ free_pages(dma_dst_addr, 2); -+ -+ if (dma_desc) -+ free_pages((unsigned int)dma_desc, 0); -+ -+ /* free dma */ -+ jz_free_dma(dma_chan); -+} -+ -+#endif -+ -+//EXPORT_SYMBOL_NOVERS(jz_dma_table); -+EXPORT_SYMBOL(jz_dma_table); -+EXPORT_SYMBOL(jz_request_dma); -+EXPORT_SYMBOL(jz_free_dma); -+EXPORT_SYMBOL(jz_set_dma_src_width); -+EXPORT_SYMBOL(jz_set_dma_dest_width); -+EXPORT_SYMBOL(jz_set_dma_block_size); -+EXPORT_SYMBOL(jz_set_dma_mode); -+EXPORT_SYMBOL(set_dma_mode); -+EXPORT_SYMBOL(jz_set_oss_dma); -+EXPORT_SYMBOL(jz_set_alsa_dma); -+EXPORT_SYMBOL(set_dma_addr); -+EXPORT_SYMBOL(set_dma_count); -+EXPORT_SYMBOL(get_dma_residue); -+EXPORT_SYMBOL(enable_dma); -+EXPORT_SYMBOL(disable_dma); -+EXPORT_SYMBOL(dump_jz_dma_channel); -diff --git a/arch/mips/jz4750/i2c.c b/arch/mips/jz4750/i2c.c -new file mode 100644 -index 0000000..cdb1223 ---- /dev/null -+++ b/arch/mips/jz4750/i2c.c -@@ -0,0 +1,273 @@ -+/* -+ * linux/arch/mips/jz4750/i2c.c -+ * -+ * Jz4750 I2C routines. -+ * -+ * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* I2C protocol */ -+#define I2C_READ 1 -+#define I2C_WRITE 0 -+ -+#define TIMEOUT 1000 -+ -+/* -+ * I2C bus protocol basic routines -+ */ -+static int i2c_put_data(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (!__i2c_received_ack() && timeout) -+ timeout--; -+ -+ if (timeout) -+ return 0; -+ else -+ return -ETIMEDOUT; -+} -+ -+#ifdef CONFIG_JZ_TPANEL_ATA2508 -+static int i2c_put_data_nack(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (timeout--); -+ return 0; -+} -+#endif -+ -+static int i2c_get_data(unsigned char *data, int ack) -+{ -+ int timeout = TIMEOUT*10; -+ -+ if (!ack) -+ __i2c_send_nack(); -+ else -+ __i2c_send_ack(); -+ -+ while (__i2c_check_drf() == 0 && timeout) -+ timeout--; -+ -+ if (timeout) { -+ if (!ack) -+ __i2c_send_stop(); -+ *data = __i2c_read(); -+ __i2c_clear_drf(); -+ return 0; -+ } else -+ return -ETIMEDOUT; -+} -+ -+/* -+ * I2C interface -+ */ -+void i2c_open(void) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -+ __i2c_enable(); -+} -+ -+void i2c_close(void) -+{ -+ udelay(300); /* wait for STOP goes over. */ -+ __i2c_disable(); -+} -+ -+void i2c_setclk(unsigned int i2cclk) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -+} -+ -+int i2c_lseek(unsigned char device, unsigned char offset) -+{ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+ if (i2c_put_data(offset) < 0) -+ goto address_err; -+ return 0; -+ device_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+ address_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -+ __i2c_send_stop(); -+ return -EREMOTEIO; -+} -+ -+int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int timeout = 5; -+ -+L_try_again: -+ -+ if (timeout < 0) -+ goto L_timeout; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_werr; -+ if (i2c_put_data(address) < 0) -+ goto address_err; -+ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -+ goto device_rerr; -+ __i2c_send_ack(); /* Master sends ACK for continue reading */ -+ while (cnt) { -+ if (cnt == 1) { -+ if (i2c_get_data(buf, 0) < 0) -+ break; -+ } else { -+ if (i2c_get_data(buf, 1) < 0) -+ break; -+ } -+ cnt--; -+ buf++; -+ } -+ -+ __i2c_send_stop(); -+ return count - cnt; -+ device_rerr: -+ device_werr: -+ address_err: -+ timeout --; -+ __i2c_send_stop(); -+ goto L_try_again; -+ -+L_timeout: -+ __i2c_send_stop(); -+ printk("Read I2C device 0x%2x failed.\n", device); -+ return -ENODEV; -+} -+ -+int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int cnt_in_pg; -+ int timeout = 5; -+ unsigned char *tmpbuf; -+ unsigned char tmpaddr; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ -+ W_try_again: -+ if (timeout < 0) -+ goto W_timeout; -+ -+ cnt = count; -+ tmpbuf = (unsigned char *)buf; -+ tmpaddr = address; -+ -+ start_write_page: -+ cnt_in_pg = 0; -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+#ifdef CONFIG_JZ_TPANEL_ATA2508 -+ if (address == 0xff) { -+ if (i2c_put_data_nack(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data_nack(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ } -+ else { -+ -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ } -+#else -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+#endif -+ __i2c_send_stop(); -+ return count - cnt; -+ device_err: -+ address_err: -+ timeout--; -+ __i2c_send_stop(); -+ goto W_try_again; -+ -+ W_timeout: -+ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+} -+ -+EXPORT_SYMBOL(i2c_open); -+EXPORT_SYMBOL(i2c_close); -+EXPORT_SYMBOL(i2c_setclk); -+EXPORT_SYMBOL(i2c_read); -+EXPORT_SYMBOL(i2c_write); -diff --git a/arch/mips/jz4750/irq.c b/arch/mips/jz4750/irq.c -new file mode 100644 -index 0000000..6a9d867 ---- /dev/null -+++ b/arch/mips/jz4750/irq.c -@@ -0,0 +1,299 @@ -+/* -+ * linux/arch/mips/jz4750/irq.c -+ * -+ * JZ4750 interrupt routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * INTC irq type -+ */ -+ -+static void enable_intc_irq(unsigned int irq) -+{ -+ __intc_unmask_irq(irq); -+} -+ -+static void disable_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+} -+ -+static void mask_and_ack_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+ __intc_ack_irq(irq); -+} -+ -+static void end_intc_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_intc_irq(irq); -+ } -+} -+ -+static unsigned int startup_intc_irq(unsigned int irq) -+{ -+ enable_intc_irq(irq); -+ return 0; -+} -+ -+static void shutdown_intc_irq(unsigned int irq) -+{ -+ disable_intc_irq(irq); -+} -+ -+static struct irq_chip intc_irq_type = { -+ .typename = "INTC", -+ .startup = startup_intc_irq, -+ .shutdown = shutdown_intc_irq, -+ .enable = enable_intc_irq, -+ .disable = disable_intc_irq, -+ .ack = mask_and_ack_intc_irq, -+ .end = end_intc_irq, -+}; -+ -+/* -+ * GPIO irq type -+ */ -+ -+static void enable_gpio_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if (irq < (IRQ_GPIO_0 + 32)) { -+ intc_irq = IRQ_GPIO0; -+ } -+ else if (irq < (IRQ_GPIO_0 + 64)) { -+ intc_irq = IRQ_GPIO1; -+ } -+ else if (irq < (IRQ_GPIO_0 + 96)) { -+ intc_irq = IRQ_GPIO2; -+ } -+ else if (irq < (IRQ_GPIO_0 + 128)) { -+ intc_irq = IRQ_GPIO3; -+ } -+ else if (irq < (IRQ_GPIO_0 + 160)) { -+ intc_irq = IRQ_GPIO4; -+ } -+ else { -+ intc_irq = IRQ_GPIO5; -+ } -+ -+ enable_intc_irq(intc_irq); -+ __gpio_unmask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void disable_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void mask_and_ack_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+ __gpio_ack_irq(irq - IRQ_GPIO_0); -+} -+ -+static void end_gpio_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_gpio_irq(irq); -+ } -+} -+ -+static unsigned int startup_gpio_irq(unsigned int irq) -+{ -+ enable_gpio_irq(irq); -+ return 0; -+} -+ -+static void shutdown_gpio_irq(unsigned int irq) -+{ -+ disable_gpio_irq(irq); -+} -+ -+static struct irq_chip gpio_irq_type = { -+ .typename = "GPIO", -+ .startup = startup_gpio_irq, -+ .shutdown = shutdown_gpio_irq, -+ .enable = enable_gpio_irq, -+ .disable = disable_gpio_irq, -+ .ack = mask_and_ack_gpio_irq, -+ .end = end_gpio_irq, -+}; -+ -+/* -+ * DMA irq type -+ */ -+ -+static void enable_dma_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -+ intc_irq = IRQ_DMAC0; -+ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -+ intc_irq = IRQ_DMAC1; -+ else { -+ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -+ return; -+ } -+ __intc_unmask_irq(intc_irq); -+ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -+} -+ -+static void disable_dma_irq(unsigned int irq) -+{ -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void mask_and_ack_dma_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -+ intc_irq = IRQ_DMAC0; -+ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -+ intc_irq = IRQ_DMAC1; -+ else { -+ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -+ return ; -+ } -+ __intc_ack_irq(intc_irq); -+ __dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */ -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void end_dma_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_dma_irq(irq); -+ } -+} -+ -+static unsigned int startup_dma_irq(unsigned int irq) -+{ -+ enable_dma_irq(irq); -+ return 0; -+} -+ -+static void shutdown_dma_irq(unsigned int irq) -+{ -+ disable_dma_irq(irq); -+} -+ -+static struct irq_chip dma_irq_type = { -+ .typename = "DMA", -+ .startup = startup_dma_irq, -+ .shutdown = shutdown_dma_irq, -+ .enable = enable_dma_irq, -+ .disable = disable_dma_irq, -+ .ack = mask_and_ack_dma_irq, -+ .end = end_dma_irq, -+}; -+ -+//---------------------------------------------------------------------- -+ -+void __init arch_init_irq(void) -+{ -+ int i; -+ -+ clear_c0_status(0xff04); /* clear ERL */ -+ set_c0_status(0x0400); /* set IP2 */ -+ -+ /* Set up INTC irq -+ */ -+ for (i = 0; i < 32; i++) { -+ disable_intc_irq(i); -+ irq_desc[i].chip = &intc_irq_type; -+ } -+ -+ /* Set up DMAC irq -+ */ -+ for (i = 0; i < NUM_DMA; i++) { -+ disable_dma_irq(IRQ_DMA_0 + i); -+ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -+ } -+ -+ /* Set up GPIO irq -+ */ -+ for (i = 0; i < NUM_GPIO; i++) { -+ disable_gpio_irq(IRQ_GPIO_0 + i); -+ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -+ } -+} -+ -+static int plat_real_irq(int irq) -+{ -+ switch (irq) { -+ case IRQ_GPIO0: -+ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -+ break; -+ case IRQ_GPIO1: -+ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -+ break; -+ case IRQ_GPIO2: -+ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -+ break; -+ case IRQ_GPIO3: -+ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -+ break; -+ case IRQ_GPIO4: -+ irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128; -+ break; -+ case IRQ_GPIO5: -+ irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160; -+ break; -+ case IRQ_DMAC0: -+ case IRQ_DMAC1: -+ irq = __dmac_get_irq() + IRQ_DMA_0; -+ break; -+ } -+ -+ return irq; -+} -+ -+asmlinkage void plat_irq_dispatch(void) -+{ -+ int irq = 0; -+ static unsigned long intc_ipr = 0; -+ -+ intc_ipr |= REG_INTC_IPR; -+ -+ if (!intc_ipr) return; -+ -+ irq = ffs(intc_ipr) - 1; -+ intc_ipr &= ~(1< -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* OHCI (USB full speed host controller) */ -+static struct resource jz_usb_ohci_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -+ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UHC, -+ .end = IRQ_UHC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+/* The dmamask must be set for OHCI to work */ -+static u64 ohci_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_ohci_device = { -+ .name = "jz-ohci", -+ .id = 0, -+ .dev = { -+ .dma_mask = &ohci_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -+ .resource = jz_usb_ohci_resources, -+}; -+ -+/*** LCD controller ***/ -+static struct resource jz_lcd_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(LCD_BASE), -+ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_LCD, -+ .end = IRQ_LCD, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_lcd_dmamask = ~(u32)0; -+ -+static struct platform_device jz_lcd_device = { -+ .name = "jz-lcd", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_lcd_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_lcd_resources), -+ .resource = jz_lcd_resources, -+}; -+ -+/* UDC (USB gadget controller) */ -+static struct resource jz_usb_gdt_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UDC_BASE), -+ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UDC, -+ .end = IRQ_UDC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 udc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_gdt_device = { -+ .name = "jz-udc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &udc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -+ .resource = jz_usb_gdt_resources, -+}; -+ -+/** MMC/SD controller **/ -+static struct resource jz_mmc_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(MSC_BASE), -+ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_MSC0, -+ .end = IRQ_MSC0, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_mmc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_mmc_device = { -+ .name = "jz-mmc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_mmc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_mmc_resources), -+ .resource = jz_mmc_resources, -+}; -+ -+/* All */ -+static struct platform_device *jz_platform_devices[] __initdata = { -+ &jz_usb_ohci_device, -+ &jz_lcd_device, -+ &jz_usb_gdt_device, -+ &jz_mmc_device, -+}; -+ -+static int __init jz_platform_init(void) -+{ -+ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -+} -+ -+arch_initcall(jz_platform_init); -diff --git a/arch/mips/jz4750/pm.c b/arch/mips/jz4750/pm.c -new file mode 100644 -index 0000000..b918cb2 ---- /dev/null -+++ b/arch/mips/jz4750/pm.c -@@ -0,0 +1,463 @@ -+/* -+ * linux/arch/mips/jz4750/common/pm.c -+ * -+ * JZ4750 Power Management Routines -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+ -+#define GPIO_PORT_NUM 6 -+ -+/* -+ * __gpio_as_sleep set all pins to pull-disable, and set all pins as input -+ * except sdram and the pins which can be used as CS1_N to CS4_N for chip select. -+ */ -+#define __gpio_as_sleep() \ -+do { \ -+ REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = ~0x03ff7fff; \ -+ REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(2) = ~0x01e00000; \ -+ REG_GPIO_PXSELC(2) = ~0x01e00000; \ -+ REG_GPIO_PXDIRC(2) = ~0x01e00000; \ -+ REG_GPIO_PXPES(2) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(3) = 0xffffffff; \ -+ REG_GPIO_PXSELC(3) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(3) = 0xffffffff; \ -+ REG_GPIO_PXPES(3) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(4) = 0xffffffff; \ -+ REG_GPIO_PXSELC(4) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(4) = 0xffffffff; \ -+ REG_GPIO_PXPES(4) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(5) = 0xffffffff; \ -+ REG_GPIO_PXSELC(5) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(5) = 0xffffffff; \ -+ REG_GPIO_PXPES(5) = 0xffffffff; \ -+} while (0) -+ -+static int jz_pm_do_hibernate(void) -+{ -+ printk("Put CPU into hibernate mode.\n"); -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* -+ * RTC Wakeup or 1Hz interrupt can be enabled or disabled -+ * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). -+ */ -+ -+ /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); -+ -+ /* Set reset pin low-level assertion time after wakeup: must > 60ms */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ -+ -+ /* Scratch pad register to be reserved */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HSPR = 0x12345678; -+ -+ /* clear wakeup status register */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HWRSR = 0x0; -+ -+ /* Put CPU to power down mode */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HCR = RTC_HCR_PD; -+ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ while(1); -+ -+ /* We can't get here */ -+ return 0; -+} -+ -+/* NOTES: -+ * 1: Pins that are floated (NC) should be set as input and pull-enable. -+ * 2: Pins that are pull-up or pull-down by outside should be set as input -+ * and pull-disable. -+ * 3: Pins that are connected to a chip except sdram and nand flash -+ * should be set as input and pull-disable, too. -+ */ -+static void jz_board_do_sleep(unsigned long *ptr) -+{ -+ unsigned char i; -+ -+ /* Print messages of GPIO registers for debug */ -+ for(i=0;i -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#define DEBUG 1 -+#undef DEBUG -+ -+ -+struct proc_dir_entry *proc_jz_root; -+ -+ -+/* -+ * EMC Modules -+ */ -+static int emc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); -+ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); -+ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -+ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -+ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -+ return len; -+} -+ -+/* -+ * Power Manager Module -+ */ -+static int pmc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned long lcr = REG_CPM_LCR; -+ unsigned long clkgr = REG_CPM_CLKGR; -+ -+ len += sprintf (page+len, "Low Power Mode : %s\n", -+ ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? -+ "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? -+ "SLEEP" : "HIBERNATE")); -+ len += sprintf (page+len, "Doze Mode : %s\n", -+ (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); -+ if (lcr & CPM_LCR_DOZE_ON) -+ len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); -+ len += sprintf (page+len, "IPU : %s\n", -+ (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); -+ len += sprintf (page+len, "DMAC : %s\n", -+ (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); -+ len += sprintf (page+len, "UHC : %s\n", -+ (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); -+ len += sprintf (page+len, "UDC : %s\n", -+ (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); -+ len += sprintf (page+len, "LCD : %s\n", -+ (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); -+ len += sprintf (page+len, "CIM : %s\n", -+ (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); -+ len += sprintf (page+len, "SADC : %s\n", -+ (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); -+ len += sprintf (page+len, "MSC0 : %s\n", -+ (clkgr & CPM_CLKGR_MSC0) ? "stopped" : "running"); -+ len += sprintf (page+len, "MSC1 : %s\n", -+ (clkgr & CPM_CLKGR_MSC1) ? "stopped" : "running"); -+ len += sprintf (page+len, "AIC1 : %s\n", -+ (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); -+ len += sprintf (page+len, "AIC2 : %s\n", -+ (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); -+ len += sprintf (page+len, "SSI0 : %s\n", -+ (clkgr & CPM_CLKGR_SSI0) ? "stopped" : "running"); -+ len += sprintf (page+len, "SSI1 : %s\n", -+ (clkgr & CPM_CLKGR_SSI1) ? "stopped" : "running"); -+ len += sprintf (page+len, "I2C : %s\n", -+ (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); -+ len += sprintf (page+len, "RTC : %s\n", -+ (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); -+ len += sprintf (page+len, "TCU : %s\n", -+ (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART1 : %s\n", -+ (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART0 : %s\n", -+ (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); -+ return len; -+} -+ -+static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+/* -+ * Clock Generation Module -+ */ -+#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 -+#define TO_KHZ(x) (x/1000),(x%1000)/10 -+ -+static int cgm_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ -+ unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ -+ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int od[4] = {1, 2, 2, 4}; -+ -+ len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); -+ len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); -+ len += sprintf (page+len, "PLL : %s\n", -+ (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); -+ len += sprintf (page+len, "m:n:o : %d:%d:%d\n", -+ __cpm_get_pllm() + 2, -+ __cpm_get_plln() + 2, -+ od[__cpm_get_pllod()] -+ ); -+ len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", -+ div[__cpm_get_cdiv()], -+ div[__cpm_get_hdiv()], -+ div[__cpm_get_mdiv()], -+ div[__cpm_get_pdiv()] -+ ); -+ len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); -+ len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); -+ len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); -+ len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); -+ len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); -+ len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); -+ len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); -+ len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); -+ len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); -+ len += sprintf (page+len, "MSC0CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(0))); -+ len += sprintf (page+len, "MSC1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(1))); -+ len += sprintf (page+len, "EXTALCLK0 : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk0())); -+ len += sprintf (page+len, "EXTALCLK(by CPM): %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); -+ len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); -+ -+ return len; -+} -+ -+static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+ -+/* USAGE: -+ * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. -+ * echo FF > /proc/jz/ipu // 255, free all buffer -+ * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx -+ * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) -+ * echo 0 > /proc/jz/ipu // debug, print ipu_buf -+ * od -X /proc/jz/ipu // read mem addr -+ */ -+ -+typedef struct _ipu_buf { -+ unsigned int addr; /* phys addr */ -+ unsigned int page_shift; -+} ipu_buf_t; -+ -+#define IPU_BUF_MAX 4 /* 4 buffers */ -+ -+static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -+static int ipu_buf_cnt = 0; -+static unsigned char g_asid=0; -+ -+extern void local_flush_tlb_all(void); -+ -+/* CP0 hazard avoidance. */ -+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ -+ "nop; nop; nop; nop; nop; nop;\n\t" \ -+ ".set reorder\n\t") -+void show_tlb(void) -+{ -+#define ASID_MASK 0xFF -+ -+ unsigned long flags; -+ unsigned int old_ctx; -+ unsigned int entry; -+ unsigned int entrylo0, entrylo1, entryhi; -+ unsigned int pagemask; -+ -+ local_irq_save(flags); -+ -+ /* Save old context */ -+ old_ctx = (read_c0_entryhi() & 0xff); -+ -+ printk("TLB content:\n"); -+ entry = 0; -+ while(entry < 32) { -+ write_c0_index(entry); -+ BARRIER; -+ tlb_read(); -+ BARRIER; -+ entryhi = read_c0_entryhi(); -+ entrylo0 = read_c0_entrylo0(); -+ entrylo1 = read_c0_entrylo1(); -+ pagemask = read_c0_pagemask(); -+ printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); -+ printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); -+ printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); -+ -+ printk("\t\tpagemask=0x%08x", pagemask); -+ printk("\tentryhi=0x%08x\n", entryhi); -+ printk("\t\tentrylo0=0x%08x", entrylo0); -+ printk("\tentrylo1=0x%08x\n", entrylo1); -+ -+ entry++; -+ } -+ BARRIER; -+ write_c0_entryhi(old_ctx); -+ -+ local_irq_restore(flags); -+} -+ -+static void ipu_add_wired_entry(unsigned long pid, -+ unsigned long entrylo0, unsigned long entrylo1, -+ unsigned long entryhi, unsigned long pagemask) -+{ -+ unsigned long flags; -+ unsigned long wired; -+ unsigned long old_pagemask; -+ unsigned long old_ctx; -+ struct task_struct *g, *p; -+ -+ /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ -+ entrylo0 = entrylo0 >> 6; -+ entrylo0 |= 0x6 | (0 << 3); -+ /*entrylo0 |= 0x6 | (1 << 3);*/ -+ -+ do_each_thread(g, p) { -+ if (p->pid == pid ) -+ g_asid = p->mm->context[0]; -+ } while_each_thread(g, p); -+ -+ local_irq_save(flags); -+ /* Save old context and create impossible VPN2 value */ -+ old_ctx = read_c0_entryhi() & 0xff; -+ old_pagemask = read_c0_pagemask(); -+ wired = read_c0_wired(); -+ write_c0_wired(wired + 1); -+ write_c0_index(wired); -+ BARRIER; -+ entryhi &= ~0xff; /* new add, 20070906 */ -+ entryhi |= g_asid; /* new add, 20070906 */ -+// entryhi |= old_ctx; /* new add, 20070906 */ -+ write_c0_pagemask(pagemask); -+ write_c0_entryhi(entryhi); -+ write_c0_entrylo0(entrylo0); -+ write_c0_entrylo1(entrylo1); -+ BARRIER; -+ tlb_write_indexed(); -+ BARRIER; -+ -+ write_c0_entryhi(old_ctx); -+ BARRIER; -+ write_c0_pagemask(old_pagemask); -+ local_flush_tlb_all(); -+ local_irq_restore(flags); -+#if defined(DEBUG) -+ printk("\nold_ctx=%03d\n", old_ctx); -+ -+ show_tlb(); -+#endif -+} -+ -+static void ipu_del_wired_entry( void ) -+{ -+ unsigned long flags; -+ unsigned long wired; -+ -+ local_irq_save(flags); -+ wired = read_c0_wired(); -+ if (wired) { -+ write_c0_wired(0); -+ } -+ local_irq_restore(flags); -+} -+ -+static inline void ipu_buf_get( unsigned int page_shift ) -+{ -+ unsigned char * virt_addr; -+ int i; -+ for ( i=0; i< IPU_BUF_MAX; ++i ) { -+ if ( ipu_buf[i].addr == 0 ) { -+ break; -+ } -+ } -+ -+ if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { -+ printk("Error, no free ipu buffer.\n"); -+ return ; -+ } -+ -+ virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ -+ if ( virt_addr ) { -+ ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); -+ ipu_buf[ipu_buf_cnt].page_shift = page_shift; -+ -+ for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ -+ printk("no free buffer.\n"); -+ *pint = 0; -+ } -+ else -+ *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ -+ len += sizeof(unsigned int); -+ -+#if defined(DEBUG) -+ show_tlb(); -+#endif -+ return len; -+ -+} -+ -+static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int val ; -+ int cnt,i; -+ char buf[12]; -+ unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -+#if defined(DEBUG) -+ printk("ipu write count=%u\n", count); -+#endif -+ if (count == 41) { -+ for (i=0;i<12;i++) -+ buf[i]=0; -+ strncpy(buf, buffer+8*0, 8); -+ pid = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) -+ buf[i]=0; -+ strncpy(buf, buffer+8*1, 8); -+ entrylo0 = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) -+ buf[i]=0; -+ strncpy(buf, buffer+8*2, 8); -+ entrylo1 = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) -+ buf[i]=0; -+ strncpy(buf, buffer+8*3, 8); -+ entryhi = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) -+ buf[i]=0; -+ strncpy(buf, buffer+8*4, 8); -+ pagemask = simple_strtoul(buf, 0, 16); -+ -+#if defined(DEBUG) -+ printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", -+ pid, entrylo0, entrylo1, entryhi, pagemask); -+#endif -+ ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); -+ return 41; -+ } else if ( count <= 9 ) { -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer, 8); -+ val = simple_strtoul(buf, 0, 16); -+ } else if (count == 44) { -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer, 10); -+ pid = simple_strtoul(buf, 0, 16); -+ -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 11, 10); -+ entryhi = simple_strtoul(buf, 0, 16);//vaddr -+ -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 22, 10); -+ entrylo0 = simple_strtoul(buf, 0, 16);//paddr -+ -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 33, 10); -+ pagemask = simple_strtoul(buf, 0, 16); -+ pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ -+ //pagemask = 0xfff << 13; /* Fixed to 16MB page size */ -+ -+ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); -+ return 44; -+ } else if (count == 12) { -+ printk("\necho release tlb > /proc/jz/ipu\n"); -+ ipu_del_wired_entry(); -+ return 12; -+ } else { -+ printk("ipu write count error, count=%d\n.", (unsigned int)count); -+ return -1; -+ } -+ -+ /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ -+ if ( val == 0 ) { /* debug, print ipu_buf info */ -+ for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages -+ * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx -+ * echo FF > /proc/jz/ipu // FF, free all buffers -+ * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer -+ */ -+ -+//#define DEBUG_IMEM 1 -+ -+#define IMEM_MAX_ORDER 12 /* max 2^10 * 4096 = 4MB */ -+ -+static unsigned int jz_imem_base; /* physical base address of ipu memory */ -+ -+static unsigned int allocated_phys_addr = 0; -+ -+/* -+ * Allocated buffer list -+ */ -+typedef struct imem_list { -+ unsigned int phys_start; /* physical start addr */ -+ unsigned int phys_end; /* physical end addr */ -+ struct imem_list *next; -+} imem_list_t; -+ -+static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ -+ -+#ifdef DEBUG_IMEM -+static void dump_imem_list(void) -+{ -+ struct imem_list *imem; -+ -+ printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); -+ imem = imem_list_head; -+ while (imem) { -+ printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); -+ imem = imem->next; -+ } -+} -+#endif -+ -+/* allocate 2^order pages inside the 4MB memory */ -+static int imem_alloc(unsigned int order) -+{ -+ int alloc_ok = 0; -+ unsigned int start, end; -+ unsigned int size = (1 << order) * PAGE_SIZE; -+ struct imem_list *imem, *imemn, *imemp; -+ -+ allocated_phys_addr = 0; -+ -+ start = jz_imem_base; -+ end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -+ -+ imem = imem_list_head; -+ while (imem) { -+ if ((imem->phys_start - start) >= size) { -+ /* we got a valid address range */ -+ alloc_ok = 1; -+ break; -+ } -+ -+ start = imem->phys_end + 1; -+ imem = imem->next; -+ } -+ -+ if (!alloc_ok) { -+ if ((end - start) >= size) -+ alloc_ok = 1; -+ } -+ -+ if (alloc_ok) { -+ end = start + size - 1; -+ allocated_phys_addr = start; -+ -+ /* add to imem_list, up sorted by phys_start */ -+ imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); -+ if (!imemn) { -+ return -ENOMEM; -+ } -+ imemn->phys_start = start; -+ imemn->phys_end = end; -+ imemn->next = NULL; -+ -+ if (!imem_list_head) -+ imem_list_head = imemn; -+ else { -+ imem = imemp = imem_list_head; -+ while (imem) { -+ if (start < imem->phys_start) { -+ break; -+ } -+ -+ imemp = imem; -+ imem = imem->next; -+ } -+ -+ if (imem == imem_list_head) { -+ imem_list_head = imemn; -+ imemn->next = imem; -+ } -+ else { -+ imemn->next = imemp->next; -+ imemp->next = imemn; -+ } -+ } -+ } -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+ return 0; -+} -+ -+static void imem_free(unsigned int phys_addr) -+{ -+ struct imem_list *imem, *imemp; -+ -+ imem = imemp = imem_list_head; -+ while (imem) { -+ if (phys_addr == imem->phys_start) { -+ if (imem == imem_list_head) { -+ imem_list_head = imem->next; -+ } -+ else { -+ imemp->next = imem->next; -+ } -+ -+ kfree(imem); -+ break; -+ } -+ -+ imemp = imem; -+ imem = imem->next; -+ } -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+} -+ -+static void imem_free_all(void) -+{ -+ struct imem_list *imem; -+ -+ imem = imem_list_head; -+ while (imem) { -+ kfree(imem); -+ imem = imem->next; -+ } -+ -+ imem_list_head = NULL; -+ -+ allocated_phys_addr = 0; -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+} -+ -+/* -+ * Return the allocated buffer address and the max order of free buffer -+ */ -+static int imem_read_proc(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int start_addr, end_addr, max_order, max_size; -+ struct imem_list *imem; -+ -+ unsigned int *tmp = (unsigned int *)(page + len); -+ -+ start_addr = jz_imem_base; -+ end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -+ -+ if (!imem_list_head) -+ max_size = end_addr - start_addr; -+ else { -+ max_size = 0; -+ imem = imem_list_head; -+ while (imem) { -+ if (max_size < (imem->phys_start - start_addr)) -+ max_size = imem->phys_start - start_addr; -+ -+ start_addr = imem->phys_end + 1; -+ imem = imem->next; -+ } -+ -+ if (max_size < (end_addr - start_addr)) -+ max_size = end_addr - start_addr; -+ } -+ -+ if (max_size > 0) { -+ max_order = get_order(max_size); -+ if (((1 << max_order) * PAGE_SIZE) > max_size) -+ max_order--; -+ } -+ else { -+ max_order = 0xffffffff; /* No any free buffer */ -+ } -+ -+ *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ -+ *tmp = max_order; /* max order of current free buffers */ -+ -+ len += 2 * sizeof(unsigned int); -+ -+ return len; -+} -+ -+static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int val; -+ -+ val = simple_strtoul(buffer, 0, 16); -+ -+ if (val == 0xff) { -+ /* free all memory */ -+ imem_free_all(); -+ ipu_del_wired_entry(); -+ } else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { -+ /* allocate 2^val pages */ -+ imem_alloc(val); -+ } else { -+ /* free buffer which phys_addr is val */ -+ imem_free(val); -+ } -+ -+ return count; -+} -+ -+/* -+ * /proc/jz/xxx entry -+ * -+ */ -+static int __init jz_proc_init(void) -+{ -+ struct proc_dir_entry *res; -+ unsigned int virt_addr, i; -+ -+ proc_jz_root = proc_mkdir("jz", 0); -+ -+ /* External Memory Controller */ -+ res = create_proc_entry("emc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = emc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* Power Management Controller */ -+ res = create_proc_entry("pmc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = pmc_read_proc; -+ res->write_proc = pmc_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Clock Generation Module */ -+ res = create_proc_entry("cgm", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = cgm_read_proc; -+ res->write_proc = cgm_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Image process unit */ -+ res = create_proc_entry("ipu", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = ipu_read_proc; -+ res->write_proc = ipu_write_proc; -+ res->data = NULL; -+ } -+ -+ /* udc hotplug */ -+ res = create_proc_entry("udc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = udc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* mmc hotplug */ -+ res = create_proc_entry("mmc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = mmc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* show tlb */ -+ res = create_proc_entry("tlb", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = tlb_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* -+ * Reserve a 4MB memory for IPU on JZ4750. -+ */ -+ jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); -+ if (jz_imem_base) { -+ /* imem (IPU memory management) */ -+ res = create_proc_entry("imem", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = imem_read_proc; -+ res->write_proc = imem_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Set page reserved */ -+ virt_addr = jz_imem_base; -+ for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { -+ SetPageReserved(virt_to_page((void *)virt_addr)); -+ virt_addr += PAGE_SIZE; -+ } -+ -+ /* Convert to physical address */ -+ jz_imem_base = virt_to_phys((void *)jz_imem_base); -+ -+ printk("Total %dMB memory at 0x%x was reserved for IPU\n", -+ (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); -+ } else -+ printk("NOT enough memory for imem\n"); -+ -+ return 0; -+} -+ -+__initcall(jz_proc_init); -diff --git a/arch/mips/jz4750/prom.c b/arch/mips/jz4750/prom.c -new file mode 100644 -index 0000000..d04bb3e ---- /dev/null -+++ b/arch/mips/jz4750/prom.c -@@ -0,0 +1,198 @@ -+/* -+ * -+ * BRIEF MODULE DESCRIPTION -+ * PROM library initialisation code, supports YAMON and U-Boot. -+ * -+ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * ppopov@mvista.com or source@mvista.com -+ * -+ * This file was derived from Carsten Langgaard's -+ * arch/mips/mips-boards/xx files. -+ * -+ * Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* #define DEBUG_CMDLINE */ -+ -+int prom_argc; -+char **prom_argv, **prom_envp; -+ -+char * prom_getcmdline(void) -+{ -+ return &(arcs_cmdline[0]); -+} -+ -+void prom_init_cmdline(void) -+{ -+ char *cp; -+ int actr; -+ -+ actr = 1; /* Always ignore argv[0] */ -+ -+ cp = &(arcs_cmdline[0]); -+ while(actr < prom_argc) { -+ strcpy(cp, prom_argv[actr]); -+ cp += strlen(prom_argv[actr]); -+ *cp++ = ' '; -+ actr++; -+ } -+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -+ --cp; -+ if (prom_argc > 1) -+ *cp = '\0'; -+ -+} -+ -+ -+char *prom_getenv(char *envname) -+{ -+#if 0 -+ /* -+ * Return a pointer to the given environment variable. -+ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -+ */ -+ -+ char **env = prom_envp; -+ int i = strlen(envname); -+ int yamon = (*env && strchr(*env, '=') == NULL); -+ -+ while (*env) { -+ if (yamon) { -+ if (strcmp(envname, *env++) == 0) -+ return *env; -+ } else { -+ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -+ return *env + i + 1; -+ } -+ env++; -+ } -+#endif -+ return NULL; -+} -+ -+inline unsigned char str2hexnum(unsigned char c) -+{ -+ if(c >= '0' && c <= '9') -+ return c - '0'; -+ if(c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ if(c >= 'A' && c <= 'F') -+ return c - 'A' + 10; -+ return 0; /* foo */ -+} -+ -+inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; -+ -+ for(i = 0; i < 6; i++) { -+ unsigned char num; -+ -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} -+ -+int get_ethernet_addr(char *ethernet_addr) -+{ -+ char *ethaddr_str; -+ -+ ethaddr_str = prom_getenv("ethaddr"); -+ if (!ethaddr_str) { -+ printk("ethaddr not set in boot prom\n"); -+ return -1; -+ } -+ str2eaddr(ethernet_addr, ethaddr_str); -+ -+#if 0 -+ { -+ int i; -+ -+ printk("get_ethernet_addr: "); -+ for (i=0; i<5; i++) -+ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -+ printk("%02x\n", *(ethernet_addr+i)); -+ } -+#endif -+ -+ return 0; -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init prom_init(void) -+{ -+ unsigned char *memsize_str; -+ unsigned long memsize; -+ -+ prom_argc = (int) fw_arg0; -+ prom_argv = (char **) fw_arg1; -+ prom_envp = (char **) fw_arg2; -+ -+ mips_machtype = MACH_INGENIC_JZ4750; -+ -+ prom_init_cmdline(); -+ memsize_str = prom_getenv("memsize"); -+ if (!memsize_str) { -+ memsize = 0x04000000; -+ } else { -+ memsize = simple_strtol(memsize_str, NULL, 0); -+ } -+ add_memory_region(0, memsize, BOOT_MEM_RAM); -+} -+ -+/* used by early printk */ -+void prom_putchar(char c) -+{ -+ volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR); -+ volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR); -+ -+ /* Wait for fifo to shift out some bytes */ -+ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -+ -+ *uart_tdr = (u8)c; -+} -+ -+const char *get_system_type(void) -+{ -+ return "JZ4750"; -+} -+ -+EXPORT_SYMBOL(prom_getcmdline); -+EXPORT_SYMBOL(get_ethernet_addr); -+EXPORT_SYMBOL(str2eaddr); -diff --git a/arch/mips/jz4750/reset.c b/arch/mips/jz4750/reset.c -new file mode 100644 -index 0000000..90b521e ---- /dev/null -+++ b/arch/mips/jz4750/reset.c -@@ -0,0 +1,46 @@ -+/* -+ * linux/arch/mips/jz4750/reset.c -+ * -+ * JZ4750 reset routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+void jz_restart(char *command) -+{ -+ printk("Restarting after 4 ms\n"); -+ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; -+ REG_WDT_TCNT = 0; -+ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ -+ REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */ -+ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ -+ while (1); -+} -+ -+void jz_halt(void) -+{ -+ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -+ -+ while (1) -+ __asm__(".set\tmips3\n\t" -+ "wait\n\t" -+ ".set\tmips0"); -+} -+ -+void jz_power_off(void) -+{ -+ jz_halt(); -+} -diff --git a/arch/mips/jz4750/setup.c b/arch/mips/jz4750/setup.c -new file mode 100644 -index 0000000..b9b4240 ---- /dev/null -+++ b/arch/mips/jz4750/setup.c -@@ -0,0 +1,197 @@ -+/* -+ * linux/arch/mips/jz4750/common/setup.c -+ * -+ * JZ4750 common setup routines. -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_PC_KEYB -+#include -+#endif -+ -+jz_clocks_t jz_clocks; -+ -+extern char * __init prom_getcmdline(void); -+extern void __init jz_board_setup(void); -+extern void jz_restart(char *); -+extern void jz_halt(void); -+extern void jz_power_off(void); -+extern void jz_time_init(void); -+ -+static void __init sysclocks_setup(void) -+{ -+#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ -+ jz_clocks.cclk = __cpm_get_cclk(); -+ jz_clocks.hclk = __cpm_get_hclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(0); -+ jz_clocks.extalclk = __cpm_get_extalclk(); -+ jz_clocks.rtcclk = __cpm_get_rtcclk(); -+#else -+ -+#define FPGACLK 8000000 -+ -+ jz_clocks.cclk = FPGACLK; -+ jz_clocks.hclk = FPGACLK; -+ jz_clocks.pclk = FPGACLK; -+ jz_clocks.mclk = FPGACLK; -+ jz_clocks.lcdclk = FPGACLK; -+ jz_clocks.pixclk = FPGACLK; -+ jz_clocks.i2sclk = FPGACLK; -+ jz_clocks.usbclk = FPGACLK; -+ jz_clocks.mscclk = FPGACLK; -+ jz_clocks.extalclk = FPGACLK; -+ jz_clocks.rtcclk = FPGACLK; -+#endif -+ -+ printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", -+ (jz_clocks.cclk + 500000) / 1000000, -+ (jz_clocks.hclk + 500000) / 1000000, -+ (jz_clocks.pclk + 500000) / 1000000, -+ (jz_clocks.mclk + 500000) / 1000000); -+} -+ -+static void __init soc_cpm_setup(void) -+{ -+ /* Start all module clocks -+ */ -+ __cpm_start_all(); -+ -+ /* Enable CKO to external memory */ -+ __cpm_enable_cko(); -+ -+ /* CPU enters IDLE mode when executing 'wait' instruction */ -+ __cpm_idle_mode(); -+ -+ /* Setup system clocks */ -+ sysclocks_setup(); -+} -+ -+static void __init soc_harb_setup(void) -+{ -+// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -+} -+ -+static void __init soc_emc_setup(void) -+{ -+} -+ -+static void __init soc_dmac_setup(void) -+{ -+ __dmac_enable_module(0); -+ __dmac_enable_module(1); -+} -+ -+static void __init jz_soc_setup(void) -+{ -+ soc_cpm_setup(); -+ soc_harb_setup(); -+ soc_emc_setup(); -+ soc_dmac_setup(); -+} -+ -+static void __init jz_serial_setup(void) -+{ -+#ifdef CONFIG_SERIAL_8250 -+ struct uart_port s; -+ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ -+ memset(&s, 0, sizeof(s)); -+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -+ s.iotype = SERIAL_IO_MEM; -+ s.regshift = 2; -+ s.uartclk = jz_clocks.extalclk ; -+ -+ s.line = 0; -+ s.membase = (u8 *)UART0_BASE; -+ s.irq = IRQ_UART0; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -+ } -+ -+ s.line = 1; -+ s.membase = (u8 *)UART1_BASE; -+ s.irq = IRQ_UART1; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -+ } -+ -+ s.line = 2; -+ s.membase = (u8 *)UART2_BASE; -+ s.irq = IRQ_UART2; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS2 setup failed!\n"); -+ } -+ -+ s.line = 3; -+ s.membase = (u8 *)UART3_BASE; -+ s.irq = IRQ_UART3; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS3 setup failed!\n"); -+ } -+#endif -+} -+ -+void __init plat_mem_setup(void) -+{ -+ char *argptr; -+ -+ argptr = prom_getcmdline(); -+ -+ /* IO/MEM resources. Which will be the addtion value in `inX' and -+ * `outX' macros defined in asm/io.h */ -+ set_io_port_base(0); -+ ioport_resource.start = 0x00000000; -+ ioport_resource.end = 0xffffffff; -+ iomem_resource.start = 0x00000000; -+ iomem_resource.end = 0xffffffff; -+ -+ _machine_restart = jz_restart; -+ _machine_halt = jz_halt; -+ pm_power_off = jz_power_off; -+ -+ jz_soc_setup(); -+ jz_serial_setup(); -+ jz_board_setup(); -+} -+ -diff --git a/arch/mips/jz4750/time.c b/arch/mips/jz4750/time.c -new file mode 100644 -index 0000000..e5d18b5 ---- /dev/null -+++ b/arch/mips/jz4750/time.c -@@ -0,0 +1,156 @@ -+/* -+ * linux/arch/mips/jz4750/time.c -+ * -+ * Setting up the clock on the JZ4750 boards. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* This is for machines which generate the exact clock. */ -+ -+#define JZ_TIMER_IRQ IRQ_TCU0 -+ -+#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ -+ -+static struct clocksource clocksource_jz; /* Jz clock source */ -+static struct clock_event_device jz_clockevent_device; /* Jz clock event */ -+ -+void (*jz_timer_callback)(void); -+ -+static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *cd = dev_id; -+ -+ REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */ -+ -+ if (jz_timer_callback) -+ jz_timer_callback(); -+ -+ cd->event_handler(cd); -+ -+ return IRQ_HANDLED; -+} -+ -+static struct irqaction jz_irqaction = { -+ .handler = jz_timer_interrupt, -+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, -+ .name = "jz-timerirq", -+}; -+ -+ -+cycle_t jz_get_cycles(void) -+{ -+ /* convert jiffes to jz timer cycles */ -+ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT); -+} -+ -+static struct clocksource clocksource_jz = { -+ .name = "jz_clocksource", -+ .rating = 300, -+ .read = jz_get_cycles, -+ .mask = 0xFFFFFFFF, -+ .shift = 10, -+ .flags = CLOCK_SOURCE_WATCHDOG, -+}; -+ -+static int __init jz_clocksource_init(void) -+{ -+ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -+ clocksource_register(&clocksource_jz); -+ return 0; -+} -+ -+static int jz_set_next_event(unsigned long evt, -+ struct clock_event_device *unused) -+{ -+ return 0; -+} -+ -+static void jz_set_mode(enum clock_event_mode mode, -+ struct clock_event_device *evt) -+{ -+ switch (mode) { -+ case CLOCK_EVT_MODE_PERIODIC: -+ break; -+ case CLOCK_EVT_MODE_ONESHOT: -+ case CLOCK_EVT_MODE_UNUSED: -+ case CLOCK_EVT_MODE_SHUTDOWN: -+ break; -+ case CLOCK_EVT_MODE_RESUME: -+ break; -+ } -+} -+ -+static struct clock_event_device jz_clockevent_device = { -+ .name = "jz-clockenvent", -+ .features = CLOCK_EVT_FEAT_PERIODIC, -+// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ -+ -+ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -+ .rating = 300, -+ .irq = JZ_TIMER_IRQ, -+ .set_mode = jz_set_mode, -+ .set_next_event = jz_set_next_event, -+}; -+ -+static void __init jz_clockevent_init(void) -+{ -+ struct clock_event_device *cd = &jz_clockevent_device; -+ unsigned int cpu = smp_processor_id(); -+ -+ cd->cpumask = cpumask_of_cpu(cpu); -+ clockevents_register_device(cd); -+} -+ -+static void __init jz_timer_setup(void) -+{ -+ jz_clocksource_init(); /* init jz clock source */ -+ jz_clockevent_init(); /* init jz clock event */ -+ -+ /* -+ * Make irqs happen for the system timer -+ */ -+ jz_irqaction.dev_id = &jz_clockevent_device; -+ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -+} -+ -+ -+void __init plat_time_init(void) -+{ -+ unsigned int latch; -+ -+ /* Init timer */ -+ latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -+ -+ REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN; -+ REG_TCU_OSTCNT = 0; -+ REG_TCU_OSTDR = latch; -+ -+ REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */ -+ REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */ -+ REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */ -+ -+ jz_timer_setup(); -+} -diff --git a/arch/mips/jz4750d/Makefile b/arch/mips/jz4750d/Makefile -new file mode 100644 -index 0000000..6bd5189 ---- /dev/null -+++ b/arch/mips/jz4750d/Makefile -@@ -0,0 +1,23 @@ -+# -+# Makefile for the Ingenic JZ4750D. -+# -+ -+# Object file lists. -+ -+obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -+ platform.o i2c.o -+ -+obj-$(CONFIG_PROC_FS) += proc.o -+ -+# board specific support -+ -+obj-$(CONFIG_JZ4750D_FUWA1) += board-fuwa1.o -+obj-$(CONFIG_JZ4750D_CETUS) += board-cetus.o -+ -+# PM support -+ -+obj-$(CONFIG_PM_LEGACY) +=pm.o -+ -+# CPU Frequency scaling support -+ -+obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -diff --git a/arch/mips/jz4750d/board-cetus.c b/arch/mips/jz4750d/board-cetus.c -new file mode 100644 -index 0000000..0febbd3 ---- /dev/null -+++ b/arch/mips/jz4750d/board-cetus.c -@@ -0,0 +1,72 @@ -+/* -+ * linux/arch/mips/jz4750d/board-cetus.c -+ * -+ * JZ4750D CETUS board setup routines. -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned char slash[] = "\\|/-"; -+// static volatile unsigned char *p = (unsigned char *)0xb6000058; -+ static volatile unsigned char *p = (unsigned char *)0xb6000016; -+ static unsigned int count = 0; -+ *p = slash[count++]; -+ count &= 3; -+} -+ -+static void cetus_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4750d/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Initialize SDRAM pins -+ */ -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4750D CETUS board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = cetus_timer_callback; -+} -diff --git a/arch/mips/jz4750d/board-fuwa1.c b/arch/mips/jz4750d/board-fuwa1.c -new file mode 100644 -index 0000000..e9294c3 ---- /dev/null -+++ b/arch/mips/jz4750d/board-fuwa1.c -@@ -0,0 +1,72 @@ -+/* -+ * linux/arch/mips/jz4750d/board-fuwa1.c -+ * -+ * JZ4750D FUWA1 board setup routines. -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void (*jz_timer_callback)(void); -+ -+static void dancing(void) -+{ -+ static unsigned char slash[] = "\\|/-"; -+// static volatile unsigned char *p = (unsigned char *)0xb6000058; -+ static volatile unsigned char *p = (unsigned char *)0xb6000016; -+ static unsigned int count = 0; -+ *p = slash[count++]; -+ count &= 3; -+} -+ -+static void fuwa1_timer_callback(void) -+{ -+ static unsigned long count = 0; -+ -+ if ((++count) % 50 == 0) { -+ dancing(); -+ count = 0; -+ } -+} -+ -+static void __init board_cpm_setup(void) -+{ -+ /* Stop unused module clocks here. -+ * We have started all module clocks at arch/mips/jz4750d/setup.c. -+ */ -+} -+ -+static void __init board_gpio_setup(void) -+{ -+ /* -+ * Initialize SDRAM pins -+ */ -+} -+ -+void __init jz_board_setup(void) -+{ -+ printk("JZ4750D FUWA1 board setup\n"); -+ -+ board_cpm_setup(); -+ board_gpio_setup(); -+ -+ jz_timer_callback = fuwa1_timer_callback; -+} -diff --git a/arch/mips/jz4750d/cpufreq.c b/arch/mips/jz4750d/cpufreq.c -new file mode 100644 -index 0000000..c0d63ac ---- /dev/null -+++ b/arch/mips/jz4750d/cpufreq.c -@@ -0,0 +1,598 @@ -+/* -+ * linux/arch/mips/jz4750d/cpufreq.c -+ * -+ * cpufreq driver for JZ4750D -+ * -+ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -+ "cpufreq-jz4750d", msg) -+ -+#undef CHANGE_PLL -+ -+#define PLL_UNCHANGED 0 -+#define PLL_GOES_UP 1 -+#define PLL_GOES_DOWN 2 -+ -+#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) -+ -+/* Saved the boot-time parameters */ -+static struct { -+ /* SDRAM parameters */ -+ unsigned int mclk; /* memory clock, KHz */ -+ unsigned int tras; /* RAS pulse width, cycles of mclk */ -+ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -+ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -+ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -+ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -+ unsigned int rtcor; /* Refresh Time Constant */ -+ unsigned int sdram_initialized; -+ -+ /* LCD parameters */ -+ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -+ unsigned int lcd_clks_initialized; -+} boot_config; -+ -+struct jz4750d_freq_percpu_info { -+ struct cpufreq_frequency_table table[7]; -+}; -+ -+static struct jz4750d_freq_percpu_info jz4750d_freq_table; -+ -+/* -+ * This contains the registers value for an operating point. -+ * If only part of a register needs to change then there is -+ * a mask value for that register. -+ * When going to a new operating point the current register -+ * value is ANDed with the ~mask and ORed with the new value. -+ */ -+struct dpm_regs { -+ u32 cpccr; /* Clock Freq Control Register */ -+ u32 cpccr_mask; /* Clock Freq Control Register mask */ -+ u32 cppcr; /* PLL1 Control Register */ -+ u32 cppcr_mask; /* PLL1 Control Register mask */ -+ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -+}; -+ -+extern jz_clocks_t jz_clocks; -+ -+static void jz_update_clocks(void) -+{ -+ /* Next clocks must be updated if we have changed -+ * the PLL or divisors. -+ */ -+ jz_clocks.cclk = __cpm_get_cclk(); -+ jz_clocks.hclk = __cpm_get_hclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(0); -+} -+ -+static void -+jz_init_boot_config(void) -+{ -+ if (!boot_config.lcd_clks_initialized) { -+ /* the first time to scale pll */ -+ boot_config.lcdpix_clk = __cpm_get_pixclk(); -+ boot_config.lcd_clks_initialized = 1; -+ } -+ -+ if (!boot_config.sdram_initialized) { -+ /* the first time to scale frequencies */ -+ unsigned int dmcr, rtcor; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ -+ dmcr = REG_EMC_DMCR; -+ rtcor = REG_EMC_RTCOR; -+ -+ tras = (dmcr >> 13) & 0x7; -+ rcd = (dmcr >> 11) & 0x3; -+ tpc = (dmcr >> 8) & 0x7; -+ trwl = (dmcr >> 5) & 0x3; -+ trc = (dmcr >> 2) & 0x7; -+ -+ boot_config.mclk = __cpm_get_mclk() / 1000; -+ boot_config.tras = tras + 4; -+ boot_config.rcd = rcd + 1; -+ boot_config.tpc = tpc + 1; -+ boot_config.trwl = trwl + 1; -+ boot_config.trc = trc * 2 + 1; -+ boot_config.rtcor = rtcor; -+ -+ boot_config.sdram_initialized = 1; -+ } -+} -+ -+static void jz_update_dram_rtcor(unsigned int new_mclk) -+{ -+ unsigned int rtcor; -+ -+ new_mclk /= 1000; -+ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -+ rtcor--; -+ -+ if (rtcor < 1) rtcor = 1; -+ if (rtcor > 255) rtcor = 255; -+ -+ REG_EMC_RTCOR = rtcor; -+ REG_EMC_RTCNT = rtcor; -+} -+ -+static void jz_update_dram_dmcr(unsigned int new_mclk) -+{ -+ unsigned int dmcr; -+ unsigned int tras, rcd, tpc, trwl, trc; -+ unsigned int valid_time, new_time; /* ns */ -+ -+ new_mclk /= 1000; -+ tras = boot_config.tras * new_mclk / boot_config.mclk; -+ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -+ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -+ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -+ trc = boot_config.trc * new_mclk / boot_config.mclk; -+ -+ /* Validation checking */ -+ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -+ new_time = (tras * 1000000) / new_mclk; -+ if (new_time < valid_time) tras += 1; -+ -+ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -+ new_time = (rcd * 1000000) / new_mclk; -+ if (new_time < valid_time) rcd += 1; -+ -+ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -+ new_time = (tpc * 1000000) / new_mclk; -+ if (new_time < valid_time) tpc += 1; -+ -+ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -+ new_time = (trwl * 1000000) / new_mclk; -+ if (new_time < valid_time) trwl += 1; -+ -+ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -+ new_time = (trc * 1000000) / new_mclk; -+ if (new_time < valid_time) trc += 2; -+ -+ tras = (tras < 4) ? 4: tras; -+ tras = (tras > 11) ? 11: tras; -+ tras -= 4; -+ -+ rcd = (rcd < 1) ? 1: rcd; -+ rcd = (rcd > 4) ? 4: rcd; -+ rcd -= 1; -+ -+ tpc = (tpc < 1) ? 1: tpc; -+ tpc = (tpc > 8) ? 8: tpc; -+ tpc -= 1; -+ -+ trwl = (trwl < 1) ? 1: trwl; -+ trwl = (trwl > 4) ? 4: trwl; -+ trwl -= 1; -+ -+ trc = (trc < 1) ? 1: trc; -+ trc = (trc > 15) ? 15: trc; -+ trc /= 2; -+ -+ dmcr = REG_EMC_DMCR; -+ -+ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -+ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -+ -+ REG_EMC_DMCR = dmcr; -+} -+ -+static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR before changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } else { -+ /* We're going SLOWER: first update RTCOR value -+ * before changing the frequency. -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } -+} -+ -+static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -+{ -+ /* No risk, no fun: run with interrupts on! */ -+ if (new_mclk > cur_mclk) { -+ /* We're going FASTER, so update RTCOR -+ * after changing the frequency -+ */ -+ jz_update_dram_rtcor(new_mclk); -+ } else { -+ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -+ * and TRC of DMCR after changing the frequency. -+ */ -+ jz_update_dram_dmcr(new_mclk); -+ } -+} -+ -+static void jz_scale_divisors(struct dpm_regs *regs) -+{ -+ unsigned int cpccr; -+ unsigned int cur_mclk, new_mclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ cpccr = REG_CPM_CPCCR; -+ cpccr &= ~((unsigned long)regs->cpccr_mask); -+ cpccr |= regs->cpccr; -+ cpccr |= CPM_CPCCR_CE; /* update immediately */ -+ -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; -+ -+ /* Update some DRAM parameters before changing frequency */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+ -+#ifdef CHANGE_PLL -+/* Maintain the LCD clock and pixel clock */ -+static void jz_scale_lcd_divisors(struct dpm_regs *regs) -+{ -+ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -+ unsigned int cpccr; -+ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -+ -+ if (!boot_config.lcd_clks_initialized) return; -+ -+ new_pll = __cpm_get_pllout(); -+ new_lcd_div = new_pll / boot_config.lcd_clk; -+ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -+ -+ if (new_lcd_div < 1) -+ new_lcd_div = 1; -+ if (new_lcd_div > 16) -+ new_lcd_div = 16; -+ -+ if (new_lcdpix_div < 1) -+ new_lcdpix_div = 1; -+ if (new_lcdpix_div > 512) -+ new_lcdpix_div = 512; -+ -+// REG_CPM_CPCCR2 = new_lcdpix_div - 1; -+ -+ cpccr = REG_CPM_CPCCR; -+ cpccr &= ~CPM_CPCCR_LDIV_MASK; -+ cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); -+ cpccr |= CPM_CPCCR_CE; /* update immediately */ -+ -+ /* update register to change the clocks. -+ * align this code to a cache line. -+ */ -+ __asm__ __volatile__( -+ ".set noreorder\n\t" -+ ".align 5\n" -+ "sw %1,0(%0)\n\t" -+ "li %3,0\n\t" -+ "1:\n\t" -+ "bne %3,%2,1b\n\t" -+ "addi %3, 1\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set reorder\n\t" -+ : -+ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -+} -+ -+static void jz_scale_pll(struct dpm_regs *regs) -+{ -+ unsigned int cppcr; -+ unsigned int cur_mclk, new_mclk, new_pll; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ int od[] = {1, 2, 2, 4}; -+ -+ cppcr = REG_CPM_CPPCR; -+ cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); -+ regs->cppcr &= ~CPM_CPPCR_PLLEN; -+ cppcr |= (regs->cppcr | 0xff); -+ -+ /* Update some DRAM parameters before changing frequency */ -+ new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); -+ cur_mclk = __cpm_get_mclk(); -+ new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf]; -+ -+ /* -+ * Update some SDRAM parameters -+ */ -+ jz_update_dram_prev(cur_mclk, new_mclk); -+ -+ /* -+ * Update PLL, align code to cache line. -+ */ -+ cppcr |= CPM_CPPCR_PLLEN; -+ __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" (CPM_CPPCR), "r" (cppcr)); -+ -+ /* Update some other DRAM parameters after changing frequency */ -+ jz_update_dram_post(cur_mclk, new_mclk); -+} -+#endif -+ -+static void jz4750d_transition(struct dpm_regs *regs) -+{ -+ /* -+ * Get and save some boot-time conditions. -+ */ -+ jz_init_boot_config(); -+ -+#ifdef CHANGE_PLL -+ /* -+ * Disable LCD before scaling pll. -+ * LCD and LCD pixel clocks should not be changed even if the PLL -+ * output frequency has been changed. -+ */ -+ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -+ -+ /* -+ * Stop module clocks before scaling PLL -+ */ -+ __cpm_stop_eth(); -+ __cpm_stop_aic(1); -+ __cpm_stop_aic(2); -+#endif -+ -+ /* ... add more as necessary */ -+ -+ if (regs->pll_up_flag == PLL_GOES_UP) { -+ /* the pll frequency is going up, so change dividors first */ -+ jz_scale_divisors(regs); -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ } -+ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -+ /* the pll frequency is going down, so change pll first */ -+#ifdef CHANGE_PLL -+ jz_scale_pll(regs); -+#endif -+ jz_scale_divisors(regs); -+ } -+ else { -+ /* the pll frequency is unchanged, so change divisors only */ -+ jz_scale_divisors(regs); -+ } -+ -+#ifdef CHANGE_PLL -+ /* -+ * Restart module clocks before scaling PLL -+ */ -+ __cpm_start_eth(); -+ __cpm_start_aic(1); -+ __cpm_start_aic(2); -+ -+ /* ... add more as necessary */ -+ -+ /* Scale the LCD divisors after scaling pll */ -+ if (regs->pll_up_flag != PLL_UNCHANGED) { -+ jz_scale_lcd_divisors(regs); -+ } -+ -+ /* Enable LCD controller */ -+ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -+ REG_LCD_CTRL |= LCD_CTRL_ENA; -+#endif -+ -+ /* Update system clocks */ -+ jz_update_clocks(); -+} -+ -+extern unsigned int idle_times; -+static unsigned int jz4750d_freq_get(unsigned int cpu) -+{ -+ return (__cpm_get_cclk() / 1000); -+} -+ -+static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -+{ -+ int n2FR[33] = { -+ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -+ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -+ 9 -+ }; -+ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -+ unsigned int div_of_cclk, new_freq, i; -+ -+ regs->pll_up_flag = PLL_UNCHANGED; -+ regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; -+ -+ new_freq = jz4750d_freq_table.table[index].frequency; -+ -+ do { -+ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -+ } while (div_of_cclk==0); -+ -+ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -+ for(i = 1; i<4; i++) { -+ div[i] = 3; -+ } -+ } else { -+ for(i = 1; i<4; i++) { -+ div[i] = 2; -+ } -+ } -+ -+ for(i = 0; i<4; i++) { -+ div[i] *= div_of_cclk; -+ } -+ -+ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -+ -+ regs->cpccr = -+ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | -+ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | -+ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | -+ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); -+ -+ return div_of_cclk; -+} -+ -+static void jz4750d_set_cpu_divider_index(unsigned int cpu, unsigned int index) -+{ -+ unsigned long divisor, old_divisor; -+ struct cpufreq_freqs freqs; -+ struct dpm_regs regs; -+ -+ old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); -+ divisor = index_to_divisor(index, ®s); -+ -+ freqs.old = __cpm_get_cclk() / 1000; -+ freqs.new = __cpm_get_pllout() / (1000 * divisor); -+ freqs.cpu = cpu; -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -+ -+ if (old_divisor != divisor) -+ jz4750d_transition(®s); -+ -+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -+} -+ -+static int jz4750d_freq_target(struct cpufreq_policy *policy, -+ unsigned int target_freq, -+ unsigned int relation) -+{ -+ unsigned int new_index = 0; -+ -+ if (cpufreq_frequency_table_target(policy, -+ &jz4750d_freq_table.table[0], -+ target_freq, relation, &new_index)) -+ return -EINVAL; -+ -+ jz4750d_set_cpu_divider_index(policy->cpu, new_index); -+ -+ dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); -+ -+ return 0; -+} -+ -+static int jz4750d_freq_verify(struct cpufreq_policy *policy) -+{ -+ return cpufreq_frequency_table_verify(policy, -+ &jz4750d_freq_table.table[0]); -+} -+ -+static int __init jz4750d_cpufreq_driver_init(struct cpufreq_policy *policy) -+{ -+ -+ struct cpufreq_frequency_table *table = &jz4750d_freq_table.table[0]; -+ unsigned int MAX_FREQ; -+ -+ dprintk(KERN_INFO "Jz4750d cpufreq driver\n"); -+ -+ if (policy->cpu != 0) -+ return -EINVAL; -+ -+ policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -+ -+ policy->cpuinfo.min_freq = MAX_FREQ/8; -+ policy->cpuinfo.max_freq = MAX_FREQ; -+ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -+ -+ table[0].index = 0; -+ table[0].frequency = MAX_FREQ/8; -+ table[1].index = 1; -+ table[1].frequency = MAX_FREQ/6; -+ table[2].index = 2; -+ table[2].frequency = MAX_FREQ/4; -+ table[3].index = 3; -+ table[3].frequency = MAX_FREQ/3; -+ table[4].index = 4; -+ table[4].frequency = MAX_FREQ/2; -+ table[5].index = 5; -+ table[5].frequency = MAX_FREQ; -+ table[6].index = 6; -+ table[6].frequency = CPUFREQ_TABLE_END; -+ -+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS -+ cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ -+#endif -+ -+ return cpufreq_frequency_table_cpuinfo(policy, table); -+} -+ -+static struct cpufreq_driver cpufreq_jz4750d_driver = { -+// .flags = CPUFREQ_STICKY, -+ .init = jz4750d_cpufreq_driver_init, -+ .verify = jz4750d_freq_verify, -+ .target = jz4750d_freq_target, -+ .get = jz4750d_freq_get, -+ .name = "jz4750d", -+}; -+ -+static int __init jz4750d_cpufreq_init(void) -+{ -+ return cpufreq_register_driver(&cpufreq_jz4750d_driver); -+} -+ -+static void __exit jz4750d_cpufreq_exit(void) -+{ -+ cpufreq_unregister_driver(&cpufreq_jz4750d_driver); -+} -+ -+module_init(jz4750d_cpufreq_init); -+module_exit(jz4750d_cpufreq_exit); -+ -+MODULE_AUTHOR("Regen "); -+MODULE_DESCRIPTION("cpufreq driver for Jz4750d"); -+MODULE_LICENSE("GPL"); -diff --git a/arch/mips/jz4750d/dma.c b/arch/mips/jz4750d/dma.c -new file mode 100644 -index 0000000..290cc12 ---- /dev/null -+++ b/arch/mips/jz4750d/dma.c -@@ -0,0 +1,822 @@ -+/* -+ * linux/arch/mips/jz4750d/dma.c -+ * -+ * Support functions for the JZ4750D internal DMA channels. -+ * No-descriptor transfer only. -+ * Descriptor transfer should also call jz_request_dma() to get a free -+ * channel and call jz_free_dma() to free the channel. And driver should -+ * build the DMA descriptor and setup the DMA channel by itself. -+ * -+ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * A note on resource allocation: -+ * -+ * All drivers needing DMA channels, should allocate and release them -+ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -+ * -+ * In order to avoid problems, all processes should allocate resources in -+ * the same sequence and release them in the reverse order. -+ * -+ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -+ * When releasing them, first release the IRQ, then release the DMA. The -+ * main reason for this order is that, if you are requesting the DMA buffer -+ * done interrupt, you won't know the irq number until the DMA channel is -+ * returned from jz_request_dma(). -+ */ -+ -+struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { -+ {dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */ -+ {dev_id:-1,}, /* DMAC0 channel 1 */ -+ {dev_id:-1,}, /* DMAC0 channel 2 */ -+ {dev_id:-1,}, /* DMAC0 channel 3 */ -+ {dev_id:-1,}, /* DMAC1 channel 0 */ -+ {dev_id:-1,}, /* DMAC1 channel 1 */ -+ {dev_id:-1,}, /* DMAC1 channel 2 */ -+ {dev_id:-1,}, /* DMAC1 channel 3 */ -+}; -+ -+// Device FIFO addresses and default DMA modes -+static const struct { -+ unsigned int fifo_addr; -+ unsigned int dma_mode; -+ unsigned int dma_source; -+} dma_dev_table[DMA_ID_MAX] = { -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */ -+ {0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */ -+ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC}, -+ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC}, -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, -+// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN}, -+ {CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT}, -+ {CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN}, -+ {CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT}, -+ {CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN}, -+ {CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT}, -+ {CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN}, -+ {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -+ {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -+ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT}, -+ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN}, -+ {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -+ {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -+ {CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT}, -+ {CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN}, -+ {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, -+ {SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */ -+ {CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */ -+ {CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */ -+ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT}, -+ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN}, -+ {CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT}, -+ {CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN}, -+ {}, -+}; -+ -+ -+int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data) -+{ -+ int i, len = 0; -+ struct jz_dma_chan *chan; -+ -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if ((chan = get_dma_chan(i)) != NULL) { -+ len += sprintf(buf + len, "%2d: %s\n", -+ i, chan->dev_str); -+ } -+ } -+ -+ if (fpos >= len) { -+ *start = buf; -+ *eof = 1; -+ return 0; -+ } -+ *start = buf + fpos; -+ if ((len -= fpos) > length) -+ return length; -+ *eof = 1; -+ return len; -+} -+ -+ -+void dump_jz_dma_channel(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > MAX_DMA_NUM) -+ return; -+ chan = &jz_dma_table[dmanr]; -+ -+ printk("DMA%d Registers:\n", dmanr); -+ printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM)); -+ printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -+ printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); -+ printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -+ printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -+ printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -+ printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); -+ printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); -+ printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM)); -+} -+ -+ -+/** -+ * jz_request_dma - dynamically allcate an idle DMA channel to return -+ * @dev_id: the specified dma device id or DMA_ID_RAW_SET -+ * @dev_str: the specified dma device string name -+ * @irqhandler: the irq handler, or NULL -+ * @irqflags: the irq handler flags -+ * @irq_dev_id: the irq handler device id for shared irq -+ * -+ * Finds a free channel, and binds the requested device to it. -+ * Returns the allocated channel number, or negative on error. -+ * Requests the DMA done IRQ if irqhandler != NULL. -+ * -+*/ -+/*int jz_request_dma(int dev_id, const char *dev_str, -+ void (*irqhandler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+*/ -+ -+int jz_request_dma(int dev_id, const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id) -+{ -+ struct jz_dma_chan *chan; -+ int i, ret; -+ -+ if (dev_id < 0 || dev_id >= DMA_ID_MAX) -+ return -EINVAL; -+ -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == MAX_DMA_NUM) /* no free channel */ -+ return -ENODEV; -+ -+ /* we got a free channel */ -+ chan = &jz_dma_table[i]; -+ -+ if (irqhandler) { -+ chan->irq = IRQ_DMA_0 + i; // allocate irq number -+ chan->irq_dev = irq_dev_id; -+ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -+ dev_str, chan->irq_dev))) { -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ return ret; -+ } -+ } else { -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ } -+ -+ // fill it in -+ chan->io = i; -+ chan->dev_id = dev_id; -+ chan->dev_str = dev_str; -+ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -+ chan->mode = dma_dev_table[dev_id].dma_mode; -+ chan->source = dma_dev_table[dev_id].dma_source; -+ -+ if (i < HALF_DMA_NUM) -+ REG_DMAC_DMACKE(0) = 1 << i; -+ else -+ REG_DMAC_DMACKE(1) = 1 << (i - HALF_DMA_NUM); -+ -+ return i; -+} -+ -+void jz_free_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) { -+ printk("Trying to free DMA%d\n", dmanr); -+ return; -+ } -+ -+ disable_dma(dmanr); -+ if (chan->irq) -+ free_irq(chan->irq, chan->irq_dev); -+ -+ chan->irq = -1; -+ chan->irq_dev = NULL; -+ chan->dev_id = -1; -+} -+ -+void jz_set_dma_dest_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_DWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCMD_DWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_DWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_DWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_src_width(int dmanr, int nbit) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_SWDH_MASK; -+ switch (nbit) { -+ case 8: -+ chan->mode |= DMAC_DCMD_SWDH_8; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_SWDH_16; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_SWDH_32; -+ break; -+ } -+} -+ -+void jz_set_dma_block_size(int dmanr, int nbyte) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode &= ~DMAC_DCMD_DS_MASK; -+ switch (nbyte) { -+ case 1: -+ chan->mode |= DMAC_DCMD_DS_8BIT; -+ break; -+ case 2: -+ chan->mode |= DMAC_DCMD_DS_16BIT; -+ break; -+ case 4: -+ chan->mode |= DMAC_DCMD_DS_32BIT; -+ break; -+ case 16: -+ chan->mode |= DMAC_DCMD_DS_16BYTE; -+ break; -+ case 32: -+ chan->mode |= DMAC_DCMD_DS_32BYTE; -+ break; -+ } -+} -+ -+unsigned int jz_get_dma_command(int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ return chan->mode; -+} -+ -+/** -+ * jz_set_dma_mode - do the raw settings for the specified DMA channel -+ * @dmanr: the specified DMA channel -+ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -+ * @dma_mode: dma raw mode -+ * @dma_source: dma raw request source -+ * @fifo_addr: dma raw device fifo address -+ * -+ * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call -+ * jz_set_dma_mode() rather than set_dma_mode() if you work with -+ * and external request dma device. -+ * -+ * NOTE: Don not dynamically allocate dma channel if one external request -+ * dma device will occupy this channel. -+*/ -+int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -+ unsigned int dma_mode, unsigned int dma_source, -+ unsigned int fifo_addr) -+{ -+ int dev_id, i; -+ struct jz_dma_chan *chan; -+ -+ if (dmanr > MAX_DMA_NUM) -+ return -ENODEV; -+ for (i = 0; i < MAX_DMA_NUM; i++) { -+ if (jz_dma_table[i].dev_id < 0) -+ break; -+ } -+ if (i == MAX_DMA_NUM) -+ return -ENODEV; -+ -+ chan = &jz_dma_table[dmanr]; -+ dev_id = chan->dev_id; -+ if (dev_id > 0) { -+ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -+ __FUNCTION__, dmanr); -+ return -ENODEV; -+ } -+ -+ /* clone it from the dynamically allocated. */ -+ if (i != dmanr) { -+ chan->irq = jz_dma_table[i].irq; -+ chan->irq_dev = jz_dma_table[i].irq_dev; -+ chan->dev_str = jz_dma_table[i].dev_str; -+ jz_dma_table[i].irq = 0; -+ jz_dma_table[i].irq_dev = NULL; -+ jz_dma_table[i].dev_id = -1; -+ } -+ chan->dev_id = DMA_ID_RAW_SET; -+ chan->io = dmanr; -+ chan->fifo_addr = fifo_addr; -+ chan->mode = dma_mode; -+ chan->source = dma_source; -+ -+ set_dma_mode(dmanr, dma_mode); -+ -+ return dmanr; -+} -+ -+void enable_dma(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+ REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ -+ __dmac_enable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_enable_irq(dmanr); -+} -+ -+#define DMA_DISABLE_POLL 0x10000 -+ -+void disable_dma(unsigned int dmanr) -+{ -+ int i; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ if (!__dmac_channel_enabled(dmanr)) -+ return; -+ -+ for (i = 0; i < DMA_DISABLE_POLL; i++) -+ if (__dmac_channel_transmit_end_detected(dmanr)) -+ break; -+#if 0 -+ if (i == DMA_DISABLE_POLL) -+ printk(KERN_INFO "disable_dma: poll expired!\n"); -+#endif -+ -+ __dmac_disable_channel(dmanr); -+ if (chan->irq) -+ __dmac_channel_disable_irq(dmanr); -+} -+ -+/* Note: DMA_MODE_MASK is simulated by sw */ -+void set_dma_mode(unsigned int dmanr, unsigned int mode) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else { -+ printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ } -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+} -+ -+void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) -+{ -+ unsigned int mode; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ mode = chan->mode & DMA_MODE_MASK; -+ if (mode == DMA_MODE_READ) { -+ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -+ REG_DMAC_DTAR(chan->io) = phyaddr; -+ } else if (mode == DMA_MODE_WRITE) { -+ REG_DMAC_DSAR(chan->io) = phyaddr; -+ REG_DMAC_DTAR(chan->io) = chan->fifo_addr; -+ } else -+ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -+} -+ -+void set_dma_count(unsigned int dmanr, unsigned int bytecnt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ unsigned int ds; -+ -+ if (!chan) -+ return; -+ -+ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -+ REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count -+} -+ -+unsigned int get_dma_residue(unsigned int dmanr) -+{ -+ unsigned int count, ds; -+ int dma_ds[] = {4, 1, 2, 16, 32}; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ -+ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -+ count = REG_DMAC_DTCR(chan->io); -+ count = count * dma_ds[ds]; -+ -+ return count; -+} -+ -+void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case AFMT_U8: -+ /* burst mode : 32BIT */ -+ break; -+ case AFMT_S16_LE: -+ /* burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ //chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else -+ printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ -+ if (!chan) -+ return; -+ -+ switch (audio_fmt) { -+ case 8: -+ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -+ break; -+ case 16: -+ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -+ if (mode == DMA_MODE_READ) { -+ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_DAI; -+ chan->mode &= ~DMAC_DCMD_SAI; -+ } else if (mode == DMA_MODE_WRITE) { -+ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -+ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -+ mode &= DMA_MODE_MASK; -+ chan->mode |= DMAC_DCMD_SAI; -+ chan->mode &= ~DMAC_DCMD_DAI; -+ } else -+ printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -+ -+ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -+ REG_DMAC_DRSR(chan->io) = chan->source; -+ break; -+ } -+} -+ -+//#define JZ4750D_DMAC_TEST_ENABLE -+#undef JZ4750D_DMAC_TEST_ENABLE -+ -+#ifdef JZ4750D_DMAC_TEST_ENABLE -+ -+/* -+ * DMA test: external address <--> external address -+ */ -+#define TEST_DMA_SIZE 16*1024 -+ -+static jz_dma_desc *dma_desc; -+ -+static int dma_chan; -+static dma_addr_t dma_desc_phys_addr; -+static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; -+ -+static int dma_check_result(void *src, void *dst, int size) -+{ -+ unsigned int addr1, addr2, i, err = 0; -+ -+ addr1 = (unsigned int)src; -+ addr2 = (unsigned int)dst; -+ -+ for (i = 0; i < size; i += 4) { -+ if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { -+ err++; -+ printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); -+ } -+ addr1 += 4; -+ addr2 += 4; -+ } -+ printk("check DMA result err=%d\n", err); -+ return err; -+} -+ -+static irqreturn_t jz4750d_dma_irq(int irq, void *dev_id) -+{ -+ printk("jz4750d_dma_irq %d\n", irq); -+ -+ -+ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -+ printk("DMA HALT\n"); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ __dmac_channel_clear_transmit_halt(dma_chan); -+ } -+ -+ if (__dmac_channel_address_error_detected(dma_chan)) { -+ printk("DMA ADDR ERROR\n"); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */ -+ REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */ -+ __dmac_channel_clear_address_error(dma_chan); -+ } -+ -+ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ printk("DMA DESC INVALID\n"); -+ __dmac_channel_clear_descriptor_invalid(dma_chan); -+ } -+ -+ if (__dmac_channel_count_terminated_detected(dma_chan)) { -+ printk("DMA CT\n"); -+ __dmac_channel_clear_count_terminated(dma_chan); -+ } -+ -+ if (__dmac_channel_transmit_end_detected(dma_chan)) { -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ printk("DMA TT\n"); -+ __dmac_channel_clear_transmit_end(dma_chan); -+ dump_jz_dma_channel(dma_chan); -+ dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+void dma_nodesc_test(void) -+{ -+ unsigned int addr, i; -+ -+ printk("dma_nodesc_test\n"); -+ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750d_dma_irq, -+ IRQF_DISABLED, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq failed\n"); -+ return; -+ } -+ -+ printk("Requested DMA channel = %d\n", dma_chan); -+ -+ /* Allocate DMA buffers */ -+ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ -+ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -+ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -+ -+ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -+ -+ /* Prepare data for source buffer */ -+ addr = (unsigned int)dma_src_addr; -+ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -+ *(volatile unsigned int *)addr = addr; -+ addr += 4; -+ } -+ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -+ -+ /* Init target buffer */ -+ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -+ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -+ -+ /* Init DMA module */ -+ printk("Starting DMA\n"); -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0; -+ REG_DMAC_DCCSR(dma_chan) = 0; -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -+ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -+ REG_DMAC_DTCR(dma_chan) = 512; -+ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */ -+ -+ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -+ -+ /* wait a long time, ensure transfer end */ -+ printk("wait 3s...\n"); -+ mdelay(3000); /* wait 3s */ -+ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ /* free buffers */ -+ printk("free DMA buffers\n"); -+ free_pages(dma_src_addr, 2); -+ free_pages(dma_dst_addr, 2); -+ -+ if (dma_desc) -+ free_pages((unsigned int)dma_desc, 0); -+ -+ /* free dma */ -+ jz_free_dma(dma_chan); -+} -+ -+void dma_desc_test(void) -+{ -+ unsigned int next, addr, i; -+ static jz_dma_desc *desc; -+ -+ printk("dma_desc_test\n"); -+ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750d_dma_irq, -+ IRQF_DISABLED, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq failed\n"); -+ return; -+ } -+ -+ printk("Requested DMA channel = %d\n", dma_chan); -+ -+ /* Allocate DMA buffers */ -+ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -+ -+ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -+ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -+ -+ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -+ -+ /* Prepare data for source buffer */ -+ addr = (unsigned int)dma_src_addr; -+ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -+ *(volatile unsigned int *)addr = addr; -+ addr += 4; -+ } -+ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -+ -+ /* Init target buffer */ -+ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -+ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -+ -+ /* Allocate DMA descriptors */ -+ dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); -+ dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); -+ -+ printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); -+ -+ /* Setup DMA descriptors */ -+ desc = dma_desc; -+ next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr; /* DMA target address */ -+ desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ -+ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -+ desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ -+ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -+ -+ desc++; -+ next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; -+ -+ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; -+ desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ -+ desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ -+ desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ -+ -+ dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); -+ -+ /* Setup DMA descriptor address */ -+ REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; -+ -+ /* Setup request source */ -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ -+ /* Setup DMA channel control/status register */ -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -+ -+ /* Enable DMA */ -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; -+ -+ /* DMA doorbell set -- start DMA now ... */ -+ REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan; -+ -+ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -+ /* wait a long time, ensure transfer end */ -+ printk("wait 3s...\n"); -+ mdelay(3000); /* wait 3s */ -+ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ /* free buffers */ -+ printk("free DMA buffers\n"); -+ free_pages(dma_src_addr, 2); -+ free_pages(dma_dst_addr, 2); -+ -+ if (dma_desc) -+ free_pages((unsigned int)dma_desc, 0); -+ -+ /* free dma */ -+ jz_free_dma(dma_chan); -+} -+ -+#endif -+ -+//EXPORT_SYMBOL_NOVERS(jz_dma_table); -+EXPORT_SYMBOL(jz_dma_table); -+EXPORT_SYMBOL(jz_request_dma); -+EXPORT_SYMBOL(jz_free_dma); -+EXPORT_SYMBOL(jz_set_dma_src_width); -+EXPORT_SYMBOL(jz_set_dma_dest_width); -+EXPORT_SYMBOL(jz_set_dma_block_size); -+EXPORT_SYMBOL(jz_set_dma_mode); -+EXPORT_SYMBOL(set_dma_mode); -+EXPORT_SYMBOL(jz_set_oss_dma); -+EXPORT_SYMBOL(jz_set_alsa_dma); -+EXPORT_SYMBOL(set_dma_addr); -+EXPORT_SYMBOL(set_dma_count); -+EXPORT_SYMBOL(get_dma_residue); -+EXPORT_SYMBOL(enable_dma); -+EXPORT_SYMBOL(disable_dma); -+EXPORT_SYMBOL(dump_jz_dma_channel); -diff --git a/arch/mips/jz4750d/i2c.c b/arch/mips/jz4750d/i2c.c -new file mode 100644 -index 0000000..c12142f ---- /dev/null -+++ b/arch/mips/jz4750d/i2c.c -@@ -0,0 +1,273 @@ -+/* -+ * linux/arch/mips/jz4750d/i2c.c -+ * -+ * Jz4750D I2C routines. -+ * -+ * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* I2C protocol */ -+#define I2C_READ 1 -+#define I2C_WRITE 0 -+ -+#define TIMEOUT 1000 -+ -+/* -+ * I2C bus protocol basic routines -+ */ -+static int i2c_put_data(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (!__i2c_received_ack() && timeout) -+ timeout--; -+ -+ if (timeout) -+ return 0; -+ else -+ return -ETIMEDOUT; -+} -+ -+#ifdef CONFIG_JZ_TPANEL_ATA2508 -+static int i2c_put_data_nack(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (timeout--); -+ return 0; -+} -+#endif -+ -+static int i2c_get_data(unsigned char *data, int ack) -+{ -+ int timeout = TIMEOUT*10; -+ -+ if (!ack) -+ __i2c_send_nack(); -+ else -+ __i2c_send_ack(); -+ -+ while (__i2c_check_drf() == 0 && timeout) -+ timeout--; -+ -+ if (timeout) { -+ if (!ack) -+ __i2c_send_stop(); -+ *data = __i2c_read(); -+ __i2c_clear_drf(); -+ return 0; -+ } else -+ return -ETIMEDOUT; -+} -+ -+/* -+ * I2C interface -+ */ -+void i2c_open(void) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -+ __i2c_enable(); -+} -+ -+void i2c_close(void) -+{ -+ udelay(300); /* wait for STOP goes over. */ -+ __i2c_disable(); -+} -+ -+void i2c_setclk(unsigned int i2cclk) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -+} -+ -+int i2c_lseek(unsigned char device, unsigned char offset) -+{ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+ if (i2c_put_data(offset) < 0) -+ goto address_err; -+ return 0; -+ device_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+ address_err: -+ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -+ __i2c_send_stop(); -+ return -EREMOTEIO; -+} -+ -+int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int timeout = 5; -+ -+L_try_again: -+ -+ if (timeout < 0) -+ goto L_timeout; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_werr; -+ if (i2c_put_data(address) < 0) -+ goto address_err; -+ -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -+ goto device_rerr; -+ __i2c_send_ack(); /* Master sends ACK for continue reading */ -+ while (cnt) { -+ if (cnt == 1) { -+ if (i2c_get_data(buf, 0) < 0) -+ break; -+ } else { -+ if (i2c_get_data(buf, 1) < 0) -+ break; -+ } -+ cnt--; -+ buf++; -+ } -+ -+ __i2c_send_stop(); -+ return count - cnt; -+ device_rerr: -+ device_werr: -+ address_err: -+ timeout --; -+ __i2c_send_stop(); -+ goto L_try_again; -+ -+L_timeout: -+ __i2c_send_stop(); -+ printk("Read I2C device 0x%2x failed.\n", device); -+ return -ENODEV; -+} -+ -+int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count) -+{ -+ int cnt = count; -+ int cnt_in_pg; -+ int timeout = 5; -+ unsigned char *tmpbuf; -+ unsigned char tmpaddr; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ -+ W_try_again: -+ if (timeout < 0) -+ goto W_timeout; -+ -+ cnt = count; -+ tmpbuf = (unsigned char *)buf; -+ tmpaddr = address; -+ -+ start_write_page: -+ cnt_in_pg = 0; -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+#ifdef CONFIG_JZ_TPANEL_ATA2508 -+ if (address == 0xff) { -+ if (i2c_put_data_nack(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data_nack(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ } -+ else { -+ -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ } -+#else -+ if (i2c_put_data(tmpaddr) < 0) -+ goto address_err; -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ tmpaddr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+#endif -+ __i2c_send_stop(); -+ return count - cnt; -+ device_err: -+ address_err: -+ timeout--; -+ __i2c_send_stop(); -+ goto W_try_again; -+ -+ W_timeout: -+ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+} -+ -+EXPORT_SYMBOL(i2c_open); -+EXPORT_SYMBOL(i2c_close); -+EXPORT_SYMBOL(i2c_setclk); -+EXPORT_SYMBOL(i2c_read); -+EXPORT_SYMBOL(i2c_write); -diff --git a/arch/mips/jz4750d/irq.c b/arch/mips/jz4750d/irq.c -new file mode 100644 -index 0000000..aa43d9b ---- /dev/null -+++ b/arch/mips/jz4750d/irq.c -@@ -0,0 +1,299 @@ -+/* -+ * linux/arch/mips/jz4750d/irq.c -+ * -+ * JZ4750D interrupt routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * INTC irq type -+ */ -+ -+static void enable_intc_irq(unsigned int irq) -+{ -+ __intc_unmask_irq(irq); -+} -+ -+static void disable_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+} -+ -+static void mask_and_ack_intc_irq(unsigned int irq) -+{ -+ __intc_mask_irq(irq); -+ __intc_ack_irq(irq); -+} -+ -+static void end_intc_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_intc_irq(irq); -+ } -+} -+ -+static unsigned int startup_intc_irq(unsigned int irq) -+{ -+ enable_intc_irq(irq); -+ return 0; -+} -+ -+static void shutdown_intc_irq(unsigned int irq) -+{ -+ disable_intc_irq(irq); -+} -+ -+static struct irq_chip intc_irq_type = { -+ .typename = "INTC", -+ .startup = startup_intc_irq, -+ .shutdown = shutdown_intc_irq, -+ .enable = enable_intc_irq, -+ .disable = disable_intc_irq, -+ .ack = mask_and_ack_intc_irq, -+ .end = end_intc_irq, -+}; -+ -+/* -+ * GPIO irq type -+ */ -+ -+static void enable_gpio_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if (irq < (IRQ_GPIO_0 + 32)) { -+ intc_irq = IRQ_GPIO0; -+ } -+ else if (irq < (IRQ_GPIO_0 + 64)) { -+ intc_irq = IRQ_GPIO1; -+ } -+ else if (irq < (IRQ_GPIO_0 + 96)) { -+ intc_irq = IRQ_GPIO2; -+ } -+ else if (irq < (IRQ_GPIO_0 + 128)) { -+ intc_irq = IRQ_GPIO3; -+ } -+ else if (irq < (IRQ_GPIO_0 + 160)) { -+ intc_irq = IRQ_GPIO4; -+ } -+ else { -+ intc_irq = IRQ_GPIO5; -+ } -+ -+ enable_intc_irq(intc_irq); -+ __gpio_unmask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void disable_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+} -+ -+static void mask_and_ack_gpio_irq(unsigned int irq) -+{ -+ __gpio_mask_irq(irq - IRQ_GPIO_0); -+ __gpio_ack_irq(irq - IRQ_GPIO_0); -+} -+ -+static void end_gpio_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_gpio_irq(irq); -+ } -+} -+ -+static unsigned int startup_gpio_irq(unsigned int irq) -+{ -+ enable_gpio_irq(irq); -+ return 0; -+} -+ -+static void shutdown_gpio_irq(unsigned int irq) -+{ -+ disable_gpio_irq(irq); -+} -+ -+static struct irq_chip gpio_irq_type = { -+ .typename = "GPIO", -+ .startup = startup_gpio_irq, -+ .shutdown = shutdown_gpio_irq, -+ .enable = enable_gpio_irq, -+ .disable = disable_gpio_irq, -+ .ack = mask_and_ack_gpio_irq, -+ .end = end_gpio_irq, -+}; -+ -+/* -+ * DMA irq type -+ */ -+ -+static void enable_dma_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -+ intc_irq = IRQ_DMAC0; -+ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -+ intc_irq = IRQ_DMAC1; -+ else { -+ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -+ return; -+ } -+ __intc_unmask_irq(intc_irq); -+ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -+} -+ -+static void disable_dma_irq(unsigned int irq) -+{ -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void mask_and_ack_dma_irq(unsigned int irq) -+{ -+ unsigned int intc_irq; -+ -+ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -+ intc_irq = IRQ_DMAC0; -+ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -+ intc_irq = IRQ_DMAC1; -+ else { -+ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -+ return ; -+ } -+ __intc_ack_irq(intc_irq); -+ __dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */ -+ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -+} -+ -+static void end_dma_irq(unsigned int irq) -+{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -+ enable_dma_irq(irq); -+ } -+} -+ -+static unsigned int startup_dma_irq(unsigned int irq) -+{ -+ enable_dma_irq(irq); -+ return 0; -+} -+ -+static void shutdown_dma_irq(unsigned int irq) -+{ -+ disable_dma_irq(irq); -+} -+ -+static struct irq_chip dma_irq_type = { -+ .typename = "DMA", -+ .startup = startup_dma_irq, -+ .shutdown = shutdown_dma_irq, -+ .enable = enable_dma_irq, -+ .disable = disable_dma_irq, -+ .ack = mask_and_ack_dma_irq, -+ .end = end_dma_irq, -+}; -+ -+//---------------------------------------------------------------------- -+ -+void __init arch_init_irq(void) -+{ -+ int i; -+ -+ clear_c0_status(0xff04); /* clear ERL */ -+ set_c0_status(0x0400); /* set IP2 */ -+ -+ /* Set up INTC irq -+ */ -+ for (i = 0; i < 32; i++) { -+ disable_intc_irq(i); -+ irq_desc[i].chip = &intc_irq_type; -+ } -+ -+ /* Set up DMAC irq -+ */ -+ for (i = 0; i < NUM_DMA; i++) { -+ disable_dma_irq(IRQ_DMA_0 + i); -+ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -+ } -+ -+ /* Set up GPIO irq -+ */ -+ for (i = 0; i < NUM_GPIO; i++) { -+ disable_gpio_irq(IRQ_GPIO_0 + i); -+ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -+ } -+} -+ -+static int plat_real_irq(int irq) -+{ -+ switch (irq) { -+ case IRQ_GPIO0: -+ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -+ break; -+ case IRQ_GPIO1: -+ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -+ break; -+ case IRQ_GPIO2: -+ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -+ break; -+ case IRQ_GPIO3: -+ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -+ break; -+ case IRQ_GPIO4: -+ irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128; -+ break; -+ case IRQ_GPIO5: -+ irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160; -+ break; -+ case IRQ_DMAC0: -+ case IRQ_DMAC1: -+ irq = __dmac_get_irq() + IRQ_DMA_0; -+ break; -+ } -+ -+ return irq; -+} -+ -+asmlinkage void plat_irq_dispatch(void) -+{ -+ int irq = 0; -+ static unsigned long intc_ipr = 0; -+ -+ intc_ipr |= REG_INTC_IPR; -+ -+ if (!intc_ipr) return; -+ -+ irq = ffs(intc_ipr) - 1; -+ intc_ipr &= ~(1< -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#if 0 -+/* OHCI (USB full speed host controller) */ -+static struct resource jz_usb_ohci_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -+ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UHC, -+ .end = IRQ_UHC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+/* The dmamask must be set for OHCI to work */ -+static u64 ohci_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_ohci_device = { -+ .name = "jz-ohci", -+ .id = 0, -+ .dev = { -+ .dma_mask = &ohci_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -+ .resource = jz_usb_ohci_resources, -+}; -+#endif -+/*** LCD controller ***/ -+static struct resource jz_lcd_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(LCD_BASE), -+ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_LCD, -+ .end = IRQ_LCD, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_lcd_dmamask = ~(u32)0; -+ -+static struct platform_device jz_lcd_device = { -+ .name = "jz-lcd", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_lcd_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_lcd_resources), -+ .resource = jz_lcd_resources, -+}; -+ -+/* UDC (USB gadget controller) */ -+static struct resource jz_usb_gdt_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(UDC_BASE), -+ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_UDC, -+ .end = IRQ_UDC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 udc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_usb_gdt_device = { -+ .name = "jz-udc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &udc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -+ .resource = jz_usb_gdt_resources, -+}; -+ -+/** MMC/SD controller **/ -+static struct resource jz_mmc_resources[] = { -+ [0] = { -+ .start = CPHYSADDR(MSC_BASE), -+ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_MSC0, -+ .end = IRQ_MSC0, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static u64 jz_mmc_dmamask = ~(u32)0; -+ -+static struct platform_device jz_mmc_device = { -+ .name = "jz-mmc", -+ .id = 0, -+ .dev = { -+ .dma_mask = &jz_mmc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .num_resources = ARRAY_SIZE(jz_mmc_resources), -+ .resource = jz_mmc_resources, -+}; -+ -+/* All */ -+static struct platform_device *jz_platform_devices[] __initdata = { -+// &jz_usb_ohci_device, -+ &jz_lcd_device, -+ &jz_usb_gdt_device, -+ &jz_mmc_device, -+}; -+ -+static int __init jz_platform_init(void) -+{ -+ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -+} -+ -+arch_initcall(jz_platform_init); -diff --git a/arch/mips/jz4750d/pm.c b/arch/mips/jz4750d/pm.c -new file mode 100644 -index 0000000..7f58372 ---- /dev/null -+++ b/arch/mips/jz4750d/pm.c -@@ -0,0 +1,461 @@ -+/* -+ * linux/arch/mips/jz4750d/common/pm.c -+ * -+ * JZ4750D Power Management Routines -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+ -+#define GPIO_PORT_NUM 6 -+ -+/* -+ * __gpio_as_sleep set all pins to pull-disable, and set all pins as input -+ * except sdram and the pins which can be used as CS1_N to CS4_N for chip select. -+ */ -+#define __gpio_as_sleep() \ -+do { \ -+ REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = ~0x03ff7fff; \ -+ REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(2) = ~0x01e00000; \ -+ REG_GPIO_PXSELC(2) = ~0x01e00000; \ -+ REG_GPIO_PXDIRC(2) = ~0x01e00000; \ -+ REG_GPIO_PXPES(2) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(3) = 0xffffffff; \ -+ REG_GPIO_PXSELC(3) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(3) = 0xffffffff; \ -+ REG_GPIO_PXPES(3) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(4) = 0xffffffff; \ -+ REG_GPIO_PXSELC(4) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(4) = 0xffffffff; \ -+ REG_GPIO_PXPES(4) = 0xffffffff; \ -+ REG_GPIO_PXFUNC(5) = 0xffffffff; \ -+ REG_GPIO_PXSELC(5) = 0xffffffff; \ -+ REG_GPIO_PXDIRC(5) = 0xffffffff; \ -+ REG_GPIO_PXPES(5) = 0xffffffff; \ -+} while (0) -+ -+static int jz_pm_do_hibernate(void) -+{ -+ printk("Put CPU into hibernate mode.\n"); -+ -+ /* Mask all interrupts */ -+ REG_INTC_IMSR = 0xffffffff; -+ -+ /* -+ * RTC Wakeup or 1Hz interrupt can be enabled or disabled -+ * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). -+ */ -+ -+ /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); -+ -+ /* Set reset pin low-level assertion time after wakeup: must > 60ms */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ -+ -+ /* Scratch pad register to be reserved */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HSPR = 0x12345678; -+ -+ /* clear wakeup status register */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HWRSR = 0x0; -+ -+ /* Put CPU to power down mode */ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_HCR = RTC_HCR_PD; -+ -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ while(1); -+ -+ /* We can't get here */ -+ return 0; -+} -+ -+/* NOTES: -+ * 1: Pins that are floated (NC) should be set as input and pull-enable. -+ * 2: Pins that are pull-up or pull-down by outside should be set as input -+ * and pull-disable. -+ * 3: Pins that are connected to a chip except sdram and nand flash -+ * should be set as input and pull-disable, too. -+ */ -+static void jz_board_do_sleep(unsigned long *ptr) -+{ -+ unsigned char i; -+ -+ /* Print messages of GPIO registers for debug */ -+ for(i=0;i -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#define DEBUG 1 -+#undef DEBUG -+ -+ -+struct proc_dir_entry *proc_jz_root; -+ -+ -+/* -+ * EMC Modules -+ */ -+static int emc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ -+ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); -+ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); -+ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -+ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -+ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -+ return len; -+} -+ -+/* -+ * Power Manager Module -+ */ -+static int pmc_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned long lcr = REG_CPM_LCR; -+ unsigned long clkgr = REG_CPM_CLKGR; -+ -+ len += sprintf (page+len, "Low Power Mode : %s\n", -+ ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? -+ "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? -+ "SLEEP" : "HIBERNATE")); -+ len += sprintf (page+len, "Doze Mode : %s\n", -+ (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); -+ if (lcr & CPM_LCR_DOZE_ON) -+ len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); -+ len += sprintf (page+len, "AUX_CPU : %s\n", -+ (clkgr & CPM_CLKGR_AUX_CPU) ? "stopped" : "running"); -+ len += sprintf (page+len, "AHB1 : %s\n", -+ (clkgr & CPM_CLKGR_AHB1) ? "stopped" : "running"); -+ len += sprintf (page+len, "IDCT : %s\n", -+ (clkgr & CPM_CLKGR_IDCT) ? "stopped" : "running"); -+ len += sprintf (page+len, "DB : %s\n", -+ (clkgr & CPM_CLKGR_DB) ? "stopped" : "running"); -+ len += sprintf (page+len, "ME : %s\n", -+ (clkgr & CPM_CLKGR_ME) ? "stopped" : "running"); -+ len += sprintf (page+len, "MC : %s\n", -+ (clkgr & CPM_CLKGR_MC) ? "stopped" : "running"); -+ len += sprintf (page+len, "TVE : %s\n", -+ (clkgr & CPM_CLKGR_TVE) ? "stopped" : "running"); -+ len += sprintf (page+len, "TSSI : %s\n", -+ (clkgr & CPM_CLKGR_TSSI) ? "stopped" : "running"); -+ len += sprintf (page+len, "IPU : %s\n", -+ (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); -+ len += sprintf (page+len, "DMAC : %s\n", -+ (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); -+ len += sprintf (page+len, "UDC : %s\n", -+ (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); -+ len += sprintf (page+len, "LCD : %s\n", -+ (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); -+ len += sprintf (page+len, "CIM : %s\n", -+ (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); -+ len += sprintf (page+len, "SADC : %s\n", -+ (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); -+ len += sprintf (page+len, "MSC0 : %s\n", -+ (clkgr & CPM_CLKGR_MSC0) ? "stopped" : "running"); -+ len += sprintf (page+len, "MSC1 : %s\n", -+ (clkgr & CPM_CLKGR_MSC1) ? "stopped" : "running"); -+ len += sprintf (page+len, "SSI : %s\n", -+ (clkgr & CPM_CLKGR_SSI) ? "stopped" : "running"); -+ len += sprintf (page+len, "I2C : %s\n", -+ (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); -+ len += sprintf (page+len, "RTC : %s\n", -+ (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); -+ len += sprintf (page+len, "TCU : %s\n", -+ (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART1 : %s\n", -+ (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); -+ len += sprintf (page+len, "UART0 : %s\n", -+ (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); -+ return len; -+} -+ -+static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+/* -+ * Clock Generation Module -+ */ -+#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 -+#define TO_KHZ(x) (x/1000),(x%1000)/10 -+ -+static int cgm_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ -+ unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ -+ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned int od[4] = {1, 2, 2, 4}; -+ -+ len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); -+ len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); -+ len += sprintf (page+len, "PLL : %s\n", -+ (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); -+ len += sprintf (page+len, "m:n:o : %d:%d:%d\n", -+ __cpm_get_pllm() + 2, -+ __cpm_get_plln() + 2, -+ od[__cpm_get_pllod()] -+ ); -+ len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", -+ div[__cpm_get_cdiv()], -+ div[__cpm_get_hdiv()], -+ div[__cpm_get_mdiv()], -+ div[__cpm_get_pdiv()] -+ ); -+ len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); -+ len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); -+ len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); -+ len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); -+ len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); -+ len += sprintf (page+len, "H1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_h1clk())); -+ len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); -+ len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); -+ len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); -+ len += sprintf (page+len, "MSC0CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(0))); -+ len += sprintf (page+len, "MSC1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(1))); -+ len += sprintf (page+len, "EXTALCLK0 : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk0())); -+ len += sprintf (page+len, "EXTALCLK(by CPM): %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); -+ len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); -+ -+ return len; -+} -+ -+static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); -+ return count; -+} -+ -+ -+/* USAGE: -+ * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. -+ * echo FF > /proc/jz/ipu // 255, free all buffer -+ * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx -+ * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) -+ * echo 0 > /proc/jz/ipu // debug, print ipu_buf -+ * od -X /proc/jz/ipu // read mem addr -+ */ -+ -+typedef struct _ipu_buf { -+ unsigned int addr; /* phys addr */ -+ unsigned int page_shift; -+} ipu_buf_t; -+ -+#define IPU_BUF_MAX 4 /* 4 buffers */ -+ -+static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -+static int ipu_buf_cnt = 0; -+static unsigned char g_asid=0; -+ -+extern void local_flush_tlb_all(void); -+ -+/* CP0 hazard avoidance. */ -+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ -+ "nop; nop; nop; nop; nop; nop;\n\t" \ -+ ".set reorder\n\t") -+void show_tlb(void) -+{ -+#define ASID_MASK 0xFF -+ -+ unsigned long flags; -+ unsigned int old_ctx; -+ unsigned int entry; -+ unsigned int entrylo0, entrylo1, entryhi; -+ unsigned int pagemask; -+ -+ local_irq_save(flags); -+ -+ /* Save old context */ -+ old_ctx = (read_c0_entryhi() & 0xff); -+ -+ printk("TLB content:\n"); -+ entry = 0; -+ while(entry < 32) { -+ write_c0_index(entry); -+ BARRIER; -+ tlb_read(); -+ BARRIER; -+ entryhi = read_c0_entryhi(); -+ entrylo0 = read_c0_entrylo0(); -+ entrylo1 = read_c0_entrylo1(); -+ pagemask = read_c0_pagemask(); -+ printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); -+ printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); -+ printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); -+ -+ printk("\t\tpagemask=0x%08x", pagemask); -+ printk("\tentryhi=0x%08x\n", entryhi); -+ printk("\t\tentrylo0=0x%08x", entrylo0); -+ printk("\tentrylo1=0x%08x\n", entrylo1); -+ -+ entry++; -+ } -+ BARRIER; -+ write_c0_entryhi(old_ctx); -+ -+ local_irq_restore(flags); -+} -+ -+static void ipu_add_wired_entry(unsigned long pid, -+ unsigned long entrylo0, unsigned long entrylo1, -+ unsigned long entryhi, unsigned long pagemask) -+{ -+ unsigned long flags; -+ unsigned long wired; -+ unsigned long old_pagemask; -+ unsigned long old_ctx; -+ struct task_struct *g, *p; -+ -+ /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ -+ wired = read_c0_wired(); -+ if (wired) return; -+ -+ do_each_thread(g, p) { -+ if (p->pid == pid ) -+ g_asid = p->mm->context[0]; -+ } while_each_thread(g, p); -+ -+ -+ local_irq_save(flags); -+ -+ entrylo0 = entrylo0 >> 6; /* PFN */ -+ entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ -+ -+ /* Save old context and create impossible VPN2 value */ -+ old_ctx = read_c0_entryhi() & 0xff; -+ old_pagemask = read_c0_pagemask(); -+ wired = read_c0_wired(); -+ write_c0_wired(wired + 1); -+ write_c0_index(wired); -+ BARRIER; -+ entryhi &= ~0xff; /* new add, 20070906 */ -+ entryhi |= g_asid; /* new add, 20070906 */ -+// entryhi |= old_ctx; /* new add, 20070906 */ -+ write_c0_pagemask(pagemask); -+ write_c0_entryhi(entryhi); -+ write_c0_entrylo0(entrylo0); -+ write_c0_entrylo1(entrylo1); -+ BARRIER; -+ tlb_write_indexed(); -+ BARRIER; -+ -+ write_c0_entryhi(old_ctx); -+ BARRIER; -+ write_c0_pagemask(old_pagemask); -+ local_flush_tlb_all(); -+ local_irq_restore(flags); -+#if defined(DEBUG) -+ printk("\nold_ctx=%03d\n", old_ctx); -+ -+ show_tlb(); -+#endif -+} -+ -+static void ipu_del_wired_entry( void ) -+{ -+ unsigned long flags; -+ unsigned long wired; -+ -+ local_irq_save(flags); -+ wired = read_c0_wired(); -+ if ( wired > 0 ) { -+ write_c0_wired(wired - 1); -+ } -+ local_irq_restore(flags); -+} -+ -+static inline void ipu_buf_get( unsigned int page_shift ) -+{ -+ unsigned char * virt_addr; -+ int i; -+ for ( i=0; i< IPU_BUF_MAX; ++i ) { -+ if ( ipu_buf[i].addr == 0 ) { -+ break; -+ } -+ } -+ -+ if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { -+ printk("Error, no free ipu buffer.\n"); -+ return ; -+ } -+ -+ virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ -+ if ( virt_addr ) { -+ ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); -+ ipu_buf[ipu_buf_cnt].page_shift = page_shift; -+ -+ for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ -+ printk("no free buffer.\n"); -+ *pint = 0; -+ } -+ else -+ *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ -+ len += sizeof(unsigned int); -+ -+#if defined(DEBUG) -+ show_tlb(); -+#endif -+ return len; -+ -+} -+ -+static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int val ; -+ int cnt,i; -+ char buf[12]; -+ unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -+#if defined(DEBUG) -+ printk("ipu write count=%u\n", count); -+#endif -+ if (count == (8*5+1)) { -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*0, 8); -+ pid = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*1, 8); -+ entrylo0 = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*2, 8); -+ entrylo1 = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*3, 8); -+ entryhi = simple_strtoul(buf, 0, 16); -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer+8*4, 8); -+ pagemask = simple_strtoul(buf, 0, 16); -+ -+#if defined(DEBUG) -+ printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", -+ pid, entrylo0, entrylo1, entryhi, pagemask); -+#endif -+ ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); -+ return 41; -+ } -+ else if ( count <= 8+1 ) { -+ for (i=0;i<12;i++) buf[i]=0; -+ strncpy(buf, buffer, 8); -+ val = simple_strtoul(buf, 0, 16); -+ } else if (count == 44) { -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer, 10); -+ pid = simple_strtoul(buf, 0, 16); -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 11, 10); -+ entryhi = simple_strtoul(buf, 0, 16);//vaddr -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 22, 10); -+ entrylo0 = simple_strtoul(buf, 0, 16);//paddr -+ for (i = 0; i < 12; i++) -+ buf[i] = 0; -+ strncpy(buf, buffer + 33, 10); -+ pagemask = simple_strtoul(buf, 0, 16); -+ pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ -+ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); -+ return 44; -+ } else { -+ printk("ipu write count error, count=%d\n.", (unsigned int)count); -+ return -1; -+ } -+ -+ /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ -+ if ( val == 0 ) { /* debug, print ipu_buf info */ -+ for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages -+ * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx -+ * echo FF > /proc/jz/ipu // FF, free all buffers -+ * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer -+ */ -+ -+//#define DEBUG_IMEM 1 -+ -+#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ -+ -+static unsigned int jz_imem_base; /* physical base address of ipu memory */ -+ -+static unsigned int allocated_phys_addr = 0; -+ -+/* -+ * Allocated buffer list -+ */ -+typedef struct imem_list { -+ unsigned int phys_start; /* physical start addr */ -+ unsigned int phys_end; /* physical end addr */ -+ struct imem_list *next; -+} imem_list_t; -+ -+static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ -+ -+#ifdef DEBUG_IMEM -+static void dump_imem_list(void) -+{ -+ struct imem_list *imem; -+ -+ printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); -+ imem = imem_list_head; -+ while (imem) { -+ printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); -+ imem = imem->next; -+ } -+} -+#endif -+ -+/* allocate 2^order pages inside the 4MB memory */ -+static int imem_alloc(unsigned int order) -+{ -+ int alloc_ok = 0; -+ unsigned int start, end; -+ unsigned int size = (1 << order) * PAGE_SIZE; -+ struct imem_list *imem, *imemn, *imemp; -+ -+ allocated_phys_addr = 0; -+ -+ start = jz_imem_base; -+ end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -+ -+ imem = imem_list_head; -+ while (imem) { -+ if ((imem->phys_start - start) >= size) { -+ /* we got a valid address range */ -+ alloc_ok = 1; -+ break; -+ } -+ -+ start = imem->phys_end + 1; -+ imem = imem->next; -+ } -+ -+ if (!alloc_ok) { -+ if ((end - start) >= size) -+ alloc_ok = 1; -+ } -+ -+ if (alloc_ok) { -+ end = start + size - 1; -+ allocated_phys_addr = start; -+ -+ /* add to imem_list, up sorted by phys_start */ -+ imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); -+ if (!imemn) { -+ return -ENOMEM; -+ } -+ imemn->phys_start = start; -+ imemn->phys_end = end; -+ imemn->next = NULL; -+ -+ if (!imem_list_head) -+ imem_list_head = imemn; -+ else { -+ imem = imemp = imem_list_head; -+ while (imem) { -+ if (start < imem->phys_start) { -+ break; -+ } -+ -+ imemp = imem; -+ imem = imem->next; -+ } -+ -+ if (imem == imem_list_head) { -+ imem_list_head = imemn; -+ imemn->next = imem; -+ } -+ else { -+ imemn->next = imemp->next; -+ imemp->next = imemn; -+ } -+ } -+ } -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+ return 0; -+} -+ -+static void imem_free(unsigned int phys_addr) -+{ -+ struct imem_list *imem, *imemp; -+ -+ imem = imemp = imem_list_head; -+ while (imem) { -+ if (phys_addr == imem->phys_start) { -+ if (imem == imem_list_head) { -+ imem_list_head = imem->next; -+ } -+ else { -+ imemp->next = imem->next; -+ } -+ -+ kfree(imem); -+ break; -+ } -+ -+ imemp = imem; -+ imem = imem->next; -+ } -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+} -+ -+static void imem_free_all(void) -+{ -+ struct imem_list *imem; -+ -+ imem = imem_list_head; -+ while (imem) { -+ kfree(imem); -+ imem = imem->next; -+ } -+ -+ imem_list_head = NULL; -+ -+ allocated_phys_addr = 0; -+ -+#ifdef DEBUG_IMEM -+ dump_imem_list(); -+#endif -+} -+ -+/* -+ * Return the allocated buffer address and the max order of free buffer -+ */ -+static int imem_read_proc(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = 0; -+ unsigned int start_addr, end_addr, max_order, max_size; -+ struct imem_list *imem; -+ -+ unsigned int *tmp = (unsigned int *)(page + len); -+ -+ start_addr = jz_imem_base; -+ end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -+ -+ if (!imem_list_head) -+ max_size = end_addr - start_addr; -+ else { -+ max_size = 0; -+ imem = imem_list_head; -+ while (imem) { -+ if (max_size < (imem->phys_start - start_addr)) -+ max_size = imem->phys_start - start_addr; -+ -+ start_addr = imem->phys_end + 1; -+ imem = imem->next; -+ } -+ -+ if (max_size < (end_addr - start_addr)) -+ max_size = end_addr - start_addr; -+ } -+ -+ if (max_size > 0) { -+ max_order = get_order(max_size); -+ if (((1 << max_order) * PAGE_SIZE) > max_size) -+ max_order--; -+ } -+ else { -+ max_order = 0xffffffff; /* No any free buffer */ -+ } -+ -+ *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ -+ *tmp = max_order; /* max order of current free buffers */ -+ -+ len += 2 * sizeof(unsigned int); -+ -+ return len; -+} -+ -+static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -+{ -+ unsigned int val; -+ -+ val = simple_strtoul(buffer, 0, 16); -+ -+ if (val == 0xff) { -+ /* free all memory */ -+ imem_free_all(); -+ } -+ else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { -+ /* allocate 2^val pages */ -+ imem_alloc(val); -+ } -+ else { -+ /* free buffer which phys_addr is val */ -+ imem_free(val); -+ } -+ -+ return count; -+} -+ -+/* -+ * /proc/jz/xxx entry -+ * -+ */ -+static int __init jz_proc_init(void) -+{ -+ struct proc_dir_entry *res; -+ unsigned int virt_addr, i; -+ -+ proc_jz_root = proc_mkdir("jz", 0); -+ -+ /* External Memory Controller */ -+ res = create_proc_entry("emc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = emc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* Power Management Controller */ -+ res = create_proc_entry("pmc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = pmc_read_proc; -+ res->write_proc = pmc_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Clock Generation Module */ -+ res = create_proc_entry("cgm", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = cgm_read_proc; -+ res->write_proc = cgm_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Image process unit */ -+ res = create_proc_entry("ipu", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = ipu_read_proc; -+ res->write_proc = ipu_write_proc; -+ res->data = NULL; -+ } -+ -+ /* udc hotplug */ -+ res = create_proc_entry("udc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = udc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* mmc hotplug */ -+ res = create_proc_entry("mmc", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = mmc_read_proc; -+ res->write_proc = NULL; -+ res->data = NULL; -+ } -+ -+ /* -+ * Reserve a 4MB memory for IPU on JZ4750D. -+ */ -+ jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); -+ if (jz_imem_base) { -+ /* imem (IPU memory management) */ -+ res = create_proc_entry("imem", 0644, proc_jz_root); -+ if (res) { -+ res->read_proc = imem_read_proc; -+ res->write_proc = imem_write_proc; -+ res->data = NULL; -+ } -+ -+ /* Set page reserved */ -+ virt_addr = jz_imem_base; -+ for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { -+ SetPageReserved(virt_to_page((void *)virt_addr)); -+ virt_addr += PAGE_SIZE; -+ } -+ -+ /* Convert to physical address */ -+ jz_imem_base = virt_to_phys((void *)jz_imem_base); -+ -+ printk("Total %dMB memory at 0x%x was reserved for IPU\n", -+ (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); -+ } -+ -+ return 0; -+} -+ -+__initcall(jz_proc_init); -diff --git a/arch/mips/jz4750d/prom.c b/arch/mips/jz4750d/prom.c -new file mode 100644 -index 0000000..3c173d6 ---- /dev/null -+++ b/arch/mips/jz4750d/prom.c -@@ -0,0 +1,198 @@ -+/* -+ * -+ * BRIEF MODULE DESCRIPTION -+ * PROM library initialisation code, supports YAMON and U-Boot. -+ * -+ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * ppopov@mvista.com or source@mvista.com -+ * -+ * This file was derived from Carsten Langgaard's -+ * arch/mips/mips-boards/xx files. -+ * -+ * Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* #define DEBUG_CMDLINE */ -+ -+int prom_argc; -+char **prom_argv, **prom_envp; -+ -+char * prom_getcmdline(void) -+{ -+ return &(arcs_cmdline[0]); -+} -+ -+void prom_init_cmdline(void) -+{ -+ char *cp; -+ int actr; -+ -+ actr = 1; /* Always ignore argv[0] */ -+ -+ cp = &(arcs_cmdline[0]); -+ while(actr < prom_argc) { -+ strcpy(cp, prom_argv[actr]); -+ cp += strlen(prom_argv[actr]); -+ *cp++ = ' '; -+ actr++; -+ } -+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -+ --cp; -+ if (prom_argc > 1) -+ *cp = '\0'; -+ -+} -+ -+ -+char *prom_getenv(char *envname) -+{ -+#if 0 -+ /* -+ * Return a pointer to the given environment variable. -+ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -+ */ -+ -+ char **env = prom_envp; -+ int i = strlen(envname); -+ int yamon = (*env && strchr(*env, '=') == NULL); -+ -+ while (*env) { -+ if (yamon) { -+ if (strcmp(envname, *env++) == 0) -+ return *env; -+ } else { -+ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -+ return *env + i + 1; -+ } -+ env++; -+ } -+#endif -+ return NULL; -+} -+ -+inline unsigned char str2hexnum(unsigned char c) -+{ -+ if(c >= '0' && c <= '9') -+ return c - '0'; -+ if(c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ if(c >= 'A' && c <= 'F') -+ return c - 'A' + 10; -+ return 0; /* foo */ -+} -+ -+inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; -+ -+ for(i = 0; i < 6; i++) { -+ unsigned char num; -+ -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} -+ -+int get_ethernet_addr(char *ethernet_addr) -+{ -+ char *ethaddr_str; -+ -+ ethaddr_str = prom_getenv("ethaddr"); -+ if (!ethaddr_str) { -+ printk("ethaddr not set in boot prom\n"); -+ return -1; -+ } -+ str2eaddr(ethernet_addr, ethaddr_str); -+ -+#if 0 -+ { -+ int i; -+ -+ printk("get_ethernet_addr: "); -+ for (i=0; i<5; i++) -+ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -+ printk("%02x\n", *(ethernet_addr+i)); -+ } -+#endif -+ -+ return 0; -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init prom_init(void) -+{ -+ unsigned char *memsize_str; -+ unsigned long memsize; -+ -+ prom_argc = (int) fw_arg0; -+ prom_argv = (char **) fw_arg1; -+ prom_envp = (char **) fw_arg2; -+ -+ mips_machtype = MACH_INGENIC_JZ4750D; -+ -+ prom_init_cmdline(); -+ memsize_str = prom_getenv("memsize"); -+ if (!memsize_str) { -+ memsize = 0x04000000; -+ } else { -+ memsize = simple_strtol(memsize_str, NULL, 0); -+ } -+ add_memory_region(0, memsize, BOOT_MEM_RAM); -+} -+ -+/* used by early printk */ -+void prom_putchar(char c) -+{ -+ volatile u8 *uart_lsr = (volatile u8 *)(UART1_BASE + OFF_LSR); -+ volatile u8 *uart_tdr = (volatile u8 *)(UART1_BASE + OFF_TDR); -+ -+ /* Wait for fifo to shift out some bytes */ -+ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -+ -+ *uart_tdr = (u8)c; -+} -+ -+const char *get_system_type(void) -+{ -+ return "JZ4750D"; -+} -+ -+EXPORT_SYMBOL(prom_getcmdline); -+EXPORT_SYMBOL(get_ethernet_addr); -+EXPORT_SYMBOL(str2eaddr); -diff --git a/arch/mips/jz4750d/reset.c b/arch/mips/jz4750d/reset.c -new file mode 100644 -index 0000000..90b521e ---- /dev/null -+++ b/arch/mips/jz4750d/reset.c -@@ -0,0 +1,46 @@ -+/* -+ * linux/arch/mips/jz4750/reset.c -+ * -+ * JZ4750 reset routines. -+ * -+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+void jz_restart(char *command) -+{ -+ printk("Restarting after 4 ms\n"); -+ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; -+ REG_WDT_TCNT = 0; -+ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ -+ REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */ -+ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ -+ while (1); -+} -+ -+void jz_halt(void) -+{ -+ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -+ -+ while (1) -+ __asm__(".set\tmips3\n\t" -+ "wait\n\t" -+ ".set\tmips0"); -+} -+ -+void jz_power_off(void) -+{ -+ jz_halt(); -+} -diff --git a/arch/mips/jz4750d/setup.c b/arch/mips/jz4750d/setup.c -new file mode 100644 -index 0000000..b9b8aab ---- /dev/null -+++ b/arch/mips/jz4750d/setup.c -@@ -0,0 +1,199 @@ -+/* -+ * linux/arch/mips/jz4750d/common/setup.c -+ * -+ * JZ4750D common setup routines. -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_PC_KEYB -+#include -+#endif -+ -+jz_clocks_t jz_clocks; -+ -+extern char * __init prom_getcmdline(void); -+extern void __init jz_board_setup(void); -+extern void jz_restart(char *); -+extern void jz_halt(void); -+extern void jz_power_off(void); -+extern void jz_time_init(void); -+ -+static void __init sysclocks_setup(void) -+{ -+#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ -+ jz_clocks.cclk = __cpm_get_cclk(); -+ jz_clocks.hclk = __cpm_get_hclk(); -+ jz_clocks.pclk = __cpm_get_pclk(); -+ jz_clocks.mclk = __cpm_get_mclk(); -+ jz_clocks.h1clk = __cpm_get_h1clk(); -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.i2sclk = __cpm_get_i2sclk(); -+ jz_clocks.usbclk = __cpm_get_usbclk(); -+ jz_clocks.mscclk = __cpm_get_mscclk(0); -+ jz_clocks.extalclk = __cpm_get_extalclk(); -+ jz_clocks.rtcclk = __cpm_get_rtcclk(); -+#else -+ -+#define FPGACLK 8000000 -+ -+ jz_clocks.cclk = FPGACLK; -+ jz_clocks.hclk = FPGACLK; -+ jz_clocks.pclk = FPGACLK; -+ jz_clocks.mclk = FPGACLK; -+ jz_clocks.h1clk = FPGACLK; -+ jz_clocks.pixclk = FPGACLK; -+ jz_clocks.i2sclk = FPGACLK; -+ jz_clocks.usbclk = FPGACLK; -+ jz_clocks.mscclk = FPGACLK; -+ jz_clocks.extalclk = FPGACLK; -+ jz_clocks.rtcclk = FPGACLK; -+#endif -+ -+ printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", -+ (jz_clocks.cclk + 500000) / 1000000, -+ (jz_clocks.hclk + 500000) / 1000000, -+ (jz_clocks.pclk + 500000) / 1000000, -+ (jz_clocks.mclk + 500000) / 1000000); -+} -+ -+static void __init soc_cpm_setup(void) -+{ -+ /* Start all module clocks -+ */ -+ __cpm_start_all(); -+ -+ /* Enable CKO to external memory */ -+ __cpm_enable_cko(); -+ -+ /* CPU enters IDLE mode when executing 'wait' instruction */ -+ __cpm_idle_mode(); -+ -+ /* Setup system clocks */ -+ sysclocks_setup(); -+} -+ -+static void __init soc_harb_setup(void) -+{ -+// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -+// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -+} -+ -+static void __init soc_emc_setup(void) -+{ -+} -+ -+static void __init soc_dmac_setup(void) -+{ -+ __dmac_enable_module(0); -+ __dmac_enable_module(1); -+} -+ -+static void __init jz_soc_setup(void) -+{ -+ soc_cpm_setup(); -+ soc_harb_setup(); -+ soc_emc_setup(); -+ soc_dmac_setup(); -+} -+ -+static void __init jz_serial_setup(void) -+{ -+#ifdef CONFIG_SERIAL_8250 -+ struct uart_port s; -+ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ -+ memset(&s, 0, sizeof(s)); -+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -+ s.iotype = SERIAL_IO_MEM; -+ s.regshift = 2; -+ s.uartclk = jz_clocks.extalclk ; -+ -+ s.line = 0; -+ s.membase = (u8 *)UART0_BASE; -+ s.irq = IRQ_UART0; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -+ } -+ -+ s.line = 1; -+ s.membase = (u8 *)UART1_BASE; -+ s.irq = IRQ_UART1; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -+ } -+ -+ s.line = 2; -+ s.membase = (u8 *)UART2_BASE; -+ s.irq = IRQ_UART2; -+ -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS2 setup failed!\n"); -+ } -+/* -+ s.line = 3; -+ s.membase = (u8 *)UART3_BASE; -+ s.irq = IRQ_UART3; -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial ttyS3 setup failed!\n"); -+ } -+*/ -+#endif -+} -+ -+void __init plat_mem_setup(void) -+{ -+ char *argptr; -+ -+ argptr = prom_getcmdline(); -+ -+ /* IO/MEM resources. Which will be the addtion value in `inX' and -+ * `outX' macros defined in asm/io.h */ -+ set_io_port_base(0); -+ ioport_resource.start = 0x00000000; -+ ioport_resource.end = 0xffffffff; -+ iomem_resource.start = 0x00000000; -+ iomem_resource.end = 0xffffffff; -+ -+ _machine_restart = jz_restart; -+ _machine_halt = jz_halt; -+ pm_power_off = jz_power_off; -+ -+ jz_soc_setup(); -+ jz_serial_setup(); -+ jz_board_setup(); -+} -+ -diff --git a/arch/mips/jz4750d/time.c b/arch/mips/jz4750d/time.c -new file mode 100644 -index 0000000..0c6d647 ---- /dev/null -+++ b/arch/mips/jz4750d/time.c -@@ -0,0 +1,156 @@ -+/* -+ * linux/arch/mips/jz4750d/time.c -+ * -+ * Setting up the clock on the JZ4750D boards. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ */ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* This is for machines which generate the exact clock. */ -+ -+#define JZ_TIMER_IRQ IRQ_TCU0 -+ -+#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ -+ -+static struct clocksource clocksource_jz; /* Jz clock source */ -+static struct clock_event_device jz_clockevent_device; /* Jz clock event */ -+ -+void (*jz_timer_callback)(void); -+ -+static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *cd = dev_id; -+ -+ REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */ -+ -+ if (jz_timer_callback) -+ jz_timer_callback(); -+ -+ cd->event_handler(cd); -+ -+ return IRQ_HANDLED; -+} -+ -+static struct irqaction jz_irqaction = { -+ .handler = jz_timer_interrupt, -+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, -+ .name = "jz-timerirq", -+}; -+ -+ -+cycle_t jz_get_cycles(void) -+{ -+ /* convert jiffes to jz timer cycles */ -+ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT); -+} -+ -+static struct clocksource clocksource_jz = { -+ .name = "jz_clocksource", -+ .rating = 300, -+ .read = jz_get_cycles, -+ .mask = 0xFFFFFFFF, -+ .shift = 10, -+ .flags = CLOCK_SOURCE_WATCHDOG, -+}; -+ -+static int __init jz_clocksource_init(void) -+{ -+ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -+ clocksource_register(&clocksource_jz); -+ return 0; -+} -+ -+static int jz_set_next_event(unsigned long evt, -+ struct clock_event_device *unused) -+{ -+ return 0; -+} -+ -+static void jz_set_mode(enum clock_event_mode mode, -+ struct clock_event_device *evt) -+{ -+ switch (mode) { -+ case CLOCK_EVT_MODE_PERIODIC: -+ break; -+ case CLOCK_EVT_MODE_ONESHOT: -+ case CLOCK_EVT_MODE_UNUSED: -+ case CLOCK_EVT_MODE_SHUTDOWN: -+ break; -+ case CLOCK_EVT_MODE_RESUME: -+ break; -+ } -+} -+ -+static struct clock_event_device jz_clockevent_device = { -+ .name = "jz-clockenvent", -+ .features = CLOCK_EVT_FEAT_PERIODIC, -+// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ -+ -+ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -+ .rating = 300, -+ .irq = JZ_TIMER_IRQ, -+ .set_mode = jz_set_mode, -+ .set_next_event = jz_set_next_event, -+}; -+ -+static void __init jz_clockevent_init(void) -+{ -+ struct clock_event_device *cd = &jz_clockevent_device; -+ unsigned int cpu = smp_processor_id(); -+ -+ cd->cpumask = cpumask_of_cpu(cpu); -+ clockevents_register_device(cd); -+} -+ -+static void __init jz_timer_setup(void) -+{ -+ jz_clocksource_init(); /* init jz clock source */ -+ jz_clockevent_init(); /* init jz clock event */ -+ -+ /* -+ * Make irqs happen for the system timer -+ */ -+ jz_irqaction.dev_id = &jz_clockevent_device; -+ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -+} -+ -+ -+void __init plat_time_init(void) -+{ -+ unsigned int latch; -+ -+ /* Init timer */ -+ latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -+ -+ REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN; -+ REG_TCU_OSTCNT = 0; -+ REG_TCU_OSTDR = latch; -+ -+ REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */ -+ REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */ -+ REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */ -+ -+ jz_timer_setup(); -+} -diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c -index 1abe990..bdcf5b6 100644 ---- a/arch/mips/kernel/cpu-probe.c -+++ b/arch/mips/kernel/cpu-probe.c -@@ -159,6 +159,7 @@ void __init check_wait(void) - case CPU_25KF: - case CPU_PR4450: - case CPU_BCM3302: -+ case CPU_JZRISC: - case CPU_CAVIUM_OCTEON: - cpu_wait = r4k_wait; - break; -@@ -580,6 +581,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) - MIPS_CPU_32FPR; - c->tlbsize = 64; - break; -+ case PRID_IMP_JZRISC: -+ c->cputype = CPU_JZRISC; -+ __cpu_name[cpu] = "Ingenic JZRISC"; -+ c->isa_level = MIPS_CPU_ISA_M32R1; -+ /* JZRISC does not implement the CP0 counter. */ -+ c->options &= ~MIPS_CPU_COUNTER; -+ c->tlbsize = 32; -+ break; - } - } - -@@ -888,6 +897,23 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu) - } - } - -+static inline void cpu_probe_ingenic(struct cpuinfo_mips *c) -+{ -+ decode_configs(c); -+ c->options &= ~MIPS_CPU_COUNTER; /* JZRISC does not implement the CP0 counter. */ -+ switch (c->processor_id & 0xff00) { -+ case PRID_IMP_JZRISC: -+ c->cputype = CPU_JZRISC; -+ __cpu_name[cpu] = "Ingenic JZRISC"; -+ c->isa_level = MIPS_CPU_ISA_M32R1; -+ c->tlbsize = 32; -+ break; -+ default: -+ panic("Unknown Ingenic Processor ID!"); -+ break; -+ } -+} -+ - const char *__cpu_name[NR_CPUS]; - - __cpuinit void cpu_probe(void) -@@ -925,6 +951,9 @@ __cpuinit void cpu_probe(void) - case PRID_COMP_CAVIUM: - cpu_probe_cavium(c, cpu); - break; -+ case PRID_COMP_INGENIC: -+ cpu_probe_ingenic(c); -+ break; - } - - BUG_ON(!__cpu_name[cpu]); -diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c -index 67bd626..9d6dca1 100644 ---- a/arch/mips/kernel/unaligned.c -+++ b/arch/mips/kernel/unaligned.c -@@ -497,6 +497,11 @@ sigill: - force_sig(SIGILL, current); - } - -+#if defined(CONFIG_JZ_TCSM) -+#undef user_mode -+#define user_mode(regs) ((((regs)->cp0_status & KU_MASK) == KU_USER) || (regs->cp0_badvaddr < 0x80000000)) -+#endif -+ - asmlinkage void do_ade(struct pt_regs *regs) - { - unsigned int __user *pc; -@@ -522,8 +527,9 @@ asmlinkage void do_ade(struct pt_regs *regs) - * This is all so but ugly ... - */ - seg = get_fs(); -- if (!user_mode(regs)) -+ if (!user_mode(regs)) { - set_fs(KERNEL_DS); -+ } - emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc); - set_fs(seg); - -diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c -index 6721ee2..dd4b70b 100644 ---- a/arch/mips/mm/c-r4k.c -+++ b/arch/mips/mm/c-r4k.c -@@ -928,6 +928,36 @@ static void __cpuinit probe_pcache(void) - c->dcache.waybit = 0; - break; - -+ case CPU_JZRISC: -+ config1 = read_c0_config1(); -+ config1 = (config1 >> 22) & 0x07; -+ if (config1 == 0x07) -+ config1 = 10; -+ else -+ config1 = config1 + 11; -+ config1 += 2; -+ icache_size = (1 << config1); -+ c->icache.linesz = 32; -+ c->icache.ways = 4; -+ c->icache.waybit = __ffs(icache_size / c->icache.ways); -+ -+ config1 = read_c0_config1(); -+ config1 = (config1 >> 13) & 0x07; -+ if (config1 == 0x07) -+ config1 = 10; -+ else -+ config1 = config1 + 11; -+ config1 += 2; -+ dcache_size = (1 << config1); -+ c->dcache.linesz = 32; -+ c->dcache.ways = 4; -+ c->dcache.waybit = __ffs(dcache_size / c->dcache.ways); -+ -+ c->dcache.flags = 0; -+ c->options |= MIPS_CPU_PREFETCH; -+ -+ break; -+ - default: - if (!(config & MIPS_CONF_M)) - panic("Don't know how to probe P-caches on this cpu."); -diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c -index 694d51f..4b2bc95 100644 ---- a/arch/mips/mm/cache.c -+++ b/arch/mips/mm/cache.c -@@ -52,6 +52,8 @@ void (*_dma_cache_wback)(unsigned long start, unsigned long size); - void (*_dma_cache_inv)(unsigned long start, unsigned long size); - - EXPORT_SYMBOL(_dma_cache_wback_inv); -+EXPORT_SYMBOL(_dma_cache_wback); -+EXPORT_SYMBOL(_dma_cache_inv); - - #endif /* CONFIG_DMA_NONCOHERENT */ - -diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c -index 9a17bf8..9b80053 100644 ---- a/arch/mips/mm/tlbex.c -+++ b/arch/mips/mm/tlbex.c -@@ -385,6 +385,11 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, - tlbw(p); - break; - -+ case CPU_JZRISC: -+ tlbw(p); -+ uasm_i_nop(p); -+ break; -+ - default: - panic("No TLB refill handler yet (CPU type: %d)", - current_cpu_data.cputype); -diff --git a/crypto/Makefile b/crypto/Makefile -index 673d9f7..7180908 100644 ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -77,6 +77,7 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o - obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o - obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o - obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o -+obj-$(CONFIG_CRYPTO_LZO) += lzo.o - obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o - obj-$(CONFIG_CRYPTO_LZO) += lzo.o - obj-$(CONFIG_CRYPTO_RNG2) += rng.o -diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c -index d59ba50..217080e 100644 ---- a/crypto/tcrypt.c -+++ b/crypto/tcrypt.c -@@ -680,6 +680,11 @@ static int do_test(int m) - ret += tcrypt_test("rfc4309(ccm(aes))"); - break; - -+ case 33: -+ test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template, -+ LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS); -+ break; -+ - case 100: - ret += tcrypt_test("hmac(md5)"); - break; -diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 6a06913..357a6c0 100644 ---- a/drivers/char/Kconfig -+++ b/drivers/char/Kconfig -@@ -831,6 +831,16 @@ config RTC - To compile this driver as a module, choose M here: the - module will be called rtc. - -+config RTC_PCF8563 -+ bool 'Philips PCF8563 Real Time Clock (I2C Bus)' -+ help -+ Philips PCF8563 Real Time Clock (I2C Bus) -+ -+config RTC_JZ -+ bool 'Jz47XX On-Chip Real Time Clock' -+ help -+ Jz47XX On-Chip Real Time Clock -+ - config JS_RTC - tristate "Enhanced Real Time Clock Support" - depends on SPARC32 && PCI -@@ -1109,6 +1119,7 @@ config DEVPORT - default y - - source "drivers/s390/char/Kconfig" -+source "drivers/char/jzchar/Kconfig" - - endmenu - -diff --git a/drivers/char/Makefile b/drivers/char/Makefile -index 66f779a..ae98c77 100644 ---- a/drivers/char/Makefile -+++ b/drivers/char/Makefile -@@ -98,6 +98,10 @@ obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o - obj-$(CONFIG_GPIO_TB0219) += tb0219.o - obj-$(CONFIG_TELCLOCK) += tlclk.o - -+obj-$(CONFIG_RTC_PCF8563) += rtc_pcf8563.o -+obj-$(CONFIG_RTC_JZ) += rtc_jz.o -+obj-$(CONFIG_JZCHAR) += jzchar/ -+ - obj-$(CONFIG_MWAVE) += mwave/ - obj-$(CONFIG_AGP) += agp/ - obj-$(CONFIG_PCMCIA) += pcmcia/ -diff --git a/drivers/char/jzchar/Kconfig b/drivers/char/jzchar/Kconfig -new file mode 100644 -index 0000000..4f7ff70 ---- /dev/null -+++ b/drivers/char/jzchar/Kconfig -@@ -0,0 +1,70 @@ -+# -+# JzSOC char devices configuration -+# -+ -+menu "JZSOC char device support" -+ depends on SOC_JZ4740 || SOC_JZ4730 || SOC_JZ4750 || SOC_JZ4750D -+ -+config JZCHAR -+ tristate 'JzSOC char device support' -+ -+config JZ_CAMERA_SENSOR -+ bool -+ -+config JZ_CIM -+ tristate 'JzSOC Camera Interface Module (CIM) support' -+ depends on JZCHAR -+ select JZ_CAMERA_SENSOR -+ -+config JZ_TPANEL_ATA2508 -+ tristate 'JzSOC MPEG4 TOUCH PANEL ATA2508 support' -+ depends on JZCHAR -+ -+config JZ_TPANEL -+ tristate 'JzSOC touchpanel driver support' -+ depends on JZCHAR -+# select JZ_SADC if SOC_JZ4740 -+# select JZ_TPANEL_AK4182 if SOC_JZ4730 -+ -+choice -+ prompt "Touch Panel ADC type" -+ depends on JZ_TPANEL -+ default JZ_SADC if SOC_JZ4740 || SOC_JZ4750 || SOC_JZ4750D -+ default JZ_TPANEL_AK4182 if SOC_JZ4730 -+ -+config JZ_SADC -+ bool 'Select the JZ47XX internal SADC' -+ -+config JZ_TPANEL_AK4182 -+ bool 'Select the AK4182 codec' -+ -+config JZ_TPANEL_UCB1400 -+ bool 'Select the UCB1400 codec' -+ -+config JZ_TPANEL_WM9712 -+ bool 'Select the WM9712 codec' -+ -+endchoice -+ -+config JZ_UDC_HOTPLUG -+ tristate 'JZ UDC hotplug driver support' -+ depends on JZCHAR -+ -+config JZ_POWEROFF -+ tristate 'JZ board poweroff support' -+ depends on JZCHAR -+ -+config JZ_OW -+ tristate 'JZ One-wire bus support' -+ depends on JZCHAR -+ -+config JZ_TCSM -+ tristate 'JZ TCSM support' -+ depends on JZCHAR -+ -+config JZ_TSSI -+ tristate 'JZ MPEG2-TS interface support' -+ depends on JZCHAR && (SOC_JZ4750 || SOC_JZ4750D) -+ -+endmenu -+ -diff --git a/drivers/char/jzchar/Makefile b/drivers/char/jzchar/Makefile -new file mode 100644 -index 0000000..b079ffc ---- /dev/null -+++ b/drivers/char/jzchar/Makefile -@@ -0,0 +1,24 @@ -+# -+# Makefile for jzchar -+# -+obj-$(CONFIG_JZCHAR) += jzchars.o -+ -+obj-$(CONFIG_JZ_SCC) += scc.o -+obj-$(CONFIG_JZ_CIM) += cim.o -+obj-$(CONFIG_JZ_TPANEL_ATA2508) += ata2508.o -+obj-$(CONFIG_JZ_CAMERA_SENSOR) += sensor.o -+obj-$(CONFIG_JZ_I2C_EEPROM) += eeprom.o -+obj-$(CONFIG_JZ_EJTAG) += ejtag.o -+obj-$(CONFIG_JZ_POWEROFF) += poweroff.o -+ -+obj-$(CONFIG_JZ_TPANEL) += jz_ts.o -+obj-$(CONFIG_JZ_TPANEL_UCB1400) += ucb1400.o -+obj-$(CONFIG_JZ_TPANEL_WM9712) += wm9712.o -+obj-$(CONFIG_JZ_TPANEL_AK4182) += ak4182.o -+obj-$(CONFIG_JZ_SADC) += sadc.o -+ -+obj-$(CONFIG_JZ_SMART_LCD) += slcd.o -+obj-$(CONFIG_JZ_UDC_HOTPLUG) += udc_hotplug.o -+obj-$(CONFIG_JZ_OW) += jz_ow.o -+obj-$(CONFIG_JZ_TCSM) += tcsm.o -+obj-$(CONFIG_JZ_TSSI) += jz_tssi.o -diff --git a/drivers/char/jzchar/ak4182.c b/drivers/char/jzchar/ak4182.c -new file mode 100644 -index 0000000..c88aa9a ---- /dev/null -+++ b/drivers/char/jzchar/ak4182.c -@@ -0,0 +1,657 @@ -+/* -+ * ak4182.c using national microwire protocol -+ * -+ * Touch screen driver interface to the AK4182A . -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jz_ts.h" -+#include "ak4182.h" -+ -+#define TS_PIN GPIO_TS_PENIRQ -+#define TS_IRQ (IRQ_GPIO_0 + TS_PIN) -+ -+static int samples = 5; -+static int first_time = 0; -+static unsigned long last_x, last_y, last_p; -+ -+static int adcsync = 0; -+ -+static struct ak4182 *ak; -+ -+extern unsigned int (*codec_read_battery)(void); -+ -+/*------------------JzSoc SSI configure----------------*/ -+static void ak4182_ssi_reset(void) -+{ -+ REG_SSI_CR0 = 0x0000; -+ REG_SSI_CR1 = 0x00007960; -+ REG_SSI_SR = 0x00000098; -+ REG_SSI_ITR = 0x0000; -+ REG_SSI_ICR = 0x00; -+ REG_SSI_GR = 0x0000; -+ -+ __ssi_disable(); -+ __ssi_flush_fifo(); -+ __ssi_clear_errors(); -+ __ssi_select_ce(); -+} -+ -+static void ak4182_ssi_enable(void) -+{ -+ __ssi_enable(); -+} -+ -+#ifdef CONFIG_PM -+static void ak4182_ssi_disable(void) -+{ -+ __ssi_disable(); -+} -+#endif -+ -+static void ak4182_ssi_set_trans_mode_format(void) -+{ -+ __ssi_microwire_format(); -+ __ssi_set_msb(); -+ __ssi_set_microwire_command_length(8); -+ __ssi_set_frame_length(12); -+} -+ -+static void ak4182_ssi_set_clk_div_ratio(int dev_clk, int ssi_clk) -+{ -+ __ssi_set_clk(dev_clk, ssi_clk); -+} -+ -+static void ak4182_ssi_set_normal_mode(void) -+{ -+ __ssi_normal_mode(); -+} -+ -+static void ak4182_ssi_set_IRQ(void) -+{ -+ __ssi_disable_tx_intr(); -+ __ssi_disable_rx_intr(); -+} -+ -+/*------------------ AK4182 routines ------------------*/ -+static inline void ak4182_reg_write(unsigned short val) -+{ -+ __ssi_transmit_data(val); -+} -+ -+static inline unsigned int ak4182_reg_read(void) -+{ -+ unsigned int val; -+ val = __ssi_receive_data(); -+ return val; -+} -+ -+static unsigned int ak4182_adc_read(int cmd_code, int sync) -+{ -+ unsigned int val, timeout = 10000; -+ unsigned int status,valid1,valid2,dataentry; -+ -+ ak4182_reg_write(cmd_code); -+ udelay(2);//wait 2 D_CLK -+ for (;;) { -+ status =0; -+ status = REG_SSI_SR; -+ valid1 = (status>>7) & 1; -+ valid2 = (status>>6) & 1; -+ if( valid1==1 && valid2==0 )//SSI transfer is finished -+ { -+ //Receive FIFO data entry number -+ dataentry = val = 0; -+ dataentry = (status>>8) & 0x1F; -+ if( dataentry > 5 ) -+ { -+ printk("R-FIFO entry=%d,SSI transfer is wrong!\n",dataentry); -+ while(dataentry > 0) -+ { -+ ak4182_reg_read(); -+ dataentry--; -+ } -+ return 0; -+ } -+ while(dataentry > 0) -+ { -+ val = ak4182_reg_read(); -+ dataentry--; -+ } -+ return val; -+ } -+ -+ if (--timeout == 0) -+ break; -+ udelay(1); -+ } -+ return 0; -+} -+ -+ -+//enable pen down IRQ -+static void ak4182_enable_irq(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ak->lock, flags); -+ __gpio_unmask_irq(TS_PIN); -+ spin_unlock_irqrestore(&ak->lock, flags); -+} -+ -+//disable pen down IRQ -+static void ak4182_disable_irq(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ak->lock, flags); -+ __gpio_mask_irq(TS_PIN); -+// spin_unlock_irqrestore(&ucb->lock, flags); -+ spin_unlock_irqrestore(&ak->lock, flags); -+} -+/* -+ * Switch to X position mode and measure Y plate. We switch the plate -+ * configuration in pressure mode, then switch to position mode. This -+ * gives a faster response time. Even so, we need to wait about 55us -+ * for things to stabilise. -+ */ -+static inline unsigned int ak4182_ts_read_xpos(void) -+{ -+ return ak4182_adc_read(0xD0, adcsync);//X-axis,0xD0 for 12bit,0xD8 for 8bit -+} -+ -+ -+/* -+ * Switch to pressure mode, and read pressure. We don't need to wait -+ * here, since both plates are being driven. -+ */ -+static inline unsigned int ak4182_ts_read_pressure(void) -+{ -+ unsigned int z1,z2,xpos,pressureval=0;//300 Om -+ //Z1 pressure -+ z1 = ak4182_adc_read(0xB0, adcsync);//0xB0 for 12bit,0xB8 for 8bit -+ if(z1>0) -+ { -+ //Z2 pressure -+ z2 = ak4182_adc_read(0xC0, adcsync);//0xC0 for 12bit,0xC8 for 8bit -+ if(z2>z1) -+ { -+ xpos = ak4182_ts_read_xpos(); -+ pressureval = (300*xpos*(z2-z1))/(4096*z1); -+ } -+ } -+ -+ return pressureval; -+} -+ -+ -+/* -+ * Switch to Y position mode and measure X plate. We switch the plate -+ * configuration in pressure mode, then switch to position mode. This -+ * gives a faster response time. Even so, we need to wait about 55us -+ * for things to stabilise. -+ */ -+static inline unsigned int ak4182_ts_read_ypos(void) -+{ -+ return ak4182_adc_read(0x90, adcsync);//Y-axis,0x90 for 12bit,0x98 for 8bit -+} -+ -+/*------------------------------------------------------------ -+ * Read the battery voltage -+ */ -+ -+unsigned int ak4182_read_battery(void) -+{ -+ unsigned int v; -+ int bat_val[5]; -+ int total = 0, max_bat, min_bat; -+ -+ v = ak4182_adc_read(0xA7, adcsync); -+ v = ak4182_adc_read(0xA7, adcsync); -+ for(v = 0;v <= 4;v++) -+ bat_val[v] = ak4182_adc_read(0xA7, adcsync); -+ -+ ak4182_adc_read(0xA4, adcsync); -+ max_bat = min_bat = bat_val[0]; -+ for(v = 0;v <= 4;v++) { -+ total += bat_val[v]; -+ if(bat_val[v] > max_bat) -+ max_bat = bat_val[v]; -+ if(bat_val[v] < min_bat) -+ min_bat = bat_val[v]; -+ } -+ total = total - max_bat - min_bat; -+ v = total / 3; -+ return v; -+} -+ -+/*------------------ Calibrate samples -------------------*/ -+ -+#define DIFF(a,b) ((a>b)?(a-b):(b-a)) -+ -+static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -+{ -+ unsigned long *xp = (unsigned long *)xbuf; -+ unsigned long *yp = (unsigned long *)ybuf; -+ unsigned long *pp = (unsigned long *)pbuf; -+ unsigned long x_cal = 0, y_cal = 0, p_cal = 0, tmp; -+ int ignored, i, j; -+ int valid = 0; -+ -+ /* throw away the max cases */ -+ tmp = xp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (xp[i] > tmp) { -+ tmp = xp[i]; -+ ignored = i; -+ } -+ }//find the max val -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ xp[j++] = xp[i]; -+ }//shift val and delete the max val -+ -+ tmp = yp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (yp[i] > tmp) { -+ tmp = yp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ yp[j++] = yp[i]; -+ } -+ -+ tmp = pp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (pp[i] > tmp) { -+ tmp = pp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ pp[j++] = pp[i]; -+ } -+ -+ /* throw away the min cases */ -+ -+ count -= 1; // decrement by 1 -+ -+ tmp = xp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (xp[i] < tmp) { -+ tmp = xp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ xp[j++] = xp[i]; -+ } -+ -+ tmp = yp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (yp[i] < tmp) { -+ tmp = yp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ yp[j++] = yp[i]; -+ } -+ -+ tmp = pp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (pp[i] < tmp) { -+ tmp = pp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ pp[j++] = pp[i]; -+ } -+ -+ count -= 1; // decrement by 1 -+ -+ /* calculate the average of the rest */ -+ for (i = 0; i < count; i++) { -+ x_cal += xp[i]; -+ y_cal += yp[i]; -+ p_cal += pp[i]; -+ } -+ x_cal /= count; -+ y_cal /= count; -+ p_cal /= count; -+ -+ if (first_time) { -+ first_time = 0; -+ last_x = x_cal; -+ last_y = y_cal; -+ last_p = p_cal; -+ valid = 1; -+ } -+ else { -+ if ((DIFF(x_cal, last_x) > 100) || -+ (DIFF(y_cal, last_y) > 100)) -+ valid = 0; -+ else -+ valid = 1; -+ } -+ -+ //printk("x_cal=%d y_cal=%d p_cal=%d valid=%d\n", x_cal, y_cal, p_cal, valid); -+ -+ if (valid) { -+ *xp = last_x = x_cal; -+ *yp = last_y = y_cal; -+ *pp = last_p = p_cal; -+ } -+ -+ return valid; -+} -+ -+ -+#define TSMAXX 945 -+#define TSMAXY 830 -+#define TSMINX 90 -+#define TSMINY 105 -+ -+#define SCREEN_X 480 -+#define SCREEN_Y 272 -+ -+static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -+{ -+ -+ if (ts->minx) -+ { -+ if (x < ts->minx) x = ts->minx; -+ if (x > ts->maxx) x = ts->maxx; -+ -+ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -+ } -+ else -+ { -+ if (x < TSMINX) x = TSMINX; -+ if (x > TSMAXX) x = TSMAXX; -+ -+ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -+ } -+} -+ -+static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -+{ -+ if (ts->miny) -+ { -+ if (y < ts->miny) y = ts->miny; -+ if (y > ts->maxy) y = ts->maxy; -+ -+ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -+ } -+ else -+ { -+ if (y < TSMINY) y = TSMINY; -+ if (y > TSMAXY) y = TSMAXY; -+ -+ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -+ } -+} -+ -+/*------------------ Common routines -------------------*/ -+ -+void ts_enable_irq(void) -+{ -+ /* interrupt mode */ -+ ak4182_enable_irq(); -+ enable_irq(TS_IRQ); -+} -+ -+void ts_disable_irq(void) -+{ -+ ak4182_disable_irq(); -+ disable_irq(TS_IRQ); -+} -+ -+int ts_request_irq(u32 *irq, -+ irqreturn_t (*handler)(int, void *), -+ const char *devname, -+ void *dev_id) -+{ -+ int retval; -+ -+ /* return the irq number */ -+ *irq = TS_IRQ; -+ /* initializate ssi for AK4182 */ -+ ak4182_ssi_reset(); -+ ak4182_ssi_set_trans_mode_format(); -+ ak4182_ssi_set_normal_mode(); -+ ak4182_ssi_set_clk_div_ratio(JZ_EXTAL, 200*1000);//DCLK is 1.5M Hz max -+ ak4182_ssi_set_IRQ(); -+ -+ ak4182_enable_irq(); -+ -+ /* enable gpio irq */ -+ __gpio_as_irq_fall_edge(TS_PIN); -+ -+ /* register irq handler */ -+ retval = request_irq(TS_IRQ, handler, IRQF_DISABLED, devname, dev_id); -+ ak4182_ssi_enable(); -+ udelay(10); -+ return retval; -+} -+ -+void ts_free_irq(struct jz_ts_t *ts) -+{ -+ free_irq(ts->pendown_irq, ts); -+ //Close SSI mode -+ ak4182_ssi_reset(); -+} -+ -+void ts_irq_callback(void) -+{ -+ /* clear interrupt status */ -+ __gpio_ack_irq(TS_PIN); -+ first_time = 1; // first time to acquire sample -+} -+ -+int PenIsDown(void) -+{ -+ unsigned int p; -+ p = ak4182_ts_read_pressure(); -+ return (p > 100) ? 1 : 0; -+} -+ -+/* -+ * Acquire Raw pen coodinate data and compute touch screen -+ * pressure resistance. Hold spinlock when calling. -+ */ -+int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -+{ -+ unsigned int x_raw[8], y_raw[8], p_raw[8]; -+ int valid, i; -+ -+ for (i = 0; i < samples; i++) { -+ x_raw[i] = ak4182_ts_read_xpos(); -+ } -+ for (i = 0; i < samples; i++) { -+ y_raw[i] = ak4182_ts_read_ypos(); -+ } -+ for (i = 0; i < samples; i++) { -+ p_raw[i] = ak4182_ts_read_pressure(); -+ } -+ -+ valid = calibrate_samples(x_raw, y_raw, p_raw, samples); -+ -+ if (valid) { -+ unsigned int x_scr, y_scr; -+ -+ if(ts->filter) { -+ x_scr = transform_to_screen_x(ts, x_raw[0]); -+ y_scr = transform_to_screen_y(ts, y_raw[0]); -+ -+ if (ts->prints) -+ printk("filter:x_raw:%d,y_raw:%d,x_tran:%d,y_tran:%d\n", x_raw[0], y_raw[0], x_scr, y_scr); -+ } -+ else { -+ x_scr = x_raw[0]; -+ y_scr = y_raw[0]; -+ -+ if (ts->prints) -+ printk("no filter:x_raw=%d y_raw=%d \n", x_raw[0], y_raw[0]); -+ } -+ -+ event->x = x_scr; -+ event->y = y_scr; -+ event->pressure = (u16)p_raw[0]; -+ event->status = PENDOWN; -+ return 1; -+ } -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+ -+/* -+ * Suspend the Touch pad. -+ */ -+static int ak4182_suspend(struct ak4182 *ak , int state) -+{ -+ ak4182_ssi_disable(); -+ -+ return 0; -+} -+ -+/* -+ * Resume the Touch panel. -+ */ -+static int ak4182_resume(struct ak4182 *ak) -+{ -+ /* initializate ssi for AK4182 */ -+ ak4182_ssi_reset(); -+ ak4182_ssi_set_trans_mode_format(); -+ ak4182_ssi_set_normal_mode(); -+ ak4182_ssi_set_clk_div_ratio(JZ_EXTAL, 200*1000);//DCLK is 1.5M Hz max -+ ak4182_ssi_set_IRQ(); -+ -+ ak4182_enable_irq(); -+ -+ ak4182_ssi_enable(); -+ -+ return 0; -+} -+ -+static int ak4182_pm_callback(struct pm_dev *pm_dev, pm_request_t rqst, void *data) -+{ -+ int ret; -+ struct ak4182 *akinfo = pm_dev->data; -+ -+ if (!akinfo) -+ return -EINVAL; -+ -+ -+ switch (rqst) { -+ case PM_SUSPEND: -+ ret = ak4182_suspend(akinfo, (int)data); -+ break; -+ -+ case PM_RESUME: -+ ret = ak4182_resume(akinfo); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+#endif /* CONFIG_PM */ -+ -+ -+/* -+ * Module init and exit -+ */ -+ -+int __init ak4182_init(void) -+{ -+ ak = kmalloc(sizeof(struct ak4182), GFP_KERNEL); -+ if (!ak) return -ENOMEM; -+ -+ memset(ak, 0, sizeof(struct ak4182)); -+ -+ codec_read_battery = ak4182_read_battery; -+ -+ spin_lock_init(&ak->lock); -+ sema_init(&ak->adc_sem, 1); -+ -+ //initialize AK4182 register -+ __gpio_clear_pin(73); -+ __gpio_as_output(73); -+ mdelay(2); -+ __gpio_set_pin(73); -+ __gpio_as_ssi(); -+ -+ ak4182_read_battery(); -+ -+#ifdef CONFIG_PM -+ ak->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ak4182_pm_callback); -+ if (ak->pmdev) -+ { -+ ak->pmdev->data = ak; -+ } -+#endif -+ -+ printk("AK4182 touch screen driver initialized\n"); -+ -+ return 0; -+} -+ -+void ak4182_cleanup(void) -+{ -+} -+ -+module_init(ak4182_init); -+module_exit(ak4182_cleanup); -+ -diff --git a/drivers/char/jzchar/ak4182.h b/drivers/char/jzchar/ak4182.h -new file mode 100644 -index 0000000..e8b1bf8 ---- /dev/null -+++ b/drivers/char/jzchar/ak4182.h -@@ -0,0 +1,16 @@ -+#ifndef __AK4182_H__ -+#define __AK4182_H__ -+ -+/* Device data structure */ -+ -+struct ak4182 { -+ spinlock_t lock; -+ struct pm_dev *pmdev; -+ struct semaphore adc_sem; -+ u16 adc_cr; -+ u16 irq_fal_enbl; -+ u16 irq_ris_enbl; -+ int irq_enabled; -+}; -+ -+#endif /* __AK4182_H__ */ -diff --git a/drivers/char/jzchar/ata2508.c b/drivers/char/jzchar/ata2508.c -new file mode 100644 -index 0000000..41a4ff4 ---- /dev/null -+++ b/drivers/char/jzchar/ata2508.c -@@ -0,0 +1,227 @@ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define MP4_KEY_RST (32*3+3) -+#define MP4_KEY_TINT (32*3+2) -+#define MP4_KEY_SCL (32*3+1) -+#define MP4_KEY_SDA (32*3+0) -+#define MP4_TINT_IRQ (IRQ_GPIO_0 + MP4_KEY_TINT) -+ -+#define ADDR_WARM_RESET 0xFF -+#define ATA2508_SENSOR_MASK 0x1F -+ -+const unsigned char init_data_burst[] = {//Address:0x0D-0x3E -+ 0x04, // BETA -+ 0x27, // AIC_WAIT -+ //0x32, // REF_DELAY -+ 0x16, // REF_DELAY -+ 0x02, // HYSTERESIS01 -+ 0x02, // HYSTERESIS1 -+ 0x02, // HYSTERESIS2 -+ 0x02, // HYSTERESIS3 -+ 0x02, // HYSTERESIS4 -+ 0x02, // HYSTERESIS51 -+ 0x02, // HYSTERESIS61 -+ 0x02, // HYSTERESIS7 -+ 0x02, // HYSTERESIS8 -+ 0x02, // HYSTERESIS9 -+ 0x02, // HYSTERESIS10 -+ 0x02, // HYSTERESIS11 -+ 0x64, // STRENGTH_THRESHOLD0 -+ 0x64, // STRENGTH_THRESHOLD1 -+ 0x64, // STRENGTH_THRESHOLD2 -+ 0x64, // STRENGTH_THRESHOLD3 -+ 0x64, // STRENGTH_THRESHOLD4 -+ 0x64, // STRENGTH_THRESHOLD5 -+ 0x64, // STRENGTH_THRESHOLD6 -+ 0x64, // STRENGTH_THRESHOLD7 -+ 0x64, // STRENGTH_THRESHOLD8 -+ 0x64, // STRENGTH_THRESHOLD9 -+ 0x64, // STRENGTH_THRESHOLD10 -+ 0x64, // STRENGTH_THRESHOLD11 -+ 0x0f, // Sampling Interval -+ 0xC8, // INTEGRATION TIME -+ 0x0f, // IDLE TIME -+ 0x00, // SIF_SETUP(RESERVED) -+ 0x01, // MODE -+ 0x00, // GPIO_REG_L -+ 0x00, // GPIO_REG_H -+ 0x00, // GPIO_CONFIGURATION_L -+ 0x00, // GPIO_CONFIGURATION_H -+ 0x00, // GPIO_DIR_L -+ 0x00, // GPIO_DIR_H -+ 0x0c, // CONTROL -+ 0x38, // INT_MASK -+ 0x00, // INT_CLEAR -+ 0xFF, // INT_edge -+ 0x02, // CONTROL_2 -+ 0xAF, // BEEP_TIME -+ 0x7F, // BEEP_FREQUENCY -+ 0x30, // CALIBRATION INTERVAL -+ 0x00, // EINT_ENABLE -+ 0x00, // EINT_POL -+ 0x00, // FILTER_PERIOD -+ 0x00, // FILTER_THRESHOLD -+}; -+const unsigned char init_data_alpha[] = {//Address:0x00-0x0C -+ 0x02, // APIS -+ 0x08, // ALPHA0 -+ 0x08, // ALPHA1 -+ 0x08, // ALPHA2 -+ 0x08, // ALPHA3 -+ 0x08, // ALPHA4 -+ 0x28, // ALPHA5 -+ 0x28, // ALPHA6 -+ 0x28, // ALPHA7 -+ 0x28, // ALPHA8 -+ 0x28, // ALPHA9 -+ 0x28, // ALPHA10 -+ 0x28, // ALPHA11 -+}; -+static unsigned int i2c_addr = 0x58; -+static unsigned int i2c_clk = 100000; -+ -+static void write_reg(u8 reg, u8 val) -+{ -+ int ret; -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ ret = i2c_write(i2c_addr, &val, reg, 1); -+ i2c_close(); -+} -+ -+static u8 read_reg(u8 reg) -+{ -+ u8 val; -+ -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_read(i2c_addr, &val, reg, 1); -+ i2c_close(); -+ return val; -+} -+ -+/* -+ * Interrupt handler -+ */ -+static irqreturn_t mp4_tint_irq(int irq, void *dev_id) -+{ -+ int key_num = 0; -+ u8 value0, value1; -+ -+ __gpio_ack_irq(MP4_KEY_TINT); -+ value0 = read_reg(0x75); -+ value1 = read_reg(0x76); -+ value0 &= ATA2508_SENSOR_MASK; -+ if (value0 == 0) { -+ printk("\nRelease key!\n"); -+ return IRQ_HANDLED; -+ } -+ while(value0 >> 1){ -+ value0 >>= 1; -+ key_num++; -+ } -+ -+ printk("\nPress key %d!\n", key_num); -+ return IRQ_HANDLED; -+} -+ -+static int __init init_ata2508(void) -+{ -+ int i; -+ unsigned char data1; -+ int retval; -+ -+ __gpio_as_output(MP4_KEY_RST); -+ __gpio_set_pin(MP4_KEY_RST); -+ mdelay(100); -+ __gpio_clear_pin(MP4_KEY_RST); -+ mdelay(800); -+ __gpio_set_pin(MP4_KEY_RST); -+ __gpio_mask_irq(MP4_KEY_TINT); -+ -+ /*write registers*/ -+ for(i=0; i<13; i++) -+ { -+ data1 = init_data_alpha[i]; -+ write_reg(i, data1); -+ } -+ -+ for(i=13; i<63; i++) -+ { -+ data1 = init_data_burst[i-13]; -+ write_reg(i, data1); -+ } -+#if 0 -+ for (i = 0; i < 63; i++) -+ { -+ data1 = read_reg(i); -+ printk("REG0x%02x = 0x%02x\n", i, data1); -+ } -+#endif -+ -+ /* wait for 1 ms*/ -+ mdelay(1); -+#if 0 -+ while(1) -+ { -+ data1 = read_reg(0x68); -+ printk("REG0x68 = %d\n", data1); -+ data1 = read_reg(0x75); -+ printk("REG0x75 = 0x%02x\n", data1); -+ data1 = read_reg(0x76); -+ printk("REG0x76 = 0x%02x\n", data1); -+ mdelay(2000); -+ } -+#endif -+ data1 = read_reg(0x68); -+ printk("REG0x68 = %d\n", data1); -+ -+ /* to activate all the new settings, give a WARM RESET.*/ -+ write_reg(ADDR_WARM_RESET, 0x00); //ADDR_WARM_RESET=0xFF -+ -+ //printk("REG0x68 = %d\n", data1); -+ -+ /* wait for 1 ~ 10 ms.*/ -+ mdelay(10); -+ data1 = read_reg(0x68); -+ -+ /* Enable INT that connected to ATA2508's TINT.*/ -+ __gpio_as_irq_rise_edge(MP4_KEY_TINT); -+ -+ retval = request_irq(MP4_TINT_IRQ, mp4_tint_irq, -+ IRQF_DISABLED, "mp4_key_tint", NULL); -+ if (retval) { -+ printk("Could not get mp4 key irq %d\n", MP4_TINT_IRQ); -+ return retval; -+ } -+ -+ printk("MP4 touch panel register!\n"); -+ -+ return 0; -+} -+ -+static void __exit exit_ata2508(void) -+{ -+ free_irq(MP4_TINT_IRQ, NULL); -+} -+ -+module_init(init_ata2508); -+module_exit(exit_ata2508); -diff --git a/drivers/char/jzchar/cim.c b/drivers/char/jzchar/cim.c -new file mode 100644 -index 0000000..c320d67 ---- /dev/null -+++ b/drivers/char/jzchar/cim.c -@@ -0,0 +1,366 @@ -+/* -+ * linux/drivers/char/jzchar/cim.c -+ * -+ * Camera Interface Module (CIM) driver for JzSOC -+ * This driver is independent of the camera sensor -+ * -+ * Copyright (C) 2005 JunZheng semiconductor -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "jzchars.h" -+ -+#define CIM_NAME "cim" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("JzSOC Camera Interface Module driver"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Define the Max Image Size -+ */ -+#define MAX_IMAGE_WIDTH 640 -+#define MAX_IMAGE_HEIGHT 480 -+#define MAX_IMAGE_BPP 16 -+#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP / 8) -+ -+typedef struct -+{ -+ u32 width; -+ u32 height; -+ u32 bpp; -+} img_param_t; -+ -+typedef struct -+{ -+ u32 cfg; -+ u32 ctrl; -+ u32 mclk; -+} cim_config_t; -+ -+/* -+ * IOCTL_XXX commands -+ */ -+#define IOCTL_SET_IMG_PARAM 0 // arg type: img_param_t * -+#define IOCTL_CIM_CONFIG 1 // arg type: cim_config_t * -+ -+/* Actual image size, must less than max values */ -+static int img_width = MAX_IMAGE_WIDTH, img_height = MAX_IMAGE_HEIGHT, img_bpp = MAX_IMAGE_BPP; -+ -+/* -+ * CIM DMA descriptor -+ */ -+struct cim_desc { -+ u32 nextdesc; /* Physical address of next desc */ -+ u32 framebuf; /* Physical address of frame buffer */ -+ u32 frameid; /* Frame ID */ -+ u32 dmacmd; /* DMA command */ -+}; -+ -+/* -+ * CIM device structure -+ */ -+struct cim_device { -+ unsigned char *framebuf; -+ unsigned int frame_size; -+ unsigned int page_order; -+ wait_queue_head_t wait_queue; -+ struct cim_desc frame_desc __attribute__ ((aligned (16))); -+}; -+ -+// global -+static struct cim_device *cim_dev; -+ -+/*========================================================================== -+ * CIM init routines -+ *========================================================================*/ -+ -+static void cim_config(cim_config_t *c) -+{ -+ REG_CIM_CFG = c->cfg; -+ REG_CIM_CTRL = c->ctrl; -+ // Set the master clock output -+#if defined(CONFIG_SOC_JZ4730) -+ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -+#elif defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#else -+ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -+#endif -+ // Enable sof, eof and stop interrupts -+ __cim_enable_sof_intr(); -+ __cim_enable_eof_intr(); -+ __cim_enable_stop_intr(); -+} -+ -+/*========================================================================== -+ * CIM start/stop operations -+ *========================================================================*/ -+ -+static int cim_start_dma(char *ubuf) -+{ -+ __cim_disable(); -+ -+ dma_cache_wback((unsigned long)cim_dev->framebuf, (2 ^ (cim_dev->page_order)) * 4096); -+ -+ // set the desc addr -+ __cim_set_da(virt_to_phys(&(cim_dev->frame_desc))); -+ -+ __cim_clear_state(); // clear state register -+ __cim_reset_rxfifo(); // resetting rxfifo -+ __cim_unreset_rxfifo(); -+ __cim_enable_dma(); // enable dma -+ -+ // start -+ __cim_enable(); -+ -+ // wait for interrupts -+ interruptible_sleep_on(&cim_dev->wait_queue); -+ -+ // copy frame data to user buffer -+ memcpy(ubuf, cim_dev->framebuf, cim_dev->frame_size); -+ -+ return cim_dev->frame_size; -+} -+ -+static void cim_stop(void) -+{ -+ __cim_disable(); -+ __cim_clear_state(); -+} -+ -+/*========================================================================== -+ * Framebuffer allocation and destroy -+ *========================================================================*/ -+ -+static void cim_fb_destroy(void) -+{ -+ if (cim_dev->framebuf) { -+ free_pages((unsigned long)(cim_dev->framebuf), cim_dev->page_order); -+ cim_dev->framebuf = NULL; -+ } -+} -+ -+static int cim_fb_alloc(void) -+{ -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+ cim_dev->page_order = get_order(cim_dev->frame_size); -+ -+ /* frame buffer */ -+ cim_dev->framebuf = (unsigned char *)__get_free_pages(GFP_KERNEL, cim_dev->page_order); -+ if ( !(cim_dev->framebuf) ) { -+ return -ENOMEM; -+ } -+ -+ cim_dev->frame_desc.nextdesc = virt_to_phys(&(cim_dev->frame_desc)); -+ cim_dev->frame_desc.framebuf = virt_to_phys(cim_dev->framebuf); -+ cim_dev->frame_desc.frameid = 0x52052018; -+ cim_dev->frame_desc.dmacmd = CIM_CMD_EOFINT | CIM_CMD_STOP | (cim_dev->frame_size >> 2); // stop after capturing a frame -+ -+ dma_cache_wback((unsigned long)(&(cim_dev->frame_desc)), 16); -+ -+ return 0; -+} -+ -+/*========================================================================== -+ * File operations -+ *========================================================================*/ -+ -+static int cim_open(struct inode *inode, struct file *filp); -+static int cim_release(struct inode *inode, struct file *filp); -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations cim_fops = -+{ -+ open: cim_open, -+ release: cim_release, -+ read: cim_read, -+ write: cim_write, -+ ioctl: cim_ioctl -+}; -+ -+static int cim_open(struct inode *inode, struct file *filp) -+{ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int cim_release(struct inode *inode, struct file *filp) -+{ -+ cim_stop(); -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ if (size < cim_dev->frame_size) -+ return -EINVAL; -+ -+ return cim_start_dma(buf); -+} -+ -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("cim error: write is not implemented\n"); -+ return -1; -+} -+ -+static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ switch (cmd) { -+ case IOCTL_SET_IMG_PARAM: -+ { -+ img_param_t i; -+ -+ if (copy_from_user((void *)&i, (void *)arg, sizeof(img_param_t))) -+ return -EFAULT; -+ -+ img_width = i.width; -+ img_height = i.height; -+ img_bpp = i.bpp; -+ -+ if ((img_width * img_height * img_bpp/8) > MAX_FRAME_SIZE) { -+ /* realloc the buffer */ -+ cim_fb_destroy(); -+ if (cim_fb_alloc() < 0) -+ return -ENOMEM; -+ } -+ -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+ -+ cim_dev->frame_desc.dmacmd = CIM_CMD_EOFINT | CIM_CMD_STOP | (cim_dev->frame_size >> 2); // stop after capturing a frame -+ -+ dma_cache_wback((unsigned long)(&(cim_dev->frame_desc)), 16); -+ -+ break; -+ } -+ case IOCTL_CIM_CONFIG: -+ { -+ cim_config_t c; -+ -+ if (copy_from_user((void *)&c, (void *)arg, sizeof(cim_config_t))) -+ return -EFAULT; -+ -+ cim_config(&c); -+ -+ break; -+ } -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return 0; -+} -+ -+/*========================================================================== -+ * Interrupt handler -+ *========================================================================*/ -+ -+static irqreturn_t cim_irq_handler(int irq, void *dev_id) -+{ -+ u32 state = REG_CIM_STATE; -+#if 0 -+ if (state & CIM_STATE_DMA_EOF) { -+ wake_up_interruptible(&cim_dev->wait_queue); -+ } -+#endif -+ if (state & CIM_STATE_DMA_STOP) { -+ // Got a frame, wake up wait routine -+ wake_up_interruptible(&cim_dev->wait_queue); -+ } -+ -+ // clear status flags -+ REG_CIM_STATE = 0; -+ return IRQ_HANDLED; -+} -+ -+/*========================================================================== -+ * Module init and exit -+ *========================================================================*/ -+ -+static int __init cim_init(void) -+{ -+ struct cim_device *dev; -+ int ret; -+ -+ /* allocate device */ -+ dev = kmalloc(sizeof(struct cim_device), GFP_KERNEL); -+ if (!dev) return -ENOMEM; -+ -+ /* record device */ -+ cim_dev = dev; -+ -+ /* allocate a frame buffer */ -+ if (cim_fb_alloc() < 0) { -+ kfree(dev); -+ return -ENOMEM; -+ } -+ -+ init_waitqueue_head(&dev->wait_queue); -+ -+ ret = jz_register_chrdev(CIM_MINOR, CIM_NAME, &cim_fops, dev); -+ if (ret < 0) { -+ cim_fb_destroy(); -+ kfree(dev); -+ return ret; -+ } -+ -+ if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, -+ CIM_NAME, dev))) { -+ cim_fb_destroy(); -+ kfree(dev); -+ printk(KERN_ERR "CIM could not get IRQ"); -+ return ret; -+ } -+ -+ printk("JzSOC Camera Interface Module (CIM) driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit cim_exit(void) -+{ -+ free_irq(IRQ_CIM, cim_dev); -+ jz_unregister_chrdev(CIM_MINOR, CIM_NAME); -+ cim_fb_destroy(); -+ kfree(cim_dev); -+} -+ -+module_init(cim_init); -+module_exit(cim_exit); -diff --git a/drivers/char/jzchar/cim.h b/drivers/char/jzchar/cim.h -new file mode 100644 -index 0000000..c21431b ---- /dev/null -+++ b/drivers/char/jzchar/cim.h -@@ -0,0 +1,36 @@ -+/* -+ * JzSOC CIM driver -+ * -+ * Copyright (C) 2005 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef __CIM_H__ -+#define __CIM_H__ -+ -+typedef struct -+{ -+ u32 width; -+ u32 height; -+ u32 bpp; -+} IMG_PARAM; -+ -+/* -+ * IOCTL_XXX commands -+ */ -+#define IOCTL_SET_IMG_PARAM 0 // arg type: IMG_PARAM * -+ -+#endif /* __CIM_H__ */ -diff --git a/drivers/char/jzchar/jz_ow.c b/drivers/char/jzchar/jz_ow.c -new file mode 100644 -index 0000000..86b3c00 ---- /dev/null -+++ b/drivers/char/jzchar/jz_ow.c -@@ -0,0 +1,497 @@ -+/* -+ * linux/drivers/char/jzchar/jz_ow.c -+ * -+ * One Wire Bus test driver -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "jzchars.h" -+ -+#define OW_CPU_READ_ROM 1 -+#define OW_INTC_READ_ROM 1 -+#define OW_CPU_SEARCH_ROM 0 -+#define OW_INTC_SEARCH_ROM 0 -+ -+#define OW_DEBUG 0 -+#if OW_DEBUG -+#define OWI_MAX 10 -+static char CFG[OWI_MAX]; -+static char CTL[OWI_MAX]; -+static char STS[OWI_MAX]; -+static char DAT[OWI_MAX]; -+static char DIV[OWI_MAX]; -+static void owi_register_dump(int i) -+{ -+ CFG[i]= REG_OWI_CFG; -+ CTL[i]= REG_OWI_CTL; -+ STS[i]= REG_OWI_STS; -+ DAT[i]= REG_OWI_DAT; -+ DIV[i]= REG_OWI_DIV; -+} -+static void owi_register_print(int i) -+{ -+ printk(" REG_OWI_CFG: 0x%08x\n", CFG[i]); -+ printk(" REG_OWI_CTL: 0x%08x\n", CTL[i]); -+ printk(" REG_OWI_STS: 0x%08x\n", STS[i]); -+ printk(" REG_OWI_DAT: 0x%08x\n", DAT[i]); -+ printk(" REG_OWI_DIV: 0x%08x\n", DIV[i]); -+} -+#endif -+ -+static DECLARE_WAIT_QUEUE_HEAD (ow_wait_queue); -+ -+/* -+ * fops routines -+ */ -+static int ow_open(struct inode *inode, struct file *filp); -+static int ow_release(struct inode *inode, struct file *filp); -+static ssize_t ow_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t ow_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int ow_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -+ -+static void do_ow_rddata(void); -+static void do_ow_wrdata(void); -+static void do_ow_wr1rd(void); -+static void do_ow_wr0(void); -+static void do_ow_rst(void); -+ -+static void do_interrupt_mode_test(void); -+static void do_cpu_mode_test(void); -+ -+static struct file_operations ow_fops = -+{ -+ open: ow_open, -+ release: ow_release, -+ read: ow_read, -+ write: ow_write, -+ ioctl: ow_ioctl, -+}; -+ -+static int ow_open(struct inode *inode, struct file *filp) -+{ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int ow_release(struct inode *inode, struct file *filp) -+{ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t ow_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ printk("OW: read is not implemented\n"); -+ return -1; -+} -+ -+static ssize_t ow_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("ow: write is not implemented\n"); -+ return -1; -+} -+ -+static int ow_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ int ret = 0; -+ switch (cmd) { -+ -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static void do_ow_rddata(void) -+{ -+ __owi_clr_sts(); -+ __owi_set_rddata(); -+ __owi_enable_ow_ops(); -+} -+ -+static void do_ow_wrdata(void) -+{ -+ __owi_clr_sts(); -+ __owi_set_wrdata(); -+ __owi_enable_ow_ops(); -+} -+ -+static void do_ow_wr1rd(void) -+{ -+ __owi_clr_sts(); -+ __owi_set_wr1rd(); -+ __owi_enable_ow_ops(); -+} -+ -+static void do_ow_wr0(void) -+{ -+ __owi_clr_sts(); -+ __owi_set_wr0(); -+ __owi_enable_ow_ops(); -+} -+ -+static void do_ow_rst(void) -+{ -+ __owi_clr_sts(); -+ __owi_set_rst(); -+ __owi_enable_ow_ops(); -+} -+ -+static irqreturn_t ow_interrupt(int irq, void *dev_id) -+{ -+ __owi_clr_sts(); -+ wake_up(&ow_wait_queue); -+ -+ return IRQ_HANDLED; -+} -+ -+static void ow_intcm_read_rom(char *rom) -+{ -+ int i; -+ -+ __owi_select_regular_mode(); -+ REG_OWI_DIV = 23; -+ __owi_clr_sts(); -+ __intc_unmask_irq(IRQ_OWI); -+ __owi_enable_all_interrupts(); -+ -+ do_ow_rst(); -+ sleep_on(&ow_wait_queue); -+ -+ REG_OWI_DAT = 0x33; -+ do_ow_wrdata(); -+ sleep_on(&ow_wait_queue); -+ -+ for(i=0; i<8; i++){ -+ do_ow_rddata(); -+ sleep_on(&ow_wait_queue); -+ rom[i] = REG_OWI_DAT; -+ } -+ __intc_mask_irq(IRQ_OWI); -+} -+ -+static void ow_intcm_search_rom(void) -+{ -+ int i, j; -+ int normal, reverse; -+#if 1 -+ unsigned char rom[8]={0x01, 0xf9, 0x35, 0x53, 0x11, 0x00, 0x00, 0x3e}; -+#else -+ unsigned char rom[8]={0x01, 0xd8, 0x10, 0x02, 0x10, 0x00, 0x00, 0x22}; -+#endif -+ __owi_select_regular_mode(); -+ REG_OWI_DIV = __cpm_get_extalclk()/1000000 - 1; -+ __owi_clr_sts(); -+ __intc_unmask_irq(IRQ_OWI); -+ __owi_enable_all_interrupts(); -+ -+ /* reset */ -+ do_ow_rst(); -+ sleep_on(&ow_wait_queue); -+ -+ /* send search ROM command */ -+ REG_OWI_DAT = 0xf0; -+ do_ow_wrdata(); -+ sleep_on(&ow_wait_queue); -+ -+ for( i=0; i<8; i++){ -+ for (j=0; j<8; j++){ -+ do_ow_wr1rd(); -+ sleep_on(&ow_wait_queue); -+ normal = ( __owi_get_rdst() !=0); -+ printk("normal: %d\n",normal); -+ -+ do_ow_wr1rd(); -+ sleep_on(&ow_wait_queue); -+ reverse = ( __owi_get_rdst() !=0); -+ printk("reverse: %d\n",reverse); -+ -+ if(normal ==1 && reverse ==1){ -+ printk("Search rom INTC mode: 11 NO device found\n"); -+ __intc_mask_irq(IRQ_OWI); -+ return; -+ } -+#if 1 -+ if ( (rom[i]>>j) & 1 ){ -+ printk("write 1\n"); -+ do_ow_wr1rd(); -+ sleep_on(&ow_wait_queue); -+ } -+ else{ -+ printk("write 0\n"); -+ do_ow_wr0(); -+ sleep_on(&ow_wait_queue); -+ } -+ -+#else -+ if(normal ==0 && reverse ==0){ -+ if (!((rom[i]>>j) & 1) ){ -+ printk("write 1\n"); -+ do_ow_wr1rd(); -+ sleep_on(&ow_wait_queue); -+ } -+ else{ -+ printk("write 0\n"); -+ do_ow_wr0(); -+ sleep_on(&ow_wait_queue); -+ } -+ }else{ -+ -+ if(normal ==0){ -+ printk("write 0\n"); -+ do_ow_wr0(); -+ sleep_on(&ow_wait_queue); -+ } -+ if(normal ==1){ -+ printk("write 1\n"); -+ do_ow_wr1rd(); -+ sleep_on(&ow_wait_queue); -+ } -+ } -+#endif -+ -+ } -+ printk("\n\n"); -+ } -+ -+ printk("\nSearch rom INTC mode: device found SUCCESSFULLY\n"); -+ __intc_mask_irq(IRQ_OWI); -+ -+} -+ -+static void ow_cpum_read_rom(char *rom) -+{ -+ int i; -+ -+ __owi_select_regular_mode(); -+ REG_OWI_DIV = __cpm_get_extalclk()/1000000 - 1; -+ __owi_clr_sts(); -+ __owi_disable_all_interrupts(); -+ -+ do_ow_rst(); -+ __owi_wait_ops_rdy(); -+ -+ if(!__owi_get_sts_pst()) -+ printk("read rom no device found\n"); -+ -+ REG_OWI_DAT = 0x33; -+ do_ow_wrdata(); -+ __owi_wait_ops_rdy(); -+ -+ for(i=0; i<8; i++){ -+ do_ow_rddata(); -+ __owi_wait_ops_rdy(); -+ rom[i] = REG_OWI_DAT; -+ } -+} -+ -+ -+static void ow_comm_bit(unsigned comm) -+{ -+ int i; -+ for(i=0; i<8; i++){ -+ if ( comm & (1<>j) & 1 ){ -+ printk("write 1\n"); -+ do_ow_wr1rd(); -+ while(!__owi_get_sts_bit_rdy()) ; -+ } -+ else{ -+ printk("write 0\n"); -+ do_ow_wr0(); -+ while(!__owi_get_sts_bit_rdy()) ; -+ } -+ -+#else -+ if(normal ==0 && reverse ==0){ -+ if (!((rom[i]>>j) & 1) ){ -+ printk("write 1\n"); -+ do_ow_wr1rd(); -+ while(!__owi_get_sts_bit_rdy()) ; -+ } -+ else{ -+ printk("write 0\n"); -+ do_ow_wr0(); -+ while(!__owi_get_sts_bit_rdy()) ; -+ } -+ }else{ -+ -+ if(normal ==0){ -+ printk("write 0\n"); -+ do_ow_wr0(); -+ while(!__owi_get_sts_bit_rdy()) ; -+ } -+ if(normal ==1){ -+ printk("write 1\n"); -+ do_ow_wr1rd(); -+ while(!__owi_get_sts_bit_rdy()) ; -+ } -+ } -+#endif -+ -+ } -+ printk("\n\n"); -+ } -+ printk("\nSearch rom CPU mode: device found SUCCESSFULLY\n"); -+} -+ -+static void do_interrupt_mode_test(void) -+{ -+ int ret, i; -+ unsigned char rom[8]; -+ -+ /* interrupt mode */ -+ ret = request_irq(IRQ_OWI, ow_interrupt, IRQF_DISABLED, -+ "JZ_OWI", NULL); -+ if(ret) -+ printk("failed irq \n"); -+ -+#if OW_INTC_READ_ROM -+ ow_intcm_read_rom(rom); -+ printk("\n\nAfter intc mode read ROM ops: \n"); -+ printk("ROM: "); -+ for(i=0; i<8; i++) -+ printk("0x%02x,",rom[i]); -+#endif -+ -+#if OW_INTC_SEARCH_ROM -+ ow_intcm_search_rom(); -+#endif -+ -+} -+ -+static void do_cpu_mode_test(void) -+{ -+ -+#if OW_CPU_READ_ROM -+ int i; -+ unsigned char rom[8]; -+ -+ ow_cpum_read_rom(rom); -+ printk("\n\nAfter CPU mode read ROM ops: \n"); -+ printk("ROM: "); -+ for(i=0; i<8; i++) -+ printk("0x%02x,",rom[i]); -+#endif -+ -+#if OW_CPU_SEARCH_ROM -+ ow_cpum_search_rom(); -+#endif -+} -+ -+/* -+ * Module init and exit -+ */ -+static int __init ow_init(void) -+{ -+ int ret; -+ -+ ret = jz_register_chrdev(OW_MINOR, "ow", &ow_fops, NULL); -+ if (ret < 0) { -+ return ret; -+ } -+ __gpio_as_func1(153); -+ -+ REG_OWI_CFG=0; -+ REG_OWI_CTL=0; -+ REG_OWI_STS=0; -+ REG_OWI_DAT=0; -+ REG_OWI_DIV=0; -+ -+ do_interrupt_mode_test(); -+ do_cpu_mode_test(); -+ -+ printk("Ingenic OW driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit ow_exit(void) -+{ -+ free_irq(IRQ_OWI, NULL); -+ jz_unregister_chrdev(OW_MINOR, "ow"); -+} -+ -+module_init(ow_init); -+module_exit(ow_exit); -+ -+MODULE_AUTHOR("Yurong Tan"); -+MODULE_DESCRIPTION("One Wire Bus test Driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/char/jzchar/jz_ts.c b/drivers/char/jzchar/jz_ts.c -new file mode 100644 -index 0000000..16b46a2 ---- /dev/null -+++ b/drivers/char/jzchar/jz_ts.c -@@ -0,0 +1,443 @@ -+/* -+ * jz_ts.c -+ * -+ * Touch screen driver for the Ingenic JZ47XX. -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz_ts.h" -+ -+MODULE_AUTHOR("Peter Wei "); -+MODULE_DESCRIPTION("Ingenic Touch Screen Driver"); -+MODULE_LICENSE("GPL"); -+ -+#define TS_NAME "jz-ts" -+#define TS_MINOR 16 /* MAJOR: 10, MINOR: 16 */ -+#define PFX TS_NAME -+ -+//#define JZ_TS_DEBUG -+ -+#ifdef JZ_TS_DEBUG -+#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) do {} while (0) -+#endif -+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg) -+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg) -+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg) -+ -+static struct jz_ts_t jz_ts; -+ -+unsigned int (*codec_read_battery)(void) = NULL; -+ -+// hold the spinlock before calling. -+static void event_add(struct jz_ts_t *ts, struct ts_event *event) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ts->lock, flags); -+ -+ // add this event to the event queue -+ ts->event_buf[ts->nextIn] = *event; -+ ts->nextIn = (ts->nextIn + 1) & (EVENT_BUFSIZE - 1); -+ if (ts->event_count < EVENT_BUFSIZE) { -+ ts->event_count++; -+ } else { -+ // throw out the oldest event -+ ts->nextOut = (ts->nextOut + 1) & (EVENT_BUFSIZE - 1); -+ } -+ -+ spin_unlock_irqrestore(&ts->lock, flags); -+ -+ // async notify -+ if (ts->fasync) -+ kill_fasync(&ts->fasync, SIGIO, POLL_IN); -+ // wake up any read call -+ if (waitqueue_active(&ts->wait)) -+ wake_up_interruptible(&ts->wait); -+} -+ -+static int event_pull(struct jz_ts_t *ts, struct ts_event *event) -+{ -+ unsigned long flags; -+ int ret; -+ -+ spin_lock_irqsave(&ts->lock, flags); -+ ret = ts->event_count; -+ if (ts->event_count) { -+ *event = ts->event_buf[ts->nextOut]; -+ ts->nextOut = (ts->nextOut + 1) & (EVENT_BUFSIZE - 1); -+ ts->event_count--; -+ } -+ spin_unlock_irqrestore(&ts->lock, flags); -+ -+ return ret; -+} -+ -+static int pen_is_down = 0; -+ -+static irqreturn_t pendown_interrupt(int irq, void * dev_id) -+{ -+ struct jz_ts_t* ts = &jz_ts; -+ struct ts_event event; -+ -+ dbg("pen down"); -+#if defined(CONFIG_SOC_JZ4740) -+ if (ts->sleeping) { -+ ts->sleeping = 0; -+ ts_data_ready(); -+ return IRQ_HANDLED; -+ } -+#endif -+ spin_lock(&ts->lock); -+ -+ if (ts->irq_enabled) { -+ ts->irq_enabled = 0; -+ } -+ else -+ ts->irq_enabled = 1; -+ -+ -+ if (pen_is_down) -+ pen_is_down = 0; -+ else -+ pen_is_down = 1; -+ -+ // callback routine to clear irq status -+ ts_irq_callback(); -+ -+ if ( (pen_is_down == 0)){ -+ del_timer(&ts->acq_timer); -+ spin_unlock(&ts->lock); -+ event.x = event.y = event.pressure = 0; -+ event.status = PENUP; -+ ts->first_read = 0; -+ event_add(ts, &event); -+ return IRQ_HANDLED; -+ } -+ -+ if ( (pen_is_down == 1)) -+ { -+ ts->acq_timer.expires = jiffies + HZ / 100; -+ del_timer(&ts->acq_timer); -+ ts->first_read = 1; -+ add_timer(&ts->acq_timer); -+ spin_unlock(&ts->lock); -+ } -+ return IRQ_HANDLED; -+} -+ -+ -+/* -+ * Raw X,Y,pressure acquisition timer function. It gets scheduled -+ * only while pen is down. Its duration between calls is the polling -+ * rate. -+ */ -+static void -+jz_acq_timer(unsigned long data) -+{ -+ struct jz_ts_t *ts = (struct jz_ts_t *)data; -+ struct ts_event event; -+ int pen_was_down = ts->pen_is_down; -+ -+ spin_lock(&ts->lock); -+ -+ if (PenIsDown()) { -+ -+ ts->pen_is_down = 1; -+ -+ if (AcquireEvent(ts, &event)) // check event is valid or not? -+ event_add(ts, &event); -+ -+ // schedule next acquire -+ ts->acq_timer.expires = jiffies + HZ / 100; -+ del_timer(&ts->acq_timer); -+ add_timer(&ts->acq_timer); -+ } else { -+ -+ if (!ts->irq_enabled) { -+ ts->irq_enabled = 1; -+ } -+ ts->pen_is_down = 0; -+ if (pen_was_down) { -+ event.x = event.y = event.pressure = 0; -+ event.status = PENUP; -+ event_add(ts, &event); -+ } -+ } -+ -+ spin_unlock(&ts->lock); -+} -+ -+/* +++++++++++++ Read battery voltage routine ++++++++++++++*/ -+ -+unsigned int jz_read_battery(void) -+{ -+ unsigned int v = 0; -+ struct jz_ts_t *ts = &jz_ts; -+ -+ spin_lock(&ts->lock); -+ -+ if (codec_read_battery) -+ v = codec_read_battery(); -+ -+ spin_unlock(&ts->lock); -+ -+ return v; -+} -+ -+/* +++++++++++++ File operations ++++++++++++++*/ -+ -+static int -+jz_fasync(int fd, struct file *filp, int mode) -+{ -+ struct jz_ts_t *ts = (struct jz_ts_t *)filp->private_data; -+ return fasync_helper(fd, filp, mode, &ts->fasync); -+} -+ -+ -+static unsigned int -+jz_poll(struct file * filp, poll_table * wait) -+{ -+ struct jz_ts_t* ts = (struct jz_ts_t*)filp->private_data; -+ poll_wait(filp, &ts->wait, wait); -+ if (ts->event_count) -+ return POLLIN | POLLRDNORM; -+ return 0; -+} -+ -+static ssize_t -+jz_read(struct file * filp, char * buffer, size_t count, loff_t * ppos) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ struct jz_ts_t* ts = (struct jz_ts_t*)filp->private_data; -+ char *ptr = buffer; -+ struct ts_event event; -+ int err = 0; -+ -+ dbg("jz_read"); -+ -+ add_wait_queue(&ts->wait, &wait); -+ while (count >= sizeof(struct ts_event)) { -+ err = -ERESTARTSYS; -+ if (signal_pending(current)) -+ break; -+ -+ -+ if (event_pull(ts, &event)) { -+ err = copy_to_user(ptr, &event, -+ sizeof(struct ts_event)); -+ if (err) -+ break; -+ ptr += sizeof(struct ts_event); -+ count -= sizeof(struct ts_event); -+ } else { -+ set_current_state(TASK_INTERRUPTIBLE); -+ err = -EAGAIN; -+ if (filp->f_flags & O_NONBLOCK) -+ break; -+ schedule(); -+ } -+ } -+ -+ current->state = TASK_RUNNING; -+ remove_wait_queue(&ts->wait, &wait); -+ -+ return ptr == buffer ? err : ptr - buffer; -+} -+ -+ -+static int -+jz_open(struct inode * inode, struct file * filp) -+{ -+ struct jz_ts_t *ts; -+ int retval; -+ -+ dbg("open ts device"); -+ filp->private_data = ts = &jz_ts; -+ -+ spin_lock(&ts->lock); -+ -+ ts->pen_is_down = 0; // start with pen up -+ ts->sleeping = 0; -+ // flush event queue -+ ts->nextIn = ts->nextOut = ts->event_count = 0; -+ -+ // Init acquisition timer function -+ init_timer(&ts->acq_timer); -+ ts->acq_timer.function = jz_acq_timer; -+ ts->acq_timer.data = (unsigned long)ts; -+ -+ ts->irq_enabled = 1; -+ -+ spin_unlock(&ts->lock); -+ -+ /* Since ts interrupt can happen immediately after request_irq, -+ * we wait until we've completed init of all relevent driver -+ * state variables. Now we grab the PenDown IRQ -+ */ -+ retval = ts_request_irq(&ts->pendown_irq, pendown_interrupt, TS_NAME, ts); -+ if (retval) { -+ err("unable to get PenDown IRQ %d", ts->pendown_irq); -+ return retval; -+ } -+ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int -+jz_release(struct inode * inode, struct file * filp) -+{ -+ struct jz_ts_t* ts = (struct jz_ts_t*)filp->private_data; -+ -+ ts_free_irq(ts); -+ jz_fasync(-1, filp, 0); -+ del_timer_sync(&ts->acq_timer); -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static int jz_ioctl(struct inode *inode, struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) -+{ -+ struct txy { -+ int minx; -+ int miny; -+ int maxx; -+ int maxy; -+ }; -+ -+ struct txy ch; -+ -+ /* -+ * Switch according to the ioctl called -+ */ -+ switch (ioctl_num) -+ { -+ case IOCTL_SET_MSG: -+ jz_ts.filter=1; -+ break; -+ case IOCTL_SET_NUM: -+ if (copy_from_user((void *)&ch, (void *)ioctl_param, sizeof(ch))) -+ return -EFAULT; -+ jz_ts.minx = ch.minx; -+ jz_ts.miny = ch.miny; -+ jz_ts.maxx = ch.maxx; -+ jz_ts.maxy = ch.maxy; -+ break; -+ } -+ -+ return 0; -+} -+ -+static struct file_operations ts_fops = { -+ owner: THIS_MODULE, -+ read: jz_read, -+ poll: jz_poll, -+ fasync: jz_fasync, -+ ioctl: jz_ioctl, -+ open: jz_open, -+ release: jz_release, -+}; -+ -+/* +++++++++++++ End File operations ++++++++++++++*/ -+ -+static int __init minx_setup(char *str) -+{ -+ int i; -+ -+ if (get_option(&str,&i)) jz_ts.minx = i; -+ jz_ts.filter=i; -+ return 1; -+} -+ -+__setup("ts_minx=", minx_setup); -+ -+static int __init miny_setup(char *str) -+{ -+ int i; -+ if (get_option(&str,&i)) jz_ts.miny = i; -+ return 1; -+} -+ -+__setup("ts_miny=", miny_setup); -+ -+static int __init maxx_setup(char *str) -+{ -+ int i; -+ if (get_option(&str,&i)) jz_ts.maxx = i; -+ return 1; -+} -+ -+__setup("ts_maxx=", maxx_setup); -+ -+static int __init maxy_setup(char *str) -+{ -+ int i; -+ if (get_option(&str,&i)) jz_ts.maxy = i; -+ return 1; -+} -+ -+__setup("ts_maxy=", maxy_setup); -+ -+static int __init printraw_setup(char *str) -+{ -+ if (str) -+ jz_ts.prints = 1; -+ -+ return 0; -+} -+ -+__setup("ts_debug", printraw_setup); -+ -+ -+static struct miscdevice jz_ts_dev = { -+ minor: TS_MINOR, -+ name: TS_NAME, -+ fops: &ts_fops, -+}; -+ -+static int __init jzts_init_module(void) -+{ -+ struct jz_ts_t *ts = &jz_ts; -+ int ret; -+ -+ if ((ret = misc_register(&jz_ts_dev)) < 0) { -+ err("can't register misc device"); -+ return ret; -+ } -+ -+// memset(ts, 0, sizeof(struct jz_ts_t)); -+ init_waitqueue_head(&ts->wait); -+ spin_lock_init(&ts->lock); -+ -+ printk("Jz generic touch screen driver registered\n"); -+ -+ return 0; -+} -+ -+static void jzts_cleanup_module(void) -+{ -+ misc_deregister(&jz_ts_dev); -+} -+ -+module_init(jzts_init_module); -+module_exit(jzts_cleanup_module); -diff --git a/drivers/char/jzchar/jz_ts.h b/drivers/char/jzchar/jz_ts.h -new file mode 100644 -index 0000000..4285797 ---- /dev/null -+++ b/drivers/char/jzchar/jz_ts.h -@@ -0,0 +1,54 @@ -+#ifndef __JZ_TS_H__ -+#define __JZ_TS_H__ -+ -+/* -+ * IOCTL commands -+ */ -+#define IOCTL_SET_MSG 0 -+#define IOCTL_SET_NUM 1 -+ -+ -+/* -+ * TS Event type -+ */ -+struct ts_event { -+ u16 status; -+ u16 x; -+ u16 y; -+ u16 pressure; -+ u16 pad; -+}; -+ -+/* TS event status */ -+#define PENUP 0x00 -+#define PENDOWN 0x01 -+ -+#define EVENT_BUFSIZE 64 // must be power of two -+ -+struct jz_ts_t { -+ int pendown_irq; // IRQ of pendown interrupt -+ int pen_is_down; // 1 = pen is down, 0 = pen is up -+ int irq_enabled; -+ struct ts_event event_buf[EVENT_BUFSIZE];// The event queue -+ int nextIn, nextOut; -+ int event_count; -+ struct fasync_struct *fasync; // asynch notification -+ struct timer_list acq_timer; // Timer for triggering acquisitions -+ wait_queue_head_t wait; // read wait queue -+ spinlock_t lock; -+ int minx, miny, maxx, maxy; -+ int filter, prints; -+ int sleeping; -+ int first_read; -+}; -+ -+extern void ts_enable_irq(void); -+extern void ts_disable_irq(void); -+extern int ts_request_irq(u32 *irq,irqreturn_t (*handler)(int, void *), const char *devname, void *dev_id); -+extern void ts_free_irq(struct jz_ts_t *ts); -+extern int PenIsDown(void); -+extern int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event); -+extern void ts_irq_callback(void); -+extern void ts_data_ready(void); -+ -+#endif /* __JZ_TS_H__ */ -diff --git a/drivers/char/jzchar/jz_tssi.c b/drivers/char/jzchar/jz_tssi.c -new file mode 100644 -index 0000000..fe4978a ---- /dev/null -+++ b/drivers/char/jzchar/jz_tssi.c -@@ -0,0 +1,457 @@ -+/* -+ * jz_tssi.c -+ * -+ * MPEG2-TS interface driver for the Ingenic JZ47XX. -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "jzchars.h" -+ -+#include "jz_tssi.h" -+ -+ -+MODULE_AUTHOR("Lucifer Liu "); -+MODULE_DESCRIPTION("Ingenic MPEG2-TS interface Driver"); -+MODULE_LICENSE("GPL"); -+ -+#define TSSI_NAME "JZ MPEG2-TS SI" -+#define TSSI_MINOR 204 /* MAJOR: 10, MINOR: 16 */ -+#define TSSI_IRQ IRQ_TSSI -+#define PFX TSSI_NAME -+#define RING_BUF_NUM 100 -+ -+#define USE_DMA -+#define TRIG_PIN ( 32 * 2 + 15 ) -+#define DMA_ID_TSSI 5 -+//#define JZ_TSSI_DEBUG -+ -+#ifdef JZ_TSSISI_DEBUG -+#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) do {} while (0) -+#endif -+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg) -+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg) -+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg) -+ -+static struct jz_tssi_t jz_tssi_g; -+static struct jz_tssi_buf_ring_t jz_tssi_ring_g; -+static int tssi_dma_reinit(int dma_chan, unsigned char *dma_buf, int size); -+ -+static void print_reg( void ) -+{ -+ printk("REG_TSSI_ENA %8x \n ", REG8( TSSI_ENA )); -+ printk("REG_TSSI_CFG %8x \n ", REG16( TSSI_CFG )); -+ printk("REG_TSSI_CTRL %8x \n ", REG8( TSSI_CTRL )); -+ printk("REG_TSSI_STAT %8x \n ", REG8( TSSI_STAT )); -+ printk("REG_TSSI_FIFO %8x \n ", REG32( TSSI_FIFO )); -+ printk("REG_TSSI_PEN %8x \n ", REG32( TSSI_PEN )); -+ printk("REG_TSSI_PID0 %8x \n ", REG32( TSSI_PID0 )); -+ printk("REG_TSSI_PID1 %8x \n ", REG32( TSSI_PID1 )); -+ printk("REG_TSSI_PID2 %8x \n ", REG32( TSSI_PID2 )); -+ printk("REG_TSSI_PID3 %8x \n ", REG32( TSSI_PID3 )); -+ printk("REG_TSSI_PID4 %8x \n ", REG32( TSSI_PID4 )); -+ printk("REG_TSSI_PID5 %8x \n ", REG32( TSSI_PID5 )); -+ printk("REG_TSSI_PID6 %8x \n ", REG32( TSSI_PID6 )); -+ printk("REG_TSSI_PID7 %8x \n ", REG32( TSSI_PID7 )); -+} -+ -+void dump_dma_channel(unsigned int dmanr) -+{ -+ printk("DMA%d Registers:\n", dmanr); -+ printk(" DMACR = 0x%8x\n", REG_DMAC_DMACR(0)); -+ printk(" DSAR = 0x%8x\n", REG_DMAC_DSAR(dmanr)); -+ printk(" DTAR = 0x%8x\n", REG_DMAC_DTAR(dmanr)); -+ printk(" DTCR = 0x%8x\n", REG_DMAC_DTCR(dmanr)); -+ printk(" DRSR = 0x%8x\n", REG_DMAC_DRSR(dmanr)); -+ printk(" DCCSR = 0x%8x\n", REG_DMAC_DCCSR(dmanr)); -+ printk(" DCMD = 0x%8x\n", REG_DMAC_DCMD(dmanr)); -+ printk(" DDA = 0x%8x\n", REG_DMAC_DDA(dmanr)); -+ printk(" DMADBR = 0x%8x\n", REG_DMAC_DMADBR(1)); -+} -+ -+static int tssi_buf_init( struct jz_tssi_buf_ring_t * ring ) -+{ -+ int i; -+ struct jz_tssi_buf * bp,* ap, *cp; -+ -+ ap = cp = bp = (struct jz_tssi_buf *)kmalloc( sizeof( struct jz_tssi_buf ) ,GFP_KERNEL ); //the first -+ if ( !bp ) { -+ printk("Can not malloc buffer! \n"); -+ return -1; -+ } -+ -+ for ( i = 0; i < RING_BUF_NUM; i ++ ) { -+ bp = ap; -+ bp->buf = (unsigned int *) kmalloc(MPEG2_TS_PACHAGE_SIZE / 4 * sizeof(unsigned int) ,GFP_KERNEL); -+ if ( !bp->buf ) { -+ printk("Can not malloc buffer! \n"); -+ return -1; -+ } -+ bp->index = i; -+ bp->pos = 0; -+ ap = (struct jz_tssi_buf *)kmalloc( sizeof( struct jz_tssi_buf ) ,GFP_KERNEL ); -+ if ( !ap ) { -+ printk("Can not malloc buffer! \n"); -+ return -1; -+ } -+ -+ bp->next = ap; //point to next ! -+ } -+ -+ bp->next = cp; //point loop to first! -+ ring->front = cp; -+ ring->rear = cp; -+ ring->fu_num = 0; -+ kfree(ap); -+ return 0; -+} -+ -+static void tssi_free_buf( struct jz_tssi_buf_ring_t * ring ) -+{ -+ int i; -+ struct jz_tssi_buf * ap; -+ for ( i = 0; i < RING_BUF_NUM; i ++ ) -+ { -+ ap = ring->front; -+ ring->front = ring->front->next; -+ kfree( ap ); -+ } -+} -+ -+#if 0 -+static void tssi_read_fifo(void *dev_id) -+{ -+ struct jz_tssi_t* tssi = ( struct jz_tssi_t* )dev_id; -+ struct jz_tssi_buf_ring_t * ring = tssi->cur_buf; -+ struct jz_tssi_buf *buf = ring->rear; -+ int i; -+#if 0 -+ if ( ring->fu_num > RING_BUF_NUM ) -+ { -+ printk("Ring buffer full ! %d \n",ring->fu_num); -+ return; -+ } -+#endif -+ -+ for ( i = 0; i < 8 ; i ++ ) -+ { -+ ring->front->buf[ring->front->pos++] = REG_TSSI_FIFO; -+ } -+ -+ if ( ring->front->pos >= MPEG2_TS_PACHAGE_SIZE ) -+ { -+ ring->fu_num ++; -+ ring->front = ring->front->next; -+ ring->front->pos = 0; -+ } -+} -+#endif -+ -+static void tssi_config_filting( void ) -+{ -+ __tssi_soft_reset(); -+ __gpio_as_tssi(); -+ __tssi_disable_ovrn_irq(); //use dma ,no need irq -+ __tssi_disable_trig_irq(); -+ __tssi_set_tigger_num( 8 ); //trig is 4 word! -+// __tssi_filter_enable(); -+ __tssi_clear_state(); -+ __tssi_filter_disable(); -+ __tssi_state_clear_overrun(); -+// __tssi_clear_trig_irq_flag(); -+#ifdef USE_DMA -+ __tssi_dma_enable(); -+#else -+ __tssi_dma_disable(); -+#endif -+ -+ __tssi_enable_ovrn_irq(); -+// __tssi_enable_trig_irq(); -+ -+ //set config -+// __tssi_set_bt_1(); -+ __tssi_set_wd_1(); -+ __tssi_set_data_use_data7(); -+ __tssi_set_data_pola_high(); -+// __tssi_select_serail_mode(); -+ __tssi_select_paral_mode(); -+ __tssi_select_clk_fast(); -+ __tssi_select_clk_posi_edge(); -+ __tssi_select_frm_act_high(); -+ __tssi_select_str_act_high(); -+ __tssi_select_fail_act_high(); -+// __tssi_select_fail_act_low(); -+ __tssi_disable_filte_pid0(); //we disable pid0 filter for ever! -+} -+ -+static void tssi_add_pid(int pid_num, int pid) -+{ -+ unsigned int addr ; -+ int n = pid_num / 2, hl = pid_num % 2; -+ if ( hl ) //use high pid, pid1 -+ { -+ addr = TSSI_PID0 + ( n * 4 ); -+ REG32( addr ) |= ( (pid & 0x1fff) << 16 ); //13bit -+ REG_TSSI_PEN |= ( 1 << (16 + n) ); -+ } -+ else //use low pid, pid0 -+ { -+ addr = TSSI_PID0 + ( n * 4 ); -+ REG32( addr ) |= pid & 0x1fff; //13bit -+ REG_TSSI_PEN |= ( 1 << n ); -+ } -+} -+ -+static irqreturn_t tssi_dma_irq(int irq, void * dev_id) -+{ -+ struct jz_tssi_t *tssi = (struct jz_tssi_t *)dev_id; -+ struct jz_tssi_buf_ring_t *buf = tssi->cur_buf; -+ -+ REG_DMAC_DCCSR(tssi->dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ -+ if (__dmac_channel_transmit_end_detected(tssi->dma_chan)) { -+ __dmac_channel_clear_transmit_end(tssi->dma_chan); -+ if ( buf->fu_num < RING_BUF_NUM ) -+ { -+ buf->front = buf->front->next; -+ REG_DMAC_DSAR(tssi->dma_chan) = CPHYSADDR(TSSI_FIFO); -+ REG_DMAC_DTAR(tssi->dma_chan) = CPHYSADDR((unsigned int)buf->front->buf); -+ REG_DMAC_DTCR(tssi->dma_chan) = MPEG2_TS_PACHAGE_SIZE / 32; -+ REG_DMAC_DCCSR(tssi->dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ buf->fu_num ++; -+ } -+ __tssi_clear_state(); -+ } -+ -+ if (__dmac_channel_transmit_halt_detected(tssi->dma_chan)) { -+ printk("DMA HALT\n"); -+ __dmac_channel_clear_transmit_halt(tssi->dma_chan); -+ } -+ -+ if (__dmac_channel_address_error_detected(tssi->dma_chan)) { -+ printk("DMA ADDR ERROR\n"); -+ __dmac_channel_clear_address_error(tssi->dma_chan); -+ } -+ -+ if (__dmac_channel_descriptor_invalid_detected(tssi->dma_chan)) { -+ printk("DMA DESC INVALID\n"); -+ __dmac_channel_clear_descriptor_invalid(tssi->dma_chan); -+ } -+ -+ if (__dmac_channel_count_terminated_detected(tssi->dma_chan)) { -+ printk("DMA CT\n"); -+ __dmac_channel_clear_count_terminated(tssi->dma_chan); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t tssi_interrupt(int irq, void * dev_id) -+{ -+ __intc_mask_irq(TSSI_IRQ); -+#if 1 -+ if ( REG_TSSI_STAT & TSSI_STAT_OVRN ) -+ { -+ printk("tssi over run occur! %x\n",REG8( TSSI_STAT )); -+ __tssi_clear_state(); -+ printk("clear ! %x\n",REG8( TSSI_STAT )); -+ } -+#endif -+ if ( REG_TSSI_STAT & TSSI_STAT_TRIG ) -+ { -+ printk("tssi trig irq occur! \n"); -+ tssi_read_fifo( dev_id ); -+ } -+ -+ __intc_ack_irq(TSSI_IRQ); -+ __intc_unmask_irq(TSSI_IRQ); -+ return IRQ_HANDLED; -+} -+ -+static ssize_t jz_read(struct file * filp, char * buffer, size_t count, loff_t * ppos) -+{ -+ jz_char_dev_t *adev = (jz_char_dev_t *)filp->private_data; -+ struct jz_tssi_t* tssi = (struct jz_tssi_t*)adev->private; -+ struct jz_tssi_buf_ring_t* ring = tssi->cur_buf; -+ -+ int i; -+ -+ count /= MPEG2_TS_PACHAGE_SIZE; -+ -+ if ( count > ring->fu_num ) -+ count = ring->fu_num; -+ -+ for ( i = 0; i < count; i ++ ) -+ { -+ memcpy( buffer + ( i * MPEG2_TS_PACHAGE_SIZE), -+ ring->rear->buf, MPEG2_TS_PACHAGE_SIZE ); -+ ring->rear->pos = 0; -+ ring->rear = ring->rear->next; -+ } -+ ring->fu_num -= count; -+ return count * MPEG2_TS_PACHAGE_SIZE; -+} -+ -+static int tssi_dma_reinit(int dma_chan, unsigned char *dma_buf, int size) -+{ -+ static unsigned int dma_src_phys_addr, dma_dst_phys_addr; -+ REG_DMAC_DMACKE(0) = 0xff; -+ dma_src_phys_addr = CPHYSADDR(TSSI_FIFO); -+ dma_dst_phys_addr = CPHYSADDR((unsigned int)dma_buf); -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0; -+ REG_DMAC_DCCSR(dma_chan) = 0; -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_TSSIIN; -+ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -+ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -+ REG_DMAC_DTCR(dma_chan) = size / 32; -+ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */ -+ return 0; -+} -+ -+static int jz_open(struct inode * inode, struct file * filp) -+{ -+ try_module_get(THIS_MODULE); -+ -+ __tssi_soft_reset(); -+ __intc_mask_irq(TSSI_IRQ); -+ tssi_config_filting(); -+ -+ return 0; -+} -+ -+static int jz_release(struct inode * inode, struct file * filp) -+{ -+ __intc_mask_irq(TSSI_IRQ); -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static int jz_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ jz_char_dev_t *adev = (jz_char_dev_t *)file->private_data; -+ struct jz_tssi_t* tssi = (struct jz_tssi_t*)adev->private; -+ -+ switch (cmd) -+ { -+ case IOCTL_TSSI_ENABLE : -+ __intc_ack_irq(TSSI_IRQ); -+ __intc_unmask_irq(TSSI_IRQ); -+ __tssi_enable(); -+ print_reg(); -+ -+ break; -+ case IOCTL_TSSI_DISABLE : -+ __tssi_disable(); -+ -+ break; -+ case IOCTL_TSSI_SOFTRESET : -+ __tssi_soft_reset(); -+ -+ break; -+ case IOCTL_TSSI_ENFILTER : -+ __tssi_filter_enable(); -+ break; -+ case IOCTL_TSSI_DEFILTER : -+ __tssi_filter_disable(); -+ break; -+ case IOCTL_TSSI_ADDPID : //add one pid to filter -+ if ( tssi->pid_num < 15 ) -+ { -+ tssi_add_pid(tssi->pid_num, arg); -+ tssi->pid_num ++ ; -+ } -+ break; -+ -+ case IOCTL_TSSI_FLUSHPID : //set all filting pid to false -+ REG_TSSI_PEN = 0x0; -+ REG_TSSI_PID0 = 0x0; -+ REG_TSSI_PID1 = 0x0; -+ REG_TSSI_PID2 = 0x0; -+ REG_TSSI_PID3 = 0x0; -+ REG_TSSI_PID4 = 0x0; -+ REG_TSSI_PID5 = 0x0; -+ REG_TSSI_PID6 = 0x0; -+ REG_TSSI_PID7 = 0x0; -+ break; -+ -+ case IOCTL_TSSI_INIT_DMA: -+ tssi_dma_reinit(tssi->dma_chan, tssi->cur_buf->front->buf, MPEG2_TS_PACHAGE_SIZE); -+ break; -+ case IOCTL_TSSI_DISABLE_DMA: -+ REG_DMAC_DCCSR(tssi->dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ break; -+ } -+ -+ return 0; -+} -+ -+static struct file_operations tssi_fops = { -+ owner: THIS_MODULE, -+ read: jz_read, -+ poll: NULL, -+ fasync: NULL, -+ ioctl: jz_ioctl, -+ open: jz_open, -+ release: jz_release, -+}; -+ -+static int __init jztssi_init_module(void) -+{ -+ int retval; -+ struct jz_tssi_t *tssi = &jz_tssi_g; -+ -+ __cpm_start_tssi(); -+ __cpm_start_dmac(); -+ tssi_buf_init( &jz_tssi_ring_g ); -+ tssi->cur_buf = &jz_tssi_ring_g; -+ tssi->pid_num = 0; -+ retval = request_irq(TSSI_IRQ, tssi_interrupt, IRQF_DISABLED, TSSI_NAME, &jz_tssi_g); -+ -+ if (retval) { -+ printk("unable to get IRQ %d",TSSI_IRQ); -+ return retval; -+ } -+ -+ tssi->dma_chan = jz_request_dma(DMA_ID_TSSI, "tssi", tssi_dma_irq, -+ IRQF_DISABLED, &jz_tssi_g); -+ if ( tssi->dma_chan < 0 ) -+ { -+ printk("MPEG2-TS request irq fail! \n"); -+ return -1; -+ } -+ -+ jz_register_chrdev(TSSI_MINOR, TSSI_NAME, &tssi_fops, &jz_tssi_g); -+ -+ printk("Jz MPEG2-TS interface driver registered %x %d\n",&jz_tssi_g,tssi->dma_chan); -+ return 0; -+} -+ -+static void jztssi_cleanup_module(void) -+{ -+ free_irq(TSSI_IRQ,0); -+ jz_free_dma(jz_tssi_g.dma_chan); -+ tssi_free_buf( &jz_tssi_ring_g ); -+ jz_unregister_chrdev(TSSI_MINOR, TSSI_NAME); -+} -+ -+module_init(jztssi_init_module); -+module_exit(jztssi_cleanup_module); -diff --git a/drivers/char/jzchar/jz_tssi.h b/drivers/char/jzchar/jz_tssi.h -new file mode 100644 -index 0000000..7ac424d ---- /dev/null -+++ b/drivers/char/jzchar/jz_tssi.h -@@ -0,0 +1,76 @@ -+#ifndef __JZ_TSSI_H__ -+#define __JZ_TSSI_H__ -+ -+/* -+ * IOCTL commands -+ */ -+#define IOCTL_TSSI_ENABLE 0x01 -+#define IOCTL_TSSI_DISABLE 0x02 -+#define IOCTL_TSSI_SOFTRESET 0x03 -+#define IOCTL_TSSI_ENFILTER 0x04 -+#define IOCTL_TSSI_DEFILTER 0x05 -+#define IOCTL_TSSI_ADDPID 0x06 -+#define IOCTL_TSSI_FLUSHPID 0x07 -+#define IOCTL_TSSI_INIT_DMA 0x08 -+#define IOCTL_TSSI_DISABLE_DMA 0x09 -+ -+#if 0 -+#define IOCTL_TSSI_SET_CFG 0x06 -+#define IOCTL_TSSI_GET_CFG 0x07 -+#define IOCTL_TSSI_ENIRQ_TRIG 0x08 -+#define IOCTL_TSSI_DEIRQ_TRIG 0x09 -+#define IOCTL_TSSI_ENIRQ_OVRN 0x0a -+#define IOCTL_TSSI_DEIRQ_OVRN 0x0b -+#define IOCTL_TSSI_ENPID0 0x0c -+#define IOCTL_TSSI_DEPID0 0x0d -+#define IOCTL_TSSI_ENPIDN 0x0e -+#define IOCTL_TSSI_DEPIDN 0x0f -+#define IOCTL_TSSI_SETPIDN 0x10 -+#define IOCTL_TSSI_SET_TRIG 0x11 -+#endif -+ -+#define MAX_PID_NUM 15 -+#define MPEG2_TS_PACHAGE_SIZE 19200 -+ -+struct jz_tssi_cfg_t -+{ -+ unsigned char wordorder; -+ unsigned char byteorder; -+ unsigned char dataploa; -+ unsigned char use0; -+ unsigned char clkch; -+ unsigned char mode; -+ unsigned char clkpola; -+ unsigned char frmpola; -+ unsigned char strpola; -+ unsigned char failpola; -+ unsigned char trignum; -+ -+ unsigned short pid; -+ unsigned char pid_index; //0 to 15 -+}; -+ -+struct jz_tssi_buf -+{ -+ unsigned int *buf; -+ unsigned int pos; -+ unsigned int index; -+ struct jz_tssi_buf *next; -+}; -+ -+struct jz_tssi_buf_ring_t -+{ -+ struct jz_tssi_buf *front; -+ struct jz_tssi_buf *rear; -+ unsigned int fu_num; -+}; -+ -+struct jz_tssi_t -+{ -+ struct jz_tssi_cfg_t cur_config; -+ struct jz_tssi_buf_ring_t *cur_buf; -+ struct semaphore tssi_sem; -+ int dma_chan, pid_num; -+}; -+ -+#endif /* __JZ_TSSI_H__ */ -diff --git a/drivers/char/jzchar/jzchars.c b/drivers/char/jzchar/jzchars.c -new file mode 100644 -index 0000000..1a1b944 ---- /dev/null -+++ b/drivers/char/jzchar/jzchars.c -@@ -0,0 +1,158 @@ -+/* -+ * linux/drivers/char/jzchar/jzchars.c -+ * -+ * JzSOC char device family common layer. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "jzchars.h" -+ -+LIST_HEAD(jz_char_devs); -+ -+int jz_register_chrdev(unsigned char minor, const char *name, -+ struct file_operations *fops, void *private) -+{ -+ struct list_head *p; -+ jz_char_dev_t *new; -+ list_for_each(p, &jz_char_devs) { -+ jz_char_dev_t *dev = (jz_char_dev_t *)p; -+ if (minor == dev->dev_minor) -+ return -EBUSY; -+ } -+ new = (jz_char_dev_t *)kmalloc(sizeof(jz_char_dev_t), GFP_KERNEL); -+ new->dev_minor = minor; -+ new->name = (char *)name; -+ new->fops = fops; -+ new->private = private; -+ list_add_tail((struct list_head *)new, &jz_char_devs); -+ return 0; -+} -+ -+int jz_unregister_chrdev(unsigned char minor, const char *name) -+{ -+ struct list_head *p; -+ jz_char_dev_t *dev = NULL; -+ list_for_each(p, &jz_char_devs) { -+ jz_char_dev_t *one = (jz_char_dev_t *)p; -+ if (minor == one->dev_minor) { -+ dev = one; -+ break; -+ } -+ } -+ if (dev == NULL) -+ return -EINVAL; -+ list_del((struct list_head *)dev); -+ kfree(dev); -+ return 0; -+} -+ -+static ssize_t jz_char_read(struct file *, char *, size_t, loff_t *); -+static ssize_t jz_char_write(struct file *, const char *, size_t, loff_t *); -+static int jz_char_open(struct inode *, struct file *); -+static int jz_char_release(struct inode *, struct file *); -+static int jz_char_ioctl(struct inode *, struct file *, -+ unsigned int, unsigned long); -+ -+static struct file_operations jz_char_fops = -+{ -+ read: jz_char_read, -+ write: jz_char_write, -+ ioctl: jz_char_ioctl, -+ open: jz_char_open, -+ release: jz_char_release -+}; -+ -+static int __init jz_char_family_init(void) -+{ -+ printk("JzSOC: char device family.\n"); -+ return register_chrdev(JZ_CHAR_MAJOR, "JzChar", &jz_char_fops); -+} -+ -+static void __exit jz_char_family_exit(void) -+{ -+ printk("JzSOC: exit char device family.\n"); -+ unregister_chrdev(JZ_CHAR_MAJOR, "JzChar"); -+} -+ -+module_init(jz_char_family_init); -+module_exit(jz_char_family_exit); -+ -+static int jz_char_open(struct inode *inode, struct file *filp) -+{ -+ jz_char_dev_t *dev = NULL; -+ unsigned int minor = iminor(inode); //minor extend to 20bit! -+ struct list_head *p; -+ list_for_each(p, &jz_char_devs) { -+ jz_char_dev_t *one = (jz_char_dev_t *)p; -+ if (one->dev_minor == minor) { -+ dev = one; -+ filp->private_data = dev; -+ return dev->fops->open(inode, filp); -+ } -+ } -+ printk("JzChar: No such device\n"); -+ return -EINVAL; -+} -+ -+static int jz_char_release(struct inode *inode, struct file *filp) -+{ -+ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -+ if (dev->fops->release) -+ return dev->fops->release(inode, filp); -+ return 0; -+} -+ -+static int jz_char_ioctl(struct inode *inode, struct file *filp, -+ unsigned int cmd, unsigned long arg) -+{ -+ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -+ if (dev->fops->ioctl) -+ return dev->fops->ioctl(inode, filp, cmd, arg); -+ return 0; -+} -+ -+static ssize_t jz_char_read(struct file *filp, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -+ if (dev->fops->read) -+ return dev->fops->read(filp, buf, count, ppos); -+ return 0; -+} -+ -+static ssize_t jz_char_write(struct file *filp, const char *buf, -+ size_t count, loff_t *ppos) -+{ -+ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -+ if (dev->fops->write) -+ return dev->fops->write(filp, buf, count, ppos); -+ return 0; -+} -+ -+EXPORT_SYMBOL(jz_register_chrdev); -+EXPORT_SYMBOL(jz_unregister_chrdev); -diff --git a/drivers/char/jzchar/jzchars.h b/drivers/char/jzchar/jzchars.h -new file mode 100644 -index 0000000..a76f2ae ---- /dev/null -+++ b/drivers/char/jzchar/jzchars.h -@@ -0,0 +1,47 @@ -+#ifndef __JZ_CHARS_H__ -+#define __JZ_CHARS_H__ -+ -+#include -+#include -+ -+#define JZ_CHAR_MAJOR 238 -+ -+#define UPRT_MINOR 0 // Micro printer -+#define CIM_MINOR 1 // Camera interface module -+#define TPANEL_MINOR 2 // Touchpanel -+#define KEYPAD_MINOR 3 // Keypad -+#define MEMCARD_MINOR 4 // Memory card -+#define MAGCARD_MINOR 5 // Magcard -+#define VFD_MINOR 6 // VFD -+#define POWERFAIL_MINOR 7 // Powerfail -+#define EJTAG_MINOR 8 // EJTAG emulation -+#define REMR0_MINOR 9 // Remote output receive 0 -+#define REMR1_MINOR 10 // Remote output receive 1 -+#define USPI_MINOR 11 // Ultra-speed SPI device -+#define SADC_MINOR 12 // SAR-ADC -+#define SLCD_MINOR 13 // Smart LCD -+ -+// 32 to 47 are reserved for SCC -+#define SCC_MINOR 32 -+// 48 to 63 are reserved for Camera sensor -+#define SENSOR_MINOR 48 -+// 64 to 71 are for EEPROM -+#define EEPROM_MINOR_BASE 64 -+// 72 for OWI -+#define OW_MINOR 72 -+// 73 for TCSM_MINOR -+#define TCSM_MINOR 73 -+ -+typedef struct { -+ struct list_head list; -+ char *name; -+ struct file_operations *fops; -+ void *private; -+ unsigned short dev_minor; -+} jz_char_dev_t; -+ -+extern int jz_register_chrdev(unsigned char minor, const char *name, -+ struct file_operations *fops, void * private); -+extern int jz_unregister_chrdev(unsigned char minor, const char *name); -+ -+#endif /* __JZ_CHARS_H__ */ -diff --git a/drivers/char/jzchar/poweroff.c b/drivers/char/jzchar/poweroff.c -new file mode 100644 -index 0000000..a488f5f ---- /dev/null -+++ b/drivers/char/jzchar/poweroff.c -@@ -0,0 +1,396 @@ -+/* -+ * linux/drivers/char/jzchar/poweroff.c -+ * -+ * Power off handling. -+ * -+ * Copyright (C) 2005-2007 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "jzchars.h" -+ -+MODULE_AUTHOR("Jianli Wei "); -+MODULE_DESCRIPTION("Poweroff handling"); -+MODULE_LICENSE("GPL"); -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+ -+//#define USE_SUSPEND_HOTPLUG -+ -+#ifdef CONFIG_SOC_JZ4730 -+#define GPIO_PW_I 97 -+#define GPIO_PW_O 66 -+#define POWEROFF_PIN_DOWN 1 -+#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_rise_edge(POWEROFF_PIN) -+#define DO_SHUTDOWN_SYSTEM __gpio_clear_pin(GPIO_PW_O) -+#define DO_SUSPEND jz_pm_suspend() -+ -+#define GPIO_DISP_OFF_N 93 -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ REG_PWM_DUT(0) = n; \ -+ REG_PWM_PER(0) = 7; \ -+ REG_PWM_CTR(0) = 0x81; \ -+} while (0) -+#define __lcd_close_backlight() \ -+do { \ -+ __lcd_set_backlight_level(0); \ -+} while (0) -+#endif -+ -+#ifdef CONFIG_SOC_JZ4740 -+#define GPIO_PW_I 125 -+#define POWEROFF_PIN_DOWN 0 -+#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_fall_edge(POWEROFF_PIN) -+#define DO_SHUTDOWN_SYSTEM jz_pm_hibernate() -+#define DO_SUSPEND { \ -+ jz_pm_sleep();\ -+ suspend_flag = 0;\ -+ SET_POWEROFF_PIN_AS_IRQ;\ -+ } -+ -+#define GPIO_DISP_OFF_N 118 -+#define GPIO_PWM 123 -+#define __lcd_close_backlight() \ -+do { \ -+__gpio_as_output(GPIO_PWM); \ -+__gpio_clear_pin(GPIO_PWM); \ -+} while (0) -+#endif -+ -+#ifdef CONFIG_SOC_JZ4750 -+#define GPIO_PW_I GPIO_WAKEUP -+#define POWEROFF_PIN_DOWN 0 -+#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_fall_edge(POWEROFF_PIN) -+#define DO_SHUTDOWN_SYSTEM jz_pm_hibernate() -+#define DO_SUSPEND { \ -+ jz_pm_sleep();\ -+ suspend_flag = 0;\ -+ SET_POWEROFF_PIN_AS_IRQ;\ -+ } -+#endif -+ -+#ifdef CONFIG_SOC_JZ4750D -+#define GPIO_PW_I GPIO_WAKEUP -+#define POWEROFF_PIN_DOWN 0 -+#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_fall_edge(POWEROFF_PIN) -+#define DO_SHUTDOWN_SYSTEM jz_pm_hibernate() -+#define DO_SUSPEND { \ -+ jz_pm_sleep();\ -+ suspend_flag = 0;\ -+ SET_POWEROFF_PIN_AS_IRQ;\ -+ } -+#endif -+ -+ -+#define POWEROFF_PIN GPIO_PW_I -+#define POWEROFF_IRQ (IRQ_GPIO_0 + POWEROFF_PIN) -+ -+#define POWEROFF_PERIOD 1000 /* unit: ms */ -+#define POWEROFF_DELAY 100 /* unit: ms */ -+ -+static struct timer_list poweroff_timer; -+static struct timer_list poweroff_delaytimer; -+static struct work_struct suspend_work; -+ -+static int poweroff_flag = 0; -+static int suspend_flag = 0; -+static int num_seconds = 0; -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+extern int jz_udc_active; -+#endif -+ -+extern void jz_pm_suspend(void); -+extern int jz_pm_hibernate(void); -+extern int jz_pm_sleep(void); -+ -+static void poweroff_timer_routine(unsigned long dummy) -+{ -+ if (__gpio_get_pin(POWEROFF_PIN) == POWEROFF_PIN_DOWN) { -+ if (++num_seconds > 3) -+ { -+ printk("\nShutdown system now ..\n"); -+ -+#ifndef USE_SUSPEND_HOTPLUG -+ /* Turn off LCD to inform user that the system is shutting down. -+ * But the information of shutting down system will be shown -+ * by userspace program if hotplug is used. -+ */ -+ __lcd_close_backlight(); -+#endif -+ -+ /* -+ * Wait until the power key is up, or the system will reset with -+ * power key down after entering hibernate. -+ */ -+ while(__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN); -+ -+ poweroff_flag = 1; -+ schedule_work(&suspend_work); /* inform user to poweroff */ -+ } -+ else { -+ del_timer(&poweroff_timer); -+ init_timer(&poweroff_timer); -+ poweroff_timer.expires = jiffies + POWEROFF_PERIOD/10; -+ poweroff_timer.data = 0; -+ poweroff_timer.function = poweroff_timer_routine; -+ add_timer(&poweroff_timer); -+ } -+ } -+ else -+ { -+ printk("\nSuspend system now ..\n"); -+ num_seconds = 0; -+ suspend_flag = 1; -+ poweroff_flag = 0; -+ schedule_work(&suspend_work); /* we are entering suspend */ -+ } -+} -+ -+static void poweroff_delaytimer_routine(unsigned long dummy) -+{ -+ __gpio_as_input(POWEROFF_PIN); -+ if (__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN) { -+ if (suspend_flag) { -+ suspend_flag = 0; -+ del_timer(&poweroff_delaytimer); -+ SET_POWEROFF_PIN_AS_IRQ; -+ __gpio_unmask_irq(POWEROFF_PIN); -+ return; -+ } -+ del_timer(&poweroff_delaytimer); -+ del_timer(&poweroff_timer); -+ init_timer(&poweroff_timer); -+ poweroff_timer.expires = jiffies + POWEROFF_PERIOD/100; -+ poweroff_timer.data = 0; -+ poweroff_timer.function = poweroff_timer_routine; -+ add_timer(&poweroff_timer); -+ } -+ else { -+ del_timer(&poweroff_delaytimer); -+ SET_POWEROFF_PIN_AS_IRQ; -+ __gpio_unmask_irq(POWEROFF_PIN); -+ -+ printk("This is a dummy key\n"); -+ } -+} -+ -+/* -+ * Poweroff pin interrupt handler -+ */ -+static irqreturn_t poweroff_irq(int irq, void *dev_id) -+{ -+ __gpio_ack_irq(POWEROFF_PIN); -+ __gpio_mask_irq(POWEROFF_PIN); -+ __gpio_as_input(POWEROFF_PIN); -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ if (__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN && jz_udc_active == 0){ -+#else -+ if (__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN){ -+#endif -+ del_timer(&poweroff_delaytimer); -+ init_timer(&poweroff_delaytimer); -+ poweroff_delaytimer.expires = jiffies + POWEROFF_DELAY/10; -+ poweroff_delaytimer.data = 0; -+ poweroff_delaytimer.function = poweroff_delaytimer_routine; -+ add_timer(&poweroff_delaytimer); -+ } -+ else { -+ -+/* -+ * If it reaches here without jz_udc_active == 0, then it indicates POWEROFF_PIN was -+ * changed to WAKEUP key in pm.c for hand is not able to rise up so quickly, so the -+ * irq handler entered because of WAKEUP key not POWEROFF_PIN. -+ */ -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ if (jz_udc_active == 1) -+ printk("\nUSB is working; Operation is denied\n"); -+#endif -+ SET_POWEROFF_PIN_AS_IRQ; -+ __gpio_unmask_irq(POWEROFF_PIN); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+#ifdef CONFIG_PM -+ -+static struct pm_dev *poweroff_dev; -+ -+static int poweroff_suspend(int *poweroff , int state) -+{ -+ suspend_flag = 1; -+ poweroff_flag = 0; -+ -+ return 0; -+} -+ -+static int poweroff_resume(int *poweroff) -+{ -+ suspend_flag = 0; -+ SET_POWEROFF_PIN_AS_IRQ; -+ __gpio_unmask_irq(POWEROFF_PIN); -+ -+ return 0; -+} -+ -+static int poweroff_pm_callback(struct pm_dev *pm_dev, pm_request_t rqst, void *data) -+{ -+ int ret; -+ int *poweroff_info = pm_dev->data; -+ -+ if (!poweroff_info) -+ return -EINVAL; -+ -+ switch (rqst) { -+ case PM_SUSPEND: -+ ret = poweroff_suspend(poweroff_info, (int)data); -+ break; -+ case PM_RESUME: -+ ret = poweroff_resume(poweroff_info); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+#endif /* CONFIG_PM */ -+ -+#ifdef USE_SUSPEND_HOTPLUG -+static void run_sbin_hotplug(int state) -+{ -+ int i; -+ char *argv[3], *envp[8]; -+ char media[64], slotnum[16]; -+ if (!uevent_helper[0]) -+ return; -+ -+ i = 0; -+ argv[i++] = uevent_helper; -+ //argv[i++] = "home/lhhuang/hotplug"; -+ -+ if ( poweroff_flag == 1 ) -+ argv[i++] = "poweroff"; -+ else -+ argv[i++] = "suspend"; -+ -+ argv[i] = 0; -+ -+ /* minimal command environment */ -+ i = 0; -+ envp[i++] = "HOME=/"; -+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; -+ -+ /* other stuff we want to pass to /sbin/hotplug */ -+ sprintf(slotnum, "SLOT=0"); -+ -+ if ( poweroff_flag == 1 ) -+ sprintf(media, "MEDIA=poweroff"); -+ else -+ sprintf(media, "MEDIA=suspend"); -+ -+ envp[i++] = slotnum; -+ envp[i++] = media; -+ -+ if (state) -+ envp[i++] = "ACTION=enter"; -+ else -+ envp[i++] = "ACTION=exit"; -+ -+ envp[i] = 0; -+ -+ dprintk("SUSPEND: hotplug path=%s state=%d\n", argv[0], state); -+ -+ SET_POWEROFF_PIN_AS_IRQ; -+ __gpio_unmask_irq(POWEROFF_PIN); /* set it because call hotplug with call_usermodehelper() \ -+ might failed, especially when using nfsroot */ -+ -+ call_usermodehelper (argv [0], argv, envp, -1); -+} -+#endif -+ -+static void suspend_handler(struct work_struct *work) -+{ -+#ifdef USE_SUSPEND_HOTPLUG -+ int state = 1; -+ run_sbin_hotplug(state); -+#else -+ if (poweroff_flag) { -+ dprintk("DO_SHUTDOWN_SYSTEM\n"); -+ DO_SHUTDOWN_SYSTEM; -+ } else { -+ dprintk("DO_SUSPEND\n"); -+ DO_SUSPEND; -+ } -+#endif -+} -+ -+static int __init poweroff_init(void) -+{ -+ int retval; -+ -+ retval = request_irq(POWEROFF_IRQ, poweroff_irq, -+ IRQF_DISABLED, "poweroff", NULL); -+ -+ SET_POWEROFF_PIN_AS_IRQ; -+ -+ if (retval) { -+ printk("Could not get poweroff irq %d\n", POWEROFF_IRQ); -+ return retval; -+ } -+ -+#ifdef CONFIG_PM -+ poweroff_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, poweroff_pm_callback); -+ if (poweroff_dev) { -+ poweroff_dev->data = &poweroff_dev; -+ } -+#endif -+ -+ INIT_WORK(&suspend_work, suspend_handler); -+ -+ return 0; -+} -+ -+static void __exit poweroff_exit(void) -+{ -+ free_irq(POWEROFF_IRQ, NULL); -+} -+ -+module_init(poweroff_init); -+module_exit(poweroff_exit); -+ -diff --git a/drivers/char/jzchar/sadc.c b/drivers/char/jzchar/sadc.c -new file mode 100644 -index 0000000..dc43404 ---- /dev/null -+++ b/drivers/char/jzchar/sadc.c -@@ -0,0 +1,580 @@ -+/* -+ * linux/drivers/char/jzchar/sadc.c -+ * -+ * SAR-ADC driver for JZ4740. -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "jzchars.h" -+#include "jz_ts.h" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("JZ4740 SADC driver"); -+MODULE_LICENSE("GPL"); -+ -+#define SADC_NAME "sadc" -+static DECLARE_WAIT_QUEUE_HEAD (sadc_wait_queue); -+ -+struct sadc_device { -+ int mode; -+ int dma_chan; -+ char *ts_buf; -+ char *pbat_buf; -+}; -+ -+static struct sadc_device *sadc_dev; -+ -+static int samples = 3; /* we sample 3 every time */ -+static int first_time = 0; -+static unsigned long last_x, last_y, last_p; -+ -+typedef struct datasource { -+ u16 xbuf; -+ u16 ybuf; -+ u16 zbuf; -+}datasource_t; -+ -+static datasource_t data_s; -+static unsigned int p; -+static unsigned int old_x, old_y; -+extern unsigned int (*codec_read_battery)(void); -+ -+/* -+ * set adc clock to 12MHz/div. A/D works at freq between 500KHz to 6MHz. -+ */ -+static void sadc_init_clock(int div) -+{ -+ if (div < 2) div = 2; -+ if (div > 23) div = 23; -+#if defined(CONFIG_SOC_JZ4740) -+ REG_SADC_CFG &= ~SADC_CFG_CLKDIV_MASK; -+ REG_SADC_CFG |= (div - 1) << SADC_CFG_CLKDIV_BIT; -+#endif -+#if defined(CONFIG_SOC_JZ4750) -+ REG_SADC_ADCLK &= ~SADC_ADCLK_CLKDIV_MASK; -+ REG_SADC_ADCLK |= (div - 1) << SADC_ADCLK_CLKDIV_BIT; -+ REG_SADC_ADCLK &= ~SADC_ADCLK_CLKDIV_BIT; -+ REG_SADC_ADCLK |= 39 << SADC_ADCLK_CLKDIV_10_BIT; /* if div ==3,here is 39 */ -+#endif -+} -+ -+void start_sadcin(void) -+{ -+ REG_SADC_CTRL &= ~SADC_CTRL_SRDYM; /* enable interrupt */ -+ REG_SADC_ENA |= SADC_ENA_SADCINEN; -+} -+ -+void start_pbat_adc(void) -+{ -+ REG_SADC_CFG |= SADC_CFG_PBAT_HIGH ; /* full baterry voltage >= 2.5V */ -+// REG_SADC_CFG |= SADC_CFG_PBAT_LOW; /* full baterry voltage < 2.5V */ -+ -+ REG_SADC_ENA |= SADC_ENA_PBATEN; /* Enable pbat adc */ -+} -+ -+void start_ts_adc(void) -+{ -+ REG_SADC_SAMETIME = 10; /* about 0.1 ms,you can change it */ -+ REG_SADC_WAITTIME = 2; /* about 0.02 ms,you can change it */ -+ -+ REG_SADC_CFG &= ~(SADC_CFG_TS_DMA | SADC_CFG_XYZ_MASK | SADC_CFG_SNUM_MASK); -+ REG_SADC_CFG |= (SADC_CFG_EXIN | SADC_CFG_XYZ | SADC_CFG_SNUM_3); -+ REG_SADC_CTRL |= (SADC_CTRL_TSRDYM|SADC_CTRL_PBATRDYM|SADC_CTRL_PENUM |SADC_CTRL_SRDYM); -+ REG_SADC_CTRL &= ~SADC_CTRL_PENDM; -+ REG_SADC_ENA |= SADC_ENA_TSEN; -+} -+ -+static int jz4740_adc_read(struct jz_ts_t *ts) -+{ -+ struct datasource *ds = &data_s; -+ u32 xybuf,z; -+ -+ if (!(REG_SADC_STATE & SADC_STATE_TSRDY)) { -+ /* sleep */ -+ REG_SADC_CTRL &= ~SADC_CTRL_TSRDYM; -+ ts->sleeping = 1; -+ sleep_on(&sadc_wait_queue); -+ } -+ ts->sleeping = 0; -+ -+ xybuf = REG_SADC_TSDAT; -+ ds->xbuf = (xybuf>>16) & 0x0fff; -+ ds->ybuf = (xybuf)& 0x0fff; -+ z = REG_SADC_TSDAT; -+ ds->zbuf = z& 0x0fff; -+ REG_SADC_STATE &= ~SADC_STATE_TSRDY; -+ return 0; -+} -+ -+/*------------------------------------------------------------ -+ * Read the battery voltage -+ */ -+unsigned int jz4740_read_battery(void) -+{ -+ unsigned int v; -+ unsigned int timeout = 0x3ff; -+ u16 pbat; -+ -+ if(!(REG_SADC_STATE & SADC_STATE_PBATRDY) ==1) -+ start_pbat_adc(); -+ -+ while(!(REG_SADC_STATE & SADC_STATE_PBATRDY) && --timeout) -+ ; -+ -+ pbat = REG_SADC_BATDAT; -+ v = pbat & 0x0fff; -+ REG_SADC_STATE = SADC_STATE_PBATRDY; -+ return v; -+} -+ -+/*------------------ Calibrate samples -------------------*/ -+ -+#define DIFF(a,b) (((a)>(b))?((a)-(b)):((b)-(a))) -+#define MIN(a,b) (((a)<(b))?(a):(b)) -+ -+#if 0 -+#define XM 36 /* XM and YM may be changed for your screen */ -+#define YM 20 -+static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -+{ -+ unsigned long usd0,usd1,usd2; -+ int xMaxError = XM,yMaxError = YM; -+ int x_valid = 0,y_valid = 0,valid = 0; -+ unsigned long x_cal = 0, y_cal = 0, p_cal = 0; -+ unsigned long *xp = (unsigned long *)xbuf; -+ unsigned long *yp = (unsigned long *)ybuf; -+ unsigned long *pp = (unsigned long *)pbuf; -+ -+ usd0 = (xp[0] > xp[1]) ? (xp[0] - xp[1]) : (xp[1] - xp[0]); -+ usd1 = (xp[1] > xp[2]) ? (xp[1] - xp[2]) : (xp[2] - xp[1]); -+ usd2 = (xp[2] > xp[0]) ? (xp[2] - xp[0]) : (xp[0] - xp[2]); -+ -+ if ( usd0 < usd1) -+ x_cal = xp[0] + ((usd2 < usd0) ? xp[2] : xp[1]); -+ else -+ x_cal= xp[2] + ((usd2 < usd1) ? xp[0] : xp[1]); -+ x_cal >>= 1; -+ -+ if ( (usd0 < xMaxError) && (usd1 < xMaxError) && (usd2 < xMaxError) ) -+ x_valid = 1; -+ -+ usd0 = (yp[0] > yp[1]) ? (yp[0] - yp[1]) : (yp[1] - yp[0]); -+ usd1 = (yp[1] > yp[2]) ? (yp[1] - yp[2]) : (yp[2] - yp[1]); -+ usd2 = (yp[2] > yp[0]) ? (yp[2] - yp[0]) : (yp[0] - yp[2]); -+ -+ if ( usd0 < usd1) -+ y_cal = yp[0] + ((usd2 < usd0) ? yp[2] : yp[1]); -+ else -+ y_cal = yp[2] + ((usd2 < usd1) ? yp[0] : yp[1]); -+ -+ y_cal >>= 1; -+ -+ if ( (usd0 < yMaxError) && (usd1 < yMaxError) && (usd2 < yMaxError) ) -+ y_valid = 1; -+ -+ if( x_valid && y_valid) -+ valid = 1; -+ -+ usd0 = (pp[0] > pp[1]) ? (pp[0] - pp[1]) : (pp[1] - pp[0]); -+ usd1 = (pp[1] > pp[2]) ? (pp[1] - pp[2]) : (pp[2] - pp[1]); -+ usd2 = (pp[2] > pp[0]) ? (pp[2] - pp[0]) : (pp[0] - pp[2]); -+ -+ if ( usd0 < usd1) -+ p_cal = pp[0] + ((usd2 < usd0) ? pp[2] : pp[1]); -+ else -+ p_cal= pp[2] + ((usd2 < usd1) ? pp[0] : pp[1]); -+ -+ p_cal >>= 1; -+ -+ if (first_time) { -+ first_time = 0; -+ last_x = x_cal; -+ last_y = y_cal; -+ last_p = p_cal; -+ } -+ else{ -+ if ((DIFF(x_cal, last_x) > 50) || -+ (DIFF(y_cal, last_y) > 50)) -+ valid = 0; -+ else -+ valid = 1; -+ } -+ *xp = last_x = x_cal; -+ *yp = last_y = y_cal; -+ *pp = last_p = p_cal; -+ -+ return valid; -+} -+#endif -+ -+static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -+{ -+ unsigned long *xp = (unsigned long *)xbuf; -+ unsigned long *yp = (unsigned long *)ybuf; -+ unsigned long *pp = (unsigned long *)pbuf; -+ unsigned long x_cal = 0, y_cal = 0, p_cal = 0; -+ int i; -+ int valid = 1; -+ -+ /* calculate the average of the rest */ -+ for (i = 0; i < count; i++) { -+ x_cal += xp[i]; -+ y_cal += yp[i]; -+ p_cal += pp[i]; -+ } -+ x_cal /= count; -+ y_cal /= count; -+ p_cal /= count; -+ -+ if (first_time) { -+ first_time = 0; -+ last_x = x_cal; -+ last_y = y_cal; -+ last_p = p_cal; -+ } -+ else { -+ if ((DIFF(x_cal, last_x) > 50) || -+ (DIFF(y_cal, last_y) > 50)) -+ valid = 0; -+ else -+ valid = 1; -+ } -+ -+ *xp = last_x = x_cal; -+ *yp = last_y = y_cal; -+ *pp = last_p = p_cal; -+ -+ return valid; -+} -+ -+#define TSMAXX 945 -+#define TSMAXY 830 -+#define TSMINX 90 -+#define TSMINY 105 -+ -+#define SCREEN_X 480 -+#define SCREEN_Y 272 -+ -+static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -+{ -+ -+ if (ts->minx) -+ { -+ if (x < ts->minx) x = ts->minx; -+ if (x > ts->maxx) x = ts->maxx; -+ -+ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -+ } -+ else -+ { -+ if (x < TSMINX) x = TSMINX; -+ if (x > TSMAXX) x = TSMAXX; -+ -+ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -+ } -+} -+ -+static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -+{ -+ if (ts->minx) -+ { -+ if (y < ts->minx) y = ts->miny; -+ if (y > ts->maxx) y = ts->maxy; -+ -+ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -+ } -+ else -+ { -+ if (y < TSMINX) y = TSMINY; -+ if (y > TSMAXX) y = TSMAXY; -+ -+ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -+ } -+} -+ -+/* -+ * File operations -+ */ -+static int sadc_open(struct inode *inode, struct file *filp); -+static int sadc_release(struct inode *inode, struct file *filp); -+static ssize_t sadc_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t sadc_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int sadc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations sadc_fops = -+{ -+ open: sadc_open, -+ release: sadc_release, -+ read: sadc_read, -+ write: sadc_write, -+ ioctl: sadc_ioctl -+}; -+ -+static int sadc_open(struct inode *inode, struct file *filp) -+{ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int sadc_release(struct inode *inode, struct file *filp) -+{ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t sadc_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ return size; -+} -+ -+static ssize_t sadc_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ return size; -+} -+ -+static int sadc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ switch (cmd) { -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return 0; -+} -+ -+/*------------------ Common routines -------------------*/ -+ -+void ts_enable_irq(void) -+{ -+ REG_SADC_CTRL &= ~SADC_CTRL_PENDM; -+} -+ -+void ts_disable_irq(void) -+{ -+ REG_SADC_CTRL |= (SADC_CTRL_PENDM | SADC_CTRL_PENUM); -+} -+ -+void ts_free_irq(struct jz_ts_t *ts) -+{ -+ free_irq(ts->pendown_irq, ts); -+} -+ -+void ts_data_ready(void) -+{ -+ REG_SADC_CTRL |= SADC_CTRL_TSRDYM; -+ wake_up(&sadc_wait_queue); -+} -+ -+/* -+ * Interrupt handler -+ */ -+void ts_irq_callback(void) -+{ -+ u32 state; -+ -+ state = REG_SADC_STATE; -+ if (!(REG_SADC_CTRL&SADC_CTRL_PENDM)&&(REG_SADC_STATE & SADC_STATE_PEND)) { -+ REG_SADC_STATE = SADC_STATE_PEND; -+ REG_SADC_STATE = SADC_STATE_PENU; -+ REG_SADC_CTRL |= SADC_CTRL_PENDM; -+ REG_SADC_CTRL &= ~SADC_CTRL_PENUM; -+ p = 1; -+ } -+ -+ if (!(REG_SADC_CTRL&SADC_CTRL_PENUM)&&(REG_SADC_STATE & SADC_STATE_PENU)) { -+ REG_SADC_STATE = SADC_STATE_PENU; -+ REG_SADC_CTRL |= SADC_CTRL_PENUM; -+ REG_SADC_CTRL &= ~SADC_CTRL_PENDM; -+ p = 0; -+ } -+ -+ first_time = 1; // first time to acquire sample -+} -+ -+int PenIsDown(void) -+{ -+ return p; -+} -+ -+int ts_request_irq(u32 *irq, -+ irqreturn_t (*handler)(int, void *), -+ const char *devname, -+ void *dev_id) -+{ -+ int ret; -+ -+ /* return the irq number */ -+ *irq = IRQ_SADC; -+ ts_disable_irq(); -+ /* interrupt mode */ -+ ret = request_irq(IRQ_SADC, handler, IRQF_DISABLED, -+ devname, dev_id); -+ if(ret) -+ printk("failed irq \n"); -+ -+ start_ts_adc(); -+ return ret; -+} -+ -+/* -+ * Acquire Raw pen coodinate data and compute touch screen -+ * pressure resistance. Hold spinlock when calling. -+ */ -+int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -+{ -+ unsigned int x_raw[8], y_raw[8], p_raw[8]; -+ int valid, i; -+ unsigned int avl_x, avl_y, diff_x, diff_y; -+ struct datasource *ds = &data_s; -+ avl_x = avl_y = 0; -+ -+ for (i = 0; i < samples; i++) { -+ if (jz4740_adc_read(ts)) { -+ return 0; -+ } -+ -+ x_raw[i] = ds->ybuf; -+ y_raw[i] = ds->xbuf; -+ p_raw[i] = ds->zbuf; -+ avl_x += x_raw[i]; -+ avl_y += y_raw[i]; -+#if 0 -+ printk("x_raw=%x y_raw=%x z_raw=%x\n",x_raw[i],y_raw[i],p_raw[i]); -+#endif -+ } -+ -+ avl_x /= samples; -+ avl_y /= samples; -+#define MAX_DELTA 20 -+ valid = 1; -+ -+ for (i = 1; i < samples; i++) -+ { -+ if ((100 * DIFF(x_raw[i],x_raw[i-1])/MIN(x_raw[i],x_raw[i-1])) > MAX_DELTA) { -+ valid = 0; -+ break; -+ } -+ -+ if ((100 * DIFF(y_raw[i],y_raw[i-1])/MIN(y_raw[i],y_raw[i-1])) > MAX_DELTA) { -+ valid = 0; -+ break; -+ } -+ -+ if ((100 * DIFF(p_raw[i],p_raw[i-1])/MIN(p_raw[i],p_raw[i-1])) > MAX_DELTA) { -+ valid = 0; -+ break; -+ } -+ } -+ -+ if (valid) { -+ if (ts->first_read) { -+ ts->first_read = 0; -+ old_x = avl_x; -+ old_y = avl_y; -+ } -+ diff_x = DIFF(old_x, avl_x); -+ diff_y = DIFF(old_y, avl_y); -+ if (diff_x < 100 && diff_y < 100) { -+ old_x = avl_x; -+ old_y = avl_y; -+ } else -+ valid = 0; -+ } -+ if (valid) { -+ valid = calibrate_samples(x_raw, y_raw, p_raw, samples); -+ } -+ -+ if (valid) { -+ unsigned int x_scr, y_scr; -+ -+ if(ts->filter) { -+ x_scr = transform_to_screen_x(ts, x_raw[0]); -+ y_scr = transform_to_screen_y(ts, y_raw[0]); -+ -+ if (ts->prints) -+ printk("x_raw=%d y_raw=%d x_transform=%d y_transform=%d\n", x_raw[0], y_raw[0], x_scr, y_scr); -+ } -+ else { -+ x_scr = x_raw[0]; -+ y_scr = y_raw[0]; -+ -+ if (ts->prints) -+ printk("x_raw=%d y_raw=%d \n", x_raw[0], y_raw[0]); -+ } -+ -+ event->x = x_scr; -+ event->y = y_scr; -+ event->pressure = (u16)p_raw[0]; -+ event->status = PENDOWN; -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * Module init and exit -+ */ -+static int __init sadc_init(void) -+{ -+ struct sadc_device *dev; -+ int ret; -+ -+ /* allocate device */ -+ dev = kmalloc(sizeof(struct sadc_device), GFP_KERNEL); -+ if (!dev) return -ENOMEM; -+ -+ sadc_dev = dev; -+ ret = jz_register_chrdev(SADC_MINOR, SADC_NAME, &sadc_fops, dev); -+ if (ret < 0) { -+ kfree(dev); -+ return ret; -+ } -+ -+ codec_read_battery = jz4740_read_battery; -+ sadc_init_clock(3); -+ -+ printk("JZ4740 SAR-ADC driver registered\n"); -+ return 0; -+} -+ -+static void __exit sadc_exit(void) -+{ -+ struct sadc_device *dev = sadc_dev; -+ -+ free_irq(IRQ_SADC, dev); -+ jz_unregister_chrdev(SADC_MINOR, SADC_NAME); -+ kfree(dev); -+} -+ -+module_init(sadc_init); -+module_exit(sadc_exit); -diff --git a/drivers/char/jzchar/sensor.c b/drivers/char/jzchar/sensor.c -new file mode 100644 -index 0000000..8123203 ---- /dev/null -+++ b/drivers/char/jzchar/sensor.c -@@ -0,0 +1,182 @@ -+/* -+ * linux/drivers/char/jzchar/sensor.c -+ * -+ * Common CMOS Camera Sensor Driver -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "jzchars.h" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("Common CMOS Camera Sensor Driver"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * ioctl commands -+ */ -+#define IOCTL_SET_ADDR 0 /* set i2c address */ -+#define IOCTL_SET_CLK 1 /* set i2c clock */ -+#define IOCTL_WRITE_REG 2 /* write sensor register */ -+#define IOCTL_READ_REG 3 /* read sensor register */ -+ -+/* -+ * i2c related -+ */ -+static unsigned int i2c_addr = 0x42; -+static unsigned int i2c_clk = 100000; -+ -+static void write_reg(u8 reg, u8 val) -+{ -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_write((i2c_addr >> 1), &val, reg, 1); -+ i2c_close(); -+} -+ -+static u8 read_reg(u8 reg) -+{ -+ u8 val; -+ -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_read((i2c_addr >> 1), &val, reg, 1); -+ i2c_close(); -+ return val; -+} -+ -+/* -+ * fops routines -+ */ -+ -+static int sensor_open(struct inode *inode, struct file *filp); -+static int sensor_release(struct inode *inode, struct file *filp); -+static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int sensor_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations sensor_fops = -+{ -+ open: sensor_open, -+ release: sensor_release, -+ read: sensor_read, -+ write: sensor_write, -+ ioctl: sensor_ioctl, -+}; -+ -+static int sensor_open(struct inode *inode, struct file *filp) -+{ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int sensor_release(struct inode *inode, struct file *filp) -+{ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ printk("sensor: read is not implemented\n"); -+ return -1; -+} -+ -+static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("sensor: write is not implemented\n"); -+ return -1; -+} -+ -+static int sensor_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ int ret = 0; -+ -+ switch (cmd) { -+ case IOCTL_SET_ADDR: -+ if (copy_from_user(&i2c_addr, (void *)arg, 4)) -+ return -EFAULT; -+ break; -+ case IOCTL_SET_CLK: -+ if (copy_from_user(&i2c_clk, (void *)arg, 4)) -+ return -EFAULT; -+ break; -+ case IOCTL_WRITE_REG: -+ { -+ u8 regval[2]; -+ -+ if (copy_from_user(regval, (void *)arg, 2)) -+ return -EFAULT; -+ -+ write_reg(regval[0], regval[1]); -+ break; -+ } -+ case IOCTL_READ_REG: -+ { -+ u8 reg, val; -+ -+ if (copy_from_user(®, (void *)arg, 1)) -+ return -EFAULT; -+ -+ val = read_reg(reg); -+ -+ if (copy_to_user((void *)(arg + 1), &val, 1)) -+ return -EFAULT; -+ break; -+ } -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+/* -+ * Module init and exit -+ */ -+ -+static int __init sensor_init(void) -+{ -+ int ret; -+ -+ ret = jz_register_chrdev(SENSOR_MINOR, "sensor", &sensor_fops, NULL); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ printk("Ingenic CMOS camera sensor driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit sensor_exit(void) -+{ -+ jz_unregister_chrdev(SENSOR_MINOR, "sensor"); -+} -+ -+module_init(sensor_init); -+module_exit(sensor_exit); -diff --git a/drivers/char/jzchar/tcsm.c b/drivers/char/jzchar/tcsm.c -new file mode 100644 -index 0000000..1941d14 ---- /dev/null -+++ b/drivers/char/jzchar/tcsm.c -@@ -0,0 +1,123 @@ -+/* -+ * linux/drivers/char/jzchar/tcsm.c -+ * -+ * Virtual device driver with tricky appoach to manage TCSM -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jzchars.h" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("Virtual Driver of TCSM"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * fops routines -+ */ -+ -+static int tcsm_open(struct inode *inode, struct file *filp); -+static int tcsm_release(struct inode *inode, struct file *filp); -+static ssize_t tcsm_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t tcsm_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int tcsm_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations tcsm_fops = -+{ -+ open: tcsm_open, -+ release: tcsm_release, -+ read: tcsm_read, -+ write: tcsm_write, -+ ioctl: tcsm_ioctl, -+}; -+ -+static int tcsm_open(struct inode *inode, struct file *filp) -+{ -+ struct pt_regs *info = task_pt_regs(current); -+ -+ info->cp0_status &= ~0x10;// clear UM bit -+ info->cp0_status |= 0x08000000; // set RP bit a tricky -+ -+ return 0; -+} -+ -+static int tcsm_release(struct inode *inode, struct file *filp) -+{ -+ struct pt_regs *info = task_pt_regs(current); -+ -+ info->cp0_status |= 0x10;// set UM bit -+ info->cp0_status &= ~0x08000000; // clear RP bit a tricky -+ -+ return 0; -+} -+ -+static ssize_t tcsm_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ printk("tcsm: read is not implemented\n"); -+ return -1; -+} -+ -+static ssize_t tcsm_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("tcsm: write is not implemented\n"); -+ return -1; -+} -+ -+static int tcsm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ int ret = 0; -+ printk("tcsm: ioctl is not implemented\n"); -+ return ret; -+} -+ -+/* -+ * Module init and exit -+ */ -+ -+static int __init tcsm_init(void) -+{ -+ int ret; -+ -+ ret = jz_register_chrdev(TCSM_MINOR, "tcsm", &tcsm_fops, NULL); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ printk("Virtual Driver of TCSM registered\n"); -+ return 0; -+} -+ -+static void __exit tcsm_exit(void) -+{ -+ jz_unregister_chrdev(TCSM_MINOR, "tcsm"); -+} -+ -+module_init(tcsm_init); -+module_exit(tcsm_exit); -diff --git a/drivers/char/jzchar/ucb1400.c b/drivers/char/jzchar/ucb1400.c -new file mode 100644 -index 0000000..d5d06f7 ---- /dev/null -+++ b/drivers/char/jzchar/ucb1400.c -@@ -0,0 +1,585 @@ -+/* -+ * ucb1400.c -+ * -+ * Touch screen driver interface to the UCB1400 codec. -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz_ts.h" -+#include "ucb1400.h" -+ -+#ifndef GPIO_TS_PENIRQ -+#define GPIO_TS_PENIRQ 68 -+#endif -+ -+#define TS_PIN GPIO_TS_PENIRQ -+#define TS_IRQ (IRQ_GPIO_0 + TS_PIN) -+ -+static int samples = 5; /* we sample 5 every time, and throw away the max and min cases, then use the average of the other 3 samples */ -+static int first_time = 0; -+static unsigned long last_x, last_y, last_p; -+ -+static int adcsync = 0; -+ -+static unsigned int ucb_id = 0; -+static struct ucb1400 *ucb; -+ -+extern struct ac97_codec * find_ac97_codec(void); -+ -+extern unsigned int (*codec_read_battery)(void); -+ -+/*------------------ UCB1400 routines ------------------*/ -+ -+static inline void ucb1400_reg_write(unsigned char reg, unsigned short val) -+{ -+ struct ac97_codec *codec = find_ac97_codec(); -+ if (!codec) -+ return; -+ codec->codec_write(codec, reg, val); -+} -+ -+static inline unsigned int ucb1400_reg_read(unsigned char reg) -+{ -+ struct ac97_codec *codec = find_ac97_codec(); -+ if (!codec) -+ return 0; -+ return codec->codec_read(codec, reg); -+} -+ -+static void ucb1400_adc_enable(void) -+{ -+ down(&ucb->adc_sem); -+ -+ ucb->adc_cr |= UCB_ADC_ENA; -+ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr); -+} -+ -+static unsigned int ucb1400_adc_read(int adc_channel, int sync) -+{ -+ unsigned int val, timeout = 10000; -+ -+ if (sync) -+ adc_channel |= UCB_ADC_SYNC_ENA; -+ -+ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr | adc_channel); -+ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); -+ -+ for (;;) { -+ val = ucb1400_reg_read(UCB_ADC_DATA); -+ if (val & UCB_ADC_DAT_VAL) -+ break; -+ if (--timeout == 0) -+ break; -+ udelay(1); -+ } -+ -+ return UCB_ADC_DAT(val); -+} -+ -+static void ucb1400_adc_disable(void) -+{ -+ ucb->adc_cr &= ~UCB_ADC_ENA; -+ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr); -+ -+ up(&ucb->adc_sem); -+} -+ -+static void ucb1400_enable_irq(unsigned int idx, int edges) -+{ -+ unsigned long flags; -+ -+ if (idx < 16) { -+ spin_lock_irqsave(&ucb->lock, flags); -+ -+ /* This prevents spurious interrupts on the UCB1400 */ -+ ucb1400_reg_write(UCB_IE_CLEAR, 1 << idx); -+ ucb1400_reg_write(UCB_IE_CLEAR, 0); -+ -+ if (edges & UCB_RISING) { -+ ucb->irq_ris_enbl |= 1 << idx; -+ ucb1400_reg_write(UCB_IE_RIS, ucb->irq_ris_enbl); -+ } -+ if (edges & UCB_FALLING) { -+ ucb->irq_fal_enbl |= 1 << idx; -+ ucb1400_reg_write(UCB_IE_FAL, ucb->irq_fal_enbl); -+ } -+ spin_unlock_irqrestore(&ucb->lock, flags); -+ } -+} -+ -+static void ucb1400_disable_irq(unsigned int idx, int edges) -+{ -+ unsigned long flags; -+ -+ if (idx < 16) { -+ spin_lock_irqsave(&ucb->lock, flags); -+ -+ if (edges & UCB_RISING) { -+ ucb->irq_ris_enbl &= ~(1 << idx); -+ ucb1400_reg_write(UCB_IE_RIS, ucb->irq_ris_enbl); -+ } -+ if (edges & UCB_FALLING) { -+ ucb->irq_fal_enbl &= ~(1 << idx); -+ ucb1400_reg_write(UCB_IE_FAL, ucb->irq_fal_enbl); -+ } -+ spin_unlock_irqrestore(&ucb->lock, flags); -+ } -+} -+ -+/* -+ * Switch to interrupt mode. -+ */ -+static inline void ucb1400_ts_mode_int(void) -+{ -+ if (!ucb_id) { -+ ucb_id = ucb1400_reg_read(UCB_ID); -+ } -+ -+ if (ucb_id == UCB_ID_1400_BUGGY) -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -+ UCB_TS_CR_MODE_INT); -+ else -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -+ UCB_TS_CR_MODE_INT); -+} -+ -+/* -+ * Switch to pressure mode, and read pressure. We don't need to wait -+ * here, since both plates are being driven. -+ */ -+static inline unsigned int ucb1400_ts_read_pressure(void) -+{ -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ -+ return ucb1400_adc_read(UCB_ADC_INP_TSPY, adcsync); -+} -+ -+/* -+ * Switch to X position mode and measure Y plate. We switch the plate -+ * configuration in pressure mode, then switch to position mode. This -+ * gives a faster response time. Even so, we need to wait about 55us -+ * for things to stabilise. -+ */ -+static inline unsigned int ucb1400_ts_read_xpos(void) -+{ -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); -+ -+ udelay(55); -+ -+ return ucb1400_adc_read(UCB_ADC_INP_TSPY, adcsync); -+} -+ -+/* -+ * Switch to Y position mode and measure X plate. We switch the plate -+ * configuration in pressure mode, then switch to position mode. This -+ * gives a faster response time. Even so, we need to wait about 55us -+ * for things to stabilise. -+ */ -+static inline unsigned int ucb1400_ts_read_ypos(void) -+{ -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1400_reg_write(UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); -+ -+ udelay(55); -+ -+ return ucb1400_adc_read(UCB_ADC_INP_TSPX, adcsync); -+} -+ -+/*------------------------------------------------------------ -+ * Read the battery voltage -+ */ -+ -+unsigned int ucb1400_read_battery(void) -+{ -+ unsigned int v; -+ -+ ucb1400_adc_enable(); -+ -+ // read twice to reduce fault value -+ v = ucb1400_adc_read(UCB_ADC_INP_AD0, adcsync); -+ v = ucb1400_adc_read(UCB_ADC_INP_AD0, adcsync); -+ -+ ucb1400_adc_disable(); -+ -+// printk("ucb1400_read_battery v=%d\n", v); -+ -+ return v; -+} -+ -+/*------------------ Calibrate samples -------------------*/ -+ -+#define DIFF(a,b) ((a>b)?(a-b):(b-a)) -+ -+static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -+{ -+ unsigned long *xp = (unsigned long *)xbuf; -+ unsigned long *yp = (unsigned long *)ybuf; -+ unsigned long *pp = (unsigned long *)pbuf; -+ unsigned long x_cal = 0, y_cal = 0, p_cal = 0, tmp; -+ int ignored, i, j; -+ int valid = 0; -+ -+ /* throw away the max cases */ -+ tmp = xp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (xp[i] > tmp) { -+ tmp = xp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ xp[j++] = xp[i]; -+ } -+ -+ tmp = yp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (yp[i] > tmp) { -+ tmp = yp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ yp[j++] = yp[i]; -+ } -+ -+ tmp = pp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (pp[i] > tmp) { -+ tmp = pp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ pp[j++] = pp[i]; -+ } -+ -+ /* throw away the min cases */ -+ -+ count -= 1; // decrement by 1 -+ -+ tmp = xp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (xp[i] < tmp) { -+ tmp = xp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ xp[j++] = xp[i]; -+ } -+ -+ tmp = yp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (yp[i] < tmp) { -+ tmp = yp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ yp[j++] = yp[i]; -+ } -+ -+ tmp = pp[0]; -+ ignored = 0; -+ for (i = 1; i < count; i++) { -+ if (pp[i] < tmp) { -+ tmp = pp[i]; -+ ignored = i; -+ } -+ } -+ j = 0; -+ for (i = 0; i < count; i++) { -+ if (i == ignored) -+ continue; -+ pp[j++] = pp[i]; -+ } -+ -+ count -= 1; // decrement by 1 -+ -+ /* calculate the average of the rest */ -+ for (i = 0; i < count; i++) { -+ x_cal += xp[i]; -+ y_cal += yp[i]; -+ p_cal += pp[i]; -+ } -+ x_cal /= count; -+ y_cal /= count; -+ p_cal /= count; -+ -+ if (first_time) { -+ first_time = 0; -+ last_x = x_cal; -+ last_y = y_cal; -+ last_p = p_cal; -+ valid = 1; -+ } -+ else { -+ if ((DIFF(x_cal, last_x) > 50) || -+ (DIFF(y_cal, last_y) > 50)) -+ valid = 0; -+ else -+ valid = 1; -+ } -+ -+// printk("x_cal=%d y_cal=%d p_cal=%d valid=%d\n", x_cal, y_cal, p_cal, valid); -+ -+ if (valid) { -+ *xp = last_x = x_cal; -+ *yp = last_y = y_cal; -+ *pp = last_p = p_cal; -+ } -+ -+ return valid; -+} -+ -+ -+#define TSMAXX 945 -+#define TSMAXY 830 -+#define TSMINX 90 -+#define TSMINY 105 -+ -+#define SCREEN_X 480 -+#define SCREEN_Y 272 -+ -+static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -+{ -+ -+ if (ts->minx) -+ { -+ if (x < ts->minx) x = ts->minx; -+ if (x > ts->maxx) x = ts->maxx; -+ -+ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -+ } -+ else -+ { -+ if (x < TSMINX) x = TSMINX; -+ if (x > TSMAXX) x = TSMAXX; -+ -+ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -+ } -+} -+ -+static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -+{ -+ if (ts->minx) -+ { -+ if (y < ts->minx) y = ts->miny; -+ if (y > ts->maxx) y = ts->maxy; -+ -+ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -+ } -+ else -+ { -+ if (y < TSMINX) y = TSMINY; -+ if (y > TSMAXX) y = TSMAXY; -+ -+ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -+ } -+} -+ -+/*------------------ Common routines -------------------*/ -+ -+void ts_enable_irq(void) -+{ -+ /* interrupt mode */ -+ ucb1400_ts_mode_int(); -+ ucb1400_enable_irq(UCB_IRQ_TSPX, UCB_FALLING); -+ -+ enable_irq(TS_IRQ); -+} -+ -+void ts_disable_irq(void) -+{ -+ ucb1400_disable_irq(UCB_IRQ_TSPX, UCB_FALLING); -+ disable_irq(TS_IRQ); -+} -+ -+int ts_request_irq(u32 *irq, -+ void (*handler)(int, void *, struct pt_regs *), -+ const char *devname, -+ void *dev_id) -+{ -+ int retval; -+ -+ /* return the irq number */ -+ *irq = TS_IRQ; -+ -+ /* interrupt mode */ -+ ucb1400_ts_mode_int(); -+ ucb1400_enable_irq(UCB_IRQ_TSPX, UCB_FALLING); -+ -+ /* enable gpio irq */ -+ __gpio_as_irq_rise_edge(TS_PIN); -+ -+ /* register irq handler */ -+ retval = request_irq(TS_IRQ, handler, SA_INTERRUPT, devname, dev_id); -+ -+ return retval; -+} -+ -+void ts_free_irq(struct jz_ts_t *ts) -+{ -+ free_irq(ts->pendown_irq, ts); -+} -+ -+void ts_irq_callback(void) -+{ -+ /* clear interrupt status */ -+ ucb1400_reg_write(UCB_IE_CLEAR, ucb1400_reg_read(UCB_IE_STATUS)); -+ __gpio_ack_irq(TS_PIN); -+ -+ first_time = 1; // first time to acquire sample -+} -+ -+int PenIsDown(void) -+{ -+ unsigned int p; -+ -+ ucb1400_adc_enable(); -+ p = ucb1400_ts_read_pressure(); -+ ucb1400_adc_disable(); -+ -+ return (p > 100) ? 1 : 0; -+} -+ -+/* -+ * Acquire Raw pen coodinate data and compute touch screen -+ * pressure resistance. Hold spinlock when calling. -+ */ -+int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -+{ -+ unsigned int x_raw[8], y_raw[8], p_raw[8]; -+ int valid, i; -+ -+ /* Enable ADC */ -+ ucb1400_adc_enable(); -+ -+ for (i = 0; i < samples; i++) { -+ x_raw[i] = ucb1400_ts_read_xpos(); -+ } -+ for (i = 0; i < samples; i++) { -+ y_raw[i] = ucb1400_ts_read_ypos(); -+ } -+ for (i = 0; i < samples; i++) { -+ p_raw[i] = ucb1400_ts_read_pressure(); -+ } -+ -+ /* Disable ADC */ -+ ucb1400_adc_disable(); -+ -+ valid = calibrate_samples(x_raw, y_raw, p_raw, samples); -+ -+ if (valid) { -+ unsigned int x_scr, y_scr; -+ -+ if(ts->filter) { -+ x_scr = transform_to_screen_x(ts, x_raw[0]); -+ y_scr = transform_to_screen_y(ts, y_raw[0]); -+ -+ if (ts->prints) -+ printk("x_raw=%d y_raw=%d x_transform=%d y_transform=%d\n", x_raw[0], y_raw[0], x_scr, y_scr); -+ } -+ else { -+ x_scr = x_raw[0]; -+ y_scr = y_raw[0]; -+ -+ if (ts->prints) -+ printk("x_raw=%d y_raw=%d \n", x_raw[0], y_raw[0]); -+ } -+ -+ event->x = x_scr; -+ event->y = y_scr; -+ event->pressure = (u16)p_raw[0]; -+ event->status = PENDOWN; -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * Module init and exit -+ */ -+ -+int __init ucb1400_init(void) -+{ -+ ucb = kmalloc(sizeof(struct ucb1400), GFP_KERNEL); -+ if (!ucb) return -ENOMEM; -+ -+ memset(ucb, 0, sizeof(struct ucb1400)); -+ -+ codec_read_battery = ucb1400_read_battery; -+ -+ spin_lock_init(&ucb->lock); -+ sema_init(&ucb->adc_sem, 1); -+ -+ return 0; -+} -+ -+void ucb1400_cleanup(void) -+{ -+ kfree(ucb); -+} -+ -+module_init(ucb1400_init); -+module_exit(ucb1400_cleanup); -diff --git a/drivers/char/jzchar/ucb1400.h b/drivers/char/jzchar/ucb1400.h -new file mode 100644 -index 0000000..318c004 ---- /dev/null -+++ b/drivers/char/jzchar/ucb1400.h -@@ -0,0 +1,113 @@ -+#ifndef __UCB1400_H__ -+#define __UCB1400_H__ -+ -+/* ucb1400 aclink register mappings */ -+ -+#define UCB_IO_DATA 0x5a -+#define UCB_IO_DIR 0x5c -+#define UCB_IE_RIS 0x5e -+#define UCB_IE_FAL 0x60 -+#define UCB_IE_STATUS 0x62 -+#define UCB_IE_CLEAR 0x62 -+#define UCB_TS_CR 0x64 -+#define UCB_ADC_CR 0x66 -+#define UCB_ADC_DATA 0x68 -+#define UCB_ID 0x7e /* 7c is mfr id, 7e part id (from aclink spec) */ -+ -+#define UCB_ADC_DAT(x) ((x) & 0x3ff) -+ -+/* register bits */ -+ -+#define UCB_IO_0 (1 << 0) -+#define UCB_IO_1 (1 << 1) -+#define UCB_IO_2 (1 << 2) -+#define UCB_IO_3 (1 << 3) -+#define UCB_IO_4 (1 << 4) -+#define UCB_IO_5 (1 << 5) -+#define UCB_IO_6 (1 << 6) -+#define UCB_IO_7 (1 << 7) -+#define UCB_IO_8 (1 << 8) -+#define UCB_IO_9 (1 << 9) -+ -+#define UCB_IE_ADC (1 << 11) -+#define UCB_IE_TSPX (1 << 12) -+#define UCB_IE_TSMX (1 << 13) -+#define UCB_IE_TCLIP (1 << 14) -+#define UCB_IE_ACLIP (1 << 15) -+ -+#define UCB_IRQ_TSPX 12 -+ -+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ -+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */ -+ -+#define UCB_TC_B_VOICE_ENA (1 << 3) -+#define UCB_TC_B_CLIP (1 << 4) -+#define UCB_TC_B_ATT (1 << 6) -+#define UCB_TC_B_SIDE_ENA (1 << 11) -+#define UCB_TC_B_MUTE (1 << 13) -+#define UCB_TC_B_IN_ENA (1 << 14) -+#define UCB_TC_B_OUT_ENA (1 << 15) -+ -+#define UCB_AC_B_LOOP (1 << 8) -+#define UCB_AC_B_MUTE (1 << 13) -+#define UCB_AC_B_IN_ENA (1 << 14) -+#define UCB_AC_B_OUT_ENA (1 << 15) -+ -+#define UCB_TS_CR_TSMX_POW (1 << 0) -+#define UCB_TS_CR_TSPX_POW (1 << 1) -+#define UCB_TS_CR_TSMY_POW (1 << 2) -+#define UCB_TS_CR_TSPY_POW (1 << 3) -+#define UCB_TS_CR_TSMX_GND (1 << 4) -+#define UCB_TS_CR_TSPX_GND (1 << 5) -+#define UCB_TS_CR_TSMY_GND (1 << 6) -+#define UCB_TS_CR_TSPY_GND (1 << 7) -+#define UCB_TS_CR_MODE_INT (0 << 8) -+#define UCB_TS_CR_MODE_PRES (1 << 8) -+#define UCB_TS_CR_MODE_POS (2 << 8) -+#define UCB_TS_CR_BIAS_ENA (1 << 11) -+#define UCB_TS_CR_TSPX_LOW (1 << 12) -+#define UCB_TS_CR_TSMX_LOW (1 << 13) -+ -+#define UCB_ADC_SYNC_ENA (1 << 0) -+#define UCB_ADC_VREFBYP_CON (1 << 1) -+#define UCB_ADC_INP_TSPX (0 << 2) -+#define UCB_ADC_INP_TSMX (1 << 2) -+#define UCB_ADC_INP_TSPY (2 << 2) -+#define UCB_ADC_INP_TSMY (3 << 2) -+#define UCB_ADC_INP_AD0 (4 << 2) -+#define UCB_ADC_INP_AD1 (5 << 2) -+#define UCB_ADC_INP_AD2 (6 << 2) -+#define UCB_ADC_INP_AD3 (7 << 2) -+#define UCB_ADC_EXT_REF (1 << 5) -+#define UCB_ADC_START (1 << 7) -+#define UCB_ADC_ENA (1 << 15) -+ -+#define UCB_ADC_DAT_VAL (1 << 15) -+ -+#define UCB_ID_1200 0x1004 -+#define UCB_ID_1300 0x1005 -+#define UCB_ID_1400 0x4304 -+#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */ -+ -+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12) -+#define UCB_MODE_AUD_OFF_CAN (1 << 13) -+ -+/* -+ * Which edges of the IRQ do you want to control today? -+ */ -+#define UCB_RISING (1 << 0) -+#define UCB_FALLING (1 << 1) -+ -+/* Device data structure */ -+ -+struct ucb1400 { -+ spinlock_t lock; -+ struct pm_dev *pmdev; -+ struct semaphore adc_sem; -+ u16 adc_cr; -+ u16 irq_fal_enbl; -+ u16 irq_ris_enbl; -+ int irq_enabled; -+}; -+ -+#endif /* __UCB1400_H__ */ -diff --git a/drivers/char/jzchar/udc_hotplug.c b/drivers/char/jzchar/udc_hotplug.c -new file mode 100644 -index 0000000..1c3e576 ---- /dev/null -+++ b/drivers/char/jzchar/udc_hotplug.c -@@ -0,0 +1,451 @@ -+/* -+ * linux/drivers/char/jzchar/udc_hotplug.c -+ * -+ * New UDC hotplug driver. -+ * -+ * Copyright (C) 2007 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include "jzchars.h" -+ -+#ifndef GPIO_UDC_HOTPLUG -+#define GPIO_UDC_HOTPLUG 86 -+#endif -+ -+#define UDC_HOTPLUG_PIN GPIO_UDC_HOTPLUG -+#define UDC_HOTPLUG_IRQ (IRQ_GPIO_0 + UDC_HOTPLUG_PIN) -+ -+#define dprintk(x,...) -+ -+//simple meaning define -+#define NOT_CONNECT 0 -+#define YES_CONNECT 1 -+#define MAX_GPIO_TIME 50 -+ -+#define EVENT_USB_ADD 1 -+#define EVENT_USB_REMOVE 2 -+#define EVENT_POWER_ADD 3 -+#define EVENT_POWER_REMOVE 4 -+#define EVENT_POWER_TO_USB 5 -+#define EVENT_USB_SUSPEND_POWER 6 -+ -+struct udc_pnp_stat -+{ -+ char cable_stat, old_cable_stat; -+ char protl_stat, old_protl_stat; -+ char object_stat1; -+ char object_stat2; -+}; -+ -+static struct udc_pnp_stat cur_pnp_stat; -+ -+static struct file_operations cable_fops = { -+ owner: THIS_MODULE, -+}; -+ -+static struct miscdevice cable_dev= -+{ -+ 231, -+ "udc_cable", -+ &cable_fops -+}; -+ -+static struct file_operations power_fops = { -+ owner: THIS_MODULE, -+}; -+ -+static struct miscdevice power_dev= -+{ -+ 232, -+ "power_cable", -+ &power_fops -+}; -+ -+int jz_udc_active = 0; /* 0: Have no actions; 1: Have actions */ -+ -+static int udc_pin_level; -+static int udc_old_state; -+static int udc_pin_time; -+ -+static struct timer_list udc_long_timer, udc_gpio_timer; -+ -+/* Kernel thread to deliver event to user space */ -+static struct task_struct *kudcd_task; -+ -+static void udc_gpio_timer_routine(unsigned long data) -+{ -+ wake_up_process(kudcd_task); -+} -+ -+static void udc_long_timer_routine(unsigned long data) -+{ -+ dprintk("udc_timer\n"); -+ if (jz_udc_active) -+ udc_old_state = 1; -+ if (!jz_udc_active && udc_old_state) //udc irq timeout! do suspend -+ { -+ dprintk("udc suspend!\n"); -+ udc_old_state = 0; -+ cur_pnp_stat.protl_stat = NOT_CONNECT; -+ del_timer(&udc_long_timer); -+ wake_up_process(kudcd_task); -+ return; -+ } -+ jz_udc_active = 0; -+ udc_long_timer.expires = jiffies + 3 * HZ; /* about 3 s */ -+ add_timer(&udc_long_timer); -+} -+ -+static int udc_get_pnp_stat(void) -+{ -+ udc_pin_level = __gpio_get_pin(UDC_HOTPLUG_PIN); -+ udc_pin_time = 1; -+ -+ init_timer(&udc_gpio_timer); -+ del_timer(&udc_gpio_timer); -+ udc_gpio_timer.function = udc_gpio_timer_routine; -+ udc_gpio_timer.expires = jiffies + 1; /* about 10 ms */ -+ add_timer(&udc_gpio_timer); -+ -+ while(1) -+ { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule(); -+ -+ if (__gpio_get_pin(UDC_HOTPLUG_PIN) != udc_pin_level) -+ { -+ udc_pin_level = __gpio_get_pin(UDC_HOTPLUG_PIN); -+ udc_pin_time = 1; -+ dprintk("udc gpio detect restart! \n"); -+ } -+ -+ udc_pin_time ++; -+ if (udc_pin_time > MAX_GPIO_TIME) -+ break; -+ -+ del_timer(&udc_gpio_timer); -+ udc_gpio_timer.function = udc_gpio_timer_routine; -+ udc_gpio_timer.expires = jiffies + 1; /* about 10 ms */ -+ add_timer(&udc_gpio_timer); -+ } -+ -+ del_timer(&udc_gpio_timer); -+ if (__gpio_get_pin(UDC_HOTPLUG_PIN)) -+ return YES_CONNECT; -+ else -+ return NOT_CONNECT; -+} -+ -+static void udc_get_cable(void) -+{ -+ u32 intr_usb; -+ -+ __intc_mask_irq(IRQ_UDC); -+ -+ /* Now enable PHY to start detect */ -+#ifdef CONFIG_SOC_JZ4740 -+ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; -+#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+ REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE; -+#endif -+ /* Clear IRQs */ -+ REG16(USB_REG_INTRINE) = 0; -+ REG16(USB_REG_INTROUTE) = 0; -+ REG8(USB_REG_INTRUSBE) = 0; -+ -+ /* disable UDC IRQs first */ -+ REG16(USB_REG_INTRINE) = 0; -+ REG16(USB_REG_INTROUTE) = 0; -+ REG8(USB_REG_INTRUSBE) = 0; -+ -+ /* Disable DMA */ -+ REG32(USB_REG_CNTL1) = 0; -+ REG32(USB_REG_CNTL2) = 0; -+ -+ /* Enable HS Mode */ -+ REG8(USB_REG_POWER) |= USB_POWER_HSENAB; -+ /* Enable soft connect */ -+ REG8(USB_REG_POWER) |= USB_POWER_SOFTCONN; -+ -+ dprintk("enable phy! %x %x %x %x %x\n", -+ REG8(USB_REG_POWER), -+ REG_CPM_SCR, -+ REG16(USB_REG_INTRINE), -+ REG16(USB_REG_INTROUTE), -+ REG8(USB_REG_INTRUSBE)); -+ -+ init_timer(&udc_gpio_timer); -+ del_timer(&udc_gpio_timer); -+ udc_gpio_timer.function = udc_gpio_timer_routine; -+ udc_gpio_timer.expires = jiffies + 11; /* about 100 ms */ -+ add_timer(&udc_gpio_timer); -+ /* Sleep a short time to see result */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule(); -+ -+ del_timer(&udc_gpio_timer); -+ intr_usb = REG8(USB_REG_INTRUSB); -+ if ((intr_usb & USB_INTR_RESET) || -+ (intr_usb & USB_INTR_RESUME) || -+ (intr_usb & USB_INTR_SUSPEND)) -+ { -+ cur_pnp_stat.protl_stat = YES_CONNECT; -+ dprintk("cable is usb! \n"); -+ } -+ else -+ { -+ cur_pnp_stat.protl_stat = NOT_CONNECT; -+ dprintk("cable is power! \n"); -+ } -+ -+ /* Detect finish ,clean every thing */ -+ /* Disconnect from usb */ -+ REG8(USB_REG_POWER) &= ~USB_POWER_SOFTCONN; -+ /* Disable the USB PHY */ -+#ifdef CONFIG_SOC_JZ4740 -+ REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; -+#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+ REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE; -+#endif -+ /* Clear IRQs */ -+ REG16(USB_REG_INTRINE) = 0; -+ REG16(USB_REG_INTROUTE) = 0; -+ REG8(USB_REG_INTRUSBE) = 0; -+ __intc_ack_irq(IRQ_UDC); -+ __intc_unmask_irq(IRQ_UDC); -+} -+ -+static void send_event_udev(int event) -+{ -+ dprintk("Send udev message: cable=%d old=%d protl=%d old=%d \n", -+ cur_pnp_stat.cable_stat, -+ cur_pnp_stat.old_cable_stat, -+ cur_pnp_stat.protl_stat, -+ cur_pnp_stat.old_protl_stat); -+ -+ switch (event) -+ { -+ case EVENT_USB_ADD: -+ printk("usb cable insert! \n"); -+ misc_register(&cable_dev); -+ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_ADD); -+ init_timer(&udc_long_timer); -+ del_timer(&udc_long_timer); -+ udc_long_timer.function = udc_long_timer_routine; -+ udc_long_timer.expires = jiffies + 3 * HZ; /* about 3 s */ -+ add_timer(&udc_long_timer); -+ break; -+ case EVENT_USB_REMOVE: -+ printk("usb cable remove! \n"); -+ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_REMOVE); -+ misc_deregister(&cable_dev); -+ del_timer(&udc_long_timer); -+ break; -+ case EVENT_POWER_ADD: -+ printk("power cable insert! \n"); -+ misc_register(&power_dev); -+ kobject_uevent(&power_dev.this_device->kobj, KOBJ_ADD); -+ break; -+ case EVENT_POWER_REMOVE: -+ printk("power cable remove! \n"); -+ kobject_uevent(&power_dev.this_device->kobj, KOBJ_REMOVE); -+ misc_deregister(&power_dev); -+ break; -+ case EVENT_POWER_TO_USB: -+ printk("change power cable to usb! \n"); -+ kobject_uevent(&power_dev.this_device->kobj, KOBJ_REMOVE); -+ misc_deregister(&power_dev); -+ misc_register(&cable_dev); -+ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_ADD); -+ break; -+ case EVENT_USB_SUSPEND_POWER: -+ printk("usb cable suspend! \n"); -+ printk("as power cable insert! \n"); -+ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_REMOVE); -+ misc_deregister(&cable_dev); -+ misc_register(&power_dev); -+ kobject_uevent(&power_dev.this_device->kobj, KOBJ_ADD); -+ break; -+ }; -+} -+ -+static void udc_pnp_detect(void) -+{ -+ if (cur_pnp_stat.cable_stat == YES_CONNECT) /* already connected! */ -+ { -+ if (udc_get_pnp_stat() == NOT_CONNECT) -+ { -+ dprintk("cable real out! \n"); -+ cur_pnp_stat.cable_stat = NOT_CONNECT; -+ cur_pnp_stat.protl_stat = NOT_CONNECT; -+ /* Deliver this event to user space in udev model */ -+ if (cur_pnp_stat.old_protl_stat) -+ send_event_udev(EVENT_USB_REMOVE); -+ else -+ send_event_udev(EVENT_POWER_REMOVE); -+ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -+ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -+ } -+ else -+ { -+ if (cur_pnp_stat.old_protl_stat != cur_pnp_stat.protl_stat) -+ { -+ send_event_udev(EVENT_USB_SUSPEND_POWER); -+ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -+ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -+ } -+ else //change power to cable -+ { -+#if 0 //not support yet! -+ udc_get_cable(); -+ if (cur_pnp_stat.old_protl_stat != cur_pnp_stat.protl_stat) -+ send_event_udev(EVENT_POWER_TO_USB); -+ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -+ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -+#endif -+ } -+ } -+ } -+ else -+ { -+ if (udc_get_pnp_stat() == YES_CONNECT) -+ { -+ dprintk("cable real in! \n"); -+ cur_pnp_stat.cable_stat = YES_CONNECT; -+ udc_get_cable(); -+ /* Deliver this event to user space in udev model */ -+ if (cur_pnp_stat.protl_stat) -+ send_event_udev(EVENT_USB_ADD); -+ else -+ send_event_udev(EVENT_POWER_ADD); -+ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -+ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -+ } -+ else -+ dprintk("cable false in! \n"); -+ -+ } -+} -+ -+static void udc_pnp_set_gpio(void) -+{ -+ if (cur_pnp_stat.cable_stat == YES_CONNECT) -+ __gpio_as_irq_fall_edge(UDC_HOTPLUG_PIN); -+ else -+ __gpio_as_irq_rise_edge(UDC_HOTPLUG_PIN); -+ -+ /* clear interrupt pending status */ -+ __gpio_ack_irq(UDC_HOTPLUG_PIN); -+ /* unmask interrupt */ -+ __gpio_unmask_irq(UDC_HOTPLUG_PIN); -+} -+ -+static int udc_pnp_thread(void *unused) -+{ -+ printk(KERN_NOTICE "UDC starting pnp monitor thread\n"); -+ -+ while(1) -+ { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule(); -+ -+ dprintk("pnp thread wake up! \n"); -+ /* wake up here */ -+ udc_pnp_detect(); -+ /* Reset gpio state last */ -+ udc_pnp_set_gpio(); -+ } -+} -+ -+static irqreturn_t udc_pnp_irq(int irq, void *dev_id) -+{ -+ printk("udc_pnp_irq----\n"); -+ /* clear interrupt pending status */ -+ __gpio_ack_irq(UDC_HOTPLUG_PIN); -+ /* mask interrupt */ -+ __gpio_mask_irq(UDC_HOTPLUG_PIN); -+ /* wake up pnp detect thread */ -+ wake_up_process(kudcd_task); -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * Module init and exit -+ */ -+static int __init udc_hotplug_init(void) -+{ -+ int retval; -+ /* Init pnp stat first */ -+ cur_pnp_stat.cable_stat = NOT_CONNECT; -+ cur_pnp_stat.protl_stat = NOT_CONNECT; -+ cur_pnp_stat.old_cable_stat = NOT_CONNECT; -+ cur_pnp_stat.old_protl_stat = NOT_CONNECT; -+ cur_pnp_stat.object_stat1 = NOT_CONNECT; -+ cur_pnp_stat.object_stat2 = NOT_CONNECT; -+ udc_old_state = 0; -+ -+ /* create pnp thread and register IRQ */ -+ kudcd_task = kthread_run(udc_pnp_thread, NULL, "kudcd"); -+ if (IS_ERR(kudcd_task)) { -+ printk(KERN_ERR "jz_udc_hotplug: Failed to create system monitor thread.\n"); -+ return PTR_ERR(kudcd_task); -+ } -+ -+ retval = request_irq(UDC_HOTPLUG_IRQ, udc_pnp_irq, -+ IRQF_DISABLED, "udc_pnp", NULL); -+ if (retval) { -+ printk("Could not get udc hotplug irq %d\n", UDC_HOTPLUG_IRQ); -+ return retval; -+ } -+ -+ /* get current pin level */ -+ __gpio_disable_pull(UDC_HOTPLUG_PIN); -+ __gpio_as_input(UDC_HOTPLUG_PIN); -+ udelay(1); -+ udc_pin_level = __gpio_get_pin(UDC_HOTPLUG_PIN); -+ -+ if (udc_pin_level) { -+ dprintk("Cable already in! \n"); -+ /* Post a event */ -+ wake_up_process(kudcd_task); -+ } -+ else { -+ __gpio_as_irq_rise_edge(UDC_HOTPLUG_PIN); -+ dprintk("Cable not in! \n"); -+ } -+ -+ printk("JZ UDC hotplug driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit udc_hotplug_exit(void) -+{ -+ free_irq(UDC_HOTPLUG_IRQ, NULL); -+} -+ -+module_init(udc_hotplug_init); -+module_exit(udc_hotplug_exit); -+ -+EXPORT_SYMBOL(jz_udc_active); -+ -+MODULE_AUTHOR("Lucifer "); -+MODULE_DESCRIPTION("JzSOC OnChip udc hotplug driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/char/jzchar/wm9712.c b/drivers/char/jzchar/wm9712.c -new file mode 100644 -index 0000000..de75435 ---- /dev/null -+++ b/drivers/char/jzchar/wm9712.c -@@ -0,0 +1,334 @@ -+/* -+ * wm9712.c -+ * -+ * Touch screen driver interface to the Wolfson WM9712 codec. -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz_ts.h" -+#include "wm9712.h" -+ -+#define POLL_TIMES 10 -+ -+static int samples = 1; -+static int inited = 0, started = 0; -+ -+extern struct ac97_codec * find_ac97_codec(void); -+extern int PenIsDown(void); -+ -+ -+static inline void wm9712_reg_write(unsigned int reg, unsigned int val) -+{ -+ struct ac97_codec *codec = find_ac97_codec(); -+ if (!codec) -+ return; -+ codec->codec_write(codec, reg, val); -+} -+ -+static inline unsigned int wm9712_reg_read(unsigned int reg) -+{ -+ struct ac97_codec *codec = find_ac97_codec(); -+ if (!codec) -+ return 0; -+ return codec->codec_read(codec, reg); -+} -+ -+static unsigned int wm9712_adc_read(int adc_channel) -+{ -+ unsigned int val; -+ -+ if (!PenIsDown()) -+ return 0; -+ -+ val = wm9712_reg_read(DIGI_REG1); -+ wm9712_reg_write(DIGI_REG1, val|adc_channel|DIGI_REG1_POLL); -+ -+ for (;;) { -+ if (wm9712_reg_read(0x54) & (1 << 12)) { -+ val = wm9712_reg_read(DIGI_READBACK); -+ break; -+ } -+ } -+ -+ /* stop the measure */ -+ wm9712_reg_write(DIGI_REG1, 0); -+ -+ return (val & 0x0fff); -+} -+ -+static struct timer_list pndn_timer; -+static void (*irq_handler)(int, void *, struct pt_regs *) = NULL; -+ -+void ts_irq_callback(void) -+{ -+#ifdef TS_IRQ -+ __gpio_ack_irq(TS_IRQ); -+#else -+#endif -+} -+ -+void ts_enable_irq(void) -+{ -+ if (!inited) -+ return; -+#ifdef TS_IRQ -+ enable_irq(TS_IRQ); -+#else -+ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -+ add_timer(&pndn_timer); -+#endif -+} -+ -+void ts_disable_irq(void) -+{ -+ if (!inited) -+ return; -+#ifdef TS_IRQ -+ disable_irq(TS_IRQ); -+#endif -+} -+ -+#ifndef TS_IRQ -+static void pndn_detect(unsigned long data) -+{ -+ if (PenIsDown()) { -+ if (!started) -+ return; -+ if (irq_handler) -+ irq_handler(NULL, data, NULL); -+ } else { -+ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -+ add_timer(&pndn_timer); -+ } -+} -+#endif -+ -+void ts_free_irq(struct jz_ts_t *ts) -+{ -+#ifdef TS_IRQ -+ free_irq(ts->pendown_irq, ts); -+#else -+ started = 0; -+ del_timer_sync(&pndn_timer); -+#endif -+} -+ -+int ts_request_irq(u32 *irq, -+ void (*handler)(int, void *, struct pt_regs *), -+ const char *devname, -+ void *dev_id) -+{ -+ /* 4wire, Ip=400uA, Rpu=64Kohm/64, wake-up on pendown without -+ * reset, meassure on pen down. Do not use wait mode. -+ */ -+ started = 1; -+ if (!inited) { -+ wm9712_reg_write(DIGI_REG2, -+ DIGI_REG2_WIRE_4 | -+ DIGI_REG2_PIL_200uA | -+ (31 << DIGI_REG2_RPU_BIT) | -+ DIGI_REG2_PRP_ALLON | -+ DIGI_REG2_RPR_NWOR); -+ /* Polling mode and no measurement */ -+ wm9712_reg_write(DIGI_REG1, 0); -+ } -+ -+#ifdef TS_IRQ -+ /* Generate irq request on PENDOWN pin, pendown cause the level high */ -+ wm9712_reg_write(0x56, wm9712_reg_read(0x56) & ~(1 << 3)); -+ wm9712_reg_write(0x4c, wm9712_reg_read(0x4c) & ~(1 << 3)); -+ -+ *irq = TS_IRQ; -+ return request_irq(TS_IRQ, handler, SA_INTERRUPT, devname, dev_id); -+#else -+ if (!inited) { -+ irq_handler = handler; -+ init_timer(&pndn_timer); -+ pndn_timer.function = pndn_detect; -+ pndn_timer.data = (unsigned long)dev_id; -+ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -+ add_timer(&pndn_timer); -+ inited = 1; -+ } else { -+ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -+ add_timer(&pndn_timer); -+ } -+ return 0; -+#endif -+} -+ -+int PenIsDown(void) -+{ -+ if (wm9712_reg_read(DIGI_READBACK) & DIGI_READBACK_PNDN) -+ return 1; -+ return 0; -+} -+ -+#if defined(CONFIG_MIPS_JZ4730_GPS) -+#define adj_data(r1, r2, r3, s) \ -+do { \ -+ if (r1 < 0x90) \ -+ r1 = 0x90; \ -+ if (r2 < 0xed) \ -+ r2 = 0xed; \ -+ r1 = ((r1 - 0x90) * 240) / 3354; \ -+ r2 = ((r2 - 0xed) * 320) / 3671; \ -+ if (r1 > 239) \ -+ r1 = 239; \ -+ if (r2 > 319) \ -+ r2 = 319; \ -+ \ -+ *s = r2; \ -+ *(s+1) = 239 - r1; \ -+ *(s+2) = z_raw; \ -+} while (0) -+#endif -+ -+#ifndef adj_data -+#define adj_data(r1, r2, r3, s) -+#endif -+ -+static int read_adc(unsigned int *sdata) -+{ -+ unsigned long x_raw=0, y_raw=0, z_raw=0, t, fail = 0; -+ int i; -+ -+ for (i=0; i 1) { -+ x_raw = (x_raw + (samples>>1)) / samples; -+ y_raw = (y_raw + (samples>>1)) / samples; -+ z_raw = (z_raw + (samples>>1)) / samples; -+ } -+ -+ adj_data (x_raw, y_raw, z_raw, sdata); -+ -+ return 1; -+} -+ -+ -+#define TSMAXX 945 -+#define TSMAXY 830 -+#define TSMINX 90 -+#define TSMINY 105 -+ -+#define SCREEN_X 480 -+#define SCREEN_Y 272 -+ -+static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -+{ -+ -+ if (ts->minx) -+ { -+ if (x < ts->minx) x = ts->minx; -+ if (x > ts->maxx) x = ts->maxx; -+ -+ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -+ } -+ else -+ { -+ if (x < TSMINX) x = TSMINX; -+ if (x > TSMAXX) x = TSMAXX; -+ -+ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -+ } -+} -+ -+static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -+{ -+ if (ts->minx) -+ { -+ if (y < ts->minx) y = ts->miny; -+ if (y > ts->maxx) y = ts->maxy; -+ -+ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -+ } -+ else -+ { -+ if (y < TSMINX) y = TSMINY; -+ if (y > TSMAXX) y = TSMAXY; -+ -+ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -+ } -+} -+ -+ -+/* -+ * Acquire Raw pen coodinate data and compute touch screen -+ * pressure resistance. Hold spinlock when calling. -+ */ -+int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -+{ -+ unsigned int s[3]; -+ unsigned int x_scr, y_scr; -+ if (!read_adc(s)) -+ return 0; -+ if(ts->filter) { -+ x_scr = transform_to_screen_x(ts, s[0]); -+ y_scr = transform_to_screen_y(ts, s[1]); -+ -+ if (ts->prints) -+ printk("x_raw=%d y_raw=%d x_transform=%d y_transform=%d\n", s[0], s[1], x_scr, y_scr); } -+ else { -+ x_scr = s[0]; -+ y_scr = s[1]; -+ -+ if (ts->prints) -+ printk("x_raw=%d y_raw=%d \n", s[0], s[1]); -+ } -+ event->x = x_scr; -+ event->y = y_scr; -+ event->pressure = (u16)s[2]; -+ event->status = PENDOWN; -+ return 1; -+#if 0 -+ do_gettimeofday(&event->stamp); -+#endif -+} -+ -+int __init wm9712_init(void) -+{ -+ return 0; -+} -+ -+void wm9712_cleanup(void) -+{ -+} -+ -+module_init(wm9712_init); -+module_exit(wm9712_cleanup); -+ -diff --git a/drivers/char/jzchar/wm9712.h b/drivers/char/jzchar/wm9712.h -new file mode 100644 -index 0000000..7cd9e5c ---- /dev/null -+++ b/drivers/char/jzchar/wm9712.h -@@ -0,0 +1,58 @@ -+#ifndef __WM9712_H__ -+#define __WM9712_H__ -+ -+#define DIGI_REG1 0x76 -+#define DIGI_REG2 0x78 -+#define DIGI_READBACK 0x7A -+ -+#define ADCSEL_BIT 12 -+#define ADCSEL_MASK (7 << ADCSEL_BIT) -+#define ADCSEL_NONE (0 << ADCSEL_BIT) -+#define ADCSEL_XPOS (1 << ADCSEL_BIT) -+#define ADCSEL_YPOS (2 << ADCSEL_BIT) -+#define ADCSEL_PRESSURE (3 << ADCSEL_BIT) -+#define ADCSEL_COMP1 (4 << ADCSEL_BIT) -+#define ADCSEL_COMP2 (5 << ADCSEL_BIT) -+#define ADCSEL_BMON (6 << ADCSEL_BIT) -+#define ADCSEL_WIPER (7 << ADCSEL_BIT) -+ -+#define DIGI_REG1_CTC (1 << 10) -+#define DIGI_REG1_POLL (1 << 15) -+#define DIGI_REG1_CR_BIT 8 -+#define DIGI_REG1_CR_MASK (3 << DIGI_REG1_CR_BIT) -+#define DIGI_REG1_COO (1 << 11) -+#define DIGI_REG1_SLEN (1 << 3) -+#define DIGI_REG1_SLT_BIT 0 -+#define DIGI_REG1_SLT_MASK (7 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_5 (0 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_6 (1 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_7 (2 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_8 (3 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_9 (4 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_10 (5 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_11 (6 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_SLT_RES (7 << DIGI_REG1_SLT_BIT) -+#define DIGI_REG1_DEL_BIT 4 -+#define DIGI_REG1_DEL_MASK (0x0f << DIGI_REG1_DEL_BIT) -+ -+#define DIGI_REG2_WIRE_5 (1 << 12) -+#define DIGI_REG2_WIRE_4 (0 << 12) -+#define DIGI_REG2_RPU_BIT 0 -+#define DIGI_REG2_RPU_MASK (0x3f << DIGI_REG2_RPU_BIT) -+#define DIGI_REG2_PIL_400uA (1 << 8) -+#define DIGI_REG2_PIL_200uA (0 << 8) -+#define DIGI_REG2_PRP_BIT 14 -+#define DIGI_REG2_PRP_MASK (3 << DIGI_REG2_PRP_BIT) -+#define DIGI_REG2_PRP_ALLOFF (0 << DIGI_REG2_PRP_BIT) -+#define DIGI_REG2_PRP_WOP (1 << DIGI_REG2_PRP_BIT) -+#define DIGI_REG2_PRP_NWOP (2 << DIGI_REG2_PRP_BIT) -+#define DIGI_REG2_PRP_ALLON (3 << DIGI_REG2_PRP_BIT) -+#define DIGI_REG2_RPR_WOR (0 << 13) -+#define DIGI_REG2_RPR_NWOR (1 << 13) -+#define DIGI_REG2_PDEN (1 << 11) -+#define DIGI_REG2_WAIT (1 << 9) -+ -+#define DIGI_READBACK_PNDN (1 << 15) -+ -+#endif /* __WM9712_H__ */ -+ -diff --git a/drivers/char/rtc_jz.c b/drivers/char/rtc_jz.c -new file mode 100644 -index 0000000..55da710 ---- /dev/null -+++ b/drivers/char/rtc_jz.c -@@ -0,0 +1,503 @@ -+/* -+ * Jz OnChip Real Time Clock interface for Linux -+ * -+ * NOTE: we need to wait rtc write ready before read or write RTC registers. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include /* get the user-level API */ -+#include -+#include -+ -+#include "rtc_jz.h" -+ -+ -+char sbin_rtc_alarm_handler_path[] = "/sbin/rtcalarm"; -+//call_usermodehelper(char *path, char **argv, char **envp, int wait) -+//extern int call_usermodehelper(char *path, char **argv, char **envp); -+ -+extern spinlock_t rtc_lock; -+ -+static int rtc_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg); -+ -+ -+static void get_rtc_time (struct rtc_time *rtc_tm); -+static int set_rtc_time (struct rtc_time *rtc_tm); -+static void get_rtc_alm_time (struct rtc_time *alm_tm); -+static int set_rtc_alm_time (struct rtc_time *alm_tm); -+ -+static void set_rtc_irq_bit(int bit); -+static void mask_rtc_irq_bit(int bit); -+ -+static unsigned int rtc_status = 0; -+static unsigned int epoch = 1900; -+ -+static void get_rtc_time(struct rtc_time *rtc_tm) -+{ -+ unsigned long lval; -+ struct rtc_time ltm; -+ -+ spin_lock_irq(&rtc_lock); -+ while ( !__rtc_write_ready() ) ; -+ lval = REG_RTC_RSR; -+ rtc_time_to_tm(lval, <m); -+ if(rtc_valid_tm(<m) == 0) { -+ /* is valid */ -+ rtc_tm->tm_sec = ltm.tm_sec; -+ rtc_tm->tm_min = ltm.tm_min; -+ rtc_tm->tm_hour = ltm.tm_hour; -+ rtc_tm->tm_mday = ltm.tm_mday; -+ rtc_tm->tm_wday = ltm.tm_wday; -+ rtc_tm->tm_mon = ltm.tm_mon; -+ rtc_tm->tm_year = ltm.tm_year; -+ } else { -+ printk("invlaid data / time!\n"); -+ } -+ spin_unlock_irq(&rtc_lock); -+} -+ -+static int set_rtc_time(struct rtc_time *rtc_tm) -+{ -+ unsigned long lval; -+ -+ rtc_tm_to_time(rtc_tm, &lval); -+ -+ spin_lock_irq(&rtc_lock); -+ while ( !__rtc_write_ready() ) ; -+ REG_RTC_RSR = lval; -+ -+ spin_unlock_irq(&rtc_lock); -+ -+ return 0; -+ -+} -+ -+static void get_rtc_alm_time(struct rtc_time *alm_tm) -+{ -+ unsigned long lval; -+ struct rtc_time altm; -+ -+ spin_lock_irq(&rtc_lock); -+ while ( !__rtc_write_ready() ) ; -+ lval = REG_RTC_RSAR; -+ rtc_time_to_tm(lval, &altm); -+ if(rtc_valid_tm(&altm) == 0) { -+ /* is valid */ -+ alm_tm->tm_sec = altm.tm_sec; -+ alm_tm->tm_min = altm.tm_min; -+ alm_tm->tm_hour = altm.tm_hour; -+ alm_tm->tm_mday = altm.tm_mday; -+ alm_tm->tm_wday = altm.tm_wday; -+ alm_tm->tm_mon = altm.tm_mon; -+ alm_tm->tm_year = altm.tm_year; -+ } else { -+ printk("invlaid data / time in Line:%d!\n",__LINE__); -+ } -+ spin_unlock_irq(&rtc_lock); -+} -+ -+static int set_rtc_alm_time(struct rtc_time *alm_tm) -+{ -+ unsigned long lval; -+ -+ rtc_tm_to_time(alm_tm, &lval); -+ -+ spin_lock_irq(&rtc_lock); -+ while ( !__rtc_write_ready() ) ; -+ REG_RTC_RSAR = lval; -+ -+ while ( !__rtc_write_ready() ) ; /* set alarm function */ -+ if ( !((REG_RTC_RCR>>2) & 0x1) ) { -+ while ( !__rtc_write_ready() ) ; -+ __rtc_enable_alarm(); -+ } -+ -+ while ( !__rtc_write_ready() ) ; -+ if ( !(REG_RTC_RCR & RTC_RCR_AIE) ) { /* Enable alarm irq */ -+ __rtc_enable_alarm_irq(); -+ } -+ -+ spin_unlock_irq(&rtc_lock); -+ -+ return 0; -+} -+ -+static void get_rtc_wakeup_alarm(struct rtc_wkalrm *wkalm) -+{ -+ int enabled, pending; -+ -+ get_rtc_alm_time(&wkalm->time); -+ -+ spin_lock_irq(&rtc_lock); -+ while ( !__rtc_write_ready() ) ; -+ enabled = (REG_RTC_HWCR & 0x1); -+ pending = 0; -+ if ( enabled ) { -+ if ( (u32)REG_RTC_RSAR > (u32)REG_RTC_RSR ) /* 32bit val */ -+ pending = 1; -+ } -+ -+ wkalm->enabled = enabled; -+ wkalm->pending = pending; -+ spin_unlock_irq(&rtc_lock); -+} -+ -+static int set_rtc_wakeup_alarm(struct rtc_wkalrm *wkalm) -+{ -+ int enabled; -+ //int pending; -+ -+ enabled = wkalm->enabled; -+ //pending = wkalm->pending; /* Fix me, what's pending mean??? */ -+ -+ while ( !__rtc_write_ready() ) ; /* set wakeup alarm enable */ -+ if ( enabled != (REG_RTC_HWCR & 0x1) ) { -+ while ( !__rtc_write_ready() ) ; -+ REG_RTC_HWCR = (REG_RTC_HWCR & ~0x1) | enabled; -+ } -+ while ( !__rtc_write_ready() ) ; /* set alarm function */ -+ if ( enabled != ((REG_RTC_RCR>>2) & 0x1) ) { -+ while ( !__rtc_write_ready() ) ; -+ REG_RTC_RCR = (REG_RTC_RCR & ~(1<<2)) | (enabled<<2); -+ } -+ -+ if ( !enabled ) /* if disabled wkalrm, rturn. */ -+ { -+ return 0; -+ } -+ -+ while ( !__rtc_write_ready() ) ; -+ if ( !(REG_RTC_RCR & RTC_RCR_AIE) ) { /* Enable alarm irq */ -+ __rtc_enable_alarm_irq(); -+ } -+ -+ set_rtc_alm_time(&wkalm->time); -+ -+ return 0; -+} -+ -+ -+static void set_rtc_irq_bit( int bit ) -+{ -+ spin_lock_irq(&rtc_lock); -+ -+ while ( !__rtc_write_ready() ) ; -+ REG_RTC_RCR |= (1<= 0xc0 -+ * means "don't care" or "match all". Only the tm_hour, -+ * tm_min, and tm_sec values are filled in. -+ */ -+ -+ get_rtc_alm_time(&wtime); -+ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -+ -+ case RTC_ALM_SET: /* Store a time into the alarm */ -+ { -+ struct rtc_time alm_tm; -+ -+ if (copy_from_user(&alm_tm, (struct rtc_time*)arg, -+ sizeof(struct rtc_time))) -+ return -EFAULT; -+ if(rtc_valid_tm(&alm_tm) != 0) { -+ printk("invalid time set in Line:%d! \n",__LINE__); -+ return -EFAULT; -+ } -+ -+ return set_rtc_alm_time(&alm_tm); -+ } -+ case RTC_RD_TIME: /* Read the time/date from RTC */ -+ get_rtc_time(&wtime); -+ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -+ case RTC_SET_TIME: /* Set the RTC */ -+ { -+ struct rtc_time rtc_tm; -+ -+ if (!capable(CAP_SYS_TIME)) -+ return -EACCES; -+ -+ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, -+ sizeof(struct rtc_time))) -+ return -EFAULT; -+ if(rtc_valid_tm(&rtc_tm) != 0) { -+ printk("invalid time set in Line:%d! \n",__LINE__); -+ return -EFAULT; -+ } -+ -+ return set_rtc_time(&rtc_tm); -+ } -+ case RTC_EPOCH_READ: /* Read the epoch. */ -+ return put_user (epoch, (unsigned long *)arg); -+ case RTC_EPOCH_SET: /* Set the epoch. */ -+ /* -+ * There were no RTC clocks before 1900. -+ */ -+ if (arg < 1900) -+ return -EINVAL; -+ -+ if (!capable(CAP_SYS_TIME)) -+ return -EACCES; -+ -+ epoch = arg; -+ return 0; -+ case RTC_WKALM_SET: /* Wake alarm set. */ -+ { -+ struct rtc_wkalrm wkalrm; -+ -+ if (copy_from_user(&wkalrm, (struct rtc_wkalrm*)arg, -+ sizeof(struct rtc_wkalrm))) -+ return -EFAULT; -+ return set_rtc_wakeup_alarm(&wkalrm); -+ } -+ case RTC_WKALM_RD: /* Wake alarm read. */ -+ { -+ struct rtc_wkalrm wkalrm; -+ get_rtc_wakeup_alarm(&wkalrm); -+ return copy_to_user((void *)arg, &wkalrm, sizeof(struct rtc_wkalrm)) ? -EFAULT : 0; -+ } -+ /* set power down: shut down the machine. */ -+ case RTC_POWER_DOWN: /* enter HIBERNATE mode */ -+ dprintk("Power down. Bye....\n"); -+ while ( !__rtc_write_ready() ) ; -+ REG_RTC_HCR = 0x1; -+ return 0; -+#ifdef DEBUG -+ case RTC_PRINT_REG: /* Print RTC registers */ -+ print_rtc_registers(); -+ return 0; -+#endif -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+/* -+ * We enforce only one user at a time here with the open/close. -+ * Also clear the previous interrupt data on an open, and clean -+ * up things on a close. -+ */ -+ -+/* We use rtc_lock to protect against concurrent opens. So the BKL is not -+ * needed here. Or anywhere else in this driver. */ -+static int rtc_open(struct inode *inode, struct file *file) -+{ -+ spin_lock_irq (&rtc_lock); -+ -+ if(rtc_status) -+ goto out_busy; -+ -+ rtc_status = 1; -+ -+ spin_unlock_irq (&rtc_lock); -+ return 0; -+ -+out_busy: -+ return -EBUSY; -+} -+ -+static int rtc_release(struct inode *inode, struct file *file) -+{ -+ -+ rtc_status = 0; -+ /* No need for locking -- nobody else can do anything until this rmw is -+ * committed, and no timer is running. */ -+ return 0; -+} -+ -+/* -+ * The various file operations we support. -+ */ -+ -+static struct file_operations rtc_fops = { -+ owner: THIS_MODULE, -+ llseek: no_llseek, -+ ioctl: rtc_ioctl, -+ open: rtc_open, -+ release: rtc_release, -+}; -+ -+ -+static void run_sbin_rtc_alarm( void ) -+{ -+ int i; -+ char *argv[2], *envp[3]; -+ -+ if (!sbin_rtc_alarm_handler_path[0]) -+ return; -+ -+ print_dbg(": sbin_rtc_alarm_handler_path=%s\n", sbin_rtc_alarm_handler_path); -+ -+ i = 0; -+ argv[i++] = sbin_rtc_alarm_handler_path; -+ argv[i] = 0; -+ -+ /* minimal command environment */ -+ i = 0; -+ envp[i++] = "HOME=/"; -+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; -+ -+ /* other stuff we want to pass to /sbin/hotplug */ -+ -+ envp[i] = 0; -+ -+ call_usermodehelper (argv [0], argv, envp, 0); -+} -+ -+static void rtc_alarm_task_handler(struct work_struct *work) -+{ -+ run_sbin_rtc_alarm(); -+} -+ -+static struct work_struct rtc_alarm_task; -+ -+static irqreturn_t jz_rtc_interrupt(int irq, void *dev_id) -+{ -+ REG_RTC_HCR = 0x0; -+ printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__); -+ spin_lock_irq(&rtc_lock); -+ -+ if ( __rtc_get_1Hz_flag() ) { -+ while ( !__rtc_write_ready() ) ; -+ __rtc_clear_1Hz_flag(); -+ dprintk("RTC 1Hz interrupt occur.\n"); -+ } -+ -+ if ( __rtc_get_alarm_flag() ) { /* rtc alarm interrupt */ -+ while ( !__rtc_write_ready() ) ; -+ __rtc_clear_alarm_flag(); -+ dprintk("RTC alarm interrupt occur.\n"); -+ //schedule_task( &rtc_alarm_task ); -+ schedule_work( &rtc_alarm_task ); -+ } -+ spin_unlock_irq(&rtc_lock); -+ -+ return IRQ_HANDLED; -+} -+ -+ -+#define RTC_MINOR 135 -+ -+static struct miscdevice rtc_dev= -+{ -+ RTC_MINOR, -+ "rtc", -+ &rtc_fops -+}; -+ -+int __init Jz_rtc_init(void) -+{ -+ -+ INIT_WORK(&rtc_alarm_task, rtc_alarm_task_handler); -+ -+ /* Enabled rtc function, enable rtc alarm function */ -+ while ( !__rtc_write_ready() ) ; /* need we wait for WRDY??? */ -+ if ( !(REG_RTC_RCR & RTC_RCR_RTCE) || !(REG_RTC_RCR &RTC_RCR_AE) ) { -+ REG_RTC_RCR |= RTC_RCR_AE | RTC_RCR_RTCE; -+ } -+ /* clear irq flags */ -+ __rtc_clear_1Hz_flag(); -+ /* In a alarm reset, we expect a alarm interrupt. -+ * We can do something in the interrupt handler. -+ * So, do not clear alarm flag. -+ */ -+/* __rtc_clear_alarm_flag(); */ -+ -+ if (request_irq(IRQ_RTC, jz_rtc_interrupt, 0, "rtc", NULL) < 0) -+ return -EBUSY; -+ -+ misc_register(&rtc_dev); -+ -+ printk("JzSOC onchip RTC installed !!!\n"); -+ return 0; -+ -+} -+ -+void __exit Jz_rtc_exit (void) -+{ -+ misc_deregister(&rtc_dev); -+ free_irq (IRQ_RTC, NULL); -+} -+ -+module_init(Jz_rtc_init); -+module_exit(Jz_rtc_exit); -+ -diff --git a/drivers/char/rtc_jz.h b/drivers/char/rtc_jz.h -new file mode 100644 -index 0000000..6c754d6 ---- /dev/null -+++ b/drivers/char/rtc_jz.h -@@ -0,0 +1,74 @@ -+#ifndef __RTC_JZ_H__ -+#define __RTC_JZ_H__ -+ -+//#define DEBUG 1 -+#undef DEBUG -+ -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#define print_dbg(f, arg...) \ -+ printk("%s, %s[%d]:" f , __FUNCTION__, __FILE__, __LINE__ , ##arg ) -+#else -+#define dprintk(x...) -+#define print_dbg(n, arg...) -+#endif -+ -+ -+#ifdef DEBUG -+ -+static void print_rtc_time( struct rtc_time * tm ) -+{ -+ printk("%02d%02d-%02d:%02d:%02d-%d\n", tm->tm_mon, tm->tm_mday, -+ tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year); -+ printk("sec:\t%d\n", tm->tm_sec); -+ printk("min:\t%d\n", tm->tm_min); -+ printk("hour:\t%d\n", tm->tm_hour); -+ printk("mday:\t%d\n", tm->tm_mday); -+ printk("mon:\t%d\n", tm->tm_mon); -+ printk("year:\t%d\n", tm->tm_year); -+ printk("wday:\t%d\n", tm->tm_wday); -+ printk("yday:\t%d\n", tm->tm_yday); -+ printk("isdst:\t%d\n", tm->tm_isdst); -+ -+} -+ -+static void print_rtc_registers( void ) -+{ -+ while ( !__rtc_write_ready() ) ; -+ printk("REG_RTC_RCR:\t 0x%8.8x\n", REG_RTC_RCR ); -+ printk("REG_RTC_RSR:\t 0x%8.8x\n", REG_RTC_RSR ); -+ printk("REG_RTC_RSAR:\t 0x%8.8x\n", REG_RTC_RSAR ); -+ printk("REG_RTC_RGR:\t 0x%8.8x\n", REG_RTC_RGR ); -+ printk("REG_RTC_HCR:\t 0x%8.8x\n", REG_RTC_HCR ); -+ printk("REG_RTC_HWFCR:\t 0x%8.8x\n", REG_RTC_HWFCR ); -+ printk("REG_RTC_HRCR:\t 0x%8.8x\n", REG_RTC_HRCR ); -+ printk("REG_RTC_HWCR:\t 0x%8.8x\n", REG_RTC_HWCR ); -+ printk("REG_RTC_HWRSR:\t 0x%8.8x\n", REG_RTC_HWRSR ); -+ printk("REG_RTC_HSPR:\t 0x%8.8x\n", REG_RTC_HSPR ); -+} -+ -+#define RTC_PRINT_REG _IOR('p', 0x12, unsigned long)/* Set power down */ -+#endif /* #ifdef DEBUG */ -+ -+ -+/* -+ * JZSOC ioctl calls that are permitted to the /dev/rtc interface -+ */ -+ -+#define RTC_ENABLED _IO('p', 0x11) /* enable rtc */ -+#define RTC_DISABLED _IO('p', 0x12) /* disable rtc */ -+#define RTC_ALM_ON _IO('p', 0x13) /* enable rtc */ -+#define RTC_ALM_OFF _IO('p', 0x14) /* disable rtc */ -+#define RTC_1HZIE_ON _IO('p', 0x15) /* 1Hz int. enable on */ -+#define RTC_1HZIE_OFF _IO('p', 0x16) /* ... off */ -+ -+#define RTC_POWER_DOWN _IOR('p', 0x11, unsigned long)/* Set power down */ -+ -+/* Registers define */ -+/* RTC Control register */ -+#define RTC_AIE 3 /* jz4740_06_rtc_spec.pdf, RTC Control Register */ -+#define RTC_1HZIE 5 /* ... */ -+#define RTC_ALM_EN 2 /* ... */ -+#define RTC_EN 0 /* ... */ -+ -+#endif /* #define __RTC_JZ_H__ */ -diff --git a/drivers/char/rtc_pcf8563.c b/drivers/char/rtc_pcf8563.c -new file mode 100644 -index 0000000..08dc30b ---- /dev/null -+++ b/drivers/char/rtc_pcf8563.c -@@ -0,0 +1,448 @@ -+/* -+ * PCF8563 Real Time Clock interface for Linux -+ * -+ * It only support 24Hour Mode, And the stored values are in BCD format. -+ * The alarm register is start at minute reg, no second alarm register. -+ */ -+ -+//#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include /* get the user-level API */ -+#include -+#include -+ -+/********************************************************************** -+ * register summary -+ **********************************************************************/ -+#define RTC_SECONDS 2 -+#define RTC_MINUTES 3 -+#define RTC_HOURS 4 -+#define RTC_DAY_OF_MONTH 5 -+#define RTC_DAY_OF_WEEK 6 -+#define RTC_MONTH 7 -+#define RTC_YEAR 8 -+ -+#define RTC_MINUTES_ALARM 9 -+#define RTC_HOURS_ALARM 0x0a -+#define RTC_DAY_ALARM 0x0b -+#define RTC_WEEKDAY_ALARM 0x0c -+ -+/* control registers - Moto names -+ */ -+#define RTC_CONTROL 0x00 -+#define RTC_STATUS 0x01 -+#define RTC_CLKOUT 0x0d -+#define RTC_TIMERCTL 0x0e -+#define RTC_TIMERCOUNTDOWN 0x0f -+ -+ -+/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) -+ * determines if the following two #defines are needed -+ */ -+#ifndef BCD2BIN -+#define BCD2BIN(val) (((val) & 0x0f) + ((val) >> 4) * 10) -+#endif -+ -+#ifndef BIN2BCD -+#define BIN2BCD(val) ((((val) / 10) << 4) + (val) % 10) -+#endif -+ -+extern spinlock_t rtc_lock; -+extern void i2c_open(void); -+extern void i2c_close(void); -+extern int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+extern int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+/* -+ * We sponge a minor off of the misc major. No need slurping -+ * up another valuable major dev number for this. If you add -+ * an ioctl, make sure you don't conflict with SPARC's RTC -+ * ioctls. -+ */ -+ -+static int rtc_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg); -+ -+ -+static void get_rtc_time (struct rtc_time *rtc_tm); -+static void get_rtc_alm_time (struct rtc_time *alm_tm); -+ -+/* -+ * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is -+ * protected by the big kernel lock. However, ioctl can still disable the timer -+ * in rtc_status and then with del_timer after the interrupt has read -+ * rtc_status but before mod_timer is called, which would then reenable the -+ * timer (but you would need to have an awful timing before you'd trip on it) -+ */ -+static unsigned long rtc_status = 0; /* bitmapped status byte. */ -+ -+/* -+ * If this driver ever becomes modularised, it will be really nice -+ * to make the epoch retain its value across module reload... -+ */ -+static unsigned int epoch = 1900; -+static const unsigned char days_in_mo[] = -+{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -+ -+static unsigned char rtcframe[16]; -+ -+static void read_rtcframe(void) -+{ -+ i2c_open(); -+ i2c_read(0x51, rtcframe, 0, 16); -+ i2c_close(); -+} -+ -+static void write_rtcframe(void) -+{ -+ i2c_open(); -+ i2c_write(0x51, rtcframe, 0, 16); -+ i2c_close(); -+} -+ -+static void write_rtc(unsigned char addr, unsigned char val) -+{ -+ volatile unsigned char v = val; -+ i2c_open(); -+ i2c_write(0x51, (unsigned char *)&v, addr, 1); -+ i2c_close(); -+} -+ -+static unsigned char read_rtc(unsigned char addr) -+{ -+ volatile unsigned char v; -+ i2c_open(); -+ i2c_read(0x51, (unsigned char *)&v, addr, 1); -+ i2c_close(); -+ return v; -+} -+ -+static void CMOS_WRITE(unsigned char addr, unsigned char val) -+{ -+ rtcframe[addr] = val; -+} -+ -+static unsigned char CMOS_READ(unsigned char addr) -+{ -+ return rtcframe[addr]; -+} -+ -+static void get_rtc_time(struct rtc_time *rtc_tm) -+{ -+ unsigned char sec,mon,mday,wday,year,hour,min; -+ -+ /* -+ * Only the values that we read from the RTC are set. We leave -+ * tm_wday, tm_yday and tm_isdst untouched. Even though the -+ * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated -+ * by the RTC when initially set to a non-zero value. -+ */ -+ -+ spin_lock_irq(&rtc_lock); -+ read_rtcframe(); -+ sec = CMOS_READ(RTC_SECONDS) & ~0x80; -+ min = CMOS_READ(RTC_MINUTES) & ~0x80; -+ hour = CMOS_READ(RTC_HOURS) & ~0xc0; -+ mday = CMOS_READ(RTC_DAY_OF_MONTH) & ~0xc0; -+ wday = CMOS_READ(RTC_DAY_OF_WEEK) & ~0xf8; -+ mon = CMOS_READ(RTC_MONTH) & ~0xe0; -+ year = CMOS_READ(RTC_YEAR) ; -+ -+ rtc_tm->tm_sec = BCD2BIN(sec); -+ rtc_tm->tm_min = BCD2BIN(min); -+ rtc_tm->tm_hour = BCD2BIN(hour); -+ rtc_tm->tm_mday = BCD2BIN(mday); -+ rtc_tm->tm_wday = wday; -+ /* Don't use centry, but start from year 1970 */ -+ rtc_tm->tm_mon = BCD2BIN(mon); -+ year = BCD2BIN(year); -+ if ((year += (epoch - 1900)) <= 69) -+ year += 100; -+ rtc_tm->tm_year = year; -+ -+ spin_unlock_irq(&rtc_lock); -+ -+ -+ /* -+ * Account for differences between how the RTC uses the values -+ * and how they are defined in a struct rtc_time; -+ */ -+ rtc_tm->tm_mon--; -+} -+ -+static void get_rtc_alm_time(struct rtc_time *alm_tm) -+{ -+ unsigned char sec, min, hour; -+ -+ /* -+ * Only the values that we read from the RTC are set. That -+ * means only tm_hour, tm_min, and tm_sec. -+ */ -+ spin_lock_irq(&rtc_lock); -+ read_rtcframe(); -+ sec = 0; -+ min = CMOS_READ(RTC_MINUTES_ALARM); -+ hour = CMOS_READ(RTC_HOURS_ALARM); -+ -+ alm_tm->tm_sec = sec;//not set sec -+ alm_tm->tm_min = BCD2BIN(min); -+ alm_tm->tm_hour = BCD2BIN(hour); -+ -+ spin_unlock_irq(&rtc_lock); -+} -+ -+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ struct rtc_time wtime; -+ switch (cmd) { -+ case RTC_ALM_READ: /* Read the present alarm time */ -+ { -+ /* -+ * This returns a struct rtc_time. Reading >= 0xc0 -+ * means "don't care" or "match all". Only the tm_hour, -+ * tm_min, and tm_sec values are filled in. -+ */ -+ -+ get_rtc_alm_time(&wtime); -+ break; -+ } -+ case RTC_ALM_SET: /* Store a time into the alarm */ -+ { -+ unsigned char hrs, min, sec; -+ struct rtc_time alm_tm; -+ -+ if (copy_from_user(&alm_tm, (struct rtc_time*)arg, -+ sizeof(struct rtc_time))) -+ return -EFAULT; -+ -+ hrs = alm_tm.tm_hour; -+ min = alm_tm.tm_min; -+ sec = alm_tm.tm_sec; -+ -+ -+ -+ if (hrs >= 24) -+ return -EINVAL; -+ -+ hrs = BIN2BCD(hrs); -+ -+ if (min >= 60) -+ return -EINVAL; -+ -+ min = BIN2BCD(min); -+ -+ if (sec >= 60) -+ return -EINVAL; -+ -+ spin_lock_irq(&rtc_lock); -+ read_rtcframe(); -+ CMOS_WRITE(RTC_HOURS_ALARM, hrs | 0x80); -+ CMOS_WRITE(RTC_MINUTES_ALARM, min | 0x80); -+ -+ CMOS_WRITE(RTC_DAY_ALARM, CMOS_READ(RTC_DAY_ALARM) | 0x80); -+ CMOS_WRITE(RTC_WEEKDAY_ALARM, CMOS_READ(RTC_WEEKDAY_ALARM) | 0x80); -+ CMOS_WRITE(RTC_STATUS, CMOS_READ(RTC_STATUS) | 0x02);/*open alarm int*/ -+ write_rtcframe(); -+ spin_unlock_irq(&rtc_lock); -+ break; -+ } -+ case RTC_RD_TIME: /* Read the time/date from RTC */ -+ { -+ get_rtc_time(&wtime); -+ break; -+ } -+ case RTC_SET_TIME: /* Set the RTC */ -+ { -+ struct rtc_time rtc_tm; -+ unsigned char mon, day, hrs, min, sec, leap_yr, date; -+ unsigned int yrs; -+// unsigned char ctr; -+ -+ if (!capable(CAP_SYS_TIME)) -+ return -EACCES; -+ -+ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, -+ sizeof(struct rtc_time))) -+ return -EFAULT; -+ -+ -+ yrs = rtc_tm.tm_year + 1900; -+ mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ -+ day = rtc_tm.tm_wday; -+ date = rtc_tm.tm_mday; -+ hrs = rtc_tm.tm_hour; -+ min = rtc_tm.tm_min; -+ sec = rtc_tm.tm_sec; -+ -+ -+ if (yrs < 1970) -+ return -EINVAL; -+ -+ leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); -+ -+ if ((mon > 12) || (date == 0)) -+ return -EINVAL; -+ -+ if (date > (days_in_mo[mon] + ((mon == 2) && leap_yr))) -+ return -EINVAL; -+ -+ if ((hrs >= 24) || (min >= 60) || (sec >= 60)) -+ return -EINVAL; -+ -+ if ((yrs -= epoch) > 255) /* They are unsigned */ -+ return -EINVAL; -+ -+ spin_lock_irq(&rtc_lock); -+ /* These limits and adjustments are independant of -+ * whether the chip is in binary mode or not. -+ */ -+ if (yrs > 169) { -+ spin_unlock_irq(&rtc_lock); -+ return -EINVAL; -+ } -+ -+ if (yrs >= 100) -+ yrs -= 100; -+ -+ min = BIN2BCD(min); -+ sec = BIN2BCD(sec); -+ hrs = BIN2BCD(hrs); -+ mon = BIN2BCD(mon); -+ yrs = BIN2BCD(yrs); -+ date = BIN2BCD(date); -+ -+ read_rtcframe(); -+ CMOS_WRITE(RTC_SECONDS, sec ); -+ CMOS_WRITE(RTC_MINUTES, min); -+ CMOS_WRITE(RTC_HOURS, hrs); -+ CMOS_WRITE(RTC_DAY_OF_MONTH, date); -+ CMOS_WRITE(RTC_DAY_OF_WEEK, day); -+ CMOS_WRITE(RTC_MONTH, mon); -+ CMOS_WRITE(RTC_YEAR, yrs); -+ write_rtcframe(); -+ -+ spin_unlock_irq(&rtc_lock); -+ return 0; -+ } -+ case RTC_EPOCH_READ: /* Read the epoch. */ -+ { -+ return put_user (epoch, (unsigned long *)arg); -+ } -+ case RTC_EPOCH_SET: /* Set the epoch. */ -+ { -+ /* -+ * There were no RTC clocks before 1900. -+ */ -+ if (arg < 1900) -+ return -EINVAL; -+ -+ if (!capable(CAP_SYS_TIME)) -+ return -EACCES; -+ -+ epoch = arg; -+ return 0; -+ } -+ default: -+ return -EINVAL; -+ } -+ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -+} -+ -+/* -+ * We enforce only one user at a time here with the open/close. -+ * Also clear the previous interrupt data on an open, and clean -+ * up things on a close. -+ */ -+ -+/* We use rtc_lock to protect against concurrent opens. So the BKL is not -+ * needed here. Or anywhere else in this driver. */ -+static int rtc_open(struct inode *inode, struct file *file) -+{ -+ spin_lock_irq (&rtc_lock); -+ -+ if(rtc_status) -+ goto out_busy; -+ -+ rtc_status = 1; -+ -+ spin_unlock_irq (&rtc_lock); -+ return 0; -+ -+out_busy: -+ spin_unlock_irq (&rtc_lock); -+ return -EBUSY; -+} -+ -+static int rtc_release(struct inode *inode, struct file *file) -+{ -+ -+ -+ /* No need for locking -- nobody else can do anything until this rmw is -+ * committed, and no timer is running. */ -+ rtc_status = 0; -+ return 0; -+} -+ -+/* -+ * The various file operations we support. -+ */ -+ -+static struct file_operations rtc_fops = { -+ owner: THIS_MODULE, -+ llseek: no_llseek, -+ ioctl: rtc_ioctl, -+ open: rtc_open, -+ release: rtc_release, -+}; -+ -+#define RTC_MINOR 135 -+ -+static struct miscdevice rtc_dev= -+{ -+ RTC_MINOR, -+ "rtc", -+ &rtc_fops -+}; -+ -+int __init pcf_rtc_init(void) -+{ -+ int r; -+ unsigned char ctr; -+ r = misc_register(&rtc_dev); -+ -+ ctr = read_rtc(RTC_CONTROL); -+ write_rtc(RTC_CONTROL,0x00 ); -+ -+ read_rtcframe(); -+ CMOS_WRITE(RTC_STATUS, 0x00); -+ CMOS_WRITE(RTC_CLKOUT, 0x80); -+ /* RTC clock out, 32.768k */ -+ -+ CMOS_WRITE(RTC_TIMERCTL, 0x00); -+ CMOS_WRITE(RTC_TIMERCOUNTDOWN, 0x00); -+ write_rtcframe(); -+ -+ printk("PCF8563 RTC installed !!!\n"); -+ return 0; -+ -+} -+ -+void __exit pcf_rtc_exit (void) -+{ -+ misc_deregister(&rtc_dev); -+} -+ -+module_init(pcf_rtc_init); -+module_exit(pcf_rtc_exit); -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 8206442..d704743 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -7,6 +7,14 @@ menu "I2C Hardware Bus support" - comment "PC SMBus host controller drivers" - depends on PCI - -+config I2C_JZ47XX -+ tristate "JZ47XX I2C Interface support" -+ depends on SOC_JZ4730 || SOC_JZ4740 -+ help -+ If you have devices in the Ingenic JZ4730/JZ4740 I2C bus, say yes to -+ this option. This driver can also be built as a module. If so, the -+ module will be called i2c-jz47xx. -+ - config I2C_ALI1535 - tristate "ALI 1535" - depends on PCI -diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index e654263..73960cd 100644 ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -37,6 +37,7 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o - obj-$(CONFIG_I2C_IMX) += i2c-imx.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_OCORES) += i2c-ocores.o -diff --git a/drivers/i2c/busses/i2c-jz47xx.c b/drivers/i2c/busses/i2c-jz47xx.c -new file mode 100644 -index 0000000..16f947e ---- /dev/null -+++ b/drivers/i2c/busses/i2c-jz47xx.c -@@ -0,0 +1,330 @@ -+/* -+ * i2c_jz47xx.c -+ * I2C adapter for the INGENIC I2C bus access. -+ * -+ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include "i2c-jz47xx.h" -+ -+/* I2C protocol */ -+#define I2C_READ 1 -+#define I2C_WRITE 0 -+ -+#define TIMEOUT 1000 -+unsigned short sub_addr = 0; -+int addr_val = 0; -+struct jz_i2c { -+ spinlock_t lock; -+ wait_queue_head_t wait; -+ struct i2c_msg *msg; -+ unsigned int msg_num; -+ unsigned int slave_addr; -+ struct i2c_adapter adap; -+ struct clk *clk; -+}; -+ -+/* -+ * I2C bus protocol basic routines -+ */ -+static int i2c_put_data(unsigned char data) -+{ -+ unsigned int timeout = TIMEOUT*10; -+ -+ __i2c_write(data); -+ __i2c_set_drf(); -+ while (__i2c_check_drf() != 0); -+ while (!__i2c_transmit_ended()); -+ while (!__i2c_received_ack() && timeout) -+ timeout--; -+ -+ if (timeout) -+ return 0; -+ else -+ return -ETIMEDOUT; -+} -+ -+static int i2c_get_data(unsigned char *data, int ack) -+{ -+ int timeout = TIMEOUT*10; -+ -+ if (!ack) -+ __i2c_send_nack(); -+ else -+ __i2c_send_ack(); -+ -+ while (__i2c_check_drf() == 0 && timeout) -+ timeout--; -+ -+ if (timeout) { -+ if (!ack) -+ __i2c_send_stop(); -+ *data = __i2c_read(); -+ __i2c_clear_drf(); -+ return 0; -+ } else -+ return -ETIMEDOUT; -+} -+ -+/* -+ * I2C interface -+ */ -+void i2c_jz_setclk(unsigned int i2cclk) -+{ -+ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -+} -+ -+static int xfer_read(unsigned char device, struct i2c_adapter *adap, unsigned char *buf, int length) -+{ -+ int cnt = length; -+ int timeout = 5; -+ -+ device = (0xa << 3) | ((sub_addr & 0x0700) >> 8); -+ sub_addr = sub_addr & 0xff; -+ -+L_try_again: -+ -+ if (timeout < 0) -+ goto L_timeout; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ -+ if (addr_val) { -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_werr; -+ if (i2c_put_data(sub_addr) < 0) -+ goto address_err; -+ } -+ __i2c_send_start(); -+ -+ if (i2c_put_data((device << 1) | I2C_READ ) < 0) -+ goto device_rerr; -+ -+ __i2c_send_ack(); /* Master sends ACK for continue reading */ -+ __i2c_send_start(); -+ -+ while (cnt) { -+ if (cnt == 1) { -+ if (i2c_get_data(buf, 0) < 0) -+ break; -+ } else { -+ if (i2c_get_data(buf, 1) < 0) -+ break; -+ } -+ cnt--; -+ buf++; -+ } -+ addr_val = 0; -+ return length - cnt; -+ device_rerr: -+ device_werr: -+ address_err: -+ timeout --; -+ __i2c_send_stop(); -+ goto L_try_again; -+ -+L_timeout: -+ __i2c_send_stop(); -+ printk("Read I2C device 0x%2x failed.\n", device); -+ return -ENODEV; -+} -+ -+static int xfer_write(unsigned char device, struct i2c_adapter *adap, unsigned char *buf, int length) -+{ -+ int cnt = length; -+ int cnt_in_pg; -+ int timeout = 5; -+ unsigned char *tmpbuf; -+ unsigned char tmpaddr; -+ -+ device = (0xa << 3) | ((sub_addr & 0x0700) >> 8); -+ sub_addr = sub_addr & 0xff; -+ -+ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -+ -+ W_try_again: -+ if (timeout < 0) -+ goto W_timeout; -+ -+ cnt = length; -+ tmpbuf = (unsigned char *)buf; -+ tmpaddr = device; -+ start_write_page: -+ cnt_in_pg = 0; -+ __i2c_send_start(); -+ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -+ goto device_err; -+ if (addr_val) { -+ if (i2c_put_data(sub_addr) < 0) -+ goto address_err; -+ } -+ while (cnt) { -+ if (++cnt_in_pg > 8) { -+ __i2c_send_stop(); -+ mdelay(1); -+ sub_addr += 8; -+ goto start_write_page; -+ } -+ if (i2c_put_data(*tmpbuf) < 0) -+ break; -+ cnt--; -+ tmpbuf++; -+ } -+ __i2c_send_stop(); -+ addr_val = 0; -+ return length - cnt; -+ device_err: -+ address_err: -+ timeout--; -+ __i2c_send_stop(); -+ goto W_try_again; -+ -+W_timeout: -+ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -+ __i2c_send_stop(); -+ return -ENODEV; -+} -+ -+static int i2c_jz_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) -+{ -+ int ret, i; -+ -+ dev_dbg(&adap->dev, "jz47xx_xfer: processing %d messages:\n", num); -+ for (i = 0; i < num; i++) { -+ dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, -+ pmsg->flags & I2C_M_RD ? "read" : "writ", -+ pmsg->len, pmsg->len > 1 ? "s" : "", -+ pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); -+ if (pmsg->len && pmsg->buf) { /* sanity check */ -+ if (pmsg->flags & I2C_M_RD) -+ ret = xfer_read(pmsg->addr, adap, pmsg->buf, pmsg->len); -+ else -+ ret = xfer_write(pmsg->addr, adap, pmsg->buf, pmsg->len); -+ -+ if (ret) -+ return ret; -+ /* Wait until transfer is finished */ -+ } -+ dev_dbg(&adap->dev, "transfer complete\n"); -+ pmsg++; /* next message */ -+ } -+ return i; -+} -+ -+static u32 i2c_jz_functionality(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm i2c_jz_algorithm = { -+ .master_xfer = i2c_jz_xfer, -+ .functionality = i2c_jz_functionality, -+}; -+ -+static int i2c_jz_probe(struct platform_device *dev) -+{ -+ struct jz_i2c *i2c; -+ struct i2c_jz_platform_data *plat = dev->dev.platform_data; -+ int ret; -+ -+ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -+ __i2c_enable(); -+ -+ i2c = kzalloc(sizeof(struct jz_i2c), GFP_KERNEL); -+ if (!i2c) { -+ printk("There is no enough memory\n"); -+ ret = -ENOMEM; -+ goto emalloc; -+ } -+ -+ i2c->adap.owner = THIS_MODULE; -+ i2c->adap.algo = &i2c_jz_algorithm; -+ i2c->adap.retries = 5; -+ spin_lock_init(&i2c->lock); -+ init_waitqueue_head(&i2c->wait); -+ sprintf(i2c->adap.name, "jz_i2c-i2c.%u", dev->id); -+ i2c->adap.algo_data = i2c; -+ i2c->adap.dev.parent = &dev->dev; -+ -+ if (plat) { -+ i2c->adap.class = plat->class; -+ } -+ -+ /* -+ * If "dev->id" is negative we consider it as zero. -+ * The reason to do so is to avoid sysfs names that only make -+ * sense when there are multiple adapters. -+ */ -+ i2c->adap.nr = dev->id != -1 ? dev->id : 0; -+ /* ret = i2c_add_adapter(&i2c->adap); */ -+ ret = i2c_add_numbered_adapter(&i2c->adap); -+ if (ret < 0) { -+ printk(KERN_INFO "I2C: Failed to add bus\n"); -+ goto eadapt; -+ } -+ -+ platform_set_drvdata(dev, i2c); -+ dev_info(&dev->dev, "JZ47xx i2c bus driver.\n"); -+ return 0; -+eadapt: -+ __i2c_disable(); -+emalloc: -+ return ret; -+} -+ -+static int i2c_jz_remove(struct platform_device *dev) -+{ -+ struct i2c_adapter *adapter = platform_get_drvdata(dev); -+ int rc; -+ -+ rc = i2c_del_adapter(adapter); -+ platform_set_drvdata(dev, NULL); -+ return rc; -+} -+ -+static struct platform_driver i2c_jz_driver = { -+ .probe = i2c_jz_probe, -+ .remove = i2c_jz_remove, -+ .driver = { -+ .name = "jz_i2c", -+ }, -+}; -+ -+static int __init i2c_adap_jz_init(void) -+{ -+ return platform_driver_register(&i2c_jz_driver); -+} -+ -+static void __exit i2c_adap_jz_exit(void) -+{ -+ return platform_driver_unregister(&i2c_jz_driver); -+} -+ -+MODULE_LICENSE("GPL"); -+ -+module_init(i2c_adap_jz_init); -+module_exit(i2c_adap_jz_exit); -diff --git a/drivers/i2c/busses/i2c-jz47xx.h b/drivers/i2c/busses/i2c-jz47xx.h -new file mode 100644 -index 0000000..eb86110 ---- /dev/null -+++ b/drivers/i2c/busses/i2c-jz47xx.h -@@ -0,0 +1,20 @@ -+/* -+ * i2c_jz47xx.h -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef _I2C_JZ_H_ -+#define _I2C_JZ_H_ -+ -+struct i2c_slave_client; -+ -+struct i2c_jz_platform_data { -+ unsigned int slave_addr; -+ struct i2c_slave_client *slave; -+ unsigned int class; -+}; -+ -+extern void jz_set_i2c_info(struct i2c_jz_platform_data *info); -+#endif -diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c -index 7e13d2d..0b0986b 100644 ---- a/drivers/i2c/i2c-dev.c -+++ b/drivers/i2c/i2c-dev.c -@@ -38,8 +38,9 @@ - #include - #include - -+extern unsigned short sub_addr; -+extern int addr_val; - static struct i2c_driver i2cdev_driver; -- - /* - * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a - * slave (i2c_client) with which messages will be exchanged. It's coupled -@@ -428,6 +429,14 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - */ - client->adapter->timeout = msecs_to_jiffies(arg * 10); - break; -+ case I2C_SET_SUB_ADDRESS: -+ addr_val = 1; -+ sub_addr = arg; -+ break; -+ case I2C_SET_CLOCK: -+ i2c_jz_setclk(arg); -+ break; -+ - default: - /* NOTE: returning a fault code here could cause trouble - * in buggy userspace code. Some old kernel bugs returned -diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig -index a6b989a..a2c9ff9 100644 ---- a/drivers/input/keyboard/Kconfig -+++ b/drivers/input/keyboard/Kconfig -@@ -146,8 +146,8 @@ config KEYBOARD_EP93XX - module will be called ep93xx_keypad. - - config KEYBOARD_GPIO -- tristate "GPIO Buttons" -- depends on GENERIC_GPIO -+ tristate "JZ GPIO Buttons support" -+# depends on GENERIC_GPIO - help - This driver implements support for buttons connected - to GPIO pins of various CPUs (and some other chips). -diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c -index efed0c9..4c8d358 100644 ---- a/drivers/input/keyboard/gpio_keys.c -+++ b/drivers/input/keyboard/gpio_keys.c -@@ -1,7 +1,13 @@ - /* -- * Driver for keys on GPIO lines capable of generating interrupts. -+ * linux/drivers/input/keyboard/gpio_keys.c - * -- * Copyright 2005 Phil Blundell -+ * JZ GPIO Buttons driver for JZ4740 PAVO -+ * -+ * User applications can access to this device via /dev/input/eventX. -+ * -+ * Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: Richard - * - * 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 -@@ -225,7 +231,7 @@ static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup) { -- int irq = gpio_to_irq(button->gpio); -+ int irq = button->gpio + IRQ_GPIO_0; - enable_irq_wake(irq); - } - } -@@ -243,7 +249,7 @@ static int gpio_keys_resume(struct platform_device *pdev) - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup) { -- int irq = gpio_to_irq(button->gpio); -+ int irq = button->gpio + IRQ_GPIO_0; - disable_irq_wake(irq); - } - } -@@ -269,11 +275,13 @@ static struct platform_driver gpio_keys_device_driver = { - - static int __init gpio_keys_init(void) - { -+ pavo_board_init(); - return platform_driver_register(&gpio_keys_device_driver); - } - - static void __exit gpio_keys_exit(void) - { -+ platform_device_unregister(&pavo_button_device); - platform_driver_unregister(&gpio_keys_device_driver); - } - -diff --git a/drivers/input/keyboard/jz_keypad.c b/drivers/input/keyboard/jz_keypad.c -new file mode 100644 -index 0000000..3e6e309 ---- /dev/null -+++ b/drivers/input/keyboard/jz_keypad.c -@@ -0,0 +1,357 @@ -+/* -+ * linux/drivers/input/keyboard/jz_keypad.c -+ * -+ * JZ Keypad Driver -+ * -+ * Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: Richard -+ * -+ * 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 -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+#define KB_ROWS 3 -+#define KB_COLS 3 -+ -+#define SCAN_INTERVAL (10) -+ -+static unsigned short col[KB_COLS] = {85,87,91}; -+static unsigned short row[KB_ROWS] = {60,61,62}; -+static unsigned short s0[KB_COLS]; -+static unsigned short s1[KB_COLS]={7,7,7}; -+static unsigned short precol,prerow; -+ -+static const unsigned int jz_kbd_keycode[KB_COLS * KB_ROWS] = { -+ KEY_1, KEY_4, KEY_7, -+ KEY_2, KEY_5, 0, -+ KEY_3, KEY_6, 0, -+}; -+ -+struct jz_kbd { -+ unsigned int keycode[ARRAY_SIZE(jz_kbd_keycode)]; -+ struct input_dev *input; -+ char phys[32]; -+ -+ spinlock_t lock; -+ struct timer_list timer; -+ -+ unsigned int suspended; -+ unsigned long suspend_jiffies; -+}; -+ -+static struct jz_kbd g_jz_kbd; -+ -+static inline void jz_scan_kbd(unsigned short *s) -+{ -+ int i; -+ -+ if (!s) -+ return; -+ -+ for (i = 0; i < KB_COLS; i++) { -+ -+ __gpio_as_input(85); /* row */ -+ __gpio_as_input(87); /* row */ -+ __gpio_as_input(91); /* row */ -+ -+ __gpio_as_input(60); /* col */ -+ __gpio_as_input(61); /* col */ -+ __gpio_as_input(62); /* col */ -+ -+ __gpio_clear_pin(col[i]); -+ __gpio_as_output(col[i]); -+ -+ udelay(1000); -+ s[i]=(__gpio_get_pin(60) << 0) | (__gpio_get_pin(61) << 1) | -+ (__gpio_get_pin(62) << 2); -+ } -+} -+ -+static void jz_kbd_scankeyboard(struct jz_kbd *kbd_data) -+{ -+ unsigned int row,col; -+ unsigned long flags; -+ unsigned int num_pressed; -+ -+ if (kbd_data->suspended) -+ return; -+ -+ spin_lock_irqsave(&kbd_data->lock, flags); -+ -+ num_pressed = 0; -+ jz_scan_kbd(s0); -+ -+ /* look for key if pressed down on not, col & row */ -+ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 7) { -+ if (s1[0] != 7 || s1[1] != 7 || s1[2] != 7) { -+ /* up */ -+ input_report_key(kbd_data->input, kbd_data->keycode[prerow * KB_COLS + precol], 0); -+ input_sync(kbd_data->input); -+ } -+ precol = prerow = -1; -+ s1[0] = s1[1] = s1[2] = 7; -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ return; -+ } -+ -+ if (s0[0] == 6 && s0[1] == 7 && s0[2] == 7) { -+ row = 0;//K7 -+ col = 2; -+ goto find_row_col; -+ } -+ if (s0[0] == 7 && s0[1] == 3 && s0[2] == 7) { -+ row = 2;//k6 -+ col = 1; -+ goto find_row_col; -+ } -+ if (s0[0] == 7 && s0[1] == 5 && s0[2] == 7) { -+ row = 1;//k5 -+ col = 1; -+ goto find_row_col; -+ } -+ if (s0[0] == 7 && s0[1] == 6 && s0[2] == 7) { -+ row = 0;//k4 -+ col = 1; -+ goto find_row_col; -+ } -+ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 3) { -+ row = 2;//k3 -+ col = 0; -+ goto find_row_col; -+ } -+ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 5) { -+ row = 1;//k2 -+ col = 0; -+ goto find_row_col; -+ } -+ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 6) { -+ row = 0;//k1 -+ col = 0; -+ goto find_row_col; -+ } -+ /* 2 or 3 buttons are pressed */ -+ s0[0] = s0[1] = s0[2] = 7; -+ s1[0] = s1[1] = s1[2] = 7; -+ prerow = precol = -1; -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ return; -+find_row_col: -+ if (s1[0] == 7 && s1[1] == 7 && s1[2] == 7) { -+ /* down */ -+ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -+ input_sync(kbd_data->input); -+ s1[0] = s0[0]; -+ s1[1] = s0[1]; -+ s1[2] = s0[2]; -+ -+ precol = col; -+ prerow = row; -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ return; -+ } -+ if (s1[0] != 7 || s1[1] != 7 || s1[2] != 7) { -+ /* is the same as the preview key */ -+ if (s0[0] == s1[0] && s0[1] == s1[1] && s0[2] == s1[2]) { -+ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -+ input_sync(kbd_data->input); -+ s1[0] = s0[0]; -+ s1[1] = s0[1]; -+ s1[2] = s0[2]; -+ -+ precol = col; -+ prerow = row; -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ return; -+ } else { -+ /* the preview key is up and other key is down */ -+ if (s0[0] != s1[0] || s0[1] != s1[1] || s0[2] != s1[2]) { -+ input_report_key(kbd_data->input, kbd_data->keycode[prerow * KB_COLS + precol], 0); -+ input_sync(kbd_data->input); -+ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -+ input_sync(kbd_data->input); -+ s1[0] = s0[0]; -+ s1[1] = s0[1]; -+ s1[2] = s0[2]; -+ precol = col; -+ prerow = row; -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ return; -+ } -+ } -+ } -+} -+ -+static void jz_kbd_timer_callback(unsigned long data) -+{ -+ jz_kbd_scankeyboard(&g_jz_kbd); -+ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -+} -+ -+#ifdef CONFIG_PM -+static int jz_kbd_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -+ jz_kbd->suspended = 1; -+ -+ return 0; -+} -+ -+static int jz_kbd_resume(struct platform_device *dev) -+{ -+ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -+ -+ jz_kbd->suspend_jiffies = jiffies; -+ jz_kbd->suspended = 0; -+ -+ return 0; -+} -+#else -+#define jz_kbd_suspend NULL -+#define jz_kbd_resume NULL -+#endif -+ -+static int __init jz_kbd_probe(struct platform_device *dev) -+{ -+ struct input_dev *input_dev; -+ int i, error; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ return -ENOMEM; -+ -+ platform_set_drvdata(dev, &g_jz_kbd); -+ -+ strcpy(g_jz_kbd.phys, "input/kbd0"); -+ -+ spin_lock_init(&g_jz_kbd.lock); -+ -+ g_jz_kbd.suspend_jiffies = jiffies; -+ g_jz_kbd.input = input_dev; -+ -+ input_dev->private = &g_jz_kbd; -+ input_dev->name = "JZ Keypad"; -+ input_dev->phys = g_jz_kbd.phys; -+ input_dev->cdev.dev = &dev->dev; -+ -+ input_dev->id.bustype = BUS_PARPORT; -+ input_dev->id.vendor = 0x0001; -+ input_dev->id.product = 0x0001; -+ input_dev->id.version = 0x0100; -+ -+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN); -+ input_dev->keycode = g_jz_kbd.keycode; /* keycode array address */ -+ input_dev->keycodesize = sizeof(unsigned int); -+ input_dev->keycodemax = ARRAY_SIZE(jz_kbd_keycode); -+ -+ memcpy(g_jz_kbd.keycode, jz_kbd_keycode, sizeof(g_jz_kbd.keycode)); -+ -+ for (i = 0; i < ARRAY_SIZE(jz_kbd_keycode); i++) -+ set_bit(g_jz_kbd.keycode[i], input_dev->keybit); -+ -+ //clear_bit(0, input_dev->keybit); -+ -+ __gpio_as_input(85); -+ __gpio_as_input(87); -+ __gpio_as_input(91); -+ -+#if 0 -+ __gpio_as_input(60); -+ __gpio_as_input(61); -+ __gpio_as_input(62); -+#endif -+ -+ /* Init Keyboard rescan timer */ -+ init_timer(&g_jz_kbd.timer); -+ g_jz_kbd.timer.function = jz_kbd_timer_callback; -+ g_jz_kbd.timer.data = (unsigned long)&g_jz_kbd; -+ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -+ -+ error = input_register_device(input_dev); -+ if (error) { -+ pr_err("gpio-keys: Unable to register input device, " -+ "error: %d\n", error); -+ } -+ printk("input: JZ Keypad Registered\n"); -+ -+ return 0; -+} -+ -+static int jz_kbd_remove(struct platform_device *dev) -+{ -+ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -+ -+ del_timer_sync(&jz_kbd->timer); -+ -+ __gpio_as_input(85); -+ __gpio_as_input(87); -+ __gpio_as_input(91); -+ -+ /* These pins is conficting with cs8900a's CS RD WE pins on JZ4740-PAVO board */ -+ __gpio_as_input(60); -+ __gpio_as_input(61); -+ __gpio_as_input(62); -+ -+ input_unregister_device(jz_kbd->input); -+ -+ return 0; -+} -+ -+static struct platform_driver jz_kbd_driver = { -+ .probe = jz_kbd_probe, -+ .remove = jz_kbd_remove, -+ .suspend = jz_kbd_suspend, -+ .resume = jz_kbd_resume, -+ .driver = { -+ .name = "jz-keypad", -+ }, -+}; -+ -+/* -+ * Jz Keyboard Device -+ */ -+static struct platform_device jzkbd_device = { -+ .name = "jz-keypad", -+ .id = -1, -+}; -+ -+static int __init jz_kbd_init(void) -+{ -+ platform_device_register(&jzkbd_device); -+ return platform_driver_register(&jz_kbd_driver); -+} -+ -+static void __exit jz_kbd_exit(void) -+{ -+ platform_device_unregister(&jzkbd_device); -+ platform_driver_unregister(&jz_kbd_driver); -+} -+ -+module_init(jz_kbd_init); -+module_exit(jz_kbd_exit); -+ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("JZ keypad driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/input/keyboard/jz_keypad_5x5.c b/drivers/input/keyboard/jz_keypad_5x5.c -new file mode 100644 -index 0000000..eb1502b ---- /dev/null -+++ b/drivers/input/keyboard/jz_keypad_5x5.c -@@ -0,0 +1,329 @@ -+/* -+ * JZ Keypad ( 5 x 5 ) Driver -+ * -+ * Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: Jason 20090210 -+ * -+ * 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 -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define KB_ROWS 5 -+#define KB_COLS 5 -+ -+#define SCAN_INTERVAL (10) -+ -+#define ROW_KEYBIT_MASK 0xFFE0 -+ -+#define SET_GPIOS_AS_INPUT() \ -+do { \ -+ unsigned short i; \ -+ \ -+ for (i = 0; i < KB_ROWS; i++) { \ -+ __gpio_as_input(jz_row_gpios[i]); \ -+ __gpio_as_input(jz_col_gpios[i]); \ -+ } \ -+} while (0) -+ -+ -+#define GET_ROW_GPIO_PINS() \ -+({ \ -+ unsigned short _pins = 0, i; \ -+ for (i = 0; \ -+ i < KB_ROWS; \ -+ _pins |= __gpio_get_pin(jz_row_gpios[i]) << i, i++) \ -+ ; \ -+ _pins; \ -+}) -+ -+#define CHECK_IF_KEY_PRESSED(s) \ -+({ \ -+ unsigned short i; \ -+ for (i = 0; i < KB_COLS && s[i] == 0x1F ; i++) \ -+ ; \ -+ i != KB_ROWS; \ -+}) -+ -+#define CLEAN_SCAN_RESULT(s) \ -+do { \ -+ unsigned short i; \ -+ for (i = 0; i < KB_COLS; s[i++] = 0x1F) \ -+ ; \ -+} while (0) -+ -+ -+static const unsigned short jz_col_gpios[KB_ROWS] = {76, 75, 74, 73, 72}; -+static const unsigned short jz_row_gpios[KB_COLS] = {181, 182, 79, 78, 77}; -+ -+static const unsigned int jz_kbd_keycode[KB_ROWS * KB_COLS] = { -+ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, -+ KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, -+ KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, -+ KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, -+ KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_SPACE, KEY_BACKSPACE, KEY_Y -+}; -+ -+struct jz_kbd { -+ unsigned int keycode[ARRAY_SIZE(jz_kbd_keycode)]; -+ struct input_dev *input; -+ char phys[32]; -+ -+ spinlock_t lock; -+ struct timer_list timer; -+ -+ unsigned int suspended; -+ unsigned long suspend_jiffies; -+}; -+static struct jz_kbd g_jz_kbd; -+ -+static unsigned short scan_result[KB_COLS]; -+static unsigned short pre_scan_result[KB_COLS] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F}; -+static unsigned short pre_col, pre_row; -+ -+/** -+ * Scan keypad by reading GPIO pins. -+ */ -+static inline void jz_do_scan(unsigned short *s) -+{ -+ unsigned short i; -+ -+ if (!s) -+ return ; -+ -+ for (i = 0; i < KB_COLS; i++) { -+ -+ SET_GPIOS_AS_INPUT(); -+ __gpio_clear_pin(jz_col_gpios[i]); -+ __gpio_as_output(jz_col_gpios[i]); -+ -+ udelay(1000); -+ -+ s[i] = GET_ROW_GPIO_PINS(); -+ } -+} -+ -+/** -+ * Call scan function and handle 'GPIO event'(like key down, key up), -+ * and report it to upper layer of input subsystem ... if necessary -+ */ -+static void jz_kbd_scan(struct jz_kbd *kbd_data) -+{ -+ unsigned short row, col, i; -+ unsigned long flags; -+ -+ if (kbd_data->suspended) -+ return; -+ -+ spin_lock_irqsave(&kbd_data->lock, flags); -+ -+ jz_do_scan(scan_result); -+ -+ /* check if any key was pressed or not */ -+ if (!CHECK_IF_KEY_PRESSED(scan_result)) { -+ -+ /* key up */ -+ if (CHECK_IF_KEY_PRESSED(pre_scan_result)) { -+ input_report_key(kbd_data->input, kbd_data->keycode[pre_row * KB_COLS + pre_col], 0); -+ input_sync(kbd_data->input); -+ } -+ pre_col = pre_row = 0xFFFF; -+ CLEAN_SCAN_RESULT(pre_scan_result); -+ -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ return; -+ } -+ -+ /* find the key */ -+ for (row = 0; row < KB_ROWS; row++) { -+ for (i = scan_result[row], col = 0; col < KB_COLS; col++) { -+ if ( !(i & 0x01) ) -+ break; -+ i >>= 1; -+ } -+ if (col != KB_COLS) -+ break; -+ } -+ -+ //printk("[DRIVER] row = %d, col = %d, key code: 0x%02X\n", row, col, kbd_data->keycode[row * KB_COLS + col]); -+ -+ /* the same as the preview one || new key */ -+ if ( (col == pre_col && row == pre_row) -+ || (pre_col == 0xFFFF && pre_row == 0xFFFF) ) { -+ -+ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -+ input_sync(kbd_data->input); -+ -+ } else { -+ /* the preview key is up and other key is down */ -+ input_report_key(kbd_data->input, kbd_data->keycode[pre_row * KB_COLS + col], 0); -+ input_sync(kbd_data->input); -+ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -+ input_sync(kbd_data->input); -+ } -+ -+ for (i = 0; i < KB_ROWS; i++) { -+ pre_scan_result[i] = scan_result[i]; -+ } -+ -+ pre_col = col; -+ pre_row = row; -+ -+ spin_unlock_irqrestore(&kbd_data->lock, flags); -+ -+ return; -+} -+ -+static void jz_kbd_timer_callback(unsigned long data) -+{ -+ jz_kbd_scan(&g_jz_kbd); -+ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -+} -+ -+#ifdef CONFIG_PM -+static int jz_kbd_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -+ jz_kbd->suspended = 1; -+ -+ return 0; -+} -+ -+static int jz_kbd_resume(struct platform_device *dev) -+{ -+ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -+ -+ jz_kbd->suspend_jiffies = jiffies; -+ jz_kbd->suspended = 0; -+ -+ return 0; -+} -+ -+#else -+#define jz_kbd_suspend NULL -+#define jz_kbd_resume NULL -+#endif -+ -+/** -+ * Driver init -+ */ -+static int __init jz_kbd_probe(struct platform_device *dev) -+{ -+ struct input_dev *input_dev; -+ int i, error; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ return -ENOMEM; -+ -+ platform_set_drvdata(dev, &g_jz_kbd); -+ -+ strcpy(g_jz_kbd.phys, "input/kbd0"); -+ -+ spin_lock_init(&g_jz_kbd.lock); -+ -+ g_jz_kbd.suspend_jiffies = jiffies; -+ g_jz_kbd.input = input_dev; -+ -+ input_dev->private = &g_jz_kbd; -+ input_dev->name = "JZ 5x5 Keypad"; -+ input_dev->phys = g_jz_kbd.phys; -+ input_dev->cdev.dev = &dev->dev; -+ -+ input_dev->id.bustype = BUS_PARPORT; -+ input_dev->id.vendor = 0x0001; -+ input_dev->id.product = 0x0001; -+ input_dev->id.version = 0x0100; -+ -+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN); -+ input_dev->keycode = g_jz_kbd.keycode; -+ input_dev->keycodesize = sizeof(unsigned int); -+ input_dev->keycodemax = ARRAY_SIZE(jz_kbd_keycode); -+ -+ memcpy(g_jz_kbd.keycode, jz_kbd_keycode, sizeof(g_jz_kbd.keycode)); -+ -+ for ( i = 0; i < ARRAY_SIZE(jz_kbd_keycode); i++) -+ set_bit(g_jz_kbd.keycode[i], input_dev->keybit); -+ -+ init_timer(&g_jz_kbd.timer); -+ g_jz_kbd.timer.function = jz_kbd_timer_callback; -+ g_jz_kbd.timer.data = (unsigned long)&g_jz_kbd; -+ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -+ -+ error = input_register_device(input_dev); -+ if (error) { -+ pr_err("gpio-keys: Unable to register input device, " -+ "error: %d\n", error); -+ } -+ printk("input: JZ 5x5 Keypad Registered.\n"); -+ -+ return 0; -+} -+ -+static int jz_kbd_remove(struct platform_device *dev) -+{ -+ struct jz_kbd *kbd = platform_get_drvdata(dev); -+ -+ del_timer_sync(&kbd->timer); -+ -+ SET_GPIOS_AS_INPUT(); -+ -+ input_unregister_device(kbd->input); -+ -+ return 0; -+} -+ -+static struct platform_driver jz_kbd_driver = { -+ .probe = jz_kbd_probe, -+ .remove = jz_kbd_remove, -+ .suspend= jz_kbd_suspend, -+ .resume = jz_kbd_resume, -+ .driver = { -+ .name = "jz-5x5-keypad", -+ }, -+}; -+ -+static struct platform_device jzkbd_device = { -+ .name = "jz-5x5-keypad", -+ .id = -1, -+}; -+ -+static int __init jz_kbd_init(void) -+{ -+ platform_device_register(&jzkbd_device); -+ return platform_driver_register(&jz_kbd_driver); -+} -+ -+static void __exit jz_kbd_exit(void) -+{ -+ platform_device_unregister(&jzkbd_device); -+ platform_driver_unregister(&jz_kbd_driver); -+} -+ -+module_init(jz_kbd_init); -+module_exit(jz_kbd_exit); -+ -+MODULE_AUTHOR("Jason "); -+MODULE_DESCRIPTION("JZ 5x5 keypad driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig -index 84b6fc1..16c0f2e 100644 ---- a/drivers/media/video/Kconfig -+++ b/drivers/media/video/Kconfig -@@ -615,6 +615,24 @@ config VIDEO_VINO - Say Y here to build in support for the Vino video input system found - on SGI Indy machines. - -+config VIDEO_JZ4730_CIM -+ tristate 'JzSOC Camera Interface Module (CIM) support' -+ depends on VIDEO_V4L2 && FB_JZSOC && SOC_JZ4730 -+ select VIDEO_JZ_SENSOR -+ -+config VIDEO_JZ4740_CIM -+ tristate 'JzSOC Camera Interface Module (CIM) support' -+ depends on VIDEO_V4L2 && FB_JZSOC && SOC_JZ4740 -+ select VIDEO_JZ_SENSOR -+ -+config VIDEO_JZ4750_CIM -+ tristate 'JzSOC Camera Interface Module (CIM) support' -+ depends on VIDEO_V4L2 && FB_JZSOC && (SOC_JZ4750 || SOC_JZ4750D) -+ select VIDEO_JZ_SENSOR -+ -+config VIDEO_JZ_SENSOR -+ tristate "Jz generic camera sensor driver" -+ - config VIDEO_STRADIS - tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS -diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile -index 9f2e321..77a2944 100644 ---- a/drivers/media/video/Makefile -+++ b/drivers/media/video/Makefile -@@ -80,6 +80,11 @@ obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o - - # And now the v4l2 drivers: - -+obj-$(CONFIG_VIDEO_JZ4730_CIM) += jz4730_cim.o -+obj-$(CONFIG_VIDEO_JZ4740_CIM) += jz4740_cim.o -+obj-$(CONFIG_VIDEO_JZ4750_CIM) += jz4750_cim.o -+obj-$(CONFIG_VIDEO_JZ_SENSOR) += jz_sensor.o -+ - obj-$(CONFIG_VIDEO_BT848) += bt8xx/ - obj-$(CONFIG_VIDEO_ZORAN) += zoran/ - obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o -diff --git a/drivers/media/video/jz4730_cim.c b/drivers/media/video/jz4730_cim.c -new file mode 100644 -index 0000000..4ea0594 ---- /dev/null -+++ b/drivers/media/video/jz4730_cim.c -@@ -0,0 +1,622 @@ -+/* -+ * linux/drivers/char/jzchar/cim.c -+ * -+ * Camera Interface Module (CIM) driver for JzSOC -+ * This driver is independent of the camera sensor -+ * -+ * Copyright (C) 2005 JunZheng semiconductor -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+//#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define CIM_NAME "cim" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("JzSOC Camera Interface Module driver"); -+MODULE_LICENSE("GPL"); -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+/* -+ * Define the Max Image Size -+ */ -+#define MAX_IMAGE_WIDTH 2048 -+#define MAX_IMAGE_HEIGHT 2048 -+#define MAX_IMAGE_BPP 16 -+#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP / 8) -+#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -+ -+typedef struct -+{ -+ u32 width; -+ u32 height; -+ u32 bpp; -+} img_param_t; -+ -+typedef struct -+{ -+ u32 cfg; -+ u32 ctrl; -+ u32 mclk; -+} cim_config_t; -+ -+/* -+ * IOCTL_XXX commands -+ */ -+#define IOCTL_SET_IMG_PARAM 0 // arg type: img_param_t * -+#define IOCTL_CIM_CONFIG 1 // arg type: cim_config_t * -+#define IOCTL_STOP_CIM 2 // arg type: void -+#define IOCTL_GET_IMG_PARAM 3 // arg type: img_param_t * -+#define IOCTL_GET_CIM_CONFIG 4 // arg type: cim_config_t * -+#define IOCTL_TEST_CIM_RAM 5 // no arg type * -+ -+/* -+ * CIM DMA descriptor -+ */ -+struct cim_desc { -+ u32 nextdesc; /* Physical address of next desc */ -+ u32 framebuf; /* Physical address of frame buffer */ -+ u32 frameid; /* Frame ID */ -+ u32 dmacmd; /* DMA command */ -+ u32 pagenum; -+}; -+ -+/* -+ * CIM device structure -+ */ -+struct cim_device { -+ struct video_device *jz_cim; -+ unsigned char *framebuf; -+ unsigned int frame_size; -+ unsigned int page_order; -+ wait_queue_head_t wait_queue; -+ struct cim_desc *frame_desc __attribute__ ((aligned (16))); -+}; -+ -+/* global*/ -+static struct cim_device *cim_dev; -+ -+/*========================================================================== -+ * CIM init routines -+ *========================================================================*/ -+#if defined(CONFIG_SOC_JZ4750) -+static void cim_image_area(img_param_t *c) { -+ /*set the image data area start 0, 0, lines_per_frame and pixels_per_line*/ -+ REG_CIM_SIZE = 0; -+ REG_CIM_OFFSET = 0; -+ if (REG_CIM_CTRL & CIM_CTRL_SIZEEN_MASK) { -+ REG_CIM_SIZE = (c->height << CIM_SIZE_LPF_BIT) | (c->width << CIM_SIZE_PPL_BIT); -+ REG_CIM_OFFSET = (0 << CIM_OFFSET_V_BIT) | (0 << CIM_OFFSET_H_BIT); -+// REG_CIM_OFFSET = (100 << CIM_OFFSET_V_BIT) | (50 << CIM_OFFSET_H_BIT); -+ } -+} -+#endif -+ -+static void cim_config(cim_config_t *c) -+{ -+ REG_CIM_CFG = c->cfg; -+ REG_CIM_CTRL = c->ctrl; -+ -+ /*Set the master clock output*/ -+#if defined(CONFIG_SOC_JZ4730) -+ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -+#elif defined(CONFIG_SOC_JZ4740) -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#elif defined(CONFIG_SOC_JZ4750) -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#else -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#endif -+ /* Enable sof, eof and stop interrupts*/ -+ __cim_enable_sof_intr(); -+ __cim_enable_eof_intr(); -+ __cim_enable_stop_intr(); -+} -+ -+/*========================================================================== -+ * CIM start/stop operations -+ *========================================================================*/ -+static int cim_start_dma(char *ubuf) -+{ -+ struct cim_desc *jz_frame_desc; -+ int cim_frame_size = 0; -+ jz_frame_desc = cim_dev->frame_desc; -+ dprintk("framedesc = %x\n", (u32) jz_frame_desc); -+ __cim_disable(); -+ dprintk("__cim_disable\n"); -+ __cim_set_da(virt_to_phys(cim_dev->frame_desc)); -+ __cim_clear_state(); // clear state register -+ __cim_reset_rxfifo(); // resetting rxfifo -+ __cim_unreset_rxfifo(); -+ __cim_enable_dma(); // enable dma -+ __cim_enable(); -+ -+ dprintk("__cim_enable\n"); -+// while(1) { -+// mdelay(10); -+// dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -+// dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -+// dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -+// dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -+// dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -+// dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -+// dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -+// dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -+// dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -+// mdelay(100); -+// } -+ // wait for interrupts -+ interruptible_sleep_on(&cim_dev->wait_queue); -+ dprintk("interruptible_sleep_on\n"); -+ dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -+ dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -+ dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -+ dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -+ dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -+ dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -+ dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -+ dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -+ dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -+ dprintk("REG_CIM_CMD_3 = %x\n", REG_CIM_CMD); -+ dprintk("REG_CIM_FA = %x\n", REG_CIM_FA); -+ /* copy frame data to user buffer */ -+ jz_frame_desc = cim_dev->frame_desc; -+ -+ while(jz_frame_desc != NULL) -+ { -+ dprintk("ubuf = %x, framebuf = %x,frame_size= %d\n", (u32)ubuf,(u32) jz_frame_desc->framebuf, jz_frame_desc->dmacmd & 0xffffff); -+ memcpy(ubuf, phys_to_virt(jz_frame_desc->framebuf), ((jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4)); -+ ubuf += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -+ cim_frame_size += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -+ jz_frame_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -+ } -+ return cim_dev->frame_size; -+} -+static void cim_stop(void) -+{ -+ __cim_disable(); -+ __cim_clear_state(); -+} -+ -+/*========================================================================== -+ * Framebuffer allocation and destroy -+ *========================================================================*/ -+static void cim_fb_destroy(void) -+{ -+ int pages; -+ struct cim_desc *jz_frame_desc, *p_desc; -+ if (cim_dev->frame_desc == NULL) { -+ printk("Original memory is NULL\n"); -+ return; -+ } -+ jz_frame_desc = cim_dev->frame_desc; -+ while (jz_frame_desc != NULL) { -+ dprintk("framebuf = %x,thisdesc = %x,frame_size= %d\n", (u32) jz_frame_desc->framebuf, (unsigned int)jz_frame_desc, (jz_frame_desc->dmacmd & 0xffffff) * 4); -+ p_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -+ pages = jz_frame_desc->pagenum; -+ dprintk("page_order = %d\n", pages); -+ free_pages((unsigned long)phys_to_virt(jz_frame_desc->framebuf), pages); -+ kfree(jz_frame_desc); -+ jz_frame_desc = p_desc; -+ } -+ cim_dev->frame_desc = NULL; -+} -+ -+static struct cim_desc *get_desc_list(int page_order) -+{ -+ int num, page_nums = 0; -+ unsigned char *p_buf; -+ struct cim_desc *desc_list_head __attribute__ ((aligned (16))); -+ struct cim_desc *desc_list_tail __attribute__ ((aligned (16))); -+ struct cim_desc *p_desc; -+// num = page_order - 1; -+ num = page_order; -+ desc_list_head = desc_list_tail = NULL; -+ -+ while(page_nums < (1 << page_order)) { -+ p_desc = (struct cim_desc *)kmalloc(sizeof(struct cim_desc), GFP_KERNEL); -+ if (NULL == p_desc) -+ return NULL; -+ //return -ENOMEM; -+ cim_realloc_pages: -+ p_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, num); -+ if ( !(p_buf) && num != 0) { -+ num --; -+ goto cim_realloc_pages; -+ } -+ else if ( !(p_buf) && num == 0) { -+ printk("No memory can be alloc!\n"); -+ //return -ENOMEM; -+ return NULL; -+ } -+ else { -+ if (desc_list_head == NULL) { -+ dprintk("Page_list_head\n"); -+ desc_list_head = p_desc; -+ } -+ -+ else -+ desc_list_tail->nextdesc = virt_to_phys(p_desc); -+ -+ desc_list_tail = p_desc; -+ desc_list_tail->framebuf = virt_to_phys(p_buf); -+ dprintk("framebuf addr is 0x%08x\n", (u32)desc_list_tail->framebuf); -+ dprintk("frame_desc addr is 0x%08x\n",(u32)virt_to_phys(desc_list_tail)); -+ -+ desc_list_tail->frameid = 0x52052018; -+ desc_list_tail->pagenum = num; -+ if ((page_nums + (1<< num)) < (1 << page_order)) { -+ desc_list_tail->dmacmd = ((1 << num) * 4096) >> 2 ; -+ } -+ else -+ desc_list_tail->dmacmd = -+ (cim_dev->frame_size - page_nums * 4096) >> 2 ; -+ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -+ page_nums += (1 << num); -+ dprintk("the pages_num is %d\n", page_nums); -+ } -+ } -+ -+ desc_list_tail->nextdesc = virt_to_phys(NULL); -+ /* stop after capturing a frame */ -+ desc_list_tail->dmacmd |= (CIM_CMD_STOP | CIM_CMD_EOFINT); -+ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -+ -+ return desc_list_head; -+} -+ -+static int cim_fb_alloc(int img_width, int img_height, int img_bpp) -+{ -+#if defined(CONFIG_SOC_JZ4750) -+ if ((REG_CIM_CFG & (CIM_CFG_DF_MASK | CIM_CFG_BYPASS_MASK)) == 0) -+ cim_dev->frame_size = img_width * (img_height-1) * (img_bpp/8); -+ else -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+#else -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+#endif -+ cim_dev->page_order = get_order(cim_dev->frame_size); -+ dprintk("cim_dev->page_order=%d\n", cim_dev->page_order); -+ /* frame buffer ?? need large mem ??*/ -+ cim_dev->frame_desc = get_desc_list(cim_dev->page_order); -+ if (cim_dev->frame_desc == NULL) -+ return -ENOMEM; -+ dma_cache_wback((unsigned long)(cim_dev->frame_desc), 16); -+ return 0; -+} -+ -+/*========================================================================== -+ * File operations -+ *========================================================================*/ -+ -+static int cim_open(struct inode *inode, struct file *filp); -+static int cim_release(struct inode *inode, struct file *filp); -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -+static int cim_mmap(struct file *file, struct vm_area_struct *vma); -+ -+static struct file_operations cim_fops = -+{ -+ open: cim_open, -+ release: cim_release, -+ read: cim_read, -+ write: cim_write, -+ ioctl: cim_ioctl, -+ compat_ioctl: v4l_compat_ioctl32, -+ mmap: cim_mmap -+}; -+ -+static struct video_device jz_v4l_device = { -+ .name = "jz cim", -+ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | -+ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY -+ .fops = &cim_fops, -+ .minor = -1, -+ .owner = THIS_MODULE, -+ .release = video_device_release, -+}; -+ -+static int cim_open(struct inode *inode, struct file *filp) -+{ -+ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int cim_release(struct inode *inode, struct file *filp) -+{ -+ cim_fb_destroy(); -+ cim_stop(); -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ if (size < cim_dev->frame_size) -+ return -EINVAL; -+ dprintk("read cim\n"); -+ return cim_start_dma(buf); -+} -+ -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("cim error: write is not implemented\n"); -+ return -1; -+} -+ -+static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ void __user *argp = (void __user *)arg; -+ switch (cmd) { -+ case IOCTL_GET_IMG_PARAM: -+ { -+ img_param_t i; -+ return copy_to_user(argp, &i, sizeof(img_param_t)) ? -EFAULT : 0; -+ } -+ case IOCTL_SET_IMG_PARAM: -+ { -+ img_param_t i; -+ int img_width, img_height, img_bpp; -+ if (copy_from_user((void *)&i, (void *)arg, sizeof(img_param_t))) -+ return -EFAULT; -+#if defined(CONFIG_SOC_JZ4750) -+ cim_image_area(&i); -+#endif -+ img_width = i.width; -+ img_height = i.height; -+ img_bpp = i.bpp; -+ dprintk("ioctl_set_cim_param\n"); -+ if ((img_width * img_height * img_bpp/8) > MAX_FRAME_SIZE){ -+ printk("ERROR! Image is too large!\n"); -+ return -EINVAL; -+ } -+ /* allocate frame buffers */ -+ if (cim_dev->frame_desc == NULL){ -+ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -+ printk("ERROR! Init & alloc cim fail!\n"); -+ return -ENOMEM; -+ } -+ } -+ else -+ if ((img_width * img_height * img_bpp/8) > cim_dev->frame_size){ -+ /* realloc the buffer */ -+ cim_fb_destroy(); -+ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -+ printk("ERRROR! Init & alloc cim fail!\n"); -+ return -ENOMEM; -+ } -+ } -+ break; -+ } -+ case IOCTL_CIM_CONFIG: -+ { -+ cim_config_t c; -+ -+ if (copy_from_user((void *)&c, (void *)arg, sizeof(cim_config_t))) -+ return -EFAULT; -+ -+ cim_config(&c); -+ -+ break; -+ } -+ case IOCTL_TEST_CIM_RAM: -+ { -+ -+ int i; -+ volatile unsigned int *ptr; -+ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -+ printk("RAM test!\n"); -+ printk("CIM_RAM_ADDR = 0x%08x\n", CIM_RAM_ADDR); -+ for (i = 0; i < 1024; ptr++, i++) -+ *ptr = i; -+ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -+ dma_cache_wback((unsigned long)CIM_RAM_ADDR,0xffc); -+ -+ for (i = 0; i < 1024; i++) { -+ if (i != *ptr) -+ printk("*ptr!=i, *ptr=%d, i=%d\n", *ptr, i); -+ if (i%32 == 0) { -+ if (i%128 == 0) -+ printk("\n"); -+ printk("*ptr=%04d, i=%04d | ", *ptr, i); -+ } -+ ptr++; -+ } -+ printk("\n"); -+ break; -+ } -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return 0; -+} -+ -+/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -+static int cim_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -+ -+ /* frame buffer memory */ -+ start = cim_dev->frame_desc->framebuf; -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + (cim_dev->frame_desc->dmacmd & CIM_CMD_LEN_MASK)); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ off += start; -+ -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ -+#if defined(CONFIG_MIPS32) -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NO_WA; /* WT cachable */ -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; -+#endif -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot)) -+ vma->vm_flags |= VM_IO; -+ return -EAGAIN; -+ -+ return 0; -+} -+/*========================================================================== -+ * Interrupt handler -+ *========================================================================*/ -+ -+static irqreturn_t cim_irq_handler(int irq, void *dev_id) -+{ -+ u32 state = REG_CIM_STATE; -+ dprintk("REG_CIM_STATE = %x\n", REG_CIM_STATE); -+ dprintk("REG_CIM_CTRL = %x\n", REG_CIM_CTRL); -+#if 1 -+ if (state & CIM_STATE_RXF_OF) { -+ dprintk("OverFlow interrupt!\n"); -+ } -+#endif -+ if (state & CIM_STATE_DMA_EOF) { -+ dprintk("EOF interrupt!\n"); -+ __cim_disable_dma(); -+ __cim_disable(); -+ wake_up_interruptible(&cim_dev->wait_queue); -+ dprintk("EOF interrupt wake up!\n"); -+ } -+ -+ if (state & CIM_STATE_DMA_STOP) { -+ // Got a frame, wake up wait routine -+ __cim_disable_dma(); -+ __cim_disable(); -+ dprintk("Stop interrupt!\n"); -+ wake_up_interruptible(&cim_dev->wait_queue); -+ } -+#if 1 -+ if (state & CIM_STATE_RXF_TRIG) { -+ dprintk("Trig!\n"); -+ } -+#endif -+ -+ /* clear status flags*/ -+ REG_CIM_STATE = 0; -+ return IRQ_HANDLED; -+} -+ -+static int v4l_device_init(void) -+{ -+ cim_dev = kzalloc(sizeof(struct cim_device), GFP_KERNEL); -+ if (!cim_dev) return -ENOMEM; -+ cim_dev->jz_cim = video_device_alloc(); -+ if (!cim_dev->jz_cim) { -+ return -ENOMEM; -+ } -+ memcpy(cim_dev->jz_cim, &jz_v4l_device, sizeof(struct video_device)); -+ cim_dev->frame_desc = NULL; -+ cim_dev->frame_size = 0; -+ cim_dev->page_order = 0; -+ return 0; -+} -+/*========================================================================== -+ * Module init and exit -+ *========================================================================*/ -+ -+static int __init jz_cim_init(void) -+{ -+ struct cim_device *dev; -+ int ret; -+ /* allocate device */ -+ ret = v4l_device_init(); -+ if (ret) -+ return ret; -+ /* record device */ -+ dev = cim_dev; -+ init_waitqueue_head(&dev->wait_queue); -+ -+ ret = video_register_device(dev->jz_cim, VFL_TYPE_GRABBER, -1); -+ if (ret < 0) { -+ printk(KERN_ERR "CIM Video4Linux-device " -+ "registration failed\n"); -+ return -EINVAL; -+ } -+ -+ if (ret < 0) { -+ cim_fb_destroy(); -+ kfree(dev); -+ return ret; -+ } -+ -+ if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, -+ CIM_NAME, dev))) { -+ printk(KERN_ERR "request_irq return error, ret=%d\n", ret); -+ cim_fb_destroy(); -+ kfree(dev); -+ printk(KERN_ERR "CIM could not get IRQ\n"); -+ return ret; -+ } -+ -+ printk("JzSOC Camera Interface Module (CIM) driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit jz_cim_exit(void) -+{ -+ free_irq(IRQ_CIM, cim_dev); -+ kfree(cim_dev); -+ video_unregister_device(cim_dev->jz_cim); -+} -+ -+module_init(jz_cim_init); -+module_exit(jz_cim_exit); -diff --git a/drivers/media/video/jz4740_cim.c b/drivers/media/video/jz4740_cim.c -new file mode 100644 -index 0000000..4ea0594 ---- /dev/null -+++ b/drivers/media/video/jz4740_cim.c -@@ -0,0 +1,622 @@ -+/* -+ * linux/drivers/char/jzchar/cim.c -+ * -+ * Camera Interface Module (CIM) driver for JzSOC -+ * This driver is independent of the camera sensor -+ * -+ * Copyright (C) 2005 JunZheng semiconductor -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+//#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define CIM_NAME "cim" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("JzSOC Camera Interface Module driver"); -+MODULE_LICENSE("GPL"); -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+/* -+ * Define the Max Image Size -+ */ -+#define MAX_IMAGE_WIDTH 2048 -+#define MAX_IMAGE_HEIGHT 2048 -+#define MAX_IMAGE_BPP 16 -+#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP / 8) -+#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -+ -+typedef struct -+{ -+ u32 width; -+ u32 height; -+ u32 bpp; -+} img_param_t; -+ -+typedef struct -+{ -+ u32 cfg; -+ u32 ctrl; -+ u32 mclk; -+} cim_config_t; -+ -+/* -+ * IOCTL_XXX commands -+ */ -+#define IOCTL_SET_IMG_PARAM 0 // arg type: img_param_t * -+#define IOCTL_CIM_CONFIG 1 // arg type: cim_config_t * -+#define IOCTL_STOP_CIM 2 // arg type: void -+#define IOCTL_GET_IMG_PARAM 3 // arg type: img_param_t * -+#define IOCTL_GET_CIM_CONFIG 4 // arg type: cim_config_t * -+#define IOCTL_TEST_CIM_RAM 5 // no arg type * -+ -+/* -+ * CIM DMA descriptor -+ */ -+struct cim_desc { -+ u32 nextdesc; /* Physical address of next desc */ -+ u32 framebuf; /* Physical address of frame buffer */ -+ u32 frameid; /* Frame ID */ -+ u32 dmacmd; /* DMA command */ -+ u32 pagenum; -+}; -+ -+/* -+ * CIM device structure -+ */ -+struct cim_device { -+ struct video_device *jz_cim; -+ unsigned char *framebuf; -+ unsigned int frame_size; -+ unsigned int page_order; -+ wait_queue_head_t wait_queue; -+ struct cim_desc *frame_desc __attribute__ ((aligned (16))); -+}; -+ -+/* global*/ -+static struct cim_device *cim_dev; -+ -+/*========================================================================== -+ * CIM init routines -+ *========================================================================*/ -+#if defined(CONFIG_SOC_JZ4750) -+static void cim_image_area(img_param_t *c) { -+ /*set the image data area start 0, 0, lines_per_frame and pixels_per_line*/ -+ REG_CIM_SIZE = 0; -+ REG_CIM_OFFSET = 0; -+ if (REG_CIM_CTRL & CIM_CTRL_SIZEEN_MASK) { -+ REG_CIM_SIZE = (c->height << CIM_SIZE_LPF_BIT) | (c->width << CIM_SIZE_PPL_BIT); -+ REG_CIM_OFFSET = (0 << CIM_OFFSET_V_BIT) | (0 << CIM_OFFSET_H_BIT); -+// REG_CIM_OFFSET = (100 << CIM_OFFSET_V_BIT) | (50 << CIM_OFFSET_H_BIT); -+ } -+} -+#endif -+ -+static void cim_config(cim_config_t *c) -+{ -+ REG_CIM_CFG = c->cfg; -+ REG_CIM_CTRL = c->ctrl; -+ -+ /*Set the master clock output*/ -+#if defined(CONFIG_SOC_JZ4730) -+ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -+#elif defined(CONFIG_SOC_JZ4740) -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#elif defined(CONFIG_SOC_JZ4750) -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#else -+ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+#endif -+ /* Enable sof, eof and stop interrupts*/ -+ __cim_enable_sof_intr(); -+ __cim_enable_eof_intr(); -+ __cim_enable_stop_intr(); -+} -+ -+/*========================================================================== -+ * CIM start/stop operations -+ *========================================================================*/ -+static int cim_start_dma(char *ubuf) -+{ -+ struct cim_desc *jz_frame_desc; -+ int cim_frame_size = 0; -+ jz_frame_desc = cim_dev->frame_desc; -+ dprintk("framedesc = %x\n", (u32) jz_frame_desc); -+ __cim_disable(); -+ dprintk("__cim_disable\n"); -+ __cim_set_da(virt_to_phys(cim_dev->frame_desc)); -+ __cim_clear_state(); // clear state register -+ __cim_reset_rxfifo(); // resetting rxfifo -+ __cim_unreset_rxfifo(); -+ __cim_enable_dma(); // enable dma -+ __cim_enable(); -+ -+ dprintk("__cim_enable\n"); -+// while(1) { -+// mdelay(10); -+// dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -+// dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -+// dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -+// dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -+// dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -+// dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -+// dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -+// dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -+// dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -+// mdelay(100); -+// } -+ // wait for interrupts -+ interruptible_sleep_on(&cim_dev->wait_queue); -+ dprintk("interruptible_sleep_on\n"); -+ dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -+ dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -+ dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -+ dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -+ dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -+ dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -+ dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -+ dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -+ dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -+ dprintk("REG_CIM_CMD_3 = %x\n", REG_CIM_CMD); -+ dprintk("REG_CIM_FA = %x\n", REG_CIM_FA); -+ /* copy frame data to user buffer */ -+ jz_frame_desc = cim_dev->frame_desc; -+ -+ while(jz_frame_desc != NULL) -+ { -+ dprintk("ubuf = %x, framebuf = %x,frame_size= %d\n", (u32)ubuf,(u32) jz_frame_desc->framebuf, jz_frame_desc->dmacmd & 0xffffff); -+ memcpy(ubuf, phys_to_virt(jz_frame_desc->framebuf), ((jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4)); -+ ubuf += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -+ cim_frame_size += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -+ jz_frame_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -+ } -+ return cim_dev->frame_size; -+} -+static void cim_stop(void) -+{ -+ __cim_disable(); -+ __cim_clear_state(); -+} -+ -+/*========================================================================== -+ * Framebuffer allocation and destroy -+ *========================================================================*/ -+static void cim_fb_destroy(void) -+{ -+ int pages; -+ struct cim_desc *jz_frame_desc, *p_desc; -+ if (cim_dev->frame_desc == NULL) { -+ printk("Original memory is NULL\n"); -+ return; -+ } -+ jz_frame_desc = cim_dev->frame_desc; -+ while (jz_frame_desc != NULL) { -+ dprintk("framebuf = %x,thisdesc = %x,frame_size= %d\n", (u32) jz_frame_desc->framebuf, (unsigned int)jz_frame_desc, (jz_frame_desc->dmacmd & 0xffffff) * 4); -+ p_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -+ pages = jz_frame_desc->pagenum; -+ dprintk("page_order = %d\n", pages); -+ free_pages((unsigned long)phys_to_virt(jz_frame_desc->framebuf), pages); -+ kfree(jz_frame_desc); -+ jz_frame_desc = p_desc; -+ } -+ cim_dev->frame_desc = NULL; -+} -+ -+static struct cim_desc *get_desc_list(int page_order) -+{ -+ int num, page_nums = 0; -+ unsigned char *p_buf; -+ struct cim_desc *desc_list_head __attribute__ ((aligned (16))); -+ struct cim_desc *desc_list_tail __attribute__ ((aligned (16))); -+ struct cim_desc *p_desc; -+// num = page_order - 1; -+ num = page_order; -+ desc_list_head = desc_list_tail = NULL; -+ -+ while(page_nums < (1 << page_order)) { -+ p_desc = (struct cim_desc *)kmalloc(sizeof(struct cim_desc), GFP_KERNEL); -+ if (NULL == p_desc) -+ return NULL; -+ //return -ENOMEM; -+ cim_realloc_pages: -+ p_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, num); -+ if ( !(p_buf) && num != 0) { -+ num --; -+ goto cim_realloc_pages; -+ } -+ else if ( !(p_buf) && num == 0) { -+ printk("No memory can be alloc!\n"); -+ //return -ENOMEM; -+ return NULL; -+ } -+ else { -+ if (desc_list_head == NULL) { -+ dprintk("Page_list_head\n"); -+ desc_list_head = p_desc; -+ } -+ -+ else -+ desc_list_tail->nextdesc = virt_to_phys(p_desc); -+ -+ desc_list_tail = p_desc; -+ desc_list_tail->framebuf = virt_to_phys(p_buf); -+ dprintk("framebuf addr is 0x%08x\n", (u32)desc_list_tail->framebuf); -+ dprintk("frame_desc addr is 0x%08x\n",(u32)virt_to_phys(desc_list_tail)); -+ -+ desc_list_tail->frameid = 0x52052018; -+ desc_list_tail->pagenum = num; -+ if ((page_nums + (1<< num)) < (1 << page_order)) { -+ desc_list_tail->dmacmd = ((1 << num) * 4096) >> 2 ; -+ } -+ else -+ desc_list_tail->dmacmd = -+ (cim_dev->frame_size - page_nums * 4096) >> 2 ; -+ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -+ page_nums += (1 << num); -+ dprintk("the pages_num is %d\n", page_nums); -+ } -+ } -+ -+ desc_list_tail->nextdesc = virt_to_phys(NULL); -+ /* stop after capturing a frame */ -+ desc_list_tail->dmacmd |= (CIM_CMD_STOP | CIM_CMD_EOFINT); -+ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -+ -+ return desc_list_head; -+} -+ -+static int cim_fb_alloc(int img_width, int img_height, int img_bpp) -+{ -+#if defined(CONFIG_SOC_JZ4750) -+ if ((REG_CIM_CFG & (CIM_CFG_DF_MASK | CIM_CFG_BYPASS_MASK)) == 0) -+ cim_dev->frame_size = img_width * (img_height-1) * (img_bpp/8); -+ else -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+#else -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+#endif -+ cim_dev->page_order = get_order(cim_dev->frame_size); -+ dprintk("cim_dev->page_order=%d\n", cim_dev->page_order); -+ /* frame buffer ?? need large mem ??*/ -+ cim_dev->frame_desc = get_desc_list(cim_dev->page_order); -+ if (cim_dev->frame_desc == NULL) -+ return -ENOMEM; -+ dma_cache_wback((unsigned long)(cim_dev->frame_desc), 16); -+ return 0; -+} -+ -+/*========================================================================== -+ * File operations -+ *========================================================================*/ -+ -+static int cim_open(struct inode *inode, struct file *filp); -+static int cim_release(struct inode *inode, struct file *filp); -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -+static int cim_mmap(struct file *file, struct vm_area_struct *vma); -+ -+static struct file_operations cim_fops = -+{ -+ open: cim_open, -+ release: cim_release, -+ read: cim_read, -+ write: cim_write, -+ ioctl: cim_ioctl, -+ compat_ioctl: v4l_compat_ioctl32, -+ mmap: cim_mmap -+}; -+ -+static struct video_device jz_v4l_device = { -+ .name = "jz cim", -+ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | -+ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY -+ .fops = &cim_fops, -+ .minor = -1, -+ .owner = THIS_MODULE, -+ .release = video_device_release, -+}; -+ -+static int cim_open(struct inode *inode, struct file *filp) -+{ -+ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int cim_release(struct inode *inode, struct file *filp) -+{ -+ cim_fb_destroy(); -+ cim_stop(); -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ if (size < cim_dev->frame_size) -+ return -EINVAL; -+ dprintk("read cim\n"); -+ return cim_start_dma(buf); -+} -+ -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("cim error: write is not implemented\n"); -+ return -1; -+} -+ -+static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ void __user *argp = (void __user *)arg; -+ switch (cmd) { -+ case IOCTL_GET_IMG_PARAM: -+ { -+ img_param_t i; -+ return copy_to_user(argp, &i, sizeof(img_param_t)) ? -EFAULT : 0; -+ } -+ case IOCTL_SET_IMG_PARAM: -+ { -+ img_param_t i; -+ int img_width, img_height, img_bpp; -+ if (copy_from_user((void *)&i, (void *)arg, sizeof(img_param_t))) -+ return -EFAULT; -+#if defined(CONFIG_SOC_JZ4750) -+ cim_image_area(&i); -+#endif -+ img_width = i.width; -+ img_height = i.height; -+ img_bpp = i.bpp; -+ dprintk("ioctl_set_cim_param\n"); -+ if ((img_width * img_height * img_bpp/8) > MAX_FRAME_SIZE){ -+ printk("ERROR! Image is too large!\n"); -+ return -EINVAL; -+ } -+ /* allocate frame buffers */ -+ if (cim_dev->frame_desc == NULL){ -+ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -+ printk("ERROR! Init & alloc cim fail!\n"); -+ return -ENOMEM; -+ } -+ } -+ else -+ if ((img_width * img_height * img_bpp/8) > cim_dev->frame_size){ -+ /* realloc the buffer */ -+ cim_fb_destroy(); -+ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -+ printk("ERRROR! Init & alloc cim fail!\n"); -+ return -ENOMEM; -+ } -+ } -+ break; -+ } -+ case IOCTL_CIM_CONFIG: -+ { -+ cim_config_t c; -+ -+ if (copy_from_user((void *)&c, (void *)arg, sizeof(cim_config_t))) -+ return -EFAULT; -+ -+ cim_config(&c); -+ -+ break; -+ } -+ case IOCTL_TEST_CIM_RAM: -+ { -+ -+ int i; -+ volatile unsigned int *ptr; -+ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -+ printk("RAM test!\n"); -+ printk("CIM_RAM_ADDR = 0x%08x\n", CIM_RAM_ADDR); -+ for (i = 0; i < 1024; ptr++, i++) -+ *ptr = i; -+ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -+ dma_cache_wback((unsigned long)CIM_RAM_ADDR,0xffc); -+ -+ for (i = 0; i < 1024; i++) { -+ if (i != *ptr) -+ printk("*ptr!=i, *ptr=%d, i=%d\n", *ptr, i); -+ if (i%32 == 0) { -+ if (i%128 == 0) -+ printk("\n"); -+ printk("*ptr=%04d, i=%04d | ", *ptr, i); -+ } -+ ptr++; -+ } -+ printk("\n"); -+ break; -+ } -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return 0; -+} -+ -+/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -+static int cim_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -+ -+ /* frame buffer memory */ -+ start = cim_dev->frame_desc->framebuf; -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + (cim_dev->frame_desc->dmacmd & CIM_CMD_LEN_MASK)); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ off += start; -+ -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ -+#if defined(CONFIG_MIPS32) -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NO_WA; /* WT cachable */ -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; -+#endif -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot)) -+ vma->vm_flags |= VM_IO; -+ return -EAGAIN; -+ -+ return 0; -+} -+/*========================================================================== -+ * Interrupt handler -+ *========================================================================*/ -+ -+static irqreturn_t cim_irq_handler(int irq, void *dev_id) -+{ -+ u32 state = REG_CIM_STATE; -+ dprintk("REG_CIM_STATE = %x\n", REG_CIM_STATE); -+ dprintk("REG_CIM_CTRL = %x\n", REG_CIM_CTRL); -+#if 1 -+ if (state & CIM_STATE_RXF_OF) { -+ dprintk("OverFlow interrupt!\n"); -+ } -+#endif -+ if (state & CIM_STATE_DMA_EOF) { -+ dprintk("EOF interrupt!\n"); -+ __cim_disable_dma(); -+ __cim_disable(); -+ wake_up_interruptible(&cim_dev->wait_queue); -+ dprintk("EOF interrupt wake up!\n"); -+ } -+ -+ if (state & CIM_STATE_DMA_STOP) { -+ // Got a frame, wake up wait routine -+ __cim_disable_dma(); -+ __cim_disable(); -+ dprintk("Stop interrupt!\n"); -+ wake_up_interruptible(&cim_dev->wait_queue); -+ } -+#if 1 -+ if (state & CIM_STATE_RXF_TRIG) { -+ dprintk("Trig!\n"); -+ } -+#endif -+ -+ /* clear status flags*/ -+ REG_CIM_STATE = 0; -+ return IRQ_HANDLED; -+} -+ -+static int v4l_device_init(void) -+{ -+ cim_dev = kzalloc(sizeof(struct cim_device), GFP_KERNEL); -+ if (!cim_dev) return -ENOMEM; -+ cim_dev->jz_cim = video_device_alloc(); -+ if (!cim_dev->jz_cim) { -+ return -ENOMEM; -+ } -+ memcpy(cim_dev->jz_cim, &jz_v4l_device, sizeof(struct video_device)); -+ cim_dev->frame_desc = NULL; -+ cim_dev->frame_size = 0; -+ cim_dev->page_order = 0; -+ return 0; -+} -+/*========================================================================== -+ * Module init and exit -+ *========================================================================*/ -+ -+static int __init jz_cim_init(void) -+{ -+ struct cim_device *dev; -+ int ret; -+ /* allocate device */ -+ ret = v4l_device_init(); -+ if (ret) -+ return ret; -+ /* record device */ -+ dev = cim_dev; -+ init_waitqueue_head(&dev->wait_queue); -+ -+ ret = video_register_device(dev->jz_cim, VFL_TYPE_GRABBER, -1); -+ if (ret < 0) { -+ printk(KERN_ERR "CIM Video4Linux-device " -+ "registration failed\n"); -+ return -EINVAL; -+ } -+ -+ if (ret < 0) { -+ cim_fb_destroy(); -+ kfree(dev); -+ return ret; -+ } -+ -+ if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, -+ CIM_NAME, dev))) { -+ printk(KERN_ERR "request_irq return error, ret=%d\n", ret); -+ cim_fb_destroy(); -+ kfree(dev); -+ printk(KERN_ERR "CIM could not get IRQ\n"); -+ return ret; -+ } -+ -+ printk("JzSOC Camera Interface Module (CIM) driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit jz_cim_exit(void) -+{ -+ free_irq(IRQ_CIM, cim_dev); -+ kfree(cim_dev); -+ video_unregister_device(cim_dev->jz_cim); -+} -+ -+module_init(jz_cim_init); -+module_exit(jz_cim_exit); -diff --git a/drivers/media/video/jz4750_cim.c b/drivers/media/video/jz4750_cim.c -new file mode 100644 -index 0000000..7edf285 ---- /dev/null -+++ b/drivers/media/video/jz4750_cim.c -@@ -0,0 +1,734 @@ -+/* -+ * linux/drivers/char/jzchar/cim.c -+ * -+ * Camera Interface Module (CIM) driver for JzSOC -+ * This driver is independent of the camera sensor -+ * -+ * Copyright (C) 2005 JunZheng semiconductor -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+//#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "jz4750_cim.h" -+ -+#define CIM_NAME "cim" -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("JzSOC Camera Interface Module driver"); -+MODULE_LICENSE("GPL"); -+ -+#if defined(CONFIG_SOC_JZ4750D) -+//#define USE_CIM_OFRCV 1 /* Test overflow recovery */ -+#define USE_CIM_DMA_SYNC 1 //set da every time -+#endif -+ -+//#define CIM_DEBUG -+#undef CIM_DEBUG -+#ifdef CIM_DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+/* -+ * Define the Max Image Size -+ */ -+#define MAX_IMAGE_WIDTH 2048 -+#define MAX_IMAGE_HEIGHT 2048 -+#define MAX_IMAGE_BPP 16 -+#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP / 8) -+#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -+ -+typedef struct -+{ -+ u32 width; -+ u32 height; -+ u32 bpp; -+} img_param_t; -+ -+typedef struct -+{ -+ u32 cfg; -+ u32 ctrl; -+ u32 mclk; -+ u32 size; -+ u32 offs; -+} cim_config_t; -+ -+/* -+ * IOCTL_XXX commands -+ */ -+#define IOCTL_SET_IMG_PARAM 0 // arg type: img_param_t * -+#define IOCTL_CIM_CONFIG 1 // arg type: cim_config_t * -+#define IOCTL_STOP_CIM 2 // arg type: void -+#define IOCTL_GET_IMG_PARAM 3 // arg type: img_param_t * -+#define IOCTL_GET_CIM_CONFIG 4 // arg type: cim_config_t * -+#define IOCTL_TEST_CIM_RAM 5 // no arg type * -+#define IOCTL_START_CIM 6 // arg type: void -+ -+/* -+ * CIM DMA descriptor -+ */ -+struct cim_desc { -+ u32 nextdesc; /* Physical address of next desc */ -+ u32 framebuf; /* Physical address of frame buffer */ -+ u32 frameid; /* Frame ID */ -+ u32 dmacmd; /* DMA command */ -+ u32 pagenum; -+}; -+ -+/* -+ * CIM device structure -+ */ -+struct cim_device { -+ struct video_device *jz_cim; -+ unsigned char *framebuf; -+ unsigned int frame_size; -+ unsigned int page_order; -+ wait_queue_head_t wait_queue; -+ struct cim_desc *frame_desc __attribute__ ((aligned (16))); -+}; -+ -+/* global*/ -+static struct cim_device *cim_dev; -+static int start_init = 1; -+static int irq_sleep; -+/*========================================================================== -+ * CIM init routines -+ *========================================================================*/ -+ -+static void cim_image_area(img_param_t *c) { -+ /*set the image data area start 0, 0, lines_per_frame and pixels_per_line*/ -+ REG_CIM_SIZE = 0; -+ REG_CIM_OFFSET = 0; -+#if defined(CONFIG_SOC_JZ4750D) -+ if (REG_CIM_CTRL & CIM_CTRL_WIN_EN) { -+ REG_CIM_SIZE = (c->height << CIM_SIZE_LPF_BIT) | (c->width << CIM_SIZE_PPL_BIT); -+// REG_CIM_OFFSET = (0 << CIM_OFFSET_V_BIT) | (0 << CIM_OFFSET_H_BIT); -+// REG_CIM_OFFSET = (100 << CIM_OFFSET_V_BIT) | (50 << CIM_OFFSET_H_BIT); -+ REG_CIM_OFFSET = (200 << CIM_OFFSET_V_BIT) | (300 << CIM_OFFSET_H_BIT); -+ } -+#endif -+} -+ -+ -+static void cim_config(cim_config_t *c) -+{ -+ REG_CIM_CFG = c->cfg; -+ REG_CIM_CTRL = c->ctrl; -+ REG_CIM_SIZE = c->size; -+ REG_CIM_OFFSET = c->offs; -+ -+ dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -+ dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -+ /* Set the master clock output */ -+ /* If use pll clock, enable it */ -+// __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -+ -+ /* Enable sof, eof and stop interrupts*/ -+ -+// __cim_enable_sof_intr(); -+ __cim_enable_eof_intr(); -+#if defined(USE_CIM_EEOFINT) -+ __cim_enable_eeof_intr(); -+#endif -+// __cim_enable_stop_intr(); -+// __cim_enable_trig_intr(); -+// __cim_enable_rxfifo_overflow_intr(); -+// __cim_enable_vdd_intr(); -+// printk("hclk=%d, mclk = %d\n", __cpm_get_hclk(),c->mclk); -+ dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -+} -+ -+/*========================================================================== -+ * CIM start/stop operations -+ *========================================================================*/ -+static int cim_start_dma(char *ubuf) -+{ -+ -+ struct cim_desc *jz_frame_desc; -+ int cim_frame_size = 0; -+ dprintk("==========start_init = %d\n", start_init); -+ __cim_disable(); -+ __cim_set_da(virt_to_phys(cim_dev->frame_desc)); -+ __cim_clear_state(); // clear state register -+ __cim_reset_rxfifo(); // resetting rxfifo -+ __cim_unreset_rxfifo(); -+ __cim_enable_dma(); // enable dma -+ __cim_enable(); -+ interruptible_sleep_on(&cim_dev->wait_queue); -+ -+#if 1 -+ dprintk("interruptible_sleep_on\n"); -+ dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -+ dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -+ dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -+ dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -+ dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -+ dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -+ dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -+ dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -+ dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -+ dprintk("REG_CIM_CMD_3 = %x\n", REG_CIM_CMD); -+ dprintk("REG_CIM_FA = %x\n", REG_CIM_FA); -+#endif -+ /* copy frame data to user buffer */ -+#if 0 -+ jz_frame_desc = cim_dev->frame_desc; -+ -+ while (jz_frame_desc != NULL) -+ { -+ dprintk("ubuf = %x, framebuf = %x,frame_size= %d\n", (u32)ubuf,(u32) jz_frame_desc->framebuf, jz_frame_desc->dmacmd & 0xffffff); -+ memcpy(ubuf, phys_to_virt(jz_frame_desc->framebuf), ((jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4)); -+ ubuf += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -+ cim_frame_size += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -+ jz_frame_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -+ } -+#endif -+ dprintk("---------**********-----\n"); -+ return cim_dev->frame_size; -+} -+static void cim_stop(void) -+{ -+ __cim_disable(); -+ __cim_clear_state(); -+} -+ -+/*========================================================================== -+ * Framebuffer allocation and destroy -+ *========================================================================*/ -+static void cim_fb_destroy(void) -+{ -+ int pages; -+ struct cim_desc *jz_frame_desc, *p_desc; -+ __cim_disable_dma(); -+ __cim_disable(); -+ -+ dprintk("cim_dev->frame_desc = %x\n", (u32)cim_dev->frame_desc); -+ if (cim_dev->frame_desc == NULL) { -+ printk("Original memory is NULL\n"); -+ return; -+ } -+ jz_frame_desc = cim_dev->frame_desc; -+// while (jz_frame_desc != NULL) { -+// while (jz_frame_desc != cim_dev->frame_desc) { -+ dprintk("framebuf = %x,thisdesc = %x,frame_size= %d\n", (u32) jz_frame_desc->framebuf, (unsigned int)jz_frame_desc, (jz_frame_desc->dmacmd & 0xffffff) * 4); -+ p_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -+ pages = jz_frame_desc->pagenum; -+ dprintk("page_order = %d\n", pages); -+ free_pages((unsigned long)phys_to_virt(jz_frame_desc->framebuf), pages); -+ kfree(jz_frame_desc); -+ jz_frame_desc = p_desc; -+// } -+ cim_dev->frame_desc = NULL; -+ start_init = 1; -+} -+ -+static struct cim_desc *get_desc_list(int page_order) -+{ -+ int num, page_nums = 0; -+ unsigned char *p_buf; -+ struct cim_desc *desc_list_head __attribute__ ((aligned (16))); -+ struct cim_desc *desc_list_tail __attribute__ ((aligned (16))); -+ struct cim_desc *p_desc; -+// num = page_order - 1; -+ num = page_order; -+ desc_list_head = desc_list_tail = NULL; -+ -+ while(page_nums < (1 << page_order)) { -+ p_desc = (struct cim_desc *)kmalloc(sizeof(struct cim_desc), GFP_KERNEL); -+ if (NULL == p_desc) -+ return NULL; -+ //return -ENOMEM; -+ cim_realloc_pages: -+ p_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, num); -+ if ( !(p_buf) && num != 0) { -+ num --; -+ goto cim_realloc_pages; -+ } -+ else if ( !(p_buf) && num == 0) { -+ printk("No memory can be alloc!\n"); -+ //return -ENOMEM; -+ return NULL; -+ } -+ else { -+ if (desc_list_head == NULL) { -+ dprintk("Page_list_head\n"); -+ desc_list_head = p_desc; -+ } -+ -+ else -+ desc_list_tail->nextdesc = virt_to_phys(p_desc); -+ -+ desc_list_tail = p_desc; -+ desc_list_tail->framebuf = virt_to_phys(p_buf); -+ dprintk("framebuf addr is 0x%08x\n", (u32)desc_list_tail->framebuf); -+ dprintk("frame_desc addr is 0x%08x\n",(u32)virt_to_phys(desc_list_tail)); -+ -+ desc_list_tail->frameid = 0x52052018; -+ desc_list_tail->pagenum = num; -+ if ((page_nums + (1<< num)) < (1 << page_order)) { -+ desc_list_tail->dmacmd = ((1 << num) * 4096) >> 2 ; -+ } -+ else -+ desc_list_tail->dmacmd = -+ (cim_dev->frame_size - page_nums * 4096) >> 2 ; -+ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -+ page_nums += (1 << num); -+ dprintk("the pages_num is %d\n", page_nums); -+ dma_cache_wback((unsigned long)(desc_list_tail), 16); -+ } -+ } -+ -+// desc_list_tail->nextdesc = virt_to_phys(NULL); -+ desc_list_tail->nextdesc = virt_to_phys(desc_list_head); -+ desc_list_tail->dmacmd |= CIM_CMD_EOFINT; -+#if defined(CONFIG_SOC_JZ4750D) -+#if defined(USE_CIM_OFRCV) -+ desc_list_tail->dmacmd |= (CIM_CMD_EOFINT | CIM_CMD_OFRCV); -+#endif -+#if defined(USE_CIM_DMA_SYNC) /* wake ervry time */ -+ desc_list_tail->nextdesc = virt_to_phys(NULL); -+ desc_list_tail->dmacmd |= (CIM_CMD_STOP | CIM_CMD_EOFINT | CIM_CMD_OFRCV); -+#endif -+#if defined(USE_CIM_EEOFINT) -+// desc_list_tail->dmacmd |= CIM_CMD_EEOFINT; -+ desc_list_tail->dmacmd |= (CIM_CMD_STOP | CIM_CMD_EOFINT | CIM_CMD_EEOFINT); -+#endif -+#endif -+ /* stop after capturing a frame */ -+// desc_list_tail->dmacmd |= (CIM_CMD_STOP | CIM_CMD_EOFINT | CIM_CMD_SOFINT); -+ -+ -+ -+ -+ dma_cache_wback((unsigned long)(desc_list_tail), 16); -+ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -+ -+ return desc_list_head; -+} -+ -+static int cim_fb_alloc(int img_width, int img_height, int img_bpp) -+{ -+ if ((REG_CIM_CFG & (CIM_CFG_DF_MASK | CIM_CFG_BYPASS_MASK)) == 0) -+ cim_dev->frame_size = img_width * (img_height-1) * (img_bpp/8); -+ else -+ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -+ -+ cim_dev->page_order = get_order(cim_dev->frame_size); -+ dprintk("cim_dev->page_order=%d\n", cim_dev->page_order); -+ /* frame buffer ?? need large mem ??*/ -+ cim_dev->frame_desc = get_desc_list(cim_dev->page_order); -+ if (cim_dev->frame_desc == NULL) -+ return -ENOMEM; -+ dma_cache_wback((unsigned long)(cim_dev->frame_desc), 16); -+ return 0; -+} -+ -+/*========================================================================== -+ * File operations -+ *========================================================================*/ -+ -+static int cim_open(struct inode *inode, struct file *filp); -+static int cim_release(struct inode *inode, struct file *filp); -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -+static int cim_mmap(struct file *file, struct vm_area_struct *vma); -+ -+static struct file_operations cim_fops = -+{ -+ open: cim_open, -+ release: cim_release, -+ read: cim_read, -+ write: cim_write, -+ ioctl: cim_ioctl, -+ compat_ioctl: v4l_compat_ioctl32, -+ mmap: cim_mmap -+}; -+ -+static struct video_device jz_v4l_device = { -+ .name = "jz cim", -+ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | -+ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY -+ .fops = &cim_fops, -+ .minor = -1, -+ .owner = THIS_MODULE, -+ .release = video_device_release, -+}; -+ -+static int cim_open(struct inode *inode, struct file *filp) -+{ -+ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int cim_release(struct inode *inode, struct file *filp) -+{ -+ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -+ cim_fb_destroy(); -+ cim_stop(); -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ printk("============cim error: write is not implemented\n"); -+ if (size < cim_dev->frame_size) -+ return -EINVAL; -+ return cim_start_dma(buf); -+} -+ -+static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("cim error: write is not implemented\n"); -+ return -1; -+} -+ -+static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ void __user *argp = (void __user *)arg; -+ switch (cmd) { -+ case IOCTL_GET_IMG_PARAM: -+ { -+ unsigned int i; -+ i = cim_dev->frame_desc->framebuf; -+// printk("cim_dev->frame_desc->framebuf = 0x%08x\n", cim_dev->frame_desc->framebuf); -+ dprintk("&&cim_dev->frame_desc->framebuf = 0x%08x\n", i); -+ -+ return copy_to_user(argp, &i, sizeof(unsigned int)) ? -EFAULT : 0; -+ } -+ case IOCTL_STOP_CIM: -+ { -+ __cim_disable_dma(); // enable dma -+ __cim_disable(); -+ -+// cim_fb_destroy(); -+ return 0; -+ } -+ case IOCTL_START_CIM: -+ { -+ __cim_set_da(virt_to_phys(cim_dev->frame_desc)); -+ __cim_clear_state(); // clear state register -+ __cim_reset_rxfifo(); // resetting rxfifo -+ __cim_unreset_rxfifo(); -+ __cim_enable_dma(); // enable dma -+ __cim_enable(); -+ return 0; -+ } -+ case IOCTL_SET_IMG_PARAM: -+ { -+ img_param_t i; -+ int img_width, img_height, img_bpp; -+ if (copy_from_user((void *)&i, (void *)arg, sizeof(img_param_t))) -+ return -EFAULT; -+ img_width = i.width; -+ img_height = i.height; -+ img_bpp = i.bpp; -+ printk("ALLOC =========\n"); -+ if ((img_width * img_height * img_bpp/8) > MAX_FRAME_SIZE){ -+ printk("ERROR! Image is too large!\n"); -+ return -EINVAL; -+ } -+ /* allocate frame buffers */ -+ if (cim_dev->frame_desc == NULL){ -+ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -+ printk("ERROR! Init & alloc cim fail!\n"); -+ return -ENOMEM; -+ } -+ } -+ else -+ if ((img_width * img_height * img_bpp/8) > cim_dev->frame_size){ -+ /* realloc the buffer */ -+ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -+ cim_fb_destroy(); -+ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -+ printk("ERRROR! Init & alloc cim fail!\n"); -+ return -ENOMEM; -+ } -+ } -+ break; -+ } -+ case IOCTL_CIM_CONFIG: -+ { -+ cim_config_t c; -+ -+ if (copy_from_user((void *)&c, (void *)arg, sizeof(cim_config_t))) -+ return -EFAULT; -+ cim_config(&c); -+ -+ break; -+ } -+ case IOCTL_TEST_CIM_RAM: -+ { -+ -+ int i; -+ volatile unsigned int *ptr; -+ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -+ dprintk("RAM test!\n"); -+ dprintk("CIM_RAM_ADDR = 0x%08x\n", CIM_RAM_ADDR); -+ for (i = 0; i < 1024; ptr++, i++) -+ *ptr = i; -+ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -+ dma_cache_wback((unsigned long)CIM_RAM_ADDR,0xffc); -+ -+ for (i = 0; i < 1024; i++) { -+ if (i != *ptr) -+ dprintk("*ptr!=i, *ptr=%d, i=%d\n", *ptr, i); -+ if (i%32 == 0) { -+ if (i%128 == 0) -+ dprintk("\n"); -+ dprintk("*ptr=%04d, i=%04d | ", *ptr, i); -+ } -+ ptr++; -+ } -+ dprintk("\n"); -+ break; -+ } -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return 0; -+} -+ -+/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -+static int cim_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ -+ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ -+ /* frame buffer memory */ -+ start = cim_dev->frame_desc->framebuf; -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + (cim_dev->frame_desc->dmacmd & CIM_CMD_LEN_MASK)*4); -+ start &= PAGE_MASK; -+ printk("vma->vm_end = 0x%08lx,\nvma->vm_start = 0x%08lx,\noff = 0x%08lx,\n len = 0x%08x\n\n", vma->vm_end, vma->vm_start, off, len); -+ if ((vma->vm_end - vma->vm_start + off) > len) { -+ printk("Error: vma is larger than memory length\n"); -+ return -EINVAL; -+ } -+ off += start; -+ -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -+ -+#if defined(CONFIG_MIPS32) -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -+#endif -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot)) { -+ return -EAGAIN; -+ } -+ return 0; -+} -+/*========================================================================== -+ * Interrupt handler -+ *========================================================================*/ -+ -+static irqreturn_t cim_irq_handler(int irq, void *dev_id) -+{ -+ u32 state = REG_CIM_STATE; -+ dprintk("REG_CIM_STATE = %x\n", REG_CIM_STATE); -+ dprintk("IRQ:REG_CIM_CTRL = %x\n", REG_CIM_CTRL); -+ -+#if 0 //sof -+ /* recommed don't open it */ -+ if ((REG_CIM_CTRL & CIM_CTRL_DMA_SOFM) && (state & CIM_STATE_DMA_SOF)) { -+ dprintk("SOF interrupt!\n"); -+ REG_CIM_STATE &= ~CIM_STATE_DMA_SOF; -+ } -+#endif -+#if 0 //eeof -+ if ((REG_CIM_CTRL & CIM_CTRL_DMA_EEOFM) && (state & CIM_STATE_DMA_EEOF)) { -+ dprintk("EEOF interrupt!\n"); -+ __cim_disable_dma(); -+ __cim_disable(); -+ wake_up_interruptible(&cim_dev->wait_queue); -+ REG_CIM_STATE &= ~CIM_STATE_DMA_EEOF; -+ } -+#endif -+ -+#if 1 //eof -+ if ((REG_CIM_CTRL & CIM_CTRL_DMA_EOFM) && (state & CIM_STATE_DMA_EOF)) { -+// if (state & CIM_STATE_DMA_EOF) { -+ dprintk("EOF interrupt!\n"); -+ -+#if defined(USE_CIM_DMA_SYNC) /* wake ervry time */ -+// __cim_disable_dma(); -+// __cim_disable(); -+ wake_up_interruptible(&cim_dev->wait_queue); -+#else -+// if(irq_sleep == 1) -+ wake_up_interruptible(&cim_dev->wait_queue); -+#endif -+ REG_CIM_STATE &= ~CIM_STATE_DMA_EOF; -+ return IRQ_HANDLED; -+ } -+#endif -+#if 0 //overflow -+ if (state & CIM_STATE_RXF_OF) { -+ printk("OverFlow interrupt!\n"); -+ REG_CIM_STATE &= ~CIM_STATE_RXF_OF; -+// dprintk("REG_CIM_STATE = %x\n", REG_CIM_STATE); -+ return IRQ_HANDLED; -+ } -+#endif -+#if 1 // stop -+ if ((REG_CIM_CTRL & CIM_CTRL_DMA_STOPM) && (state & CIM_STATE_DMA_STOP)) { -+ // Got a frame, wake up wait routine -+//#if defined(USE_CIM_DMA_SYNC) /* wake ervry time */ -+ __cim_disable_dma(); -+// __cim_disable(); -+ -+ dprintk("Stop interrupt!\n"); -+// wake_up_interruptible(&cim_dev->wait_queue); -+ REG_CIM_STATE &= ~CIM_STATE_DMA_STOP; -+ } -+#endif -+ -+#if 0 //trig -+ if ((REG_CIM_CTRL & CIM_CTRL_RXF_TRIGM) && (state & CIM_STATE_RXF_TRIG)) { -+ REG_CIM_STATE &= ~CIM_STATE_RXF_TRIG; -+ dprintk("Trig interrupt!\n"); -+ } -+#endif -+ -+#if 0 //vdd -+ /* only happen disable cim during DMA transfer*/ -+ if ((REG_CIM_CTRL & CIM_CTRL_VDDM) && (state & CIM_STATE_VDD)) { -+ dprintk(">>CIM Disable Done Interrupt!\n"); -+ REG_CIM_STATE &= ~CIM_STATE_VDD; -+ } -+#endif -+ /* clear status flags*/ -+ dprintk("before clear REG_CIM_STATE = %x\n", REG_CIM_STATE); -+// REG_CIM_STATE = 0; -+ -+ return IRQ_HANDLED; -+} -+ -+/*Camera gpio init, different operationg according sensor*/ -+static void camera_gpio_init(void) { -+ -+ __gpio_as_cim(); -+ __gpio_as_i2c(); -+ __sensor_gpio_init(); -+} -+ -+static int v4l_device_init(void) -+{ -+ camera_gpio_init(); -+ cim_dev = kzalloc(sizeof(struct cim_device), GFP_KERNEL); -+ if (!cim_dev) return -ENOMEM; -+ cim_dev->jz_cim = video_device_alloc(); -+ if (!cim_dev->jz_cim) { -+ return -ENOMEM; -+ } -+ memcpy(cim_dev->jz_cim, &jz_v4l_device, sizeof(struct video_device)); -+ cim_dev->frame_desc = NULL; -+ cim_dev->frame_size = 0; -+ cim_dev->page_order = 0; -+ return 0; -+} -+/*========================================================================== -+ * Module init and exit -+ *========================================================================*/ -+ -+static int __init jz4750_cim_init(void) -+{ -+ struct cim_device *dev; -+ int ret; -+ /* allocate device */ -+ ret = v4l_device_init(); -+ if (ret) -+ return ret; -+ /* record device */ -+ dev = cim_dev; -+ init_waitqueue_head(&dev->wait_queue); -+ -+ ret = video_register_device(dev->jz_cim, VFL_TYPE_GRABBER, -1); -+ if (ret < 0) { -+ printk(KERN_ERR "CIM Video4Linux-device " -+ "registration failed\n"); -+ return -EINVAL; -+ } -+ -+ if (ret < 0) { -+ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -+ cim_fb_destroy(); -+ kfree(dev); -+ return ret; -+ } -+ -+ if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, -+ CIM_NAME, dev))) { -+ printk(KERN_ERR "request_irq return error, ret=%d\n", ret); -+ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -+ cim_fb_destroy(); -+ kfree(dev); -+ printk(KERN_ERR "CIM could not get IRQ\n"); -+ return ret; -+ } -+ -+ printk("JzSOC Camera Interface Module (CIM) driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit jz4750_cim_exit(void) -+{ -+ free_irq(IRQ_CIM, cim_dev); -+ kfree(cim_dev); -+ video_unregister_device(cim_dev->jz_cim); -+} -+ -+module_init(jz4750_cim_init); -+module_exit(jz4750_cim_exit); -diff --git a/drivers/media/video/jz4750_cim.h b/drivers/media/video/jz4750_cim.h -new file mode 100644 -index 0000000..7e73c7c ---- /dev/null -+++ b/drivers/media/video/jz4750_cim.h -@@ -0,0 +1,49 @@ -+/* -+ * linux/drivers/media/video/jz4750_cim.h -- Ingenic Jz4750 On-Chip CIM driver -+ * -+ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#ifndef __JZ4750_CIM_H__ -+#define __JZ4750_CIM_H__ -+ -+/* gpio init */ -+#if defined(CONFIG_JZ4750_APUS) || defined(CONFIG_JZ4750D_FUWA1) /* board pavo */ -+#define GPIO_CAMERA_RST (32*4+8) /* CIM_MCLK as reset */ -+#else -+#error "driver/video/Jzlcd.h, please define SPI pins on your board." -+#endif -+ -+#define CONFIG_OV9650 1 -+ -+#if defined(CONFIG_OV9650) || defined(CONFIG_OV2640) -+#if defined(CONFIG_JZ4750_APUS) /* board pavo */ -+#define __sensor_gpio_init() \ -+do {\ -+ __gpio_as_output(GPIO_CAMERA_RST); \ -+ __gpio_set_pin(GPIO_CAMERA_RST); \ -+ mdelay(50); \ -+ __gpio_clear_pin(GPIO_CAMERA_RST);\ -+} while(0) -+ -+#elif defined(CONFIG_JZ4750D_FUWA1) /* board pavo */ -+#define __sensor_gpio_init() \ -+do {\ -+ __gpio_as_output(GPIO_CAMERA_RST); \ -+ __gpio_set_pin(GPIO_CAMERA_RST); \ -+ mdelay(50); \ -+ __gpio_clear_pin(GPIO_CAMERA_RST);\ -+} while(0) -+#endif -+#endif -+ -+#ifndef __sensor_gpio_init -+#define __sensor_gpio_init() -+#endif -+#endif /* __JZ4750_CIM_H__ */ -+ -diff --git a/drivers/media/video/jz_cim.h b/drivers/media/video/jz_cim.h -new file mode 100644 -index 0000000..f72cfa4 ---- /dev/null -+++ b/drivers/media/video/jz_cim.h -@@ -0,0 +1,36 @@ -+/* -+ * JzSOC CIM driver -+ * -+ * Copyright (C) 2005 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef __JZ_CIM_H__ -+#define __JZ_CIM_H__ -+ -+typedef struct -+{ -+ u32 width; -+ u32 height; -+ u32 bpp; -+} IMG_PARAM; -+ -+/* -+ * IOCTL_XXX commands -+ */ -+#define IOCTL_SET_IMG_PARAM 0 // arg type: IMG_PARAM * -+ -+#endif /* __JZ__CIM_H__ */ -diff --git a/drivers/media/video/jz_sensor.c b/drivers/media/video/jz_sensor.c -new file mode 100644 -index 0000000..2d6005f ---- /dev/null -+++ b/drivers/media/video/jz_sensor.c -@@ -0,0 +1,202 @@ -+/* -+ * linux/drivers/char/jzchar/sensor.c -+ * -+ * Common CMOS Camera Sensor Driver -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+//#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+//#include -+//#include "jz-chars.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+MODULE_AUTHOR("Jianli Wei"); -+MODULE_DESCRIPTION("Common CMOS Camera Sensor Driver"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * ioctl commands -+ */ -+#define IOCTL_SET_ADDR 0 /* set i2c address */ -+#define IOCTL_SET_CLK 1 /* set i2c clock */ -+#define IOCTL_WRITE_REG 2 /* write sensor register */ -+#define IOCTL_READ_REG 3 /* read sensor register */ -+ -+/* -+ * i2c related -+ */ -+static unsigned int i2c_addr = 0x42; -+static unsigned int i2c_clk = 100000; -+ -+struct video_device *jz_sensor; -+ -+static void write_reg(u8 reg, u8 val) -+{ -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_write((i2c_addr >> 1), &val, reg, 1); -+ i2c_close(); -+} -+ -+static u8 read_reg(u8 reg) -+{ -+ u8 val; -+ -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_read((i2c_addr >> 1), &val, reg, 1); -+ i2c_close(); -+ return val; -+} -+ -+/* -+ * fops routines -+ */ -+ -+static int sensor_open(struct inode *inode, struct file *filp); -+static int sensor_release(struct inode *inode, struct file *filp); -+static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l); -+static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l); -+static int sensor_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations sensor_fops = -+{ -+ open: sensor_open, -+ release: sensor_release, -+ read: sensor_read, -+ write: sensor_write, -+ ioctl: sensor_ioctl, -+}; -+ -+static int sensor_open(struct inode *inode, struct file *filp) -+{ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int sensor_release(struct inode *inode, struct file *filp) -+{ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l) -+{ -+ printk("sensor: read is not implemented\n"); -+ return -1; -+} -+ -+static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l) -+{ -+ printk("sensor: write is not implemented\n"); -+ return -1; -+} -+ -+static int sensor_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ int ret = 0; -+ -+ switch (cmd) { -+ case IOCTL_SET_ADDR: -+ if (copy_from_user(&i2c_addr, (void *)arg, 4)) -+ return -EFAULT; -+ break; -+ case IOCTL_SET_CLK: -+ if (copy_from_user(&i2c_clk, (void *)arg, 4)) -+ return -EFAULT; -+ break; -+ case IOCTL_WRITE_REG: -+ { -+ u8 regval[2]; -+ -+ if (copy_from_user(regval, (void *)arg, 2)) -+ return -EFAULT; -+ -+ write_reg(regval[0], regval[1]); -+ break; -+ } -+ case IOCTL_READ_REG: -+ { -+ u8 reg, val; -+ -+ if (copy_from_user(®, (void *)arg, 1)) -+ return -EFAULT; -+ -+ val = read_reg(reg); -+ -+ if (copy_to_user((void *)(arg + 1), &val, 1)) -+ return -EFAULT; -+ break; -+ } -+ default: -+ printk("Not supported command: 0x%x\n", cmd); -+ return -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static struct video_device jz_v4l_device = { -+ .name = "jz sensor", -+ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | -+ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY -+ .fops = &sensor_fops, -+ .minor = -1, -+}; -+ -+/* -+ * Module init and exit -+ */ -+ -+static int __init jz_sensor_init(void) -+{ -+ int ret; -+// cim_dev = kzalloc(sizeof(struct cim_device), GFP_KERNEL); -+ jz_sensor = video_device_alloc(); -+ memcpy(jz_sensor, &jz_v4l_device, sizeof(struct video_device)); -+ jz_sensor->release = video_device_release; -+// ret = jz_register_chrdev(SENSOR_MINOR, "sensor", &sensor_fops, NULL); -+ ret = video_register_device(jz_sensor, VFL_TYPE_GRABBER, -1); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ printk("Ingenic CMOS camera sensor driver registered\n"); -+ -+ return 0; -+} -+ -+static void __exit jz_sensor_exit(void) -+{ -+// jz_unregister_chrdev(SENSOR_MINOR, "sensor"); -+ video_unregister_device(jz_sensor); -+} -+ -+module_init(jz_sensor_init); -+module_exit(jz_sensor_exit); -diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c -index 06084db..1185e08 100644 ---- a/drivers/mmc/core/mmc.c -+++ b/drivers/mmc/core/mmc.c -@@ -140,8 +140,13 @@ static int mmc_decode_csd(struct mmc_card *card) - - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); -- csd->capacity = (1 + m) << (e + 2); - -+#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -+ csd->capacity = (1 + m) << (e + 2); -+ csd->capacity -= 16384; -+#else -+ csd->capacity = (1 + m) << (e + 2); -+#endif - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); -diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c -index cd81c39..47033d7 100644 ---- a/drivers/mmc/core/sd.c -+++ b/drivers/mmc/core/sd.c -@@ -109,8 +109,13 @@ static int mmc_decode_csd(struct mmc_card *card) - - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); -- csd->capacity = (1 + m) << (e + 2); - -+#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -+ csd->capacity = (1 + m) << (e + 2); -+ csd->capacity -= 16384; -+#else -+ csd->capacity = (1 + m) << (e + 2); -+#endif - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); -@@ -137,8 +142,13 @@ static int mmc_decode_csd(struct mmc_card *card) - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - - m = UNSTUFF_BITS(resp, 48, 22); -- csd->capacity = (1 + m) << 10; - -+#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -+ csd->capacity = (1 + m) << 10; -+ csd->capacity -= 16384; -+#else -+ csd->capacity = (1 + m) << 10; -+#endif - csd->read_blkbits = 9; - csd->read_partial = 0; - csd->write_misalign = 0; -@@ -268,9 +278,11 @@ static int mmc_switch_hs(struct mmc_card *card) - goto out; - - if ((status[16] & 0xF) != 1) { -+#if 0 - printk(KERN_WARNING "%s: Problem switching card " - "into high-speed mode!\n", - mmc_hostname(card->host)); -+#endif - } else { - mmc_card_set_highspeed(card); - mmc_set_timing(card->host, MMC_TIMING_SD_HS); -@@ -417,6 +429,9 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, - goto free_card; - - mmc_decode_cid(card); -+ -+ /* set 24MHz clock again, why?? */ -+ mmc_set_clock(host, 24000000); - } - - /* -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 891ef18..c774b9a 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -4,6 +4,104 @@ - - comment "MMC/SD/SDIO Host Controller Drivers" - -+config MMC_JZ -+ tristate "JZ SD/Multimedia Card Interface support" -+ depends on SOC_JZ4730 || SOC_JZ4740 -+ help -+ This selects the Ingenic JZ4730/JZ4740 SD/Multimedia card Interface. -+ If you have abIngenic platform with a Multimedia Card slot, -+ say Y or M here. -+ -+ If unsure, say N. -+choice -+ depends on MMC_JZ -+ prompt "MMC BUS Width" -+ default JZ_MMC_BUS_4 -+ help -+ This defines the BUS Width of the Ingenic JZ4730/JZ4740 SD/Multimedia card Interface. -+ -+config JZ_MMC_BUS_1 -+ bool "1 Bit Bus" -+ help -+ 1 Bit SD/Multimedia Card Bus -+ -+config JZ_MMC_BUS_4 -+ bool "4 Bit Bus" -+ help -+ 4 Bit SD/Multimedia Card Bus -+ -+endchoice -+ -+config MSC0_JZ4750 -+ tristate "JZ4750 SD/Multimedia Card 0 Interface support" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ This selects the Ingenic JZ4750 SD/Multimedia card 0 Interface. -+ If you have a Ingenic platform with a Multimedia Card slot, -+ say Y or M here. -+ -+ If unsure, say N. -+ -+choice -+ depends on MSC0_JZ4750 -+ prompt "MSC0 BUS Width" -+ default JZ4750_MSC0_BUS_4 -+ help -+ This defines the BUS Width of the Ingenic JZ4750 SD/Multimedia card Interface. -+ -+config JZ4750_MSC0_BUS_1 -+ bool "1 Bit Bus" -+ help -+ 1 Bit SD/Multimedia Card Bus -+ -+config JZ4750_MSC0_BUS_4 -+ bool "4 Bit Bus" -+ help -+ 4 Bit SD/Multimedia Card Bus -+ -+config JZ4750_MSC0_BUS_8 -+ bool "8 Bit Bus" -+ help -+ 8 Bit Multimedia Card Bus -+ -+endchoice -+ -+config MSC1_JZ4750 -+ tristate "JZ4750 SD/Multimedia Card 1 Interface support" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ This selects the Ingenic JZ4750 SD/Multimedia card 1 Interface. -+ If you have a Ingenic platform with a Multimedia Card slot, -+ say Y or M here. -+ -+ If unsure, say N. -+ -+choice -+ depends on MSC1_JZ4750 -+ prompt "MSC1 BUS Width" -+ default JZ4750_MSC1_BUS_4 -+ help -+ This defines the BUS Width of the Ingenic JZ4750 SD/Multimedia card Interface. -+ -+config JZ4750_MSC1_BUS_1 -+ bool "1 Bit Bus" -+ help -+ 1 Bit SD/Multimedia Card Bus -+ -+config JZ4750_MSC1_BUS_4 -+ bool "4 Bit Bus" -+ help -+ 4 Bit SD/Multimedia Card Bus -+endchoice -+ -+config JZ4750_BOOT_FROM_MSC0 -+ tristate "JZ4750 Boot from SD/Multimedia Card Interface support" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ This selects boot from the Sd/Multimedia Card. -+ -+ If unsure,say N. -+ - config MMC_ARMMMCI - tristate "ARM AMBA Multimedia Card Interface support" - depends on ARM_AMBA -diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index cf153f6..92d76ab 100644 ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -6,6 +6,9 @@ ifeq ($(CONFIG_MMC_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG - endif - -+obj-$(CONFIG_MMC_JZ) += jz_mmc.o -+obj-$(CONFIG_MSC0_JZ4750) += jz4750_mmc.o -+obj-$(CONFIG_MSC1_JZ4750) += jz4750_mmc.o - obj-$(CONFIG_MMC_ARMMMCI) += mmci.o - obj-$(CONFIG_MMC_PXA) += pxamci.o - obj-$(CONFIG_MMC_IMX) += imxmmc.o -diff --git a/drivers/mmc/host/jz4750_mmc.c b/drivers/mmc/host/jz4750_mmc.c -new file mode 100644 -index 0000000..94004fa ---- /dev/null -+++ b/drivers/mmc/host/jz4750_mmc.c -@@ -0,0 +1,1051 @@ -+/* -+ * linux/drivers/mmc/jz_mmc.c - JZ SD/MMC driver -+ * -+ * Copyright (C) 2005 - 2008 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jz4750_mmc.h" -+ -+#define DRIVER_NAME "jz-mmc" -+ -+#define USE_DMA -+ -+static int r_type = 0; -+static int rxdmachan = 0; -+static int txdmachan = 0; -+static int mmc_slot_enable = 0; -+static int auto_select_bus = MSC_4BIT_BUS; /* default 4 bit bus*/ -+ -+/* Start the MMC clock and operation */ -+static inline int jz_mmc_start_op(void) -+{ -+ REG_MSC_STRPCL(MSC_ID) = MSC_STRPCL_START_OP; -+ -+ return MMC_NO_ERROR; -+} -+ -+static inline u32 jz_mmc_calc_clkrt(int is_low, u32 rate) -+{ -+ u32 clkrt; -+ u32 clk_src = is_low ? 24000000 : 48000000; -+ -+ clkrt = 0; -+ while (rate < clk_src) { -+ clkrt++; -+ clk_src >>= 1; -+ } -+ return clkrt; -+} -+ -+/* Select the MMC clock frequency */ -+static int jz_mmc_set_clock(u32 rate) -+{ -+ int clkrt; -+ -+ /* __cpm_select_msc_clk_high will select 48M clock for MMC/SD card -+ * perhaps this will made some card with bad quality init fail,or -+ * bad stabilization. -+ */ -+ if (rate > SD_CLOCK_FAST) { -+ __cpm_select_msc_clk_high(MSC_ID,1); /* select clock source from CPM */ -+ clkrt = jz_mmc_calc_clkrt(0, rate); -+ } else { -+ __cpm_select_msc_clk(MSC_ID,1); /* select clock source from CPM */ -+ clkrt = jz_mmc_calc_clkrt(1, rate); -+ } -+ -+#ifndef CONFIG_FPGA -+ REG_MSC_CLKRT(MSC_ID) = clkrt; -+#else -+ REG_MSC_CLKRT(MSC_ID) = 7; -+#endif -+ return MMC_NO_ERROR; -+} -+ -+static void jz_mmc_enable_irq(struct jz_mmc_host *host, unsigned int mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ host->imask &= ~mask; -+ REG_MSC_IMASK(MSC_ID) = host->imask; -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void jz_mmc_disable_irq(struct jz_mmc_host *host, unsigned int mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ host->imask |= mask; -+ REG_MSC_IMASK(MSC_ID) = host->imask; -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+void jz_set_dma_block_size(int dmanr, int nbyte); -+ -+#ifdef USE_DMA -+static inline void -+jz_mmc_start_dma(int chan, unsigned long phyaddr, int count, int mode) -+{ -+ unsigned long flags; -+ -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ jz_set_dma_block_size(chan, 32); -+ set_dma_mode(chan, mode); -+ set_dma_addr(chan, phyaddr); -+ set_dma_count(chan, count + 31); -+ enable_dma(chan); -+ release_dma_lock(flags); -+} -+ -+static irqreturn_t jz_mmc_dma_rx_callback(int irq, void *devid) -+{ -+ int chan = rxdmachan; -+ -+ disable_dma(chan); -+ if (__dmac_channel_address_error_detected(chan)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", -+ __FUNCTION__); -+ __dmac_channel_clear_address_error(chan); -+ } -+ if (__dmac_channel_transmit_end_detected(chan)) { -+ __dmac_channel_clear_transmit_end(chan); -+ } -+ return IRQ_HANDLED; -+} -+static irqreturn_t jz_mmc_dma_tx_callback(int irq, void *devid) -+{ -+ int chan = txdmachan; -+ -+ disable_dma(chan); -+ if (__dmac_channel_address_error_detected(chan)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", -+ __FUNCTION__); -+ __dmac_channel_clear_address_error(chan); -+ } -+ if (__dmac_channel_transmit_end_detected(chan)) { -+ __dmac_channel_clear_transmit_end(chan); -+ } -+ return IRQ_HANDLED; -+} -+ -+/* Prepare DMA to start data transfer from the MMC card */ -+static void jz_mmc_rx_setup_data(struct jz_mmc_host *host, -+ struct mmc_data *data) -+{ -+ unsigned int nob = data->blocks; -+ int channelrx = rxdmachan; -+ int i; -+ u32 size; -+ -+ if (data->flags & MMC_DATA_STREAM) -+ nob = 0xffff; -+ -+ REG_MSC_NOB(MSC_ID) = nob; -+ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -+ size = nob * data->blksz; -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->dma.dir = DMA_FROM_DEVICE; -+ } else { -+ host->dma.dir = DMA_TO_DEVICE; -+ } -+ -+ host->dma.len = -+ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -+ host->dma.dir); -+ -+ for (i = 0; i < host->dma.len; i++) { -+ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -+ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -+ dma_cache_wback_inv((unsigned long) -+ CKSEG0ADDR(sg_dma_address(data->sg)) + -+ data->sg->offset, -+ host->sg_cpu[i].dcmd); -+ jz_mmc_start_dma(channelrx, host->sg_cpu[i].dtadr, -+ host->sg_cpu[i].dcmd, DMA_MODE_READ); -+ } -+} -+ -+/* Prepare DMA to start data transfer from the MMC card */ -+static void jz_mmc_tx_setup_data(struct jz_mmc_host *host, -+ struct mmc_data *data) -+{ -+ unsigned int nob = data->blocks; -+ int channeltx = txdmachan; -+ int i; -+ u32 size; -+ -+ if (data->flags & MMC_DATA_STREAM) -+ nob = 0xffff; -+ -+ REG_MSC_NOB(MSC_ID) = nob; -+ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -+ size = nob * data->blksz; -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->dma.dir = DMA_FROM_DEVICE; -+ } else { -+ host->dma.dir = DMA_TO_DEVICE; -+ } -+ -+ host->dma.len = -+ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -+ host->dma.dir); -+ -+ for (i = 0; i < host->dma.len; i++) { -+ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -+ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -+ dma_cache_wback_inv((unsigned long) -+ CKSEG0ADDR(sg_dma_address(data->sg)) + -+ data->sg->offset, -+ host->sg_cpu[i].dcmd); -+ jz_mmc_start_dma(channeltx, host->sg_cpu[i].dtadr, -+ host->sg_cpu[i].dcmd, DMA_MODE_WRITE); -+ } -+} -+#else -+static void jz_mmc_receive_pio(struct jz_mmc_host *host) -+{ -+ -+ struct mmc_data *data = 0; -+ int sg_len = 0, max = 0, count = 0; -+ u32 *buf = 0; -+ struct scatterlist *sg; -+ unsigned int nob; -+ -+ data = host->mrq->data; -+ nob = data->blocks; -+ REG_MSC_NOB(MSC_ID) = nob; -+ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -+ -+ max = host->pio.len; -+ if (host->pio.index < host->dma.len) { -+ sg = &data->sg[host->pio.index]; -+ buf = sg_virt(sg) + host->pio.offset; -+ -+ /* This is the space left inside the buffer */ -+ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; -+ /* Check to if we need less then the size of the sg_buffer */ -+ if (sg_len < max) max = sg_len; -+ } -+ max = max / 4; -+ for(count = 0; count < max; count++) { -+ while (REG_MSC_STAT(MSC_ID) & MSC_STAT_DATA_FIFO_EMPTY) -+ ; -+ *buf++ = REG_MSC_RXFIFO(MSC_ID); -+ } -+ host->pio.len -= count; -+ host->pio.offset += count; -+ -+ if (sg_len && count == sg_len) { -+ host->pio.index++; -+ host->pio.offset = 0; -+ } -+} -+ -+static void jz_mmc_send_pio(struct jz_mmc_host *host) -+{ -+ -+ struct mmc_data *data = 0; -+ int sg_len, max, count = 0; -+ u32 *wbuf = 0; -+ struct scatterlist *sg; -+ unsigned int nob; -+ -+ data = host->mrq->data; -+ nob = data->blocks; -+ -+ REG_MSC_NOB(MSC_ID) = nob; -+ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -+ -+ /* This is the pointer to the data buffer */ -+ sg = &data->sg[host->pio.index]; -+ wbuf = sg_virt(sg) + host->pio.offset; -+ -+ /* This is the space left inside the buffer */ -+ sg_len = data->sg[host->pio.index].length - host->pio.offset; -+ -+ /* Check to if we need less then the size of the sg_buffer */ -+ max = (sg_len > host->pio.len) ? host->pio.len : sg_len; -+ max = max / 4; -+ for(count = 0; count < max; count++ ) { -+ while (REG_MSC_STAT(MSC_ID) & MSC_STAT_DATA_FIFO_FULL) -+ ; -+ REG_MSC_TXFIFO(MSC_ID) = *wbuf++; -+ } -+ -+ host->pio.len -= count; -+ host->pio.offset += count; -+ -+ if (count == sg_len) { -+ host->pio.index++; -+ host->pio.offset = 0; -+ } -+} -+ -+static int -+jz_mmc_prepare_data(struct jz_mmc_host *host, struct mmc_data *data) -+{ -+ int datalen = data->blocks * data->blksz; -+ -+ host->dma.dir = DMA_BIDIRECTIONAL; -+ host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, -+ data->sg_len, host->dma.dir); -+ if (host->dma.len == 0) -+ return -ETIMEDOUT; -+ -+ host->pio.index = 0; -+ host->pio.offset = 0; -+ host->pio.len = datalen; -+ return 0; -+} -+#endif -+ -+static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat); -+ -+static void jz_mmc_finish_request(struct jz_mmc_host *host, struct mmc_request *mrq) -+{ -+ host->mrq = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ mmc_request_done(host->mmc, mrq); -+} -+ -+static void jz_mmc_start_cmd(struct jz_mmc_host *host, -+ struct mmc_command *cmd, unsigned int cmdat) -+{ -+ u32 timeout = 0x3fffff; -+ unsigned int stat; -+ struct jz_mmc_host *hst = host; -+ WARN_ON(host->cmd != NULL); -+ host->cmd = cmd; -+ -+ /* mask interrupts */ -+ REG_MSC_IMASK(MSC_ID) = 0xffff; -+ -+ /* clear status */ -+ REG_MSC_IREG(MSC_ID) = 0xffff; -+ -+ if (cmd->flags & MMC_RSP_BUSY) -+ cmdat |= MSC_CMDAT_BUSY; -+ -+#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) -+ switch (RSP_TYPE(mmc_resp_type(cmd))) { -+ case RSP_TYPE(MMC_RSP_R1): /* r1,r1b, r6, r7 */ -+ cmdat |= MSC_CMDAT_RESPONSE_R1; -+ r_type = 1; -+ break; -+ case RSP_TYPE(MMC_RSP_R3): -+ cmdat |= MSC_CMDAT_RESPONSE_R3; -+ r_type = 1; -+ break; -+ case RSP_TYPE(MMC_RSP_R2): -+ cmdat |= MSC_CMDAT_RESPONSE_R2; -+ r_type = 2; -+ break; -+ default: -+ break; -+ } -+ -+ REG_MSC_CMD(MSC_ID) = cmd->opcode; -+ -+ /* Set argument */ -+#ifdef CONFIG_MSC0_JZ4750 -+#ifdef CONFIG_JZ4750_MSC0_BUS_1 -+ if (cmd->opcode == 6) { -+ /* set 1 bit sd card bus*/ -+ if (cmd->arg ==2) -+ REG_MSC_ARG(MSC_ID) = 0; -+ -+ /* set 1 bit mmc card bus*/ -+ if (cmd->arg == 0x3b70101) { -+ REG_MSC_ARG(MSC_ID) = 0x3b70001; -+ } -+ } else -+ REG_MSC_ARG(MSC_ID) = cmd->arg; -+ -+#elif defined CONFIG_JZ4750_MSC0_BUS_8 -+ if (cmd->opcode == 6) { -+ /* set 8 bit mmc card bus*/ -+ if (cmd->arg == 0x3b70101) -+ REG_MSC_ARG(MSC_ID) = 0x3b70201; -+ else -+ REG_MSC_ARG(MSC_ID) = cmd->arg; -+ -+ } else -+ REG_MSC_ARG(MSC_ID) = cmd->arg; -+#else -+ REG_MSC_ARG(MSC_ID) = cmd->arg; -+#endif /* CONFIG_JZ4750_MSC0_BUS_1 */ -+#else -+#ifdef CONFIG_JZ4750_MSC1_BUS_1 -+ if (cmd->opcode == 6) { -+ /* set 1 bit sd card bus*/ -+ if (cmd->arg ==2) -+ REG_MSC_ARG(MSC_ID) = 0; -+ -+ /* set 1 bit mmc card bus*/ -+ if (cmd->arg == 0x3b70101) { -+ REG_MSC_ARG(MSC_ID) = 0x3b70001; -+ } -+ } else -+ REG_MSC_ARG(MSC_ID) = cmd->arg; -+ -+#else -+ REG_MSC_ARG(MSC_ID) = cmd->arg; -+#endif /* CONFIG_JZ4750_MSC1_BUS_1 */ -+#endif /* CONFIG_MSC0_JZ4750*/ -+ -+ /* Set command */ -+ REG_MSC_CMDAT(MSC_ID) = cmdat; -+ -+ /* Send command */ -+ jz_mmc_start_op(); -+ -+ while (timeout-- && !(REG_MSC_STAT(MSC_ID) & MSC_STAT_END_CMD_RES)) -+ ; -+ -+ REG_MSC_IREG(MSC_ID) = MSC_IREG_END_CMD_RES; /* clear irq flag */ -+ if (cmd->opcode == 12) { -+ while (timeout-- && !(REG_MSC_IREG(MSC_ID) & MSC_IREG_PRG_DONE)) -+ ; -+ REG_MSC_IREG(MSC_ID) = MSC_IREG_PRG_DONE; /* clear status */ -+ } -+ if (!mmc_slot_enable) { -+ /* It seems that MSC can't report the MSC_STAT_TIME_OUT_RES when -+ * card was removed. We force to return here. -+ */ -+ cmd->error = -ETIMEDOUT; -+ jz_mmc_finish_request(hst, hst->mrq); -+ return; -+ } -+ -+ if (SD_IO_SEND_OP_COND == cmd->opcode) { -+ /* -+ * Don't support SDIO card currently. -+ */ -+ cmd->error = -ETIMEDOUT; -+ jz_mmc_finish_request(hst, hst->mrq); -+ return; -+ } -+ -+ /* Check for status */ -+ stat = REG_MSC_STAT(MSC_ID); -+ jz_mmc_cmd_done(hst, stat); -+ if (host->data) { -+ if (cmd->opcode == MMC_WRITE_BLOCK || cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) -+#ifdef USE_DMA -+ jz_mmc_tx_setup_data(host, host->data); -+#else -+ jz_mmc_send_pio(host); -+ else -+ jz_mmc_receive_pio(host); -+#endif -+ } -+} -+ -+static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat) -+{ -+ struct mmc_command *cmd = host->cmd; -+ int i, temp[16]; -+ u8 *buf; -+ u32 data, v, w1, w2; -+ -+ if (!cmd) -+ return 0; -+ -+ host->cmd = NULL; -+ buf = (u8 *) temp; -+ switch (r_type) { -+ case 1: -+ { -+ data = REG_MSC_RES(MSC_ID); -+ buf[0] = (data >> 8) & 0xff; -+ buf[1] = data & 0xff; -+ data = REG_MSC_RES(MSC_ID); -+ buf[2] = (data >> 8) & 0xff; -+ buf[3] = data & 0xff; -+ data = REG_MSC_RES(MSC_ID); -+ buf[4] = data & 0xff; -+ cmd->resp[0] = -+ buf[1] << 24 | buf[2] << 16 | buf[3] << 8 | -+ buf[4]; -+ break; -+ } -+ case 2: -+ { -+ data = REG_MSC_RES(MSC_ID); -+ v = data & 0xffff; -+ for (i = 0; i < 4; i++) { -+ data = REG_MSC_RES(MSC_ID); -+ w1 = data & 0xffff; -+ data = REG_MSC_RES(MSC_ID); -+ w2 = data & 0xffff; -+ cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; -+ v = w2; -+ } -+ break; -+ } -+ case 0: -+ break; -+ } -+ if (stat & MSC_STAT_TIME_OUT_RES) { -+ printk("MSC_STAT_TIME_OUT_RES\n"); -+ cmd->error = -ETIMEDOUT; -+ } else if (stat & MSC_STAT_CRC_RES_ERR && cmd->flags & MMC_RSP_CRC) { -+ printk("MSC_STAT_CRC\n"); -+ if (cmd->opcode == MMC_ALL_SEND_CID || -+ cmd->opcode == MMC_SEND_CSD || -+ cmd->opcode == MMC_SEND_CID) { -+ /* a bogus CRC error can appear if the msb of -+ the 15 byte response is a one */ -+ if ((cmd->resp[0] & 0x80000000) == 0) -+ cmd->error = -EILSEQ; -+ } -+ } -+ /* -+ * Did I mention this is Sick. We always need to -+ * discard the upper 8 bits of the first 16-bit word. -+ */ -+ if (host->data && cmd->error == 0) -+ jz_mmc_enable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -+ else -+ jz_mmc_finish_request(host, host->mrq); -+ -+ return 1; -+} -+ -+static int jz_mmc_data_done(struct jz_mmc_host *host, unsigned int stat) -+{ -+ struct mmc_data *data = host->data; -+ -+ if (!data) -+ return 0; -+ REG_MSC_IREG(MSC_ID) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ -+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, -+ host->dma_dir); -+ if (stat & MSC_STAT_TIME_OUT_READ) { -+ printk("MMC/SD timeout, MMC_STAT 0x%x\n", stat); -+ data->error = -ETIMEDOUT; -+ } else if (REG_MSC_STAT(MSC_ID) & -+ (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR)) { -+ printk("MMC/SD CRC error, MMC_STAT 0x%x\n", stat); -+ data->error = -EILSEQ; -+ } -+ /* -+ * There appears to be a hardware design bug here. There seems to -+ * be no way to find out how much data was transferred to the card. -+ * This means that if there was an error on any block, we mark all -+ * data blocks as being in error. -+ */ -+ if (data->error == 0) -+ data->bytes_xfered = data->blocks * data->blksz; -+ else -+ data->bytes_xfered = 0; -+ -+ jz_mmc_disable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -+ host->data = NULL; -+ if (host->mrq->stop) { -+ jz_mmc_start_cmd(host, host->mrq->stop, 0); -+ } else { -+ jz_mmc_finish_request(host, host->mrq); -+ } -+ return 1; -+} -+ -+static void jz_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ unsigned int cmdat; -+ -+ /* Save current request for the future processing */ -+ host->mrq = mrq; -+ host->data = mrq->data; -+ cmdat = host->cmdat; -+ host->cmdat &= ~MSC_CMDAT_INIT; -+ -+ if (mrq->data) { -+ cmdat &= ~MSC_CMDAT_BUSY; -+#ifdef USE_DMA -+ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -+ -+ cmdat |= -+ MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+ else { -+#ifdef CONFIG_MSC0_JZ4750 -+#ifdef CONFIG_JZ4750_MSC0_BUS_1 -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+#elif defined CONFIG_JZ4750_MSC0_BUS_4 -+ if(auto_select_bus == MSC_1BIT_BUS) { -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+ } else { -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+ } -+#else -+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; -+#endif /* CONFIG_JZ4750_MSC0_BUS_1 */ -+#else -+#ifdef CONFIG_JZ4750_MSC1_BUS_1 -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+#else -+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; -+#endif /* CONFIG_JZ4750_MSC1_BUS_1 */ -+#endif /* CONFIG_MSC0_JZ4750 */ -+ } -+ if (mrq->data->flags & MMC_DATA_WRITE) -+ cmdat |= MSC_CMDAT_WRITE; -+ -+ if (mrq->data->flags & MMC_DATA_STREAM) -+ cmdat |= MSC_CMDAT_STREAM_BLOCK; -+ if (mrq->cmd->opcode != MMC_WRITE_BLOCK -+ && mrq->cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) -+ jz_mmc_rx_setup_data(host, mrq->data); -+#else /*USE_DMA*/ -+ -+ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -+ else { -+#ifdef CONFIG_MSC0_JZ4750 -+#ifdef CONFIG_JZ4750_MSC0_BUS_1 -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -+#elif defined CONFIG_JZ4750_MSC0_BUS_4 -+ if(auto_select_bus == MSC_1BIT_BUS) { -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -+ } else { -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT | MSC_CMDAT_DATA_EN; -+ } -+#else -+ cmdat |= MSC_CMDAT_DATA_EN; -+#endif -+#else -+#ifdef CONFIG_JZ4750_MSC1_BUS_1 -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -+#else -+ cmdat |= MSC_CMDAT_DATA_EN; -+#endif /* CONFIG_JZ4750_MSC1_BUS_1 */ -+#endif /* CONFIG_MSC0_JZ4750 */ -+ } -+ if (mrq->data->flags & MMC_DATA_WRITE) -+ cmdat |= MSC_CMDAT_WRITE; -+ -+ if (mrq->data->flags & MMC_DATA_STREAM) -+ cmdat |= MSC_CMDAT_STREAM_BLOCK; -+ jz_mmc_prepare_data(host, host->data); -+#endif /*USE_DMA*/ -+ } -+ jz_mmc_start_cmd(host, mrq->cmd, cmdat); -+} -+ -+static irqreturn_t jz_mmc_irq(int irq, void *devid) -+{ -+ struct jz_mmc_host *host = devid; -+ unsigned int ireg; -+ int handled = 0; -+ -+ ireg = REG_MSC_IREG(MSC_ID); -+ -+ if (ireg) { -+ unsigned stat = REG_MSC_STAT(MSC_ID); -+ if (ireg & MSC_IREG_DATA_TRAN_DONE) -+ handled |= jz_mmc_data_done(host, stat); -+ } -+ return IRQ_RETVAL(handled); -+} -+ -+/* Returns true if MMC slot is empty */ -+static int jz_mmc_slot_is_empty(int slot) -+{ -+ int empty; -+ -+#ifdef CONFIG_FPGA -+ return 0; -+#endif -+ -+#ifdef CONFIG_MSC1_JZ4750 -+ empty = (__msc1_card_detected(slot) == 0) ? 1 : 0; -+#else -+ empty = (__msc0_card_detected(slot) == 0) ? 1 : 0; -+ -+#endif -+ if (empty) { -+ /* wait for card insertion */ -+#ifdef CONFIG_MSC1_JZ4750 -+ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -+#else -+ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -+#endif -+ } else { -+ /* wait for card removal */ -+#ifdef CONFIG_MSC1_JZ4750 -+ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -+#else -+ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -+#endif -+ } -+ -+ return empty; -+} -+ -+static irqreturn_t jz_mmc_detect_irq(int irq, void *devid) -+{ -+ struct jz_mmc_host *host = (struct jz_mmc_host *) devid; -+ -+ auto_select_bus = MSC_4BIT_BUS; -+ if (jz_mmc_slot_is_empty(0)) { -+ mmc_slot_enable = 0; -+ mmc_detect_change(host->mmc, 50); -+ } else { -+ mmc_slot_enable = 1; -+ mmc_detect_change(host->mmc, 50); -+ } -+ return IRQ_HANDLED; -+} -+ -+static int jz_mmc_get_ro(struct mmc_host *mmc) -+{ -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ -+ if (host->pdata && host->pdata->get_ro) -+ return host->pdata->get_ro(mmc_dev(mmc)); -+ /* Host doesn't support read only detection so assume writeable */ -+ return 0; -+} -+ -+/* set clock and power */ -+static void jz_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ -+ if (ios->clock) -+ jz_mmc_set_clock(ios->clock); -+ -+ if (host->power_mode != ios->power_mode) { -+ host->power_mode = ios->power_mode; -+ -+ if (ios->power_mode == MMC_POWER_ON) -+ host->cmdat |= CMDAT_INIT; -+ } -+ -+ if (ios->bus_width == MMC_BUS_WIDTH_4) { -+ auto_select_bus = MSC_4BIT_BUS; -+ host->cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; -+ } -+ else if (ios->bus_width == MMC_BUS_WIDTH_8) { -+ host->cmdat |= MSC_CMDAT_BUS_WIDTH_8BIT; -+ auto_select_bus = MSC_8BIT_BUS; -+ } else { -+ /* 1 bit bus*/ -+ host->cmdat &= ~MSC_CMDAT_BUS_WIDTH_8BIT; -+ auto_select_bus = MSC_1BIT_BUS; -+ } -+} -+ -+static const struct mmc_host_ops jz_mmc_ops = { -+ .request = jz_mmc_request, -+ .get_ro = jz_mmc_get_ro, -+ .set_ios = jz_mmc_set_ios, -+}; -+static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -+ pm_request_t req, void *data); -+ -+static int jz_mmc_probe(struct platform_device *pdev) -+{ -+ int retval; -+ struct mmc_host *mmc; -+ struct jz_mmc_host *host = NULL; -+ int irq; -+ struct resource *r; -+ -+#ifdef CONFIG_MSC0_JZ4750 -+#ifdef CONFIG_SOC_JZ4750 -+ __gpio_as_msc0_8bit(); // for jz4750 -+#else -+ __gpio_as_msc0_4bit(); // for jz4750d -+#endif -+ __msc0_init_io(); -+ __msc0_enable_power(); -+#else -+ __gpio_as_msc1_4bit(); -+ __msc1_init_io(); -+ __msc1_enable_power(); -+#endif -+ __msc_reset(MSC_ID); -+ REG_MSC_LPM(MSC_ID) = 0x1; -+ -+ MMC_IRQ_MASK(); -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ irq = platform_get_irq(pdev, 0); -+ if (!r || irq < 0) -+ return -ENXIO; -+ -+ r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); -+ if (!r) -+ return -EBUSY; -+ -+ mmc = mmc_alloc_host(sizeof(struct jz_mmc_host), &pdev->dev); -+ if (!mmc) { -+ retval = -ENOMEM; -+ goto out; -+ } -+ mmc->ops = &jz_mmc_ops; -+ mmc->f_min = MMC_CLOCK_SLOW; -+ mmc->f_max = SD_CLOCK_HIGH; -+ /* -+ * We can do SG-DMA, but we don't because we never know how much -+ * data we successfully wrote to the card. -+ */ -+ mmc->max_phys_segs = NR_SG; -+ -+ mmc->max_seg_size = PAGE_SIZE * 16; -+ mmc->max_req_size = mmc->max_seg_size; -+ mmc->max_blk_size = 4095; -+ /* -+ * Block count register is 16 bits. -+ */ -+ mmc->max_blk_count = 65535; -+ host = mmc_priv(mmc); -+ host->mmc = mmc; -+ host->pdata = pdev->dev.platform_data; -+ mmc->ocr_avail = host->pdata ? -+ host->pdata->ocr_mask : MMC_VDD_32_33 | MMC_VDD_33_34; -+ host->mmc->caps = -+ MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_SD_HIGHSPEED -+ | MMC_CAP_MMC_HIGHSPEED; -+ /* -+ *MMC_CAP_4_BIT_DATA (1 << 0) The host can do 4 bit transfers -+ * -+ */ -+ host->sg_cpu = -+ dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, -+ GFP_KERNEL); -+ if (!host->sg_cpu) { -+ retval = -ENOMEM; -+ goto out; -+ } -+ spin_lock_init(&host->lock); -+ host->irq = IRQ_MSC; /* is it useful ?*/ -+ host->imask = 0xffff; -+ /* -+ * Ensure that the host controller is shut down, and setup -+ * with our defaults. -+ */ -+ retval = request_irq(IRQ_MSC, jz_mmc_irq, 0, "MMC/SD", host); -+ if (retval) { -+ printk(KERN_ERR "MMC/SD: can't request MMC/SD IRQ\n"); -+ return retval; -+ } -+ -+ jz_mmc_slot_is_empty(0); -+ /* Request card detect interrupt */ -+ -+ retval = request_irq(MSC_HOTPLUG_IRQ, jz_mmc_detect_irq, 0, //SA_INTERRUPT, -+ "MMC card detect", host); -+ if (retval) { -+ printk(KERN_ERR "MMC/SD: can't request card detect IRQ\n"); -+ goto err1; -+ } -+#ifdef USE_DMA -+ /* Request MMC Rx DMA channel */ -+ rxdmachan = -+ jz_request_dma(DMA_ID_MSC_RX, "MMC Rx", jz_mmc_dma_rx_callback, -+ 0, host); -+ if (rxdmachan < 0) { -+ printk(KERN_ERR "jz_request_dma failed for MMC Rx\n"); -+ goto err2; -+ } -+ -+ if (rxdmachan < HALF_DMA_NUM) -+ REG_DMAC_DMACR(0) |= DMAC_DMACR_FMSC; -+ else -+ REG_DMAC_DMACR(1) |= DMAC_DMACR_FMSC; -+ -+ /* Request MMC Tx DMA channel */ -+ txdmachan = -+ jz_request_dma(DMA_ID_MSC_TX, "MMC Tx", jz_mmc_dma_tx_callback, -+ 0, host); -+ if (txdmachan < 0) { -+ printk(KERN_ERR "jz_request_dma failed for MMC Tx\n"); -+ goto err3; -+ } -+ -+ if (txdmachan < HALF_DMA_NUM) -+ REG_DMAC_DMACR(0) |= DMAC_DMACR_FMSC; -+ else -+ REG_DMAC_DMACR(1) |= DMAC_DMACR_FMSC; -+ -+#endif -+ platform_set_drvdata(pdev, mmc); -+ mmc_add_host(mmc); -+#ifdef CONFIG_PM -+ /* Register MMC slot as as power-managed device */ -+ pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, jz_mmc_pm_callback); -+#endif -+ printk("JZ SD/MMC card driver registered\n"); -+ -+ /* Detect card during initialization */ -+#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+ if (!jz_mmc_slot_is_empty(0)) { -+ mmc_slot_enable = 1; -+ mmc_detect_change(host->mmc, 0); -+ } -+#endif -+ return 0; -+ -+err1:free_irq(IRQ_MSC, &host); -+#ifdef USE_DMA -+ err2:jz_free_dma(rxdmachan); -+ err3:jz_free_dma(txdmachan); -+#endif -+out: -+ if (host) { -+ if (host->sg_cpu) -+ dma_free_coherent(&pdev->dev, PAGE_SIZE, -+ host->sg_cpu, host->sg_dma); -+ } -+ if (mmc) -+ mmc_free_host(mmc); -+ return -1; -+} -+ -+static int jz_mmc_remove(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(pdev); -+ long flags; -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ if (mmc) { -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ -+ if (host->pdata && host->pdata->exit) -+ host->pdata->exit(&pdev->dev, mmc); -+ -+ mmc_remove_host(mmc); -+ -+ local_irq_save(flags); -+ __msc0_disable_power(); -+ jz_free_dma(rxdmachan); -+ jz_free_dma(txdmachan); -+ free_irq(IRQ_MSC, host); -+ local_irq_restore(flags); -+ mmc_free_host(mmc); -+ } -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+pm_message_t state; -+static int jz_mmc_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(dev); -+ int ret = 0; -+ -+ if (mmc) -+ ret = mmc_suspend_host(mmc, state); -+ -+ return ret; -+} -+ -+static int jz_mmc_resume(struct platform_device *dev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(dev); -+ int ret = 0; -+ -+ if (mmc) -+ ret = mmc_resume_host(mmc); -+ -+ return ret; -+} -+static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -+ pm_request_t req, void *data) -+{ -+ struct platform_device *pdev = (struct platform_device *)pm_dev; -+ -+ switch(req) { -+ case PM_RESUME: -+ jz_mmc_resume(pdev); -+ break; -+ case PM_SUSPEND: -+ /* state has no use */ -+ jz_mmc_suspend(pdev,state); -+ break; -+ default: -+ printk("MMC/SD: invalid PM request %d\n", req); -+ break; -+ } -+ return 0; -+} -+#else -+#define jz_mmc_suspend NULL -+#define jz_mmc_resume NULL -+#endif -+ -+static struct platform_driver jz_mmc_driver = { -+ .probe = jz_mmc_probe, -+ .remove = jz_mmc_remove, -+ .suspend = jz_mmc_suspend, -+ .resume = jz_mmc_resume, -+ .driver = { -+ .name = DRIVER_NAME, -+ }, -+}; -+ -+static int __init jz_mmc_init(void) -+{ -+ return platform_driver_register(&jz_mmc_driver); -+} -+ -+static void __exit jz_mmc_exit(void) -+{ -+ platform_driver_unregister(&jz_mmc_driver); -+} -+ -+module_init(jz_mmc_init); -+module_exit(jz_mmc_exit); -+ -+MODULE_DESCRIPTION("JZ47XX SD/Multimedia Card Interface Driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/mmc/host/jz4750_mmc.h b/drivers/mmc/host/jz4750_mmc.h -new file mode 100644 -index 0000000..8577db6 ---- /dev/null -+++ b/drivers/mmc/host/jz4750_mmc.h -@@ -0,0 +1,88 @@ -+#ifndef __JZ4750_MMC_H__ -+#define __JZ4750_MMC_H__ -+ -+#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ -+#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ -+#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ -+#define SD_CLOCK_HIGH 24000000 /* 24 MHz for SD Cards */ -+#define MMC_NO_ERROR 0 -+ -+#define NR_SG 1 -+ -+#ifdef CONFIG_MSC0_JZ4750 -+#define MSC_ID 0 -+#define MSC_HOTPLUG_IRQ MSC0_HOTPLUG_IRQ -+#define IRQ_MSC IRQ_MSC0 -+#define DMA_ID_MSC_RX DMA_ID_MSC0_RX -+#define DMA_ID_MSC_TX DMA_ID_MSC0_TX -+#define MSC_HOTPLUG_PIN MSC0_HOTPLUG_PIN -+#else -+#define MSC_ID 1 -+#define MSC_HOTPLUG_IRQ MSC1_HOTPLUG_IRQ -+#define IRQ_MSC IRQ_MSC1 -+#define DMA_ID_MSC_RX DMA_ID_MSC1_RX -+#define DMA_ID_MSC_TX DMA_ID_MSC1_TX -+#define MSC_HOTPLUG_PIN MSC1_HOTPLUG_PIN -+#endif -+ -+#define MSC_1BIT_BUS 0 -+#define MSC_4BIT_BUS 1 -+#define MSC_8BIT_BUS 2 -+ -+#define SZ_4K 0x00001000 -+ -+struct jz_mmc_host { -+ struct mmc_host *mmc; -+ spinlock_t lock; -+ struct { -+ int len; -+ int dir; -+ } dma; -+ struct { -+ int index; -+ int offset; -+ int len; -+ } pio; -+ int irq; -+ unsigned int clkrt; -+ unsigned int cmdat; -+ unsigned int imask; -+ unsigned int power_mode; -+ struct jz_mmc_platform_data *pdata; -+ struct mmc_request *mrq; -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ dma_addr_t sg_dma; -+ struct jzsoc_dma_desc *sg_cpu; -+ unsigned int dma_len; -+ unsigned int dma_dir; -+}; -+ -+#define MMC_IRQ_MASK() \ -+do { \ -+ REG_MSC_IMASK(MSC_ID) = 0xffff; \ -+ REG_MSC_IREG(MSC_ID) = 0xffff; \ -+} while (0) -+ -+typedef struct jzsoc_dma_desc { -+ volatile u32 ddadr; /* Points to the next descriptor + flags */ -+ volatile u32 dsadr; /* DSADR value for the current transfer */ -+ volatile u32 dtadr; /* DTADR value for the current transfer */ -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+} jzsoc_dma_desc; -+ -+#include -+ -+struct device; -+struct mmc_host; -+ -+struct jz_mmc_platform_data { -+ unsigned int ocr_mask; /* available voltages */ -+ unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ -+ int (*init)(struct device *, irq_handler_t , void *); -+ int (*get_ro)(struct device *); -+ void (*setpower)(struct device *, unsigned int); -+ void (*exit)(struct device *, void *); -+}; -+ -+#endif /* __JZ4750_MMC_H__ */ -diff --git a/drivers/mmc/host/jz_mmc.c b/drivers/mmc/host/jz_mmc.c -new file mode 100644 -index 0000000..29ab9bb ---- /dev/null -+++ b/drivers/mmc/host/jz_mmc.c -@@ -0,0 +1,1026 @@ -+/* -+ * linux/drivers/mmc/jz_mmc.c - JZ SD/MMC driver -+ * -+ * Copyright (C) 2005 - 2008 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jz_mmc.h" -+ -+#define DRIVER_NAME "jz-mmc" -+ -+#define NR_SG 1 -+ -+#if defined(CONFIG_SOC_JZ4725) || defined(CONFIG_SOC_JZ4720) -+#undef USE_DMA -+#else -+#define USE_DMA -+#endif -+ -+struct jz_mmc_host { -+ struct mmc_host *mmc; -+ spinlock_t lock; -+ struct { -+ int len; -+ int dir; -+ } dma; -+ struct { -+ int index; -+ int offset; -+ int len; -+ } pio; -+ int irq; -+ unsigned int clkrt; -+ unsigned int cmdat; -+ unsigned int imask; -+ unsigned int power_mode; -+ struct jz_mmc_platform_data *pdata; -+ struct mmc_request *mrq; -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ dma_addr_t sg_dma; -+ struct jzsoc_dma_desc *sg_cpu; -+ unsigned int dma_len; -+ unsigned int dma_dir; -+ struct pm_dev *pmdev; -+}; -+ -+static int r_type = 0; -+ -+#define MMC_IRQ_MASK() \ -+do { \ -+ REG_MSC_IMASK = 0xff; \ -+ REG_MSC_IREG = 0xff; \ -+} while (0) -+ -+static int rxdmachan = 0; -+static int txdmachan = 0; -+static int mmc_slot_enable = 0; -+ -+/* Stop the MMC clock and wait while it happens */ -+static inline int jz_mmc_stop_clock(void) -+{ -+ int timeout = 1000; -+ -+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; -+ while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) { -+ timeout--; -+ if (timeout == 0) -+ return 0; -+ udelay(1); -+ } -+ return MMC_NO_ERROR; -+} -+ -+/* Start the MMC clock and operation */ -+static inline int jz_mmc_start_clock(void) -+{ -+ REG_MSC_STRPCL = -+ MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; -+ return MMC_NO_ERROR; -+} -+ -+static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate) -+{ -+ u32 clkrt; -+ u32 clk_src = is_sd ? 24000000 : 20000000; -+ -+ clkrt = 0; -+ while (rate < clk_src) { -+ clkrt++; -+ clk_src >>= 1; -+ } -+ return clkrt; -+} -+ -+/* Select the MMC clock frequency */ -+static int jz_mmc_set_clock(u32 rate) -+{ -+ int clkrt; -+ -+ jz_mmc_stop_clock(); -+ __cpm_select_msc_clk(1); /* select clock source from CPM */ -+ clkrt = jz_mmc_calc_clkrt(1, rate); -+ REG_MSC_CLKRT = clkrt; -+ return MMC_NO_ERROR; -+} -+ -+static void jz_mmc_enable_irq(struct jz_mmc_host *host, unsigned int mask) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&host->lock, flags); -+ host->imask &= ~mask; -+ REG_MSC_IMASK = host->imask; -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void jz_mmc_disable_irq(struct jz_mmc_host *host, unsigned int mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ host->imask |= mask; -+ REG_MSC_IMASK = host->imask; -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+void jz_set_dma_block_size(int dmanr, int nbyte); -+ -+#ifdef USE_DMA -+static inline void -+jz_mmc_start_dma(int chan, unsigned long phyaddr, int count, int mode) -+{ -+ unsigned long flags; -+ -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ jz_set_dma_block_size(chan, 32); -+ set_dma_mode(chan, mode); -+ set_dma_addr(chan, phyaddr); -+ set_dma_count(chan, count + 31); -+ enable_dma(chan); -+ release_dma_lock(flags); -+} -+ -+static irqreturn_t jz_mmc_dma_rx_callback(int irq, void *devid) -+{ -+ int chan = rxdmachan; -+ -+ disable_dma(chan); -+ if (__dmac_channel_address_error_detected(chan)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", -+ __FUNCTION__); -+ __dmac_channel_clear_address_error(chan); -+ } -+ if (__dmac_channel_transmit_end_detected(chan)) { -+ __dmac_channel_clear_transmit_end(chan); -+ } -+ return IRQ_HANDLED; -+} -+static irqreturn_t jz_mmc_dma_tx_callback(int irq, void *devid) -+{ -+ int chan = txdmachan; -+ -+ disable_dma(chan); -+ if (__dmac_channel_address_error_detected(chan)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", -+ __FUNCTION__); -+ __dmac_channel_clear_address_error(chan); -+ } -+ if (__dmac_channel_transmit_end_detected(chan)) { -+ __dmac_channel_clear_transmit_end(chan); -+ } -+ return IRQ_HANDLED; -+} -+ -+/* Prepare DMA to start data transfer from the MMC card */ -+static void jz_mmc_rx_setup_data(struct jz_mmc_host *host, -+ struct mmc_data *data) -+{ -+ unsigned int nob = data->blocks; -+ int channelrx = rxdmachan; -+ int i; -+ u32 size; -+ -+ if (data->flags & MMC_DATA_STREAM) -+ nob = 0xffff; -+ -+ REG_MSC_NOB = nob; -+ REG_MSC_BLKLEN = data->blksz; -+ size = nob * data->blksz; -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->dma.dir = DMA_FROM_DEVICE; -+ } else { -+ host->dma.dir = DMA_TO_DEVICE; -+ } -+ -+ host->dma.len = -+ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -+ host->dma.dir); -+ -+ for (i = 0; i < host->dma.len; i++) { -+ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -+ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -+ dma_cache_wback_inv((unsigned long) -+ CKSEG0ADDR(sg_dma_address(data->sg)) + -+ data->sg->offset, -+ host->sg_cpu[i].dcmd); -+ jz_mmc_start_dma(channelrx, host->sg_cpu[i].dtadr, -+ host->sg_cpu[i].dcmd, DMA_MODE_READ); -+ } -+} -+ -+/* Prepare DMA to start data transfer from the MMC card */ -+static void jz_mmc_tx_setup_data(struct jz_mmc_host *host, -+ struct mmc_data *data) -+{ -+ unsigned int nob = data->blocks; -+ int channeltx = txdmachan; -+ int i; -+ u32 size; -+ -+ if (data->flags & MMC_DATA_STREAM) -+ nob = 0xffff; -+ -+ REG_MSC_NOB = nob; -+ REG_MSC_BLKLEN = data->blksz; -+ size = nob * data->blksz; -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->dma.dir = DMA_FROM_DEVICE; -+ } else { -+ host->dma.dir = DMA_TO_DEVICE; -+ } -+ -+ host->dma.len = -+ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -+ host->dma.dir); -+ -+ for (i = 0; i < host->dma.len; i++) { -+ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -+ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -+ dma_cache_wback_inv((unsigned long) -+ CKSEG0ADDR(sg_dma_address(data->sg)) + -+ data->sg->offset, -+ host->sg_cpu[i].dcmd); -+ jz_mmc_start_dma(channeltx, host->sg_cpu[i].dtadr, -+ host->sg_cpu[i].dcmd, DMA_MODE_WRITE); -+ } -+} -+#else -+static void jz_mmc_receive_pio(struct jz_mmc_host *host) -+{ -+ -+ struct mmc_data *data = 0; -+ int sg_len = 0, max = 0, count = 0; -+ u32 *buf = 0; -+ struct scatterlist *sg; -+ unsigned int nob; -+ -+ data = host->mrq->data; -+ nob = data->blocks; -+ REG_MSC_NOB = nob; -+ REG_MSC_BLKLEN = data->blksz; -+ -+ max = host->pio.len; -+ if (host->pio.index < host->dma.len) { -+ sg = &data->sg[host->pio.index]; -+ buf = sg_virt(sg) + host->pio.offset; -+ -+ /* This is the space left inside the buffer */ -+ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; -+ /* Check to if we need less then the size of the sg_buffer */ -+ if (sg_len < max) max = sg_len; -+ } -+ max = max / 4; -+ for(count = 0; count < max; count++) { -+ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY) -+ ; -+ *buf++ = REG_MSC_RXFIFO; -+ } -+ host->pio.len -= count; -+ host->pio.offset += count; -+ -+ if (sg_len && count == sg_len) { -+ host->pio.index++; -+ host->pio.offset = 0; -+ } -+} -+ -+static void jz_mmc_send_pio(struct jz_mmc_host *host) -+{ -+ -+ struct mmc_data *data = 0; -+ int sg_len, max, count = 0; -+ u32 *wbuf = 0; -+ struct scatterlist *sg; -+ unsigned int nob; -+ -+ data = host->mrq->data; -+ nob = data->blocks; -+ -+ REG_MSC_NOB = nob; -+ REG_MSC_BLKLEN = data->blksz; -+ -+ /* This is the pointer to the data buffer */ -+ sg = &data->sg[host->pio.index]; -+ wbuf = sg_virt(sg) + host->pio.offset; -+ -+ /* This is the space left inside the buffer */ -+ sg_len = data->sg[host->pio.index].length - host->pio.offset; -+ -+ /* Check to if we need less then the size of the sg_buffer */ -+ max = (sg_len > host->pio.len) ? host->pio.len : sg_len; -+ max = max / 4; -+ for(count = 0; count < max; count++ ) { -+ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL) -+ ; -+ REG_MSC_TXFIFO = *wbuf++; -+ } -+ -+ host->pio.len -= count; -+ host->pio.offset += count; -+ -+ if (count == sg_len) { -+ host->pio.index++; -+ host->pio.offset = 0; -+ } -+} -+ -+static int -+jz_mmc_prepare_data(struct jz_mmc_host *host, struct mmc_data *data) -+{ -+ int datalen = data->blocks * data->blksz; -+ -+ host->dma.dir = DMA_BIDIRECTIONAL; -+ host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, -+ data->sg_len, host->dma.dir); -+ if (host->dma.len == 0) -+ return -ETIMEDOUT; -+ -+ host->pio.index = 0; -+ host->pio.offset = 0; -+ host->pio.len = datalen; -+ return 0; -+} -+#endif -+ -+static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat); -+ -+static void jz_mmc_finish_request(struct jz_mmc_host *host, struct mmc_request *mrq) -+{ -+ jz_mmc_stop_clock(); -+ host->mrq = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ mmc_request_done(host->mmc, mrq); -+} -+ -+static void jz_mmc_start_cmd(struct jz_mmc_host *host, -+ struct mmc_command *cmd, unsigned int cmdat) -+{ -+ u32 timeout = 0x3fffff; -+ unsigned int stat; -+ struct jz_mmc_host *hst = host; -+ WARN_ON(host->cmd != NULL); -+ host->cmd = cmd; -+ -+ /* stop MMC clock */ -+ jz_mmc_stop_clock(); -+ -+ /* mask interrupts */ -+ REG_MSC_IMASK = 0xff; -+ -+ /* clear status */ -+ REG_MSC_IREG = 0xff; -+ -+ if (cmd->flags & MMC_RSP_BUSY) -+ cmdat |= MSC_CMDAT_BUSY; -+ -+#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) -+ switch (RSP_TYPE(mmc_resp_type(cmd))) { -+ case RSP_TYPE(MMC_RSP_R1): /* r1,r1b, r6, r7 */ -+ cmdat |= MSC_CMDAT_RESPONSE_R1; -+ r_type = 1; -+ break; -+ case RSP_TYPE(MMC_RSP_R3): -+ cmdat |= MSC_CMDAT_RESPONSE_R3; -+ r_type = 1; -+ break; -+ case RSP_TYPE(MMC_RSP_R2): -+ cmdat |= MSC_CMDAT_RESPONSE_R2; -+ r_type = 2; -+ break; -+ default: -+ break; -+ } -+ REG_MSC_CMD = cmd->opcode; -+ -+ /* Set argument */ -+#ifdef CONFIG_JZ_MMC_BUS_1 -+ if (cmd->opcode == 6) { -+ /* set 1 bit sd card bus*/ -+ if (cmd->arg ==2) -+ REG_MSC_ARG = 0; -+ -+ /* set 1 bit mmc card bus*/ -+ if (cmd->arg == 0x3b70101) -+ REG_MSC_ARG = 0x3b70001; -+ } else -+ REG_MSC_ARG = cmd->arg; -+#else -+ REG_MSC_ARG = cmd->arg; -+#endif -+ -+ /* Set command */ -+ REG_MSC_CMDAT = cmdat; -+ -+ /* Send command */ -+ jz_mmc_start_clock(); -+ -+ while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)) -+ ; -+ -+ REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear irq flag */ -+ if (cmd->opcode == 12) { -+ while (timeout-- && !(REG_MSC_IREG & MSC_IREG_PRG_DONE)) -+ ; -+ REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ -+ } -+ if (!mmc_slot_enable) { -+ /* It seems that MSC can't report the MSC_STAT_TIME_OUT_RES when -+ * card was removed. We force to return here. -+ */ -+ cmd->error = -ETIMEDOUT; -+ jz_mmc_finish_request(hst, hst->mrq); -+ return; -+ } -+ -+ if (SD_IO_SEND_OP_COND == cmd->opcode) { -+ /* -+ * Don't support SDIO card currently. -+ */ -+ cmd->error = -ETIMEDOUT; -+ jz_mmc_finish_request(hst, hst->mrq); -+ return; -+ } -+ -+ /* Check for status */ -+ stat = REG_MSC_STAT; -+ jz_mmc_cmd_done(hst, stat); -+ if (host->data) { -+ if (cmd->opcode == MMC_WRITE_BLOCK || cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) -+#ifdef USE_DMA -+ jz_mmc_tx_setup_data(host, host->data); -+#else -+ jz_mmc_send_pio(host); -+ else -+ jz_mmc_receive_pio(host); -+#endif -+ } -+} -+ -+static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat) -+{ -+ struct mmc_command *cmd = host->cmd; -+ int i, temp[16]; -+ u8 *buf; -+ u32 data, v, w1, w2; -+ -+ if (!cmd) -+ return 0; -+ -+ host->cmd = NULL; -+ buf = (u8 *) temp; -+ switch (r_type) { -+ case 1: -+ { -+ data = REG_MSC_RES; -+ buf[0] = (data >> 8) & 0xff; -+ buf[1] = data & 0xff; -+ data = REG_MSC_RES; -+ buf[2] = (data >> 8) & 0xff; -+ buf[3] = data & 0xff; -+ data = REG_MSC_RES; -+ buf[4] = data & 0xff; -+ cmd->resp[0] = -+ buf[1] << 24 | buf[2] << 16 | buf[3] << 8 | -+ buf[4]; -+ break; -+ } -+ case 2: -+ { -+ data = REG_MSC_RES; -+ v = data & 0xffff; -+ for (i = 0; i < 4; i++) { -+ data = REG_MSC_RES; -+ w1 = data & 0xffff; -+ data = REG_MSC_RES; -+ w2 = data & 0xffff; -+ cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; -+ v = w2; -+ } -+ break; -+ } -+ case 0: -+ break; -+ } -+ if (stat & MSC_STAT_TIME_OUT_RES) { -+ printk("MSC_STAT_TIME_OUT_RES\n"); -+ cmd->error = -ETIMEDOUT; -+ } else if (stat & MSC_STAT_CRC_RES_ERR && cmd->flags & MMC_RSP_CRC) { -+ printk("MSC_STAT_CRC\n"); -+ if (cmd->opcode == MMC_ALL_SEND_CID || -+ cmd->opcode == MMC_SEND_CSD || -+ cmd->opcode == MMC_SEND_CID) { -+ /* a bogus CRC error can appear if the msb of -+ the 15 byte response is a one */ -+ if ((cmd->resp[0] & 0x80000000) == 0) -+ cmd->error = -EILSEQ; -+ } -+ } -+ /* -+ * Did I mention this is Sick. We always need to -+ * discard the upper 8 bits of the first 16-bit word. -+ */ -+ if (host->data && cmd->error == 0) -+ jz_mmc_enable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -+ else -+ jz_mmc_finish_request(host, host->mrq); -+ -+ return 1; -+} -+ -+static int jz_mmc_data_done(struct jz_mmc_host *host, unsigned int stat) -+{ -+ struct mmc_data *data = host->data; -+ -+ if (!data) -+ return 0; -+ REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ -+ jz_mmc_stop_clock(); -+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, -+ host->dma_dir); -+ if (stat & MSC_STAT_TIME_OUT_READ) { -+ printk("MMC/SD timeout, MMC_STAT 0x%x\n", stat); -+ data->error = -ETIMEDOUT; -+ } else if (REG_MSC_STAT & -+ (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR)) { -+ printk("MMC/SD CRC error, MMC_STAT 0x%x\n", stat); -+ data->error = -EILSEQ; -+ } -+ /* -+ * There appears to be a hardware design bug here. There seems to -+ * be no way to find out how much data was transferred to the card. -+ * This means that if there was an error on any block, we mark all -+ * data blocks as being in error. -+ */ -+ if (data->error == 0) -+ data->bytes_xfered = data->blocks * data->blksz; -+ else -+ data->bytes_xfered = 0; -+ -+ jz_mmc_disable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -+ host->data = NULL; -+ if (host->mrq->stop) { -+ jz_mmc_stop_clock(); -+ jz_mmc_start_cmd(host, host->mrq->stop, 0); -+ } else { -+ jz_mmc_finish_request(host, host->mrq); -+ } -+ return 1; -+} -+ -+static void jz_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ unsigned int cmdat; -+ -+ /* stop MMC clock */ -+ jz_mmc_stop_clock(); -+ -+ /* Save current request for the future processing */ -+ host->mrq = mrq; -+ host->data = mrq->data; -+ cmdat = host->cmdat; -+ host->cmdat &= ~MSC_CMDAT_INIT; -+ -+ if (mrq->data) { -+ cmdat &= ~MSC_CMDAT_BUSY; -+#ifdef USE_DMA -+ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -+ -+ cmdat |= -+ MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+ else { -+#ifdef CONFIG_JZ_MMC_BUS_1 -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -+ MSC_CMDAT_DMA_EN; -+#else -+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; -+#endif -+ } -+ if (mrq->data->flags & MMC_DATA_WRITE) -+ cmdat |= MSC_CMDAT_WRITE; -+ -+ if (mrq->data->flags & MMC_DATA_STREAM) -+ cmdat |= MSC_CMDAT_STREAM_BLOCK; -+ if (mrq->cmd->opcode != MMC_WRITE_BLOCK -+ && mrq->cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) -+ jz_mmc_rx_setup_data(host, mrq->data); -+#else /*USE_DMA*/ -+ -+ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -+ else { -+#ifdef CONFIG_JZ_MMC_BUS_1 -+ cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; -+ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -+#else -+ cmdat |= MSC_CMDAT_DATA_EN; -+#endif -+ } -+ if (mrq->data->flags & MMC_DATA_WRITE) -+ cmdat |= MSC_CMDAT_WRITE; -+ -+ if (mrq->data->flags & MMC_DATA_STREAM) -+ cmdat |= MSC_CMDAT_STREAM_BLOCK; -+ jz_mmc_prepare_data(host, host->data); -+#endif /*USE_DMA*/ -+ } -+ jz_mmc_start_cmd(host, mrq->cmd, cmdat); -+} -+ -+static irqreturn_t jz_mmc_irq(int irq, void *devid) -+{ -+ struct jz_mmc_host *host = devid; -+ unsigned int ireg; -+ int handled = 0; -+ -+ ireg = REG_MSC_IREG; -+ -+ if (ireg) { -+ unsigned stat = REG_MSC_STAT; -+ if (ireg & MSC_IREG_DATA_TRAN_DONE) -+ handled |= jz_mmc_data_done(host, stat); -+ } -+ return IRQ_RETVAL(handled); -+} -+ -+/* Returns true if MMC slot is empty */ -+static int jz_mmc_slot_is_empty(int slot) -+{ -+ int empty; -+ -+ empty = (__msc_card_detected(slot) == 0) ? 1 : 0; -+ -+ if (empty) { -+ /* wait for card insertion */ -+#ifdef CONFIG_MIPS_JZ4740_LYRA -+ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -+#else -+ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -+#endif -+ } else { -+ /* wait for card removal */ -+#ifdef CONFIG_MIPS_JZ4740_LYRA -+ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -+#else -+ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -+#endif -+ } -+ -+ return empty; -+} -+ -+static irqreturn_t jz_mmc_detect_irq(int irq, void *devid) -+{ -+ struct jz_mmc_host *host = (struct jz_mmc_host *) devid; -+ -+ if (jz_mmc_slot_is_empty(0)) { -+ mmc_slot_enable = 0; -+ mmc_detect_change(host->mmc, 50); -+ } else { -+ mmc_slot_enable = 1; -+ mmc_detect_change(host->mmc, 50); -+ } -+ return IRQ_HANDLED; -+} -+ -+static int jz_mmc_get_ro(struct mmc_host *mmc) -+{ -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ -+ if (host->pdata && host->pdata->get_ro) -+ return host->pdata->get_ro(mmc_dev(mmc)); -+ /* Host doesn't support read only detection so assume writeable */ -+ return 0; -+} -+ -+/* set clock and power */ -+static void jz_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ -+ if (ios->clock) -+ jz_mmc_set_clock(ios->clock); -+ else -+ jz_mmc_stop_clock(); -+ -+ if (host->power_mode != ios->power_mode) { -+ host->power_mode = ios->power_mode; -+ -+ if (ios->power_mode == MMC_POWER_ON) -+ host->cmdat |= CMDAT_INIT; -+ } -+ -+ if ((ios->bus_width == MMC_BUS_WIDTH_4) || (ios->bus_width == MMC_BUS_WIDTH_8)) -+ host->cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; -+ else -+ host->cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; -+} -+ -+static const struct mmc_host_ops jz_mmc_ops = { -+ .request = jz_mmc_request, -+ .get_ro = jz_mmc_get_ro, -+ .set_ios = jz_mmc_set_ios, -+}; -+static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -+ pm_request_t req, void *data); -+ -+static int jz_mmc_probe(struct platform_device *pdev) -+{ -+ int retval; -+ struct mmc_host *mmc; -+ struct jz_mmc_host *host = NULL; -+ int irq; -+ struct resource *r; -+ -+ __gpio_as_msc(); -+ __msc_init_io(); -+ __msc_enable_power(); -+ -+ __msc_reset(); -+ -+ /* On reset, stop MMC clock */ -+ jz_mmc_stop_clock(); -+ -+ MMC_IRQ_MASK(); -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ irq = platform_get_irq(pdev, 0); -+ if (!r || irq < 0) -+ return -ENXIO; -+ -+ r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); -+ if (!r) -+ return -EBUSY; -+ -+ mmc = mmc_alloc_host(sizeof(struct jz_mmc_host), &pdev->dev); -+ if (!mmc) { -+ retval = -ENOMEM; -+ goto out; -+ } -+ mmc->ops = &jz_mmc_ops; -+ mmc->f_min = MMC_CLOCK_SLOW; -+ mmc->f_max = SD_CLOCK_FAST; -+ /* -+ * We can do SG-DMA, but we don't because we never know how much -+ * data we successfully wrote to the card. -+ */ -+ mmc->max_phys_segs = NR_SG; -+ /* -+ * Our hardware DMA can handle a maximum of one page per SG entry. -+ */ -+ mmc->max_seg_size = PAGE_SIZE; -+ /* -+ * Block length register is 10 bits. -+ */ -+ mmc->max_blk_size = 1023; -+ /* -+ * Block count register is 16 bits. -+ */ -+ mmc->max_blk_count = 65535; -+ host = mmc_priv(mmc); -+ host->mmc = mmc; -+ host->pdata = pdev->dev.platform_data; -+ mmc->ocr_avail = host->pdata ? -+ host->pdata->ocr_mask : MMC_VDD_32_33 | MMC_VDD_33_34; -+ host->mmc->caps = -+ MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_SD_HIGHSPEED -+ | MMC_CAP_MMC_HIGHSPEED; -+ /* -+ *MMC_CAP_4_BIT_DATA (1 << 0) The host can do 4 bit transfers -+ * -+ */ -+ host->sg_cpu = -+ dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, -+ GFP_KERNEL); -+ if (!host->sg_cpu) { -+ retval = -ENOMEM; -+ goto out; -+ } -+ spin_lock_init(&host->lock); -+ host->irq = IRQ_MSC; -+ host->imask = 0xff; -+ /* -+ * Ensure that the host controller is shut down, and setup -+ * with our defaults. -+ */ -+ retval = request_irq(IRQ_MSC, jz_mmc_irq, 0, "MMC/SD", host); -+ if (retval) { -+ printk(KERN_ERR "MMC/SD: can't request MMC/SD IRQ\n"); -+ return retval; -+ } -+ jz_mmc_slot_is_empty(0); -+ /* Request card detect interrupt */ -+ -+ retval = request_irq(MSC_HOTPLUG_IRQ, jz_mmc_detect_irq, 0, //SA_INTERRUPT, -+ "MMC card detect", host); -+ if (retval) { -+ printk(KERN_ERR "MMC/SD: can't request card detect IRQ\n"); -+ goto err1; -+ } -+#ifdef USE_DMA -+ /* Request MMC Rx DMA channel */ -+ rxdmachan = -+ jz_request_dma(DMA_ID_MSC_RX, "MMC Rx", jz_mmc_dma_rx_callback, -+ 0, host); -+ if (rxdmachan < 0) { -+ printk(KERN_ERR "jz_request_dma failed for MMC Rx\n"); -+ goto err2; -+ } -+ -+ /* Request MMC Tx DMA channel */ -+ txdmachan = -+ jz_request_dma(DMA_ID_MSC_TX, "MMC Tx", jz_mmc_dma_tx_callback, -+ 0, host); -+ if (txdmachan < 0) { -+ printk(KERN_ERR "jz_request_dma failed for MMC Tx\n"); -+ goto err3; -+ } -+#endif -+ platform_set_drvdata(pdev, mmc); -+ mmc_add_host(mmc); -+#ifdef CONFIG_PM -+ /* Register MMC slot as as power-managed device */ -+ host->pmdev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, jz_mmc_pm_callback); -+ if (host->pmdev) -+ host->pmdev->data = pdev; -+#endif -+ printk("JZ SD/MMC card driver registered\n"); -+ -+ /* Detect card during initialization */ -+#ifdef CONFIG_SOC_JZ4740 -+ if (!jz_mmc_slot_is_empty(0)) { -+ mmc_slot_enable = 1; -+ mmc_detect_change(host->mmc, 0); -+ } -+#endif -+ return 0; -+ -+err1:free_irq(IRQ_MSC, &host); -+#ifdef USE_DMA -+ err2:jz_free_dma(rxdmachan); -+ err3:jz_free_dma(txdmachan); -+#endif -+out: -+ if (host) { -+ if (host->sg_cpu) -+ dma_free_coherent(&pdev->dev, PAGE_SIZE, -+ host->sg_cpu, host->sg_dma); -+ } -+ if (mmc) -+ mmc_free_host(mmc); -+ return -1; -+} -+ -+static int jz_mmc_remove(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(pdev); -+ long flags; -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ if (mmc) { -+ struct jz_mmc_host *host = mmc_priv(mmc); -+ -+ if (host->pdata && host->pdata->exit) -+ host->pdata->exit(&pdev->dev, mmc); -+ -+ mmc_remove_host(mmc); -+ -+ local_irq_save(flags); -+ jz_mmc_stop_clock(); -+ __msc_disable_power(); -+ jz_free_dma(rxdmachan); -+ jz_free_dma(txdmachan); -+ free_irq(IRQ_MSC, host); -+ local_irq_restore(flags); -+ mmc_free_host(mmc); -+ } -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+pm_message_t state; -+static int jz_mmc_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(dev); -+ int ret = 0; -+ -+ __msc_disable_power(); -+ if (mmc) -+ ret = mmc_suspend_host(mmc, state); -+ -+ return ret; -+} -+ -+static int jz_mmc_resume(struct platform_device *dev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(dev); -+ int ret = 0; -+#if 0 -+ /*for sandisk BB0807011816D and other strange cards*/ -+ int i; -+ -+ for(i = 104; i < 110; i++) -+ __gpio_as_input(i); -+ -+ /* perhaps you should mdelay more */ -+ mdelay(1000); -+ __gpio_as_msc(); -+#endif -+ __msc_init_io(); -+ __msc_enable_power(); -+ __msc_reset(); -+ -+ if (!jz_mmc_slot_is_empty(0)) { -+ mmc_slot_enable = 1; -+ mmc_detect_change(mmc, 10); -+ } -+ -+ if (mmc) -+ ret = mmc_resume_host(mmc); -+ -+ return ret; -+} -+static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -+ pm_request_t req, void *data) -+{ -+ struct platform_device *pdev = (struct platform_device *)pm_dev->data; -+ -+ switch(req) { -+ case PM_RESUME: -+ jz_mmc_resume(pdev); -+ break; -+ case PM_SUSPEND: -+ /* state has no use */ -+ jz_mmc_suspend(pdev, state); -+ break; -+ default: -+ printk("MMC/SD: invalid PM request %d\n", req); -+ break; -+ } -+ return 0; -+} -+#else -+#define jz_mmc_suspend NULL -+#define jz_mmc_resume NULL -+#endif -+ -+static struct platform_driver jz_mmc_driver = { -+ .probe = jz_mmc_probe, -+ .remove = jz_mmc_remove, -+ .suspend = jz_mmc_suspend, -+ .resume = jz_mmc_resume, -+ .driver = { -+ .name = DRIVER_NAME, -+ }, -+}; -+ -+static int __init jz_mmc_init(void) -+{ -+ return platform_driver_register(&jz_mmc_driver); -+} -+ -+static void __exit jz_mmc_exit(void) -+{ -+ platform_driver_unregister(&jz_mmc_driver); -+} -+ -+module_init(jz_mmc_init); -+module_exit(jz_mmc_exit); -+ -+MODULE_DESCRIPTION("JZ47XX SD/Multimedia Card Interface Driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/mmc/host/jz_mmc.h b/drivers/mmc/host/jz_mmc.h -new file mode 100644 -index 0000000..c733529 ---- /dev/null -+++ b/drivers/mmc/host/jz_mmc.h -@@ -0,0 +1,65 @@ -+#ifndef __JZ_MMC_H__ -+#define __JZ_MMC_H__ -+ -+#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ -+#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ -+#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ -+#define MMC_NO_ERROR 0 -+/* Extra MMC commands for state control */ -+/* Use negative numbers to disambiguate */ -+#define MMC_CIM_RESET -1 -+#define MMC_SET_CLOCK 100 -+ -+typedef struct jzsoc_dma_desc { -+ volatile u32 ddadr; /* Points to the next descriptor + flags */ -+ volatile u32 dsadr; /* DSADR value for the current transfer */ -+ volatile u32 dtadr; /* DTADR value for the current transfer */ -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+} jzsoc_dma_desc; -+ -+ -+ -+ -+#include -+ -+struct device; -+struct mmc_host; -+ -+struct jz_mmc_platform_data { -+ unsigned int ocr_mask; /* available voltages */ -+ unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ -+ int (*init)(struct device *, irq_handler_t , void *); -+ int (*get_ro)(struct device *); -+ void (*setpower)(struct device *, unsigned int); -+ void (*exit)(struct device *, void *); -+}; -+ -+//extern void pxa_set_mci_info(struct pxamci_platform_data *info); -+ -+ -+ -+#define SZ_1K 0x00000400 -+#define SZ_4K 0x00001000 -+#define SZ_8K 0x00002000 -+#define SZ_16K 0x00004000 -+#define SZ_64K 0x00010000 -+#define SZ_128K 0x00020000 -+#define SZ_256K 0x00040000 -+#define SZ_512K 0x00080000 -+ -+#define SZ_1M 0x00100000 -+#define SZ_2M 0x00200000 -+#define SZ_4M 0x00400000 -+#define SZ_8M 0x00800000 -+#define SZ_16M 0x01000000 -+#define SZ_32M 0x02000000 -+#define SZ_64M 0x04000000 -+#define SZ_128M 0x08000000 -+#define SZ_256M 0x10000000 -+#define SZ_512M 0x20000000 -+ -+#define SZ_1G 0x40000000 -+#define SZ_2G 0x80000000 -+ -+ -+#endif /* __JZ_MMC_H__ */ -diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c -index 77db5ce..b9541ab 100644 ---- a/drivers/mtd/mtdblock.c -+++ b/drivers/mtd/mtdblock.c -@@ -13,7 +13,7 @@ - #include - #include - #include -- -+#include - #include - #include - #include -@@ -371,12 +371,27 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) - kfree(dev); - } - -+ -+static int mtdblock_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) -+{ -+ struct gendisk *gd = dev->blkcore_priv; -+ memset(geo, 0, sizeof(*geo)); -+ geo->heads = 4; -+ geo->sectors = 16; -+ geo->cylinders = dev->size/(4*16); -+ -+ printk("cylinders: %x \n", geo->cylinders); -+ printk("sects: %x\n", dev->size); -+ return 0; -+} -+ - static struct mtd_blktrans_ops mtdblock_tr = { - .name = "mtdblock", - .major = 31, - .part_bits = 0, - .blksize = 512, - .open = mtdblock_open, -+ .getgeo = mtdblock_getgeo, - .flush = mtdblock_flush, - .release = mtdblock_release, - .readsect = mtdblock_readsect, -diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c -index 5b081cb..cdc69c0 100644 ---- a/drivers/mtd/mtdchar.c -+++ b/drivers/mtd/mtdchar.c -@@ -635,6 +635,73 @@ static int mtd_ioctl(struct inode *inode, struct file *file, - break; - } - -+ case MEMWRITEPAGE: -+ { -+ struct mtd_page_buf buf; -+ struct mtd_oob_ops ops; -+ -+ memset(&ops, 0, sizeof(ops)); -+#if 1 -+ if(!(file->f_mode & 2)) -+ return -EPERM; -+#endif -+ -+ if (copy_from_user(&buf, argp, sizeof(struct mtd_page_buf))) -+ return -EFAULT; -+ -+ if (buf.ooblength > mtd->oobsize) -+ return -EINVAL; -+ -+ if (!mtd->write_oob) -+ ret = -EOPNOTSUPP; -+ else -+ ret = access_ok(VERIFY_READ, buf.oobptr, -+ buf.ooblength) ? 0 : EFAULT; -+ -+ if (ret) -+ return ret; -+ -+ ops.len = mtd->writesize; -+ ops.ooblen = buf.ooblength; -+ ops.ooboffs = buf.start & (mtd->oobsize - 1); -+ ops.mode = MTD_OOB_PLACE; -+ -+ if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) -+ return -EINVAL; -+ -+ /* alloc memory and copy oob data from user mode to kernel mode */ -+ ops.oobbuf = kmalloc(buf.ooblength, GFP_KERNEL); -+ if (!ops.oobbuf) -+ return -ENOMEM; -+ -+ if (copy_from_user(ops.oobbuf, buf.oobptr, buf.ooblength)) { -+ kfree(ops.oobbuf); -+ return -EFAULT; -+ } -+ -+ /* alloc memory and copy page data from user mode to kernel mode */ -+ ops.datbuf = kmalloc(mtd->writesize, GFP_KERNEL); -+ if (!ops.datbuf) -+ return -ENOMEM; -+ -+ if (copy_from_user(ops.datbuf, buf.datptr, mtd->writesize)) { -+ kfree(ops.datbuf); -+ return -EFAULT; -+ } -+ -+ buf.start &= ~(mtd->oobsize - 1); -+ ret = mtd->write_oob(mtd, buf.start, &ops); -+ -+ if (copy_to_user(argp + 2*sizeof(uint32_t), &ops.retlen, -+ sizeof(uint32_t))) -+ ret = -EFAULT; -+ -+ kfree(ops.oobbuf); -+ kfree(ops.datbuf); -+ break; -+ } -+ -+ - case MEMLOCK: - { - struct erase_info_user einfo; -diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c -index 349fcbe..69f511c 100644 ---- a/drivers/mtd/mtdpart.c -+++ b/drivers/mtd/mtdpart.c -@@ -346,6 +346,10 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, - /* set up the MTD object for this partition */ - slave->mtd.type = master->type; - slave->mtd.flags = master->flags & ~part->mask_flags; -+ if (part[i].mtdblock_jz_invalid) -+ slave->mtd.flags |= MTD_MTDBLOCK_JZ_INVALID; -+ if (part[i].cpu_mode) -+ slave->mtd.flags |= MTD_NAND_CPU_MODE; - slave->mtd.size = part->size; - slave->mtd.writesize = master->writesize; - slave->mtd.oobsize = master->oobsize; -@@ -363,6 +367,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, - - slave->mtd.read = part_read; - slave->mtd.write = part_write; -+ slave->mtd.priv = master->priv; - - if (master->panic_write) - slave->mtd.panic_write = part_panic_write; -diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index ce96c09..138afb0 100644 ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -452,4 +452,134 @@ config MTD_NAND_SOCRATES - help - Enables support for NAND Flash chips wired onto Socrates board. - -+config MTD_NAND_JZ4730 -+ tristate "Support NAND Flash device on Jz4730 board" -+ depends on SOC_JZ4730 -+ help -+ Support NAND Flash device on Jz4730 board -+ -+config MTD_NAND_JZ4740 -+ tristate "Support NAND Flash device on Jz4740 board" -+ depends on SOC_JZ4740 -+ help -+ Support NAND Flash device on Jz4740 board -+ -+config MTD_NAND_JZ4750 -+ tristate "Support NAND Flash device on Jz4750 board" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ Support NAND Flash device on Jz4750 board -+ -+config MTD_NAND_CS2 -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use NAND on CS2_N of JZSOC' -+ default n -+ -+config MTD_NAND_CS3 -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use NAND on CS3_N of JZSOC' -+ default n -+ -+config MTD_NAND_CS4 -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use NAND on CS4_N of JZSOC' -+ default n -+ -+config MTD_NAND_MULTI_PLANE -+ depends on MTD_NAND_JZ4730 || MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use multiple planes if the NAND supports' -+ default y -+ help -+ It is just supported on jz4740 now. -+ -+if MTD_NAND_JZ4740 || MTD_NAND_JZ4730 || MTD_NAND_JZ4750 -+choice -+ prompt "ECC type" -+ default CONFIG_MTD_SW_HM_ECC -+ -+config MTD_HW_HM_ECC -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4730 -+ bool 'Select hardware HM ECC' -+ -+config MTD_SW_HM_ECC -+ bool 'Select software HM ECC' -+ -+config MTD_HW_RS_ECC -+ depends on MTD_NAND_JZ4740 -+ bool 'Select hardware RS ECC' -+ -+config MTD_HW_BCH_ECC -+ depends on MTD_NAND_JZ4750 -+ bool 'Select hardware BCH ECC' -+endchoice -+ -+choice -+ prompt "4 bit or 8 bit BCH ecc" -+ depends on MTD_HW_BCH_ECC -+ default CONFIG_MTD_HW_BCH_4BIT -+ -+config MTD_HW_BCH_4BIT -+ bool '4 bit' -+ -+config MTD_HW_BCH_8BIT -+ bool '8 bit' -+ -+endchoice -+ -+config MTD_NAND_DMA -+ depends on MTD_HW_BCH_ECC || MTD_HW_RS_ECC -+ bool 'Use DMA mode' -+ help -+ This enables using DMA for reading and writing NAND flash, if not selected, -+ then CPU mode is used. DMA is only used for two planes for jz4740. -+ -+config MTD_NAND_DMABUF -+ depends on MTD_NAND_DMA && MTD_HW_BCH_ECC -+ bool 'use DMA buffer in NAND driver' -+ help -+ It's better to say NO. If saying yes, DMA buffers will be allocated for -+ NAND reading and writing in NAND driver instead of upper layer. It's -+ slower. Just usable on CS1_N now. By saying NO, upper buffers will be -+ used as DMA buffer. It's faster, but kmalloc instead of vmalloc is required. -+endif -+ -+config ALLOCATE_MTDBLOCK_JZ_EARLY -+ bool "Allocate memory for mtdblock-jz early" -+ default n -+ help -+ Allocate memory (a nand block cache) for mtdblock-jz.c early in nand_base.c, -+ Especially for the vfat partition which will be used as USB disk by PC. -+ -+config MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -+ bool "MTDBLOCK write verify enable" -+ default n -+ help -+ This will enable the write verification, which will read back data to check -+ after doing a write opetaion. -+ -+ It will be used by the JZ mtdblock driver (mtdblock-jz.c). -+ -+config MTD_OOB_COPIES -+ int "how many copies of the fs info in the oob area" -+ default 3 -+ range 0 128 -+ depends on MTD -+ help -+ This defines the copies of the fs info in the oob area inside a block. -+ Value ranges from 0 to (pages_per_block - 1). -+ -+ It will be used by the JZ mtdblock driver (mtdblock-jz.c). -+ -+config MTD_BADBLOCK_FLAG_PAGE -+ int "which page inside a block will store the badblock mark" -+ default 0 -+ range 0 127 -+ depends on MTD -+ help -+ This defines which page of a block will store the badblock mark. -+ Value ranges from 0 to (pages_per_block - 1). -+ -+ Old SLC NANDs store the badblock mark in the first page of a block, but -+ most modern MLC NANDs store it in the last page of a block. -+ - endif # MTD_NAND -diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile -index f3a786b..748a92a 100644 ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -32,6 +32,9 @@ obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o - obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o - obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o - obj-$(CONFIG_MTD_ALAUDA) += alauda.o -+obj-$(CONFIG_MTD_NAND_JZ4730) += jz4730_nand.o -+obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o -+obj-$(CONFIG_MTD_NAND_JZ4750) += jz4750_nand.o - obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o - obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o - obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o -diff --git a/drivers/mtd/nand/jz4730_nand.c b/drivers/mtd/nand/jz4730_nand.c -new file mode 100644 -index 0000000..f3e57f7 ---- /dev/null -+++ b/drivers/mtd/nand/jz4730_nand.c -@@ -0,0 +1,367 @@ -+/* -+ * linux/drivers/mtd/nand/jz4730_nand.c -+ * -+ * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Ingenic JZ4730 NAND 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. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define NAND_DATA_PORT 0xB4000000 /* read-write area */ -+#define __nand_ecc() (REG_EMC_NFECC & 0x00ffffff) -+#define __nand_ecc_enable() (REG_EMC_NFCSR |= EMC_NFCSR_ECCE | EMC_NFCSR_ERST) -+#define __nand_ecc_disable() (REG_EMC_NFCSR &= ~EMC_NFCSR_ECCE) -+ -+/* -+ * MTD structure for JzSOC board -+ */ -+static struct mtd_info *jz_mtd = NULL; -+ -+/* -+ * Define partitions for flash devices -+ */ -+#ifdef CONFIG_JZ4730_PMP -+static struct mtd_partition partition_info[] = { -+ { 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: 56 * 0x100000 }, -+ { name: "NAND SSFDC partition", -+ offset: 64 * 0x100000, -+ size: 64 * 0x100000 }, -+}; -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[]= { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10}; /* reserved blocks of mtd3 */ -+#elif CONFIG_JZ4730_PMPV1 -+static struct mtd_partition partition_info[] = { -+ { name: "NAND ROOTFS partition", -+ offset: 3 * 0x100000, -+ size: (32-3) * 0x100000 }, -+ { name: "NAND DATAFS partition", -+ offset: 32 * 0x100000, -+ size: 32 * 0x100000 }, -+}; -+static int partition_reserved_badblocks[]={ -+ 10, -+ 10}; -+#else -+static struct mtd_partition partition_info[] = { -+ { name: "NAND ROOTFS partition", -+ offset: 3 * 0x100000, -+ size: (128-3) * 0x100000 }, -+}; -+static int partition_reserved_badblocks[]={ -+ 20}; -+#endif -+ -+/*------------------------------------------------------------------------- -+ * Following three functions are exported and used by the mtdblock-jz.c -+ * NAND FTL driver only. -+ */ -+ -+unsigned short get_mtdblock_write_verify_enable(void) -+{ -+#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -+ return 1; -+#endif -+ return 0; -+} -+EXPORT_SYMBOL(get_mtdblock_write_verify_enable); -+ -+unsigned short get_mtdblock_oob_copies(void) -+{ -+ return CONFIG_MTD_OOB_COPIES; -+} -+EXPORT_SYMBOL(get_mtdblock_oob_copies); -+ -+int *get_jz_badblock_table(void) -+{ -+ return partition_reserved_badblocks; -+} -+EXPORT_SYMBOL(get_jz_badblock_table); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void jz_hwcontrol(struct mtd_info *mtd, int dat, -+ unsigned int ctrl) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; -+ -+ if (ctrl & NAND_CTRL_CHANGE) { -+ if ( ctrl & NAND_ALE ) -+ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) | 0x00080000); -+ else -+ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) & ~0x00080000); -+ -+ if ( ctrl & NAND_CLE ) -+ nandaddr = nandaddr | 0x00040000; -+ else -+ nandaddr = nandaddr & ~0x00040000; -+ if ( ctrl & NAND_NCE ) -+ REG_EMC_NFCSR |= EMC_NFCSR_FCE; -+ else -+ REG_EMC_NFCSR &= ~EMC_NFCSR_FCE; -+ } -+ -+ this->IO_ADDR_W = (void __iomem *)nandaddr; -+ if (dat != NAND_CMD_NONE) -+ writeb(dat , this->IO_ADDR_W); -+ -+} -+ -+static int jz_device_ready(struct mtd_info *mtd) -+{ -+ int ready; -+ ready = (REG_EMC_NFCSR & EMC_NFCSR_RB) ? 1 : 0; -+ return ready; -+} -+ -+/* -+ * EMC setup -+ */ -+static void jz_device_setup(void) -+{ -+ /* Set NFE bit */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE; -+} -+ -+static void jzsoc_nand_enable_hwecc(struct mtd_info* mtd, int mode) -+{ -+ __nand_ecc_enable(); -+} -+ -+static int jzsoc_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat, -+ u_char* ecc_code) -+{ -+ unsigned int calc_ecc; -+ unsigned char *tmp; -+ -+ __nand_ecc_disable(); -+ -+ calc_ecc = ~(__nand_ecc()) | 0x00030000; -+ -+ tmp = (unsigned char *)&calc_ecc; -+ -+ ecc_code[0] = tmp[1]; -+ ecc_code[1] = tmp[0]; -+ ecc_code[2] = tmp[2]; -+ -+ return 0; -+} -+ -+/* ECC handling functions */ -+ -+static int jzsoc_nand_correct_data(struct mtd_info *mtd, u_char *dat, -+ u_char *read_ecc, u_char *calc_ecc) -+{ -+ u_char a, b, c, d1, d2, d3, add, bit, i; -+ -+ /* Do error detection */ -+ d1 = calc_ecc[0] ^ read_ecc[0]; -+ d2 = calc_ecc[1] ^ read_ecc[1]; -+ d3 = calc_ecc[2] ^ read_ecc[2]; -+ -+ if ((d1 | d2 | d3) == 0) { -+ /* No errors */ -+ return 0; -+ } -+ else { -+ a = (d1 ^ (d1 >> 1)) & 0x55; -+ b = (d2 ^ (d2 >> 1)) & 0x55; -+ c = (d3 ^ (d3 >> 1)) & 0x54; -+ -+ /* Found and will correct single bit error in the data */ -+ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { -+ c = 0x80; -+ add = 0; -+ a = 0x80; -+ for (i=0; i<4; i++) { -+ if (d1 & c) -+ add |= a; -+ c >>= 2; -+ a >>= 1; -+ } -+ c = 0x80; -+ for (i=0; i<4; i++) { -+ if (d2 & c) -+ add |= a; -+ c >>= 2; -+ a >>= 1; -+ } -+ bit = 0; -+ b = 0x04; -+ c = 0x80; -+ for (i=0; i<3; i++) { -+ if (d3 & c) -+ bit |= b; -+ c >>= 2; -+ b >>= 1; -+ } -+ b = 0x01; -+ a = dat[add]; -+ a ^= (b << bit); -+ dat[add] = a; -+ return 0; -+ } -+ else { -+ i = 0; -+ while (d1) { -+ if (d1 & 0x01) -+ ++i; -+ d1 >>= 1; -+ } -+ while (d2) { -+ if (d2 & 0x01) -+ ++i; -+ d2 >>= 1; -+ } -+ while (d3) { -+ if (d3 & 0x01) -+ ++i; -+ d3 >>= 1; -+ } -+ if (i == 1) { -+ /* ECC Code Error Correction */ -+ read_ecc[0] = calc_ecc[0]; -+ read_ecc[1] = calc_ecc[1]; -+ read_ecc[2] = calc_ecc[2]; -+ return 0; -+ } -+ else { -+ /* Uncorrectable Error */ -+ printk("uncorrectable ECC error\n"); -+ return -1; -+ } -+ } -+ } -+ -+ /* Should never happen */ -+ return -1; -+} -+ -+ -+/* -+ * Main initialization routine -+ */ -+int __init jznand_init(void) -+{ -+ struct nand_chip *this; -+ int nr_partitions; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ jz_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!jz_mtd) { -+ printk ("Unable to allocate JzSOC NAND MTD device structure.\n"); -+ return -ENOMEM; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&jz_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) jz_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ jz_mtd->priv = this; -+ -+ /* Set & initialize NAND Flash controller */ -+ jz_device_setup(); -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = (void __iomem *) NAND_DATA_PORT; -+ this->IO_ADDR_W = (void __iomem *) NAND_DATA_PORT; -+ this->cmd_ctrl = jz_hwcontrol; -+ this->dev_ready = jz_device_ready; -+ -+#ifdef CONFIG_MTD_HW_HM_ECC -+ this->ecc.calculate = jzsoc_nand_calculate_ecc; -+ this->ecc.correct = jzsoc_nand_correct_data; -+ this->ecc.hwctl = jzsoc_nand_enable_hwecc; -+ this->ecc.mode = NAND_ECC_HW; -+ this->ecc.size = 256; -+ this->ecc.bytes = 3; -+ -+#endif -+ -+#ifdef CONFIG_MTD_SW_HM_ECC -+ this->eccmode = NAND_ECC_SOFT; -+#endif -+ -+ /* 20 us command delay time */ -+ this->chip_delay = 20; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan(jz_mtd, 1)) { -+ kfree (jz_mtd); -+ return -ENXIO; -+ } -+ -+ /* Register the partitions */ -+ nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); -+ printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); -+ add_mtd_partitions(jz_mtd, partition_info, nr_partitions); -+ -+ return 0; -+} -+module_init(jznand_init); -+ -+/* -+ * Clean up routine -+ */ -+#ifdef MODULE -+static void __exit jznand_cleanup(void) -+{ -+ struct nand_chip *this = (struct nand_chip *) &jz_mtd[1]; -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(jz_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device (jz_mtd); -+ -+ /* Free internal data buffers */ -+ kfree (this->data_buf); -+ -+ /* Free the MTD device structure */ -+ kfree (jz_mtd); -+} -+module_exit(jznand_cleanup); -+#endif -diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c -new file mode 100644 -index 0000000..5269670 ---- /dev/null -+++ b/drivers/mtd/nand/jz4740_nand.c -@@ -0,0 +1,1123 @@ -+/* -+ * linux/drivers/mtd/nand/jz4740_nand.c -+ * -+ * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Ingenic JZ4740 NAND 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define NAND_DATA_PORT1 0xB8000000 /* read-write area in static bank 1 */ -+#define NAND_DATA_PORT2 0xB4000000 /* read-write area in static bank 2 */ -+#define NAND_DATA_PORT3 0xAC000000 /* read-write area in static bank 3 */ -+#define NAND_DATA_PORT4 0xA8000000 /* read-write area in static bank 4 */ -+ -+#define PAR_SIZE 9 -+ -+#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) -+#define __nand_disable() (REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1) -+ -+#define __nand_ecc_enable() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST ) -+#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE) -+ -+#define __nand_select_hm_ecc() (REG_EMC_NFECR &= ~EMC_NFECR_RS ) -+#define __nand_select_rs_ecc() (REG_EMC_NFECR |= EMC_NFECR_RS) -+ -+#define __nand_read_hm_ecc() (REG_EMC_NFECC & 0x00ffffff) -+ -+#define __nand_rs_ecc_encoding() (REG_EMC_NFECR |= EMC_NFECR_RS_ENCODING) -+#define __nand_rs_ecc_decoding() (REG_EMC_NFECR &= ~EMC_NFECR_RS_ENCODING) -+#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF)) -+#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF)) -+ -+/* -+ * MTD structure for JzSOC board -+ */ -+static struct mtd_info *jz_mtd = NULL; -+extern struct mtd_info *jz_mtd1; -+extern char all_use_planes; -+extern int global_page; /* for two-plane operations */ -+ -+int nr_partitions; /* Number of partitions */ -+ -+/* -+ * Define partitions for flash devices -+ */ -+#ifdef CONFIG_JZ4740_PAVO -+struct mtd_partition partition_info[] = { -+ {name:"NAND BOOT partition", -+ offset:0 * 0x100000, -+ size:4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND KERNEL partition", -+ offset:4 * 0x100000, -+ size:4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND ROOTFS partition", -+ offset:8 * 0x100000, -+ size:504 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND VFAT partition", -+ offset:512 * 0x100000, -+ size:512 * 0x100000, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0}, -+}; -+ -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10, /* reserved blocks of mtd3 */ -+ 20, /* reserved blocks of mtd4 */ -+ 20}; /* reserved blocks of mtd5 */ -+#endif /* CONFIG_JZ4740_PAVO */ -+ -+#ifdef CONFIG_JZ4740_LEO -+struct mtd_partition partition_info[] = { -+ { name: "NAND BOOT partition", -+ offset: 0 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND KERNEL partition", -+ offset: 4 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND ROOTFS partition", -+ offset: 8 * 0x100000, -+ size: 56 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND VFAT partition", -+ offset: 64 * 0x100000, -+ size: 64 * 0x100000, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0 }, -+}; -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10}; /* reserved blocks of mtd3 */ -+#endif /* CONFIG_JZ4740_LEO */ -+ -+#ifdef CONFIG_JZ4740_LYRA -+struct mtd_partition partition_info[] = { -+ { name: "NAND BOOT partition", -+ offset: 0 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND KERNEL partition", -+ offset: 4 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND ROOTFS partition", -+ offset: 8 * 0x100000, -+ size: 120 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND DATA1 partition", -+ offset: 128 * 0x100000, -+ size: 128 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND DATA2 partition", -+ offset: 256 * 0x100000, -+ size: 256 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND VFAT partition", -+ offset: 512 * 0x100000, -+ size: 512 * 0x100000, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0 }, -+}; -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10, /* reserved blocks of mtd3 */ -+ 20, /* reserved blocks of mtd4 */ -+ 20}; /* reserved blocks of mtd5 */ -+#endif /* CONFIG_JZ4740_LYRA */ -+ -+#ifdef CONFIG_JZ4725_DIPPER -+struct mtd_partition partition_info[] = { -+ { name: "NAND BOOT partition", -+ offset: 0 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND KERNEL partition", -+ offset: 4 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND ROOTFS partition", -+ offset: 8 * 0x100000, -+ size: 56 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND VFAT partition", -+ offset: 64 * 0x100000, -+ size: 64 * 0x100000, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0 }, -+}; -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10}; /* reserved blocks of mtd3 */ -+#endif /* CONFIG_JZ4740_DIPPER */ -+ -+#ifdef CONFIG_JZ4720_VIRGO -+struct mtd_partition partition_info[] = { -+ { name: "NAND BOOT partition", -+ offset: 0 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND KERNEL partition", -+ offset: 4 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND ROOTFS partition", -+ offset: 8 * 0x100000, -+ size: 120 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND DATA1 partition", -+ offset: 128 * 0x100000, -+ size: 128 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND DATA2 partition", -+ offset: 256 * 0x100000, -+ size: 256 * 0x100000, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1 }, -+ { name: "NAND VFAT partition", -+ offset: 512 * 0x100000, -+ size: 512 * 0x100000, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0 }, -+}; -+ -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10, /* reserved blocks of mtd3 */ -+ 20, /* reserved blocks of mtd4 */ -+ 20}; /* reserved blocks of mtd5 */ -+#endif /* CONFIG_JZ4720_VIRGO */ -+ -+#ifdef CONFIG_JZ4740_QI_LB60 -+static struct mtd_partition partition_info[] = { -+ { name: "NAND BOOT partition", -+ offset: 0 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0 }, -+ { name: "NAND KERNEL partition", -+ offset: 4 * 0x100000, -+ size: 4 * 0x100000, -+ use_planes: 0 }, -+ { name: "NAND ROOTFS partition", -+ offset: 8 * 0x100000, -+ size: 504 * 0x100000, -+ use_planes: 0 }, -+ { name: "NAND DATA1 partition", -+ offset: 512 * 0x100000, -+ size: 512 * 0x100000, -+ use_planes: 1 }, -+ { name: "NAND DATA2 partition", -+ offset: 1024 * 0x100000, -+ size: 512 * 0x100000, -+ use_planes: 1 }, -+ { name: "NAND VFAT partition", -+ offset: (1024 + 512) * 0x100000, -+ size: 512 * 0x100000, -+ use_planes: 1 }, -+}; -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10, /* reserved blocks of mtd3 */ -+ 10, /* reserved blocks of mtd4 */ -+ 20}; /* reserved blocks of mtd5 */ -+#endif /* CONFIG_JZ4740_QI_LB60 */ -+ -+/*------------------------------------------------------------------------- -+ * Following three functions are exported and used by the mtdblock-jz.c -+ * NAND FTL driver only. -+ */ -+ -+unsigned short get_mtdblock_write_verify_enable(void) -+{ -+#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -+ return 1; -+#endif -+ return 0; -+} -+EXPORT_SYMBOL(get_mtdblock_write_verify_enable); -+ -+unsigned short get_mtdblock_oob_copies(void) -+{ -+ return CONFIG_MTD_OOB_COPIES; -+} -+EXPORT_SYMBOL(get_mtdblock_oob_copies); -+ -+int *get_jz_badblock_table(void) -+{ -+ return partition_reserved_badblocks; -+} -+EXPORT_SYMBOL(get_jz_badblock_table); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void jz_hwcontrol(struct mtd_info *mtd, int dat, -+ unsigned int ctrl) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; -+ extern u8 nand_nce; /* in nand_base.c, indicates which chip select is used for current nand chip */ -+ -+ if (ctrl & NAND_CTRL_CHANGE) { -+ if (ctrl & NAND_NCE) { -+ switch (nand_nce) { -+ case NAND_NCE1: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; -+ break; -+ case NAND_NCE2: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE2; -+ break; -+ case NAND_NCE3: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE3; -+ break; -+ case NAND_NCE4: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT4; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE4; -+ break; -+ default: -+ printk("error: no nand_nce 0x%x\n",nand_nce); -+ break; -+ } -+ } else { -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ } -+ -+ if ( ctrl & NAND_ALE ) -+ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) | 0x00010000); -+ else -+ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) & ~0x00010000); -+ -+ if ( ctrl & NAND_CLE ) -+ nandaddr = nandaddr | 0x00008000; -+ else -+ nandaddr = nandaddr & ~0x00008000; -+ } -+ -+ this->IO_ADDR_W = (void __iomem *)nandaddr; -+ if (dat != NAND_CMD_NONE) -+ writeb(dat, this->IO_ADDR_W); -+} -+ -+static int jz_device_ready(struct mtd_info *mtd) -+{ -+ int ready, wait = 10; -+ while (wait--); -+ ready = __gpio_get_pin(94); -+ return ready; -+} -+ -+/* -+ * EMC setup -+ */ -+static void jz_device_setup(void) -+{ -+// PORT 0: -+// ... -+// PORT 1: -+// PIN/BIT N FUNC0 FUNC1 -+// 25 CS1# - -+// 26 CS2# - -+// 27 CS3# - -+// 28 CS4# - -+#define GPIO_CS2_N (32+26) -+#define GPIO_CS3_N (32+27) -+#define GPIO_CS4_N (32+28) -+#define SMCR_VAL 0x0d221200 -+ -+ /* Set NFE bit */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE1; -+ /* Read/Write timings */ -+ REG_EMC_SMCR1 = SMCR_VAL; -+ -+#if defined(CONFIG_MTD_NAND_CS2) -+ /* Set CS2# pin as function 0 */ -+ __gpio_as_func0(GPIO_CS2_N); -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE2; -+ REG_EMC_SMCR2 = SMCR_VAL; -+#endif -+ -+#if defined(CONFIG_MTD_NAND_CS3) -+ __gpio_as_func0(GPIO_CS3_N); -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE3; -+ REG_EMC_SMCR3 = SMCR_VAL; -+#endif -+ -+#if defined(CONFIG_MTD_NAND_CS4) -+ __gpio_as_func0(GPIO_CS4_N); -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE4; -+ REG_EMC_SMCR4 = SMCR_VAL; -+#endif -+} -+ -+#ifdef CONFIG_MTD_HW_HM_ECC -+ -+static int jzsoc_nand_calculate_hm_ecc(struct mtd_info* mtd, -+ const u_char* dat, u_char* ecc_code) -+{ -+ unsigned int calc_ecc; -+ unsigned char *tmp; -+ -+ __nand_ecc_disable(); -+ -+ calc_ecc = ~(__nand_read_hm_ecc()) | 0x00030000; -+ -+ tmp = (unsigned char *)&calc_ecc; -+ //adjust eccbytes order for compatible with software ecc -+ ecc_code[0] = tmp[1]; -+ ecc_code[1] = tmp[0]; -+ ecc_code[2] = tmp[2]; -+ -+ return 0; -+} -+ -+static void jzsoc_nand_enable_hm_hwecc(struct mtd_info* mtd, int mode) -+{ -+ __nand_ecc_enable(); -+ __nand_select_hm_ecc(); -+} -+ -+static int jzsoc_nand_hm_correct_data(struct mtd_info *mtd, u_char *dat, -+ u_char *read_ecc, u_char *calc_ecc) -+{ -+ u_char a, b, c, d1, d2, d3, add, bit, i; -+ -+ /* Do error detection */ -+ d1 = calc_ecc[0] ^ read_ecc[0]; -+ d2 = calc_ecc[1] ^ read_ecc[1]; -+ d3 = calc_ecc[2] ^ read_ecc[2]; -+ -+ if ((d1 | d2 | d3) == 0) { -+ /* No errors */ -+ return 0; -+ } -+ else { -+ a = (d1 ^ (d1 >> 1)) & 0x55; -+ b = (d2 ^ (d2 >> 1)) & 0x55; -+ c = (d3 ^ (d3 >> 1)) & 0x54; -+ -+ /* Found and will correct single bit error in the data */ -+ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { -+ c = 0x80; -+ add = 0; -+ a = 0x80; -+ for (i=0; i<4; i++) { -+ if (d1 & c) -+ add |= a; -+ c >>= 2; -+ a >>= 1; -+ } -+ c = 0x80; -+ for (i=0; i<4; i++) { -+ if (d2 & c) -+ add |= a; -+ c >>= 2; -+ a >>= 1; -+ } -+ bit = 0; -+ b = 0x04; -+ c = 0x80; -+ for (i=0; i<3; i++) { -+ if (d3 & c) -+ bit |= b; -+ c >>= 2; -+ b >>= 1; -+ } -+ b = 0x01; -+ a = dat[add]; -+ a ^= (b << bit); -+ dat[add] = a; -+ return 0; -+ } -+ else { -+ i = 0; -+ while (d1) { -+ if (d1 & 0x01) -+ ++i; -+ d1 >>= 1; -+ } -+ while (d2) { -+ if (d2 & 0x01) -+ ++i; -+ d2 >>= 1; -+ } -+ while (d3) { -+ if (d3 & 0x01) -+ ++i; -+ d3 >>= 1; -+ } -+ if (i == 1) { -+ /* ECC Code Error Correction */ -+ read_ecc[0] = calc_ecc[0]; -+ read_ecc[1] = calc_ecc[1]; -+ read_ecc[2] = calc_ecc[2]; -+ return 0; -+ } -+ else { -+ /* Uncorrectable Error */ -+ printk("NAND: uncorrectable ECC error\n"); -+ return -1; -+ } -+ } -+ } -+ -+ /* Should never happen */ -+ return -1; -+} -+ -+#endif /* CONFIG_MTD_HW_HM_ECC */ -+ -+#ifdef CONFIG_MTD_HW_RS_ECC -+ -+static void jzsoc_nand_enable_rs_hwecc(struct mtd_info* mtd, int mode) -+{ -+ REG_EMC_NFINTS = 0x0; -+ __nand_ecc_enable(); -+ __nand_select_rs_ecc(); -+ -+ if (mode == NAND_ECC_READ) -+ __nand_rs_ecc_decoding(); -+ -+ if (mode == NAND_ECC_WRITE) -+ __nand_rs_ecc_encoding(); -+} -+ -+static void jzsoc_rs_correct(unsigned char *dat, int idx, int mask) -+{ -+ int i; -+ -+ idx--; -+ -+ i = idx + (idx >> 3); -+ if (i >= 512) -+ return; -+ -+ mask <<= (idx & 0x7); -+ -+ dat[i] ^= mask & 0xff; -+ if (i < 511) -+ dat[i+1] ^= (mask >> 8) & 0xff; -+} -+ -+/* -+ * calc_ecc points to oob_buf for us -+ */ -+static int jzsoc_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat, -+ u_char *read_ecc, u_char *calc_ecc) -+{ -+ volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0; -+ short k; -+ u32 stat; -+ -+ /* Set PAR values */ -+ for (k = 0; k < PAR_SIZE; k++) { -+ *paraddr++ = read_ecc[k]; -+ } -+ -+ /* Set PRDY */ -+ REG_EMC_NFECR |= EMC_NFECR_PRDY; -+ -+ /* Wait for completion */ -+ __nand_ecc_decode_sync(); -+ __nand_ecc_disable(); -+ -+ /* Check decoding */ -+ stat = REG_EMC_NFINTS; -+ -+ if (stat & EMC_NFINTS_ERR) { -+ /* Error occurred */ -+ if (stat & EMC_NFINTS_UNCOR) { -+ printk("NAND: Uncorrectable ECC error\n"); -+ return -1; -+ } else { -+ u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT; -+ switch (errcnt) { -+ case 4: -+ jzsoc_rs_correct(dat, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -+ /* FALL-THROUGH */ -+ case 3: -+ jzsoc_rs_correct(dat, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -+ /* FALL-THROUGH */ -+ case 2: -+ jzsoc_rs_correct(dat, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -+ /* FALL-THROUGH */ -+ case 1: -+ jzsoc_rs_correct(dat, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -+ return 0; -+ default: -+ break; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int jzsoc_nand_calculate_rs_ecc(struct mtd_info* mtd, const u_char* dat, -+ u_char* ecc_code) -+{ -+ volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0; -+ short i; -+ -+ __nand_ecc_encode_sync(); -+ __nand_ecc_disable(); -+ -+ for(i = 0; i < PAR_SIZE; i++) { -+ ecc_code[i] = *paraddr++; -+ } -+ -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_HW_RS_ECC */ -+ -+/* Nand optimized functions */ -+static int dma_chan; -+static unsigned int dma_src_phys_addr, dma_dst_phys_addr; -+extern int jz_request_dma(int dev_id, const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, void *irq_dev_id); -+ -+static void dma_setup(void) -+{ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", NULL, IRQF_DISABLED, NULL); -+ if (dma_chan < 0) { -+ printk("Setup irq for nand failed!\n"); -+ return; -+ } else -+ printk("Nand DMA request channel %d.\n",dma_chan); -+} -+ -+static void jz4740_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) -+{ -+ int i; -+ struct nand_chip *chip = mtd->priv; -+ -+ if ((len <= 32) || (len & 0xf) || ((u32)buf >= (u32)high_memory)) -+ { -+ for (i = 0; i < len; i++) -+ buf[i] = readb(chip->IO_ADDR_R); -+ } else { -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ dma_src_phys_addr = CPHYSADDR(chip->IO_ADDR_R); -+ dma_dst_phys_addr = CPHYSADDR(buf); -+ dma_cache_inv((u32)buf, len); -+ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -+ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -+ REG_DMAC_DTCR(dma_chan) = len / 16; -+ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_DAI | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ -+ -+ while(!(REG_DMAC_DCCSR(dma_chan) & DMAC_DCCSR_TT)); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ __dmac_channel_clear_transmit_end(dma_chan); -+ } -+} -+ -+static void jz4740_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) -+{ -+ int i; -+ struct nand_chip *chip = mtd->priv; -+ -+ if ((len <= 32) || (len & 0xf) || ((u32)buf >= (u32)high_memory)) -+ { -+ for (i = 0; i < len; i++) -+ writeb(buf[i], chip->IO_ADDR_W); -+ } else { -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -+ dma_dst_phys_addr = CPHYSADDR(chip->IO_ADDR_R); -+ dma_src_phys_addr = CPHYSADDR(buf); -+ dma_cache_wback((unsigned long)buf, len); -+ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -+ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -+ REG_DMAC_DTCR(dma_chan) = len / 16; -+ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_16BYTE ; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -+ REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ -+ -+ while(!(REG_DMAC_DCCSR(dma_chan) & DMAC_DCCSR_TT)); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ __dmac_channel_clear_transmit_end(dma_chan); -+ } -+} -+ -+static int nand_read_page_hwecc_rs_planes(struct mtd_info *mtd, struct nand_chip *chip, -+ uint8_t *buf) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccbytes = chip->ecc.bytes; -+ int eccsteps = chip->ecc.steps >> 1; -+ uint8_t *p; -+ uint8_t *ecc_calc = chip->buffers->ecccalc; -+ uint8_t *ecc_code = chip->buffers->ecccode; -+ uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t page; -+ uint8_t flag = 0; -+ int oobsize = mtd->oobsize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ int ecctotal = chip->ecc.total >> 1; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* Read first page */ -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ chip->read_buf(mtd, chip->oob_poi, oobsize); -+ for (i = 0; i < ecctotal; i++) { -+ ecc_code[i] = chip->oob_poi[eccpos[i]]; -+ if (ecc_code[i] != 0xff) flag = 1; -+ } -+ -+ p = buf; -+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -+ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -+ int stat; -+ if (flag) { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -+ if (stat < 0) -+ mtd->ecc_stats.failed++; -+ else -+ mtd->ecc_stats.corrected += stat; -+ } -+ else { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ } -+ } -+ /* Read second page */ -+ page += ppb; -+ flag = 0; -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ chip->read_buf(mtd, chip->oob_poi + oobsize, oobsize); -+ for (i = 0; i < ecctotal; i++) { -+ ecc_code[i] = chip->oob_poi[oobsize + eccpos[i]]; -+ if (ecc_code[i] != 0xff) flag = 1; -+ } -+ -+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -+ eccsteps = chip->ecc.steps >> 1; -+ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -+ int stat; -+ if (flag) { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -+ if (stat < 0) -+ mtd->ecc_stats.failed++; -+ else -+ mtd->ecc_stats.corrected += stat; -+ } -+ else { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ } -+ } -+ -+ return 0; -+} -+ -+static int nand_read_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -+ int global_page, int sndcmd) -+{ -+ int page; -+ int oobsize = mtd->oobsize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* Read first page OOB */ -+ if (sndcmd) { -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ } -+ chip->read_buf(mtd, chip->oob_poi, oobsize); -+ /* Read second page OOB */ -+ page += ppb; -+ if (sndcmd) { -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ sndcmd = 0; -+ } -+ chip->read_buf(mtd, chip->oob_poi+oobsize, oobsize); -+ return 0; -+} -+ -+static int nand_write_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -+ int global_page) -+{ -+ int status = 0,page; -+ int pagesize = mtd->writesize >> 1; -+ int oobsize = mtd->oobsize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ const uint8_t *buf = chip->oob_poi; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x80, pagesize, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x80, pagesize, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ chip->write_buf(mtd, buf, oobsize); -+ /* Send first command to program the OOB data */ -+ chip->cmdfunc(mtd, 0x11, -1, -1); -+ ndelay(100); -+ status = chip->waitfunc(mtd, chip); -+ -+ page += ppb; -+ buf += oobsize; -+ chip->cmdfunc(mtd, 0x81, pagesize, page); -+ chip->write_buf(mtd, buf, oobsize); -+ /* Send command to program the OOB data */ -+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+ /* Wait long R/B */ -+ ndelay(100); -+ status = chip->waitfunc(mtd, chip); -+ -+ return status & NAND_STATUS_FAIL ? -EIO : 0; -+} -+ -+static void nand_write_page_hwecc_planes(struct mtd_info *mtd, struct nand_chip *chip, -+ const uint8_t *buf) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccbytes = chip->ecc.bytes; -+ int eccsteps = chip->ecc.steps >> 1; -+ uint8_t *ecc_calc = chip->buffers->ecccalc; -+ uint8_t *p = (uint8_t *)buf; -+ uint32_t *eccpos = chip->ecc.layout->eccpos; -+ int oobsize = mtd->oobsize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ int ecctotal = chip->ecc.total >> 1; -+ int page; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x80, 0x00, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ chip->write_buf(mtd, p, eccsize); -+ chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ } -+ for (i = 0; i < ecctotal; i++) -+ chip->oob_poi[eccpos[i]] = ecc_calc[i]; -+ -+ chip->write_buf(mtd, chip->oob_poi, oobsize); -+ -+ chip->cmdfunc(mtd, 0x11, -1, -1); /* send cmd 0x11 */ -+ ndelay(100); -+ while(!chip->dev_ready(mtd)); -+ -+ page += ppb; -+ chip->cmdfunc(mtd, 0x81, 0x00, page); /* send cmd 0x81 */ -+ eccsteps = chip->ecc.steps >> 1; -+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ chip->write_buf(mtd, p, eccsize); -+ chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ } -+ -+ for (i = 0; i < ecctotal; i++) -+ chip->oob_poi[eccpos[i]] = ecc_calc[i]; -+ -+ chip->write_buf(mtd, chip->oob_poi, oobsize); -+} -+ -+static void single_erase_cmd_planes(struct mtd_info *mtd, int global_page) -+{ -+ struct nand_chip *chip = mtd->priv; -+ -+ /* Send commands to erase a block */ -+ int page; -+ int ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x60, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x60, -1, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x60, -1, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ page += ppb; -+ chip->cmdfunc(mtd, 0x60, -1, page & (~(ppb-1))); /* send cmd 0x60 */ -+ -+ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); /* send cmd 0xd0 */ -+ /* Do not need wait R/B or check status */ -+} -+ -+/* -+ * Main initialization routine -+ */ -+int __init jznand_init(void) -+{ -+ struct nand_chip *this; -+ int ret, i; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ jz_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!jz_mtd) { -+ printk ("Unable to allocate JzSOC NAND MTD device structure.\n"); -+ return -ENOMEM; -+ } -+ -+ jz_mtd1 = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!jz_mtd1) { -+ printk ("Unable to allocate JzSOC NAND MTD device structure 1.\n"); -+ kfree(jz_mtd); -+ return -ENOMEM; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&jz_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) jz_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ jz_mtd->priv = this; -+ -+ /* Set & initialize NAND Flash controller */ -+ jz_device_setup(); -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = (void __iomem *) NAND_DATA_PORT1; -+ this->IO_ADDR_W = (void __iomem *) NAND_DATA_PORT1; -+ this->cmd_ctrl = jz_hwcontrol; -+ this->dev_ready = jz_device_ready; -+ -+#ifdef CONFIG_MTD_HW_HM_ECC -+ this->ecc.calculate = jzsoc_nand_calculate_hm_ecc; -+ this->ecc.correct = jzsoc_nand_hm_correct_data; -+ this->ecc.hwctl = jzsoc_nand_enable_hm_hwecc; -+ this->ecc.mode = NAND_ECC_HW; -+ this->ecc.size = 256; -+ this->ecc.bytes = 3; -+ -+#endif -+ -+#ifdef CONFIG_MTD_HW_RS_ECC -+ this->ecc.calculate = jzsoc_nand_calculate_rs_ecc; -+ this->ecc.correct = jzsoc_nand_rs_correct_data; -+ this->ecc.hwctl = jzsoc_nand_enable_rs_hwecc; -+ this->ecc.mode = NAND_ECC_HW; -+ this->ecc.size = 512; -+ this->ecc.bytes = 9; -+#endif -+ -+#ifdef CONFIG_MTD_SW_HM_ECC -+ this->ecc.mode = NAND_ECC_SOFT; -+#endif -+ /* 20 us command delay time */ -+ this->chip_delay = 20; -+ -+#ifdef CONFIG_MTD_NAND_DMA -+ dma_setup(); -+#endif -+ /* Scan to find existance of the device */ -+ ret = nand_scan_ident(jz_mtd, NAND_MAX_CHIPS); -+ if (!ret) { -+ if (this->planenum == 2) { -+ /* reset nand functions */ -+ this->erase_cmd = single_erase_cmd_planes; -+ this->ecc.read_page = nand_read_page_hwecc_rs_planes; //Muti planes read -+ this->ecc.write_page = nand_write_page_hwecc_planes; -+ this->ecc.read_oob = nand_read_oob_std_planes; -+ this->ecc.write_oob = nand_write_oob_std_planes; -+#ifdef CONFIG_MTD_NAND_DMA -+ this->write_buf = jz4740_nand_write_buf; -+ this->read_buf = jz4740_nand_read_buf; -+#endif -+ printk(KERN_INFO "Nand using two-plane mode, " -+ "and resized to writesize:%d oobsize:%d blocksize:0x%x \n", -+ jz_mtd->writesize, jz_mtd->oobsize, jz_mtd->erasesize); -+ } -+ } -+ -+ /* Determine whether all the partitions will use multiple planes if supported */ -+ nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); -+ all_use_planes = 1; -+ for (i = 0; i < nr_partitions; i++) { -+ all_use_planes &= partition_info[i].use_planes; -+ } -+ -+ if (!ret) -+ ret = nand_scan_tail(jz_mtd); -+ -+ if (ret){ -+ kfree (jz_mtd1); -+ kfree (jz_mtd); -+ return -ENXIO; -+ } -+ -+ /* Register the partitions */ -+ printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); -+ -+ if ((this->planenum == 2) && !all_use_planes) { -+ for (i = 0; i < nr_partitions; i++) { -+ if (partition_info[i].use_planes) -+ add_mtd_partitions(jz_mtd, &partition_info[i], 1); -+ else -+ add_mtd_partitions(jz_mtd1, &partition_info[i], 1); -+ } -+ } else { -+ kfree(jz_mtd1); -+ add_mtd_partitions(jz_mtd, partition_info, nr_partitions); -+ } -+ return 0; -+} -+module_init(jznand_init); -+ -+/* -+ * Clean up routine -+ */ -+#ifdef MODULE -+static void __exit jznand_cleanup(void) -+{ -+ struct nand_chip *this = (struct nand_chip *) &jz_mtd[1]; -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(jz_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device (jz_mtd); -+ -+ /* Free internal data buffers */ -+ kfree (this->data_buf); -+ -+ /* Free the MTD device structure */ -+ if ((this->planenum == 2) && !all_use_planes) -+ kfree (jz_mtd1); -+ kfree (jz_mtd); -+} -+module_exit(jznand_cleanup); -+#endif -diff --git a/drivers/mtd/nand/jz4750_nand.c b/drivers/mtd/nand/jz4750_nand.c -new file mode 100644 -index 0000000..f50fe74 ---- /dev/null -+++ b/drivers/mtd/nand/jz4750_nand.c -@@ -0,0 +1,1857 @@ -+/* -+ * linux/drivers/mtd/nand/jz4750_nand.c -+ * -+ * JZ4750 NAND driver -+ * -+ * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* 32bit instead of 16byte burst is used by DMA to read or -+ write NAND and BCH avoiding grabbing bus for too long */ -+#define DMAC_DCMD_DS_NAND DMAC_DCMD_DS_32BIT -+#define DIV_DS_NAND 4 -+ -+#define DMAC_DCMD_DS_BCH DMAC_DCMD_DS_32BIT -+#define DIV_DS_BCH 4 -+ -+#define DEBUG1 0 -+#if DEBUG1 -+#define dprintk(n,x...) printk(n,##x) -+#else -+#define dprintk(n,x...) -+#endif -+ -+#if defined(CONFIG_MTD_HW_BCH_8BIT) -+#define __ECC_ENCODING __ecc_encoding_8bit -+#define __ECC_DECODING __ecc_decoding_8bit -+#define ERRS_SIZE 5 /* 5 words */ -+#else -+#define __ECC_ENCODING __ecc_encoding_4bit -+#define __ECC_DECODING __ecc_decoding_4bit -+#define ERRS_SIZE 3 /* 3 words */ -+#endif -+ -+#define NAND_DATA_PORT1 0xB8000000 /* read-write area in static bank 1 */ -+#define NAND_DATA_PORT2 0xB4000000 /* read-write area in static bank 2 */ -+#define NAND_DATA_PORT3 0xAC000000 /* read-write area in static bank 3 */ -+#define NAND_DATA_PORT4 0xA8000000 /* read-write area in static bank 4 */ -+ -+#define NAND_ADDR_OFFSET0 0x00010000 /* address port offset for share mode */ -+#define NAND_CMD_OFFSET0 0x00008000 /* command port offset for share mode */ -+#define NAND_ADDR_OFFSET1 0x00000010 /* address port offset for unshare mode */ -+#define NAND_CMD_OFFSET1 0x00000008 /* command port offset for unshare mode */ -+ -+#if defined(CONFIG_MTD_NAND_DMA) -+#define USE_IRQ 1 -+enum { -+ NAND_NONE, -+ NAND_PROG, -+ NAND_READ -+}; -+static volatile u8 nand_status; -+static volatile int dma_ack = 0; -+static volatile int dma_ack1 = 0; -+static char nand_dma_chan; /* automatically select a free channel */ -+static char bch_dma_chan = 0; /* fixed to channel 0 */ -+static u32 *errs; -+static jz_dma_desc_8word *dma_desc_enc, *dma_desc_enc1, *dma_desc_dec, *dma_desc_dec1, *dma_desc_dec2, -+ *dma_desc_nand_prog, *dma_desc_nand_read; -+static u32 *pval_nand_ddr; -+static u8 *pval_nand_cmd_pgprog; /* for sending 0x11 or 0x10 when programing*/ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+u8 *prog_buf, *read_buf; -+#endif -+DECLARE_WAIT_QUEUE_HEAD(nand_prog_wait_queue); -+DECLARE_WAIT_QUEUE_HEAD(nand_read_wait_queue); -+#endif -+ -+struct buf_be_corrected { -+ u8 *data; -+ u8 *oob; -+}; -+ -+static u32 addr_offset; -+static u32 cmd_offset; -+static int nand_chips = 1; /* Number of nand chips to be scanned */ -+extern int global_page; /* for two-plane operations */ -+ -+/* -+ * MTD structure for JzSOC board -+ */ -+static struct mtd_info *jz_mtd = NULL; -+extern struct mtd_info *jz_mtd1; -+extern char all_use_planes; -+ -+int nr_partitions; /* Number of partitions */ -+ -+/* -+ * Define partitions for flash devices -+ */ -+#if defined(CONFIG_JZ4750_FUWA) || defined(CONFIG_JZ4750D_FUWA1) || defined(CONFIG_JZ4750D_CETUS) -+struct mtd_partition partition_info[] = { -+ {name:"NAND BOOT partition", -+ offset:0 * 0x100000, -+ size:4 * 0x100000, -+ cpu_mode: 1, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND KERNEL partition", -+ offset:4 * 0x100000, -+ size:4 * 0x100000, -+ cpu_mode: 1, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND ROOTFS partition", -+ offset:8 * 0x100000, -+ size:120 * 0x100000, -+ cpu_mode: 1, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND DATA1 partition", -+ offset:128 * 0x100000, -+ size:128 * 0x100000, -+ cpu_mode: 1, -+ use_planes: 1, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND DATA2 partition", -+ offset:256 * 0x100000, -+ size:256 * 0x100000, -+ cpu_mode: 1, -+ use_planes: 1, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND VFAT partition", -+ offset:512 * 0x100000, -+ size:512 * 0x100000, -+ cpu_mode: 0, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0}, -+}; -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10, /* reserved blocks of mtd3 */ -+ 20, /* reserved blocks of mtd4 */ -+ 20 -+}; /* reserved blocks of mtd5 */ -+#endif /* CONFIG_JZ4750_FUWA */ -+ -+#if defined(CONFIG_JZ4750_APUS) -+struct mtd_partition partition_info[] = { -+ {name:"NAND BOOT partition", -+ offset:0 * 0x100000, -+ size:4 * 0x100000, -+ cpu_mode: 0, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND KERNEL partition", -+ offset:4 * 0x100000, -+ size:4 * 0x100000, -+ cpu_mode: 0, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND ROOTFS partition", -+ offset:8 * 0x100000, -+ size:504 * 0x100000, -+ cpu_mode: 1, -+ use_planes: 0, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND DATA partition", -+ offset:512 * 0x100000, -+ size:512 * 0x100000, -+ cpu_mode: 0, -+ use_planes: 1, -+ mtdblock_jz_invalid: 1}, -+ {name:"NAND VFAT partition", -+ offset:1024 * 0x100000, -+ size:1024 * 0x100000, -+ cpu_mode: 0, -+ use_planes: 1, -+ mtdblock_jz_invalid: 0}, -+}; -+ -+ -+/* Define max reserved bad blocks for each partition. -+ * This is used by the mtdblock-jz.c NAND FTL driver only. -+ * -+ * The NAND FTL driver reserves some good blocks which can't be -+ * seen by the upper layer. When the bad block number of a partition -+ * exceeds the max reserved blocks, then there is no more reserved -+ * good blocks to be used by the NAND FTL driver when another bad -+ * block generated. -+ */ -+static int partition_reserved_badblocks[] = { -+ 2, /* reserved blocks of mtd0 */ -+ 2, /* reserved blocks of mtd1 */ -+ 10, /* reserved blocks of mtd2 */ -+ 10, /* reserved blocks of mtd3 */ -+ 10, /* reserved blocks of mtd4 */ -+}; -+#endif /* CONFIG_JZ4750_APUS */ -+ -+/*------------------------------------------------------------------------- -+ * Following three functions are exported and used by the mtdblock-jz.c -+ * NAND FTL driver only. -+ */ -+ -+unsigned short get_mtdblock_write_verify_enable(void) -+{ -+#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -+ return 1; -+#endif -+ return 0; -+} -+ -+EXPORT_SYMBOL(get_mtdblock_write_verify_enable); -+ -+unsigned short get_mtdblock_oob_copies(void) -+{ -+ return CONFIG_MTD_OOB_COPIES; -+} -+ -+EXPORT_SYMBOL(get_mtdblock_oob_copies); -+ -+int *get_jz_badblock_table(void) -+{ -+ if (sizeof(partition_reserved_badblocks) / sizeof(int) != nr_partitions) -+ printk("partition_reserved_badblocks setting error!\n"); -+ -+ return partition_reserved_badblocks; -+} -+ -+EXPORT_SYMBOL(get_jz_badblock_table); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void jz_hwcontrol(struct mtd_info *mtd, int dat, u32 ctrl) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ u32 nandaddr = (u32)this->IO_ADDR_W; -+ extern u8 nand_nce; /* defined in nand_base.c, indicates which chip select is used for current nand chip */ -+ -+ if (ctrl & NAND_CTRL_CHANGE) { -+ if (ctrl & NAND_NCE) { -+ switch (nand_nce) { -+ case NAND_NCE1: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; -+ break; -+ case NAND_NCE2: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE2; -+ break; -+ case NAND_NCE3: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE3; -+ break; -+ case NAND_NCE4: -+ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT4; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE4; -+ break; -+ default: -+ printk("error: no nand_nce 0x%x\n",nand_nce); -+ break; -+ } -+ } else { -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -+ } -+ -+ if (ctrl & NAND_ALE) -+ nandaddr = (u32)((u32)(this->IO_ADDR_W) | addr_offset); -+ else -+ nandaddr = (u32)((u32)(this->IO_ADDR_W) & ~addr_offset); -+ if (ctrl & NAND_CLE) -+ nandaddr = (u32)(nandaddr | cmd_offset); -+ else -+ nandaddr = (u32)(nandaddr & ~cmd_offset); -+ } -+ -+ this->IO_ADDR_W = (void __iomem *)nandaddr; -+ if (dat != NAND_CMD_NONE) { -+ writeb(dat, this->IO_ADDR_W); -+ /* printk("write cmd:0x%x to 0x%x\n",dat,(u32)this->IO_ADDR_W); */ -+ } -+} -+ -+static int jz_device_ready(struct mtd_info *mtd) -+{ -+ int ready, wait = 10; -+ while (wait--); -+ ready = __gpio_get_pin(91); -+ return ready; -+} -+ -+/* -+ * EMC setup -+ */ -+static void jz_device_setup(void) -+{ -+// PORT 0: -+// PORT 1: -+// PORT 2: -+// PIN/BIT N FUNC0 FUNC1 -+// 21 CS1# - -+// 22 CS2# - -+// 23 CS3# - -+// 24 CS4# - -+#define GPIO_CS2_N (32*2+22) -+#define GPIO_CS3_N (32*2+23) -+#define GPIO_CS4_N (32*2+24) -+#define SMCR_VAL 0x0d444400 -+ -+ __gpio_as_nand_8bit(1); -+ /* Set NFE bit */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE1; -+ /* Read/Write timings */ -+ REG_EMC_SMCR1 = SMCR_VAL; -+ -+#if defined(CONFIG_MTD_NAND_CS2) -+ __gpio_as_func0(GPIO_CS2_N); -+ /* Set NFE bit */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE2; -+ /* Read/Write timings */ -+ REG_EMC_SMCR2 = SMCR_VAL; -+ nand_chips++; -+#endif -+ -+#if defined(CONFIG_MTD_NAND_CS3) -+ __gpio_as_func0(GPIO_CS3_N); -+ /* Set NFE bit */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE3; -+ /* Read/Write timings */ -+ REG_EMC_SMCR3 = SMCR_VAL; -+ nand_chips++; -+#endif -+ -+#if defined(CONFIG_MTD_NAND_CS4) -+ __gpio_as_func0(GPIO_CS4_N); -+ /* Set NFE bit */ -+ REG_EMC_NFCSR |= EMC_NFCSR_NFE4; -+ /* Read/Write timings */ -+ REG_EMC_SMCR4 = SMCR_VAL; -+ nand_chips++; -+#endif -+} -+ -+#ifdef CONFIG_MTD_HW_BCH_ECC -+ -+static void jzsoc_nand_enable_bch_hwecc(struct mtd_info *mtd, int mode) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ int eccsize = this->ecc.size; -+ int eccbytes = this->ecc.bytes; -+ int eccsteps = this->ecc.steps / this->planenum; -+ int oob_per_eccsize = this->ecc.layout->eccpos[0] / eccsteps; -+ -+ REG_BCH_INTS = 0xffffffff; -+ if (mode == NAND_ECC_READ) { -+ __ECC_DECODING(); -+ __ecc_cnt_dec(eccsize + oob_per_eccsize + eccbytes); -+ -+ if (!(mtd->flags & MTD_NAND_CPU_MODE)) -+ __ecc_dma_enable(); -+ else -+ __ecc_dma_disable(); -+ } -+ -+ if (mode == NAND_ECC_WRITE) { -+ __ECC_ENCODING(); -+ __ecc_cnt_enc(eccsize + oob_per_eccsize); -+ -+ if (!(mtd->flags & MTD_NAND_CPU_MODE)) -+ __ecc_dma_enable(); -+ else -+ __ecc_dma_disable(); -+ } -+} -+ -+/** -+ * bch_correct -+ * @dat: data to be corrected -+ * @idx: the index of error bit in an eccsize -+ */ -+static void bch_correct(struct mtd_info *mtd, u8 * dat, int idx) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ int eccsize = this->ecc.size; -+ int eccsteps = this->ecc.steps / this->planenum; -+ int ecc_pos = this->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ int i, bit; /* the 'bit' of i byte is error */ -+ -+ i = (idx - 1) >> 3; -+ bit = (idx - 1) & 0x7; -+ -+ dprintk("error:i=%d, bit=%d\n",i,bit); -+ -+ if (i < eccsize){ -+ ((struct buf_be_corrected *)dat)->data[i] ^= (1 << bit); -+ } else if (i < eccsize + oob_per_eccsize) { -+ ((struct buf_be_corrected *)dat)->oob[i-eccsize] ^= (1 << bit); -+ } -+} -+ -+#if defined(CONFIG_MTD_NAND_DMA) -+ -+/** -+ * jzsoc_nand_bch_correct_data -+ * @mtd: mtd info structure -+ * @dat: data to be corrected -+ * @errs0: pointer to the dma target buffer of bch decoding which stores BHINTS and -+ * BHERR0~3(8-bit BCH) or BHERR0~1(4-bit BCH) -+ * @calc_ecc: no used -+ */ -+static int jzsoc_nand_bch_correct_data(struct mtd_info *mtd, u_char * dat, u_char * errs0, u_char * calc_ecc) -+{ -+ u32 stat; -+ u32 *errs = (u32 *)errs0; -+ -+ if (REG_DMAC_DCCSR(0) & DMAC_DCCSR_BERR) { -+ stat = errs[0]; -+ dprintk("stat=%x err0:%x err1:%x \n", stat, errs[1], errs[2]); -+ -+ if (stat & BCH_INTS_ERR) { -+ if (stat & BCH_INTS_UNCOR) { -+ printk("NAND: Uncorrectable ECC error\n"); -+ return -1; -+ } else { -+ u32 errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT; -+ switch (errcnt) { -+#if defined(CONFIG_MTD_HW_BCH_8BIT) -+ case 8: -+ bch_correct(mtd, dat, (errs[4] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ case 7: -+ bch_correct(mtd, dat, (errs[4] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ case 6: -+ bch_correct(mtd, dat, (errs[3] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ case 5: -+ bch_correct(mtd, dat, (errs[3] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+#endif -+ case 4: -+ bch_correct(mtd, dat, (errs[2] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ case 3: -+ bch_correct(mtd, dat, (errs[2] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ case 2: -+ bch_correct(mtd, dat, (errs[1] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ case 1: -+ bch_correct(mtd, dat, (errs[1] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ default: -+ break; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_NAND_DMA */ -+ -+/** -+ * jzsoc_nand_bch_correct_data_cpu -+ * @mtd: mtd info structure -+ * @dat: data to be corrected -+ * @read_ecc: pointer to ecc buffer calculated when nand writing -+ * @calc_ecc: no used -+ */ -+static int jzsoc_nand_bch_correct_data_cpu(struct mtd_info *mtd, u_char * dat, u_char * read_ecc, u_char * calc_ecc) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ int eccsize = this->ecc.size; -+ int eccbytes = this->ecc.bytes; -+ int eccsteps = this->ecc.steps / this->planenum; -+ int ecc_pos = this->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ short k; -+ u32 stat; -+ -+ /* Write data to REG_BCH_DR */ -+ for (k = 0; k < eccsize; k++) { -+ REG_BCH_DR = ((struct buf_be_corrected *)dat)->data[k]; -+ } -+ /* Write oob to REG_BCH_DR */ -+ for (k = 0; k < oob_per_eccsize; k++) { -+ REG_BCH_DR = ((struct buf_be_corrected *)dat)->oob[k]; -+ } -+ /* Write parities to REG_BCH_DR */ -+ for (k = 0; k < eccbytes; k++) { -+ REG_BCH_DR = read_ecc[k]; -+ } -+ -+ /* Wait for completion */ -+ __ecc_decode_sync(); -+ __ecc_disable(); -+ -+ /* Check decoding */ -+ stat = REG_BCH_INTS; -+ -+ if (stat & BCH_INTS_ERR) { -+ /* Error occurred */ -+ if (stat & BCH_INTS_UNCOR) { -+ printk("NAND: Uncorrectable ECC error--\n"); -+ return -1; -+ } else { -+ u32 errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT; -+ switch (errcnt) { -+#if defined(CONFIG_MTD_HW_BCH_8BIT) -+ case 8: -+ bch_correct(mtd, dat, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ /* FALL-THROUGH */ -+ case 7: -+ bch_correct(mtd, dat, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ /* FALL-THROUGH */ -+ case 6: -+ bch_correct(mtd, dat, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ /* FALL-THROUGH */ -+ case 5: -+ bch_correct(mtd, dat, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ /* FALL-THROUGH */ -+#endif -+ case 4: -+ bch_correct(mtd, dat, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ /* FALL-THROUGH */ -+ case 3: -+ bch_correct(mtd, dat, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ /* FALL-THROUGH */ -+ case 2: -+ bch_correct(mtd, dat, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -+ /* FALL-THROUGH */ -+ case 1: -+ bch_correct(mtd, dat, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -+ return 0; -+ default: -+ break; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+ -+static int jzsoc_nand_calculate_bch_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) -+{ -+ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -+ int eccsize = this->ecc.size; -+ int eccbytes = this->ecc.bytes; -+ int eccsteps = this->ecc.steps / this->planenum; -+ int ecc_pos = this->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ volatile u8 *paraddr = (volatile u8 *)BCH_PAR0; -+ short i; -+ -+ /* Write data to REG_BCH_DR */ -+ for (i = 0; i < eccsize; i++) { -+ REG_BCH_DR = ((struct buf_be_corrected *)dat)->data[i]; -+ } -+ /* Write oob to REG_BCH_DR */ -+ for (i = 0; i < oob_per_eccsize; i++) { -+ REG_BCH_DR = ((struct buf_be_corrected *)dat)->oob[i]; -+ } -+ __ecc_encode_sync(); -+ __ecc_disable(); -+ -+ for (i = 0; i < eccbytes; i++) { -+ ecc_code[i] = *paraddr++; -+ } -+ -+ return 0; -+} -+ -+#if defined(CONFIG_MTD_NAND_DMA) -+ -+/** -+ * nand_write_page_hwecc_bch - [REPLACABLE] hardware ecc based page write function -+ * @mtd: mtd info structure -+ * @chip: nand chip info structure -+ * @buf: data buffer -+ */ -+static void nand_write_page_hwecc_bch0(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, u8 cmd_pgprog) -+{ -+ int eccsize = chip->ecc.size; -+ int eccsteps = chip->ecc.steps / chip->planenum; -+ int eccbytes = chip->ecc.bytes; -+ int ecc_pos = chip->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ int pagesize = mtd->writesize / chip->planenum; -+ int oobsize = mtd->oobsize / chip->planenum; -+ int i, err, timeout; -+ const u8 *databuf; -+ u8 *oobbuf; -+ jz_dma_desc_8word *desc; -+ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ memcpy(prog_buf, buf, pagesize); -+ memcpy(prog_buf + pagesize, chip->oob_poi, oobsize); -+ dma_cache_wback_inv((u32)prog_buf, pagesize + oobsize); -+#else -+ databuf = buf; -+ oobbuf = chip->oob_poi; -+ -+ /* descriptors for encoding data blocks */ -+ desc = dma_desc_enc; -+ for (i = 0; i < eccsteps; i++) { -+ desc->dsadr = CPHYSADDR((u32)databuf) + i * eccsize; /* DMA source address */ -+ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -+ dprintk("dma_desc_enc:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ /* descriptors for encoding oob blocks */ -+ desc = dma_desc_enc1; -+ for (i = 0; i < eccsteps; i++) { -+ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address, 28/4 = 7bytes */ -+ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -+ dprintk("dma_desc_enc1:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ /* descriptor for nand programing data block */ -+ desc = dma_desc_nand_prog; -+ desc->dsadr = CPHYSADDR((u32)databuf); /* DMA source address */ -+ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_W); /* It will be changed when using multiply chip select */ -+ dprintk("dma_desc_nand_prog:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ -+ /* descriptor for nand programing oob block */ -+ desc++; -+ desc->dsadr = CPHYSADDR((u32)oobbuf); /* DMA source address */ -+ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_W); /* It will be changed when using multiply chip select */ -+ dprintk("dma_desc_oob_prog:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ -+ /* descriptor for __nand_cmd(CMD_PGPROG) */ -+ desc++; -+ *pval_nand_cmd_pgprog = cmd_pgprog; -+ desc->dsadr = CPHYSADDR((u32)pval_nand_cmd_pgprog); -+ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_R | cmd_offset); /* DMA target address: cmdport */ -+ if (cmd_pgprog == 0x10) -+ desc->dcmd |= DMAC_DCMD_LINK; /* __nand_sync() by a DMA descriptor */ -+ else if (cmd_pgprog == 0x11) -+ desc->dcmd &= ~DMAC_DCMD_LINK; /* __nand_sync() by polling */ -+ -+ dma_cache_wback_inv((u32)dma_desc_enc, (eccsteps * 2 + 2 + 1) * (sizeof(jz_dma_desc_8word))); -+ dma_cache_wback_inv((u32)databuf, pagesize); -+ dma_cache_wback_inv((u32)oobbuf, oobsize); -+ /* 4*6: pval_nand_ddr, pval_nand_dcs, pval_bch_ddr, pval_bch_dcs, dummy, pval_nand_cmd_pgprog */ -+ dma_cache_wback_inv((u32)pval_nand_ddr, 4 * 8); /* 8 words, a cache line */ -+#endif -+ -+ REG_DMAC_DCCSR(bch_dma_chan) = 0; -+ REG_DMAC_DCCSR(nand_dma_chan) = 0; -+ -+ /* Setup DMA descriptor address */ -+ REG_DMAC_DDA(bch_dma_chan) = CPHYSADDR((u32)dma_desc_enc); -+ REG_DMAC_DDA(nand_dma_chan) = CPHYSADDR((u32)dma_desc_nand_prog); -+ -+ /* Setup request source */ -+ REG_DMAC_DRSR(bch_dma_chan) = DMAC_DRSR_RS_BCH_ENC; -+ REG_DMAC_DRSR(nand_dma_chan) = DMAC_DRSR_RS_AUTO; -+ -+ /* Setup DMA channel control/status register */ -+ REG_DMAC_DCCSR(bch_dma_chan) = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -+ -+ /* Enable DMA */ -+ REG_DMAC_DMACR(0) |= DMAC_DMACR_DMAE; -+ REG_DMAC_DMACR(nand_dma_chan/HALF_DMA_NUM) |= DMAC_DMACR_DMAE; -+ -+ /* Enable BCH encoding */ -+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ -+ dma_ack1 = 0; -+ nand_status = NAND_PROG; -+ -+ /* DMA doorbell set -- start DMA now ... */ -+ __dmac_channel_set_doorbell(bch_dma_chan); -+ -+#if USE_IRQ -+ if (cmd_pgprog == 0x10) { -+ dprintk("nand prog before wake up\n"); -+ err = wait_event_interruptible_timeout(nand_prog_wait_queue, dma_ack1, 3 * HZ); -+ nand_status = NAND_NONE; -+ dprintk("nand prog after wake up\n"); -+ if (!err) { -+ printk("*** NAND WRITE, Warning, wait event 3s timeout!\n"); -+ dump_jz_dma_channel(0); -+ dump_jz_dma_channel(nand_dma_chan); -+ printk("REG_BCH_CR=%x REG_BCH_CNT=0x%x REG_BCH_INTS=%x\n", REG_BCH_CR, REG_BCH_CNT, REG_BCH_INTS); -+ } -+ dprintk("timeout remain = %d\n", err); -+ } else if (cmd_pgprog == 0x11) { -+ timeout = 100000; -+ while ((!__dmac_channel_transmit_end_detected(nand_dma_chan)) && (timeout--)); -+ if (timeout <= 0) -+ printk("two-plane prog 0x11 timeout!\n"); -+ } -+#else -+ timeout = 100000; -+ while ((!__dmac_channel_transmit_end_detected(nand_dma_chan)) && (timeout--)); -+ while(!chip->dev_ready(mtd)); -+ if (timeout <= 0) -+ printk("not use irq, prog timeout!\n"); -+#endif -+} -+ -+static void nand_write_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf) -+{ -+ nand_write_page_hwecc_bch0(mtd, chip, buf, 0x10); -+} -+ -+static void nand_write_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf) -+{ -+ int page; -+ int pagesize = mtd->writesize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x80, 0x00, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ nand_write_page_hwecc_bch0(mtd, chip, buf, 0x11); -+ chip->cmdfunc(mtd, 0x81, 0x00, page + ppb); -+ nand_write_page_hwecc_bch0(mtd, chip, buf + pagesize, 0x10); -+} -+ -+#endif /* CONFIG_MTD_NAND_DMA */ -+ -+static void nand_write_page_hwecc_bch_cpu(struct mtd_info *mtd, struct nand_chip *chip, -+ const uint8_t *buf) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccbytes = chip->ecc.bytes; -+ int eccsteps = chip->ecc.steps / chip->planenum; -+ int oob_per_eccsize = chip->ecc.layout->eccpos[0] / eccsteps; -+ int oobsize = mtd->oobsize / chip->planenum; -+ int ecctotal = chip->ecc.total / chip->planenum; -+ uint8_t *p = (uint8_t *)buf; -+ uint8_t *ecc_calc = chip->buffers->ecccalc; -+ uint32_t *eccpos = chip->ecc.layout->eccpos; -+ static struct buf_be_corrected buf_calc0; -+ struct buf_be_corrected *buf_calc = &buf_calc0; -+ -+ for (i = 0; i < eccsteps; i++, p += eccsize) { -+ buf_calc->data = (u8 *)buf + eccsize * i; -+ buf_calc->oob = chip->oob_poi + oob_per_eccsize * i; -+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ chip->ecc.calculate(mtd, (u8 *)buf_calc, &ecc_calc[eccbytes*i]); -+ chip->write_buf(mtd, p, eccsize); -+ } -+ -+ for (i = 0; i < ecctotal; i++) -+ chip->oob_poi[eccpos[i]] = ecc_calc[i]; -+ -+ chip->write_buf(mtd, chip->oob_poi, oobsize); -+} -+ -+/* nand write using two-plane mode with cpu mode */ -+static void nand_write_page_hwecc_bch_planes_cpu(struct mtd_info *mtd, struct nand_chip *chip, -+ const uint8_t *buf) -+{ -+ int pagesize = mtd->writesize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ int page; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x80, 0x00, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ nand_write_page_hwecc_bch_cpu(mtd, chip, buf); -+ -+ chip->cmdfunc(mtd, 0x11, -1, -1); /* send cmd 0x11 */ -+ ndelay(100); -+ while(!chip->dev_ready(mtd)); -+ -+ chip->cmdfunc(mtd, 0x81, 0x00, page + ppb); /* send cmd 0x81 */ -+ nand_write_page_hwecc_bch_cpu(mtd, chip, buf + pagesize); -+} -+ -+/** -+ * nand_read_page_hwecc_bch - [REPLACABLE] hardware ecc based page read function -+ * @mtd: mtd info structure -+ * @chip: nand chip info structure -+ * @buf: buffer to store read data -+ * -+ * Not for syndrome calculating ecc controllers which need a special oob layout -+ */ -+#if defined(CONFIG_MTD_NAND_DMA) -+static int nand_read_page_hwecc_bch0(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, u32 page) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccsteps = chip->ecc.steps / chip->planenum; -+ int eccbytes = chip->ecc.bytes; -+ int ecc_pos = chip->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ int pagesize = mtd->writesize / chip->planenum; -+ int oobsize = mtd->oobsize / chip->planenum; -+ u8 *databuf, *oobbuf; -+ jz_dma_desc_8word *desc; -+ int err; -+ u32 addrport, cmdport; -+ static struct buf_be_corrected buf_correct0; -+ -+ addrport = (u32)(chip->IO_ADDR_R) | addr_offset; -+ cmdport = (u32)(chip->IO_ADDR_R) | cmd_offset; -+ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ databuf = read_buf; -+ oobbuf = read_buf + pagesize; -+ -+ dma_cache_inv((u32)read_buf, pagesize + oobsize); // databuf should be invalidated. -+ memset(errs, 0, eccsteps * ERRS_SIZE * 4); -+ dma_cache_wback_inv((u32)errs, eccsteps * ERRS_SIZE * 4); -+#else -+ -+ databuf = buf; -+ oobbuf = chip->oob_poi; -+ -+ /* descriptor for nand reading data block */ -+ desc = dma_desc_nand_read; -+ desc->dsadr = CPHYSADDR((u32)chip->IO_ADDR_R); /* It will be changed when using multiply chip select */ -+ desc->dtadr = CPHYSADDR((u32)databuf); /* DMA target address */ -+ -+ dprintk("desc_nand_read:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ -+ /* descriptor for nand reading oob block */ -+ desc++; -+ desc->dsadr = CPHYSADDR((u32)chip->IO_ADDR_R); /* It will be changed when using multiply chip select */ -+ desc->dtadr = CPHYSADDR((u32)oobbuf); /* DMA target address */ -+ dprintk("desc_oob_read:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ -+ /* descriptors for data to be written to bch */ -+ desc = dma_desc_dec; -+ for (i = 0; i < eccsteps; i++) { -+ desc->dsadr = CPHYSADDR((u32)databuf) + i * eccsize; /* DMA source address */ -+ dprintk("dma_desc_dec:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ /* descriptors for oob to be written to bch */ -+ desc = dma_desc_dec1; -+ for (i = 0; i < eccsteps; i++) { -+ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address */ -+ dprintk("dma_desc_dec1:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ /* descriptors for parities to be written to bch */ -+ desc = dma_desc_dec2; -+ for (i = 0; i < eccsteps; i++) { -+ desc->dsadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA source address */ -+ dprintk("dma_desc_dec2:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ dma_cache_wback_inv((u32)dma_desc_nand_read, (2 + eccsteps * 3) * (sizeof(jz_dma_desc_8word))); -+ -+ memset(errs, 0, eccsteps * ERRS_SIZE * 4); -+ dma_cache_inv((u32)databuf, pagesize); // databuf should be invalidated. -+ dma_cache_inv((u32)oobbuf, oobsize); // oobbuf should be invalidated too -+ dma_cache_wback_inv((u32)errs, eccsteps * ERRS_SIZE * 4); -+#endif -+ REG_DMAC_DCCSR(bch_dma_chan) = 0; -+ REG_DMAC_DCCSR(nand_dma_chan) = 0; -+ -+ /* Setup DMA descriptor address */ -+ REG_DMAC_DDA(nand_dma_chan) = CPHYSADDR((u32)dma_desc_nand_read); -+ REG_DMAC_DDA(bch_dma_chan) = CPHYSADDR((u32)dma_desc_dec); -+ -+ /* Setup request source */ -+ REG_DMAC_DRSR(nand_dma_chan) = DMAC_DRSR_RS_NAND; -+ REG_DMAC_DRSR(bch_dma_chan) = DMAC_DRSR_RS_BCH_DEC; -+ -+ /* Enable DMA */ -+ REG_DMAC_DMACR(0) |= DMAC_DMACR_DMAE; -+ REG_DMAC_DMACR(nand_dma_chan/HALF_DMA_NUM) |= DMAC_DMACR_DMAE; -+ -+ /* Enable BCH decoding */ -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ -+ dma_ack = 0; -+ nand_status = NAND_READ; -+ /* DMA doorbell set -- start nand DMA now ... */ -+ __dmac_channel_set_doorbell(nand_dma_chan); -+ -+ /* Setup DMA channel control/status register */ -+ REG_DMAC_DCCSR(nand_dma_chan) = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; -+ -+#define __nand_cmd(n) (REG8(cmdport) = (n)) -+#define __nand_addr(n) (REG8(addrport) = (n)) -+ -+ __nand_cmd(NAND_CMD_READ0); -+ -+ __nand_addr(0); -+ if (pagesize != 512) -+ __nand_addr(0); -+ -+ __nand_addr(page & 0xff); -+ __nand_addr((page >> 8) & 0xff); -+ -+ /* One more address cycle for the devices whose number of page address bits > 16 */ -+ if (((chip->chipsize >> chip->page_shift) >> 16) - 1 > 0) -+ __nand_addr((page >> 16) & 0xff); -+ -+ if (pagesize != 512) -+ __nand_cmd(NAND_CMD_READSTART); -+ -+#if USE_IRQ -+ do { -+ err = wait_event_interruptible_timeout(nand_read_wait_queue, dma_ack, 3 * HZ); -+ }while(err == -ERESTARTSYS); -+ nand_status = NAND_NONE; -+ -+ if (!err) { -+ printk("*** NAND READ, Warning, wait event 3s timeout!\n"); -+ dump_jz_dma_channel(0); -+ dump_jz_dma_channel(nand_dma_chan); -+ printk("REG_BCH_CR=%x REG_BCH_CNT=0x%x REG_BCH_INTS=%x\n", REG_BCH_CR, REG_BCH_CNT, REG_BCH_INTS); -+ printk("databuf[0]=%x\n", databuf[0]); -+ } -+ dprintk("timeout remain = %d\n", err); -+#else -+ int timeout; -+ timeout = 100000; -+ while ((!__dmac_channel_transmit_end_detected(bch_dma_chan)) && (timeout--)); -+ if (timeout <= 0) { -+ printk("not use irq, NAND READ timeout!\n"); -+ } -+#endif -+ -+ for (i = 0; i < eccsteps; i++) { -+ int stat; -+ struct buf_be_corrected *buf_correct = &buf_correct0; -+ -+ buf_correct->data = databuf + eccsize * i; -+ buf_correct->oob = oobbuf + oob_per_eccsize * i; -+ -+ stat = chip->ecc.correct(mtd, (u8 *)buf_correct, (u8 *)&errs[i * ERRS_SIZE], NULL); -+ if (stat < 0) -+ mtd->ecc_stats.failed++; -+ else -+ mtd->ecc_stats.corrected += stat; -+ } -+ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ memcpy(buf, read_buf, pagesize); -+ memcpy(chip->oob_poi, read_buf + pagesize, oobsize); -+#endif -+ return 0; -+} -+ -+static int nand_read_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -+{ -+ u32 page = global_page; -+ -+ nand_read_page_hwecc_bch0(mtd, chip, buf, page); -+ return 0; -+} -+ -+static int nand_read_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -+{ -+ u32 page; -+ int pagesize = mtd->writesize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* read 1st page */ -+ nand_read_page_hwecc_bch0(mtd, chip, buf, page); -+ -+ /* read 2nd page */ -+ nand_read_page_hwecc_bch0(mtd, chip, buf + pagesize, page + ppb); -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_NAND_DMA */ -+ -+static int nand_read_page_hwecc_bch_cpu(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccbytes = chip->ecc.bytes; -+ int eccsteps = chip->ecc.steps / chip->planenum; -+ int ecc_pos = chip->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ uint8_t *ecc_calc = chip->buffers->ecccalc; -+ uint8_t *ecc_code = chip->buffers->ecccode; -+ uint32_t *eccpos = chip->ecc.layout->eccpos; -+ int pagesize = mtd->writesize / chip->planenum; -+ int oobsize = mtd->oobsize / chip->planenum; -+ int ecctotal = chip->ecc.total / chip->planenum; -+ static struct buf_be_corrected buf_correct0; -+ -+ chip->read_buf(mtd, buf, pagesize); -+ chip->read_buf(mtd, chip->oob_poi, oobsize); -+ -+ for (i = 0; i < ecctotal; i++) { -+ ecc_code[i] = chip->oob_poi[eccpos[i]]; -+ } -+ -+ for (i = 0; i < eccsteps; i++) { -+ int stat; -+ struct buf_be_corrected *buf_correct = &buf_correct0; -+ -+ buf_correct->data = buf + eccsize * i; -+ buf_correct->oob = chip->oob_poi + oob_per_eccsize * i; -+ -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ stat = chip->ecc.correct(mtd, (u8 *)buf_correct, &ecc_code[eccbytes*i], &ecc_calc[eccbytes*i]); -+ if (stat < 0) -+ mtd->ecc_stats.failed++; -+ else -+ mtd->ecc_stats.corrected += stat; -+ } -+ -+ return 0; -+} -+ -+static int nand_read_page_hwecc_bch_planes_cpu(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -+{ -+ int pagesize = mtd->writesize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ uint32_t page; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* Read first page */ -+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); -+ nand_read_page_hwecc_bch_cpu(mtd, chip, buf); -+ -+ /* Read 2nd page */ -+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page + ppb); -+ nand_read_page_hwecc_bch_cpu(mtd, chip, buf+pagesize); -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_HW_BCH_ECC */ -+ -+/* read oob using two-plane mode */ -+static int nand_read_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -+ int global_page, int sndcmd) -+{ -+ int page; -+ int oobsize = mtd->oobsize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* Read first page OOB */ -+ if (sndcmd) { -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ } -+ chip->read_buf(mtd, chip->oob_poi, oobsize); -+ /* Read second page OOB */ -+ page += ppb; -+ if (sndcmd) { -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ sndcmd = 0; -+ } -+ chip->read_buf(mtd, chip->oob_poi+oobsize, oobsize); -+ return 0; -+} -+ -+/* write oob using two-plane mode */ -+static int nand_write_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -+ int global_page) -+{ -+ int status = 0, page; -+ const uint8_t *buf = chip->oob_poi; -+ int pagesize = mtd->writesize >> 1; -+ int oobsize = mtd->oobsize >> 1; -+ int ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x80, pagesize, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x80, pagesize, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ chip->write_buf(mtd, buf, oobsize); -+ /* Send first command to program the OOB data */ -+ chip->cmdfunc(mtd, 0x11, -1, -1); -+ ndelay(100); -+ status = chip->waitfunc(mtd, chip); -+ -+ page += ppb; -+ buf += oobsize; -+ chip->cmdfunc(mtd, 0x81, pagesize, page); -+ chip->write_buf(mtd, buf, oobsize); -+ /* Send command to program the OOB data */ -+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+ /* Wait long R/B */ -+ ndelay(100); -+ status = chip->waitfunc(mtd, chip); -+ -+ return status & NAND_STATUS_FAIL ? -EIO : 0; -+} -+ -+/* nand erase using two-plane mode */ -+static void single_erase_cmd_planes(struct mtd_info *mtd, int global_page) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int page, ppb = mtd->erasesize / mtd->writesize; -+ -+ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -+ -+ /* send cmd 0x60, the MSB should be valid if realplane is 4 */ -+ if (chip->realplanenum == 2) -+ chip->cmdfunc(mtd, 0x60, -1, 0x00); -+ else -+ chip->cmdfunc(mtd, 0x60, -1, page & (1 << (chip->chip_shift - chip->page_shift))); -+ -+ page += ppb; -+ chip->cmdfunc(mtd, 0x60, -1, page & (~(ppb-1))); /* send cmd 0x60 */ -+ -+ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); /* send cmd 0xd0 */ -+ /* Do not need wait R/B or check status */ -+} -+ -+#if defined(CONFIG_MTD_NAND_DMA) -+ -+#if USE_IRQ -+static irqreturn_t nand_dma_irq(int irq, void *dev_id) -+{ -+ u8 dma_chan; -+ volatile int wakeup = 0; -+ -+ dma_chan = irq - IRQ_DMA_0; -+ -+ dprintk("jz4750_dma_irq %d, channel %d\n", irq, dma_chan); -+ -+ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -+ __dmac_channel_clear_transmit_halt(dma_chan); -+ wakeup = 1; -+ printk("DMA HALT\n"); -+ } -+ -+ if (__dmac_channel_address_error_detected(dma_chan)) { -+ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ __dmac_channel_clear_address_error(dma_chan); -+ -+ REG_DMAC_DSAR(dma_chan) = 0; /* reset source address register */ -+ REG_DMAC_DTAR(dma_chan) = 0; /* reset destination address register */ -+ -+ /* clear address error in DMACR */ -+ REG_DMAC_DMACR((dma_chan / HALF_DMA_NUM)) &= ~(1 << 2); -+ wakeup = 1; -+ printk("DMA address error!\n"); -+ } -+ -+ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -+ __dmac_channel_clear_descriptor_invalid(dma_chan); -+ wakeup = 1; -+ printk("DMA DESC INVALID\n"); -+ } -+#if 1 -+ -+ while (!__dmac_channel_transmit_end_detected(dma_chan)); -+ -+ if (__dmac_channel_count_terminated_detected(dma_chan)) { -+ dprintk("DMA CT\n"); -+ __dmac_channel_clear_count_terminated(dma_chan); -+ wakeup = 0; -+ } -+#endif -+ -+ if (__dmac_channel_transmit_end_detected(dma_chan)) { -+ dprintk("DMA TT\n"); -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ __dmac_channel_clear_transmit_end(dma_chan); -+ wakeup = 1; -+ } -+ -+ if (wakeup) { -+ dprintk("ack %d irq , wake up dma_chan %d nand_status %d\n", dma_ack, dma_chan, nand_status); -+ /* wakeup wait event */ -+ if ((dma_chan == nand_dma_chan) && (nand_status == NAND_PROG)) { -+ dprintk("nand prog dma irq, wake up----\n"); -+ dma_ack1 = 1; -+ wake_up_interruptible(&nand_prog_wait_queue); -+ } -+ -+ if ((dma_chan == bch_dma_chan) && (nand_status == NAND_READ)) { -+ dprintk("nand read irq, wake up----\n"); -+ dma_ack = 1; -+ wake_up_interruptible(&nand_read_wait_queue); -+ } -+ wakeup = 0; -+ } -+ -+ return IRQ_HANDLED; -+} -+#endif /* USE_IRQ */ -+ -+static int jz4750_nand_dma_init(struct mtd_info *mtd) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int eccsize = chip->ecc.size; -+ int eccsteps = chip->ecc.steps / chip->planenum; -+ int eccbytes = chip->ecc.bytes; -+ int ecc_pos = chip->ecc.layout->eccpos[0]; -+ int oob_per_eccsize = ecc_pos / eccsteps; -+ int pagesize = mtd->writesize / chip->planenum; -+ int oobsize = mtd->oobsize / chip->planenum; -+ int i, err; -+ jz_dma_desc_8word *desc, *dma_desc_bch_ddr, *dma_desc_nand_ddr, *dma_desc_nand_cmd_pgprog; -+ u32 *pval_nand_dcs, *pval_bch_ddr, *pval_bch_dcs, *dummy; -+ u32 next; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ u8 *oobbuf; -+#endif -+ -+#if USE_IRQ -+ if ((nand_dma_chan = jz_request_dma(DMA_ID_NAND, "nand read or write", nand_dma_irq, IRQF_DISABLED, NULL)) < 0) { -+ printk("can't reqeust DMA nand channel.\n"); -+ return 0; -+ } -+ dprintk("nand dma channel:%d----\n", nand_dma_chan); -+ -+ if ((err = request_irq(IRQ_DMA_0 + bch_dma_chan, nand_dma_irq, IRQF_DISABLED, "bch_dma", NULL))) { -+ printk("bch_dma irq request err\n"); -+ return 0; -+ } -+#else -+ if ((nand_dma_chan = jz_request_dma(DMA_ID_NAND, "nand read or write", NULL, IRQF_DISABLED, NULL)) < 0) { -+ printk("can't reqeust DMA nand channel.\n"); -+ return 0; -+ } -+ dprintk("nand dma channel:%d----\n", nand_dma_chan); -+#endif -+ -+ __dmac_channel_enable_clk(nand_dma_chan); -+ __dmac_channel_enable_clk(bch_dma_chan); -+ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ if (pagesize < 4096) { -+ read_buf = prog_buf = (u8 *) __get_free_page(GFP_KERNEL); -+ } else { -+ read_buf = prog_buf = (u8 *) __get_free_pages(GFP_KERNEL, 1); -+ } -+ if (!read_buf) -+ return -ENOMEM; -+#endif -+ /* space for the error reports of bch decoding((4 * 5 * eccsteps) bytes), and the space for the value -+ * of ddr and dcs of channel 0 and channel nand_dma_chan (4 * (2 + 2) bytes) */ -+ errs = (u32 *)kmalloc(4 * (2 + 2 + 5 * eccsteps), GFP_KERNEL); -+ if (!errs) -+ return -ENOMEM; -+ -+ pval_nand_ddr = errs + 5 * eccsteps; -+ pval_nand_dcs = pval_nand_ddr + 1; -+ pval_bch_ddr = pval_nand_dcs + 1; -+ pval_bch_dcs = pval_bch_ddr + 1; -+ /* space for nand prog waiting target, the content is useless */ -+ dummy = pval_bch_dcs + 1; -+ /* space to store CMD_PGPROG(0x10) or 0x11 */ -+ pval_nand_cmd_pgprog = (u8 *)(dummy + 1); -+ -+ /* desc can't across 4KB boundary, as desc base address is fixed */ -+ /* space of descriptors for nand reading data and oob blocks */ -+ dma_desc_nand_read = (jz_dma_desc_8word *) __get_free_page(GFP_KERNEL); -+ if (!dma_desc_nand_read) -+ return -ENOMEM; -+ -+ /* space of descriptors for bch decoding */ -+ dma_desc_dec = dma_desc_nand_read + 2; -+ dma_desc_dec1 = dma_desc_dec + eccsteps; -+ dma_desc_dec2 = dma_desc_dec + eccsteps * 2; -+ -+ /* space of descriptors for notifying bch channel */ -+ dma_desc_bch_ddr = dma_desc_dec2 + eccsteps; -+ -+ /* space of descriptors for bch encoding */ -+ dma_desc_enc = dma_desc_bch_ddr + 2; -+ dma_desc_enc1 = dma_desc_enc + eccsteps; -+ -+ /* space of descriptors for nand programing data and oob blocks */ -+ dma_desc_nand_prog = dma_desc_enc1 + eccsteps; -+ -+ /* space of descriptors for nand prog waiting, including pgprog and sync */ -+ dma_desc_nand_cmd_pgprog = dma_desc_nand_prog + 2; -+ -+ /* space of descriptors for notifying nand channel, including ddr and dcsr */ -+ dma_desc_nand_ddr = dma_desc_nand_cmd_pgprog + 2; -+ -+/************************************* -+ * Setup of nand programing descriptors -+ *************************************/ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ oobbuf = prog_buf + pagesize; -+#endif -+ /* set descriptor for encoding data blocks */ -+ desc = dma_desc_enc; -+ for (i = 0; i < eccsteps; i++) { -+ next = (CPHYSADDR((u32)dma_desc_enc1) + i * (sizeof(jz_dma_desc_8word))) >> 4; -+ -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | -+ DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)prog_buf) + i * eccsize; /* DMA source address */ -+ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -+#endif -+ desc->ddadr = (next << 24) + eccsize / DIV_DS_BCH; /* size: eccsize bytes */ -+ desc->dreqt = DMAC_DRSR_RS_BCH_ENC; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ desc++; -+ } -+ -+ /* set descriptor for encoding oob blocks */ -+ desc = dma_desc_enc1; -+ for (i = 0; i < eccsteps; i++) { -+ next = (CPHYSADDR((u32)dma_desc_enc) + (i + 1) * (sizeof(jz_dma_desc_8word))) >> 4; -+ -+ desc->dcmd = -+ DMAC_DCMD_BLAST | DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | -+ DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address, 28/4 = 7bytes */ -+ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -+#endif -+ desc->ddadr = (next << 24) + (oob_per_eccsize + 3) / 4; /* size: 7 bytes -> 2 words */ -+ desc->dreqt = DMAC_DRSR_RS_BCH_ENC; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ desc++; -+ } -+ -+ next = (CPHYSADDR((u32)dma_desc_nand_ddr)) >> 4; -+ desc--; -+ desc->ddadr = (next << 24) + (oob_per_eccsize + 3) / 4; -+ -+ /* set the descriptor to set door bell of nand_dma_chan for programing nand */ -+ desc = dma_desc_nand_ddr; -+ *pval_nand_ddr = 1 << (nand_dma_chan - nand_dma_chan / HALF_DMA_NUM * HALF_DMA_NUM); -+ next = (CPHYSADDR((u32)dma_desc_nand_ddr) + sizeof(jz_dma_desc_8word)) >> 4; -+ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -+ desc->dsadr = CPHYSADDR((u32)pval_nand_ddr); /* DMA source address */ -+ desc->dtadr = CPHYSADDR(DMAC_DMADBSR(nand_dma_chan / HALF_DMA_NUM)); /* nand_dma_chan's descriptor addres register */ -+ desc->ddadr = (next << 24) + 1; /* size: 1 word */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ dprintk("*pval_nand_ddr=0x%x\n", *pval_nand_ddr); -+ -+ /* set the descriptor to write dccsr of nand_dma_chan for programing nand, dccsr should be set at last */ -+ desc++; -+ *pval_nand_dcs = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; /* set value for writing ddr to enable channel nand_dma_chan */ -+ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -+ desc->dsadr = CPHYSADDR((u32)pval_nand_dcs); /* DMA source address */ -+ desc->dtadr = CPHYSADDR(DMAC_DCCSR(nand_dma_chan)); /* address of dma door bell set register */ -+ desc->ddadr = (0 << 24) + 1; /* size: 1 word */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ dprintk("*pval_nand_dcs=0x%x\n", *pval_nand_dcs); -+ -+ /* set descriptor for nand programing data block */ -+ desc = dma_desc_nand_prog; -+ next = (CPHYSADDR((u32)dma_desc_nand_prog) + sizeof(jz_dma_desc_8word)) >> 4; -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | -+ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)prog_buf); /* DMA source address */ -+#endif -+ desc->dtadr = CPHYSADDR((u32)(chip->IO_ADDR_W)); /* DMA target address */ -+ desc->ddadr = (next << 24) + pagesize / DIV_DS_NAND; /* size: eccsize bytes */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ -+ /* set descriptor for nand programing oob block */ -+ desc++; -+ next = (CPHYSADDR((u32)dma_desc_nand_cmd_pgprog)) >> 4; -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | -+ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)oobbuf); /* DMA source address */ -+#endif -+ desc->dtadr = CPHYSADDR((u32)(chip->IO_ADDR_W)); /* DMA target address: dataport */ -+ desc->ddadr = (next << 24) + oobsize / DIV_DS_NAND; /* size: eccsize bytes */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ -+ /* set descriptor for __nand_cmd(CMD_PGPROG) */ -+ desc = dma_desc_nand_cmd_pgprog; -+ *pval_nand_cmd_pgprog = NAND_CMD_PAGEPROG; -+ next = (CPHYSADDR((u32)dma_desc_nand_cmd_pgprog) + sizeof(jz_dma_desc_8word)) >> 4; -+ desc->dcmd = -+ DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_8BIT | DMAC_DCMD_LINK; -+ desc->dsadr = CPHYSADDR((u32)pval_nand_cmd_pgprog); /* DMA source address */ -+ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_R | cmd_offset); /* DMA target address: cmdport */ -+ desc->ddadr = (next << 24) + 1; /* size: 1 byte */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ -+ /* set descriptor for __nand_sync() */ -+ desc++; -+#if USE_IRQ -+ desc->dcmd = -+ DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; -+#else -+ desc->dcmd = -+ DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -+#endif -+ desc->dsadr = CPHYSADDR((u32)pval_nand_ddr); /* DMA source address */ -+ desc->dtadr = CPHYSADDR((u32)dummy); /* DMA target address, the content is useless */ -+ desc->ddadr = (0 << 24) + 1; /* size: 1 word */ -+ desc->dreqt = DMAC_DRSR_RS_NAND; -+ dprintk("1cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ -+ /* eccsteps*2 + 2 + 2 + 2: -+ dma_desc_enc + dma_desc_enc1 + dma_desc_nand_prog(oob) + dma_desc_nand_ddr(csr) -+ + dma_desc_nand_cmd_pgprog(sync) */ -+ dma_cache_wback_inv((u32)dma_desc_enc, (eccsteps * 2 + 2 + 2 + 2) * (sizeof(jz_dma_desc_8word))); -+ /* 4*6: pval_nand_ddr, pval_nand_dcs, pval_bch_ddr, pval_bch_dcs, dummy, pval_nand_cmd_pgprog */ -+ dma_cache_wback_inv((u32)pval_nand_ddr, 4 * 8); /* 8 words, a cache line */ -+ -+/************************************* -+ * Setup of nand reading descriptors -+ *************************************/ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ oobbuf = read_buf + pagesize; -+#endif -+ /* set descriptor for nand reading data block */ -+ desc = dma_desc_nand_read; -+ next = (CPHYSADDR((u32)dma_desc_nand_read) + sizeof(jz_dma_desc_8word)) >> 4; -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | -+ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -+ desc->dsadr = CPHYSADDR((u32)(chip->IO_ADDR_R)); /* DMA source address */ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dtadr = CPHYSADDR((u32)read_buf); /* DMA target address */ -+#endif -+ desc->ddadr = (next << 24) + pagesize / DIV_DS_NAND; /* size: eccsize bytes */ -+ desc->dreqt = DMAC_DRSR_RS_NAND; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ -+ /* set descriptor for nand reading oob block */ -+ desc++; -+ next = (CPHYSADDR((u32)dma_desc_bch_ddr)) >> 4; -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | -+ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -+ desc->dsadr = CPHYSADDR((u32)(chip->IO_ADDR_R)); /* DMA source address */ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dtadr = CPHYSADDR((u32)oobbuf); /* DMA target address */ -+#endif -+ desc->ddadr = (next << 24) + oobsize / DIV_DS_NAND; /* size: eccsize bytes */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -+ -+ /* set the descriptor to set door bell for bch */ -+ desc = dma_desc_bch_ddr; -+ *pval_bch_ddr = DMAC_DMADBSR_DBS0; // set value for writing ddr to enable channel 0 -+ next = (CPHYSADDR((u32)dma_desc_bch_ddr) + sizeof(jz_dma_desc_8word)) >> 4; -+ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -+ desc->dsadr = CPHYSADDR((u32)pval_bch_ddr); /* DMA source address */ -+ desc->dtadr = CPHYSADDR(DMAC_DMADBSR(0)); /* channel 1's descriptor addres register */ -+ desc->ddadr = (next << 24) + 1; /* size: 1 word */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ -+ /* set descriptor for writing dcsr */ -+ desc++; -+ *pval_bch_dcs = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; // set value for writing ddr to enable channel 1 -+ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -+ desc->dsadr = CPHYSADDR((u32)pval_bch_dcs); /* DMA source address */ -+ desc->dtadr = CPHYSADDR(DMAC_DCCSR(bch_dma_chan)); /* address of dma door bell set register */ -+ desc->ddadr = (0 << 24) + 1; /* size: 1 word */ -+ desc->dreqt = DMAC_DRSR_RS_AUTO; -+ -+ /* descriptors for data to be written to bch */ -+ desc = dma_desc_dec; -+ for (i = 0; i < eccsteps; i++) { -+ next = CPHYSADDR((u32)dma_desc_dec1 + i * (sizeof(jz_dma_desc_8word))) >> 4; -+ -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | -+ DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)read_buf) + i * eccsize; /* DMA source address */ -+#endif -+ desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ -+ desc->ddadr = (next << 24) + eccsize / DIV_DS_BCH; /* size: eccsize bytes */ -+ desc->dreqt = DMAC_DRSR_RS_BCH_DEC; -+ dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ /* descriptors for oob to be written to bch */ -+ desc = dma_desc_dec1; -+ for (i = 0; i < eccsteps; i++) { -+ next = CPHYSADDR((u32)dma_desc_dec2 + i * (sizeof(jz_dma_desc_8word))) >> 4; -+ -+ desc->dcmd = -+ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address */ -+#endif -+ desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ -+ desc->ddadr = (next << 24) + oob_per_eccsize; /* size: 7 bytes */ -+ desc->dreqt = DMAC_DRSR_RS_BCH_DEC; -+ dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ -+ /* descriptors for parities to be written to bch */ -+ desc = dma_desc_dec2; -+ for (i = 0; i < eccsteps; i++) { -+ next = (CPHYSADDR((u32)dma_desc_dec) + (i + 1) * (sizeof(jz_dma_desc_8word))) >> 4; -+ -+ desc->dcmd = -+ DMAC_DCMD_BLAST | DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | -+ DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ desc->dsadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA source address */ -+#endif -+ desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ -+ desc->ddadr = (next << 24) + (eccbytes + 15) / DIV_DS_BCH; /* size: eccbytes bytes */ -+ desc->dreqt = DMAC_DRSR_RS_BCH_DEC; -+ dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -+ desc->ddadr); -+ desc++; -+ } -+ desc--; -+ desc->dcmd &= ~DMAC_DCMD_LINK; -+#if USE_IRQ -+ desc->dcmd |= DMAC_DCMD_TIE; -+#endif -+ -+ dma_cache_wback_inv((u32)dma_desc_nand_read, (2 + 2 + eccsteps * 3) * (sizeof(jz_dma_desc_8word))); -+ dma_cache_wback_inv((u32)pval_bch_ddr, 4 * 2); /* two words */ -+ -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_NAND_DMA */ -+ -+void copy_to_cpu_mode(struct mtd_info *mtd_cpu, struct mtd_info *mtd_dma, char use_planes) -+{ -+ struct nand_chip *chip_cpu = (struct nand_chip *)(&mtd_cpu[1]); -+ struct nand_chip *chip_dma = (struct nand_chip *)(&mtd_dma[1]); -+ -+ memcpy(mtd_cpu, mtd_dma, sizeof(struct mtd_info)); -+ mtd_cpu->priv = chip_cpu; -+ memcpy(chip_cpu, chip_dma, sizeof(struct nand_chip)); -+ -+ chip_cpu->ecc.correct = jzsoc_nand_bch_correct_data_cpu; -+ -+ if (use_planes) { -+ chip_cpu->ecc.read_page = nand_read_page_hwecc_bch_planes_cpu; -+ chip_cpu->ecc.write_page = nand_write_page_hwecc_bch_planes_cpu; -+ } else { -+ chip_cpu->ecc.read_page = nand_read_page_hwecc_bch_cpu; -+ chip_cpu->ecc.write_page = nand_write_page_hwecc_bch_cpu; -+ } -+ -+ mtd_cpu->flags |= MTD_NAND_CPU_MODE; -+} -+ -+/* -+ * Main initialization routine -+ */ -+int __init jznand_init(void) -+{ -+ struct nand_chip *this; -+ struct mtd_info *jz_mtd_cpu, *jz_mtd_cpu1; /* jz_mtd_cpu for 2 planes, jz_mtd_cpu1 for 1 plane */ -+ int ret, i; -+ -+ printk("JZ NAND init:"); -+#if defined(CONFIG_MTD_NAND_DMA) -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ printk(" DMA mode, using DMA buffer in NAND driver, "); -+#else -+ printk(" DMA mode, using DMA buffer in upper layer, "); -+#endif -+#else -+ printk(KERN_INFO " CPU mode, "); -+#endif -+#if defined(CONFIG_MTD_HW_BCH_8BIT) -+ printk(" 8bit BCH.\n"); -+#else -+ printk(" 4bit BCH.\n"); -+#endif -+ -+ /* Allocate memory for MTD device structure and private data */ -+ jz_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); -+ if (!jz_mtd) { -+ printk("Unable to allocate JzSOC NAND MTD device structure for dma mode using multi-planes.\n"); -+ return -ENOMEM; -+ } -+ -+ jz_mtd1 = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); -+ if (!jz_mtd1) { -+ printk ("Unable to allocate JzSOC NAND MTD device structure for dma mode using 1 plane.\n"); -+ kfree(jz_mtd); -+ return -ENOMEM; -+ } -+ -+ jz_mtd_cpu = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); -+ if (!jz_mtd_cpu) { -+ printk ("Unable to allocate JzSOC NAND MTD device structure for cpu mode using multi-planes.\n"); -+ kfree(jz_mtd); -+ kfree(jz_mtd1); -+ return -ENOMEM; -+ } -+ -+ jz_mtd_cpu1 = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); -+ if (!jz_mtd_cpu) { -+ printk ("Unable to allocate JzSOC NAND MTD device structure for cpu mode using 1 plane.\n"); -+ kfree(jz_mtd); -+ kfree(jz_mtd1); -+ kfree(jz_mtd_cpu); -+ return -ENOMEM; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *)(&jz_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *)jz_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *)this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ jz_mtd->priv = this; -+ -+ if (is_share_mode()) { -+ addr_offset = NAND_ADDR_OFFSET0; -+ cmd_offset = NAND_CMD_OFFSET0; -+ } else { -+ addr_offset = NAND_ADDR_OFFSET1; -+ cmd_offset = NAND_CMD_OFFSET1; -+ } -+ -+ /* Set & initialize NAND Flash controller */ -+ jz_device_setup(); -+ -+ /* Set address of NAND IO lines to static bank1 by default */ -+ this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; -+ this->IO_ADDR_W = (void __iomem *)NAND_DATA_PORT1; -+ this->cmd_ctrl = jz_hwcontrol; -+ this->dev_ready = jz_device_ready; -+ -+#ifdef CONFIG_MTD_HW_BCH_ECC -+ this->ecc.calculate = jzsoc_nand_calculate_bch_ecc; -+ this->ecc.hwctl = jzsoc_nand_enable_bch_hwecc; -+ this->ecc.mode = NAND_ECC_HW; -+ this->ecc.size = 512; -+#if defined(CONFIG_MTD_NAND_DMA) -+ this->ecc.correct = jzsoc_nand_bch_correct_data; -+ this->ecc.read_page = nand_read_page_hwecc_bch; -+ this->ecc.write_page = nand_write_page_hwecc_bch; -+#else -+ this->ecc.correct = jzsoc_nand_bch_correct_data_cpu; -+ this->ecc.read_page = nand_read_page_hwecc_bch_cpu; -+ this->ecc.write_page = nand_write_page_hwecc_bch_cpu; -+#endif -+#if defined(CONFIG_MTD_HW_BCH_8BIT) -+ this->ecc.bytes = 13; -+#else -+ this->ecc.bytes = 7; -+#endif -+#endif -+ -+#ifdef CONFIG_MTD_SW_HM_ECC -+ this->ecc.mode = NAND_ECC_SOFT; -+#endif -+ /* 20 us command delay time */ -+ this->chip_delay = 20; -+ /* Scan to find existance of the device */ -+ ret = nand_scan_ident(jz_mtd, nand_chips); -+ -+ if (!ret) { -+ if (this->planenum == 2) { -+ /* reset nand functions */ -+ this->erase_cmd = single_erase_cmd_planes; -+#if defined(CONFIG_MTD_NAND_DMA) -+ this->ecc.read_page = nand_read_page_hwecc_bch_planes; -+ this->ecc.write_page = nand_write_page_hwecc_bch_planes; -+#else -+ this->ecc.read_page = nand_read_page_hwecc_bch_planes_cpu; -+ this->ecc.write_page = nand_write_page_hwecc_bch_planes_cpu; -+#endif -+ this->ecc.read_oob = nand_read_oob_std_planes; -+ this->ecc.write_oob = nand_write_oob_std_planes; -+ -+ printk(KERN_INFO "Nand using two-plane mode, " -+ "and resized to writesize:%d oobsize:%d blocksize:0x%x \n", -+ jz_mtd->writesize, jz_mtd->oobsize, jz_mtd->erasesize); -+ } -+ } -+ -+ /* Determine whether all the partitions will use multiple planes if supported */ -+ nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); -+ all_use_planes = 1; -+ for (i = 0; i < nr_partitions; i++) { -+ all_use_planes &= partition_info[i].use_planes; -+ } -+ -+ if (!ret) -+ ret = nand_scan_tail(jz_mtd); -+ -+ if (ret){ -+ kfree (jz_mtd1); -+ kfree (jz_mtd); -+ return -ENXIO; -+ } -+ -+#if defined(CONFIG_MTD_NAND_DMA) -+ jz4750_nand_dma_init(jz_mtd); -+ -+ ((struct nand_chip *) (&jz_mtd1[1]))->ecc.read_page = nand_read_page_hwecc_bch; -+ ((struct nand_chip *) (&jz_mtd1[1]))->ecc.write_page = nand_write_page_hwecc_bch; -+#else -+ ((struct nand_chip *) (&jz_mtd1[1]))->ecc.read_page = nand_read_page_hwecc_bch_cpu; -+ ((struct nand_chip *) (&jz_mtd1[1]))->ecc.write_page = nand_write_page_hwecc_bch_cpu; -+#endif -+ -+ copy_to_cpu_mode(jz_mtd_cpu, jz_mtd, 1); -+ copy_to_cpu_mode(jz_mtd_cpu1, jz_mtd1, 0); -+ -+ /* Register the partitions */ -+ printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); -+ -+ if ((this->planenum == 2) && !all_use_planes) { -+ for (i = 0; i < nr_partitions; i++) { -+ if (partition_info[i].use_planes) { -+ if (partition_info[i].cpu_mode) -+ add_mtd_partitions(jz_mtd_cpu, &partition_info[i], 1); -+ else -+ add_mtd_partitions(jz_mtd, &partition_info[i], 1); -+ } else { -+ if (partition_info[i].cpu_mode) -+ add_mtd_partitions(jz_mtd_cpu1, &partition_info[i], 1); -+ else -+ add_mtd_partitions(jz_mtd1, &partition_info[i], 1); -+ } -+ } -+ } else { -+ kfree(jz_mtd1); -+ kfree(jz_mtd_cpu1); -+ for (i = 0; i < nr_partitions; i++) { -+ if (partition_info[i].cpu_mode) -+ add_mtd_partitions(jz_mtd_cpu, &partition_info[i], 1); -+ else -+ add_mtd_partitions(jz_mtd, &partition_info[i], 1); -+ } -+ } -+ return 0; -+} -+ -+module_init(jznand_init); -+ -+/* -+ * Clean up routine -+ */ -+#ifdef MODULE -+ -+#if defined(CONFIG_MTD_NAND_DMA) -+static int jz4750_nand_dma_exit(struct mtd_info *mtd) -+{ -+ int pagesize = mtd->writesize / chip->planenum; -+ -+#if USE_IRQ -+ free_irq(IRQ_DMA_0 + nand_dma_chan, NULL); -+ free_irq(IRQ_DMA_0 + bch_dma_chan, NULL); -+#endif -+ -+ /* space for the error reports of bch decoding((4 * 5 * eccsteps) bytes), -+ * and the space for the value of ddr and dcs of channel 0 and channel -+ * nand_dma_chan (4 * (2 + 2) bytes) */ -+ kfree(errs); -+ -+ /* space for dma_desc_nand_read contains dma_desc_nand_prog, -+ * dma_desc_enc and dma_desc_dec */ -+ free_page((u32)dma_desc_nand_read); -+ -+#if defined(CONFIG_MTD_NAND_DMABUF) -+ if (pagesize < 4096) { -+ free_page((u32)prog_buf); -+ } else { -+ free_pages((u32)prog_buf, 1); -+ } -+#endif -+ -+ return 0; -+} -+#endif -+ -+static void __exit jznand_cleanup(void) -+{ -+#if defined(CONFIG_MTD_NAND_DMA) -+ jz4750_nand_dma_exit(jz_mtd); -+#endif -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(jz_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device(jz_mtd); -+ -+ /* Free the MTD device structure */ -+ if ((this->planenum == 2) && !all_use_planes) -+ kfree (jz_mtd1); -+ kfree(jz_mtd); -+} -+ -+module_exit(jznand_cleanup); -+#endif -diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c -index 8c21b89..fbbcfdb 100644 ---- a/drivers/mtd/nand/nand_base.c -+++ b/drivers/mtd/nand/nand_base.c -@@ -52,6 +52,22 @@ - #include - #endif - -+#include -+ -+ -+u8 nand_nce; /* indicates which chip select on JZSOC is used for current nand chip */ -+int global_page; /* page index of large page used for nand with multiple planes */ -+struct mtd_info *jz_mtd1 = NULL; /* for 1 plane operation */ -+ -+/* indicates whether multiple planes operation is used by all partitions -+ if multiple planes is supported by NAND */ -+char all_use_planes = 1; -+ -+/* The pointer to the address of block cache for partitions which work -+ over mtdblock-jz */ -+extern struct mtd_partition partition_info[]; /* defined in jz47xx_nand.c */ -+unsigned char **jz_mtdblock_cache = NULL; /* used by mtdblock-jz.c */ -+ - /* Define default oob placement schemes for large and small page devices */ - static struct nand_ecclayout nand_oob_8 = { - .eccbytes = 3, -@@ -68,10 +84,35 @@ static struct nand_ecclayout nand_oob_16 = { - .eccpos = {0, 1, 2, 3, 6, 7}, - .oobfree = { - {.offset = 8, -- . length = 8}} -+ .length = 8}} - }; - - static struct nand_ecclayout nand_oob_64 = { -+#if defined(CONFIG_MTD_HW_RS_ECC) -+/* Reed-Solomon ECC */ -+ .eccbytes = 36, -+ .eccpos = { -+ 28, 29, 30, 31, -+ 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63}, -+ .oobfree = { -+ {.offset = 2, -+ .length = 26}} -+#elif defined(CONFIG_MTD_HW_BCH_ECC) -+/* BCH ECC */ -+ .eccbytes = 28, -+ .eccpos = { -+ 24, 25, 26, 27, 28, 29, 30, 31, -+ 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51}, -+ .oobfree = { -+ {.offset = 2, -+ .length = 22}} -+#else -+/* HW&SW Hamming ECC */ - .eccbytes = 24, - .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, -@@ -109,6 +150,35 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, - DEFINE_LED_TRIGGER(nand_led_trigger); - - /** -+ * ffs_ll - find first bit set in a 64bit word. -+ * @word: The word to search -+ */ -+static inline int ffs_ll(u64 word) -+{ -+ u32 low = word & 0xffffffff; -+ u32 high = word >> 32; -+ int i; -+ -+ for(i = 0; i < 32; i++) { -+ if (low & 0x1) -+ break; -+ low >>= 1; -+ } -+ if (i == 32) { -+ for(i = 0; i < 32; i++) { -+ if (high & 0x1) -+ break; -+ high >>= 1; -+ } -+ i += 32; -+ } -+ if (i == 64) -+ return 0; -+ else -+ return (i+1); -+} -+ -+/** - * nand_release_device - [GENERIC] release chip - * @mtd: MTD device structure - * -@@ -183,6 +253,20 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) - chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); - break; - case 0: -+ nand_nce = NAND_NCE1; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ case 1: -+ nand_nce = NAND_NCE2; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ case 2: -+ nand_nce = NAND_NCE3; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ case 3: -+ nand_nce = NAND_NCE4; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - break; - - default: -@@ -314,11 +398,17 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) - */ - static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) - { -- int page, chipnr, res = 0; -+ int page, page1 = 0, chipnr, res = 0; - struct nand_chip *chip = mtd->priv; - u16 bad; - -- page = (int)(ofs >> chip->page_shift) & chip->pagemask; -+ if (chip->planenum > 1) { -+ page = ((int)(ofs >> chip->page_shift) * chip->planenum + CONFIG_MTD_BADBLOCK_FLAG_PAGE); -+ page1 = page + mtd->erasesize / mtd->writesize; -+ page &= chip->pagemask; -+ page1 &= chip->pagemask; -+ } else -+ page = ((int)(ofs >> chip->page_shift) + CONFIG_MTD_BADBLOCK_FLAG_PAGE) & chip->pagemask; - - if (getchip) { - chipnr = (int)(ofs >> chip->chip_shift); -@@ -341,6 +431,11 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) - chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page); - if (chip->read_byte(mtd) != 0xff) - res = 1; -+ if (chip->planenum > 1) { -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page1); -+ if (chip->read_byte(mtd) != 0xff) -+ res = 1; -+ } - } - - if (getchip) -@@ -377,6 +472,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) - */ - nand_get_device(chip, mtd, FL_WRITING); - ofs += mtd->oobsize; -+ ofs += (CONFIG_MTD_BADBLOCK_FLAG_PAGE << chip->page_shift); - chip->ops.len = chip->ops.ooblen = 2; - chip->ops.datbuf = NULL; - chip->ops.oobbuf = buf; -@@ -568,7 +664,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, - - /* Emulate NAND_CMD_READOOB */ - if (command == NAND_CMD_READOOB) { -- column += mtd->writesize; -+ if (chip->planenum > 1) -+ column += (mtd->writesize / chip->planenum); -+ else -+ column += mtd->writesize; - command = NAND_CMD_READ0; - } - -@@ -614,6 +713,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, - case NAND_CMD_RNDIN: - case NAND_CMD_STATUS: - case NAND_CMD_DEPLETE1: -+ case 0x81: /* for two-plane page program */ -+ case 0x11: /* for two-plane page program */ - return; - - /* -@@ -935,6 +1036,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 - return 0; - } - -+#ifndef CONFIG_MTD_HW_RS_ECC /* HW&SW Hamming ECC */ - /** - * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function - * @mtd: mtd info structure -@@ -979,6 +1081,63 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - return 0; - } - -+#else /* CONFIG_MTD_HW_RS_ECC */ -+ -+/** -+ * nand_read_page_hwecc_rs - [REPLACABLE] hardware rs ecc based page read function -+ * @mtd: mtd info structure -+ * @chip: nand chip info structure -+ * @buf: buffer to store read data -+ * -+ * Not for syndrome calculating ecc controllers which need a special oob layout -+ */ -+static int nand_read_page_hwecc_rs(struct mtd_info *mtd, struct nand_chip *chip, -+ uint8_t *buf) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccbytes = chip->ecc.bytes; -+ int eccsteps = chip->ecc.steps; -+ uint8_t *p = buf; -+ uint8_t *ecc_calc = chip->buffers->ecccalc; -+ uint8_t *ecc_code = chip->buffers->ecccode; -+ uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t page; -+ uint8_t flag = 0; -+ -+ page = (buf[3]<<24) + (buf[2]<<16) + (buf[1]<<8) + buf[0]; -+ -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); -+ for (i = 0; i < chip->ecc.total; i++) { -+ ecc_code[i] = chip->oob_poi[eccpos[i]]; -+ if (ecc_code[i] != 0xff) flag = 1; -+ } -+ -+ eccsteps = chip->ecc.steps; -+ p = buf; -+ -+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -+ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -+ int stat; -+ if (flag) { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -+ if (stat < 0) -+ mtd->ecc_stats.failed++; -+ else -+ mtd->ecc_stats.corrected += stat; -+ } -+ else { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ } -+ } -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_HW_RS_ECC */ -+ - /** - * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read - * @mtd: mtd info structure -@@ -1124,10 +1283,25 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, - if (realpage != chip->pagebuf || oob) { - bufpoi = aligned ? buf : chip->buffers->databuf; - -+ global_page = page; -+#if defined(CONFIG_MTD_HW_RS_ECC) -+ bufpoi[0] = (uint8_t)page; -+ bufpoi[1] = (uint8_t)(page >> 8); -+ bufpoi[2] = (uint8_t)(page >> 16); -+ bufpoi[3] = (uint8_t)(page >> 24); -+#elif defined(CONFIG_SOC_JZ4730) - if (likely(sndcmd)) { - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); - sndcmd = 0; - } -+#else /* for jz4750 and later chip */ -+ if (mtd->flags & MTD_NAND_CPU_MODE) { -+ if (likely(sndcmd)) { -+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); -+ sndcmd = 0; -+ } -+ } -+#endif - - /* Now read the page into the buffer */ - if (unlikely(ops->mode == MTD_OOB_RAW)) -@@ -1699,12 +1873,17 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - { - int status; - -- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); -- -- if (unlikely(raw)) -- chip->ecc.write_page_raw(mtd, chip, buf); -- else -+ global_page = page; -+ if (chip->planenum > 1) - chip->ecc.write_page(mtd, chip, buf); -+ else { -+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); -+ -+ if (unlikely(raw)) -+ chip->ecc.write_page_raw(mtd, chip, buf); -+ else -+ chip->ecc.write_page(mtd, chip, buf); -+ } - - /* - * Cached progamming disabled for now, Not sure if its worth the -@@ -1713,9 +1892,19 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - cached = 0; - - if (!cached || !(chip->options & NAND_CACHEPRG)) { -- -- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+/* -+* __nand_cmd(CMD_PAGEPROG) and __nand_sync() have been done by DMA for jz4750 and -+* later chip, status should still be read by "status = chip->waitfunc(mtd, chip)" -+*/ -+#if defined(CONFIG_SOC_JZ4730) || defined(CONFIG_SOC_JZ4740) -+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+#else -+ if (mtd->flags & MTD_NAND_CPU_MODE) { -+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+ } -+#endif - status = chip->waitfunc(mtd, chip); -+ - /* - * See if operation failed and additional status checks are - * available -@@ -2485,7 +2674,21 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; -+ /* The 5th id byte */ -+#if defined(CONFIG_MTD_NAND_MULTI_PLANE) -+ extid = chip->read_byte(mtd); -+ chip->realplanenum = 1 << ((extid & 0x0c) >> 2); -+#else -+ chip->realplanenum = 1; -+#endif - -+ if (chip->realplanenum > 1) { /* use muti planes mode */ -+ chip->planenum = 2; -+ mtd->writesize *= 2; /* two pages as one page */ -+ mtd->oobsize *= 2; -+ mtd->erasesize *= 2; /* two blocks as one block */ -+ } else -+ chip->planenum = 1; - } else { - /* - * Old devices have chip data hardcoded in the device id table -@@ -2558,8 +2761,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, - chip->cmdfunc = nand_command_lp; - - printk(KERN_INFO "NAND device: Manufacturer ID:" -- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, -- nand_manuf_ids[maf_idx].name, type->name); -+ " 0x%02x, Chip ID: 0x%02x (%s %s) planenum:%d\n", *maf_id, dev_id, -+ nand_manuf_ids[maf_idx].name, type->name, chip->realplanenum); - - return type; - } -@@ -2627,7 +2830,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) - */ - int nand_scan_tail(struct mtd_info *mtd) - { -- int i; -+ int i, res; - struct nand_chip *chip = mtd->priv; - - if (!(chip->options & NAND_OWN_BUFFERS)) -@@ -2655,6 +2858,16 @@ int nand_scan_tail(struct mtd_info *mtd) - case 128: - chip->ecc.layout = &nand_oob_128; - break; -+ case 128: -+ if (chip->planenum > 1) -+ chip->ecc.layout = &nand_oob_64; -+ else -+ chip->ecc.layout = &nand_oob_128; -+ break; -+ case 256: -+ if (chip->planenum > 1) -+ chip->ecc.layout = &nand_oob_128; -+ break; - default: - printk(KERN_WARNING "No oob scheme defined for " - "oobsize %d\n", mtd->oobsize); -@@ -2673,8 +2886,13 @@ int nand_scan_tail(struct mtd_info *mtd) - switch (chip->ecc.mode) { - case NAND_ECC_HW: - /* Use standard hwecc read page function ? */ -- if (!chip->ecc.read_page) -+ if (!chip->ecc.read_page) { -+#ifndef CONFIG_MTD_HW_RS_ECC - chip->ecc.read_page = nand_read_page_hwecc; -+#else -+ chip->ecc.read_page = nand_read_page_hwecc_rs; -+#endif -+ } - if (!chip->ecc.write_page) - chip->ecc.write_page = nand_write_page_hwecc; - if (!chip->ecc.read_page_raw) -@@ -2826,8 +3044,80 @@ int nand_scan_tail(struct mtd_info *mtd) - if (chip->options & NAND_SKIP_BBTSCAN) - return 0; - -- /* Build bad block table */ -- return chip->scan_bbt(mtd); -+ /* Create jz_mtd1 for one plane operation if the NAND support multiple -+ planes operation, because some partitions will only use one plane. */ -+ if ((chip->planenum == 2) && !all_use_planes) { -+ int i, len, numblocks; -+ struct nand_chip *this = (struct nand_chip *) (&jz_mtd1[1]); -+ -+ memcpy(jz_mtd1, mtd, sizeof(*mtd)); -+ jz_mtd1->priv = this; -+ memcpy(this, chip, sizeof(*chip)); -+ -+ this->planenum = 1; -+ jz_mtd1->writesize >>= 1; -+ jz_mtd1->oobsize >>= 1; -+ jz_mtd1->erasesize >>= 1; -+ this->page_shift = chip->page_shift - 1; -+ this->pagemask = (this->chipsize >> this->page_shift) - 1; -+ this->bbt_erase_shift = this->phys_erase_shift = -+ chip->phys_erase_shift - 1; -+ this->ecc.steps >>= 1; -+ this->ecc.total = this->ecc.steps * this->ecc.bytes; -+ this->subpagesize = jz_mtd1->writesize; -+ -+ this->erase_cmd = single_erase_cmd; -+#if defined(CONFIG_MTD_HW_RS_ECC) -+ this->ecc.read_page = nand_read_page_hwecc_rs; -+ this->ecc.write_page = nand_write_page_hwecc; -+#endif -+ this->ecc.read_oob = nand_read_oob_std; -+ this->ecc.write_oob = nand_write_oob_std; -+ this->write_buf = nand_write_buf; -+ this->read_buf = nand_read_buf; -+ -+ /* Firstly, build bad block table as one plane */ -+ res = this->scan_bbt(jz_mtd1); -+ -+ /* Secondly, build bad block table as 2 plane based on bbt of jz_mtd1 */ -+ numblocks = chip->chipsize >> (chip->bbt_erase_shift - 1); /* = (real numblocks * 2) */ -+ len = mtd->size >> (chip->bbt_erase_shift + 2); -+ chip->bbt = kzalloc(len, GFP_KERNEL); -+ -+#define isbad_2plane(block) (((this->bbt[(block) >> 3] >> ((block) & 0x06)) \ -+ | (this->bbt[((block)+2) >> 3] >> (((block)+2) & 0x06))) & 0x03) -+ -+ for (i = 0; i < numblocks; i += 2) { -+ if (isbad_2plane(2*i)) -+ chip->bbt[i >> 3] |= 0x03 << (i & 0x6); -+ } -+ } else { -+ res = chip->scan_bbt(mtd); -+ } -+ -+#if defined(CONFIG_ALLOCATE_MTDBLOCK_JZ_EARLY) && !defined(CONFIG_SOC_JZ4730) -+ /* Allocate a block cache for every partitions which works over mtdblock-jz */ -+ { -+ extern int nr_partitions; -+ -+ jz_mtdblock_cache = kmalloc(nr_partitions * sizeof(unsigned char *), GFP_KERNEL); -+ -+ for (i = 0; i < nr_partitions; i++) { -+ if (!(partition_info[i].mtdblock_jz_invalid) && !(partition_info[i].cpu_mode)) { -+ if (partition_info[i].use_planes) { -+ jz_mtdblock_cache[i] = kmalloc(mtd->erasesize, GFP_KERNEL); -+ printk("Allocate 0x%x bytes for jz_mtdblock%d at address:0x%p.\n", mtd->erasesize, i, jz_mtdblock_cache[i]); -+ } else { -+ jz_mtdblock_cache[i] = kmalloc(jz_mtd1->erasesize, GFP_KERNEL); -+ printk("Allocate 0x%x bytes for jz_mtdblock%d at address:0x%p.\n", jz_mtd1->erasesize, i, jz_mtdblock_cache[i]); -+ } -+ if (!jz_mtdblock_cache[i]) -+ printk("Cannot allocate memory for jz_mtdblock%d!\n", i); -+ } -+ } -+ } -+#endif -+ return res; - } - - /* is_module_text_address() isn't exported, and it's mostly a pointless -diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c -index 55c23e5..34c5a29 100644 ---- a/drivers/mtd/nand/nand_bbt.c -+++ b/drivers/mtd/nand/nand_bbt.c -@@ -401,7 +401,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, - * below as it makes shifting and masking less painful */ - numblocks = mtd->size >> (this->bbt_erase_shift - 1); - startblock = 0; -- from = 0; -+ from = (CONFIG_MTD_BADBLOCK_FLAG_PAGE << this->page_shift); //from = 0; - } else { - if (chip >= this->numchips) { - printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", -diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c -index 69ee2c9..8665859 100644 ---- a/drivers/mtd/nand/nand_ids.c -+++ b/drivers/mtd/nand/nand_ids.c -@@ -109,6 +109,9 @@ struct nand_flash_dev nand_flash_ids[] = { - {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, - {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, - -+ /* 32 Gigabit */ -+ {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, -+ - /* - * Renesas AND 1 Gigabit. Those chips do not support extended id and - * have a strange page/block layout ! The chosen minimum erasesize is -diff --git a/drivers/mtd/udc_cache.c b/drivers/mtd/udc_cache.c -new file mode 100644 -index 0000000..35b4be0 ---- /dev/null -+++ b/drivers/mtd/udc_cache.c -@@ -0,0 +1,531 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CACHE_MAX_NUM 256 -+#define SECTOR_SIZE 512 -+ -+//#define UDC_CACHE_DEBUG -+ -+#ifdef UDC_CACHE_DEBUG -+#define dprintk(a...) printk(a) -+#else -+#define dprintk(a...) while(0){} -+#endif -+ -+typedef struct { -+ unsigned short CacheState; -+ unsigned short UseCount; -+ unsigned short CacheChange; -+ unsigned short CacheReserve; -+ unsigned int BlockId; -+ unsigned char *aBlockData; -+} SSFDC__LB_CACHE; -+ -+#define FREE_CACHE 0 -+#define PREWRITE_CACHE 2 -+#define OFTEN_USE_CACHE 3 -+#define SECTOR_SHIFT 9 -+ -+#define CACHE_TO_UNCATCH(x) ((unsigned int)x | 0xa0000000) -+static unsigned int __aBlockData[SECTOR_SIZE * CACHE_MAX_NUM / 4] __attribute__ ((aligned (32))); -+static SSFDC__LB_CACHE ssfdc_cache[CACHE_MAX_NUM]; -+static unsigned short Cur_CacheCount = 0; -+int FlushDataState = 0; -+static struct mtdblk_dev *g_udc_mtdblk; -+static struct mtd_info *g_udc_mtd; -+ -+extern int udc_mtdblock_readsect(struct mtdblk_dev *, unsigned long, char *, int); -+extern int udc_mtdblock_writesect(struct mtdblk_dev *, unsigned long, char *); -+extern struct mtdblk_dev *udc_get_mtdblk(void); -+extern struct mtd_info *udc_get_mtd(void); -+extern void udc_flush_cache(struct mtdblk_dev *mtdblk); -+ -+#define _NAND_LB_Write(pCache) udc_mtdblock_writesect(g_udc_mtdblk, pCache->BlockId,pCache->aBlockData) -+#define _NAND_LB_Read(Sector,pBuffer) udc_mtdblock_readsect(g_udc_mtdblk, Sector, pBuffer, SECTOR_SIZE); -+ -+#define DMA_ENABLE 0 -+ -+#if DMA_ENABLE -+#define DMA_CHANNEL 5 -+#define PHYSADDR(x) virt_to_phys((void *)x) -+#else -+#define lb_memcpy memcpy -+#endif -+ -+#if DMA_ENABLE -+static void lb_memcpy(void *target,void* source,unsigned int len) -+{ -+ int ch = DMA_CHANNEL; -+ if(((unsigned int)source < 0xa0000000) && len) -+ dma_cache_wback_inv((unsigned long)source, len); -+ if(((unsigned int)target < 0xa0000000) && len) -+ dma_cache_wback_inv((unsigned long)target, len); -+ -+ REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long)source); -+ REG_DMAC_DTAR(ch) = PHYSADDR((unsigned long)target); -+ REG_DMAC_DTCR(ch) = len / 32; -+ REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_AUTO; -+ REG_DMAC_DCMD(ch) = DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32|DMAC_DCMD_DS_32BYTE; -+ REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; -+ while ( REG_DMAC_DTCR(ch) ); -+} -+#endif -+ -+static void _NAND_LB_InitCache(void) -+{ -+ int i; -+ SSFDC__LB_CACHE *pCache = ssfdc_cache; -+#if DMA_ENABLE -+ unsigned char * ptr = (unsigned char *)CACHE_TO_UNCATCH(__aBlockData); -+#else -+ unsigned char * ptr = (unsigned char *)(__aBlockData); -+#endif -+ for(i = 0;i < CACHE_MAX_NUM;i++) -+ { -+ pCache->CacheState = FREE_CACHE; -+ pCache->UseCount = 0; -+ pCache->CacheChange = 0; -+ pCache->aBlockData = ptr; -+ ptr+=SECTOR_SIZE; -+ pCache++; -+ } -+ Cur_CacheCount = 0; -+} -+ -+static SSFDC__LB_CACHE * _NAND_LB_GetFreeCache(void) -+{ -+ int ret = 0; -+ SSFDC__LB_CACHE *pCacheInfo = &ssfdc_cache[Cur_CacheCount]; -+ while(1) -+ { -+ if(ret >= CACHE_MAX_NUM) -+ return 0; -+ if(pCacheInfo >= &ssfdc_cache[CACHE_MAX_NUM]) -+ { -+ pCacheInfo = ssfdc_cache; -+ Cur_CacheCount = 0; -+ } -+ -+ if(pCacheInfo->CacheState == FREE_CACHE) -+ { -+ return pCacheInfo; -+ } -+ pCacheInfo++; -+ Cur_CacheCount++; -+ ret++; -+ } -+ return 0; -+} -+ -+static void _NAND_LB_CloseCACHES(unsigned int sectorstart,unsigned int sectorend) -+{ -+ unsigned int i; -+ SSFDC__LB_CACHE *pCache = ssfdc_cache; -+ for( i = 0;i < CACHE_MAX_NUM;i++){ -+ if((pCache->CacheState != FREE_CACHE) && (pCache->BlockId >= sectorstart) && (pCache->BlockId < sectorend)){ -+ pCache->CacheChange = 0; -+ pCache->CacheState = FREE_CACHE; -+ pCache->UseCount = 0; -+ } -+ pCache++; -+ } -+} -+ -+static void _NAND_LB_FLUSHCACHES(unsigned int sectorstart,unsigned int sectorend) -+{ -+ unsigned int i; -+ SSFDC__LB_CACHE *pCache = ssfdc_cache; -+ for( i = 0;i < CACHE_MAX_NUM;i++){ -+ if((pCache->CacheState != FREE_CACHE) && (pCache->BlockId >= sectorstart) && (pCache->BlockId < sectorend)){ -+ if(pCache->CacheChange) -+ _NAND_LB_Write(pCache); -+ pCache->CacheChange = 0; -+ pCache->CacheState = FREE_CACHE; -+ pCache->UseCount = 0; -+ } -+ pCache++; -+ -+ } -+} -+ -+inline static int Get_NAND_CacheFreeCount(void) -+{ -+ SSFDC__LB_CACHE *pCache = ssfdc_cache; -+ SSFDC__LB_CACHE *pEndCache = &ssfdc_cache[CACHE_MAX_NUM]; -+ unsigned int count = 0; -+ while(pCache < pEndCache) -+ { -+ if(pCache->CacheState == FREE_CACHE) -+ count++; -+ pCache++; -+ } -+ return count; -+ -+} -+ -+static unsigned int _NAND_LB_PreWiteToNand(SSFDC__LB_CACHE *pCache,unsigned short *count,unsigned int update) -+{ -+ SSFDC__LB_CACHE *pWriteCache; -+ SSFDC__LB_CACHE *pEndCache = &ssfdc_cache[CACHE_MAX_NUM]; -+ unsigned int sector = -1; -+ unsigned int flag; -+ while(1) -+ { -+ sector = -1; -+ flag = 0; -+ pWriteCache = ssfdc_cache; -+ while(pWriteCache < pEndCache) -+ { -+ if(pWriteCache->CacheState == update) //PREWRITE_CACHE -+ { -+ if(pWriteCache->BlockId < sector) -+ { -+ sector = pWriteCache->BlockId; -+ pCache = pWriteCache; -+ } -+ }else -+ flag++; -+ pWriteCache++; -+ } -+ -+ if(flag < CACHE_MAX_NUM) -+ { -+ if(pCache->CacheChange) -+ { -+ _NAND_LB_Write(pCache); -+ pCache->CacheChange = 0; -+ } -+ pCache->CacheState = FREE_CACHE; -+ pCache->UseCount = 0; -+ (*count)++; -+ }else -+ break; -+ } -+ return 0; -+} -+ -+static void _NAND_LB_OftenToNand(SSFDC__LB_CACHE *pCache,unsigned short *count,unsigned int update) -+{ -+ SSFDC__LB_CACHE *pWriteCache = pCache; -+ SSFDC__LB_CACHE *pOldCache = pCache; -+ SSFDC__LB_CACHE *pEndCache = &ssfdc_cache[CACHE_MAX_NUM]; -+ -+ dprintk("%s!\n",__FUNCTION__); -+ while(pCache) -+ { -+ if(pCache->CacheState == OFTEN_USE_CACHE) -+ { -+ if(pWriteCache->CacheState != OFTEN_USE_CACHE) -+ pWriteCache = pCache; -+ else if(pWriteCache->UseCount > pCache->UseCount) -+ { -+ pWriteCache = pCache; -+ } -+ } -+ pCache++; -+ if(pCache >= pEndCache) -+ break; -+ } -+ if(pWriteCache->CacheState == OFTEN_USE_CACHE) -+ { -+ (*count)++; -+ if(pWriteCache->CacheChange) -+ _NAND_LB_Write(pWriteCache); -+ pWriteCache->CacheState = FREE_CACHE; -+ -+ pWriteCache->UseCount = 0; -+ pWriteCache->CacheChange = 0; -+ if(update != -1) -+ update--; -+ if(update != 0) -+ _NAND_LB_OftenToNand(pOldCache,count,update); -+ } -+} -+ -+static int _NAND_LB_FreeCache(unsigned int update) -+{ -+ unsigned short freecount = 0,totalfree = 0; -+ -+ freecount = 0; -+ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,PREWRITE_CACHE); -+ -+ totalfree += freecount; -+ dprintk("free count = %d\n",freecount); -+ if(freecount == 0) -+ { -+ freecount = 0; -+ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,OFTEN_USE_CACHE); -+ totalfree += freecount; -+ update = 0; -+ } -+ if(update) -+ { -+ if(Get_NAND_CacheFreeCount() < CACHE_MAX_NUM * 1 / 4) // because fat is 4 sector -+ { -+ freecount = 0; -+ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,OFTEN_USE_CACHE); -+ totalfree += freecount; -+ } -+ } -+ -+ dprintk("Free = %d\r\n",totalfree); -+ return totalfree; -+} -+ -+static int _NAND_LB_GetFromCache(unsigned int Sector, void *pBuffer) { -+ -+ SSFDC__LB_CACHE *pCache = &ssfdc_cache[Cur_CacheCount]; -+ SSFDC__LB_CACHE *pUseCache = 0; -+ unsigned short i; -+ dprintk("sector = %x pBuffer = %x\n",Sector,pBuffer); -+ if(pCache >= &ssfdc_cache[CACHE_MAX_NUM]) -+ pCache = ssfdc_cache; -+ -+ i = 0; -+ while (1) { -+ if(pCache->CacheState != FREE_CACHE) -+ { -+ if (Sector == pCache->BlockId) { -+ dprintk("Cache is use = %d\r\n",pCache->BlockId); -+ pUseCache = pCache; -+ pCache->UseCount++; -+ if(pCache->UseCount == 0) -+ pCache->UseCount = -1; -+ pCache->CacheState = OFTEN_USE_CACHE; -+ } -+ } -+ pCache--; -+ if(pCache < ssfdc_cache) -+ pCache = &ssfdc_cache[CACHE_MAX_NUM - 1]; -+ -+ i++; -+ if (i >= CACHE_MAX_NUM) { -+ break; /* Sector not in cache */ -+ } -+ } -+ if (pUseCache) { -+ dprintk("From Cache %d\r\n",Sector); -+ lb_memcpy(pBuffer, pUseCache->aBlockData, SECTOR_SIZE); -+ return 0; -+ } -+ return -1; -+} -+ -+static void _NAND_LB_ClearCache(void) { -+ -+ unsigned short freecount = 0; -+ dprintk("Clear Cache\r\n"); -+ -+ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,PREWRITE_CACHE); -+ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,OFTEN_USE_CACHE); -+} -+ -+static void _NAND_LB_CopyToCache(unsigned int Sector, void *pBuffer,unsigned short rw) -+{ -+ SSFDC__LB_CACHE *pCache = _NAND_LB_GetFreeCache(); -+ dprintk("Copy to Cache = 0x%08x 0x%08x\r\n",pCache,ssfdc_cache); -+ -+ if(!pCache) -+ { -+ _NAND_LB_FreeCache(rw); -+ -+ pCache = _NAND_LB_GetFreeCache(); -+ } -+ pCache->BlockId = Sector; -+ pCache->CacheState = PREWRITE_CACHE; -+ pCache->UseCount = 0; -+ pCache->CacheChange = rw; -+ -+ lb_memcpy(pCache->aBlockData,pBuffer,SECTOR_SIZE); -+} -+ -+ -+static int _NAND_LB_UpdateInCache(unsigned int Sector, void *pBuffer) { -+ short i,ret = 0; -+ i = Cur_CacheCount; -+ if(Cur_CacheCount > CACHE_MAX_NUM) -+ i = 0; -+ while(1) -+ { -+ if(ret >= CACHE_MAX_NUM) -+ return -1; -+ if(ssfdc_cache[i].CacheState != FREE_CACHE) -+ { -+ -+ if(ssfdc_cache[i].BlockId == Sector) -+ { -+ dprintk("UpdateInCache = %d\r\n",Sector); -+ ssfdc_cache[i].CacheState = OFTEN_USE_CACHE; -+ ssfdc_cache[i].UseCount++; -+ ssfdc_cache[i].CacheChange = 1; -+ lb_memcpy(ssfdc_cache[i].aBlockData,pBuffer,SECTOR_SIZE); -+ return 0; -+ } -+ } -+ i--; -+ if(i < 0) -+ i = CACHE_MAX_NUM - 1; -+ ret++; -+ } -+ return -1; -+} -+ -+static int NAND_LB_MultiRead(unsigned int Sector, void *pBuffer,unsigned int SectorCount) -+{ -+ int i,ret,end; -+ void *p; -+ -+ dprintk("NAND_LB_MultiRead = %d %d \n",Sector,SectorCount); -+ end = Sector + SectorCount; -+ _NAND_LB_FLUSHCACHES(Sector,end); -+ -+ p = pBuffer; -+ for (i = Sector; i < end; i ++) -+ { -+ ret = udc_mtdblock_readsect(g_udc_mtdblk, i, p, SECTOR_SIZE); -+ p += SECTOR_SIZE; -+ } -+ return ret; -+} -+ -+static int NAND_LB_Read(unsigned int Sector, void *pBuffer) -+{ -+ int x; -+#if DMA_ENABLE -+ unsigned char *ptr = (unsigned char *)CACHE_TO_UNCATCH(pBuffer); -+ dma_cache_wback_inv(pBuffer,SECTOR_SIZE); -+#else -+ unsigned char *ptr = (unsigned char *)pBuffer; -+#endif -+ dprintk("LB_Read = %d \n",Sector); -+ if(_NAND_LB_GetFromCache(Sector,ptr)) -+ { -+ x = _NAND_LB_Read(Sector,ptr); -+ _NAND_LB_CopyToCache(Sector,ptr,0); -+ } -+ return 512; -+} -+ -+static int NAND_LB_MultiWrite(unsigned int Sector, void *pBuffer,unsigned int SectorCount) -+{ -+ int i,ret; -+ unsigned char *p; -+ -+ _NAND_LB_CloseCACHES(Sector,Sector + SectorCount); -+ p = (unsigned char *)pBuffer; -+ for (i = Sector; i < Sector + SectorCount; i ++) -+ { -+ ret = udc_mtdblock_writesect(g_udc_mtdblk, i, p); -+ p += 512; -+ } -+ return ret; -+} -+ -+static int NAND_LB_Write(unsigned int Sector, void *pBuffer) -+{ -+#if DMA_ENABLE -+ unsigned char *ptr = (unsigned char *)CACHE_TO_UNCATCH(pBuffer); -+ dma_cache_wback_inv(pBuffer,SECTOR_SIZE); -+#else -+ unsigned char *ptr = (unsigned char *)pBuffer; -+#endif -+ dprintk("LB_Write = %x %x\r\n",Sector,pBuffer); -+ if(_NAND_LB_UpdateInCache(Sector,ptr)) -+ { -+ _NAND_LB_CopyToCache(Sector,ptr,1); -+ } -+ return 512; -+} -+/********************************************************************* -+* -+* Global functions -+* -+***********************************************************************/ -+ -+int NAND_LB_Init(void) -+{ -+ dprintk("UDC CACHE Init \n"); -+ _NAND_LB_InitCache(); -+ g_udc_mtdblk = udc_get_mtdblk(); -+ g_udc_mtd = udc_get_mtd(); -+ return 0; -+} -+ -+int NAND_LB_FLASHCACHE(void) -+{ -+ dprintk("Flush lb cache !\n"); -+ _NAND_LB_ClearCache(); -+// dprintk("Flush mtd cache !\n"); -+// udc_flush_cache(g_udc_mtdblk); -+ return 0; -+} -+ -+int NAND_MTD_FLASHCACHE(void) -+{ -+ dprintk("Flush mtd cache !\n"); -+ udc_flush_cache(g_udc_mtdblk); -+ return 0; -+} -+ -+int udc_read(unsigned long long offset, unsigned int len, unsigned char *buf) -+{ -+ unsigned long block,sector,i; -+ -+ block = offset >> SECTOR_SHIFT; -+ sector = len >> SECTOR_SHIFT; -+ dprintk("read dev = ia:%x, s:%d c:%d\r\n",buf,block,sector); -+ -+ if (sector <= 8) -+ { -+ for(i = 0;i < sector; i++) -+ { -+ NAND_LB_Read(block + i,(void *)(buf)); -+ buf += 512; -+ } -+ } -+ else -+ NAND_LB_MultiRead(block, buf, sector); -+ -+ return len; -+} -+ -+int udc_write(unsigned long long offset, unsigned int len, unsigned char *buf) -+{ -+ unsigned long block,sector,i; -+ -+ block = offset >> SECTOR_SHIFT; -+ sector = len >> SECTOR_SHIFT; -+ dprintk("write dev s:%d c:%d\r\n",block,sector); -+ -+ if(sector <= 8) -+ { -+ for(i = 0;i < sector; i++) -+ { -+ NAND_LB_Write(block + i,(void *)(buf)); -+ buf += 512; -+ FlushDataState = 1; -+ } -+ }else -+ NAND_LB_MultiWrite(block,(void *)(buf),sector); -+ -+ return len; -+} -+ -+EXPORT_SYMBOL_GPL(udc_write); -+EXPORT_SYMBOL_GPL(udc_read); -+EXPORT_SYMBOL_GPL(NAND_LB_Init); -+EXPORT_SYMBOL_GPL(NAND_LB_FLASHCACHE); -+EXPORT_SYMBOL_GPL(FlushDataState); -+EXPORT_SYMBOL_GPL(NAND_MTD_FLASHCACHE); -diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig -index 5f6509a..c0acd09 100644 ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -207,6 +207,24 @@ config MII - or internal device. It is safe to say Y or M here even if your - ethernet card lack MII. - -+config JZ_ETH -+ tristate "JZ4730/JZ5730 On-Chip Ethernet support" -+ depends on NET_ETHERNET && (SOC_JZ4730 || SOC_JZ5730 || JZ_FPGA) -+ help -+ Say Y for support of JZ4730/JZ5730 On-Chip Ethernet interface. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called jz_eth. -+ -+config JZCS8900 -+ tristate "JZ CS8900A Ethernet support" -+ depends on NET_ETHERNET && (SOC_JZ4740 || SOC_JZ4750) -+ help -+ Say Y for support of JZ CS8900A Ethernet interface. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called jzcs8900a. -+ - config MACB - tristate "Atmel MACB support" - depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91CAP9 -diff --git a/drivers/net/Makefile b/drivers/net/Makefile -index ead8cab..8d87dfd 100644 ---- a/drivers/net/Makefile -+++ b/drivers/net/Makefile -@@ -103,6 +103,8 @@ obj-$(CONFIG_MII) += mii.o - obj-$(CONFIG_MDIO) += mdio.o - obj-$(CONFIG_PHYLIB) += phy/ - -+obj-$(CONFIG_JZ_ETH) += jz_eth.o -+obj-$(CONFIG_JZCS8900) += jzcs8900a.o - obj-$(CONFIG_SUNDANCE) += sundance.o - obj-$(CONFIG_HAMACHI) += hamachi.o - obj-$(CONFIG_NET) += Space.o loopback.o -diff --git a/drivers/net/jz_eth.c b/drivers/net/jz_eth.c -new file mode 100644 -index 0000000..ade9556 ---- /dev/null -+++ b/drivers/net/jz_eth.c -@@ -0,0 +1,1290 @@ -+/* -+ * linux/drivers/net/jz_eth.c -+ * -+ * Jz4730/Jz5730 On-Chip ethernet driver. -+ * -+ * Copyright (C) 2005 - 2007 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz_eth.h" -+ -+#define P2ADDR(a) (((unsigned long)(a) & 0x1fffffff) | 0xa0000000) -+#define P1ADDR(a) (((unsigned long)(a) & 0x1fffffff) | 0x80000000) -+ -+//#define DEBUG -+#ifdef DEBUG -+# define DBPRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) -+#else -+# define DBPRINTK(fmt,args...) do {} while(0) -+#endif -+ -+#define errprintk(fmt,args...) printk(KERN_ERR fmt,##args); -+#define infoprintk(fmt,args...) printk(KERN_INFO fmt,##args); -+ -+#define DRV_NAME "jz_eth" -+#define DRV_VERSION "1.2" -+#define DRV_AUTHOR "Peter Wei " -+#define DRV_DESC "JzSOC On-chip Ethernet driver" -+ -+MODULE_AUTHOR(DRV_AUTHOR); -+MODULE_DESCRIPTION(DRV_DESC); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Local variables -+ */ -+static struct net_device *netdev; -+static char * hwaddr = NULL; -+static int debug = -1; -+static struct mii_if_info mii_info; -+ -+MODULE_PARM_DESC(debug, "i"); -+MODULE_PARM_DESC(hwaddr,"s"); -+ -+/* -+ * Local routines -+ */ -+static irqreturn_t jz_eth_interrupt(int irq, void *dev_id); -+ -+static int link_check_thread (void *data); -+ -+/* -+ * Get MAC address -+ */ -+ -+#define I2C_DEVICE 0x57 -+#define MAC_OFFSET 64 -+ -+extern void i2c_open(void); -+extern void i2c_close(void); -+extern int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+ -+static inline unsigned char str2hexnum(unsigned char c) -+{ -+ if (c >= '0' && c <= '9') -+ return c - '0'; -+ if (c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ if (c >= 'A' && c <= 'F') -+ return c - 'A' + 10; -+ return 0; /* foo */ -+} -+ -+static inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; -+ -+ for (i = 0; i < 6; i++) { -+ unsigned char num; -+ -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} -+ -+static int ethaddr_cmd = 0; -+static unsigned char ethaddr_hex[6]; -+ -+static int __init ethernet_addr_setup(char *str) -+{ -+ if (!str) { -+ printk("ethaddr not set in command line\n"); -+ return -1; -+ } -+ ethaddr_cmd = 1; -+ str2eaddr(ethaddr_hex, str); -+ -+ return 0; -+} -+ -+__setup("ethaddr=", ethernet_addr_setup); -+ -+static int get_mac_address(struct net_device *dev) -+{ -+ int i; -+ unsigned char flag0=0; -+ unsigned char flag1=0xff; -+ -+ dev->dev_addr[0] = 0xff; -+ if (hwaddr != NULL) { -+ /* insmod jz-ethc.o hwaddr=00:ef:a3:c1:00:10 */ -+ str2eaddr(dev->dev_addr, hwaddr); -+ } else if (ethaddr_cmd) { -+ /* linux command line: ethaddr=00:ef:a3:c1:00:10 */ -+ for (i=0; i<6; i++) -+ dev->dev_addr[i] = ethaddr_hex[i]; -+ } else { -+#if 0 -+ /* mac address in eeprom: byte 0x40-0x45 */ -+ i2c_open(); -+ i2c_read(I2C_DEVICE, dev->dev_addr, MAC_OFFSET, 6); -+ i2c_close(); -+#endif -+ } -+ -+ /* check whether valid MAC address */ -+ for (i=0; i<6; i++) { -+ flag0 |= dev->dev_addr[i]; -+ flag1 &= dev->dev_addr[i]; -+ } -+ if ((dev->dev_addr[0] & 0xC0) || (flag0 == 0) || (flag1 == 0xff)) { -+ printk("WARNING: There is not MAC address, use default ..\n"); -+ dev->dev_addr[0] = 0x00; -+ dev->dev_addr[1] = 0xef; -+ dev->dev_addr[2] = 0xa3; -+ dev->dev_addr[3] = 0xc1; -+ dev->dev_addr[4] = 0x00; -+ dev->dev_addr[5] = 0x10; -+ dev->dev_addr[5] = 0x03; -+ } -+ return 0; -+} -+ -+/*---------------------------------------------------------------------*/ -+ -+static u32 jz_eth_curr_mode(struct net_device *dev); -+ -+/* -+ * Ethernet START/STOP routines -+ */ -+#define START_ETH { \ -+ s32 val; \ -+ val = readl(DMA_OMR); \ -+ val |= OMR_ST | OMR_SR; \ -+ writel(val, DMA_OMR); \ -+} -+ -+#define STOP_ETH { \ -+ s32 val; \ -+ val = readl(DMA_OMR); \ -+ val &= ~(OMR_ST|OMR_SR); \ -+ writel(val, DMA_OMR); \ -+} -+ -+/* -+ * Link check routines -+ */ -+static void start_check(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ -+ np->thread_die = 0; -+ init_waitqueue_head(&np->thr_wait); -+ init_completion (&np->thr_exited); -+ np->thr_pid = kernel_thread (link_check_thread,(void *)dev, -+ CLONE_FS | CLONE_FILES); -+ if (np->thr_pid < 0) -+ errprintk("%s: unable to start kernel thread\n",dev->name); -+} -+ -+static int close_check(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ int ret = 0; -+ -+ if (np->thr_pid >= 0) { -+ np->thread_die = 1; -+ wmb(); -+ ret = kill_proc (np->thr_pid, SIGTERM, 1); -+ if (ret) { -+ errprintk("%s: unable to signal thread\n", dev->name); -+ return 1; -+ } -+ wait_for_completion (&np->thr_exited); -+ } -+ return 0; -+} -+ -+static int link_check_thread(void *data) -+{ -+ struct net_device *dev=(struct net_device *)data; -+ struct jz_eth_private *np = (struct jz_eth_private *)netdev->priv; -+ unsigned char current_link; -+ unsigned long timeout; -+ -+ daemonize("%s", dev->name); -+ spin_lock_irq(¤t->sighand->siglock); -+ sigemptyset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ strncpy (current->comm, dev->name, sizeof(current->comm) - 1); -+ current->comm[sizeof(current->comm) - 1] = '\0'; -+ -+ while (1) { -+ timeout = 3*HZ; -+ do { -+ timeout = interruptible_sleep_on_timeout (&np->thr_wait, timeout); -+ /* make swsusp happy with our thread */ -+// if (current->flags & PF_FREEZE) -+// refrigerator(PF_FREEZE); -+ } while (!signal_pending (current) && (timeout > 0)); -+ -+ if (signal_pending (current)) { -+ spin_lock_irq(¤t->sighand->siglock); -+ flush_signals(current); -+ spin_unlock_irq(¤t->sighand->siglock); -+ } -+ -+ if (np->thread_die) -+ break; -+ -+ current_link=mii_link_ok(&mii_info); -+ if (np->link_state!=current_link) { -+ if (current_link) { -+ infoprintk("%s: Ethernet Link OK!\n",dev->name); -+ jz_eth_curr_mode(dev); -+ netif_carrier_on(dev); -+ } -+ else { -+ errprintk("%s: Ethernet Link offline!\n",dev->name); -+ netif_carrier_off(dev); -+ } -+ } -+ np->link_state=current_link; -+ -+ } -+ complete_and_exit (&np->thr_exited, 0); -+} -+ -+#ifdef DEBUG -+/* -+ * Display ethernet packet header -+ * This routine is used for test function -+ */ -+static void eth_dbg_rx(struct sk_buff *skb, int len) -+{ -+ -+ int i, j; -+ -+ printk("R: %02x:%02x:%02x:%02x:%02x:%02x <- %02x:%02x:%02x:%02x:%02x:%02x len/SAP:%02x%02x [%d]\n", -+ (u8)skb->data[0], -+ (u8)skb->data[1], -+ (u8)skb->data[2], -+ (u8)skb->data[3], -+ (u8)skb->data[4], -+ (u8)skb->data[5], -+ (u8)skb->data[6], -+ (u8)skb->data[7], -+ (u8)skb->data[8], -+ (u8)skb->data[9], -+ (u8)skb->data[10], -+ (u8)skb->data[11], -+ (u8)skb->data[12], -+ (u8)skb->data[13], -+ len); -+ for (j=0; len>0; j+=16, len-=16) { -+ printk(" %03x: ",j); -+ for (i=0; i<16 && idata[i+j]); -+ } -+ printk("\n"); -+ } -+ return; -+ } -+#endif -+ -+/* -+ * Reset ethernet device -+ */ -+static inline void jz_eth_reset(void) -+{ -+ u32 i; -+ i = readl(DMA_BMR); -+ writel(i | BMR_SWR, DMA_BMR); -+ for(i = 0; i < 1000; i++) { -+ if(!(readl(DMA_BMR) & BMR_SWR)) break; -+ mdelay(1); -+ } -+} -+ -+/* -+ * MII operation routines -+ */ -+static inline void mii_wait(void) -+{ -+ int i; -+ for(i = 0; i < 10000; i++) { -+ if(!(readl(MAC_MIIA) & 0x1)) -+ break; -+ mdelay(1); -+ } -+ if (i >= 10000) -+ printk("MII wait timeout : %d.\n", i); -+} -+ -+static int mdio_read(struct net_device *dev,int phy_id, int location) -+{ -+ u32 mii_cmd = (phy_id << 11) | (location << 6) | 1; -+ int retval = 0; -+ -+ writel(mii_cmd, MAC_MIIA); -+ mii_wait(); -+ retval = readl(MAC_MIID) & 0x0000ffff; -+ -+ return retval; -+ -+} -+ -+static void mdio_write(struct net_device *dev,int phy_id, int location, int data) -+{ -+ u32 mii_cmd = (phy_id << 11) | (location << 6) | 0x2 | 1; -+ -+ writel(mii_cmd, MAC_MIIA); -+ writel(data & 0x0000ffff, MAC_MIID); -+ mii_wait(); -+} -+ -+ -+/* -+ * Search MII phy -+ */ -+static int jz_search_mii_phy(struct net_device *dev) -+{ -+ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ int phy, phy_idx = 0; -+ -+ np->valid_phy = 0xff; -+ for (phy = 0; phy < 32; phy++) { -+ int mii_status = mdio_read(dev,phy, 1); -+ if (mii_status != 0xffff && mii_status != 0x0000) { -+ np->phys[phy_idx] = phy; -+ np->ecmds[phy_idx].speed=SPEED_100; -+ np->ecmds[phy_idx].duplex=DUPLEX_FULL; -+ np->ecmds[phy_idx].port=PORT_MII; -+ np->ecmds[phy_idx].transceiver=XCVR_INTERNAL; -+ np->ecmds[phy_idx].phy_address=np->phys[phy_idx]; -+ np->ecmds[phy_idx].autoneg=AUTONEG_ENABLE; -+ np->ecmds[phy_idx].advertising=(ADVERTISED_10baseT_Half | -+ ADVERTISED_10baseT_Full | -+ ADVERTISED_100baseT_Half | -+ ADVERTISED_100baseT_Full); -+ phy_idx++; -+ } -+ } -+ if (phy_idx == 1) { -+ np->valid_phy = np->phys[0]; -+ np->phy_type = 0; -+ } -+ if (phy_idx != 0) { -+ phy = np->valid_phy; -+ np->advertising = mdio_read(dev,phy, 4); -+ } -+ return phy_idx; -+} -+ -+/* -+ * CRC calc for Destination Address for gets hashtable index -+ */ -+ -+#define POLYNOMIAL 0x04c11db7UL -+static u16 jz_hashtable_index(u8 *addr) -+{ -+#if 1 -+ u32 crc = 0xffffffff, msb; -+ int i, j; -+ u32 byte; -+ for (i = 0; i < 6; i++) { -+ byte = *addr++; -+ for (j = 0; j < 8; j++) { -+ msb = crc >> 31; -+ crc <<= 1; -+ if (msb ^ (byte & 1)) crc ^= POLYNOMIAL; -+ byte >>= 1; -+ } -+ } -+ return ((int)(crc >> 26)); -+#endif -+#if 0 -+ int crc = -1; -+ int length=6; -+ int bit; -+ unsigned char current_octet; -+ while (--length >= 0) { -+ current_octet = *addr++; -+ for (bit = 0; bit < 8; bit++, current_octet >>= 1) -+ crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? -+ POLYNOMIAL : 0); -+ } -+ return ((int)(crc >> 26)); -+#endif -+} -+ -+/* -+ * Multicast filter and config multicast hash table -+ */ -+#define MULTICAST_FILTER_LIMIT 64 -+ -+static void jz_set_multicast_list(struct net_device *dev) -+{ -+ int i, hash_index; -+ u32 mcr, hash_h, hash_l, hash_bit; -+ -+ mcr = readl(MAC_MCR); -+ mcr &= ~(MCR_PR | MCR_PM | MCR_HP); -+ -+ if (dev->flags & IFF_PROMISC) { -+ /* Accept any kinds of packets */ -+ mcr |= MCR_PR; -+ hash_h = 0xffffffff; -+ hash_l = 0xffffffff; -+ DBPRINTK("%s: enter promisc mode!\n",dev->name); -+ } -+ else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > MULTICAST_FILTER_LIMIT)){ -+ /* Accept all multicast packets */ -+ mcr |= MCR_PM; -+ hash_h = 0xffffffff; -+ hash_l = 0xffffffff; -+ DBPRINTK("%s: enter allmulticast mode! %d \n",dev->name,dev->mc_count); -+ } -+ else if (dev->flags & IFF_MULTICAST) -+ { -+ /* Update multicast hash table */ -+ struct dev_mc_list *mclist; -+ hash_h = readl(MAC_HTH); -+ hash_l = readl(MAC_HTL); -+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; -+ i++, mclist = mclist->next) -+ { -+ hash_index = jz_hashtable_index(mclist->dmi_addr); -+ hash_bit=0x00000001; -+ hash_bit <<= (hash_index & 0x1f); -+ if (hash_index > 0x1f) -+ hash_h |= hash_bit; -+ else -+ hash_l |= hash_bit; -+ DBPRINTK("----------------------------\n"); -+#ifdef DEBUG -+ int j; -+ for (j=0;jdmi_addrlen;j++) -+ printk("%2.2x:",mclist->dmi_addr[j]); -+ printk("\n"); -+#endif -+ DBPRINTK("dmi.addrlen => %d\n",mclist->dmi_addrlen); -+ DBPRINTK("dmi.users => %d\n",mclist->dmi_users); -+ DBPRINTK("dmi.gusers => %d\n",mclist->dmi_users); -+ } -+ writel(hash_h,MAC_HTH); -+ writel(hash_l,MAC_HTL); -+ mcr |= MCR_HP; -+ DBPRINTK("This is multicast hash table high bits [%4.4x]\n",readl(MAC_HTH)); -+ DBPRINTK("This is multicast hash table low bits [%4.4x]\n",readl(MAC_HTL)); -+ DBPRINTK("%s: enter multicast mode!\n",dev->name); -+ } -+ writel(mcr,MAC_MCR); -+} -+ -+static inline int jz_phy_reset(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ unsigned int mii_reg0; -+ unsigned int count; -+ -+ mii_reg0 = mdio_read(dev,np->valid_phy,MII_BMCR); -+ mii_reg0 |=MII_CR_RST; -+ mdio_write(dev,np->valid_phy,MII_BMCR,mii_reg0); //reset phy -+ for ( count = 0; count < 1000; count++) { -+ mdelay(1); -+ mii_reg0 = mdio_read(dev,np->valid_phy,MII_BMCR); -+ if (!(mii_reg0 & MII_CR_RST)) break; //reset completed -+ } -+ if (count>=100) -+ return 1; //phy error -+ else -+ return 0; -+} -+ -+/* -+ * Show all mii registers - this routine is used for test -+ */ -+#ifdef DEBUG -+static void mii_db_out(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ unsigned int mii_test; -+ -+ mii_test = mdio_read(dev,np->valid_phy,MII_BMCR); -+ DBPRINTK("BMCR ====> 0x%4.4x \n",mii_test); -+ -+ mii_test = mdio_read(dev,np->valid_phy,MII_BMSR); -+ DBPRINTK("BMSR ====> 0x%4.4x \n",mii_test); -+ -+ mii_test = mdio_read(dev,np->valid_phy,MII_ANAR); -+ DBPRINTK("ANAR ====> 0x%4.4x \n",mii_test); -+ -+ mii_test = mdio_read(dev,np->valid_phy,MII_ANLPAR); -+ DBPRINTK("ANLPAR ====> 0x%4.4x \n",mii_test); -+ -+ mii_test = mdio_read(dev,np->valid_phy,16); -+ DBPRINTK("REG16 ====> 0x%4.4x \n",mii_test); -+ -+ mii_test = mdio_read(dev,np->valid_phy,17); -+ DBPRINTK("REG17 ====> 0x%4.4x \n",mii_test); -+} -+#endif -+ -+/* -+ * Start Auto-Negotiation function for PHY -+ */ -+static int jz_autonet_complete(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ int count; -+ u32 mii_reg1, timeout = 3000; -+ -+ for (count = 0; count < timeout; count++) { -+ mdelay(1); -+ mii_reg1 = mdio_read(dev,np->valid_phy,MII_BMSR); -+ if (mii_reg1 & 0x0020) break; -+ } -+ //mii_db_out(dev); //for debug to display all register of MII -+ if (count >= timeout) -+ return 1; //auto negotiation error -+ else -+ return 0; -+} -+ -+/* -+ * Get current mode of eth phy -+ */ -+static u32 jz_eth_curr_mode(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ unsigned int mii_reg17; -+ u32 flag = 0; -+ -+ mii_reg17 = mdio_read(dev,np->valid_phy,MII_DSCSR); -+ np->media = mii_reg17>>12; -+ if (np->media==8) { -+ infoprintk("%s: Current Operation Mode is [100M Full Duplex]",dev->name); -+ flag = 0; -+ np->full_duplex=1; -+ } -+ if (np->media==4) { -+ infoprintk("%s: Current Operation Mode is [100M Half Duplex]",dev->name); -+ flag = 0; -+ np->full_duplex=0; -+ } -+ if (np->media==2) { -+ infoprintk("%s: Current Operation Mode is [10M Full Duplex]",dev->name); -+ flag = OMR_TTM; -+ np->full_duplex=1; -+ } -+ if (np->media==1) { -+ infoprintk("%s: Current Operation Mode is [10M Half Duplex]",dev->name); -+ flag = OMR_TTM; -+ np->full_duplex=0; -+ } -+ printk("\n"); -+ return flag; -+} -+ -+/* -+ * Ethernet device hardware init -+ * This routine initializes the ethernet device hardware and PHY -+ */ -+static int jz_init_hw(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ struct ethtool_cmd ecmd; -+ u32 mcr, omr; -+ u32 sts, flag = 0; -+ int i; -+ -+ jz_eth_reset(); -+ STOP_ETH; -+#if 0 -+ /* mii operation */ -+ if (jz_phy_reset(dev)) { -+ errprintk("PHY device do not reset!\n"); -+ return -EPERM; // return operation not permitted -+ } -+#endif -+ /* Set MAC address */ -+ writel(le32_to_cpu(*(unsigned long *)&dev->dev_addr[0]), MAC_MAL); -+ writel(le32_to_cpu(*(unsigned long *)&dev->dev_addr[4]), MAC_MAH); -+ printk("%s: JZ On-Chip ethernet (MAC ", dev->name); -+ for (i = 0; i < 5; i++) { -+ printk("%2.2x:", dev->dev_addr[i]); -+ } -+ printk("%2.2x, IRQ %d)\n", dev->dev_addr[i], dev->irq); -+ -+ np->mii_phy_cnt = jz_search_mii_phy(dev); -+ printk("%s: Found %d PHY on JZ MAC\n", dev->name, np->mii_phy_cnt); -+ -+ mii_info.phy_id = np->valid_phy; -+ mii_info.dev = dev; -+ mii_info.mdio_read = &mdio_read; -+ mii_info.mdio_write = &mdio_write; -+ -+ ecmd.speed = SPEED_100; -+ ecmd.duplex = DUPLEX_FULL; -+ ecmd.port = PORT_MII; -+ ecmd.transceiver = XCVR_INTERNAL; -+ ecmd.phy_address = np->valid_phy; -+ ecmd.autoneg = AUTONEG_ENABLE; -+ -+ mii_ethtool_sset(&mii_info,&ecmd); -+ if (jz_autonet_complete(dev)) -+ errprintk("%s: Ethernet Module AutoNegotiation failed\n",dev->name); -+ mii_ethtool_gset(&mii_info,&ecmd); -+ -+ infoprintk("%s: Provide Modes: ",dev->name); -+ for (i = 0; i < 5;i++) -+ if (ecmd.advertising & (1<full_duplex) -+ mcr |= MCR_FDX; -+ mcr |= MCR_BFD | MCR_TE | MCR_RE | MCR_OWD|MCR_HBD; -+ writel(mcr, MAC_MCR); -+// mcr &= (readl(MAC_MCR) & ~(MCR_PM | MCR_PR | MCR_IF | MCR_HO | MCR_HP)); -+// mcr &= 0xffdf; -+// mcr |= 0x0020; -+// writel(mcr, MAC_MCR); -+ -+ /* Set base address of TX and RX descriptors */ -+ writel(np->dma_rx_ring, DMA_RRBA); -+ writel(np->dma_tx_ring, DMA_TRBA); -+ -+ START_ETH; -+ -+ /* set interrupt mask */ -+ writel(IMR_DEFAULT | IMR_ENABLE, DMA_IMR); -+ -+ /* Reset any pending (stale) interrupts */ -+ sts = readl(DMA_STS); -+ writel(sts, DMA_STS); -+ -+ return 0; -+} -+ -+static int jz_eth_open(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ int retval, i; -+ -+ retval = request_irq(dev->irq, jz_eth_interrupt, 0, dev->name, dev); -+ if (retval) { -+ errprintk("%s: unable to get IRQ %d .\n", dev->name, dev->irq); -+ return -EAGAIN; -+ } -+ -+ for (i = 0; i < NUM_RX_DESCS; i++) { -+ np->rx_ring[i].status = cpu_to_le32(R_OWN); -+ np->rx_ring[i].desc1 = cpu_to_le32(RX_BUF_SIZE | RD_RCH); -+ np->rx_ring[i].buf1_addr = cpu_to_le32(np->dma_rx_buf + i*RX_BUF_SIZE); -+ np->rx_ring[i].next_addr = cpu_to_le32(np->dma_rx_ring + (i+1) * sizeof (jz_desc_t)); -+ } -+ np->rx_ring[NUM_RX_DESCS - 1].next_addr = cpu_to_le32(np->dma_rx_ring); -+ -+ for (i = 0; i < NUM_TX_DESCS; i++) { -+ np->tx_ring[i].status = cpu_to_le32(0); -+ np->tx_ring[i].desc1 = cpu_to_le32(TD_TCH); -+ np->tx_ring[i].buf1_addr = 0; -+ np->tx_ring[i].next_addr = cpu_to_le32(np->dma_tx_ring + (i+1) * sizeof (jz_desc_t)); -+ } -+ np->tx_ring[NUM_TX_DESCS - 1].next_addr = cpu_to_le32(np->dma_tx_ring); -+ -+ np->rx_head = 0; -+ np->tx_head = np->tx_tail = 0; -+ -+ jz_init_hw(dev); -+ -+ dev->trans_start = jiffies; -+ netif_start_queue(dev); -+ start_check(dev); -+ -+ return 0; -+} -+ -+static int jz_eth_close(struct net_device *dev) -+{ -+ netif_stop_queue(dev); -+ close_check(dev); -+ STOP_ETH; -+ free_irq(dev->irq, dev); -+ return 0; -+} -+ -+/* -+ * Get the current statistics. -+ * This may be called with the device open or closed. -+ */ -+static struct net_device_stats * jz_eth_get_stats(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ int tmp; -+ -+ tmp = readl(DMA_MFC); // After read clear to zero -+ np->stats.rx_missed_errors += (tmp & MFC_CNT2) + ((tmp & MFC_CNT1) >> 16); -+ -+ return &np->stats; -+} -+ -+/* -+ * ethtool routines -+ */ -+static int jz_ethtool_ioctl(struct net_device *dev, void *useraddr) -+{ -+ struct jz_eth_private *np = dev->priv; -+ u32 ethcmd; -+ -+ /* dev_ioctl() in ../../net/core/dev.c has already checked -+ capable(CAP_NET_ADMIN), so don't bother with that here. */ -+ -+ if (get_user(ethcmd, (u32 *)useraddr)) -+ return -EFAULT; -+ -+ switch (ethcmd) { -+ -+ case ETHTOOL_GDRVINFO: { -+ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; -+ strcpy (info.driver, DRV_NAME); -+ strcpy (info.version, DRV_VERSION); -+ strcpy (info.bus_info, "OCS"); -+ if (copy_to_user (useraddr, &info, sizeof (info))) -+ return -EFAULT; -+ return 0; -+ } -+ -+ /* get settings */ -+ case ETHTOOL_GSET: { -+ struct ethtool_cmd ecmd = { ETHTOOL_GSET }; -+ spin_lock_irq(&np->lock); -+ mii_ethtool_gset(&mii_info, &ecmd); -+ spin_unlock_irq(&np->lock); -+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) -+ return -EFAULT; -+ return 0; -+ } -+ /* set settings */ -+ case ETHTOOL_SSET: { -+ int r; -+ struct ethtool_cmd ecmd; -+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) -+ return -EFAULT; -+ spin_lock_irq(&np->lock); -+ r = mii_ethtool_sset(&mii_info, &ecmd); -+ spin_unlock_irq(&np->lock); -+ return r; -+ } -+ /* restart autonegotiation */ -+ case ETHTOOL_NWAY_RST: { -+ return mii_nway_restart(&mii_info); -+ } -+ /* get link status */ -+ case ETHTOOL_GLINK: { -+ struct ethtool_value edata = {ETHTOOL_GLINK}; -+ edata.data = mii_link_ok(&mii_info); -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+ } -+ -+ /* get message-level */ -+ case ETHTOOL_GMSGLVL: { -+ struct ethtool_value edata = {ETHTOOL_GMSGLVL}; -+ edata.data = debug; -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+ } -+ /* set message-level */ -+ case ETHTOOL_SMSGLVL: { -+ struct ethtool_value edata; -+ if (copy_from_user(&edata, useraddr, sizeof(edata))) -+ return -EFAULT; -+ debug = edata.data; -+ return 0; -+ } -+ -+ -+ default: -+ break; -+ } -+ -+ return -EOPNOTSUPP; -+ -+} -+ -+/* -+ * Config device -+ */ -+static int jz_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -+{ -+ struct jz_eth_private *np =(struct jz_eth_private *)dev->priv; -+ struct mii_ioctl_data *data, rdata; -+ -+ switch (cmd) { -+ case SIOCETHTOOL: -+ return jz_ethtool_ioctl(dev, (void *) rq->ifr_data); -+ case SIOCGMIIPHY: -+ case SIOCDEVPRIVATE: -+ data = (struct mii_ioctl_data *)&rq->ifr_data; -+ data->phy_id = np->valid_phy; -+ case SIOCGMIIREG: -+ case SIOCDEVPRIVATE+1: -+ data = (struct mii_ioctl_data *)&rq->ifr_data; -+ data->val_out = mdio_read(dev,np->valid_phy, data->reg_num & 0x1f); -+ return 0; -+ case SIOCSMIIREG: -+ case SIOCDEVPRIVATE+2: -+ data = (struct mii_ioctl_data *)&rq->ifr_data; -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ mdio_write(dev,np->valid_phy, data->reg_num & 0x1f, data->val_in); -+ return 0; -+ case READ_COMMAND: -+ data = (struct mii_ioctl_data *)rq->ifr_data; -+ if (copy_from_user(&rdata,data,sizeof(rdata))) -+ return -EFAULT; -+ rdata.val_out = mdio_read(dev,rdata.phy_id, rdata.reg_num & 0x1f); -+ if (copy_to_user(data,&rdata,sizeof(rdata))) -+ return -EFAULT; -+ return 0; -+ case WRITE_COMMAND: -+ if (np->phy_type==1) { -+ data = (struct mii_ioctl_data *)rq->ifr_data; -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ if (copy_from_user(&rdata,data,sizeof(rdata))) -+ return -EFAULT; -+ mdio_write(dev,rdata.phy_id, rdata.reg_num & 0x1f, rdata.val_in); -+ } -+ return 0; -+ case GETDRIVERINFO: -+ if (np->phy_type==1) { -+ data = (struct mii_ioctl_data *)rq->ifr_data; -+ if (copy_from_user(&rdata,data,sizeof(rdata))) -+ return -EFAULT; -+ rdata.val_in = 0x1; -+ rdata.val_out = 0x00d0; -+ if (copy_to_user(data,&rdata,sizeof(rdata))) -+ return -EFAULT; -+ } -+ return 0; -+ default: -+ return -EOPNOTSUPP; -+ } -+ return 0; -+} -+ -+/* -+ * Received one packet -+ */ -+static void eth_rxready(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private*)dev->priv; -+ struct sk_buff *skb; -+ unsigned char *pkt_ptr; -+ u32 pkt_len; -+ u32 status; -+ -+ status = le32_to_cpu(np->rx_ring[np->rx_head].status); -+ while (!(status & R_OWN)) { /* owner bit = 0 */ -+ if (status & RD_ES) { /* error summary */ -+ np->stats.rx_errors++; /* Update the error stats. */ -+ if (status & (RD_RF | RD_TL)) -+ np->stats.rx_frame_errors++; -+ if (status & RD_CE) -+ np->stats.rx_crc_errors++; -+ if (status & RD_TL) -+ np->stats.rx_length_errors++; -+ } else { -+ pkt_ptr = bus_to_virt(le32_to_cpu(np->rx_ring[np->rx_head].buf1_addr)); -+ pkt_len = ((status & RD_FL) >> 16) - 4; -+ -+ skb = dev_alloc_skb(pkt_len + 2); -+ if (skb == NULL) { -+ printk("%s: Memory squeeze, dropping.\n", -+ dev->name); -+ np->stats.rx_dropped++; -+ break; -+ } -+ skb->dev = dev; -+ skb_reserve(skb, 2); /* 16 byte align */ -+ -+ //pkt_ptr = P1ADDR(pkt_ptr); -+ //dma_cache_inv(pkt_ptr, pkt_len); -+ memcpy(skb->data, pkt_ptr, pkt_len); -+ skb_put(skb, pkt_len); -+ -+ //eth_dbg_rx(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb,dev); -+ netif_rx(skb); /* pass the packet to upper layers */ -+ dev->last_rx = jiffies; -+ np->stats.rx_packets++; -+ np->stats.rx_bytes += pkt_len; -+ } -+ np->rx_ring[np->rx_head].status = cpu_to_le32(R_OWN); -+ -+ np->rx_head ++; -+ if (np->rx_head >= NUM_RX_DESCS) -+ np->rx_head = 0; -+ status = le32_to_cpu(np->rx_ring[np->rx_head].status); -+ } -+} -+ -+/* -+ * Tx timeout routine -+ */ -+static void jz_eth_tx_timeout(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ -+ jz_init_hw(dev); -+ np->stats.tx_errors ++; -+ netif_wake_queue(dev); -+} -+ -+/* -+ * One packet was transmitted -+ */ -+static void eth_txdone(struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private*)dev->priv; -+ int tx_tail = np->tx_tail; -+ -+ while (tx_tail != np->tx_head) { -+ int entry = tx_tail % NUM_TX_DESCS; -+ s32 status = le32_to_cpu(np->tx_ring[entry].status); -+ if(status < 0) break; -+ if (status & TD_ES ) { /* Error summary */ -+ np->stats.tx_errors++; -+ if (status & TD_NC) np->stats.tx_carrier_errors++; -+ if (status & TD_LC) np->stats.tx_window_errors++; -+ if (status & TD_UF) np->stats.tx_fifo_errors++; -+ if (status & TD_DE) np->stats.tx_aborted_errors++; -+ if (np->tx_head != np->tx_tail) -+ writel(1, DMA_TPD); /* Restart a stalled TX */ -+ } else -+ np->stats.tx_packets++; -+ /* Update the collision counter */ -+ np->stats.collisions += ((status & TD_EC) ? 16 : ((status & TD_CC) >> 3)); -+ /* Free the original skb */ -+ if (np->tx_skb[entry]) { -+ dev_kfree_skb_irq(np->tx_skb[entry]); -+ np->tx_skb[entry] = 0; -+ } -+ tx_tail++; -+ } -+ if (np->tx_full && (tx_tail + NUM_TX_DESCS > np->tx_head + 1)) { -+ /* The ring is no longer full */ -+ np->tx_full = 0; -+ netif_start_queue(dev); -+ } -+ np->tx_tail = tx_tail; -+} -+ -+/* -+ * Update the tx descriptor -+ */ -+static void load_tx_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ int entry = np->tx_head % NUM_TX_DESCS; -+ -+ np->tx_ring[entry].buf1_addr = cpu_to_le32(virt_to_bus(buf)); -+ np->tx_ring[entry].desc1 &= cpu_to_le32((TD_TER | TD_TCH)); -+ np->tx_ring[entry].desc1 |= cpu_to_le32(flags); -+ np->tx_ring[entry].status = cpu_to_le32(T_OWN); -+ np->tx_skb[entry] = skb; -+} -+ -+/* -+ * Transmit one packet -+ */ -+static int jz_eth_send_packet(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -+ u32 length; -+ -+ if (np->tx_full) { -+ return 0; -+ } -+#ifdef CONFIG_FPGA -+ mdelay(10); -+#else -+ udelay(500); /* FIXME: can we remove this delay ? */ -+#endif -+ length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; -+ dma_cache_wback((unsigned long)skb->data, length); -+ load_tx_packet(dev, (char *)skb->data, TD_IC | TD_LS | TD_FS | length, skb); -+ spin_lock_irq(&np->lock); -+ np->tx_head ++; -+ np->stats.tx_bytes += length; -+ writel(1, DMA_TPD); /* Start the TX */ -+ dev->trans_start = jiffies; /* for timeout */ -+ if (np->tx_tail + NUM_TX_DESCS > np->tx_head + 1) { -+ np->tx_full = 0; -+ } -+ else { -+ np->tx_full = 1; -+ netif_stop_queue(dev); -+ } -+ spin_unlock_irq(&np->lock); -+ -+ return 0; -+} -+ -+/* -+ * Interrupt service routine -+ */ -+static irqreturn_t jz_eth_interrupt(int irq, void *dev_id) -+{ -+ struct net_device *dev = (struct net_device *)dev_id; -+ struct jz_eth_private *np = dev->priv; -+ u32 sts; -+ int i; -+ -+ spin_lock(&np->lock); -+ -+ writel((readl(DMA_IMR) & ~IMR_ENABLE), DMA_IMR); /* Disable interrupt */ -+ -+ for (i = 0; i < 100; i++) { -+ sts = readl(DMA_STS); -+ writel(sts, DMA_STS); /* clear status */ -+ -+ if (!(sts & IMR_DEFAULT)) break; -+ -+ if (sts & (DMA_INT_RI | DMA_INT_RU)) /* Rx IRQ */ -+ eth_rxready(dev); -+ if (sts & (DMA_INT_TI | DMA_INT_TU)) /* Tx IRQ */ -+ eth_txdone(dev); -+ -+ /* check error conditions */ -+ if (sts & DMA_INT_FB){ /* fatal bus error */ -+ STOP_ETH; -+ errprintk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",dev->name, sts); -+ break; -+ } -+ -+ if (sts & DMA_INT_UN) { /* Transmit underrun */ -+ u32 omr; -+ omr = readl(DMA_OMR); -+ if (!(omr & OMR_SF)) { -+ omr &= ~(OMR_ST | OMR_SR); -+ writel(omr, DMA_OMR); -+ while (readl(DMA_STS) & STS_TS); /* wait for stop */ -+ if ((omr & OMR_TR) < OMR_TR) { /* ? */ -+ omr += TR_24; -+ } else { -+ omr |= OMR_SF; -+ } -+ writel(omr | OMR_ST | OMR_SR, DMA_OMR); -+ } -+ } -+ } -+ -+ writel(readl(DMA_IMR) | IMR_ENABLE, DMA_IMR); /* enable interrupt */ -+ -+ spin_unlock(&np->lock); -+ -+ return IRQ_HANDLED; -+} -+ -+#if 0 //def CONFIG_PM -+/* -+ * Suspend the ETH interface. -+ */ -+static int jz_eth_suspend(struct net_device *dev, int state) -+{ -+ struct jz_eth_private *jep = (struct jz_eth_private *)dev->priv; -+ unsigned long flags, tmp; -+ -+ printk("ETH suspend.\n"); -+ -+ if (!netif_running(dev)) { -+ return 0; -+ } -+ -+ netif_device_detach(dev); -+ -+ spin_lock_irqsave(&jep->lock, flags); -+ -+ /* Disable interrupts, stop Tx and Rx. */ -+ REG32(DMA_IMR) = 0; -+ STOP_ETH; -+ -+ /* Update the error counts. */ -+ tmp = REG32(DMA_MFC); -+ jep->stats.rx_missed_errors += (tmp & 0x1ffff); -+ jep->stats.rx_fifo_errors += ((tmp >> 17) & 0x7ff); -+ -+ spin_unlock_irqrestore(&jep->lock, flags); -+ -+ return 0; -+} -+ -+/* -+ * Resume the ETH interface. -+ */ -+static int jz_eth_resume(struct net_device *dev) -+{ -+ printk("ETH resume.\n"); -+ -+ if (!netif_running(dev)) -+ return 0; -+ -+ jz_init_hw(dev); -+ -+ netif_device_attach(dev); -+ jz_eth_tx_timeout(dev); -+ netif_wake_queue(dev); -+ -+ return 0; -+} -+ -+static int jz_eth_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) -+{ -+ int ret; -+ -+ if (!dev->data) -+ return -EINVAL; -+ -+ switch (rqst) { -+ case PM_SUSPEND: -+ ret = jz_eth_suspend((struct net_device *)dev->data, -+ (int)data); -+ break; -+ -+ case PM_RESUME: -+ ret = jz_eth_resume((struct net_device *)dev->data); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+#endif /* CONFIG_PM */ -+ -+static int __init jz_eth_init(void) -+{ -+ struct net_device *dev; -+ struct jz_eth_private *np; -+ int err; -+ -+ dev = alloc_etherdev(sizeof(struct jz_eth_private)); -+ if (!dev) { -+ printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); -+ return -ENOMEM; -+ } -+ netdev = dev; -+ -+ np = (struct jz_eth_private *)P2ADDR(dev->priv); -+ dev->priv = np; -+ memset(np, 0, sizeof(struct jz_eth_private)); -+ -+ np->vaddr_rx_buf = (u32)dma_alloc_noncoherent(NULL, NUM_RX_DESCS*RX_BUF_SIZE, -+ &np->dma_rx_buf, 0); -+ -+ if (!np->vaddr_rx_buf) { -+ printk(KERN_ERR "%s: Cannot alloc dma buffers\n", DRV_NAME); -+ unregister_netdev(dev); -+ free_netdev(dev); -+ return -ENOMEM; -+ } -+ -+ np->dma_rx_ring = virt_to_bus(np->rx_ring); -+ np->dma_tx_ring = virt_to_bus(np->tx_ring); -+ np->full_duplex = 1; -+ np->link_state = 1; -+ -+ spin_lock_init(&np->lock); -+ -+ ether_setup(dev); -+ dev->irq = IRQ_ETH; -+ dev->open = jz_eth_open; -+ dev->stop = jz_eth_close; -+ dev->hard_start_xmit = jz_eth_send_packet; -+ dev->get_stats = jz_eth_get_stats; -+ dev->set_multicast_list = jz_set_multicast_list; -+ dev->do_ioctl = jz_eth_ioctl; -+ dev->tx_timeout = jz_eth_tx_timeout; -+ dev->watchdog_timeo = ETH_TX_TIMEOUT; -+ -+ /* configure MAC address */ -+ get_mac_address(dev); -+ -+ if ((err = register_netdev(dev)) != 0) { -+ printk(KERN_ERR "%s: Cannot register net device, error %d\n", -+ DRV_NAME, err); -+ free_netdev(dev); -+ return -ENOMEM; -+ } -+ -+//#ifdef 0 //CONFIG_PM -+// np->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, jz_eth_pm_callback); -+// if (np->pmdev) -+// np->pmdev->data = dev; -+//#endif -+ -+ return 0; -+} -+ -+static void __exit jz_eth_exit(void) -+{ -+ struct net_device *dev = netdev; -+ struct jz_eth_private *np = dev->priv; -+ -+ unregister_netdev(dev); -+ dma_free_noncoherent(NULL, NUM_RX_DESCS * RX_BUF_SIZE, -+ (void *)np->vaddr_rx_buf, np->dma_rx_buf); -+ free_netdev(dev); -+} -+ -+module_init(jz_eth_init); -+module_exit(jz_eth_exit); -diff --git a/drivers/net/jz_eth.h b/drivers/net/jz_eth.h -new file mode 100644 -index 0000000..cb8486e ---- /dev/null -+++ b/drivers/net/jz_eth.h -@@ -0,0 +1,403 @@ -+/* -+ * linux/drivers/net/jz_eth.h -+ * -+ * Jz4730/Jz5730 On-Chip ethernet driver. -+ * -+ * Copyright (C) 2005 - 2007 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+#ifndef __JZ_ETH_H__ -+#define __JZ_ETH_H__ -+ -+/* DMA control and status registers */ -+#define DMA_BMR (ETH_BASE + 0x1000) // Bus mode -+#define DMA_TPD (ETH_BASE + 0x1004) // Transmit poll demand register -+#define DMA_RPD (ETH_BASE + 0x1008) // Receieve poll demand register -+#define DMA_RRBA (ETH_BASE + 0x100C) // Receieve descriptor base address -+#define DMA_TRBA (ETH_BASE + 0x1010) // Transmit descriptor base address -+#define DMA_STS (ETH_BASE + 0x1014) // Status register -+#define DMA_OMR (ETH_BASE + 0x1018) // Command register -+#define DMA_IMR (ETH_BASE + 0x101C) -+#define DMA_MFC (ETH_BASE + 0x1020) -+ -+/* DMA CSR8-CSR19 reserved */ -+#define DMA_CTA (ETH_BASE + 0x1050) -+#define DMA_CRA (ETH_BASE + 0x1054) -+ -+/* Mac control and status registers */ -+#define MAC_MCR (ETH_BASE + 0x0000) -+#define MAC_MAH (ETH_BASE + 0x0004) -+#define MAC_MAL (ETH_BASE + 0x0008) -+#define MAC_HTH (ETH_BASE + 0x000C) -+#define MAC_HTL (ETH_BASE + 0x0010) -+#define MAC_MIIA (ETH_BASE + 0x0014) -+#define MAC_MIID (ETH_BASE + 0x0018) -+#define MAC_FCR (ETH_BASE + 0x001C) -+#define MAC_VTR1 (ETH_BASE + 0x0020) -+#define MAC_VTR2 (ETH_BASE + 0x0024) -+ -+/* -+ * Bus Mode Register (DMA_BMR) -+ */ -+#define BMR_PBL 0x00003f00 /* Programmable Burst Length */ -+#define BMR_DSL 0x0000007c /* Descriptor Skip Length */ -+#define BMR_BAR 0x00000002 /* Bus ARbitration */ -+#define BMR_SWR 0x00000001 /* Software Reset */ -+ -+#define PBL_0 0x00000000 /* DMA burst length = amount in RX FIFO */ -+#define PBL_1 0x00000100 /* 1 longword DMA burst length */ -+#define PBL_2 0x00000200 /* 2 longwords DMA burst length */ -+#define PBL_4 0x00000400 /* 4 longwords DMA burst length */ -+#define PBL_8 0x00000800 /* 8 longwords DMA burst length */ -+#define PBL_16 0x00001000 /* 16 longwords DMA burst length */ -+#define PBL_32 0x00002000 /* 32 longwords DMA burst length */ -+ -+#define DSL_0 0x00000000 /* 0 longword / descriptor */ -+#define DSL_1 0x00000004 /* 1 longword / descriptor */ -+#define DSL_2 0x00000008 /* 2 longwords / descriptor */ -+#define DSL_4 0x00000010 /* 4 longwords / descriptor */ -+#define DSL_8 0x00000020 /* 8 longwords / descriptor */ -+#define DSL_16 0x00000040 /* 16 longwords / descriptor */ -+#define DSL_32 0x00000080 /* 32 longwords / descriptor */ -+ -+/* -+ * Status Register (DMA_STS) -+ */ -+#define STS_BE 0x03800000 /* Bus Error Bits */ -+#define STS_TS 0x00700000 /* Transmit Process State */ -+#define STS_RS 0x000e0000 /* Receive Process State */ -+ -+#define TS_STOP 0x00000000 /* Stopped */ -+#define TS_FTD 0x00100000 /* Running Fetch Transmit Descriptor */ -+#define TS_WEOT 0x00200000 /* Running Wait for End Of Transmission */ -+#define TS_QDAT 0x00300000 /* Running Queue skb data into TX FIFO */ -+#define TS_RES 0x00400000 /* Reserved */ -+#define TS_SPKT 0x00500000 /* Reserved */ -+#define TS_SUSP 0x00600000 /* Suspended */ -+#define TS_CLTD 0x00700000 /* Running Close Transmit Descriptor */ -+ -+#define RS_STOP 0x00000000 /* Stopped */ -+#define RS_FRD 0x00020000 /* Running Fetch Receive Descriptor */ -+#define RS_CEOR 0x00040000 /* Running Check for End of Receive Packet */ -+#define RS_WFRP 0x00060000 /* Running Wait for Receive Packet */ -+#define RS_SUSP 0x00080000 /* Suspended */ -+#define RS_CLRD 0x000a0000 /* Running Close Receive Descriptor */ -+#define RS_FLUSH 0x000c0000 /* Running Flush RX FIFO */ -+#define RS_QRFS 0x000e0000 /* Running Queue RX FIFO into RX Skb */ -+ -+/* -+ * Operation Mode Register (DMA_OMR) -+ */ -+#define OMR_TTM 0x00400000 /* Transmit Threshold Mode */ -+#define OMR_SF 0x00200000 /* Store and Forward */ -+#define OMR_TR 0x0000c000 /* Threshold Control Bits */ -+#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ -+#define OMR_OSF 0x00000004 /* Operate on Second Frame */ -+#define OMR_SR 0x00000002 /* Start/Stop Receive */ -+ -+#define TR_18 0x00000000 /* Threshold set to 18 (32) bytes */ -+#define TR_24 0x00004000 /* Threshold set to 24 (64) bytes */ -+#define TR_32 0x00008000 /* Threshold set to 32 (128) bytes */ -+#define TR_40 0x0000c000 /* Threshold set to 40 (256) bytes */ -+ -+/* -+ * Missed Frames Counters (DMA_MFC) -+ */ -+//#define MFC_CNT1 0xffff0000 /* Missed Frames Counter Bits by application */ -+#define MFC_CNT1 0x0ffe0000 /* Missed Frames Counter Bits by application */ -+#define MFC_CNT2 0x0000ffff /* Missed Frames Counter Bits by controller */ -+ -+/* -+ * Mac control Register (MAC_MCR) -+ */ -+#define MCR_RA 0x80000000 /* Receive All */ -+#define MCR_HBD 0x10000000 /* HeartBeat Disable */ -+#define MCR_PS 0x08000000 /* Port Select */ -+#define MCR_OWD 0x00800000 /* Receive own Disable */ -+#define MCR_OM 0x00600000 /* Operating(loopback) Mode */ -+#define MCR_FDX 0x00100000 /* Full Duplex Mode */ -+#define MCR_PM 0x00080000 /* Pass All Multicast */ -+#define MCR_PR 0x00040000 /* Promiscuous Mode */ -+#define MCR_IF 0x00020000 /* Inverse Filtering */ -+#define MCR_PB 0x00010000 /* Pass Bad Frames */ -+#define MCR_HO 0x00008000 /* Hash Only Filtering Mode */ -+#define MCR_HP 0x00002000 /* Hash/Perfect Receive Filtering Mode */ -+#define MCR_FC 0x00001000 /* Late Collision control */ -+#define MCR_BFD 0x00000800 /* Boardcast frame Disable */ -+#define MCR_RED 0x00000400 /* Retry Disable */ -+#define MCR_APS 0x00000100 /* Automatic pad stripping */ -+#define MCR_BL 0x000000c0 /* Back off Limit */ -+#define MCR_DC 0x00000020 /* Deferral check */ -+#define MCR_TE 0x00000008 /* Transmitter enable */ -+#define MCR_RE 0x00000004 /* Receiver enable */ -+ -+#define MCR_MII_10 ( OMR_TTM | MCR_PS) -+#define MCR_MII_100 ( MCR_HBD | MCR_PS) -+ -+/* Flow control Register (MAC_FCR) */ -+#define FCR_PT 0xffff0000 /* Pause time */ -+#define FCR_PCF 0x00000004 /* Pass control frames */ -+#define FCR_FCE 0x00000002 /* Flow control enable */ -+#define FCR_FCB 0x00000001 /* Flow control busy */ -+ -+ -+/* Constants for the interrupt mask and -+ * interrupt status registers. (DMA_SIS and DMA_IMR) -+ */ -+#define DMA_INT_NI 0x00010000 // Normal interrupt summary -+#define DMA_INT_AI 0x00008000 // Abnormal interrupt summary -+#define DMA_INT_ER 0x00004000 // Early receive interrupt -+#define DMA_INT_FB 0x00002000 // Fatal bus error -+#define DMA_INT_ET 0x00000400 // Early transmit interrupt -+#define DMA_INT_RW 0x00000200 // Receive watchdog timeout -+#define DMA_INT_RS 0x00000100 // Receive stop -+#define DMA_INT_RU 0x00000080 // Receive buffer unavailble -+#define DMA_INT_RI 0x00000040 // Receive interrupt -+#define DMA_INT_UN 0x00000020 // Underflow -+#define DMA_INT_TJ 0x00000008 // Transmit jabber timeout -+#define DMA_INT_TU 0x00000004 // Transmit buffer unavailble -+#define DMA_INT_TS 0x00000002 // Transmit stop -+#define DMA_INT_TI 0x00000001 // Transmit interrupt -+ -+/* -+ * Receive Descriptor Bit Summary -+ */ -+#define R_OWN 0x80000000 /* Own Bit */ -+#define RD_FF 0x40000000 /* Filtering Fail */ -+#define RD_FL 0x3fff0000 /* Frame Length */ -+#define RD_ES 0x00008000 /* Error Summary */ -+#define RD_DE 0x00004000 /* Descriptor Error */ -+#define RD_LE 0x00001000 /* Length Error */ -+#define RD_RF 0x00000800 /* Runt Frame */ -+#define RD_MF 0x00000400 /* Multicast Frame */ -+#define RD_FS 0x00000200 /* First Descriptor */ -+#define RD_LS 0x00000100 /* Last Descriptor */ -+#define RD_TL 0x00000080 /* Frame Too Long */ -+#define RD_CS 0x00000040 /* Collision Seen */ -+#define RD_FT 0x00000020 /* Frame Type */ -+#define RD_RJ 0x00000010 /* Receive Watchdog timeout*/ -+#define RD_RE 0x00000008 /* Report on MII Error */ -+#define RD_DB 0x00000004 /* Dribbling Bit */ -+#define RD_CE 0x00000002 /* CRC Error */ -+ -+#define RD_RER 0x02000000 /* Receive End Of Ring */ -+#define RD_RCH 0x01000000 /* Second Address Chained */ -+#define RD_RBS2 0x003ff800 /* Buffer 2 Size */ -+#define RD_RBS1 0x000007ff /* Buffer 1 Size */ -+ -+/* -+ * Transmit Descriptor Bit Summary -+ */ -+#define T_OWN 0x80000000 /* Own Bit */ -+#define TD_ES 0x00008000 /* Frame Aborted (error summary)*/ -+#define TD_LO 0x00000800 /* Loss Of Carrier */ -+#define TD_NC 0x00000400 /* No Carrier */ -+#define TD_LC 0x00000200 /* Late Collision */ -+#define TD_EC 0x00000100 /* Excessive Collisions */ -+#define TD_HF 0x00000080 /* Heartbeat Fail */ -+#define TD_CC 0x0000003c /* Collision Counter */ -+#define TD_UF 0x00000002 /* Underflow Error */ -+#define TD_DE 0x00000001 /* Deferred */ -+ -+#define TD_IC 0x80000000 /* Interrupt On Completion */ -+#define TD_LS 0x40000000 /* Last Segment */ -+#define TD_FS 0x20000000 /* First Segment */ -+#define TD_FT1 0x10000000 /* Filtering Type */ -+#define TD_SET 0x08000000 /* Setup Packet */ -+#define TD_AC 0x04000000 /* Add CRC Disable */ -+#define TD_TER 0x02000000 /* Transmit End Of Ring */ -+#define TD_TCH 0x01000000 /* Second Address Chained */ -+#define TD_DPD 0x00800000 /* Disabled Padding */ -+#define TD_FT0 0x00400000 /* Filtering Type */ -+#define TD_TBS2 0x003ff800 /* Buffer 2 Size */ -+#define TD_TBS1 0x000007ff /* Buffer 1 Size */ -+ -+#define PERFECT_F 0x00000000 -+#define HASH_F TD_FT0 -+#define INVERSE_F TD_FT1 -+#define HASH_O_F (TD_FT1 | TD_F0) -+ -+/* -+ * Constant setting -+ */ -+ -+#define IMR_DEFAULT ( DMA_INT_TI | DMA_INT_RI | \ -+ DMA_INT_TS | DMA_INT_RS | \ -+ DMA_INT_TU | DMA_INT_RU | \ -+ DMA_INT_FB ) -+ -+#define IMR_ENABLE (DMA_INT_NI | DMA_INT_AI) -+ -+#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -+#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ -+ -+#define HASH_TABLE_LEN 512 /* Bits */ -+#define HASH_BITS 0x01ff /* 9 LS bits */ -+ -+#define SETUP_FRAME_LEN 192 /* Bytes */ -+#define IMPERF_PA_OFFSET 156 /* Bytes */ -+ -+/* -+ * Address Filtering Modes -+ */ -+#define PERFECT 0 /* 16 perfect physical addresses */ -+#define HASH_PERF 1 /* 1 perfect, 512 multicast addresses */ -+#define PERFECT_REJ 2 /* Reject 16 perfect physical addresses */ -+#define ALL_HASH 3 /* Hashes all physical & multicast addrs */ -+ -+#define ALL 0 /* Clear out all the setup frame */ -+#define PHYS_ADDR_ONLY 1 /* Update the physical address only */ -+ -+/* MII register */ -+#define MII_BMCR 0x00 /* MII Basic Mode Control Register */ -+#define MII_BMSR 0x01 /* MII Basic Mode Status Register */ -+#define MII_ID1 0x02 /* PHY Identifier Register 1 */ -+#define MII_ID2 0x03 /* PHY Identifier Register 2 */ -+#define MII_ANAR 0x04 /* Auto Negotiation Advertisement Register */ -+#define MII_ANLPAR 0x05 /* Auto Negotiation Link Partner Ability */ -+#define MII_ANER 0x06 /* Auto Negotiation Expansion */ -+#define MII_DSCR 0x10 /* Davicom Specified Configration Register */ -+#define MII_DSCSR 0x11 /* Davicom Specified Configration/Status Register */ -+#define MII_10BTCSR 0x12 /* 10base-T Specified Configration/Status Register */ -+ -+ -+#define MII_PREAMBLE 0xffffffff /* MII Management Preamble */ -+#define MII_TEST 0xaaaaaaaa /* MII Test Signal */ -+#define MII_STRD 0x06 /* Start of Frame+Op Code: use low nibble */ -+#define MII_STWR 0x0a /* Start of Frame+Op Code: use low nibble */ -+ -+/* -+ * MII Management Control Register -+ */ -+#define MII_CR_RST 0x8000 /* RESET the PHY chip */ -+#define MII_CR_LPBK 0x4000 /* Loopback enable */ -+#define MII_CR_SPD 0x2000 /* 0: 10Mb/s; 1: 100Mb/s */ -+#define MII_CR_ASSE 0x1000 /* Auto Speed Select Enable */ -+#define MII_CR_PD 0x0800 /* Power Down */ -+#define MII_CR_ISOL 0x0400 /* Isolate Mode */ -+#define MII_CR_RAN 0x0200 /* Restart Auto Negotiation */ -+#define MII_CR_FDM 0x0100 /* Full Duplex Mode */ -+#define MII_CR_CTE 0x0080 /* Collision Test Enable */ -+ -+/* -+ * MII Management Status Register -+ */ -+#define MII_SR_T4C 0x8000 /* 100BASE-T4 capable */ -+#define MII_SR_TXFD 0x4000 /* 100BASE-TX Full Duplex capable */ -+#define MII_SR_TXHD 0x2000 /* 100BASE-TX Half Duplex capable */ -+#define MII_SR_TFD 0x1000 /* 10BASE-T Full Duplex capable */ -+#define MII_SR_THD 0x0800 /* 10BASE-T Half Duplex capable */ -+#define MII_SR_ASSC 0x0020 /* Auto Speed Selection Complete*/ -+#define MII_SR_RFD 0x0010 /* Remote Fault Detected */ -+#define MII_SR_ANC 0x0008 /* Auto Negotiation capable */ -+#define MII_SR_LKS 0x0004 /* Link Status */ -+#define MII_SR_JABD 0x0002 /* Jabber Detect */ -+#define MII_SR_XC 0x0001 /* Extended Capabilities */ -+ -+/* -+ * MII Management Auto Negotiation Advertisement Register -+ */ -+#define MII_ANA_TAF 0x03e0 /* Technology Ability Field */ -+#define MII_ANA_T4AM 0x0200 /* T4 Technology Ability Mask */ -+#define MII_ANA_TXAM 0x0180 /* TX Technology Ability Mask */ -+#define MII_ANA_FDAM 0x0140 /* Full Duplex Technology Ability Mask */ -+#define MII_ANA_HDAM 0x02a0 /* Half Duplex Technology Ability Mask */ -+#define MII_ANA_100M 0x0380 /* 100Mb Technology Ability Mask */ -+#define MII_ANA_10M 0x0060 /* 10Mb Technology Ability Mask */ -+#define MII_ANA_CSMA 0x0001 /* CSMA-CD Capable */ -+ -+/* -+ * MII Management Auto Negotiation Remote End Register -+ */ -+#define MII_ANLPA_NP 0x8000 /* Next Page (Enable) */ -+#define MII_ANLPA_ACK 0x4000 /* Remote Acknowledge */ -+#define MII_ANLPA_RF 0x2000 /* Remote Fault */ -+#define MII_ANLPA_TAF 0x03e0 /* Technology Ability Field */ -+#define MII_ANLPA_T4AM 0x0200 /* T4 Technology Ability Mask */ -+#define MII_ANLPA_TXAM 0x0180 /* TX Technology Ability Mask */ -+#define MII_ANLPA_FDAM 0x0140 /* Full Duplex Technology Ability Mask */ -+#define MII_ANLPA_HDAM 0x02a0 /* Half Duplex Technology Ability Mask */ -+#define MII_ANLPA_100M 0x0380 /* 100Mb Technology Ability Mask */ -+#define MII_ANLPA_10M 0x0060 /* 10Mb Technology Ability Mask */ -+#define MII_ANLPA_CSMA 0x0001 /* CSMA-CD Capable */ -+ -+/* -+ * MII Management DAVICOM Specified Configuration And Status Register -+ */ -+#define MII_DSCSR_100FDX 0x8000 /* 100M Full Duplex Operation Mode */ -+#define MII_DSCSR_100HDX 0x4000 /* 100M Half Duplex Operation Mode */ -+#define MII_DSCSR_10FDX 0x2000 /* 10M Full Duplex Operation Mode */ -+#define MII_DSCSR_10HDX 0x1000 /* 10M Half Duplex Operation Mode */ -+#define MII_DSCSR_ANMB 0x000f /* Auto-Negotiation Monitor Bits */ -+ -+ -+/* -+ * Used by IOCTL -+ */ -+#define READ_COMMAND (SIOCDEVPRIVATE+4) -+#define WRITE_COMMAND (SIOCDEVPRIVATE+5) -+#define GETDRIVERINFO (SIOCDEVPRIVATE+6) -+ -+/* -+ * Device data and structure -+ */ -+ -+#define ETH_TX_TIMEOUT (6*HZ) -+ -+#define RX_BUF_SIZE 1536 -+ -+#define NUM_RX_DESCS 32 -+#define NUM_TX_DESCS 16 -+ -+static const char *media_types[] = { -+ "10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ", -+ "100baseTx-FD", "100baseT4", 0 -+}; -+ -+typedef struct { -+ unsigned int status; -+ unsigned int desc1; -+ unsigned int buf1_addr; -+ unsigned int next_addr; -+} jz_desc_t; -+ -+struct jz_eth_private { -+ jz_desc_t tx_ring[NUM_TX_DESCS]; /* transmit descriptors */ -+ jz_desc_t rx_ring[NUM_RX_DESCS]; /* receive descriptors */ -+ dma_addr_t dma_tx_ring; /* bus address of tx ring */ -+ dma_addr_t dma_rx_ring; /* bus address of rx ring */ -+ dma_addr_t dma_rx_buf; /* DMA address of rx buffer */ -+ unsigned int vaddr_rx_buf; /* virtual address of rx buffer */ -+ -+ unsigned int rx_head; /* first rx descriptor */ -+ unsigned int tx_head; /* first tx descriptor */ -+ unsigned int tx_tail; /* last unacked transmit packet */ -+ unsigned int tx_full; /* transmit buffers are full */ -+ struct sk_buff *tx_skb[NUM_TX_DESCS]; /* skbuffs for packets to transmit */ -+ -+ struct net_device_stats stats; -+ spinlock_t lock; -+ -+ int media; /* Media (eg TP), mode (eg 100B)*/ -+ int full_duplex; /* Current duplex setting. */ -+ int link_state; -+ char phys[32]; /* List of attached PHY devices */ -+ char valid_phy; /* Current linked phy-id with MAC */ -+ int mii_phy_cnt; -+ int phy_type; /* 1-RTL8309,0-DVCOM */ -+ struct ethtool_cmd ecmds[32]; -+ u16 advertising; /* NWay media advertisement */ -+ -+ pid_t thr_pid; /* Link cheak thread ID */ -+ int thread_die; -+ struct completion thr_exited; -+ wait_queue_head_t thr_wait; -+ -+ struct pm_dev *pmdev; -+}; -+ -+#endif /* __JZ_ETH_H__ */ -diff --git a/drivers/net/jzcs8900a.c b/drivers/net/jzcs8900a.c -new file mode 100644 -index 0000000..db345d0 ---- /dev/null -+++ b/drivers/net/jzcs8900a.c -@@ -0,0 +1,649 @@ -+ -+/* -+ * linux/drivers/net/jzcs8900a.c -+ * -+ * Author: Lucifer -+ * -+ * A Cirrus Logic CS8900A driver for Linux -+ * based on the cs89x0 driver written by Russell Nelson, -+ * Donald Becker, and others. -+ * -+ * This source code 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. -+ */ -+ -+/* -+ * At the moment the driver does not support memory mode operation. -+ * It is trivial to implement this, but not worth the effort. -+ */ -+ -+/* -+ * TODO: -+ * -+ * 1. If !ready in send_start(), queue buffer and send it in interrupt handler -+ * when we receive a BufEvent with Rdy4Tx, send it again. dangerous! -+ * 2. how do we prevent interrupt handler destroying integrity of get_stats()? -+ * 3. Change reset code to check status. -+ * 4. Implement set_mac_address and remove fake mac address -+ * 5. Link status detection stuff -+ * 6. Write utility to write EEPROM, do self testing, etc. -+ * 7. Implement DMA routines (I need a board w/ DMA support for that) -+ * 8. Power management -+ * 9. Add support for multiple ethernet chips -+ * 10. Add support for other cs89xx chips (need hardware for that) -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jzcs8900a.h" -+ -+#define FULL_DUPLEX -+#define INT_PIN 0 -+#ifdef CONFIG_SOC_JZ4740 -+#define CIRRUS_DEFAULT_IO 0xa8000000 -+#define CIRRUS_DEFAULT_IRQ 107 -+ -+#elif CONFIG_SOC_JZ4750 -+#define CIRRUS_DEFAULT_IO 0xac000000 -+ -+#ifdef CONFIG_JZ4750_FUWA -+#define CIRRUS_DEFAULT_IRQ (32*4+20+48) -+#else -+#define CIRRUS_DEFAULT_IRQ (32*2 +6+48) -+#endif -+ -+ -+#endif -+ -+typedef struct { -+ struct net_device_stats stats; -+ u16 txlen; -+} cirrus_t; -+ -+static int ethaddr_cmd = 0; -+static unsigned char ethaddr_hex[6]; -+static struct net_device *dev; -+ -+/* -+ * I/O routines -+ */ -+static void gpio_init_cs8900(void) -+{ -+#ifdef CONFIG_SOC_JZ4740 -+ __gpio_as_func0(60); //CS4# -+ __gpio_as_func0(61); //RD# -+ __gpio_as_func0(62); //WR# -+ __gpio_as_irq_high_level(59); //irq -+ __gpio_disable_pull(59); //disable pull -+ REG_EMC_SMCR4 |= (1 << 6); //16bit -+#elif CONFIG_SOC_JZ4750 -+ __gpio_as_func0(32*2+23); //CS3# -+ __gpio_as_func0(32*2+25); //RD# -+ __gpio_as_func0(32*2+26); //WR# -+ -+#ifdef CONFIG_JZ4750_FUWA -+ __gpio_as_irq_high_level(32*4+20); //irq -+ __gpio_disable_pull(32*4+20); //disable pull -+#else -+ __gpio_as_irq_high_level(32*2 +6); //irq -+ __gpio_disable_pull(32*2 +6); //disable pull -+#endif -+ -+ REG_EMC_SMCR3 |= (1 << 6); //16bit -+#endif -+ udelay(1); -+} -+ -+static inline u16 cirrus_read (struct net_device *dev,u16 reg) -+{ -+ outw (reg,dev->base_addr + PP_Address); -+ return (inw (dev->base_addr + PP_Data)); -+} -+ -+static inline void cirrus_write (struct net_device *dev,u16 reg,u16 value) -+{ -+ outw (reg,dev->base_addr + PP_Address); -+ outw (value,dev->base_addr + PP_Data); -+} -+ -+static inline void cirrus_set (struct net_device *dev,u16 reg,u16 value) -+{ -+ cirrus_write (dev,reg,cirrus_read (dev,reg) | value); -+} -+ -+static inline void cirrus_clear (struct net_device *dev,u16 reg,u16 value) -+{ -+ cirrus_write (dev,reg,cirrus_read (dev,reg) & ~value); -+} -+ -+static inline void cirrus_frame_read (struct net_device *dev,struct sk_buff *skb,u16 length) -+{ -+ insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2); -+} -+ -+static inline void cirrus_frame_write (struct net_device *dev,struct sk_buff *skb) -+{ -+ outsw (dev->base_addr,skb->data,(skb->len + 1) / 2); -+} -+ -+/* -+ * Debugging functions -+ */ -+ -+#ifdef DEBUG -+static inline int printable (int c) -+{ -+ return ((c >= 32 && c <= 126) || -+ (c >= 174 && c <= 223) || -+ (c >= 242 && c <= 243) || -+ (c >= 252 && c <= 253)); -+} -+ -+static void dump16 (struct net_device *dev,const u8 *s,size_t len) -+{ -+ int i; -+ char str[128]; -+ -+ if (!len) return; -+ -+ *str = '\0'; -+ -+ for (i = 0; i < len; i++) { -+ if (i && !(i % 4)) strcat (str," "); -+ sprintf (str,"%s%.2x ",str,s[i]); -+ } -+ -+ for ( ; i < 16; i++) { -+ if (i && !(i % 4)) strcat (str," "); -+ strcat (str," "); -+ } -+ -+ strcat (str," "); -+ for (i = 0; i < len; i++) sprintf (str,"%s%c",str,printable (s[i]) ? s[i] : '.'); -+ -+ printk (KERN_DEBUG "%s: %s\n",dev->name,str); -+} -+ -+static void hexdump (struct net_device *dev,const void *ptr,size_t size) -+{ -+ const u8 *s = (u8 *) ptr; -+ int i; -+ for (i = 0; i < size / 16; i++, s += 16) dump16 (dev,s,16); -+ dump16 (dev,s,size % 16); -+} -+ -+static void dump_packet (struct net_device *dev,struct sk_buff *skb,const char *type) -+{ -+ printk (KERN_INFO "%s: %s %d byte frame %.2x:%.2x:%.2x:%.2x:%.2x:%.2x to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x type %.4x\n", -+ dev->name, -+ type, -+ skb->len, -+ skb->data[0],skb->data[1],skb->data[2],skb->data[3],skb->data[4],skb->data[5], -+ skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11], -+ (skb->data[12] << 8) | skb->data[13]); -+ if (skb->len < 0x100) hexdump (dev,skb->data,skb->len); -+} -+#endif /* #ifdef DEBUG */ -+ -+/* -+ * Driver functions -+ */ -+ -+static void cirrus_receive (struct net_device *dev) -+{ -+ cirrus_t *priv = (cirrus_t *) dev->priv; -+ struct sk_buff *skb; -+ u16 status,length; -+ -+ status = cirrus_read (dev,PP_RxStatus); -+ length = cirrus_read (dev,PP_RxLength); -+ -+ if (!(status & RxOK)) { -+ priv->stats.rx_errors++; -+ if ((status & (Runt | Extradata))) priv->stats.rx_length_errors++; -+ if ((status & CRCerror)) priv->stats.rx_crc_errors++; -+ return; -+ } -+ -+ if ((skb = dev_alloc_skb (length + 4)) == NULL) { -+ priv->stats.rx_dropped++; -+ return; -+ } -+ -+ skb->dev = dev; -+ skb_reserve (skb,2); -+ -+ cirrus_frame_read (dev,skb,length); -+ skb->protocol = eth_type_trans (skb,dev); -+ -+ netif_rx (skb); -+ dev->last_rx = jiffies; -+ -+ priv->stats.rx_packets++; -+ priv->stats.rx_bytes += length; -+} -+ -+static int cirrus_send_start (struct sk_buff *skb,struct net_device *dev) -+{ -+ cirrus_t *priv = (cirrus_t *) dev->priv; -+ u16 status; -+ -+ mdelay(10); -+ netif_stop_queue (dev); -+ -+ cirrus_write (dev,PP_TxCMD,TxStart (After5)); -+ cirrus_write (dev,PP_TxLength,skb->len); -+ -+ status = cirrus_read (dev,PP_BusST); -+ -+ if ((status & TxBidErr)) { -+ printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len); -+ priv->stats.tx_errors++; -+ priv->stats.tx_aborted_errors++; -+ priv->txlen = 0; -+ return (1); -+ } -+ -+ if (!(status & Rdy4TxNOW)) { -+ //printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name); -+ priv->stats.tx_errors++; -+ priv->txlen = 0; -+ /* FIXME: store skb and send it in interrupt handler */ -+ return (1); -+ } -+ -+ cirrus_frame_write (dev,skb); -+ dev->trans_start = jiffies; -+ -+ dev_kfree_skb (skb); -+ -+ priv->txlen = skb->len; -+ -+ return (0); -+} -+ -+static irqreturn_t cirrus_interrupt(int irq, void *id) -+{ -+ struct net_device *dev = (struct net_device *) id; -+ cirrus_t *priv; -+ u16 status; -+ -+ if (dev->priv == NULL) { -+ return IRQ_NONE; -+ } -+ -+ priv = (cirrus_t *) dev->priv; -+ -+ while ((status = cirrus_read (dev,PP_ISQ))) { -+ switch (RegNum (status)) { -+ case RxEvent: -+ cirrus_receive (dev); -+ break; -+ -+ case TxEvent: -+ priv->stats.collisions += ColCount (cirrus_read (dev,PP_TxCOL)); -+ if (!(RegContent (status) & TxOK)) { -+ priv->stats.tx_errors++; -+ if ((RegContent (status) & Out_of_window)) priv->stats.tx_window_errors++; -+ if ((RegContent (status) & Jabber)) priv->stats.tx_aborted_errors++; -+ break; -+ } else if (priv->txlen) { -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += priv->txlen; -+ } -+ priv->txlen = 0; -+ netif_wake_queue (dev); -+ break; -+ -+ case BufEvent: -+ if ((RegContent (status) & RxMiss)) { -+ u16 missed = MissCount (cirrus_read (dev,PP_RxMISS)); -+ priv->stats.rx_errors += missed; -+ priv->stats.rx_missed_errors += missed; -+ } -+ if ((RegContent (status) & TxUnderrun)) { -+ priv->stats.tx_errors++; -+ priv->stats.tx_fifo_errors++; -+ } -+ /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */ -+ priv->txlen = 0; -+ netif_wake_queue (dev); -+ break; -+ -+ case TxCOL: -+ priv->stats.collisions += ColCount (cirrus_read (dev,PP_TxCOL)); -+ break; -+ -+ case RxMISS: -+ status = MissCount (cirrus_read (dev,PP_RxMISS)); -+ priv->stats.rx_errors += status; -+ priv->stats.rx_missed_errors += status; -+ break; -+ default: -+ return IRQ_HANDLED; -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void cirrus_transmit_timeout (struct net_device *dev) -+{ -+ cirrus_t *priv = (cirrus_t *) dev->priv; -+ priv->stats.tx_errors++; -+ priv->stats.tx_heartbeat_errors++; -+ priv->txlen = 0; -+ netif_wake_queue (dev); -+} -+ -+static int cirrus_start (struct net_device *dev) -+{ -+ int result; -+ -+ /* valid ethernet address? */ -+ if (!is_valid_ether_addr(dev->dev_addr)) { -+ printk(KERN_ERR "%s: invalid ethernet MAC address\n",dev->name); -+ return (-EINVAL); -+ } -+ -+ /* install interrupt handler */ -+ if ((result = request_irq (dev->irq, &cirrus_interrupt, IRQF_DISABLED, dev->name, dev)) < 0) { -+ printk (KERN_ERR "%s: could not register interrupt %d\n",dev->name,dev->irq); -+ return (result); -+ } -+ -+ /* enable the ethernet controller */ -+ cirrus_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE); -+ cirrus_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA); -+ cirrus_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE); -+ cirrus_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE); -+ cirrus_set (dev,PP_LineCTL,SerRxON | SerTxON); -+ cirrus_set (dev,PP_BusCTL,EnableRQ); -+ -+#ifdef FULL_DUPLEX -+ cirrus_set (dev,PP_TestCTL,FDX); -+#endif /* #ifdef FULL_DUPLEX */ -+ -+ /* start the queue */ -+ netif_start_queue (dev); -+ __gpio_unmask_irq(59); -+ -+ //MOD_INC_USE_COUNT; -+ return (0); -+} -+ -+static int cirrus_stop (struct net_device *dev) -+{ -+ /* disable ethernet controller */ -+ cirrus_write (dev,PP_BusCTL,0); -+ cirrus_write (dev,PP_TestCTL,0); -+ cirrus_write (dev,PP_SelfCTL,0); -+ cirrus_write (dev,PP_LineCTL,0); -+ cirrus_write (dev,PP_BufCFG,0); -+ cirrus_write (dev,PP_TxCFG,0); -+ cirrus_write (dev,PP_RxCTL,0); -+ cirrus_write (dev,PP_RxCFG,0); -+ -+ /* uninstall interrupt handler */ -+ free_irq (dev->irq,dev); -+ -+ /* stop the queue */ -+ netif_stop_queue (dev); -+ -+ //MOD_DEC_USE_COUNT; -+ -+ return (0); -+} -+ -+static int cirrus_set_mac_address (struct net_device *dev, void *p) -+{ -+ struct sockaddr *addr = (struct sockaddr *)p; -+ int i; -+ -+ if (netif_running(dev)) -+ return -EBUSY; -+ -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ -+ /* configure MAC address */ -+ for (i = 0; i < ETH_ALEN; i += 2) -+ cirrus_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8)); -+ -+ return 0; -+} -+ -+static struct net_device_stats *cirrus_get_stats (struct net_device *dev) -+{ -+ cirrus_t *priv = (cirrus_t *) dev->priv; -+ return (&priv->stats); -+} -+ -+static void cirrus_set_receive_mode (struct net_device *dev) -+{ -+ if ((dev->flags & IFF_PROMISC)) -+ cirrus_set (dev,PP_RxCTL,PromiscuousA); -+ else -+ cirrus_clear (dev,PP_RxCTL,PromiscuousA); -+ -+ if ((dev->flags & IFF_ALLMULTI) && dev->mc_list) -+ cirrus_set (dev,PP_RxCTL,MulticastA); -+ else -+ cirrus_clear (dev,PP_RxCTL,MulticastA); -+} -+ -+/* -+ * Architecture dependant code -+ */ -+ -+/* -+ * Driver initialization routines -+ */ -+ -+int __init cirrus_probe(void) -+{ -+ static cirrus_t priv; -+ int i; -+ u16 value; -+ -+ printk ("Jz CS8900A driver for Linux (V0.02)\n"); -+ -+ /* Init hardware for PAVO board */ -+ gpio_init_cs8900(); -+ -+ /* Allocate ethernet device */ -+ dev = alloc_etherdev(sizeof(struct net_device)); -+ -+ memset (&priv,0,sizeof (cirrus_t)); -+ -+ ether_setup (dev); -+ -+ dev->open = cirrus_start; -+ dev->stop = cirrus_stop; -+ dev->hard_start_xmit = cirrus_send_start; -+ dev->get_stats = cirrus_get_stats; -+ dev->set_multicast_list = cirrus_set_receive_mode; -+ dev->set_mac_address = cirrus_set_mac_address; -+ dev->tx_timeout = cirrus_transmit_timeout; -+ dev->watchdog_timeo = HZ; -+ -+ if (ethaddr_cmd==1) -+ { -+ dev->dev_addr[0] = ethaddr_hex[0]; -+ dev->dev_addr[1] = ethaddr_hex[1]; -+ dev->dev_addr[2] = ethaddr_hex[2]; -+ dev->dev_addr[3] = ethaddr_hex[3]; -+ dev->dev_addr[4] = ethaddr_hex[4]; -+ dev->dev_addr[5] = ethaddr_hex[5]; -+ } -+ else //default mac address 00:2a:cc:2a:af:fe -+ { -+ dev->dev_addr[0] = 0x00; -+ dev->dev_addr[1] = 0x62; -+ dev->dev_addr[2] = 0x9c; -+ dev->dev_addr[3] = 0x61; -+ dev->dev_addr[4] = 0xcf; -+ dev->dev_addr[5] = 0x16; -+ } -+ dev->if_port = IF_PORT_10BASET; -+ dev->priv = (void *) &priv; -+ -+ dev->base_addr = CIRRUS_DEFAULT_IO; -+ dev->irq = CIRRUS_DEFAULT_IRQ; -+ -+ -+ /* module parameters override everything */ -+ if (!dev->base_addr) { -+ printk (KERN_ERR -+ "%s: No default I/O base address defined. Use io=... or\n" -+ "%s: define CIRRUS_DEFAULT_IO for your platform\n", -+ dev->name,dev->name); -+ return (-EINVAL); -+ } -+ -+ if (!dev->irq) { -+ printk (KERN_ERR -+ "%s: No default IRQ number defined. Use irq=... or\n" -+ "%s: define CIRRUS_DEFAULT_IRQ for your platform\n", -+ dev->name,dev->name); -+ return (-EINVAL); -+ } -+#if 0 -+ if ((result = check_region (dev->base_addr,16))) { -+ printk (KERN_ERR "%s: can't get I/O port address 0x%lx\n",dev->name,dev->base_addr); -+ return (result); -+ } -+#endif -+ if (!request_region (dev->base_addr,16,dev->name)) -+ return -EBUSY; -+#if 0 -+ /* verify EISA registration number for Cirrus Logic */ -+ if ((value = cirrus_read (dev,PP_ProductID)) != EISA_REG_CODE) { -+ printk (KERN_ERR "%s: incorrect signature 0x%.4x\n",dev->name,value); -+ return (-ENXIO); -+ } -+#endif -+ -+ /* verify chip version */ -+ value = cirrus_read (dev,PP_ProductID + 2); -+ if (VERSION (value) != CS8900A) { -+ printk (KERN_ERR "%s: unknown chip version 0x%.8x\n",dev->name,VERSION (value)); -+ return (-ENXIO); -+ } -+ printk (KERN_INFO "%s: CS8900A rev %c detected\n",dev->name,'B' + REVISION (value) - REV_B); -+ -+ /* setup interrupt number */ -+ cirrus_write (dev,PP_IntNum,INT_PIN); -+ -+ /* configure MAC address */ -+ for (i = 0; i < ETH_ALEN; i += 2) -+ { -+ //printk(" %x",dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8)); -+ cirrus_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8)); -+ } -+ -+ if (register_netdev(dev) != 0) { -+ printk(KERN_ERR " Cannot register net device\n"); -+ free_netdev(dev); -+ return -ENOMEM; -+ } -+ -+ return (0); -+} -+ -+static inline unsigned char str2hexnum(unsigned char c) -+{ -+ if(c >= '0' && c <= '9') -+ return c - '0'; -+ if(c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ if(c >= 'A' && c <= 'F') -+ return c - 'A' + 10; -+ return 0; /* foo */ -+} -+ -+static inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; -+ -+ for(i = 0; i < 6; i++) { -+ unsigned char num; -+ -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} -+ -+static int __init ethernet_addr_setup(char *str) -+{ -+ if (!str) { -+ printk("ethaddr not set in command line\n"); -+ return -1; -+ } -+ ethaddr_cmd = 1; -+ str2eaddr(ethaddr_hex, str); -+ return 0; -+} -+ -+__setup("ethaddr=", ethernet_addr_setup); -+ -+//EXPORT_NO_SYMBOLS; -+ -+MODULE_AUTHOR ("Lucifer "); -+MODULE_DESCRIPTION ("Jz CS8900A driver for Linux (V0.02)"); -+MODULE_LICENSE ("GPL"); -+ -+//#ifdef MODULE -+ -+ -+#if 0 -+static int io = 0; -+static int irq = 0; -+ -+module_param(io, int, 0); -+MODULE_PARM_DESC (io,"I/O Base Address"); -+//MODULE_PARM (io,"i"); -+ -+module_param(irq, int, 0); -+MODULE_PARM_DESC (irq,"IRQ Number"); -+//MODULE_PARM (irq,"i"); -+#endif -+ -+static int __init jzcs8900_init(void) -+{ -+ if (cirrus_probe()) { -+ printk(KERN_WARNING "jzcs8900: No cs8900a found\n"); -+ } -+ -+ return 0; -+} -+ -+static void __exit jzcs8900_exit(void) -+{ -+ release_region(dev->base_addr,16); -+ unregister_netdev(dev); -+ free_netdev(dev); -+} -+ -+module_init(jzcs8900_init); -+module_exit(jzcs8900_exit); -diff --git a/drivers/net/jzcs8900a.h b/drivers/net/jzcs8900a.h -new file mode 100644 -index 0000000..68d76bb ---- /dev/null -+++ b/drivers/net/jzcs8900a.h -@@ -0,0 +1,235 @@ -+#ifndef JZCS8900A_H -+#define JZCS8900A_H -+ -+/* -+ * linux/drivers/net/jzcs8900a.h -+ * -+ * Author: Lucifer -+ * -+ * A Cirrus Logic CS8900A driver for Linux -+ * based on the cs89x0 driver written by Russell Nelson, -+ * Donald Becker, and others. -+ * -+ * This source code 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. -+ */ -+ -+/* -+ * Ports -+ */ -+ -+#define PP_Address 0x0a /* PacketPage Pointer Port (Section 4.10.10) */ -+#define PP_Data 0x0c /* PacketPage Data Port (Section 4.10.10) */ -+ -+/* -+ * Registers -+ */ -+ -+#define PP_ProductID 0x0000 /* Section 4.3.1 Product Identification Code */ -+#define PP_MemBase 0x002c /* Section 4.9.2 Memory Base Address Register */ -+#define PP_IntNum 0x0022 /* Section 3.2.3 Interrupt Number */ -+#define PP_EEPROMCommand 0x0040 /* Section 4.3.11 EEPROM Command */ -+#define PP_EEPROMData 0x0042 /* Section 4.3.12 EEPROM Data */ -+#define PP_RxCFG 0x0102 /* Section 4.4.6 Receiver Configuration */ -+#define PP_RxCTL 0x0104 /* Section 4.4.8 Receiver Control */ -+#define PP_TxCFG 0x0106 /* Section 4.4.9 Transmit Configuration */ -+#define PP_BufCFG 0x010a /* Section 4.4.12 Buffer Configuration */ -+#define PP_LineCTL 0x0112 /* Section 4.4.16 Line Control */ -+#define PP_SelfCTL 0x0114 /* Section 4.4.18 Self Control */ -+#define PP_BusCTL 0x0116 /* Section 4.4.20 Bus Control */ -+#define PP_TestCTL 0x0118 /* Section 4.4.22 Test Control */ -+#define PP_ISQ 0x0120 /* Section 4.4.5 Interrupt Status Queue */ -+#define PP_TxEvent 0x0128 /* Section 4.4.10 Transmitter Event */ -+#define PP_BufEvent 0x012c /* Section 4.4.13 Buffer Event */ -+#define PP_RxMISS 0x0130 /* Section 4.4.14 Receiver Miss Counter */ -+#define PP_TxCOL 0x0132 /* Section 4.4.15 Transmit Collision Counter */ -+#define PP_SelfST 0x0136 /* Section 4.4.19 Self Status */ -+#define PP_BusST 0x0138 /* Section 4.4.21 Bus Status */ -+#define PP_TxCMD 0x0144 /* Section 4.4.11 Transmit Command */ -+#define PP_TxLength 0x0146 /* Section 4.5.2 Transmit Length */ -+#define PP_IA 0x0158 /* Section 4.6.2 Individual Address (IEEE Address) */ -+#define PP_RxStatus 0x0400 /* Section 4.7.1 Receive Status */ -+#define PP_RxLength 0x0402 /* Section 4.7.1 Receive Length (in bytes) */ -+#define PP_RxFrame 0x0404 /* Section 4.7.2 Receive Frame Location */ -+#define PP_TxFrame 0x0a00 /* Section 4.7.2 Transmit Frame Location */ -+ -+/* -+ * Values -+ */ -+ -+/* PP_IntNum */ -+#define INTRQ0 0x0000 -+#define INTRQ1 0x0001 -+#define INTRQ2 0x0002 -+#define INTRQ3 0x0003 -+ -+/* PP_ProductID */ -+#define EISA_REG_CODE 0x630e -+#define REVISION(x) (((x) & 0x1f00) >> 8) -+#define VERSION(x) ((x) & ~0x1f00) -+ -+#define CS8900A 0x0000 -+#define REV_B 7 -+#define REV_C 8 -+#define REV_D 9 -+ -+/* PP_RxCFG */ -+#define Skip_1 0x0040 -+#define StreamE 0x0080 -+#define RxOKiE 0x0100 -+#define RxDMAonly 0x0200 -+#define AutoRxDMAE 0x0400 -+#define BufferCRC 0x0800 -+#define CRCerroriE 0x1000 -+#define RuntiE 0x2000 -+#define ExtradataiE 0x4000 -+ -+/* PP_RxCTL */ -+#define IAHashA 0x0040 -+#define PromiscuousA 0x0080 -+#define RxOKA 0x0100 -+#define MulticastA 0x0200 -+#define IndividualA 0x0400 -+#define BroadcastA 0x0800 -+#define CRCerrorA 0x1000 -+#define RuntA 0x2000 -+#define ExtradataA 0x4000 -+ -+/* PP_TxCFG */ -+#define Loss_of_CRSiE 0x0040 -+#define SQErroriE 0x0080 -+#define TxOKiE 0x0100 -+#define Out_of_windowiE 0x0200 -+#define JabberiE 0x0400 -+#define AnycolliE 0x0800 -+#define T16colliE 0x8000 -+ -+/* PP_BufCFG */ -+#define SWint_X 0x0040 -+#define RxDMAiE 0x0080 -+#define Rdy4TxiE 0x0100 -+#define TxUnderruniE 0x0200 -+#define RxMissiE 0x0400 -+#define Rx128iE 0x0800 -+#define TxColOvfiE 0x1000 -+#define MissOvfloiE 0x2000 -+#define RxDestiE 0x8000 -+ -+/* PP_LineCTL */ -+#define SerRxON 0x0040 -+#define SerTxON 0x0080 -+#define AUIonly 0x0100 -+#define AutoAUI_10BT 0x0200 -+#define ModBackoffE 0x0800 -+#define PolarityDis 0x1000 -+#define L2_partDefDis 0x2000 -+#define LoRxSquelch 0x4000 -+ -+/* PP_SelfCTL */ -+#define RESET 0x0040 -+#define SWSuspend 0x0100 -+#define HWSleepE 0x0200 -+#define HWStandbyE 0x0400 -+#define HC0E 0x1000 -+#define HC1E 0x2000 -+#define HCB0 0x4000 -+#define HCB1 0x8000 -+ -+/* PP_BusCTL */ -+#define ResetRxDMA 0x0040 -+#define DMAextend 0x0100 -+#define UseSA 0x0200 -+#define MemoryE 0x0400 -+#define DMABurst 0x0800 -+#define IOCHRDYE 0x1000 -+#define RxDMAsize 0x2000 -+#define EnableRQ 0x8000 -+ -+/* PP_TestCTL */ -+#define DisableLT 0x0080 -+#define ENDECloop 0x0200 -+#define AUIloop 0x0400 -+#define DisableBackoff 0x0800 -+#define FDX 0x4000 -+ -+/* PP_ISQ */ -+#define RegNum(x) ((x) & 0x3f) -+#define RegContent(x) ((x) & ~0x3d) -+ -+#define RxEvent 0x0004 -+#define TxEvent 0x0008 -+#define BufEvent 0x000c -+#define RxMISS 0x0010 -+#define TxCOL 0x0012 -+ -+/* PP_RxStatus */ -+#define IAHash 0x0040 -+#define Dribblebits 0x0080 -+#define RxOK 0x0100 -+#define Hashed 0x0200 -+#define IndividualAdr 0x0400 -+#define Broadcast 0x0800 -+#define CRCerror 0x1000 -+#define Runt 0x2000 -+#define Extradata 0x4000 -+ -+#define HashTableIndex(x) ((x) >> 0xa) -+ -+/* PP_TxCMD */ -+#define After5 0 -+#define After381 1 -+#define After1021 2 -+#define AfterAll 3 -+#define TxStart(x) ((x) << 6) -+ -+#define Force 0x0100 -+#define Onecoll 0x0200 -+#define InhibitCRC 0x1000 -+#define TxPadDis 0x2000 -+ -+/* PP_BusST */ -+#define TxBidErr 0x0080 -+#define Rdy4TxNOW 0x0100 -+ -+/* PP_TxEvent */ -+#define Loss_of_CRS 0x0040 -+#define SQEerror 0x0080 -+#define TxOK 0x0100 -+#define Out_of_window 0x0200 -+#define Jabber 0x0400 -+#define T16coll 0x8000 -+ -+#define TX_collisions(x) (((x) >> 0xb) & ~0x8000) -+ -+/* PP_BufEvent */ -+#define SWint 0x0040 -+#define RxDMAFrame 0x0080 -+#define Rdy4Tx 0x0100 -+#define TxUnderrun 0x0200 -+#define RxMiss 0x0400 -+#define Rx128 0x0800 -+#define RxDest 0x8000 -+ -+/* PP_RxMISS */ -+#define MissCount(x) ((x) >> 6) -+ -+/* PP_TxCOL */ -+#define ColCount(x) ((x) >> 6) -+ -+/* PP_SelfST */ -+#define T3VActive 0x0040 -+#define INITD 0x0080 -+#define SIBUSY 0x0100 -+#define EEPROMpresent 0x0200 -+#define EEPROMOK 0x0400 -+#define ELpresent 0x0800 -+#define EEsize 0x1000 -+ -+/* PP_EEPROMCommand */ -+#define EEWriteRegister 0x0100 -+#define EEReadRegister 0x0200 -+#define EEEraseRegister 0x0300 -+#define ELSEL 0x0400 -+ -+#endif /* #ifndef CIRRUS_H */ -diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig -index 2a37b3f..8a8e831 100644 ---- a/drivers/pnp/Kconfig -+++ b/drivers/pnp/Kconfig -@@ -5,7 +5,7 @@ - menuconfig PNP - bool "Plug and Play support" - depends on HAS_IOMEM -- depends on ISA || ACPI -+# depends on ISA || ACPI - ---help--- - Plug and Play (PnP) is a standard for peripherals which allows those - peripherals to be configured by software, e.g. assign IRQ's or other -diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c -index 5dba909..fd77eb4 100644 ---- a/drivers/pnp/core.c -+++ b/drivers/pnp/core.c -@@ -74,6 +74,8 @@ int pnp_register_protocol(struct pnp_protocol *protocol) - return device_register(&protocol->dev); - } - -+EXPORT_SYMBOL(pnp_register_protocol); -+ - /** - * pnp_protocol_unregister - removes a pnp protocol from the pnp layer - * @protocol: pointer to the corresponding pnp_protocol structure -@@ -86,6 +88,8 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol) - device_unregister(&protocol->dev); - } - -+EXPORT_SYMBOL(pnp_unregister_protocol); -+ - static void pnp_free_ids(struct pnp_dev *dev) - { - struct pnp_id *id; -@@ -196,6 +200,8 @@ int pnp_add_device(struct pnp_dev *dev) - return 0; - } - -+EXPORT_SYMBOL(pnp_add_device); -+ - void __pnp_remove_device(struct pnp_dev *dev) - { - spin_lock(&pnp_lock); -@@ -205,6 +211,21 @@ void __pnp_remove_device(struct pnp_dev *dev) - device_unregister(&dev->dev); - } - -+/** -+ * pnp_remove_device - removes a pnp device from the pnp layer -+ * @dev: pointer to dev to add -+ * -+ * this function will free all mem used by dev -+ */ -+void pnp_remove_device(struct pnp_dev *dev) -+{ -+ if (!dev || dev->card) -+ return; -+ __pnp_remove_device(dev); -+} -+ -+EXPORT_SYMBOL(pnp_remove_device); -+ - static int __init pnp_init(void) - { - return bus_register(&pnp_bus_type); -diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c -index 527ee76..9e1132f 100644 ---- a/drivers/pnp/driver.c -+++ b/drivers/pnp/driver.c -@@ -259,3 +259,4 @@ EXPORT_SYMBOL(pnp_register_driver); - EXPORT_SYMBOL(pnp_unregister_driver); - EXPORT_SYMBOL(pnp_device_attach); - EXPORT_SYMBOL(pnp_device_detach); -+EXPORT_SYMBOL(pnp_add_id); -diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c -index ba97654..525211c 100644 ---- a/drivers/pnp/resource.c -+++ b/drivers/pnp/resource.c -@@ -406,6 +406,10 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) - - int pnp_check_dma(struct pnp_dev *dev, struct resource *res) - { -+ printk("*********** %s, %s, line[%d]: Fix me, this should update in the future *********\n", -+ __FILE__, __FUNCTION__, __LINE__); -+ return 0; /* should be update in the future. Wolfgang ???*/ -+ - #ifndef CONFIG_IA64 - int i; - struct pnp_dev *tdev; -diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c -index fb867a9..e8d0962 100644 ---- a/drivers/serial/8250.c -+++ b/drivers/serial/8250.c -@@ -194,7 +194,7 @@ static const struct serial8250_config uart_config[] = { - [PORT_16550A] = { - .name = "16550A", - .fifo_size = 16, -- .tx_loadsz = 16, -+ .tx_loadsz = 8, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO, - }, -@@ -2213,6 +2213,83 @@ static void serial8250_shutdown(struct uart_port *port) - serial_unlink_irq_chain(up); - } - -+#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -+static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */ -+static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud) -+{ -+ int err, sum, i, j; -+ int a[12], b[12]; -+ unsigned short div, umr, uacr; -+ unsigned short umr_best, div_best, uacr_best; -+ long long t0, t1, t2, t3; -+ -+ sum = 0; -+ umr_best = div_best = uacr_best = 0; -+ div = 1; -+ -+ if ((port->uartclk % (16 * baud)) == 0) { -+ quot1[0] = port->uartclk / (16 * baud); -+ quot1[1] = 16; -+ quot1[2] = 0; -+ return quot1; -+ } -+ -+ while (1) { -+ umr = port->uartclk / (baud * div); -+ if (umr > 32) { -+ div++; -+ continue; -+ } -+ if (umr < 4) { -+ break; -+ } -+ for (i = 0; i < 12; i++) { -+ a[i] = umr; -+ b[i] = 0; -+ sum = 0; -+ for (j = 0; j <= i; j++) { -+ sum += a[j]; -+ } -+ -+ /* the precision could be 1/2^(36) due to the value of t0 */ -+ t0 = 0x1000000000LL; -+ t1 = (i + 1) * t0; -+ t2 = (sum * div) * t0; -+ t3 = div * t0; -+ do_div(t1, baud); -+ do_div(t2, port->uartclk); -+ do_div(t3, (2 * port->uartclk)); -+ err = t1 - t2 - t3; -+ -+ if (err > 0) { -+ a[i] += 1; -+ b[i] = 1; -+ } -+ } -+ -+ uacr = 0; -+ for (i = 0; i < 12; i++) { -+ if (b[i] == 1) { -+ uacr |= 1 << i; -+ } -+ } -+ -+ /* the best value of umr should be near 16, and the value of uacr should better be smaller */ -+ if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) { -+ div_best = div; -+ umr_best = umr; -+ uacr_best = uacr; -+ } -+ div++; -+ } -+ -+ quot1[0] = div_best; -+ quot1[1] = umr_best; -+ quot1[2] = uacr_best; -+ -+ return quot1; -+} -+#else - static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) - { - unsigned int quot; -@@ -2232,6 +2309,7 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int - - return quot; - } -+#endif - - static void - serial8250_set_termios(struct uart_port *port, struct ktermios *termios, -@@ -2241,6 +2319,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - unsigned char cval, fcr = 0; - unsigned long flags; - unsigned int baud, quot; -+#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -+ unsigned short *quot1; -+#endif - - switch (termios->c_cflag & CSIZE) { - case CS5: -@@ -2273,7 +2354,12 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); -+#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -+ quot1 = serial8250_get_divisor(port, baud); -+ quot = quot1[0]; /* not usefull, just let gcc happy */ -+#else - quot = serial8250_get_divisor(port, baud); -+#endif - - /* - * Oxford Semi 952 rev B workaround -@@ -2351,6 +2437,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - if (up->capabilities & UART_CAP_UUE) - up->ier |= UART_IER_UUE | UART_IER_RTOIE; - -+#ifdef CONFIG_JZSOC -+ up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */ -+#endif -+ - serial_out(up, UART_IER, up->ier); - - if (up->capabilities & UART_CAP_EFR) { -@@ -2385,7 +2475,15 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ - } - -+#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -+#define UART_UMR 9 -+#define UART_UACR 10 -+ serial_dl_write(up, quot1[0]); -+ serial_outp(up, UART_UMR, quot1[1]); -+ serial_outp(up, UART_UACR, quot1[2]); -+#else - serial_dl_write(up, quot); -+#endif - - /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR -diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig -index dcd49f1..0eb9723 100644 ---- a/drivers/usb/Kconfig -+++ b/drivers/usb/Kconfig -@@ -44,6 +44,7 @@ config USB_ARCH_HAS_OHCI - default y if PPC_MPC52xx - # MIPS: - default y if SOC_AU1X00 -+ default y if JZSOC - # SH: - default y if CPU_SUBTYPE_SH7720 - default y if CPU_SUBTYPE_SH7721 -diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index 7f8e83a..29ca462 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -374,6 +374,61 @@ config SUPERH_BUILT_IN_M66592 - # Controllers available only in discrete form (and all PCI controllers) - # - -+config USB_GADGET_JZ4740 -+ boolean "JZ4740 UDC" -+ depends on SOC_JZ4740 -+ select USB_GADGET_DUALSPEED -+ help -+ 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 -+ select USB_GADGET_SELECTED -+ -+config USB_GADGET_JZ4750 -+ boolean "JZ4750 UDC" -+ depends on SOC_JZ4750 -+ select USB_GADGET_DUALSPEED -+ help -+ Select this to support the Ingenic JZ4750 processor -+ high speed USB device controller. -+ -+config USB_JZ4750 -+ tristate -+ depends on USB_GADGET_JZ4750 -+ default USB_GADGET -+ select USB_GADGET_SELECTED -+ -+config USB_GADGET_JZ4750D -+ boolean "JZ4750D UDC" -+ depends on SOC_JZ4750D -+ select USB_GADGET_DUALSPEED -+ help -+ Select this to support the Ingenic JZ4750D processor -+ high speed USB device controller. -+ -+config USB_JZ4750D -+ tristate -+ depends on USB_GADGET_JZ4750D -+ default USB_GADGET -+ select USB_GADGET_SELECTED -+ -+config USB_GADGET_JZ4730 -+ boolean "JZ4730 UDC" -+ depends on SOC_JZ4730 -+ help -+ Select this to support the Ingenic JZ4730 processor -+ full speed USB device controller. -+ -+config USB_JZ4730 -+ tristate -+ depends on USB_GADGET_JZ4730 -+ default USB_GADGET -+ select USB_GADGET_SELECTED -+ - config USB_GADGET_AMD5536UDC - boolean "AMD5536 UDC" - depends on PCI -@@ -702,6 +757,14 @@ config USB_FILE_STORAGE_TEST - behavior of USB Mass Storage hosts. Not needed for - normal operation. - -+config UDC_USE_LB_CACHE -+ bool "enable lb cache" -+ depends on USB_FILE_STORAGE && (SOC_JZ4740 || SOC_JZ4750 || SOC_JZ4750D) -+ default y -+ help -+ say "y" to enable lb cache and UDC work in faster speed. -+ say "n" to disable lb cache and UDC work in normal speed. -+ - config USB_G_SERIAL - tristate "Serial Gadget (with CDC ACM and CDC OBEX support)" - help -diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile -index e6017e6..03e6df3 100644 ---- a/drivers/usb/gadget/Makefile -+++ b/drivers/usb/gadget/Makefile -@@ -27,6 +27,11 @@ obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o - obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o - obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o - obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o -+obj-$(CONFIG_USB_JZ4740) += jz4740_udc.o -+obj-$(CONFIG_USB_JZ4730) += jz4730_udc.o -+obj-$(CONFIG_USB_JZ4750) += jz4740_udc.o -+obj-$(CONFIG_USB_JZ4750D) += jz4740_udc.o -+ - - # - # USB gadget drivers -diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c -index 1e6aa50..ba357c9 100644 ---- a/drivers/usb/gadget/file_storage.c -+++ b/drivers/usb/gadget/file_storage.c -@@ -297,6 +297,18 @@ MODULE_LICENSE("Dual BSD/GPL"); - - - /*-------------------------------------------------------------------------*/ -+#if defined(CONFIG_UDC_USE_LB_CACHE) -+#define GHOST -+#endif -+ -+#ifdef GHOST -+extern unsigned long udc_read(unsigned long long offset, unsigned int len, unsigned char *); -+extern unsigned long udc_write(unsigned long long offset, unsigned int len, unsigned char *); -+extern int NAND_LB_Init(void); -+extern int NAND_LB_FLASHCACHE(void); -+extern int NAND_MTD_FLASHCACHE(void); -+extern int FlushDataState; -+#endif - - #define LDBG(lun,fmt,args...) \ - dev_dbg(&(lun)->dev , fmt , ## args) -@@ -575,7 +587,9 @@ struct lun { - unsigned int prevent_medium_removal : 1; - unsigned int registered : 1; - unsigned int info_valid : 1; -- -+#ifdef GHOST -+ unsigned int is_nand : 1; -+#endif - u32 sense_data; - u32 sense_data_info; - u32 unit_attention_data; -@@ -819,6 +833,7 @@ static u32 get_unaligned_be24(u8 *buf) - #define STRING_SERIAL 3 - #define STRING_CONFIG 4 - #define STRING_INTERFACE 5 -+#define STRING_MS_OS 0xee - - /* There is only one configuration. */ - #define CONFIG_VALUE 1 -@@ -1006,6 +1021,7 @@ static struct usb_string strings[] = { - {STRING_SERIAL, serial}, - {STRING_CONFIG, "Self-powered"}, - {STRING_INTERFACE, "Mass Storage"}, -+ {STRING_MS_OS, "Microsoft"}, - {} - }; - -@@ -1627,9 +1643,20 @@ static int do_read(struct fsg_dev *fsg) - - /* Perform the read */ - file_offset_tmp = file_offset; -+#ifdef GHOST -+ if (curlun->is_nand) -+ nread = udc_read(file_offset_tmp, amount, bh->buf); -+ else -+ nread = vfs_read(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -+ -+#else - nread = vfs_read(curlun->filp, - (char __user *) bh->buf, - amount, &file_offset_tmp); -+#endif -+ - VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nread); -@@ -1813,9 +1840,18 @@ static int do_write(struct fsg_dev *fsg) - - /* Perform the write */ - file_offset_tmp = file_offset; -+#ifdef GHOST -+ if (curlun->is_nand) -+ nwritten = udc_write(file_offset_tmp, amount, bh->buf); -+ else -+ nwritten = vfs_write(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -+#else - nwritten = vfs_write(curlun->filp, - (char __user *) bh->buf, - amount, &file_offset_tmp); -+#endif - VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nwritten); -@@ -1974,9 +2010,19 @@ static int do_verify(struct fsg_dev *fsg) - - /* Perform the read */ - file_offset_tmp = file_offset; -+#ifdef GHOST -+ if (curlun->is_nand) -+ nread = udc_read(file_offset_tmp, amount, bh->buf); -+ else -+ nread = vfs_read(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -+#else - nread = vfs_read(curlun->filp, - (char __user *) bh->buf, - amount, &file_offset_tmp); -+#endif -+ - VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nread); -@@ -2992,6 +3038,15 @@ static int do_scsi_command(struct fsg_dev *fsg) - reply = check_command(fsg, 6, DATA_DIR_NONE, - 0, 1, - "TEST UNIT READY"); -+#ifdef GHOST -+ if( FlushDataState >= 1) -+ FlushDataState++; -+ if(FlushDataState > 6) -+ { -+ NAND_LB_FLASHCACHE(); -+ FlushDataState = 0; -+ } -+#endif - break; - - /* Although optional, this command is used by MS-Windows. We -@@ -3544,6 +3599,13 @@ static int fsg_main_thread(void *fsg_) - - /* The main loop */ - while (fsg->state != FSG_STATE_TERMINATED) { -+#ifdef GHOST -+ if ((fsg->atomic_bitflags & SUSPENDED)) -+ { -+ NAND_LB_FLASHCACHE(); -+ NAND_MTD_FLASHCACHE(); -+ } -+#endif - if (exception_in_progress(fsg) || signal_pending(current)) { - handle_exception(fsg); - continue; -@@ -3675,6 +3737,13 @@ static int open_backing_file(struct lun *curlun, const char *filename) - curlun->num_sectors = num_sectors; - LDBG(curlun, "open backing file: %s\n", filename); - rc = 0; -+#ifdef GHOST -+ if (strstr(filename,"mtd")) -+ { -+ curlun->is_nand = 1; -+ NAND_LB_Init(); -+ } -+#endif - - out: - filp_close(filp, current->files); -diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h -index 8e0e9a0..553ff9e 100644 ---- a/drivers/usb/gadget/gadget_chips.h -+++ b/drivers/usb/gadget/gadget_chips.h -@@ -15,6 +15,18 @@ - #ifndef __GADGET_CHIPS_H - #define __GADGET_CHIPS_H - -+#ifdef CONFIG_USB_GADGET_JZ4740 -+#define gadget_is_jz4740(g) !strcmp("jz4740_udc", (g)->name) -+#else -+#define gadget_is_jz4740(g) 0 -+#endif -+ -+#ifdef CONFIG_USB_GADGET_JZ4730 -+#define gadget_is_jz4730(g) !strcmp("jz4730_udc", (g)->name) -+#else -+#define gadget_is_jz4730(g) 0 -+#endif -+ - #ifdef CONFIG_USB_GADGET_NET2280 - #define gadget_is_net2280(g) !strcmp("net2280", (g)->name) - #else -@@ -239,6 +251,11 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) - return 0x23; - else if (gadget_is_langwell(gadget)) - return 0x24; -+ else if (gadget_is_jz4730(gadget)) -+ return 0x25; -+ else if (gadget_is_jz4740(gadget)) -+ return 0x26; -+ - return -ENOENT; - } - -diff --git a/drivers/usb/gadget/jz4730_udc.c b/drivers/usb/gadget/jz4730_udc.c -new file mode 100644 -index 0000000..fb182a6 ---- /dev/null -+++ b/drivers/usb/gadget/jz4730_udc.c -@@ -0,0 +1,1403 @@ -+/* -+ * JZ4730 USB Device Controller driver -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+/* -+ * This device has ep0 and six bulk/interrupt/iso endpoints. -+ * -+ * - Endpoint numbering is fixed: ep0, ep1in-int, ep2in-bulk, ep3in-bulk, -+ * ep4in-iso, ep5out-bulk, ep6out-bulk, ep7out-iso. -+ * - Gadget drivers can choose ep maxpacket (8/16/32/64). -+ * - Just PIO mode currently. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "jz4730_udc.h" -+ -+//#define DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) -+//#define DEBUG_EP0(fmt,args...) printk(KERN_DEBUG fmt , ## args) -+ -+#ifndef DEBUG -+# define DEBUG(fmt,args...) do {} while(0) -+#endif -+#ifndef DEBUG_EP0 -+# define DEBUG_EP0(fmt,args...) do {} while(0) -+#endif -+ -+#define DRIVER_DESC "JZ4730 USB Device Controller" -+#define DRIVER_VERSION "20 Sep 2007" -+ -+static const char driver_name [] = "jz4730_udc"; -+static const char driver_desc [] = DRIVER_DESC; -+ -+static unsigned int udc_debug = 0; /* 0: normal mode, 1: test udc cable type mode */ -+ -+module_param(udc_debug, int, 0); -+MODULE_PARM_DESC(udc_debug, "test udc cable type"); -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+extern int jz_udc_active; /* 0: No actions; 1: Have actions */ -+#endif -+ -+/* -+ * Local declarations. -+ */ -+static void nuke(struct jz4730_ep *, int status); -+static inline void pio_irq_enable(struct jz4730_ep *ep); -+static inline void pio_irq_disable(struct jz4730_ep *ep); -+static void jz4730_udc_release (struct device *dev) {} -+/*-------------------------------------------------------------------------*/ -+ -+static int jz4730_ep_enable(struct usb_ep *_ep, -+ const struct usb_endpoint_descriptor *desc) -+{ -+ struct jz4730_udc *dev; -+ struct jz4730_ep *ep; -+ unsigned long flags; -+ u32 max; -+ -+ ep = container_of(_ep, struct jz4730_ep, ep); -+ if (!_ep || !desc || ep->desc -+ || desc->bDescriptorType != USB_DT_ENDPOINT) -+ return -EINVAL; -+ dev = ep->dev; -+ if (ep == &dev->ep[0]) -+ return -EINVAL; -+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ if (ep->index != (desc->bEndpointAddress & 0x0f)) -+ return -EINVAL; -+ -+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -+ case USB_ENDPOINT_XFER_BULK: -+ case USB_ENDPOINT_XFER_INT: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+// max = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); -+ max = 64; -+ ep->is_in = (USB_DIR_IN & desc->bEndpointAddress) != 0; -+ -+ spin_lock_irqsave(&ep->dev->lock, flags); -+ -+ ep->stopped = 0; -+ ep->desc = desc; -+ ep->ep.maxpacket = max; -+ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ -+ DEBUG("enable %s %s maxpacket %u\n", ep->ep.name, -+ ep->is_in ? "IN" : "OUT", max); -+ -+ return 0; -+} -+ -+static int jz4730_ep_disable(struct usb_ep *_ep) -+{ -+ struct jz4730_ep *ep; -+ struct jz4730_udc *dev; -+ unsigned long flags; -+ -+ ep = container_of(_ep, struct jz4730_ep, ep); -+ if (!_ep || !ep->desc) -+ return -ENODEV; -+ dev = ep->dev; -+ if (dev->ep0state == EP0_SUSPEND) -+ return -EBUSY; -+ -+ DEBUG("disable %s\n", _ep->name); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* Nuke all pending requests */ -+ nuke(ep, -ESHUTDOWN); -+ -+ /* Disable ep IRQ */ -+ pio_irq_disable(ep); -+ -+ ep->desc = 0; -+ ep->stopped = 1; -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+static struct usb_request *jz4730_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) -+{ -+ struct jz4730_request *req; -+ -+ req = kzalloc(sizeof *req, gfp_flags); -+ if (!req) -+ return 0; -+ -+ INIT_LIST_HEAD(&req->queue); -+ return &req->req; -+} -+ -+static void jz4730_free_request(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct jz4730_request *req; -+ -+ req = container_of(_req, struct jz4730_request, req); -+ WARN_ON(!list_empty(&req->queue)); -+ kfree(req); -+} -+ -+static void *jz4730_alloc_buffer(struct usb_ep *_ep, unsigned bytes, -+ dma_addr_t *dma, gfp_t gfp_flags) -+{ -+ void *retval; -+ -+ retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM)); -+ if (retval) -+ *dma = virt_to_phys(retval); -+ return retval; -+} -+ -+static void jz4730_free_buffer(struct usb_ep *_ep, void *buf, -+ dma_addr_t dma, unsigned bytes) -+{ -+ kfree(buf); -+} -+ -+/* -+ * done - retire a request; caller blocked irqs -+ */ -+static void done(struct jz4730_ep *ep, struct jz4730_request *req, int status) -+{ -+ struct jz4730_udc *dev; -+ unsigned stopped = ep->stopped; -+ -+ list_del_init(&req->queue); -+ -+ if (likely(req->req.status == -EINPROGRESS)) -+ req->req.status = status; -+ else -+ status = req->req.status; -+ -+ if (status && status != -ESHUTDOWN) -+ DEBUG("complete %s req %p stat %d len %u/%u\n", -+ ep->ep.name, &req->req, status, -+ req->req.actual, req->req.length); -+ -+ dev = ep->dev; -+ -+ /* don't modify queue heads during completion callback */ -+ ep->stopped = 1; -+ spin_unlock(&dev->lock); -+ req->req.complete(&ep->ep, &req->req); -+ spin_lock(&dev->lock); -+ ep->stopped = stopped; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static __inline__ int write_packet(struct jz4730_ep *ep, -+ struct jz4730_request *req, int max) -+{ -+ u8 *buf; -+ int length, nlong, nbyte; -+ volatile u32 *fifo = (volatile u32 *)ep->fifo; -+ -+ buf = req->req.buf + req->req.actual; -+ prefetch(buf); -+ -+ length = req->req.length - req->req.actual; -+ length = min(length, max); -+ req->req.actual += length; -+ -+ DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo); -+ -+ if (!length) { -+ /* Send ZLP */ -+ writel(0, (unsigned int *)UDC_TXZLP); -+ writel(0x12345678, (unsigned int *)fifo); -+ } -+ else { -+ nlong = length >> 2; -+ nbyte = length & 0x3; -+ while (nlong--) { -+ *fifo = *((u32 *)buf); -+ buf += 4; -+ } -+ while (nbyte--) { -+ *((volatile u8 *)fifo) = *buf++; -+ } -+ } -+ -+ writel(0, (unsigned int *)UDC_TXCONFIRM); -+ -+ return length; -+} -+ -+static __inline__ int read_packet(struct jz4730_ep *ep, -+ struct jz4730_request *req, int count) -+{ -+ u8 *buf; -+ int length, nlong, nbyte; -+ volatile u32 *fifo = (volatile u32 *)ep->fifo; -+ -+ buf = req->req.buf + req->req.actual; -+ prefetchw(buf); -+ -+ length = req->req.length - req->req.actual; -+ length = min(length, count); -+ req->req.actual += length; -+ -+ DEBUG("Read %d, fifo %p\n", length, fifo); -+ -+ nlong = length >> 2; -+ nbyte = length & 0x3; -+ while (nlong--) { -+ *((u32 *)buf) = *fifo; -+ buf += 4; -+ } -+ if (nbyte) { -+ u32 data = *fifo; -+ while (nbyte--) { -+ *buf++ = data & 0x0ff; -+ data >>= 8; -+ } -+ } -+ -+ REG32(UDC_RXCONFIRM); -+ -+ return length; -+} -+ -+/** Write request to FIFO (max write == maxp size) -+ * Return: 0 = still running, 1 = completed, negative = errno -+ */ -+static int write_fifo(struct jz4730_ep *ep, struct jz4730_request *req) -+{ -+ u32 max, count; -+ int is_last; -+ -+ max = ep->ep.maxpacket; -+ -+ count = write_packet(ep, req, max); -+ -+ /* last packet often short (sometimes a zlp, especially on ep0) */ -+ if (unlikely(count != max)) { -+ is_last = 1; -+ } else { -+ if (likely(req->req.length != req->req.actual) -+ || req->req.zero) -+ is_last = 0; -+ else -+ is_last = 1; -+ } -+ -+ DEBUG("write %s (%d)(IN) %d bytes%s req %p %d/%d is_last %d\n", -+ ep->ep.name, ep->index, count, -+ (count != ep->ep.maxpacket) ? " (short)" : "", -+ req, req->req.actual, req->req.length, is_last); -+ -+ /* requests complete when all IN data is in the FIFO, -+ * or sometimes later, if a zlp was needed. -+ */ -+ if (is_last) { -+ done(ep, req, 0); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/** Read to request from FIFO (max read == bytes in fifo) -+ * Return: 0 = still running, 1 = completed, negative = errno -+ */ -+static int read_fifo(struct jz4730_ep *ep, struct jz4730_request *req, u32 count) -+{ -+ int is_short; -+ -+ is_short = (count < ep->ep.maxpacket); -+ -+ count = read_packet(ep, req, count); -+ -+ DEBUG("read %s %u bytes%s OUT req %p %u/%u is_short %d\n", -+ ep->ep.name, count, (count < ep->ep.maxpacket) ? "(short)" : "", -+ req, req->req.actual, req->req.length, is_short); -+ -+ /* completion */ -+ if (is_short || req->req.actual == req->req.length) { -+ done(ep, req, 0); -+ return 1; -+ } -+ -+ /* finished that packet. the next one may be waiting... */ -+ return 0; -+} -+ -+static inline void pio_irq_enable(struct jz4730_ep *ep) -+{ -+ switch (ep->index) { -+ case 0: -+ REG_UDC_EPIntMR &= ~0x1; -+ break; -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ REG_UDC_EPIntMR &= ~(1 << ep->index); -+ break; -+ case 5: -+ case 6: -+ case 7: -+ REG_UDC_EPIntMR &= ~(1 << (ep->index + 16)); -+ break; -+ } -+} -+ -+static inline void pio_irq_disable(struct jz4730_ep *ep) -+{ -+ switch (ep->index) { -+ case 0: -+ REG_UDC_EPIntMR |= 0x1; -+ break; -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ REG_UDC_EPIntMR |= (1 << ep->index); -+ break; -+ case 5: -+ case 6: -+ case 7: -+ REG_UDC_EPIntMR |= (1 << (ep->index + 16)); -+ break; -+ } -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int -+jz4730_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) -+{ -+ struct jz4730_request *req; -+ struct jz4730_ep *ep; -+ struct jz4730_udc *dev; -+ unsigned long flags; -+ int status; -+ -+ /* always require a cpu-view buffer so pio works */ -+ req = container_of(_req, struct jz4730_request, req); -+ if (unlikely(!_req || !_req->complete -+ || !_req->buf || !list_empty(&req->queue))) -+ return -EINVAL; -+ ep = container_of(_ep, struct jz4730_ep, ep); -+ if (unlikely(!_ep || (!ep->desc && ep->index != 0))) -+ return -EINVAL; -+ dev = ep->dev; -+ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) -+ return -ESHUTDOWN; -+ -+ DEBUG("%s queue req %p, len %u buf %p\n", -+ _ep->name, _req, _req->length, _req->buf); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ _req->status = -EINPROGRESS; -+ _req->actual = 0; -+ -+ /* for ep0 IN without premature status, zlp is required and -+ * writing EOP starts the status stage (OUT). -+ */ -+ if (unlikely(ep->index == 0 && ep->is_in)) -+ _req->zero = 1; -+ -+ /* kickstart this i/o queue? */ -+ status = 0; -+ if (list_empty(&ep->queue) && likely(!ep->stopped)) { -+ if (unlikely(ep->index == 0)) { -+ pio_irq_enable(ep); -+ if (ep->irq_pending || -+ (REG_UDC_EPIntR & UDC_EPIntR_OUTEP0)) { -+ u32 stats, count; -+ -+ stats = REG_UDC_EP0OutSR; -+ if (stats & UDC_EPSR_OUT_RCVDATA) { -+ ep->irq_pending = 0; -+ REG_UDC_EP0OutSR &= ~UDC_EPSR_OUT_MASK; -+ if (REG_UDC_EPIntR & UDC_EPIntR_OUTEP0) -+ REG_UDC_EPIntR = UDC_EPIntR_OUTEP0; -+ -+ count = OUT_COUNT(stats); -+ if (read_fifo(ep, req, count) == 1) -+ req = 0; -+ } -+ } -+ -+ } else if (ep->is_in) { -+ /* EP1 ~ EP4 */ -+ if (ep->irq_pending || -+ (REG_UDC_EPIntR & UDC_EPIntR_INEP2)) { -+ if (REG_UDC_EP2InSR & UDC_EPSR_IN) { -+ ep->irq_pending = 0; -+ REG_UDC_EP2InSR &= ~UDC_EPSR_IN; -+ if (REG_UDC_EPIntR & UDC_EPIntR_INEP2) -+ REG_UDC_EPIntR = UDC_EPIntR_INEP2; -+ -+ if (write_fifo(ep, req) == 1) -+ req = 0; -+ } -+ } -+ pio_irq_enable(ep); -+ } else { -+ /* EP5 ~ EP7 */ -+ pio_irq_enable(ep); -+ -+ if (ep->irq_pending || -+ (REG_UDC_EPIntR & UDC_EPIntR_OUTEP5)) { -+ u32 stats, count; -+ -+ stats = REG_UDC_EP5OutSR; -+ if (stats & UDC_EPSR_OUT_RCVDATA) { -+ ep->irq_pending = 0; -+ REG_UDC_EP5OutSR &= ~UDC_EPSR_OUT_MASK; -+ if (REG_UDC_EPIntR & UDC_EPIntR_OUTEP5) -+ REG_UDC_EPIntR = UDC_EPIntR_OUTEP5; -+ -+ count = OUT_COUNT(stats); -+ if (read_fifo(ep, req, count) == 1) -+ req = 0; -+ } -+ } -+ } -+ } -+ -+ /* pio or dma irq handler advances the queue. */ -+ if (likely(req != 0)) { -+ list_add_tail(&req->queue, &ep->queue); -+ } -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return status; -+} -+ -+/* dequeue ALL requests */ -+static void nuke(struct jz4730_ep *ep, int status) -+{ -+ struct jz4730_request *req; -+ -+ if (list_empty(&ep->queue)) -+ return; -+ while (!list_empty(&ep->queue)) { -+ req = list_entry(ep->queue.next, struct jz4730_request, queue); -+ done(ep, req, status); -+ } -+} -+ -+/* dequeue JUST ONE request */ -+static int jz4730_dequeue(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct jz4730_request *req; -+ struct jz4730_ep *ep; -+ struct jz4730_udc *dev; -+ unsigned long flags; -+ int stopped; -+ -+ ep = container_of(_ep, struct jz4730_ep, ep); -+ if (!_ep || !_req || (!ep->desc && ep->index != 0)) -+ return -EINVAL; -+ dev = ep->dev; -+ if (!dev->driver) -+ return -ESHUTDOWN; -+ -+ DEBUG("%s %s %p\n", __FUNCTION__, _ep->name,_req); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ stopped = ep->stopped; -+ ep->stopped = 1; -+ -+ /* make sure it's actually queued on this endpoint */ -+ list_for_each_entry (req, &ep->queue, queue) { -+ if (&req->req == _req) -+ break; -+ } -+ if (&req->req != _req) { -+ spin_unlock_irqrestore (&dev->lock, flags); -+ return -EINVAL; -+ } -+ -+ /* queue head may be partially complete. */ -+ if (ep->queue.next == &req->queue) { -+ done (ep, req, -ECONNRESET); -+ req = 0; -+ } -+ -+ if (req) -+ done (ep, req, -ECONNRESET); -+ ep->stopped = stopped; -+ -+ spin_unlock_irqrestore (&ep->dev->lock, flags); -+ return req ? 0 : -EOPNOTSUPP; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void jz4730_clear_halt(struct jz4730_ep *ep) -+{ -+ if (ep->stopped) { -+ ep->stopped = 0; -+ } -+} -+ -+static int jz4730_set_halt(struct usb_ep *_ep, int value) -+{ -+ struct jz4730_ep *ep; -+ unsigned long flags; -+ int retval = 0; -+ -+ if (!_ep) -+ return -ENODEV; -+ ep = container_of (_ep, struct jz4730_ep, ep); -+ if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03) -+ == USB_ENDPOINT_XFER_ISOC) -+ return -EINVAL; -+ -+ if (ep->index == 0) { -+ if (value) { -+ ep->dev->ep0state = EP0_STALL; -+ ep->dev->ep[0].stopped = 1; -+ } else -+ return -EINVAL; -+ -+ /* don't change EPxSTATUS_EP_INVALID to READY */ -+ } else if (!ep->desc) { -+ DEBUG("%s %s inactive?\n", __FUNCTION__, ep->ep.name); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&ep->dev->lock, flags); -+ -+ if (!list_empty(&ep->queue)) -+ retval = -EAGAIN; -+ else if (!value) -+ jz4730_clear_halt(ep); -+ else { -+ ep->stopped = 1; -+ } -+ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ return retval; -+} -+ -+static int jz4730_fifo_status(struct usb_ep *_ep) -+{ -+ struct jz4730_ep *ep; -+ u32 size = 0; -+ -+ if (!_ep) -+ return -ENODEV; -+ ep = container_of(_ep, struct jz4730_ep, ep); -+ -+ /* size is only reported sanely for OUT */ -+ if (ep->is_in) -+ return -EOPNOTSUPP; -+ -+ return size; -+} -+ -+static void jz4730_fifo_flush(struct usb_ep *_ep) -+{ -+ struct jz4730_ep *ep; -+ -+ if (!_ep) -+ return; -+ ep = container_of(_ep, struct jz4730_ep, ep); -+ -+ /* don't change EPxSTATUS_EP_INVALID to READY */ -+ if (!ep->desc && ep->index != 0) { -+ return; -+ } -+} -+ -+static struct usb_ep_ops jz4730_ep_ops = { -+ .enable = jz4730_ep_enable, -+ .disable = jz4730_ep_disable, -+ -+ .alloc_request = jz4730_alloc_request, -+ .free_request = jz4730_free_request, -+#if 0 -+ .alloc_buffer = jz4730_alloc_buffer, -+ .free_buffer = jz4730_free_buffer, -+#endif -+ .queue = jz4730_queue, -+ .dequeue = jz4730_dequeue, -+ -+ .set_halt = jz4730_set_halt, -+ .fifo_status = jz4730_fifo_status, -+ .fifo_flush = jz4730_fifo_flush, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int jz4730_get_frame(struct usb_gadget *_gadget) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static const struct usb_gadget_ops jz4730_ops = { -+ .get_frame = jz4730_get_frame, -+ // no remote wakeup -+ // not selfpowered -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void udc_reinit(struct jz4730_udc *dev) -+{ -+ static char *names [] = { "ep0", "ep1in-int", "ep2in-bulk", "ep3in-bulk", -+ "ep4in-iso", "ep5out-bulk", "ep6out-bulk", -+ "ep7out-iso" }; -+ int i; -+ -+ INIT_LIST_HEAD (&dev->gadget.ep_list); -+ dev->gadget.ep0 = &dev->ep[0].ep; -+ dev->gadget.speed = USB_SPEED_UNKNOWN; -+ dev->ep0state = EP0_DISCONNECT; -+ -+ for (i = 0; i < MAX_EP_NUM; i++) { -+ struct jz4730_ep *ep = &dev->ep[i]; -+ -+ ep->index = i; -+ ep->ep.name = names[i]; -+ ep->fifo = ep_fifo[i]; -+ ep->ep.maxpacket = 64; -+ -+ ep->ep.ops = &jz4730_ep_ops; -+ list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); -+ ep->dev = dev; -+ INIT_LIST_HEAD(&ep->queue); -+ -+ ep->desc = 0; -+ ep->stopped = 1; -+ ep->irq_pending = 0; -+ } -+ -+ dev->ep[0].ep.maxpacket = MAX_EP0_SIZE; -+ list_del_init(&dev->ep[0].ep.ep_list); -+} -+ -+/* Reset udc registers */ -+static void udc_reset(struct jz4730_udc *dev) -+{ -+ REG_UDC_DevIntMR = 0x32; /* Enable RESET and SC interrupts */ -+ REG_UDC_EPIntMR = 0x0; /* Enable all EP interrupts */ -+ REG_UDC_DevCFGR = 0x17; -+ REG_UDC_DevCR = 0x0; -+ -+ REG_UDC_EP0InCR = (0 << 4) | (1 << 1); -+ REG_UDC_EP0InCR = (0 << 4); -+ REG_UDC_EP1InCR = (3 << 4) | (1 << 1); -+ REG_UDC_EP1InCR = (3 << 4); -+ REG_UDC_EP2InCR = (2 << 4) | (1 << 1); -+ REG_UDC_EP2InCR = (2 << 4); -+ REG_UDC_EP3InCR = (2 << 4) | (1 << 1); -+ REG_UDC_EP3InCR = (2 << 4); -+ REG_UDC_EP4InCR = (1 << 4) | (1 << 1); -+ REG_UDC_EP4InCR = (1 << 4); -+ -+ REG_UDC_EP0OutCR = (0 << 4); -+ REG_UDC_EP5OutCR = (2 << 4); -+ REG_UDC_EP6OutCR = (2 << 4); -+ REG_UDC_EP7OutCR = (1 << 4); -+ -+ REG_UDC_EP0InSR = 0; -+ REG_UDC_EP1InSR = 0; -+ REG_UDC_EP2InSR = 0; -+ REG_UDC_EP3InSR = 0; -+ REG_UDC_EP4InSR = 0; -+ REG_UDC_EP5OutSR = 0; -+ REG_UDC_EP6OutSR = 0; -+ REG_UDC_EP7OutSR = 0; -+ -+ REG_UDC_EP0InBSR = MAX_EP0_SIZE/4; -+ REG_UDC_EP1InBSR = MAX_EP1_SIZE/4; -+ REG_UDC_EP2InBSR = MAX_EP2_SIZE/4; -+ REG_UDC_EP3InBSR = MAX_EP3_SIZE/4; -+ REG_UDC_EP4InBSR = MAX_EP4_SIZE/4; -+ -+ REG_UDC_EP0InMPSR = MAX_EP0_SIZE; -+ REG_UDC_EP1InMPSR = MAX_EP1_SIZE; -+ REG_UDC_EP2InMPSR = MAX_EP2_SIZE; -+ REG_UDC_EP3InMPSR = MAX_EP3_SIZE; -+ REG_UDC_EP4InMPSR = MAX_EP4_SIZE; -+ -+ REG_UDC_EP0OutMPSR = MAX_EP0_SIZE; -+ REG_UDC_EP5OutMPSR = MAX_EP5_SIZE; -+ REG_UDC_EP6OutMPSR = MAX_EP6_SIZE; -+ REG_UDC_EP7OutMPSR = MAX_EP7_SIZE; -+ -+ REG_UDC_EP0InfR = (MAX_EP0_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (0 << 5) | (0 << 4) | (0 << 0); -+ REG_UDC_EP1InfR = (MAX_EP1_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (3 << 5) | (1 << 4) | (1 << 0); -+ REG_UDC_EP2InfR = (MAX_EP2_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (1 << 4) | (2 << 0); -+ REG_UDC_EP3InfR = (MAX_EP3_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (1 << 4) | (3 << 0); -+ REG_UDC_EP4InfR = (MAX_EP4_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (1 << 5) | (1 << 4) | (4 << 0); -+ REG_UDC_EP5InfR = (MAX_EP5_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (0 << 4) | (5 << 0); -+ REG_UDC_EP6InfR = (MAX_EP6_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (0 << 4) | (6 << 0); -+ REG_UDC_EP7InfR = (MAX_EP7_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (1 << 5) | (0 << 4) | (7 << 0); -+ -+ REG_UDC_STCMAR = 0xffff; -+} -+ -+static void ep0_start(struct jz4730_udc *dev) -+{ -+ udc_reset(dev); -+ udc_reinit(dev); -+ -+ /* expect ep0 requests when the host drops reset */ -+ dev->gadget.speed = USB_SPEED_FULL; -+ dev->ep0state = EP0_IDLE; -+} -+ -+static void udc_enable(struct jz4730_udc *dev) -+{ -+ /* Enable udc and enable all interrupts */ -+ __intc_unmask_irq(IRQ_UDC); -+ __harb_usb0_udc(); -+ -+ /* start enumeration now, or after power detect irq */ -+ ep0_start(dev); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* keeping it simple: -+ * - one bus driver, initted first; -+ * - one function driver, initted second -+ */ -+ -+static struct jz4730_udc *the_controller; -+ -+/* when a driver is successfully registered, it will receive -+ * control requests including set_configuration(), which enables -+ * non-control requests. then usb traffic follows until a -+ * disconnect is reported. then a host may connect again, or -+ * the driver might get unbound. -+ */ -+int usb_gadget_register_driver(struct usb_gadget_driver *driver) -+{ -+ struct jz4730_udc *dev = the_controller; -+ int retval; -+ -+ if (!driver -+// || driver->speed != USB_SPEED_FULL -+ || !driver->bind -+ || !driver->unbind -+ || !driver->disconnect -+ || !driver->setup) -+ { -+ printk("\n -EINVAL"); -+ return -EINVAL; -+ } -+ if (!dev) -+ return -ENODEV; -+ -+ if (dev->driver) -+ return -EBUSY; -+ -+ /* hook up the driver */ -+ dev->driver = driver; -+ retval = driver->bind(&dev->gadget); -+ if (retval) { -+ DEBUG("bind to driver %s --> error %d\n", -+ driver->driver.name, retval); -+ dev->driver = 0; -+ return retval; -+ } -+ /* then enable host detection and ep0; and we're ready -+ * for set_configuration as well as eventual disconnect. -+ */ -+ udc_enable(dev); -+ -+ DEBUG("registered gadget driver '%s'\n", driver->driver.name); -+ return 0; -+} -+EXPORT_SYMBOL(usb_gadget_register_driver); -+ -+static void -+stop_activity(struct jz4730_udc *dev, struct usb_gadget_driver *driver) -+{ -+ unsigned i; -+ -+ DEBUG("%s\n", __FUNCTION__); -+ -+ if (dev->gadget.speed == USB_SPEED_UNKNOWN) -+ driver = 0; -+ -+ /* disconnect gadget driver after quiesceing hw and the driver */ -+ udc_reset (dev); -+ for (i = 0; i < MAX_EP_NUM; i++) -+ nuke(&dev->ep [i], -ESHUTDOWN); -+ if (driver) { -+ spin_unlock(&dev->lock); -+ driver->disconnect(&dev->gadget); -+ spin_lock(&dev->lock); -+ } -+ -+ if (dev->driver) -+ udc_enable(dev); -+} -+ -+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -+{ -+ struct jz4730_udc *dev = the_controller; -+ unsigned long flags; -+ -+ /* disable UDC irq */ -+ __intc_mask_irq(IRQ_UDC); -+ __harb_usb0_uhc(); -+ -+ if (!dev) -+ return -ENODEV; -+ if (!driver || driver != dev->driver) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->driver = 0; -+ stop_activity(dev, driver); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ driver->unbind(&dev->gadget); -+ -+ DEBUG("unregistered driver '%s'\n", driver->driver.name); -+ return 0; -+} -+EXPORT_SYMBOL(usb_gadget_unregister_driver); -+ -+static void jz4730_epn_out(struct jz4730_udc *dev, int ep_idx, u32 count) -+{ -+ struct jz4730_request *req; -+ struct jz4730_ep *ep = &dev->ep[ep_idx]; -+ -+ req = list_entry(ep->queue.next, struct jz4730_request, queue); -+ read_fifo(ep, req, count); -+} -+ -+static void jz4730_epn_in(struct jz4730_udc *dev, int ep_idx) -+{ -+ struct jz4730_request *req; -+ struct jz4730_ep *ep = &dev->ep[ep_idx]; -+ -+ req = list_entry(ep->queue.next, struct jz4730_request, queue); -+ write_fifo(ep, req); -+} -+ -+/****************************************************************/ -+/* End Point 0 related functions */ -+/****************************************************************/ -+ -+/* return: 0 = still running, 1 = completed, negative = errno */ -+static int write_fifo_ep0(struct jz4730_ep *ep, struct jz4730_request *req) -+{ -+ u32 max, count; -+ int is_last; -+ -+ max = ep->ep.maxpacket; -+ -+ count = write_packet(ep, req, max); -+ -+ /* last packet is usually short (or a zlp) */ -+ if (unlikely(count != max)) -+ is_last = 1; -+ else { -+ if (likely(req->req.length != req->req.actual) || req->req.zero) -+ is_last = 0; -+ else -+ is_last = 1; -+ } -+ -+ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__, -+ ep->ep.name, count, -+ is_last ? "/L" : "", req->req.length - req->req.actual, req); -+ -+ /* requests complete when all IN data is in the FIFO */ -+ if (is_last) { -+ done(ep, req, 0); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Simulate a USB_REQ_SET_CONFIGURATION to the function driver, -+ * this is required to enable the endpoints of the function driver. -+ * UDC should let software have the chance to handle this standard -+ * request, unfortunately UDC can't do that. -+ */ -+static void psudo_set_config(void) -+{ -+ struct jz4730_udc *dev = (struct jz4730_udc *) the_controller; -+ struct usb_ctrlrequest ctrl; -+ int tmp; -+ -+ /* SETUP packet */ -+ ctrl.bRequestType = 0x00; -+ ctrl.bRequest = USB_REQ_SET_CONFIGURATION; -+ ctrl.wValue = 1; -+ ctrl.wIndex = 0; -+ ctrl.wLength = 0; -+ -+ nuke(&dev->ep[0], 0); -+ dev->ep[0].stopped = 0; -+ -+ if (likely(ctrl.bRequestType & USB_DIR_IN)) { -+ dev->ep[0].is_in = 1; -+ dev->ep0state = EP0_IN; -+ } else { -+ dev->ep[0].is_in = 0; -+ dev->ep0state = EP0_OUT; -+ } -+ -+ /* delegate everything to the gadget driver. -+ * it may respond after this irq handler returns. -+ */ -+ spin_unlock (&dev->lock); -+ tmp = dev->driver->setup(&dev->gadget, &ctrl); -+ spin_lock (&dev->lock); -+ if (unlikely(tmp < 0)) { -+ DEBUG_EP0("req %02x.%02x protocol STALL; err %d\n", -+ ctrl.bRequestType, ctrl.bRequest, tmp); -+ dev->ep[0].stopped = 1; -+ dev->ep0state = EP0_STALL; -+ } -+} -+ -+/* -+ * Read 8 bytes setup packet from EP0 RX buffer -+ */ -+static void read_setup_packet(u8 *buf) -+{ -+ u32 *tmp = (u32 *)buf; -+ -+ *tmp++ = readl((unsigned int *)RXFIFO); -+ *tmp++ = readl((unsigned int *)RXFIFO); -+ -+ REG32(UDC_RXCONFIRM); -+} -+ -+static void jz4730_ep0_setup(struct jz4730_udc *dev) -+{ -+ struct jz4730_ep *ep = &dev->ep[0]; -+ struct usb_ctrlrequest ctrl; -+ int tmp; -+ -+ /* read control req from fifo (8 bytes) */ -+ read_setup_packet((unsigned char *) &ctrl); -+ -+ DEBUG_EP0("SETUP %02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bRequestType, ctrl.bRequest, -+ ctrl.wValue, ctrl.wIndex, ctrl.wLength); -+ -+ /* Set direction of EP0 */ -+ if (likely(ctrl.bRequestType & USB_DIR_IN)) { -+ ep->is_in = 1; -+ dev->ep0state = EP0_IN; -+ } else { -+ ep->is_in = 0; -+ dev->ep0state = EP0_OUT; -+ } -+ -+ /* Nuke all previous transfers */ -+ nuke(ep, 0); -+ ep->stopped = 0; -+ -+ /* delegate everything to the gadget driver. -+ * it may respond after this irq handler returns. -+ */ -+ if (likely((u32)dev->driver)) { -+ /* device-2-host (IN) or no data setup command, process immediately */ -+ spin_unlock(&dev->lock); -+ tmp = dev->driver->setup(&dev->gadget, &ctrl); -+ spin_lock(&dev->lock); -+ -+ if (unlikely(tmp < 0)) { -+ /* setup processing failed, force stall */ -+ DEBUG_EP0("req %02x.%02x protocol STALL; err %d\n", -+ ctrl.bRequestType, ctrl.bRequest, tmp); -+ dev->ep0state = EP0_STALL; -+ } -+ } -+} -+ -+static int jz4730_ep0_in(struct jz4730_udc *dev) -+{ -+ struct jz4730_request *req; -+ struct jz4730_ep *ep = &dev->ep[0]; -+ int ret; -+ -+ if (list_empty(&ep->queue)) -+ req = 0; -+ else -+ req = list_entry(ep->queue.next, struct jz4730_request, queue); -+ -+ if (!req) { -+ DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__); -+ return 0; -+ } -+ -+ ret = write_fifo_ep0(ep, req); -+ -+ return ret; -+} -+ -+static void jz4730_ep0_out(struct jz4730_udc *dev) -+{ -+ u32 epsr; -+ struct jz4730_ep *ep = &dev->ep[0]; -+ -+ epsr = REG_UDC_EP0OutSR; -+ REG_UDC_EP0OutSR &= ~UDC_EPSR_OUT_MASK; -+ -+ if (epsr & UDC_EPSR_OUT_RCVSETUP) { -+ jz4730_ep0_setup(dev); -+ } -+ else if (epsr & UDC_EPSR_OUT_RCVDATA) { -+ u32 count = __udc_ep0out_packet_size(); -+ if (count == 0) { -+ readl((unsigned int *)UDC_RXCONFIRM); // ack zero packet -+ } -+ else { -+ /* EP0 OUT Data */ -+ if (list_empty(&ep->queue)) { -+ ep->irq_pending = 1; -+ pio_irq_disable(ep); -+ } -+ else -+ jz4730_epn_out(dev, 0, count); -+ -+ } -+ } -+} -+ -+static void handle_reset_irq(struct jz4730_udc *dev) -+{ -+ int i; -+ -+ /* clear any status */ -+ REG_UDC_EPIntR = 0xffffffff; -+ REG_UDC_DevIntR = 0xffffffff; -+ -+ /* reset udc */ -+ udc_reset(dev); -+ -+ /* reset driver status */ -+ for (i = 0; i < MAX_EP_NUM; i++) { -+ struct jz4730_ep *ep = &dev->ep[i]; -+ -+ ep->irq_pending = 0; -+// nuke(ep, 0); -+ nuke(ep, -ESHUTDOWN); -+ } -+} -+ -+static irqreturn_t jz4730_udc_irq(int irq, void *_dev) -+{ -+ struct jz4730_udc *dev = _dev; -+ struct jz4730_ep *ep; -+ -+ u32 intr_dev, intr_ep, stats, count; -+ -+ spin_lock(&dev->lock); -+ -+ intr_dev = REG_UDC_DevIntR; -+ intr_ep = REG_UDC_EPIntR; -+ -+ DEBUG("*** udc irq intr_dev=0x%x intr_ep=0x%x\n", intr_dev, intr_ep); -+ -+ if (!intr_dev && !intr_ep) { -+ spin_unlock(&dev->lock); -+ return IRQ_HANDLED; -+ } -+ -+ if (udc_debug) { -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ jz_udc_active = 1; -+#endif -+ REG_UDC_DevIntR = intr_dev; -+ REG_UDC_EPIntR = intr_ep; -+ __harb_usb0_uhc(); -+ __intc_mask_irq(IRQ_UDC); -+ spin_unlock(&dev->lock); -+ return IRQ_HANDLED; -+ } -+ -+ if (intr_dev) { -+ if (intr_dev & UDC_DevIntR_SC) { -+ psudo_set_config(); -+ udelay(100); -+ } -+ -+ if (intr_dev & UDC_DevIntR_UR) { -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ jz_udc_active = 1; -+#endif -+ handle_reset_irq(dev); -+ } -+ -+ REG_UDC_DevIntR = intr_dev; -+ } -+ -+ if (intr_ep & UDC_EPIntR_OUTEP0) { -+ REG_UDC_EPIntR = UDC_EPIntR_OUTEP0; -+ jz4730_ep0_out(dev); -+ } -+ -+ if (intr_ep & UDC_EPIntR_INEP0) { -+ ep = &dev->ep[0]; -+ if (list_empty(&ep->queue)) { -+ pio_irq_disable(ep); -+ } -+ else { -+ stats = REG_UDC_EP0InSR; -+ if (stats & UDC_EPSR_IN) { -+ REG_UDC_EPIntR = UDC_EPIntR_INEP0; -+ REG_UDC_EP0InSR &= ~UDC_EPSR_IN; -+ -+ jz4730_ep0_in(dev); -+ } -+ } -+ } -+ -+ if (intr_ep & UDC_EPIntR_OUTEP5) { -+ REG_UDC_EPIntR = UDC_EPIntR_OUTEP5; -+ ep = &dev->ep[5]; -+ if (list_empty(&ep->queue)) { -+ ep->irq_pending = 1; -+ pio_irq_disable(ep); -+ } -+ else { -+ stats = REG_UDC_EP5OutSR; -+ if (stats & UDC_EPSR_OUT_RCVDATA) { -+ REG_UDC_EP5OutSR &= ~UDC_EPSR_OUT_MASK; -+ -+ count = OUT_COUNT(stats); -+ jz4730_epn_out(dev, 5, count); -+ } -+ } -+ } -+ -+ if (intr_ep & UDC_EPIntR_INEP2) { -+ ep = &dev->ep[2]; -+ if (list_empty(&ep->queue)) { -+ ep->irq_pending = 1; -+ pio_irq_disable(ep); -+ } -+ else { -+ stats = REG_UDC_EP2InSR; -+ if (stats & UDC_EPSR_IN) { -+ REG_UDC_EP2InSR &= ~UDC_EPSR_IN; -+ jz4730_epn_in(dev, 2); -+ } -+ } -+ -+ REG_UDC_EPIntR = UDC_EPIntR_INEP2; -+ } -+ -+ if (intr_ep & UDC_EPIntR_INEP1) { -+ ep = &dev->ep[1]; -+ if (list_empty(&ep->queue)) { -+ ep->irq_pending = 1; -+ pio_irq_disable(ep); -+ } -+ else { -+ stats = REG_UDC_EP1InSR; -+ if (stats & UDC_EPSR_IN) { -+ REG_UDC_EP1InSR &= ~UDC_EPSR_IN; -+ jz4730_epn_in(dev, 1); -+ } -+ } -+ -+ REG_UDC_EPIntR = UDC_EPIntR_INEP1; -+ } -+ -+ spin_unlock(&dev->lock); -+ return IRQ_HANDLED; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static struct jz4730_udc udc_dev = { -+ .usb_address = 0, -+ -+ .gadget = { -+ .ops = &jz4730_ops, -+ .ep0 = &udc_dev.ep[0].ep, -+ .name = driver_name, -+ .dev = { -+ .bus_id = "gadget", -+ }, -+ }, -+ /* control endpoint no need to init here!*/ -+ /* control endpoint */ -+}; -+ -+ -+/* tear down the binding between this driver and the pci device */ -+static int jz4730_udc_remove(struct platform_device *pdev) -+{ -+ struct jz4730_udc *dev = platform_get_drvdata(pdev); -+ -+ if (dev->driver) -+ return -EBUSY; -+ -+ /* USB port0 as UHC */ -+ __harb_usb0_uhc(); -+ -+ /* reset udc */ -+ udc_reset(dev); -+ -+ /* clear any status */ -+ REG_UDC_EPIntR = 0xffffffff; -+ REG_UDC_DevIntR = 0xffffffff; -+ -+ /* disable all UDC interrupts */ -+ REG_UDC_DevIntMR = 0xffffffff; -+ REG_UDC_EPIntMR = 0xffffffff; -+ -+ free_irq(IRQ_UDC, dev); -+ platform_set_drvdata(pdev, 0); -+ device_unregister(&dev->gadget.dev); -+ the_controller = 0; -+ -+ return 0; -+} -+ -+static int jz4730_udc_probe(struct platform_device *pdev) -+{ -+ struct jz4730_udc *dev = &udc_dev; -+ int retval,rc; -+ -+ /* if you want to support more than one controller in a system, -+ * usb_gadget_driver_{register,unregister}() must change. -+ */ -+ if (the_controller) { -+ printk("Check the_controller: %s\n", driver_name); -+ return -EBUSY; -+ } -+ -+ spin_lock_init(&dev->lock); -+ device_initialize(&dev->gadget.dev); -+ dev->gadget.dev.parent = &pdev->dev; //if no,can only insmod once!! -+ dev->gadget.dev.release = jz4730_udc_release; -+ rc = device_register (&dev->gadget.dev); -+ if (rc < 0) -+ return rc; -+ platform_set_drvdata(pdev, dev); -+ -+ /* -+ * Note: we just mask INTC irq but allow UDC irq. -+ * This avoid that we miss any UDC irqs. -+ */ -+ -+ /* To avoid any UDC irqs here, we call cli() first */ -+// cli(); -+ -+ /* disable INTC irq */ -+ __intc_mask_irq(IRQ_UDC); -+ -+ /* init to known state, then setup irqs */ -+ udc_reset(dev); -+ udc_reinit(dev); -+ -+ /* request UDC irq */ -+ if (request_irq(IRQ_UDC, jz4730_udc_irq, IRQF_DISABLED, // SA_INTERRUPT, -+ driver_name, dev) != 0) { -+ printk(KERN_INFO "request UDC interrupt %d failed\n", IRQ_UDC); -+ retval = -EBUSY; -+ goto done; -+ } -+ -+ /* disable INTC irq again since request_irq has enabled it */ -+ __intc_mask_irq(IRQ_UDC); -+ __intc_ack_irq(IRQ_UDC); -+ -+ /* Re-enable irqs */ -+// sti(); -+ -+ printk(KERN_INFO "%s\n", driver_desc); -+ printk(KERN_INFO "version: " DRIVER_VERSION "\n"); -+ -+ /* done */ -+ the_controller = dev; -+ -+ return 0; -+ -+done: -+ if (dev) -+ jz4730_udc_remove (pdev); -+ return retval; -+} -+ -+static struct platform_driver udc_driver = { -+ .probe = jz4730_udc_probe, -+ .remove = jz4730_udc_remove, -+ .suspend = NULL, -+ .resume = NULL, -+ .driver = { -+ .name = (char *) driver_name, -+ .owner = THIS_MODULE, -+ }, -+}; -+static struct platform_device the_udc_pdev = { -+ .name = (char *) driver_name, -+ .id = -1, -+ .dev = { -+ .release = jz4730_udc_release, -+ }, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __init udc_init (void) -+{ -+ platform_driver_register(&udc_driver); -+ return platform_device_register (&the_udc_pdev); -+} -+ -+static void __exit udc_exit (void) -+{ -+ platform_driver_unregister(&udc_driver); -+ platform_device_unregister(&the_udc_pdev); -+} -+ -+module_init(udc_init); -+module_exit(udc_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR("Wei Jianli "); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/usb/gadget/jz4730_udc.h b/drivers/usb/gadget/jz4730_udc.h -new file mode 100644 -index 0000000..6ea368b ---- /dev/null -+++ b/drivers/usb/gadget/jz4730_udc.h -@@ -0,0 +1,107 @@ -+/* -+ * JZ4730 USB Device Controller driver -+ * -+ * Copyright (C) 2005 by Wei Jianli -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#ifndef __JZ4730_UDC_H__ -+#define __JZ4730_UDC_H__ -+ -+/* DRIVER DATA STRUCTURES and UTILITIES */ -+#define MAX_EP_NUM 8 /* Number of endpoints on this UDC */ -+ -+#define MAX_EP0_SIZE 32 -+#define MAX_EP1_SIZE 64 -+#define MAX_EP2_SIZE 64 -+#define MAX_EP3_SIZE 64 -+#define MAX_EP4_SIZE 64 -+#define MAX_EP5_SIZE 64 -+#define MAX_EP6_SIZE 64 -+#define MAX_EP7_SIZE 64 -+ -+// UDC FIFO -+#define RXFIFO (UDC_RXFIFO) /* EP0 OUT, EP5-7 OUT */ -+#define TXFIFOEP0 (UDC_TXFIFOEP0) /* EP0 IN */ -+#define TXFIFOEP1 (TXFIFOEP0 + MAX_EP0_SIZE) /* EP1 IN */ -+#define TXFIFOEP2 (TXFIFOEP1 + MAX_EP1_SIZE) /* EP2 IN */ -+#define TXFIFOEP3 (TXFIFOEP2 + MAX_EP2_SIZE) /* EP3 IN */ -+#define TXFIFOEP4 (TXFIFOEP3 + MAX_EP3_SIZE) /* EP4 IN */ -+ -+static u32 ep_fifo[MAX_EP_NUM] = {TXFIFOEP0, TXFIFOEP1, TXFIFOEP2, -+ TXFIFOEP3, TXFIFOEP4, RXFIFO, RXFIFO, -+ RXFIFO}; -+ -+#define OUT_COUNT(stats) \ -+ ((stats&UDC_EPSR_RXPKTSIZE_MASK)>>UDC_EPSR_RXPKTSIZE_BIT) -+ -+struct jz4730_ep { -+ struct usb_ep ep; -+ struct jz4730_udc *dev; -+ -+ u8 index; -+ u8 is_in; -+ u8 stopped; -+ u8 irq_pending; -+ u32 fifo; -+ -+ struct list_head queue; -+ const struct usb_endpoint_descriptor *desc; -+}; -+ -+struct jz4730_request { -+ struct usb_request req; -+ struct list_head queue; -+}; -+ -+enum ep0state { -+ EP0_DISCONNECT, /* no host */ -+ EP0_IDLE, /* between STATUS ack and SETUP report */ -+ EP0_IN, EP0_OUT, /* data stage */ -+ EP0_STATUS, /* status stage */ -+ EP0_STALL, /* data or status stages */ -+ EP0_SUSPEND, /* usb suspend */ -+}; -+ -+struct jz4730_udc { -+ struct usb_gadget gadget; -+ struct usb_gadget_driver *driver; -+ spinlock_t lock; -+ -+ struct jz4730_ep ep[MAX_EP_NUM]; -+ enum ep0state ep0state; -+ unsigned char usb_address; -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* 2.5 stuff that's sometimes missing in 2.4 */ -+ -+#ifndef container_of -+#define container_of list_entry -+#endif -+ -+#ifndef likely -+#define likely(x) (x) -+#define unlikely(x) (x) -+#endif -+ -+#ifndef BUG_ON -+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) -+#endif -+ -+#ifndef WARN_ON -+#define WARN_ON(x) do { } while (0) -+#endif -+ -+#ifndef IRQ_NONE -+typedef void irqreturn_t; -+#define IRQ_NONE -+#define IRQ_HANDLED -+#define IRQ_RETVAL(x) -+#endif -+ -+#endif /* __JZ4730_UDC_H__ */ -diff --git a/drivers/usb/gadget/jz4740_udc.c b/drivers/usb/gadget/jz4740_udc.c -new file mode 100644 -index 0000000..a1d5dbb ---- /dev/null -+++ b/drivers/usb/gadget/jz4740_udc.c -@@ -0,0 +1,2251 @@ -+/* -+ * linux/drivers/usb/gadget/jz4740_udc.c -+ * -+ * Ingenic JZ4740 on-chip high speed USB device controller -+ * -+ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+/* -+ * This device has ep0, two bulk-in/interrupt-in endpoints, and one bulk-out endpoint. -+ * -+ * - Endpoint numbering is fixed: ep0, ep1in-int, ep2in-bulk, ep1out-bulk. -+ * - DMA works with bulk-in (channel 1) and bulk-out (channel 2) endpoints. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz4740_udc.h" -+ -+//#define DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) -+//#define DEBUG(fmt,args...) printk(fmt , ## args) -+//#define DEBUG_EP0(fmt,args...) printk(fmt , ## args) -+//#define DEBUG_SETUP(fmt,args...) printk(fmt , ## args) -+ -+#ifndef DEBUG -+# define DEBUG(fmt,args...) do {} while(0) -+#endif -+#ifndef DEBUG_EP0 -+# define NO_STATES -+# define DEBUG_EP0(fmt,args...) do {} while(0) -+#endif -+#ifndef DEBUG_SETUP -+# define DEBUG_SETUP(fmt,args...) do {} while(0) -+#endif -+ -+static unsigned int udc_debug = 0; /* 0: normal mode, 1: test udc cable type mode */ -+ -+module_param(udc_debug, int, 0); -+MODULE_PARM_DESC(udc_debug, "test udc cable or power type"); -+ -+static unsigned int use_dma = 1; /* 1: use DMA, 0: use PIO */ -+ -+module_param(use_dma, int, 0); -+MODULE_PARM_DESC(use_dma, "DMA mode enable flag"); -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+extern int jz_udc_active; /* 0: No actions; 1: Have actions */ -+#endif -+ -+/* -+ * Local definintions. -+ */ -+ -+#define DRIVER_VERSION "13-Mar-2008" -+#define DRIVER_DESC "JZ4740 USB Device Controller" -+ -+static const char gadget_name [] = "jz4740_udc"; -+ -+struct jz4740_udc *the_controller; -+ -+static const char driver_name [] = "jz4740_udc"; -+static const char driver_desc [] = DRIVER_DESC; -+static const char ep0name[] = "ep0"; -+ -+#ifndef NO_STATES -+static char *state_names[] = { -+ "WAIT_FOR_SETUP", -+ "DATA_STATE_XMIT", -+ "DATA_STATE_NEED_ZLP", -+ "WAIT_FOR_OUT_STATUS", -+ "DATA_STATE_RECV" -+}; -+#endif -+ -+/* -+ * Local declarations. -+ */ -+static int jz4740_ep_enable(struct usb_ep *_ep, -+ const struct usb_endpoint_descriptor *desc); -+static int jz4740_ep_disable(struct usb_ep *_ep); -+static struct usb_request *jz4740_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags); -+static void jz4740_free_request(struct usb_ep *_ep, struct usb_request *_req); -+ -+static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags); -+static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req); -+static int jz4740_set_halt(struct usb_ep *_ep, int value); -+static int jz4740_fifo_status(struct usb_ep *_ep); -+static void jz4740_fifo_flush(struct usb_ep *_ep); -+ -+static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep); -+static void jz4740_handle_ep0(struct jz4740_udc *dev, u32 intr); -+ -+static void done(struct jz4740_ep *ep, struct jz4740_request *req, -+ int status); -+static void pio_irq_enable(struct jz4740_ep *ep); -+static void pio_irq_disable(struct jz4740_ep *ep); -+static void stop_activity(struct jz4740_udc *dev, -+ struct usb_gadget_driver *driver); -+static void nuke(struct jz4740_ep *ep, int status); -+static void flush(struct jz4740_ep *ep); -+static void udc_enable(struct jz4740_udc *dev); -+static void udc_set_address(struct jz4740_udc *dev, unsigned char address); -+static void jz4740_udc_release (struct device *dev) {} -+ -+extern void *dma_alloc_noncoherent(struct device *dev, size_t size, -+ dma_addr_t *dma_handle, gfp_t flag); -+extern void dma_free_noncoherent(struct device *dev, size_t size, -+ void *vaddr, dma_addr_t dma_handle); -+ -+static struct usb_ep_ops jz4740_ep_ops = { -+ .enable = jz4740_ep_enable, -+ .disable = jz4740_ep_disable, -+ -+ .alloc_request = jz4740_alloc_request, -+ .free_request = jz4740_free_request, -+ -+ .queue = jz4740_queue, -+ .dequeue = jz4740_dequeue, -+ -+ .set_halt = jz4740_set_halt, -+ .fifo_status = jz4740_fifo_status, -+ .fifo_flush = jz4740_fifo_flush, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* inline functions of register read/write/set/clear */ -+ -+static __inline__ u8 usb_readb(u32 port) -+{ -+ return *(volatile u8 *)port; -+} -+ -+static __inline__ u16 usb_readw(u32 port) -+{ -+ return *(volatile u16 *)port; -+} -+ -+static __inline__ u32 usb_readl(u32 port) -+{ -+ return *(volatile u32 *)port; -+} -+ -+static __inline__ void usb_writeb(u32 port, u8 val) -+{ -+ *(volatile u8 *)port = val; -+} -+ -+static __inline__ void usb_writew(u32 port, u16 val) -+{ -+ *(volatile u16 *)port = val; -+} -+ -+static __inline__ void usb_writel(u32 port, u32 val) -+{ -+ *(volatile u32 *)port = val; -+} -+ -+static __inline__ void usb_setb(u32 port, u8 val) -+{ -+ volatile u8 *ioport = (volatile u8 *)(port); -+ *ioport = (*ioport) | val; -+} -+ -+static __inline__ void usb_setw(u32 port, u16 val) -+{ -+ volatile u16 *ioport = (volatile u16 *)(port); -+ *ioport = (*ioport) | val; -+} -+ -+static __inline__ void usb_setl(u32 port, u32 val) -+{ -+ volatile u32 *ioport = (volatile u32 *)(port); -+ *ioport = (*ioport) | val; -+} -+ -+static __inline__ void usb_clearb(u32 port, u8 val) -+{ -+ volatile u8 *ioport = (volatile u8 *)(port); -+ *ioport = (*ioport) & ~val; -+} -+ -+static __inline__ void usb_clearw(u32 port, u16 val) -+{ -+ volatile u16 *ioport = (volatile u16 *)(port); -+ *ioport = (*ioport) & ~val; -+} -+ -+static __inline__ void usb_clearl(u32 port, u32 val) -+{ -+ volatile u32 *ioport = (volatile u32 *)(port); -+ *ioport = (*ioport) & ~val; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static __inline__ int write_packet(struct jz4740_ep *ep, -+ struct jz4740_request *req, int max) -+{ -+ u8 *buf; -+ int length, nlong, nbyte; -+ volatile u32 *fifo = (volatile u32 *)ep->fifo; -+ -+ buf = req->req.buf + req->req.actual; -+ prefetch(buf); -+ -+ length = req->req.length - req->req.actual; -+ length = min(length, max); -+ req->req.actual += length; -+ -+ DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo); -+ -+ nlong = length >> 2; -+ nbyte = length & 0x3; -+ while (nlong--) { -+ *fifo = *((u32 *)buf); -+ buf += 4; -+ } -+ while (nbyte--) { -+ *((volatile u8 *)fifo) = *buf++; -+ } -+ -+ return length; -+} -+ -+static __inline__ int read_packet(struct jz4740_ep *ep, -+ struct jz4740_request *req, int count) -+{ -+ u8 *buf; -+ int length, nlong, nbyte; -+ volatile u32 *fifo = (volatile u32 *)ep->fifo; -+ -+ buf = req->req.buf + req->req.actual; -+ prefetchw(buf); -+ -+ length = req->req.length - req->req.actual; -+ length = min(length, count); -+ req->req.actual += length; -+ -+ DEBUG("Read %d, fifo %p\n", length, fifo); -+ -+ nlong = length >> 2; -+ nbyte = length & 0x3; -+ while (nlong--) { -+ *((u32 *)buf) = *fifo; -+ buf += 4; -+ } -+ while (nbyte--) { -+ *buf++ = *((volatile u8 *)fifo); -+ } -+ -+ return length; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * udc_disable - disable USB device controller -+ */ -+static void udc_disable(struct jz4740_udc *dev) -+{ -+ DEBUG("%s, %p\n", __FUNCTION__, dev); -+ -+ udc_set_address(dev, 0); -+ -+ /* Disable interrupts */ -+ usb_writew(USB_REG_INTRINE, 0); -+ usb_writew(USB_REG_INTROUTE, 0); -+ usb_writeb(USB_REG_INTRUSBE, 0); -+ -+ /* Disable DMA */ -+ usb_writel(USB_REG_CNTL1, 0); -+ usb_writel(USB_REG_CNTL2, 0); -+ -+ /* Disconnect from usb */ -+ usb_clearb(USB_REG_POWER, USB_POWER_SOFTCONN); -+ -+ /* Disable the USB PHY */ -+#ifdef CONFIG_SOC_JZ4740 -+ REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; -+#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+ REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE; -+#endif -+ -+ dev->ep0state = WAIT_FOR_SETUP; -+ dev->gadget.speed = USB_SPEED_UNKNOWN; -+} -+ -+/* -+ * udc_reinit - initialize software state -+ */ -+static void udc_reinit(struct jz4740_udc *dev) -+{ -+ u32 i; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, dev); -+ -+ /* device/ep0 records init */ -+ INIT_LIST_HEAD(&dev->gadget.ep_list); -+ INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); -+ dev->ep0state = WAIT_FOR_SETUP; -+ -+ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { -+ struct jz4740_ep *ep = &dev->ep[i]; -+ -+ if (i != 0) -+ list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); -+ -+ INIT_LIST_HEAD(&ep->queue); -+ ep->desc = 0; -+ ep->stopped = 0; -+ ep->pio_irqs = 0; -+ } -+} -+ -+/* until it's enabled, this UDC should be completely invisible -+ * to any USB host. -+ */ -+static void udc_enable(struct jz4740_udc *dev) -+{ -+ int i; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, dev); -+ -+ dev->gadget.speed = USB_SPEED_UNKNOWN; -+ -+ /* Flush FIFO for each */ -+ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { -+ struct jz4740_ep *ep = &dev->ep[i]; -+ -+ usb_set_index(ep_index(ep)); -+ flush(ep); -+ } -+ -+ /* Set this bit to allow the UDC entering low-power mode when -+ * there are no actions on the USB bus. -+ * UDC still works during this bit was set. -+ */ -+ __cpm_stop_udc(); -+ -+ /* Enable the USB PHY */ -+#ifdef CONFIG_SOC_JZ4740 -+ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; -+#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+ REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE; -+#endif -+ -+ /* Disable interrupts */ -+ usb_writew(USB_REG_INTRINE, 0); -+ usb_writew(USB_REG_INTROUTE, 0); -+ usb_writeb(USB_REG_INTRUSBE, 0); -+ -+ /* Enable interrupts */ -+ usb_setw(USB_REG_INTRINE, USB_INTR_EP0); -+ usb_setb(USB_REG_INTRUSBE, USB_INTR_RESET); -+ /* Don't enable rest of the interrupts */ -+ /* usb_setw(USB_REG_INTRINE, USB_INTR_INEP1 | USB_INTR_INEP2); -+ usb_setw(USB_REG_INTROUTE, USB_INTR_OUTEP1); */ -+ -+ /* Enable SUSPEND */ -+ /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ -+ -+ /* Enable HS Mode */ -+ usb_setb(USB_REG_POWER, USB_POWER_HSENAB); -+ -+ /* Let host detect UDC: -+ * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this -+ * transistor on and pull the USBDP pin HIGH. -+ */ -+ usb_setb(USB_REG_POWER, USB_POWER_SOFTCONN); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* keeping it simple: -+ * - one bus driver, initted first; -+ * - one function driver, initted second -+ */ -+ -+/* -+ * Register entry point for the peripheral controller driver. -+ */ -+ -+int usb_gadget_register_driver(struct usb_gadget_driver *driver) -+{ -+ struct jz4740_udc *dev = the_controller; -+ int retval; -+ -+ if (!driver -+ || !driver->bind -+ || !driver->unbind || !driver->disconnect || !driver->setup) -+ { -+ printk("\n-EINVAL"); -+ return -EINVAL; -+ } -+ if (!dev) -+ { -+ printk("\n-ENODEV"); -+ return -ENODEV; -+ } -+ if (dev->driver) -+ { -+ printk("\n-ENODEV"); -+ return -EBUSY; -+ } -+ -+ /* hook up the driver */ -+ dev->driver = driver; -+ retval = driver->bind(&dev->gadget); -+ if (retval) { -+ DEBUG("%s: bind to driver %s --> error %d\n", dev->gadget.name, -+ driver->driver.name, retval); -+ dev->driver = 0; -+ return retval; -+ } -+ -+ /* then enable host detection and ep0; and we're ready -+ * for set_configuration as well as eventual disconnect. -+ */ -+ udc_enable(dev); -+ DEBUG("%s: registered gadget driver '%s'\n", dev->gadget.name, -+ driver->driver.name); -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL(usb_gadget_register_driver); -+ -+ -+static void stop_activity(struct jz4740_udc *dev, -+ struct usb_gadget_driver *driver) -+{ -+ int i; -+ -+ DEBUG("%s\n", __FUNCTION__); -+ -+ /* don't disconnect drivers more than once */ -+ if (dev->gadget.speed == USB_SPEED_UNKNOWN) -+ driver = 0; -+ dev->gadget.speed = USB_SPEED_UNKNOWN; -+ -+ /* prevent new request submissions, kill any outstanding requests */ -+ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { -+ struct jz4740_ep *ep = &dev->ep[i]; -+ -+ ep->stopped = 1; -+ -+ usb_set_index(ep_index(ep)); -+ nuke(ep, -ESHUTDOWN); -+ } -+ -+ /* report disconnect; the driver is already quiesced */ -+ if (driver) { -+ spin_unlock(&dev->lock); -+ driver->disconnect(&dev->gadget); -+ spin_lock(&dev->lock); -+ } -+ -+ /* re-init driver-visible data structures */ -+ udc_reinit(dev); -+} -+ -+ -+/* -+ * Unregister entry point for the peripheral controller driver. -+ */ -+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -+{ -+ struct jz4740_udc *dev = the_controller; -+ unsigned long flags; -+ -+ if (!dev) -+ return -ENODEV; -+ if (!driver || driver != dev->driver) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->driver = 0; -+ stop_activity(dev, driver); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ driver->unbind(&dev->gadget); -+ -+ udc_disable(dev); -+ -+ DEBUG("unregistered driver '%s'\n", driver->driver.name); -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL(usb_gadget_unregister_driver); -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * Starting DMA using mode 1 -+ */ -+static void kick_dma(struct jz4740_ep *ep, struct jz4740_request *req) -+{ -+ u32 count = req->req.length; -+ u32 physaddr = virt_to_phys((void *)req->req.buf); -+ -+ usb_set_index(ep_index(ep)); -+ if (ep_is_in(ep)) { /* Bulk-IN transfer using DMA channel 1 */ -+ ep->reg_addr = USB_REG_ADDR1; -+ -+ dma_cache_wback_inv((unsigned long)req->req.buf, count); -+ -+ pio_irq_enable(ep); -+ -+ usb_writeb(USB_REG_INCSRH, -+ USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE); -+ -+ usb_writel(USB_REG_ADDR1, physaddr); -+ usb_writel(USB_REG_COUNT1, count); -+ usb_writel(USB_REG_CNTL1, USB_CNTL_ENA | USB_CNTL_DIR_IN | USB_CNTL_MODE_1 | -+ USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep))); -+ } -+ else { /* Bulk-OUT transfer using DMA channel 2 */ -+ ep->reg_addr = USB_REG_ADDR2; -+ -+ dma_cache_wback_inv((unsigned long)req->req.buf, count); -+ -+ pio_irq_enable(ep); -+ -+ usb_setb(USB_REG_OUTCSRH, -+ USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); -+ -+ usb_writel(USB_REG_ADDR2, physaddr); -+ usb_writel(USB_REG_COUNT2, count); -+ usb_writel(USB_REG_CNTL2, USB_CNTL_ENA | USB_CNTL_MODE_1 | -+ USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep))); -+ } -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/** Write request to FIFO (max write == maxp size) -+ * Return: 0 = still running, 1 = completed, negative = errno -+ * NOTE: INDEX register must be set for EP -+ */ -+static int write_fifo(struct jz4740_ep *ep, struct jz4740_request *req) -+{ -+ u32 max, csr; -+ u32 physaddr = virt_to_phys((void *)req->req.buf); -+ -+ max = le16_to_cpu(ep->desc->wMaxPacketSize); -+ -+ if (use_dma) { -+ u32 dma_count; -+ -+ /* DMA interrupt generated due to the last packet loaded into the FIFO */ -+ -+ dma_count = usb_readl(ep->reg_addr) - physaddr; -+ req->req.actual += dma_count; -+ -+ if (dma_count % max) { -+ /* If the last packet is less than MAXP, set INPKTRDY manually */ -+ usb_setb(ep->csr, USB_INCSR_INPKTRDY); -+ } -+ -+ done(ep, req, 0); -+ if (list_empty(&ep->queue)) { -+ pio_irq_disable(ep); -+ return 1; -+ } -+ else { -+ /* advance the request queue */ -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ kick_dma(ep, req); -+ return 0; -+ } -+ } -+ -+ /* -+ * PIO mode handling starts here ... -+ */ -+ -+ csr = usb_readb(ep->csr); -+ -+ if (!(csr & USB_INCSR_FFNOTEMPT)) { -+ unsigned count; -+ int is_last, is_short; -+ -+ count = write_packet(ep, req, max); -+ usb_setb(ep->csr, USB_INCSR_INPKTRDY); -+ -+ /* last packet is usually short (or a zlp) */ -+ if (unlikely(count != max)) -+ is_last = is_short = 1; -+ else { -+ if (likely(req->req.length != req->req.actual) -+ || req->req.zero) -+ is_last = 0; -+ else -+ is_last = 1; -+ /* interrupt/iso maxpacket may not fill the fifo */ -+ is_short = unlikely(max < ep_maxpacket(ep)); -+ } -+ -+ DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__, -+ ep->ep.name, count, -+ is_last ? "/L" : "", is_short ? "/S" : "", -+ req->req.length - req->req.actual, req); -+ -+ /* requests complete when all IN data is in the FIFO */ -+ if (is_last) { -+ done(ep, req, 0); -+ if (list_empty(&ep->queue)) { -+ pio_irq_disable(ep); -+ } -+ return 1; -+ } -+ } else { -+ DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep)); -+ } -+ -+ return 0; -+} -+ -+/** Read to request from FIFO (max read == bytes in fifo) -+ * Return: 0 = still running, 1 = completed, negative = errno -+ * NOTE: INDEX register must be set for EP -+ */ -+static int read_fifo(struct jz4740_ep *ep, struct jz4740_request *req) -+{ -+ u32 csr; -+ unsigned count, is_short; -+ u32 physaddr = virt_to_phys((void *)req->req.buf); -+ -+ if (use_dma) { -+ u32 dma_count; -+ -+ /* DMA interrupt generated due to a packet less than MAXP loaded into the FIFO */ -+ -+ dma_count = usb_readl(ep->reg_addr) - physaddr; -+ req->req.actual += dma_count; -+ -+ /* Disable interrupt and DMA */ -+ pio_irq_disable(ep); -+ usb_writel(USB_REG_CNTL2, 0); -+ -+ /* Read all bytes from this packet */ -+ count = usb_readw(USB_REG_OUTCOUNT); -+ count = read_packet(ep, req, count); -+ -+ if (count) { -+ /* If the last packet is greater than zero, clear OUTPKTRDY manually */ -+ usb_clearb(ep->csr, USB_OUTCSR_OUTPKTRDY); -+ } -+ -+ done(ep, req, 0); -+ -+ if (!list_empty(&ep->queue)) { -+ /* advance the request queue */ -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ kick_dma(ep, req); -+ } -+ -+ return 1; -+ } -+ -+ /* -+ * PIO mode handling starts here ... -+ */ -+ -+ /* make sure there's a packet in the FIFO. */ -+ csr = usb_readb(ep->csr); -+ if (!(csr & USB_OUTCSR_OUTPKTRDY)) { -+ DEBUG("%s: Packet NOT ready!\n", __FUNCTION__); -+ return -EINVAL; -+ } -+ -+ /* read all bytes from this packet */ -+ count = usb_readw(USB_REG_OUTCOUNT); -+ -+ is_short = (count < ep->ep.maxpacket); -+ -+ count = read_packet(ep, req, count); -+ -+ DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n", -+ ep->ep.name, csr, count, -+ is_short ? "/S" : "", req, req->req.actual, req->req.length); -+ -+ /* Clear OutPktRdy */ -+ usb_clearb(ep->csr, USB_OUTCSR_OUTPKTRDY); -+ -+ /* completion */ -+ if (is_short || req->req.actual == req->req.length) { -+ done(ep, req, 0); -+ -+ if (list_empty(&ep->queue)) -+ pio_irq_disable(ep); -+ return 1; -+ } -+ -+ /* finished that packet. the next one may be waiting... */ -+ return 0; -+} -+ -+/* -+ * done - retire a request; caller blocked irqs -+ * INDEX register is preserved to keep same -+ */ -+static void done(struct jz4740_ep *ep, struct jz4740_request *req, int status) -+{ -+ unsigned int stopped = ep->stopped; -+ u32 index; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, ep); -+ list_del_init(&req->queue); -+ -+ if (likely(req->req.status == -EINPROGRESS)) -+ req->req.status = status; -+ else -+ status = req->req.status; -+ -+ if (status && status != -ESHUTDOWN) -+ DEBUG("complete %s req %p stat %d len %u/%u\n", -+ ep->ep.name, &req->req, status, -+ req->req.actual, req->req.length); -+ -+ /* don't modify queue heads during completion callback */ -+ ep->stopped = 1; -+ /* Read current index (completion may modify it) */ -+ index = usb_readb(USB_REG_INDEX); -+ -+ spin_unlock(&ep->dev->lock); -+ req->req.complete(&ep->ep, &req->req); -+ spin_lock(&ep->dev->lock); -+ -+ /* Restore index */ -+ usb_set_index(index); -+ ep->stopped = stopped; -+} -+ -+/** Enable EP interrupt */ -+static void pio_irq_enable(struct jz4740_ep *ep) -+{ -+ DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT"); -+ -+ if (ep_is_in(ep)) { -+ switch (ep_index(ep)) { -+ case 1: -+ usb_setw(USB_REG_INTRINE, USB_INTR_INEP1); -+ break; -+ case 2: -+ usb_setw(USB_REG_INTRINE, USB_INTR_INEP2); -+ break; -+ default: -+ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -+ break; -+ } -+ } -+ else { -+ switch (ep_index(ep)) { -+ case 1: -+ usb_setw(USB_REG_INTROUTE, USB_INTR_OUTEP1); -+ break; -+ default: -+ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -+ break; -+ } -+ } -+} -+ -+/** Disable EP interrupt */ -+static void pio_irq_disable(struct jz4740_ep *ep) -+{ -+ DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT"); -+ -+ if (ep_is_in(ep)) { -+ switch (ep_index(ep)) { -+ case 1: -+ usb_clearw(USB_REG_INTRINE, USB_INTR_INEP1); -+ break; -+ case 2: -+ usb_clearw(USB_REG_INTRINE, USB_INTR_INEP2); -+ break; -+ default: -+ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -+ break; -+ } -+ } -+ else { -+ switch (ep_index(ep)) { -+ case 1: -+ usb_clearw(USB_REG_INTROUTE, USB_INTR_OUTEP1); -+ break; -+ default: -+ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -+ break; -+ } -+ } -+} -+ -+/* -+ * nuke - dequeue ALL requests -+ */ -+static void nuke(struct jz4740_ep *ep, int status) -+{ -+ struct jz4740_request *req; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, ep); -+ -+ /* Flush FIFO */ -+ flush(ep); -+ -+ /* called with irqs blocked */ -+ while (!list_empty(&ep->queue)) { -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ done(ep, req, status); -+ } -+ -+ /* Disable IRQ if EP is enabled (has descriptor) */ -+ if (ep->desc) -+ pio_irq_disable(ep); -+} -+ -+/** Flush EP FIFO -+ * NOTE: INDEX register must be set before this call -+ */ -+static void flush(struct jz4740_ep *ep) -+{ -+ DEBUG("%s, %p\n", __FUNCTION__, ep); -+ -+ switch (ep->ep_type) { -+ case ep_control: -+ break; -+ -+ case ep_bulk_in: -+ case ep_interrupt: -+ usb_setb(ep->csr, USB_INCSR_FF); -+ break; -+ -+ case ep_bulk_out: -+ usb_setb(ep->csr, USB_OUTCSR_FF); -+ break; -+ } -+} -+ -+/** -+ * jz4740_in_epn - handle IN interrupt -+ */ -+static void jz4740_in_epn(struct jz4740_udc *dev, u32 ep_idx, u32 intr) -+{ -+ u32 csr; -+ struct jz4740_ep *ep = &dev->ep[ep_idx + 1]; -+ struct jz4740_request *req; -+ -+ usb_set_index(ep_index(ep)); -+ -+ csr = usb_readb(ep->csr); -+ DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr); -+ -+ if (csr & USB_INCSR_SENTSTALL) { -+ DEBUG("USB_INCSR_SENTSTALL\n"); -+ usb_clearb(ep->csr, USB_INCSR_SENTSTALL); -+ return; -+ } -+ -+ if (!ep->desc) { -+ DEBUG("%s: NO EP DESC\n", __FUNCTION__); -+ return; -+ } -+ -+ if (list_empty(&ep->queue)) -+ req = 0; -+ else -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ -+ DEBUG("req: %p\n", req); -+ -+ if (!req) -+ return; -+ -+ write_fifo(ep, req); -+} -+ -+/* -+ * Bulk OUT (recv) -+ */ -+static void jz4740_out_epn(struct jz4740_udc *dev, u32 ep_idx, u32 intr) -+{ -+ struct jz4740_ep *ep = &dev->ep[ep_idx]; -+ struct jz4740_request *req; -+ -+ DEBUG("%s: %d\n", __FUNCTION__, ep_idx); -+ -+ usb_set_index(ep_index(ep)); -+ if (ep->desc) { -+ u32 csr; -+ -+ if (use_dma) { -+ /* DMA starts here ... */ -+ if (list_empty(&ep->queue)) -+ req = 0; -+ else -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ -+ if (req) -+ read_fifo(ep, req); -+ return; -+ } -+ -+ /* -+ * PIO mode starts here ... -+ */ -+ -+ while ((csr = usb_readb(ep->csr)) & -+ (USB_OUTCSR_OUTPKTRDY | USB_OUTCSR_SENTSTALL)) { -+ DEBUG("%s: %x\n", __FUNCTION__, csr); -+ -+ if (csr & USB_OUTCSR_SENTSTALL) { -+ DEBUG("%s: stall sent, flush fifo\n", -+ __FUNCTION__); -+ /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */ -+ flush(ep); -+ } else if (csr & USB_OUTCSR_OUTPKTRDY) { -+ if (list_empty(&ep->queue)) -+ req = 0; -+ else -+ req = -+ list_entry(ep->queue.next, -+ struct jz4740_request, -+ queue); -+ -+ if (!req) { -+ DEBUG("%s: NULL REQ %d\n", -+ __FUNCTION__, ep_idx); -+ break; -+ } else { -+ read_fifo(ep, req); -+ } -+ } -+ } -+ } else { -+ /* Throw packet away.. */ -+ printk("%s: ep %p ep_indx %d No descriptor?!?\n", __FUNCTION__, ep, ep_idx); -+ flush(ep); -+ } -+} -+ -+static int jz4740_ep_enable(struct usb_ep *_ep, -+ const struct usb_endpoint_descriptor *desc) -+{ -+ struct jz4740_ep *ep; -+ struct jz4740_udc *dev; -+ unsigned long flags; -+ u32 max, csrh = 0; -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (!_ep || !desc || ep->desc || _ep->name == ep0name -+ || desc->bDescriptorType != USB_DT_ENDPOINT -+ || ep->bEndpointAddress != desc->bEndpointAddress) { -+ DEBUG("%s, bad ep or descriptor\n", __FUNCTION__); -+ return -EINVAL; -+ } -+ -+ /* xfer types must match, except that interrupt ~= bulk */ -+ if (ep->bmAttributes != desc->bmAttributes -+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK -+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { -+ DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name); -+ return -EINVAL; -+ } -+ -+ dev = ep->dev; -+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { -+ DEBUG("%s, bogus device state\n", __FUNCTION__); -+ return -ESHUTDOWN; -+ } -+ -+ max = le16_to_cpu(desc->wMaxPacketSize); -+ -+ /* Configure the endpoint */ -+ usb_set_index(desc->bEndpointAddress & 0x0F); -+ if (ep_is_in(ep)) { -+ usb_writew(USB_REG_INMAXP, max); -+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -+ case USB_ENDPOINT_XFER_BULK: -+ case USB_ENDPOINT_XFER_INT: -+ csrh &= ~USB_INCSRH_ISO; -+ break; -+ case USB_ENDPOINT_XFER_ISOC: -+ csrh |= USB_INCSRH_ISO; -+ break; -+ } -+ usb_writeb(USB_REG_INCSRH, csrh); -+ } -+ else { -+ usb_writew(USB_REG_OUTMAXP, max); -+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -+ case USB_ENDPOINT_XFER_BULK: -+ csrh &= ~USB_OUTCSRH_ISO; -+ break; -+ case USB_ENDPOINT_XFER_INT: -+ csrh &= ~USB_OUTCSRH_ISO; -+ csrh |= USB_OUTCSRH_DNYT; -+ break; -+ case USB_ENDPOINT_XFER_ISOC: -+ csrh |= USB_OUTCSRH_ISO; -+ break; -+ } -+ usb_writeb(USB_REG_OUTCSRH, csrh); -+ } -+ -+ spin_lock_irqsave(&ep->dev->lock, flags); -+ -+ ep->stopped = 0; -+ ep->desc = desc; -+ ep->pio_irqs = 0; -+ ep->ep.maxpacket = max; -+ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ -+ /* Reset halt state (does flush) */ -+ jz4740_set_halt(_ep, 0); -+ -+ DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name); -+ -+ return 0; -+} -+ -+/** Disable EP -+ * NOTE: Sets INDEX register -+ */ -+static int jz4740_ep_disable(struct usb_ep *_ep) -+{ -+ struct jz4740_ep *ep; -+ unsigned long flags; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, _ep); -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (!_ep || !ep->desc) { -+ DEBUG("%s, %s not enabled\n", __FUNCTION__, -+ _ep ? ep->ep.name : NULL); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&ep->dev->lock, flags); -+ -+ usb_set_index(ep_index(ep)); -+ -+ /* Nuke all pending requests (does flush) */ -+ nuke(ep, -ESHUTDOWN); -+ -+ /* Disable ep IRQ */ -+ pio_irq_disable(ep); -+ -+ ep->desc = 0; -+ ep->stopped = 1; -+ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ -+ DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name); -+ return 0; -+} -+ -+static struct usb_request *jz4740_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) -+{ -+ struct jz4740_request *req; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, ep); -+ -+ req = kzalloc(sizeof(*req), gfp_flags); -+ if (!req) -+ return 0; -+ -+ INIT_LIST_HEAD(&req->queue); -+ -+ return &req->req; -+} -+ -+static void jz4740_free_request(struct usb_ep *ep, struct usb_request *_req) -+{ -+ struct jz4740_request *req; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, ep); -+ -+ req = container_of(_req, struct jz4740_request, req); -+ WARN_ON(!list_empty(&req->queue)); -+ kfree(req); -+} -+ -+/*--------------------------------------------------------------------*/ -+ -+/** Queue one request -+ * Kickstart transfer if needed -+ * NOTE: Sets INDEX register -+ */ -+static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req, -+ gfp_t gfp_flags) -+{ -+ struct jz4740_request *req; -+ struct jz4740_ep *ep; -+ struct jz4740_udc *dev; -+ unsigned long flags; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, _ep); -+ -+ req = container_of(_req, struct jz4740_request, req); -+ if (unlikely -+ (!_req || !_req->complete || !_req->buf -+ || !list_empty(&req->queue))) { -+ DEBUG("%s, bad params\n", __FUNCTION__); -+ return -EINVAL; -+ } -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { -+ DEBUG("%s, bad ep\n", __FUNCTION__); -+ return -EINVAL; -+ } -+ -+ dev = ep->dev; -+ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { -+ DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver); -+ return -ESHUTDOWN; -+ } -+ -+ DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, -+ _req->buf); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ _req->status = -EINPROGRESS; -+ _req->actual = 0; -+ -+ /* kickstart this i/o queue? */ -+ DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue), -+ ep->stopped); -+ if (list_empty(&ep->queue) && likely(!ep->stopped)) { -+ u32 csr; -+ -+ if (unlikely(ep_index(ep) == 0)) { -+ /* EP0 */ -+ list_add_tail(&req->queue, &ep->queue); -+ jz4740_ep0_kick(dev, ep); -+ req = 0; -+ } else if (use_dma) { -+ /* DMA */ -+ kick_dma(ep, req); -+ } -+ /* PIO */ -+ else if (ep_is_in(ep)) { -+ /* EP1 & EP2 */ -+ usb_set_index(ep_index(ep)); -+ csr = usb_readb(ep->csr); -+ pio_irq_enable(ep); -+ if (!(csr & USB_INCSR_FFNOTEMPT)) { -+ if (write_fifo(ep, req) == 1) -+ req = 0; -+ } -+ } else { -+ /* EP1 */ -+ usb_set_index(ep_index(ep)); -+ csr = usb_readb(ep->csr); -+ pio_irq_enable(ep); -+ if (csr & USB_OUTCSR_OUTPKTRDY) { -+ if (read_fifo(ep, req) == 1) -+ req = 0; -+ } -+ } -+ } -+ -+ /* pio or dma irq handler advances the queue. */ -+ if (likely(req != 0)) -+ list_add_tail(&req->queue, &ep->queue); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+/* dequeue JUST ONE request */ -+static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct jz4740_ep *ep; -+ struct jz4740_request *req; -+ unsigned long flags; -+ -+ DEBUG("%s, %p\n", __FUNCTION__, _ep); -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (!_ep || ep->ep.name == ep0name) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&ep->dev->lock, flags); -+ -+ /* make sure it's actually queued on this endpoint */ -+ list_for_each_entry(req, &ep->queue, queue) { -+ if (&req->req == _req) -+ break; -+ } -+ if (&req->req != _req) { -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ return -EINVAL; -+ } -+ -+ done(ep, req, -ECONNRESET); -+ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ return 0; -+} -+ -+/** Halt specific EP -+ * Return 0 if success -+ * NOTE: Sets INDEX register to EP ! -+ */ -+static int jz4740_set_halt(struct usb_ep *_ep, int value) -+{ -+ struct jz4740_ep *ep; -+ unsigned long flags; -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { -+ DEBUG("%s, bad ep\n", __FUNCTION__); -+ return -EINVAL; -+ } -+ -+ usb_set_index(ep_index(ep)); -+ -+ DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value); -+ -+ spin_lock_irqsave(&ep->dev->lock, flags); -+ -+ if (ep_index(ep) == 0) { -+ /* EP0 */ -+ usb_setb(USB_REG_CSR0, USB_CSR0_SENDSTALL); -+ } else if (ep_is_in(ep)) { -+ u32 csr = usb_readb(ep->csr); -+ if (value && ((csr & USB_INCSR_FFNOTEMPT) -+ || !list_empty(&ep->queue))) { -+ /* -+ * Attempts to halt IN endpoints will fail (returning -EAGAIN) -+ * if any transfer requests are still queued, or if the controller -+ * FIFO still holds bytes that the host hasnÂ’t collected. -+ */ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ DEBUG -+ ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n", -+ (csr & USB_INCSR_FFNOTEMPT), -+ !list_empty(&ep->queue)); -+ return -EAGAIN; -+ } -+ flush(ep); -+ if (value) { -+ usb_setb(ep->csr, USB_INCSR_SENDSTALL); -+ } -+ else { -+ usb_clearb(ep->csr, USB_INCSR_SENDSTALL); -+ usb_setb(ep->csr, USB_INCSR_CDT); -+ } -+ } else { -+ -+ flush(ep); -+ if (value) { -+ usb_setb(ep->csr, USB_OUTCSR_SENDSTALL); -+ } -+ else { -+ usb_clearb(ep->csr, USB_OUTCSR_SENDSTALL); -+ usb_setb(ep->csr, USB_OUTCSR_CDT); -+ } -+ } -+ -+ if (value) { -+ ep->stopped = 1; -+ } else { -+ ep->stopped = 0; -+ } -+ -+ spin_unlock_irqrestore(&ep->dev->lock, flags); -+ -+ DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS"); -+ -+ return 0; -+} -+ -+/** Return bytes in EP FIFO -+ * NOTE: Sets INDEX register to EP -+ */ -+static int jz4740_fifo_status(struct usb_ep *_ep) -+{ -+ u32 csr; -+ int count = 0; -+ struct jz4740_ep *ep; -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (!_ep) { -+ DEBUG("%s, bad ep\n", __FUNCTION__); -+ return -ENODEV; -+ } -+ -+ DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep)); -+ -+ /* LPD can't report unclaimed bytes from IN fifos */ -+ if (ep_is_in(ep)) -+ return -EOPNOTSUPP; -+ -+ usb_set_index(ep_index(ep)); -+ -+ csr = usb_readb(ep->csr); -+ if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN || -+ csr & 0x1) { -+ count = usb_readw(USB_REG_OUTCOUNT); -+ } -+ -+ return count; -+} -+ -+/** Flush EP FIFO -+ * NOTE: Sets INDEX register to EP -+ */ -+static void jz4740_fifo_flush(struct usb_ep *_ep) -+{ -+ struct jz4740_ep *ep; -+ -+ ep = container_of(_ep, struct jz4740_ep, ep); -+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { -+ DEBUG("%s, bad ep\n", __FUNCTION__); -+ return; -+ } -+ -+ usb_set_index(ep_index(ep)); -+ flush(ep); -+} -+ -+/****************************************************************/ -+/* End Point 0 related functions */ -+/****************************************************************/ -+ -+/* return: 0 = still running, 1 = completed, negative = errno */ -+static int write_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req) -+{ -+ u32 max; -+ unsigned count; -+ int is_last; -+ -+ max = ep_maxpacket(ep); -+ -+ count = write_packet(ep, req, max); -+ -+ /* last packet is usually short (or a zlp) */ -+ if (unlikely(count != max)) -+ is_last = 1; -+ else { -+ if (likely(req->req.length != req->req.actual) || req->req.zero) -+ is_last = 0; -+ else -+ is_last = 1; -+ } -+ -+ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__, -+ ep->ep.name, count, -+ is_last ? "/L" : "", req->req.length - req->req.actual, req); -+ -+ /* requests complete when all IN data is in the FIFO */ -+ if (is_last) { -+ done(ep, req, 0); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static __inline__ int jz4740_fifo_read(struct jz4740_ep *ep, -+ unsigned char *cp, int max) -+{ -+ int bytes; -+ int count = usb_readw(USB_REG_OUTCOUNT); -+ volatile u8 *fifo = (volatile u8 *)ep->fifo; -+ -+ if (count > max) -+ count = max; -+ bytes = count; -+ while (count--) -+ *cp++ = *fifo; -+ return bytes; -+} -+ -+static __inline__ void jz4740_fifo_write(struct jz4740_ep *ep, -+ unsigned char *cp, int count) -+{ -+ volatile u8 *fifo = (volatile u8 *)ep->fifo; -+ DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count); -+ while (count--) -+ *fifo = *cp++; -+} -+ -+static int read_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req) -+{ -+ u32 csr; -+ u8 *buf; -+ unsigned bufferspace, count, is_short; -+ volatile u8 *fifo = (volatile u8 *)ep->fifo; -+ -+ DEBUG_EP0("%s\n", __FUNCTION__); -+ -+ csr = usb_readb(USB_REG_CSR0); -+ if (!(csr & USB_CSR0_OUTPKTRDY)) -+ return 0; -+ -+ buf = req->req.buf + req->req.actual; -+ prefetchw(buf); -+ bufferspace = req->req.length - req->req.actual; -+ -+ /* read all bytes from this packet */ -+ if (likely(csr & USB_CSR0_OUTPKTRDY)) { -+ count = usb_readw(USB_REG_OUTCOUNT); -+ req->req.actual += min(count, bufferspace); -+ } else /* zlp */ -+ count = 0; -+ -+ is_short = (count < ep->ep.maxpacket); -+ DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n", -+ ep->ep.name, csr, count, -+ is_short ? "/S" : "", req, req->req.actual, req->req.length); -+ -+ while (likely(count-- != 0)) { -+ u8 byte = (u8) (*fifo & 0xff); -+ -+ if (unlikely(bufferspace == 0)) { -+ /* this happens when the driver's buffer -+ * is smaller than what the host sent. -+ * discard the extra data. -+ */ -+ if (req->req.status != -EOVERFLOW) -+ DEBUG_EP0("%s overflow %d\n", ep->ep.name, -+ count); -+ req->req.status = -EOVERFLOW; -+ } else { -+ *buf++ = byte; -+ bufferspace--; -+ } -+ } -+ -+ /* completion */ -+ if (is_short || req->req.actual == req->req.length) { -+ done(ep, req, 0); -+ return 1; -+ } -+ -+ /* finished that packet. the next one may be waiting... */ -+ return 0; -+} -+ -+/** -+ * udc_set_address - set the USB address for this device -+ * @address: -+ * -+ * Called from control endpoint function after it decodes a set address setup packet. -+ */ -+static void udc_set_address(struct jz4740_udc *dev, unsigned char address) -+{ -+ DEBUG_EP0("%s: %d\n", __FUNCTION__, address); -+ -+ dev->usb_address = address; -+ usb_writeb(USB_REG_FADDR, address); -+} -+ -+/* -+ * DATA_STATE_RECV (USB_CSR0_OUTPKTRDY) -+ * - if error -+ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits -+ * - else -+ * set USB_CSR0_SVDOUTPKTRDY bit -+ if last set USB_CSR0_DATAEND bit -+ */ -+static void jz4740_ep0_out(struct jz4740_udc *dev, u32 csr) -+{ -+ struct jz4740_request *req; -+ struct jz4740_ep *ep = &dev->ep[0]; -+ int ret; -+ -+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -+ -+ if (list_empty(&ep->queue)) -+ req = 0; -+ else -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ -+ if (req) { -+ if (req->req.length == 0) { -+ DEBUG_EP0("ZERO LENGTH OUT!\n"); -+/* usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); */ -+ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY)); -+ dev->ep0state = WAIT_FOR_SETUP; -+ return; -+ } -+ ret = read_fifo_ep0(ep, req); -+ if (ret) { -+ /* Done! */ -+ DEBUG_EP0("%s: finished, waiting for status\n", -+ __FUNCTION__); -+ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -+ dev->ep0state = WAIT_FOR_SETUP; -+ } else { -+ /* Not done yet.. */ -+ DEBUG_EP0("%s: not finished\n", __FUNCTION__); -+ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -+ } -+ } else { -+ DEBUG_EP0("NO REQ??!\n"); -+ } -+} -+ -+/* -+ * DATA_STATE_XMIT -+ */ -+static int jz4740_ep0_in(struct jz4740_udc *dev, u32 csr) -+{ -+ struct jz4740_request *req; -+ struct jz4740_ep *ep = &dev->ep[0]; -+ int ret, need_zlp = 0; -+ -+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -+ -+ if (list_empty(&ep->queue)) -+ req = 0; -+ else -+ req = list_entry(ep->queue.next, struct jz4740_request, queue); -+ -+ if (!req) { -+ DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__); -+ return 0; -+ } -+ -+ if (req->req.length == 0) { -+ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -+ dev->ep0state = WAIT_FOR_SETUP; -+ return 1; -+ } -+ -+ if (req->req.length - req->req.actual == EP0_MAXPACKETSIZE) { -+ /* Next write will end with the packet size, */ -+ /* so we need zero-length-packet */ -+ need_zlp = 1; -+ } -+ -+ ret = write_fifo_ep0(ep, req); -+ -+ if (ret == 1 && !need_zlp) { -+ /* Last packet */ -+ DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__); -+ -+ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -+ dev->ep0state = WAIT_FOR_SETUP; -+ } else { -+ DEBUG_EP0("%s: not finished\n", __FUNCTION__); -+ usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); -+ } -+ -+ if (need_zlp) { -+ DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__); -+ usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); -+ dev->ep0state = DATA_STATE_NEED_ZLP; -+ } -+ -+ return 1; -+} -+ -+#if 0 -+static int jz4740_handle_get_status(struct jz4740_udc *dev, -+ struct usb_ctrlrequest *ctrl) -+{ -+ struct jz4740_ep *ep0 = &dev->ep[0]; -+ struct jz4740_ep *qep; -+ int reqtype = (ctrl->bRequestType & USB_RECIP_MASK); -+ u16 val = 0; -+ -+ if (reqtype == USB_RECIP_INTERFACE) { -+ /* This is not supported. -+ * And according to the USB spec, this one does nothing.. -+ * Just return 0 -+ */ -+ DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n"); -+ } else if (reqtype == USB_RECIP_DEVICE) { -+ DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n"); -+ val |= (1 << 0); /* Self powered */ -+ /*val |= (1<<1); *//* Remote wakeup */ -+ } else if (reqtype == USB_RECIP_ENDPOINT) { -+ int ep_num = (ctrl->wIndex & ~USB_DIR_IN); -+ -+ DEBUG_SETUP -+ ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n", -+ ep_num, ctrl->wLength); -+ -+ if (ctrl->wLength > 2 || ep_num > 3) -+ return -EOPNOTSUPP; -+ -+ qep = &dev->ep[ep_num]; -+ if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0) -+ && ep_index(qep) != 0) { -+ return -EOPNOTSUPP; -+ } -+ -+ usb_set_index(ep_index(qep)); -+ -+ /* Return status on next IN token */ -+ switch (qep->ep_type) { -+ case ep_control: -+ val = -+ (usb_readb(qep->csr) & USB_CSR0_SENDSTALL) == -+ USB_CSR0_SENDSTALL; -+ break; -+ case ep_bulk_in: -+ case ep_interrupt: -+ val = -+ (usb_readb(qep->csr) & USB_INCSR_SENDSTALL) == -+ USB_INCSR_SENDSTALL; -+ break; -+ case ep_bulk_out: -+ val = -+ (usb_readb(qep->csr) & USB_OUTCSR_SENDSTALL) == -+ USB_OUTCSR_SENDSTALL; -+ break; -+ } -+ -+ /* Back to EP0 index */ -+ usb_set_index(0); -+ -+ DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num, -+ ctrl->wIndex, val); -+ } else { -+ DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype); -+ return -EOPNOTSUPP; -+ } -+ -+ /* Clear "out packet ready" */ -+ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -+ /* Put status to FIFO */ -+ jz4740_fifo_write(ep0, (u8 *) & val, sizeof(val)); -+ /* Issue "In packet ready" */ -+ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -+ -+ return 0; -+} -+#endif -+ -+/* -+ * WAIT_FOR_SETUP (OUTPKTRDY) -+ * - read data packet from EP0 FIFO -+ * - decode command -+ * - if error -+ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits -+ * - else -+ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND bits -+ */ -+static void jz4740_ep0_setup(struct jz4740_udc *dev, u32 csr) -+{ -+ struct jz4740_ep *ep = &dev->ep[0]; -+ struct usb_ctrlrequest ctrl; -+ int i; -+ -+ DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr); -+ -+ /* Nuke all previous transfers */ -+ nuke(ep, -EPROTO); -+ -+ /* read control req from fifo (8 bytes) */ -+ jz4740_fifo_read(ep, (unsigned char *)&ctrl, 8); -+ -+ DEBUG_SETUP("SETUP %02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bRequestType, ctrl.bRequest, -+ ctrl.wValue, ctrl.wIndex, ctrl.wLength); -+ -+ /* Set direction of EP0 */ -+ if (likely(ctrl.bRequestType & USB_DIR_IN)) { -+ ep->bEndpointAddress |= USB_DIR_IN; -+ } else { -+ ep->bEndpointAddress &= ~USB_DIR_IN; -+ } -+ -+ /* Handle some SETUP packets ourselves */ -+ switch (ctrl.bRequest) { -+ case USB_REQ_SET_ADDRESS: -+ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) -+ break; -+ -+ DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue); -+ udc_set_address(dev, ctrl.wValue); -+ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -+ return; -+ -+ case USB_REQ_SET_CONFIGURATION: -+ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) -+ break; -+ -+ DEBUG_SETUP("USB_REQ_SET_CONFIGURATION (%d)\n", ctrl.wValue); -+ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -+ -+ /* Enable RESUME and SUSPEND interrupts */ -+ usb_setb(USB_REG_INTRUSBE, (USB_INTR_RESUME | USB_INTR_SUSPEND)); -+ break; -+ -+ case USB_REQ_SET_INTERFACE: -+ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) -+ break; -+ -+ DEBUG_SETUP("USB_REQ_SET_INTERFACE (%d)\n", ctrl.wValue); -+ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -+ break; -+ -+// case USB_REQ_GET_STATUS: -+// if (jz4740_handle_get_status(dev, &ctrl) == 0) -+// return; -+ -+ case USB_REQ_CLEAR_FEATURE: -+ case USB_REQ_SET_FEATURE: -+ if (ctrl.bRequestType == USB_RECIP_ENDPOINT) { -+ struct jz4740_ep *qep; -+ int ep_num = (ctrl.wIndex & 0x0f); -+ -+ /* Support only HALT feature */ -+ if (ctrl.wValue != 0 || ctrl.wLength != 0 -+ || ep_num > 3 || ep_num < 1) -+ break; -+ -+ qep = &dev->ep[ep_num]; -+ spin_unlock(&dev->lock); -+ if (ctrl.bRequest == USB_REQ_SET_FEATURE) { -+ DEBUG_SETUP("SET_FEATURE (%d)\n", -+ ep_num); -+ jz4740_set_halt(&qep->ep, 1); -+ } else { -+ DEBUG_SETUP("CLR_FEATURE (%d)\n", -+ ep_num); -+ jz4740_set_halt(&qep->ep, 0); -+ } -+ spin_lock(&dev->lock); -+ -+ usb_set_index(0); -+ -+ /* Reply with a ZLP on next IN token */ -+ usb_setb(USB_REG_CSR0, -+ (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -+ return; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ /* gadget drivers see class/vendor specific requests, -+ * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION}, -+ * and more. -+ */ -+ if (likely((u32)dev->driver)) { -+ /* device-2-host (IN) or no data setup command, process immediately */ -+ spin_unlock(&dev->lock); -+ -+ i = dev->driver->setup(&dev->gadget, &ctrl); -+ spin_lock(&dev->lock); -+ -+ if (unlikely(i < 0)) { -+ /* setup processing failed, force stall */ -+ DEBUG_SETUP -+ (" --> ERROR: gadget setup FAILED (stalling), setup returned %d\n", -+ i); -+ usb_set_index(0); -+ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL)); -+ -+ /* ep->stopped = 1; */ -+ dev->ep0state = WAIT_FOR_SETUP; -+ } -+ else { -+ DEBUG_SETUP("gadget driver setup ok (%d)\n", ctrl.wLength); -+ if (!ctrl.wLength) { -+ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -+ } -+ } -+ } -+} -+ -+/* -+ * DATA_STATE_NEED_ZLP -+ */ -+static void jz4740_ep0_in_zlp(struct jz4740_udc *dev, u32 csr) -+{ -+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -+ -+ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -+ dev->ep0state = WAIT_FOR_SETUP; -+} -+ -+/* -+ * handle ep0 interrupt -+ */ -+static void jz4740_handle_ep0(struct jz4740_udc *dev, u32 intr) -+{ -+ struct jz4740_ep *ep = &dev->ep[0]; -+ u32 csr; -+ -+ /* Set index 0 */ -+ usb_set_index(0); -+ csr = usb_readb(USB_REG_CSR0); -+ -+ DEBUG_EP0("%s: csr = %x state = \n", __FUNCTION__, csr);//, state_names[dev->ep0state]); -+ -+ /* -+ * if SENT_STALL is set -+ * - clear the SENT_STALL bit -+ */ -+ if (csr & USB_CSR0_SENTSTALL) { -+ DEBUG_EP0("%s: USB_CSR0_SENTSTALL is set: %x\n", __FUNCTION__, csr); -+ usb_clearb(USB_REG_CSR0, USB_CSR0_SENDSTALL | USB_CSR0_SENTSTALL); -+ nuke(ep, -ECONNABORTED); -+ dev->ep0state = WAIT_FOR_SETUP; -+ return; -+ } -+ -+ /* -+ * if a transfer is in progress && INPKTRDY and OUTPKTRDY are clear -+ * - fill EP0 FIFO -+ * - if last packet -+ * - set IN_PKT_RDY | DATA_END -+ * - else -+ * set IN_PKT_RDY -+ */ -+ if (!(csr & (USB_CSR0_INPKTRDY | USB_CSR0_OUTPKTRDY))) { -+ DEBUG_EP0("%s: INPKTRDY and OUTPKTRDY are clear\n", -+ __FUNCTION__); -+ -+ switch (dev->ep0state) { -+ case DATA_STATE_XMIT: -+ DEBUG_EP0("continue with DATA_STATE_XMIT\n"); -+ jz4740_ep0_in(dev, csr); -+ return; -+ case DATA_STATE_NEED_ZLP: -+ DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n"); -+ jz4740_ep0_in_zlp(dev, csr); -+ return; -+ default: -+ /* Stall? */ -+// DEBUG_EP0("Odd state!! state = %s\n", -+// state_names[dev->ep0state]); -+ dev->ep0state = WAIT_FOR_SETUP; -+ /* nuke(ep, 0); */ -+ /* usb_setb(ep->csr, USB_CSR0_SENDSTALL); */ -+// break; -+ return; -+ } -+ } -+ -+ /* -+ * if SETUPEND is set -+ * - abort the last transfer -+ * - set SERVICED_SETUP_END_BIT -+ */ -+ if (csr & USB_CSR0_SETUPEND) { -+ DEBUG_EP0("%s: USB_CSR0_SETUPEND is set: %x\n", __FUNCTION__, csr); -+ -+ usb_setb(USB_REG_CSR0, USB_CSR0_SVDSETUPEND); -+ nuke(ep, 0); -+ dev->ep0state = WAIT_FOR_SETUP; -+ } -+ -+ /* -+ * if USB_CSR0_OUTPKTRDY is set -+ * - read data packet from EP0 FIFO -+ * - decode command -+ * - if error -+ * set SVDOUTPKTRDY | DATAEND | SENDSTALL bits -+ * - else -+ * set SVDOUTPKTRDY | DATAEND bits -+ */ -+ if (csr & USB_CSR0_OUTPKTRDY) { -+ -+ DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__, -+ csr); -+ -+ switch (dev->ep0state) { -+ case WAIT_FOR_SETUP: -+ DEBUG_EP0("WAIT_FOR_SETUP\n"); -+ jz4740_ep0_setup(dev, csr); -+ break; -+ -+ case DATA_STATE_RECV: -+ DEBUG_EP0("DATA_STATE_RECV\n"); -+ jz4740_ep0_out(dev, csr); -+ break; -+ -+ default: -+ /* send stall? */ -+ DEBUG_EP0("strange state!! 2. send stall? state = %d\n", -+ dev->ep0state); -+ break; -+ } -+ } -+} -+ -+static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep) -+{ -+ u32 csr; -+ -+ usb_set_index(0); -+ csr = usb_readb(USB_REG_CSR0); -+ -+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -+ -+ /* Clear "out packet ready" */ -+ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -+ -+ if (ep_is_in(ep)) { -+ dev->ep0state = DATA_STATE_XMIT; -+ jz4740_ep0_in(dev, csr); -+ } else { -+ dev->ep0state = DATA_STATE_RECV; -+ jz4740_ep0_out(dev, csr); -+ } -+} -+ -+/** Handle USB RESET interrupt -+ */ -+static void jz4740_reset_irq(struct jz4740_udc *dev) -+{ -+ dev->gadget.speed = (usb_readb(USB_REG_POWER) & USB_POWER_HSMODE) ? -+ USB_SPEED_HIGH : USB_SPEED_FULL; -+ -+ DEBUG_SETUP("%s: address = %d, speed = %s\n", __FUNCTION__, dev->usb_address, -+ (dev->gadget.speed == USB_SPEED_HIGH) ? "HIGH":"FULL" ); -+} -+ -+/* -+ * jz4740 usb device interrupt handler. -+ */ -+static irqreturn_t jz4740_udc_irq(int irq, void *_dev) -+{ -+ struct jz4740_udc *dev = _dev; -+ -+ u32 intr_usb = usb_readb(USB_REG_INTRUSB) & 0x7; /* mask SOF */ -+ u32 intr_in = usb_readw(USB_REG_INTRIN); -+ u32 intr_out = usb_readw(USB_REG_INTROUT); -+ u32 intr_dma = usb_readb(USB_REG_INTR); -+ -+ if (!intr_usb && !intr_in && !intr_out && !intr_dma) -+ return IRQ_HANDLED; -+ -+ DEBUG("intr_out = %x intr_in=%x intr_usb=%x\n", -+ intr_out, intr_in, intr_usb); -+ -+ spin_lock(&dev->lock); -+ -+ /* Check for resume from suspend mode */ -+ if ((intr_usb & USB_INTR_RESUME) && -+ (usb_readb(USB_REG_INTRUSBE) & USB_INTR_RESUME)) { -+ DEBUG("USB resume\n"); -+ } -+ -+ /* Check for system interrupts */ -+ if (intr_usb & USB_INTR_RESET) { -+ DEBUG("USB reset\n"); -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ jz_udc_active = 1; -+#endif -+ if (udc_debug) { -+ /* We have tested the cable type, disable module and -+ * disconnect from host right now. -+ */ -+ udc_disable(dev); -+ spin_unlock(&dev->lock); -+ return IRQ_HANDLED; -+ } -+ jz4740_reset_irq(dev); -+ } -+ -+ /* Check for endpoint 0 interrupt */ -+ if (intr_in & USB_INTR_EP0) { -+ DEBUG("USB_INTR_EP0 (control)\n"); -+ jz4740_handle_ep0(dev, intr_in); -+ } -+ -+ /* Check for Bulk-IN DMA interrupt */ -+ if (intr_dma & 0x1) { -+ int ep_num; -+ ep_num = (usb_readl(USB_REG_CNTL1) >> 4) & 0xf; -+ jz4740_in_epn(dev, ep_num, intr_in); -+ } -+ -+ /* Check for Bulk-OUT DMA interrupt */ -+ if (intr_dma & 0x2) { -+ int ep_num; -+ ep_num = (usb_readl(USB_REG_CNTL2) >> 4) & 0xf; -+ jz4740_out_epn(dev, ep_num, intr_out); -+ } -+ -+ /* Check for each configured endpoint interrupt */ -+ if (intr_in & USB_INTR_INEP1) { -+ DEBUG("USB_INTR_INEP1\n"); -+ jz4740_in_epn(dev, 1, intr_in); -+ } -+ -+ if (intr_in & USB_INTR_INEP2) { -+ DEBUG("USB_INTR_INEP2\n"); -+ jz4740_in_epn(dev, 2, intr_in); -+ } -+ -+ if (intr_out & USB_INTR_OUTEP1) { -+ DEBUG("USB_INTR_OUTEP1\n"); -+ jz4740_out_epn(dev, 1, intr_out); -+ } -+ -+ /* Check for suspend mode */ -+ if ((intr_usb & USB_INTR_SUSPEND) && -+ (usb_readb(USB_REG_INTRUSBE) & USB_INTR_SUSPEND)) { -+ DEBUG("USB suspend\n"); -+ dev->driver->suspend(&dev->gadget); -+ /* Host unloaded from us, can do something, such as flushing -+ the NAND block cache etc. */ -+ } -+ -+#ifdef CONFIG_JZ_UDC_HOTPLUG -+ jz_udc_active = 1; -+#endif -+ -+ spin_unlock(&dev->lock); -+ return IRQ_HANDLED; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int jz4740_udc_get_frame(struct usb_gadget *_gadget) -+{ -+ DEBUG("%s, %p\n", __FUNCTION__, _gadget); -+ return usb_readw(USB_REG_FRAME); -+} -+ -+static int jz4740_udc_wakeup(struct usb_gadget *_gadget) -+{ -+ /* host may not have enabled remote wakeup */ -+ /*if ((UDCCS0 & UDCCS0_DRWF) == 0) -+ return -EHOSTUNREACH; -+ udc_set_mask_UDCCR(UDCCR_RSM); */ -+ return -ENOTSUPP; -+} -+ -+static const struct usb_gadget_ops jz4740_udc_ops = { -+ .get_frame = jz4740_udc_get_frame, -+ .wakeup = jz4740_udc_wakeup, -+ /* current versions must always be self-powered */ -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static struct jz4740_udc udc_dev = { -+ .usb_address = 0, -+ -+ .gadget = { -+ .ops = &jz4740_udc_ops, -+ .ep0 = &udc_dev.ep[0].ep, -+ .name = driver_name, -+ .dev = { -+ .bus_id = "gadget", -+ }, -+ }, -+ -+ /* control endpoint */ -+ .ep[0] = { -+ .ep = { -+ .name = ep0name, -+ .ops = &jz4740_ep_ops, -+ .maxpacket = EP0_MAXPACKETSIZE, -+ }, -+ .dev = &udc_dev, -+ -+ .bEndpointAddress = 0, -+ .bmAttributes = 0, -+ -+ .ep_type = ep_control, -+ .fifo = USB_FIFO_EP0, -+ .csr = USB_REG_CSR0, -+ }, -+ -+ /* bulk out endpoint */ -+ .ep[1] = { -+ .ep = { -+ .name = "ep1out-bulk", -+ .ops = &jz4740_ep_ops, -+ .maxpacket = EPBULK_MAXPACKETSIZE, -+ }, -+ .dev = &udc_dev, -+ -+ .bEndpointAddress = 1, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ -+ .ep_type = ep_bulk_out, -+ .fifo = USB_FIFO_EP1, -+ .csr = USB_REG_OUTCSR, -+ }, -+ -+ /* bulk in endpoint */ -+ .ep[2] = { -+ .ep = { -+ .name = "ep1in-bulk", -+ .ops = &jz4740_ep_ops, -+ .maxpacket = EPBULK_MAXPACKETSIZE, -+ }, -+ .dev = &udc_dev, -+ -+ .bEndpointAddress = USB_DIR_IN | 1, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ -+ .ep_type = ep_bulk_in, -+ .fifo = USB_FIFO_EP1, -+ .csr = USB_REG_INCSR, -+ }, -+ -+ /* interrupt in endpoint */ -+ .ep[3] = { -+ .ep = { -+ .name = "ep2in-int", -+ .ops = &jz4740_ep_ops, -+ .maxpacket = EPINTR_MAXPACKETSIZE, -+ }, -+ .dev = &udc_dev, -+ -+ .bEndpointAddress = USB_DIR_IN | 2, -+ .bmAttributes = USB_ENDPOINT_XFER_INT, -+ -+ .ep_type = ep_interrupt, -+ .fifo = USB_FIFO_EP2, -+ .csr = USB_REG_INCSR, -+ }, -+}; -+ -+static int jz4740_udc_probe(struct platform_device *pdev) -+{ -+ struct jz4740_udc *dev = &udc_dev; -+ int rc; -+ -+ DEBUG("%s\n", __FUNCTION__); -+ -+ spin_lock_init(&dev->lock); -+ the_controller = dev; -+ -+ dev->dev = &pdev->dev; -+ device_initialize(&dev->gadget.dev); -+ dev->gadget.dev.parent = &pdev->dev; -+ -+// strcpy (dum->gadget.dev.bus_id, "gadget"); -+ dev->gadget.dev.release = jz4740_udc_release; -+ if ((rc = device_register (&dev->gadget.dev)) < 0) -+ return rc; -+ platform_set_drvdata(pdev, dev); -+ -+ udc_disable(dev); -+ udc_reinit(dev); -+ -+ /* irq setup */ -+ if (request_irq(IRQ_UDC, jz4740_udc_irq, IRQF_DISABLED,//SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, -+ driver_name, dev) != 0) { -+ printk(KERN_INFO "request UDC interrupt %d failed\n", IRQ_UDC); -+ return -EBUSY; -+ } -+ -+ printk(KERN_INFO "%s\n", driver_desc); -+ printk(KERN_INFO "version: " DRIVER_VERSION "\n"); -+ -+ return 0; -+} -+ -+static int jz4740_udc_remove(struct platform_device *pdev) -+{ -+ struct jz4740_udc *dev = platform_get_drvdata(pdev); -+ DEBUG("%s: %p\n", __FUNCTION__, dev); -+ -+ if (dev->driver) -+ return -EBUSY; -+ -+ udc_disable(dev); -+#ifdef UDC_PROC_FILE -+ remove_proc_entry(proc_node_name, NULL); -+#endif -+ -+ free_irq(IRQ_UDC, dev); -+ platform_set_drvdata(pdev, 0); -+ device_unregister(&dev->gadget.dev); -+ the_controller = 0; -+ -+ return 0; -+} -+ -+static struct platform_driver udc_driver = { -+ .probe = jz4740_udc_probe, -+ .remove = jz4740_udc_remove, -+ .suspend = NULL, -+ .resume = NULL, -+ .driver = { -+ .name = (char *) driver_name, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+ -+ -+static struct platform_device the_udc_pdev = { -+ .name = (char *) gadget_name, -+ .id = -1, -+ .dev = { -+ .release = jz4740_udc_release, -+ }, -+}; -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __init udc_init (void) -+{ -+ platform_driver_register(&udc_driver); -+ return platform_device_register (&the_udc_pdev); -+} -+ -+static void __exit udc_exit (void) -+{ -+ platform_driver_unregister(&udc_driver); -+ platform_device_unregister(&the_udc_pdev); -+} -+ -+module_init(udc_init); -+module_exit(udc_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR("Wei Jianli "); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/usb/gadget/jz4740_udc.h b/drivers/usb/gadget/jz4740_udc.h -new file mode 100644 -index 0000000..ee642b4 ---- /dev/null -+++ b/drivers/usb/gadget/jz4740_udc.h -@@ -0,0 +1,112 @@ -+/* -+ * linux/drivers/usb/gadget/jz4740_udc.h -+ * -+ * Ingenic JZ4740 on-chip high speed USB device controller -+ * -+ * Copyright (C) 2006 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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 __USB_GADGET_JZ4740_H__ -+#define __USB_GADGET_JZ4740_H__ -+ -+/*-------------------------------------------------------------------------*/ -+ -+// Max packet size -+#define EP0_MAXPACKETSIZE 64 -+#define EPBULK_MAXPACKETSIZE 512 -+#define EPINTR_MAXPACKETSIZE 64 -+ -+#define UDC_MAX_ENDPOINTS 4 -+ -+/*-------------------------------------------------------------------------*/ -+ -+typedef enum ep_type { -+ ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt -+} ep_type_t; -+ -+struct jz4740_ep { -+ struct usb_ep ep; -+ struct jz4740_udc *dev; -+ -+ const struct usb_endpoint_descriptor *desc; -+ struct list_head queue; -+ unsigned long pio_irqs; -+ -+ u8 stopped; -+ u8 bEndpointAddress; -+ u8 bmAttributes; -+ -+ ep_type_t ep_type; -+ u32 fifo; -+ u32 csr; -+ -+ u32 reg_addr; -+}; -+ -+struct jz4740_request { -+ struct usb_request req; -+ struct list_head queue; -+}; -+ -+enum ep0state { -+ WAIT_FOR_SETUP, /* between STATUS ack and SETUP report */ -+ DATA_STATE_XMIT, /* data tx stage */ -+ DATA_STATE_NEED_ZLP, /* data tx zlp stage */ -+ WAIT_FOR_OUT_STATUS, /* status stages */ -+ DATA_STATE_RECV, /* data rx stage */ -+}; -+ -+struct jz4740_udc { -+ struct usb_gadget gadget; -+ struct usb_gadget_driver *driver; -+ struct device *dev; -+ spinlock_t lock; -+ -+ enum ep0state ep0state; -+ struct jz4740_ep ep[UDC_MAX_ENDPOINTS]; -+ -+ unsigned char usb_address; -+}; -+ -+extern struct jz4740_udc *the_controller; -+ -+#define ep_is_in(EP) (((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN) -+#define ep_maxpacket(EP) ((EP)->ep.maxpacket) -+#define ep_index(EP) ((EP)->bEndpointAddress&0xF) -+#define usb_set_index(i) (REG8(USB_REG_INDEX) = (i)) -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* 2.5 stuff that's sometimes missing in 2.4 */ -+ -+#ifndef container_of -+#define container_of list_entry -+#endif -+ -+#ifndef likely -+#define likely(x) (x) -+#define unlikely(x) (x) -+#endif -+ -+#ifndef BUG_ON -+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) -+#endif -+ -+#ifndef WARN_ON -+#define WARN_ON(x) do { } while (0) -+#endif -+ -+#ifndef IRQ_NONE -+typedef void irqreturn_t; -+#define IRQ_NONE -+#define IRQ_HANDLED -+#define IRQ_RETVAL(x) -+#endif -+ -+#endif /* __USB_GADGET_JZ4740_H__ */ -diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c -index 5815168..148ef67 100644 ---- a/drivers/usb/host/ohci-hcd.c -+++ b/drivers/usb/host/ohci-hcd.c -@@ -992,6 +992,11 @@ MODULE_LICENSE ("GPL"); - #define PCI_DRIVER ohci_pci_driver - #endif - -+#ifdef CONFIG_JZSOC -+#include "ohci-jz.c" -+#define PLATFORM_DRIVER ohci_hcd_jz_driver -+#endif -+ - #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) - #include "ohci-sa1111.c" - #define SA1111_DRIVER ohci_hcd_sa1111_driver -diff --git a/drivers/usb/host/ohci-jz.c b/drivers/usb/host/ohci-jz.c -new file mode 100644 -index 0000000..9604728 ---- /dev/null -+++ b/drivers/usb/host/ohci-jz.c -@@ -0,0 +1,260 @@ -+/* -+ * OHCI HCD (Host Controller Driver) for USB. -+ * -+ * (C) Copyright 1999 Roman Weissgaerber -+ * (C) Copyright 2000-2002 David Brownell -+ * (C) Copyright 2002 Hewlett-Packard Company -+ * -+ * Bus Glue for Ingenic Jz47xx. -+ * -+ * Written by Christopher Hoover -+ * Based on fragments of previous driver by Rusell King et al. -+ * -+ * Modified for LH7A404 from ohci-sa1111.c -+ * by Durgesh Pattamatta -+ * Modified for AMD Alchemy Au1xxx -+ * by Matt Porter -+ * Modified for Jz47xx from ohci-au1xxx.c -+ * by Peter -+ * -+ * This file is licenced under the GPL. -+ */ -+ -+#include -+#include -+ -+#include -+ -+extern int usb_disabled(void); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void jz_start_ohc(struct platform_device *dev) -+{ -+ printk(KERN_DEBUG __FILE__ -+ ": starting JZ OHCI USB Controller\n"); -+ -+ /* enable host controller */ -+ __cpm_start_uhc(); -+ -+#ifdef CONFIG_SOC_JZ4750 -+ __cpm_enable_uhcphy(); -+#endif -+ -+ printk(KERN_DEBUG __FILE__ -+ ": Clock to USB host has been enabled \n"); -+} -+ -+static void jz_stop_ohc(struct platform_device *dev) -+{ -+ printk(KERN_DEBUG __FILE__ -+ ": stopping JZ OHCI USB Controller\n"); -+ -+#ifdef CONFIG_SOC_JZ4750 -+ __cpm_suspend_uhcphy(); -+#endif -+ -+ __cpm_stop_uhc(); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* configure so an HC device and id are always provided */ -+/* always called with process context; sleeping is OK */ -+ -+ -+/** -+ * usb_ohci_jz_probe - initialize Jz-based HCDs -+ * Context: !in_interrupt() -+ * -+ * Allocates basic resources for this USB host controller, and -+ * then invokes the start() method for the HCD associated with it -+ * through the hotplug entry's driver_data. -+ * -+ */ -+static int usb_ohci_jz_probe(const struct hc_driver *driver, -+ struct platform_device *dev) -+{ -+ int retval; -+ struct usb_hcd *hcd; -+ -+ if (dev->resource[1].flags != IORESOURCE_IRQ) { -+ pr_debug("resource[1] is not IORESOURCE_IRQ\n"); -+ return -ENOMEM; -+ } -+ -+ hcd = usb_create_hcd(driver, &dev->dev, "jz"); -+ if (!hcd) -+ return -ENOMEM; -+ hcd->rsrc_start = dev->resource[0].start; -+ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; -+ -+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -+ pr_debug("request_mem_region failed\n"); -+ retval = -EBUSY; -+ goto err1; -+ } -+ -+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -+ if (!hcd->regs) { -+ pr_debug("ioremap failed\n"); -+ retval = -ENOMEM; -+ goto err2; -+ } -+ -+ jz_start_ohc(dev); -+ ohci_hcd_init(hcd_to_ohci(hcd)); -+ -+ retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED); -+ if (retval == 0) -+ return retval; -+ -+ jz_stop_ohc(dev); -+ iounmap(hcd->regs); -+ err2: -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ err1: -+ usb_put_hcd(hcd); -+ return retval; -+} -+ -+ -+/* may be called without controller electrically present */ -+/* may be called with controller, bus, and devices active */ -+ -+/** -+ * usb_hcd_jz_remove - shutdown processing for Jz-based HCDs -+ * @dev: USB Host Controller being removed -+ * Context: !in_interrupt() -+ * -+ * Reverses the effect of usb_hcd_jz_probe(), first invoking -+ * the HCD's stop() method. It is always called from a thread -+ * context, normally "rmmod", "apmd", or something similar. -+ * -+ */ -+static void usb_ohci_jz_remove(struct usb_hcd *hcd, struct platform_device *dev) -+{ -+ usb_remove_hcd(hcd); -+ jz_stop_ohc(dev); -+ iounmap(hcd->regs); -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ usb_put_hcd(hcd); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __devinit -+ohci_jz_start (struct usb_hcd *hcd) -+{ -+ struct ohci_hcd *ohci = hcd_to_ohci (hcd); -+ int ret; -+ -+ ohci_dbg (ohci, "ohci_jz_start, ohci:%p", ohci); -+ -+ if ((ret = ohci_init (ohci)) < 0) -+ return ret; -+ -+ if ((ret = ohci_run (ohci)) < 0) { -+ err ("can't start %s", hcd->self.bus_name); -+ ohci_stop (hcd); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static const struct hc_driver ohci_jz_hc_driver = { -+ .description = hcd_name, -+ .product_desc = "JZ OHCI", -+ .hcd_priv_size = sizeof(struct ohci_hcd), -+ -+ /* -+ * generic hardware linkage -+ */ -+ .irq = ohci_irq, -+ .flags = HCD_USB11 | HCD_MEMORY, -+ -+ /* -+ * basic lifecycle operations -+ */ -+ .start = ohci_jz_start, -+ .stop = ohci_stop, -+ .shutdown = ohci_shutdown, -+ -+ /* -+ * managing i/o requests and associated device resources -+ */ -+ .urb_enqueue = ohci_urb_enqueue, -+ .urb_dequeue = ohci_urb_dequeue, -+ .endpoint_disable = ohci_endpoint_disable, -+ -+ /* -+ * scheduling support -+ */ -+ .get_frame_number = ohci_get_frame, -+ -+ /* -+ * root hub support -+ */ -+ .hub_status_data = ohci_hub_status_data, -+ .hub_control = ohci_hub_control, -+ .hub_irq_enable = ohci_rhsc_enable, -+#ifdef CONFIG_PM -+ .bus_suspend = ohci_bus_suspend, -+ .bus_resume = ohci_bus_resume, -+#endif -+ .start_port_reset = ohci_start_port_reset, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int ohci_hcd_jz_drv_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ pr_debug ("In ohci_hcd_jz_drv_probe"); -+ -+ if (usb_disabled()) -+ return -ENODEV; -+ -+ ret = usb_ohci_jz_probe(&ohci_jz_hc_driver, pdev); -+ return ret; -+} -+ -+static int ohci_hcd_jz_drv_remove(struct platform_device *pdev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ -+ usb_ohci_jz_remove(hcd, pdev); -+ return 0; -+} -+ /*TBD*/ -+/*static int ohci_hcd_jz_drv_suspend(struct platform_device *dev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(dev); -+ -+ return 0; -+} -+static int ohci_hcd_jz_drv_resume(struct platform_device *dev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(dev); -+ -+ return 0; -+} -+*/ -+ -+static struct platform_driver ohci_hcd_jz_driver = { -+ .probe = ohci_hcd_jz_drv_probe, -+ .remove = ohci_hcd_jz_drv_remove, -+ .shutdown = usb_hcd_platform_shutdown, -+ /*.suspend = ohci_hcd_jz_drv_suspend, */ -+ /*.resume = ohci_hcd_jz_drv_resume, */ -+ .driver = { -+ .name = "jz-ohci", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig -index 3b54b39..45df749 100644 ---- a/drivers/video/Kconfig -+++ b/drivers/video/Kconfig -@@ -237,6 +237,226 @@ config FB_TILEBLITTING - comment "Frame buffer hardware drivers" - depends on FB - -+config FB_JZSOC -+ tristate "JZSOC LCD controller support" -+ depends on FB && JZSOC -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ select FB_CFB_IMAGEBLIT -+ ---help--- -+ JZSOC LCD Controller and Smart LCD Controller driver support. -+ -+config FB_JZ4740_SLCD -+ tristate "JZ4740 Smart LCD controller support" -+ depends on FB_JZSOC && SOC_JZ4740 -+ default n -+ ---help--- -+ This is the frame buffer device driver for the JZ4740 Smart LCD controller. -+ If select this, please set to . -+ -+choice -+ depends on FB_JZ4740_SLCD -+ prompt "SLCD Panel" -+ default JZ_SLCD_LGDP4551_8BUS -+ -+config JZ_SLCD_LGDP4551 -+ bool "LG LGDP4551 Smart LCD panel" -+ ---help--- -+ Driver for Smart LCD LGDP4551, 8-bit sytem interface, 16BPP. -+ -+config JZ_SLCD_SPFD5420A -+ bool "SPFD5420A Smart LCD panel" -+ ---help--- -+ Driver for Smart LCD SPFD5420A 18-bit sytem interface, 18BPP. -+ -+config JZ_SLCD_TRULY -+ bool "TRULY Smart LCD panel (MAX Pixels 400x240)" -+ ---help--- -+ -+endchoice -+ -+config FB_JZLCD_4730_4740 -+ tristate "JZ4730 JZ4740 LCD controller support" -+ depends on FB_JZSOC && (SOC_JZ4730 || SOC_JZ4740) -+ help -+ This is the frame buffer device driver for the JZ4730 and JZ4740 LCD controller. -+config JZLCD_FRAMEBUFFER_MAX -+ int "Default FrameBuffer num" -+ depends on FB_JZLCD_4730_4740 -+ default "1" -+ ---help--- -+ JZ LCD driver support multi-framebuffers for video applications. -+config JZLCD_FRAMEBUFFER_ROTATE_SUPPORT -+ bool "JZLCD FrameBuffer Rotate Support(For TEST)" -+ depends on FB_JZLCD_4730_4740 -+ default n -+ ---help--- -+ JZ LCD driver framebuffer rotate support. Rotate angle can be 0,90,180,270. -+ Note, this fearture is implemented by software, and will cost a lot of cpu capcity. -+ That is to say, if you select this function, you system will become slowly. -+ Rotate cost cpu about: -+ ratate angle 0'C: 0% cpu -+ ratate angle 90'C: 40% cpu -+ ratate angle 180'C: 20% cpu -+ ratate angle 270'C: 40% cpu -+ -+config JZLCD_FRAMEBUFFER_DEFAULT_ROTATE_ANGLE -+ int "FrameBuffer default rotate angle" -+ depends on JZLCD_FRAMEBUFFER_ROTATE_SUPPORT -+ default 0 -+ ---help--- -+ JZ LCD driver framebuffer angle value can be: -+ 0: 0'C -+ 1: 90'C -+ 2: 180'C -+ 3: 270'C -+config JZLCD_FRAMEBUFFER_BPP -+ int "FrameBuffer bit per pixel" -+ depends on JZLCD_FRAMEBUFFER_ROTATE_SUPPORT -+ default 32 -+ ---help--- -+ JZ LCD driver framebuffer support 8bpp, 16bpp, 32bpp -+choice -+ depends on FB_JZLCD_4730_4740 -+ prompt "LCD Panel" -+ default JZLCD_SAMSUNG_LTP400WQF01 -+ -+config JZLCD_SHARP_LQ035Q7 -+ bool "SHARP LQ035Q7 TFT panel (240x320)" -+ -+config JZLCD_SAMSUNG_LTS350Q1 -+ bool "SAMSUNG LTS350Q1 TFT panel (240x320)" -+ -+config JZLCD_SAMSUNG_LTV350QVF04 -+ bool "SAMSUNG LTV350QV_F04 TFT panel (320x240)" -+ -+config JZLCD_SAMSUNG_LTP400WQF01 -+ bool "SAMSUNG LTP400WQF01 TFT panel (480x272)(16bits)" -+ -+config JZLCD_SAMSUNG_LTP400WQF02 -+ bool "SAMSUNG LTP400WQF02 TFT panel (480x272)(18bits)" -+ -+config JZLCD_AUO_A030FL01_V1 -+ bool "AUO A030FL01_V1 TFT panel (480x272)" -+ -+config JZLCD_TRULY_TFTG320240DTSW -+ bool "TRULY TFTG320240DTSW TFT panel (320x240)" -+ -+config JZLCD_TRULY_TFTG320240DTSW_SERIAL -+ bool "TRULY TFTG320240DTSW TFT panel (320x240)(8bit-serial mode)" -+ -+config JZLCD_TRULY_TFTG240320UTSW_63W_E -+ bool "TRULY TFTG240320UTSW-63W-E TFT panel (240x320,2.5in)" -+ -+config JZLCD_FOXCONN_PT035TN01 -+ bool "FOXCONN PT035TN01 TFT panel (320x240)" -+ -+config JZLCD_INNOLUX_PT035TN01_SERIAL -+ bool "INNOLUX PT035TN01 TFT panel (320x240,3.5in)(8bit-serial mode)" -+ -+config JZLCD_TOSHIBA_LTM084P363 -+ bool "Toshiba LTM084P363 TFT panel (800x600)" -+ -+config JZLCD_HYNIX_HT10X21 -+ bool "Hynix HT10X21_300 TFT panel (1024x768)" -+ -+config JZLCD_INNOLUX_AT080TN42 -+ bool "INNOLUX AT080TN42 TFT panel (800x600)" -+ -+config JZLCD_CSTN_800x600 -+ bool "800x600 colorDSTN panel" -+ -+config JZLCD_CSTN_320x240 -+ bool "320x240 colorSTN panel" -+ -+config JZLCD_MSTN_480x320 -+ bool "480x320 monoSTN panel" -+ -+config JZLCD_MSTN_320x240 -+ bool "320x240 monoSTN panel" -+ -+config JZLCD_MSTN_240x128 -+ bool "240x128 monoSTN panel" -+ -+config JZLCD_MSTN_INVERSE -+ bool "Use an inverse color display." -+ depends on (JZLCD_MSTN_480x320 || JZLCD_MSTN_240x128) -+ -+endchoice -+ -+config FB_JZ4750_LCD -+ tristate "JZ4750 LCD Controller support" -+ depends on FB_JZSOC && (SOC_JZ4750 || SOC_JZ4750D) -+ ---help--- -+ JZ4750 LCD Controller driver. -+ JZ4750 LCD Controller support OSD function(refer jz4750_lcdc_spec.pdf).JZ4750 LCD OSD implement 2 framebuffer layers: foreground0 and foreground1. JZ4750 LCD driver support only foreground0 default. -+ -+config FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER -+ bool "JZ4750 LCD driver 2 layers framebuffer support." -+ depends on FB_JZ4750_LCD -+ ---help--- -+ JZ4750 LCD driver support only foreground0 by default. -+ If you need both foreground0 and foreground1, please select this. -+ -+config FB_JZ4750_TVE -+ tristate "Jz4750 TV Encode support" -+ depends on FB_JZSOC && FB_JZ4750_LCD -+ default n -+ -+config IPU_JZ4750 -+ tristate "Jz4750 ipu support (Only for debug)" -+ depends on FB_JZSOC && FB_JZ4750_LCD -+ default n -+ ---help--- -+ Test JZ4750 IPU, if not sure, please set it to n. -+ -+config FB_JZ4750_SLCD -+ bool -+ depends on FB_JZ4750_LCD -+ default n -+choice -+ depends on FB_JZ4750_LCD -+ prompt "JZ4750 LCD Panels Support" -+ default JZ4750_LCD_SAMSUNG_LTP400WQF02 -+ ---help--- -+ Please select the lcd panel in you board -+ -+config JZ4750_LCD_SAMSUNG_LTP400WQF01 -+ bool "SAMSUNG LTP400WQF01 TFT panel (480x272)(16bits)" -+ -+config JZ4750_LCD_SAMSUNG_LTP400WQF02 -+ bool "SAMSUNG LTP400WQF02 TFT panel (480x272)(18bits)" -+ -+config JZ4750_LCD_AUO_A043FL01V2 -+ bool "AUO A043FL01V2 TFT panel (480x272)(24bits)" -+ -+config JZ4750_LCD_FOXCONN_PT035TN01 -+ bool "FOXCONN PT035TN01 TFT panel (320x240,3.5in)(18bit-parallel mode)" -+ -+config JZ4750_LCD_INNOLUX_PT035TN01_SERIAL -+ bool "INNOLUX PT035TN01 TFT panel (320x240,3.5in)(8bit-serial mode)" -+ -+config JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA -+ bool "TOPPOLY_TD025THEA7 TFT panel(320x240)(serial RGB delta mode)" -+ -+config JZ4750_LCD_TOPPOLY_TD043MGEB1 -+ bool "TOPPOLY_TD043MGEB1 TFT panel(800x480)(24bit mode)" -+ -+config JZ4750_LCD_TRULY_TFTG320240DTSW_18BIT -+ bool "TRULY_TFTG320240DTSW TFT panel (320x240) (Parallel 18bit mode)" -+ -+config JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W -+ bool "TRULY_TFT_GG1P0319LTSW_W (240x320) (Smart LCD 16bit)" -+ -+config JZ4750_SLCD_KGM701A3_TFT_SPFD5420A -+ bool "KGM701A3_TFT_SPFD5420A (400x240) (Smart LCD 18bit)" -+ select FB_JZ4750_SLCD -+ -+config JZ4750D_VGA_DISPLAY -+ depends on SOC_JZ4750D -+ bool "Jz4750D VGA Display" -+endchoice -+ - config FB_CIRRUS - tristate "Cirrus Logic support" - depends on FB && (ZORRO || PCI) -diff --git a/drivers/video/Makefile b/drivers/video/Makefile -index 01a819f..5a3c60d 100644 ---- a/drivers/video/Makefile -+++ b/drivers/video/Makefile -@@ -28,6 +28,10 @@ obj-$(CONFIG_FB_DDC) += fb_ddc.o - obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o - - # Hardware specific drivers go first -+obj-$(CONFIG_FB_JZLCD_4730_4740) += jzlcd.o -+obj-$(CONFIG_FB_JZ4740_SLCD) += jz4740_slcd.o -+obj-$(CONFIG_FB_JZ4750_LCD) += jz4750_lcd.o -+obj-$(CONFIG_FB_JZ4750_TVE) += jz4750_tve.o - obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o - obj-$(CONFIG_FB_ARC) += arcfb.o - obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o -diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig -index 2f50a80..92bd3ce 100644 ---- a/drivers/video/console/Kconfig -+++ b/drivers/video/console/Kconfig -@@ -118,6 +118,14 @@ config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY - - If unsure, select n. - -+config FRAMEBUFFER_CONSOLE_CURSOR_FLASH -+ bool "Framebuffer Console Cursor flash" -+ depends on FRAMEBUFFER_CONSOLE -+ help -+ Enable cursor flush for the framebuffer console. This is done -+ in software and may be significantly slower than a normally oriented -+ display. -+ - config FRAMEBUFFER_CONSOLE_ROTATION - bool "Framebuffer Console Rotation" - depends on FRAMEBUFFER_CONSOLE -diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c -index 3a44695..212b25a 100644 ---- a/drivers/video/console/fbcon.c -+++ b/drivers/video/console/fbcon.c -@@ -366,6 +366,7 @@ static void fbcon_update_softback(struct vc_data *vc) - - static void fb_flashcursor(struct work_struct *work) - { -+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH - struct fb_info *info = container_of(work, struct fb_info, queue); - struct fbcon_ops *ops = info->fbcon_par; - struct display *p; -@@ -391,6 +392,7 @@ static void fb_flashcursor(struct work_struct *work) - ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1), - get_color(vc, info, c, 0)); - release_console_sem(); -+#endif - } - - static void cursor_timer_handler(unsigned long dev_addr) -diff --git a/drivers/video/jz4740_slcd.c b/drivers/video/jz4740_slcd.c -new file mode 100644 -index 0000000..41f0928 ---- /dev/null -+++ b/drivers/video/jz4740_slcd.c -@@ -0,0 +1,1334 @@ -+/* -+ * linux/drivers/video/jzslcd.c -- Ingenic On-Chip Smart LCD frame buffer device -+ * -+ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "console/fbcon.h" -+ -+#include "jz4740_slcd.h" -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+ -+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) -+#ifdef DEBUG -+#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) -+#else -+#define print_dbg(f, arg...) do {} while (0) -+#endif -+ -+static jz_dma_desc slcd_palette_desc __attribute__ ((aligned (16))); -+static jz_dma_desc slcd_frame_desc __attribute__ ((aligned (16))); -+ -+static int dma_chan; -+static dma_addr_t slcd_frame_desc_phys_addr, slcd_palette_desc_phys_addr; -+ -+static unsigned char non_link_desp = 0; -+static unsigned char is_set_reg = 0; -+struct lcd_cfb_info { -+ struct fb_info fb; -+ struct display_switch *dispsw; -+ signed int currcon; -+ int func_use_count; -+ -+ struct { -+ u16 red, green, blue; -+ } palette[NR_PALETTE]; -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+struct slcd_reg_info { -+ unsigned int cmd; -+ unsigned int data; -+}; -+static struct slcd_reg_info reg_buf; -+static struct lcd_cfb_info *jzslcd_info; -+ -+struct jzfb_info { -+ unsigned int cfg; /* panel mode and pin usage etc. */ -+ unsigned int w; -+ unsigned int h; -+ unsigned int bpp; /* bit per pixel */ -+ unsigned int bus; -+ unsigned int pclk; /* pixel clk */ -+ -+}; -+ -+static struct jzfb_info jzfb = { -+#ifdef CONFIG_JZ_SLCD_LGDP4551 -+ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, -+ 400, 240, 16, 8, 16000000 /*16 bpp, 8 bus*/ -+// 240, 400, 18, 8, 16000000 /*18 bpp, 8 bus*/ -+// 400, 240, 18, 8, 16000000 /*18 bpp, 8 bus*/ -+#endif -+ -+#ifdef CONFIG_JZ_SLCD_SPFD5420A -+ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, -+ 400, 240, 18, 18, 16000000 /*18 bpp, 18 bus*/ -+#endif -+}; -+ -+ -+static volatile unsigned char *slcd_palette; -+static volatile unsigned char *slcd_frame; -+ -+//extern struct display fb_display[MAX_NR_CONSOLES]; -+static irqreturn_t slcd_dma_irq(int irq, void *dev_id); -+ -+ -+static void Mcupanel_RegSet(UINT32 cmd, UINT32 data) -+{ -+ switch (jzfb.bus) { -+ case 8: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -+ break; -+ case 9: -+ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -+ data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -+ break; -+ case 16: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -+ break; -+ case 18: -+ cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); -+ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); -+ break; -+ default: -+ printk("Don't support %d bit Bus\n", jzfb.bus ); -+ break; -+ } -+} -+ -+/* Sent a command withou data */ -+static void Mcupanel_Command(UINT32 cmd) { -+ switch (jzfb.bus) { -+ case 8: -+ case 9: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -+ break; -+ case 16: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -+ break; -+ case 18: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); -+ break; -+ default: -+ printk("Don't support %d bit Bus\n", jzfb.bus ); -+ break; -+ } -+} -+ -+/* Set the start address of screen, for example (0, 0) */ -+#ifdef CONFIG_JZ_SLCD_LGDP4551 -+static void Mcupanel_SetAddr(UINT16 x, UINT16 y) -+{ -+ Mcupanel_RegSet(0x20,x) ; -+ udelay(1); -+ Mcupanel_RegSet(0x21,y) ; -+ udelay(1); -+ Mcupanel_Command(0x22); -+ -+} -+#endif -+#ifdef CONFIG_JZ_SLCD_SPFD5420A -+void Mcupanel_SetAddr(u32 x, u32 y) //u32 -+{ -+ Mcupanel_RegSet(0x200,x) ; -+ udelay(1); -+ Mcupanel_RegSet(0x201,y) ; -+ udelay(1); -+ Mcupanel_Command(0x202); -+ -+} -+ -+#endif -+ -+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -+{ -+ chan &= 0xffff; -+ chan >>= 16 - bf->length; -+ return chan << bf->offset; -+} -+ -+static int jzfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -+ u_int transp, struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ unsigned short *ptr, ctmp; -+ -+ print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); -+ if (regno >= NR_PALETTE) -+ return 1; -+ -+ cfb->palette[regno].red = red ; -+ cfb->palette[regno].green = green; -+ cfb->palette[regno].blue = blue; -+ if (cfb->fb.var.bits_per_pixel <= 16) { -+ red >>= 8; -+ green >>= 8; -+ blue >>= 8; -+ -+ red &= 0xff; -+ green &= 0xff; -+ blue &= 0xff; -+ } -+ switch (cfb->fb.var.bits_per_pixel) { -+ case 1: -+ case 2: -+ case 4: -+ case 8: -+ /* RGB 565 */ -+ if (((red >> 3) == 0) && ((red >> 2) != 0)) -+ red = 1 << 3; -+ if (((blue >> 3) == 0) && ((blue >> 2) != 0)) -+ blue = 1 << 3; -+ ctmp = ((red >> 3) << 11) -+ | ((green >> 2) << 5) | (blue >> 3); -+ -+ ptr = (unsigned short *)slcd_palette; -+ ptr = (unsigned short *)(((u32)ptr)|0xa0000000); -+ ptr[regno] = ctmp; -+ -+ break; -+ -+ case 15: -+ if (regno < 16) -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ ((red >> 3) << 10) | -+ ((green >> 3) << 5) | -+ (blue >> 3); -+ break; -+ case 16: -+ if (regno < 16) { -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ ((red >> 3) << 11) | -+ ((green >> 2) << 5) | -+ (blue >> 3); -+ } -+ break; -+ case 18: -+ case 24: -+ case 32: -+ if (regno < 16) -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ (red << 16) | -+ (green << 8) | -+ (blue << 0); -+ -+/* if (regno < 16) { -+ unsigned val; -+ val = chan_to_field(red, &cfb->fb.var.red); -+ val |= chan_to_field(green, &cfb->fb.var.green); -+ val |= chan_to_field(blue, &cfb->fb.var.blue); -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = val; -+ } -+*/ -+ -+ break; -+ } -+ return 0; -+} -+ -+static int jzfb_ioctl (struct fb_info *info, unsigned int cmd, unsigned long arg ) -+{ -+ int ret = 0; -+ void __user *argp = (void __user *)arg; -+ -+ switch (cmd) { -+ case FBIOSETBACKLIGHT: -+ __slcd_set_backlight_level(arg); /* We support 8 levels here. */ -+ break; -+ case FBIODISPON: -+ __slcd_display_on(); -+ break; -+ case FBIODISPOFF: -+ __slcd_display_off(); -+ break; -+ case FBIO_REFRESH_ALWAYS: -+ dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); -+ if (slcd_frame_desc.dcmd & DMAC_DCMD_LINK) -+ printk("The Smart LCD refreshes automatically. Option is omitted!\n"); -+ else { -+ dprintk("OPEN DMAC_DCMD_LINK \n"); -+ slcd_frame_desc.dcmd &= ~DMAC_DCMD_TIE; -+ slcd_frame_desc.dcmd |= DMAC_DCMD_LINK; -+ dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); -+ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_TIE; -+ __dmac_channel_set_doorbell(dma_chan); -+ } -+ break; -+ case FBIO_REFRESH_EVENTS: -+ dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); -+ if (!(slcd_frame_desc.dcmd & DMAC_DCMD_LINK)) -+ printk("The Smart LCD is refreshed by envents. Option is omitted!\n"); -+ else { -+ non_link_desp = 1; -+ REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; -+ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -+ } -+ break; -+ case FBIO_DO_REFRESH: -+ -+ dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); -+ if (slcd_frame_desc.dcmd & DMAC_DCMD_LINK) -+ printk("The Smart LCD can refresh automatically. Option is omitted!\n"); -+ else { -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ __dmac_channel_set_doorbell(dma_chan); -+ } -+ break; -+ case FBIO_SET_REG: -+ if (copy_from_user(®_buf, argp, sizeof(reg_buf))) -+ return -EFAULT; -+ is_set_reg = 1; -+ REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; -+ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -+ break; -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -+static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -+ -+ /* frame buffer memory */ -+ start = cfb->fb.fix.smem_start; -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ off += start; -+ -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -+ -+#if 1 -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+// pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -+ pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Through */ -+#endif -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot)) { -+ return -EAGAIN; -+ } -+ return 0; -+} -+ -+/* checks var and eventually tweaks it to something supported, -+ * DO NOT MODIFY PAR */ -+static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ print_dbg("jzfb_check_var"); -+ return 0; -+} -+ -+ -+/* -+ * set the video mode according to info->var -+ */ -+static int jzfb_set_par(struct fb_info *info) -+{ -+// print_dbg("jzfb_set_par"); -+ printk("jzfb_set_par"); -+ return 0; -+} -+ -+ -+/* -+ * (Un)Blank the display. -+ * Fix me: should we use VESA value? -+ */ -+static int jzfb_blank(int blank_mode, struct fb_info *info) -+{ -+ -+ dprintk("fb_blank %d %p", blank_mode, info); -+ -+ switch (blank_mode) { -+ -+ case FB_BLANK_UNBLANK: -+ /* Turn on panel */ -+ break; -+ -+ case FB_BLANK_NORMAL: -+ case FB_BLANK_VSYNC_SUSPEND: -+ case FB_BLANK_HSYNC_SUSPEND: -+ case FB_BLANK_POWERDOWN: -+ /* Turn off panel */ -+ break; -+ default: -+ break; -+ -+ } -+ return 0; -+} -+ -+/* -+ * pan display -+ */ -+static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ int dy; -+ -+ if (!var || !cfb) { -+ return -EINVAL; -+ } -+ -+ if (var->xoffset - cfb->fb.var.xoffset) { -+ /* No support for X panning for now! */ -+ return -EINVAL; -+ } -+ -+ dy = var->yoffset - cfb->fb.var.yoffset; -+ print_dbg("var.yoffset: %d", dy); -+ if (dy) { -+ -+ print_dbg("Panning screen of %d lines", dy); -+// slcd_frame_desc->databuf += (cfb->fb.fix.line_length * dy); -+// slcd_frame_desc->dsadr += (cfb->fb.fix.line_length * dy); -+ /* TODO: Wait for current frame to finished */ -+ } -+ -+ return 0; -+} -+ -+ -+/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ -+static struct fb_ops jzfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_setcolreg = jzfb_setcolreg, -+ .fb_check_var = jzfb_check_var, -+ .fb_set_par = jzfb_set_par, -+ .fb_blank = jzfb_blank, -+ .fb_pan_display = jzfb_pan_display, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+ .fb_mmap = jzfb_mmap, -+ .fb_ioctl = jzfb_ioctl, -+}; -+ -+static int jzfb_set_var(struct fb_var_screeninfo *var, int con, -+ struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ //struct display *display; -+ int chgvar = 0; -+ -+ var->height = jzfb.h ; -+ var->width = jzfb.w ; -+ var->bits_per_pixel = jzfb.bpp; -+ -+ var->vmode = FB_VMODE_NONINTERLACED; -+ var->activate = cfb->fb.var.activate; -+ var->xres = var->width; -+ var->yres = var->height; -+ var->xres_virtual = var->width; -+ var->yres_virtual = var->height; -+ var->xoffset = 0; -+ var->yoffset = 0; -+ var->pixclock = 0; -+ var->left_margin = 0; -+ var->right_margin = 0; -+ var->upper_margin = 0; -+ var->lower_margin = 0; -+ var->hsync_len = 0; -+ var->vsync_len = 0; -+ var->sync = 0; -+ var->activate &= ~FB_ACTIVATE_TEST; -+ -+ /* -+ * CONUPDATE and SMOOTH_XPAN are equal. However, -+ * SMOOTH_XPAN is only used internally by fbcon. -+ */ -+ if (var->vmode & FB_VMODE_CONUPDATE) { -+ var->vmode |= FB_VMODE_YWRAP; -+ var->xoffset = cfb->fb.var.xoffset; -+ var->yoffset = cfb->fb.var.yoffset; -+ } -+ -+ if (var->activate & FB_ACTIVATE_TEST) -+ return 0; -+ -+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) -+ return -EINVAL; -+ -+ if (cfb->fb.var.xres != var->xres) -+ chgvar = 1; -+ if (cfb->fb.var.yres != var->yres) -+ chgvar = 1; -+ if (cfb->fb.var.xres_virtual != var->xres_virtual) -+ chgvar = 1; -+ if (cfb->fb.var.yres_virtual != var->yres_virtual) -+ chgvar = 1; -+ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) -+ chgvar = 1; -+ -+ //display = fb_display + con; -+ -+ var->red.msb_right = 0; -+ var->green.msb_right = 0; -+ var->blue.msb_right = 0; -+ -+ switch(var->bits_per_pixel){ -+ case 1: /* Mono */ -+ cfb->fb.fix.visual = FB_VISUAL_MONO01; -+ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ break; -+ case 2: /* Mono */ -+ var->red.offset = 0; -+ var->red.length = 2; -+ var->green.offset = 0; -+ var->green.length = 2; -+ var->blue.offset = 0; -+ var->blue.length = 2; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ break; -+ case 4: /* PSEUDOCOLOUR*/ -+ var->red.offset = 0; -+ var->red.length = 4; -+ var->green.offset = 0; -+ var->green.length = 4; -+ var->blue.offset = 0; -+ var->blue.length = 4; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = var->xres / 2; -+ break; -+ case 8: /* PSEUDOCOLOUR, 256 */ -+ var->red.offset = 0; -+ var->red.length = 8; -+ var->green.offset = 0; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = var->xres ; -+ break; -+ case 15: /* DIRECTCOLOUR, 32k */ -+ var->bits_per_pixel = 15; -+ var->red.offset = 10; -+ var->red.length = 5; -+ var->green.offset = 5; -+ var->green.length = 5; -+ var->blue.offset = 0; -+ var->blue.length = 5; -+ -+ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 2; -+ break; -+ case 16: /* DIRECTCOLOUR, 64k */ -+ var->bits_per_pixel = 16; -+ var->red.offset = 11; -+ var->red.length = 5; -+ var->green.offset = 5; -+ var->green.length = 6; -+ var->blue.offset = 0; -+ var->blue.length = 5; -+ -+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 2; -+ break; -+ case 18: -+ case 24: -+ case 32: -+ /* DIRECTCOLOUR, 256 */ -+ var->bits_per_pixel = 32; -+ -+ var->red.offset = 16; -+ var->red.length = 8; -+ var->green.offset = 8; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ var->transp.offset = 24; -+ var->transp.length = 8; -+ -+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 4; -+ break; -+ -+ default: /* in theory this should never happen */ -+ printk(KERN_WARNING "%s: don't support for %dbpp\n", -+ cfb->fb.fix.id, var->bits_per_pixel); -+ break; -+ } -+ -+ cfb->fb.var = *var; -+ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; -+ -+ /* -+ * If we are setting all the virtual consoles, also set the -+ * defaults used to create new consoles. -+ */ -+ fb_set_cmap(&cfb->fb.cmap, &cfb->fb); -+ dprintk("jzfb_set_var: after fb_set_cmap...\n"); -+ -+ return 0; -+} -+ -+static struct lcd_cfb_info * jzfb_alloc_fb_info(void) -+{ -+ struct lcd_cfb_info *cfb; -+ -+ cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); -+ -+ if (!cfb) -+ return NULL; -+ -+ jzslcd_info = cfb; -+ -+ memset(cfb, 0, sizeof(struct lcd_cfb_info) ); -+ -+ cfb->currcon = -1; -+ -+ -+ strcpy(cfb->fb.fix.id, "jz-slcd"); -+ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; -+ cfb->fb.fix.type_aux = 0; -+ cfb->fb.fix.xpanstep = 1; -+ cfb->fb.fix.ypanstep = 1; -+ cfb->fb.fix.ywrapstep = 0; -+ cfb->fb.fix.accel = FB_ACCEL_NONE; -+ -+ cfb->fb.var.nonstd = 0; -+ cfb->fb.var.activate = FB_ACTIVATE_NOW; -+ cfb->fb.var.height = -1; -+ cfb->fb.var.width = -1; -+ cfb->fb.var.accel_flags = FB_ACCELF_TEXT; -+ -+ cfb->fb.fbops = &jzfb_ops; -+ cfb->fb.flags = FBINFO_FLAG_DEFAULT; -+ -+ cfb->fb.pseudo_palette = (void *)(cfb + 1); -+ -+ switch (jzfb.bpp) { -+ case 1: -+ fb_alloc_cmap(&cfb->fb.cmap, 4, 0); -+ break; -+ case 2: -+ fb_alloc_cmap(&cfb->fb.cmap, 8, 0); -+ break; -+ case 4: -+ fb_alloc_cmap(&cfb->fb.cmap, 32, 0); -+ break; -+ case 8: -+ -+ default: -+ fb_alloc_cmap(&cfb->fb.cmap, 256, 0); -+ break; -+ } -+ dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); -+ -+ return cfb; -+} -+ -+/* -+ * Map screen memory -+ */ -+static int jzfb_map_smem(struct lcd_cfb_info *cfb) -+{ -+ struct page * map = NULL; -+ unsigned char *tmp; -+ unsigned int page_shift, needroom, t; -+ -+ t = jzfb.bpp; -+ if (jzfb.bpp == 15) -+ t = 16; -+ if (jzfb.bpp == 18 || jzfb.bpp == 24) -+ t = 32; -+ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -+ -+ for (page_shift = 0; page_shift < 12; page_shift++) -+ if ((PAGE_SIZE << page_shift) >= needroom) -+ break; -+ -+ slcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -+ slcd_frame = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ if ((!slcd_palette) || (!slcd_frame)) -+ return -ENOMEM; -+ -+ memset((void *)slcd_palette, 0, PAGE_SIZE); -+ memset((void *)slcd_frame, 0, PAGE_SIZE << page_shift); -+ -+ map = virt_to_page(slcd_palette); -+ set_bit(PG_reserved, &map->flags); -+ -+ for (tmp=(unsigned char *)slcd_frame; -+ tmp < slcd_frame + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ set_bit(PG_reserved, &map->flags); -+ } -+ -+ cfb->fb.fix.smem_start = virt_to_phys((void *)slcd_frame); -+ -+ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); -+ -+ cfb->fb.screen_base = -+ (unsigned char *)(((unsigned int)slcd_frame & 0x1fffffff) | 0xa0000000); -+ -+ if (!cfb->fb.screen_base) { -+ printk("%s: unable to map screen memory\n", cfb->fb.fix.id); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void jzfb_free_fb_info(struct lcd_cfb_info *cfb) -+{ -+ if (cfb) { -+ fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -+ kfree(cfb); -+ } -+} -+ -+static void jzfb_unmap_smem(struct lcd_cfb_info *cfb) -+{ -+ struct page * map = NULL; -+ unsigned char *tmp; -+ unsigned int page_shift, needroom, t; -+ -+ t = jzfb.bpp; -+ if (jzfb.bpp == 18 || jzfb.bpp == 24) -+ t = 32; -+ if (jzfb.bpp == 15) -+ t = 16; -+ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -+ for (page_shift = 0; page_shift < 12; page_shift++) -+ if ((PAGE_SIZE << page_shift) >= needroom) -+ break; -+ -+ if (cfb && cfb->fb.screen_base) { -+ iounmap(cfb->fb.screen_base); -+ cfb->fb.screen_base = NULL; -+ release_mem_region(cfb->fb.fix.smem_start, -+ cfb->fb.fix.smem_len); -+ } -+ -+ if (slcd_palette) { -+ map = virt_to_page(slcd_palette); -+ clear_bit(PG_reserved, &map->flags); -+ free_pages((int)slcd_palette, 0); -+ } -+ -+ if (slcd_frame) { -+ -+ for (tmp=(unsigned char *)slcd_frame; -+ tmp < slcd_frame + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ clear_bit(PG_reserved, &map->flags); -+ } -+ -+ free_pages((int)slcd_frame, page_shift); -+ } -+} -+ -+static void slcd_descriptor_init(void) -+{ -+ int i; -+ int frm_size, pal_size; -+ unsigned int next; -+ unsigned int slcd_frame_src_phys_addr, slcd_palette_src_phys_addr, slcd_dma_dst_phys_addr; -+ -+ i = jzfb.bpp; -+ if (i == 18 || i == 24) -+ i = 32; -+ if (i == 15) -+ i = 16; -+ -+ switch (jzfb.bpp) { -+ case 1: -+ pal_size = 4; -+ break; -+ case 2: -+ pal_size = 8; -+ break; -+ case 4: -+ pal_size = 32; -+ break; -+ case 8: -+ default: -+ pal_size = 512; -+ } -+ -+ frm_size = jzfb.w * jzfb.h * jzfb.bpp / 8; -+ -+ /*Offset of next descriptor*/ -+ slcd_frame_desc_phys_addr = (dma_addr_t)CPHYSADDR((unsigned long)(&slcd_frame_desc)); -+ slcd_palette_desc_phys_addr = (dma_addr_t)CPHYSADDR((unsigned long)(&slcd_palette_desc)); -+ -+ /*Soure address and Target address*/ -+ slcd_palette_src_phys_addr = (unsigned int)virt_to_phys(slcd_palette); -+ slcd_frame_src_phys_addr = (unsigned int)virt_to_phys(slcd_frame); -+ slcd_dma_dst_phys_addr = (unsigned int)CPHYSADDR(SLCD_FIFO); -+ next = slcd_frame_desc_phys_addr >> 4; -+ -+ /* Prepare Palette Descriptor */ -+ slcd_palette_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 -+ | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V -+ | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; -+ switch (slcd_palette_desc.dcmd & DMAC_DCMD_DS_MASK) { -+ case DMAC_DCMD_DS_32BYTE: -+ pal_size /= 32; -+ break; -+ case DMAC_DCMD_DS_16BYTE: -+ pal_size /= 16; -+ break; -+ case DMAC_DCMD_DS_32BIT: -+ pal_size /= 4; -+ break; -+ case DMAC_DCMD_DS_16BIT: -+ pal_size /= 2; -+ break; -+ case DMAC_DCMD_DS_8BIT: -+ default: -+ break; -+ } -+ -+ slcd_palette_desc.dsadr = (unsigned int)virt_to_phys(slcd_palette); /* DMA source address */ -+ slcd_palette_desc.dtadr = (unsigned int)CPHYSADDR(SLCD_FIFO); /* DMA target address */ -+ slcd_palette_desc.ddadr = (volatile unsigned int)((next << 24) | (pal_size & 0xffffff)); /* offset and size*/ -+ dma_cache_wback((unsigned long)(&slcd_palette_desc), 16); -+ -+ /*Prepare Frame Descriptor in memory*/ -+ switch (jzfb.bpp) { -+ case 8 ... 16: -+ slcd_frame_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 -+ | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V -+ | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; -+ break; -+ -+ case 17 ... 32: -+ slcd_frame_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 -+ | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V -+ | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; -+ break; -+ } -+ switch (slcd_frame_desc.dcmd & DMAC_DCMD_DS_MASK) { -+ case DMAC_DCMD_DS_32BYTE: -+ frm_size /= 32; -+ break; -+ case DMAC_DCMD_DS_16BYTE: -+ frm_size /= 16; -+ break; -+ case DMAC_DCMD_DS_32BIT: -+ frm_size /= 4; -+ break; -+ case DMAC_DCMD_DS_16BIT: -+ frm_size /= 2; -+ break; -+ case DMAC_DCMD_DS_8BIT: -+ default: -+ break; -+ } -+ -+ slcd_frame_desc.dsadr = slcd_frame_src_phys_addr; /* DMA source address */ -+ slcd_frame_desc.dtadr = slcd_dma_dst_phys_addr; /* DMA target address */ -+ slcd_frame_desc.ddadr = (volatile unsigned int)((next << 24) | (frm_size & 0xffffff)); /* offset and size*/ -+ dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); -+} -+ -+void slcd_hw_init(void) -+{ -+ unsigned int val, pclk; -+ int pll_div; -+ -+ REG_LCD_CFG &= ~LCD_CFG_LCDPIN_MASK; -+ REG_LCD_CFG |= LCD_CFG_LCDPIN_SLCD; -+ -+ if ((jzfb.bpp == 18) | (jzfb.bpp == 24)) -+ jzfb.bpp = 32; -+ -+ /* Configure SLCD module for initialize smart lcd registers*/ -+ switch (jzfb.bus) { -+ case 8: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -+ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_8bit(); -+ break; -+ case 9: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -+ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_9bit(); -+ break; -+ case 16: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_16 -+ | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_16bit(); -+ break; -+ case 18: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_18 -+ | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_18bit(); -+ break; -+ default: -+ printk("Error: Don't support BUS %d!\n", jzfb.bus); -+ break; -+ } -+ -+ REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; -+ __cpm_stop_lcd(); -+ pclk = jzfb.pclk; -+ pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */ -+ pll_div = pll_div ? 1 : 2 ; -+ val = ( __cpm_get_pllout()/pll_div ) / pclk; -+ val--; -+ if ( val > 0x1ff ) { -+ printk("CPM_LPCDR too large, set it to 0x1ff\n"); -+ val = 0x1ff; -+ } -+ __cpm_set_pixdiv(val); -+ -+ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -+ -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ printk("SLCDC: PixClock:%d LcdClock:%d\n", -+ jz_clocks.pixclk, jz_clocks.lcdclk); -+ -+ __cpm_start_lcd(); -+ udelay(1000); -+ __slcd_display_pin_init(); -+ __slcd_special_on(); -+ -+ /* Configure SLCD module for transfer data to smart lcd GRAM*/ -+ switch (jzfb.bus) { -+ case 8: -+ switch (jzfb.bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15: -+ case 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ case 9: -+ switch (jzfb.bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15 ... 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_9_x2; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ case 16: -+ switch (jzfb.bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15 ... 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ case 18: -+ switch (jzfb.bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15: -+ case 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_18; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ default: -+ printk("Error: The BUS %d is not supported\n", jzfb.bus); -+ break; -+ } -+ dprintk("SLCD_CFG=0x%x\n", REG_SLCD_CFG); -+} -+ -+static irqreturn_t slcd_dma_irq(int irq, void *dev_id) -+{ -+ -+ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -+ dprintk("DMA HALT\n"); -+ __dmac_channel_clear_transmit_halt(dma_chan); -+ } -+ -+ if (__dmac_channel_address_error_detected(dma_chan)) { -+ dprintk("DMA ADDR ERROR\n"); -+ __dmac_channel_clear_address_error(dma_chan); -+ } -+ -+ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -+ dprintk("DMA DESC INVALID\n"); -+ __dmac_channel_clear_descriptor_invalid(dma_chan); -+ } -+ -+ if (__dmac_channel_count_terminated_detected(dma_chan)) { -+ dprintk("DMA CT\n"); -+ __dmac_channel_clear_count_terminated(dma_chan); -+ if(is_set_reg){ -+ printk("Close DMAC_DCMD_LINK \n"); -+ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -+ } -+ if (non_link_desp) { -+ printk("Close DMAC_DCMD_LINK \n"); -+ /*Set to Non-Link Descriptor*/ -+ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -+ } -+ } -+ -+ if (__dmac_channel_transmit_end_detected(dma_chan)) { -+ printk("DMA TT\n"); -+ __dmac_channel_clear_transmit_end(dma_chan); -+ if (non_link_desp) { -+ slcd_frame_desc.dcmd |= DMAC_DCMD_TIE; -+ slcd_frame_desc.dcmd &= ~DMAC_DCMD_LINK; -+ dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); -+ non_link_desp = 0; -+ } -+ if (is_set_reg) { -+ is_set_reg = 0; -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE; /* disable DMA */ -+ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -+ REG_SLCD_CTRL = 0; -+ -+ /* -+ *add operation here -+ */ -+ Mcupanel_RegSet(reg_buf.cmd, reg_buf.data); -+ Mcupanel_Command(0x0022);/*Write Data to GRAM */ -+ mdelay(100); -+ REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; -+ REG_DMAC_DMACR = DMAC_DMACR_DMAE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; -+ __dmac_channel_set_doorbell(dma_chan); -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+static int slcd_dma_init(void) -+{ -+ /* Request DMA channel and setup irq handler */ -+ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", slcd_dma_irq, 0, NULL); -+ if (dma_chan < 0) { -+ printk("Request DMA Failed\n"); -+ return -1; -+ } -+ printk("DMA channel %d is requested by SLCD!\n", dma_chan); -+ -+ /*Init the SLCD DMA and Enable*/ -+ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_SLCD; -+ REG_DMAC_DMACR = DMAC_DMACR_DMAE; -+ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /*Descriptor Transfer*/ -+ -+ if (jzfb.bpp <= 8) -+ REG_DMAC_DDA(dma_chan) = slcd_palette_desc_phys_addr; -+ else -+ REG_DMAC_DDA(dma_chan) = slcd_frame_desc_phys_addr; -+ -+ /* DMA doorbell set -- start DMA now ... */ -+ __dmac_channel_set_doorbell(dma_chan); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+ -+/* -+ * Suspend the LCDC. -+ */ -+static int jzfb_suspend(void) -+{ -+ -+ __slcd_close_backlight(); -+ __dmac_disable_channel(dma_chan); -+ __slcd_dma_disable(); /* Quick Disable */ -+ __slcd_special_off(); -+ __cpm_stop_lcd(); -+ return 0; -+} -+ -+/* -+ * Resume the LCDC. -+ */ -+ -+static int jzfb_resume(void) -+{ -+ __cpm_start_lcd(); -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ switch (jzfb.bpp) { -+ case 8: -+ /* DATA 8-bit once*/ -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15: -+ case 16: -+ case 18: -+ case 24: -+ case 32: -+ /* DATA 8-bit twice*/ -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -+ break; -+ default: -+ REG_SLCD_CFG = SLCD_CFG_DWIDTH_8_x2; -+ break; -+ } -+ __slcd_display_pin_init(); -+ __slcd_special_on(); -+ -+ if (jzfb.bpp == 32) { -+ /* DATA 8-bit three time*/ -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -+ } -+ __slcd_dma_enable(); -+ udelay(100); -+ __dmac_enable_channel(dma_chan); -+ __dmac_channel_set_doorbell(dma_chan); -+ mdelay(200); -+ __slcd_set_backlight_level(80); -+ return 0; -+} -+ -+/* -+ * Power management hook. Note that we won't be called from IRQ context, -+ * unlike the blank functions above, so we may sleep. -+ */ -+static int jzslcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct lcd_cfb_info *cfb = pm_dev->data; -+ -+ if (!cfb) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jzfb_suspend(); -+ break; -+ -+ case PM_RESUME: -+ ret = jzfb_resume(); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#else -+#define jzfb_suspend NULL -+#define jzfb_resume NULL -+#endif /* CONFIG_PM */ -+static int __init jzslcd_fb_init(void) -+{ -+ -+ struct lcd_cfb_info *cfb; -+ int err = 0; -+ -+ /*the parameters of slcd*/ -+ cfb = jzfb_alloc_fb_info(); -+ if (!cfb) -+ goto failed; -+ -+ err = jzfb_map_smem(cfb); -+ if (err) -+ goto failed; -+ jzfb_set_var(&cfb->fb.var, -1, &cfb->fb); -+ -+ slcd_hw_init(); -+ -+ err = register_framebuffer(&cfb->fb); -+ if (err < 0) { -+ printk("jzslcd_fb_init(): slcd register framebuffer err.\n"); -+ goto failed; -+ } -+ -+ printk("fb%d: %s frame buffer device, using %dK of video memory\n", -+ cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); -+ -+ slcd_descriptor_init(); -+ err = slcd_dma_init(); -+ if (err != 0) { -+ printk("SLCD Init DMA Fail!\n"); -+ return err; -+ } -+ mdelay(100); -+ __slcd_set_backlight_level(80); -+ -+#ifdef CONFIG_PM -+ /* -+ * Note that the console registers this as well, but we want to -+ * power down the display prior to sleeping. -+ */ -+//struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback); -+ -+ cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzslcd_pm_callback); -+ if (cfb->pm) -+ cfb->pm->data = cfb; -+ -+#endif -+ return 0; -+ -+failed: -+ jzfb_unmap_smem(cfb); -+ jzfb_free_fb_info(cfb); -+ -+ return err; -+} -+ -+#if 0 -+static int jzfb_remove(struct device *dev) -+{ -+ struct lcd_cfb_info *cfb = dev_get_drvdata(dev); -+ jzfb_unmap_smem(cfb); -+ jzfb_free_fb_info(cfb); -+ return 0; -+} -+#endif -+ -+#if 0 -+static struct device_driver jzfb_driver = { -+ .name = "jz-slcd", -+ .bus = &platform_bus_type, -+ .probe = jzfb_probe, -+ .remove = jzfb_remove, -+ .suspend = jzfb_suspend, -+ .resume = jzfb_resume, -+}; -+#endif -+ -+static void __exit jzslcd_fb_cleanup(void) -+{ -+ //driver_unregister(&jzfb_driver); -+ //jzfb_remove(); -+} -+ -+module_init(jzslcd_fb_init); -+module_exit(jzslcd_fb_cleanup); -+ -+MODULE_DESCRIPTION("JzSOC SLCD Controller driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/video/jz4740_slcd.h b/drivers/video/jz4740_slcd.h -new file mode 100644 -index 0000000..84754f6 ---- /dev/null -+++ b/drivers/video/jz4740_slcd.h -@@ -0,0 +1,376 @@ -+/* -+ * linux/drivers/video/jzslcd.h -- Ingenic On-Chip SLCD frame buffer device -+ * -+ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#ifndef __JZSLCD_H__ -+#define __JZSLCD_H__ -+ -+#define UINT16 unsigned short -+#define UINT32 unsigned int -+ -+#define NR_PALETTE 256 -+/* Jz LCDFB supported I/O controls. */ -+#define FBIOSETBACKLIGHT 0x4688 -+#define FBIODISPON 0x4689 -+#define FBIODISPOFF 0x468a -+#define FBIORESET 0x468b -+#define FBIOPRINT_REG 0x468c -+#define FBIO_REFRESH_ALWAYS 0x468d -+#define FBIO_REFRESH_EVENTS 0x468e -+#define FBIO_DO_REFRESH 0x468f -+#define FBIO_SET_REG 0x4690 -+ -+#ifdef CONFIG_JZ_SLCD_LGDP4551 -+#define PIN_CS_N (32*2+18) /* Chip select :SLCD_WR: GPC18 */ -+#define PIN_RESET_N (32*2+21) /* LCD reset :SLCD_RST: GPC21*/ -+#define PIN_RS_N (32*2+19) -+ -+#define __slcd_special_pin_init() \ -+do { \ -+ __gpio_as_output(PIN_CS_N); \ -+ __gpio_as_output(PIN_RESET_N); \ -+ __gpio_clear_pin(PIN_CS_N); /* Clear CS */\ -+ mdelay(100); \ -+} while(0) -+ -+#define __slcd_special_on() \ -+do { /* RESET# */ \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_clear_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(100); \ -+ Mcupanel_RegSet(0x0015,0x0050); \ -+ Mcupanel_RegSet(0x0011,0x0000); \ -+ Mcupanel_RegSet(0x0010,0x3628); \ -+ Mcupanel_RegSet(0x0012,0x0002); \ -+ Mcupanel_RegSet(0x0013,0x0E47); \ -+ udelay(100); \ -+ Mcupanel_RegSet(0x0012,0x0012); \ -+ udelay(100); \ -+ Mcupanel_RegSet(0x0010,0x3620); \ -+ Mcupanel_RegSet(0x0013,0x2E47); \ -+ udelay(50); \ -+ Mcupanel_RegSet(0x0030,0x0000); \ -+ Mcupanel_RegSet(0x0031,0x0502); \ -+ Mcupanel_RegSet(0x0032,0x0307); \ -+ Mcupanel_RegSet(0x0033,0x0304); \ -+ Mcupanel_RegSet(0x0034,0x0004); \ -+ Mcupanel_RegSet(0x0035,0x0401); \ -+ Mcupanel_RegSet(0x0036,0x0707); \ -+ Mcupanel_RegSet(0x0037,0x0303); \ -+ Mcupanel_RegSet(0x0038,0x1E02); \ -+ Mcupanel_RegSet(0x0039,0x1E02); \ -+ Mcupanel_RegSet(0x0001,0x0000); \ -+ Mcupanel_RegSet(0x0002,0x0300); \ -+ if (jzfb.bpp == 16) \ -+ Mcupanel_RegSet(0x0003,0x10B8); /*8-bit system interface two transfers -+ up:0x10B8 down:0x1088 left:0x1090 right:0x10a0*/ \ -+ else \ -+ if (jzfb.bpp == 32)\ -+ Mcupanel_RegSet(0x0003,0xD0B8);/*8-bit system interface three transfers,666 -+ up:0xD0B8 down:0xD088 left:0xD090 right:0xD0A0*/ \ -+ Mcupanel_RegSet(0x0008,0x0204);\ -+ Mcupanel_RegSet(0x000A,0x0008);\ -+ Mcupanel_RegSet(0x0060,0x3100);\ -+ Mcupanel_RegSet(0x0061,0x0001);\ -+ Mcupanel_RegSet(0x0090,0x0052);\ -+ Mcupanel_RegSet(0x0092,0x000F);\ -+ Mcupanel_RegSet(0x0093,0x0001);\ -+ Mcupanel_RegSet(0x009A,0x0008);\ -+ Mcupanel_RegSet(0x00A3,0x0010);\ -+ Mcupanel_RegSet(0x0050,0x0000);\ -+ Mcupanel_RegSet(0x0051,0x00EF);\ -+ Mcupanel_RegSet(0x0052,0x0000);\ -+ Mcupanel_RegSet(0x0053,0x018F);\ -+ /*===Display_On_Function=== */ \ -+ Mcupanel_RegSet(0x0007,0x0001);\ -+ Mcupanel_RegSet(0x0007,0x0021);\ -+ Mcupanel_RegSet(0x0007,0x0023);\ -+ Mcupanel_RegSet(0x0007,0x0033);\ -+ Mcupanel_RegSet(0x0007,0x0133);\ -+ Mcupanel_Command(0x0022);/*Write Data to GRAM */ \ -+ udelay(1); \ -+ Mcupanel_SetAddr(0,0); \ -+ mdelay(100); \ -+} while (0) -+ -+#define __slcd_special_off() \ -+do { \ -+} while(0) -+#endif /*CONFIG_JZ_SLCD_LGDP4551_xxBUS*/ -+ -+#ifdef CONFIG_JZ_SLCD_SPFD5420A -+ -+ //#define PIN_CS_N (32*2+18) // Chip select //GPC18; -+#define PIN_CS_N (32*2+22) // Chip select //GPC18; -+#define PIN_RESET_N (32*1+18) // LCD reset //GPB18; -+#define PIN_RS_N (32*2+19) // LCD RS //GPC19; -+#define PIN_POWER_N (32*3+0) //Power off //GPD0; -+#define PIN_FMARK_N (32*3+1) //fmark //GPD1; -+ -+#define GAMMA() \ -+do { \ -+ Mcupanel_RegSet(0x0300,0x0101); \ -+ Mcupanel_RegSet(0x0301,0x0b27); \ -+ Mcupanel_RegSet(0x0302,0x132a); \ -+ Mcupanel_RegSet(0x0303,0x2a13); \ -+ Mcupanel_RegSet(0x0304,0x270b); \ -+ Mcupanel_RegSet(0x0305,0x0101); \ -+ Mcupanel_RegSet(0x0306,0x1205); \ -+ Mcupanel_RegSet(0x0307,0x0512); \ -+ Mcupanel_RegSet(0x0308,0x0005); \ -+ Mcupanel_RegSet(0x0309,0x0003); \ -+ Mcupanel_RegSet(0x030a,0x0f04); \ -+ Mcupanel_RegSet(0x030b,0x0f00); \ -+ Mcupanel_RegSet(0x030c,0x000f); \ -+ Mcupanel_RegSet(0x030d,0x040f); \ -+ Mcupanel_RegSet(0x030e,0x0300); \ -+ Mcupanel_RegSet(0x030f,0x0500); \ -+ /*** secorrect gamma2 ***/ \ -+ Mcupanel_RegSet(0x0400,0x3500); \ -+ Mcupanel_RegSet(0x0401,0x0001); \ -+ Mcupanel_RegSet(0x0404,0x0000); \ -+ Mcupanel_RegSet(0x0500,0x0000); \ -+ Mcupanel_RegSet(0x0501,0x0000); \ -+ Mcupanel_RegSet(0x0502,0x0000); \ -+ Mcupanel_RegSet(0x0503,0x0000); \ -+ Mcupanel_RegSet(0x0504,0x0000); \ -+ Mcupanel_RegSet(0x0505,0x0000); \ -+ Mcupanel_RegSet(0x0600,0x0000); \ -+ Mcupanel_RegSet(0x0606,0x0000); \ -+ Mcupanel_RegSet(0x06f0,0x0000); \ -+ Mcupanel_RegSet(0x07f0,0x5420); \ -+ Mcupanel_RegSet(0x07f3,0x288a); \ -+ Mcupanel_RegSet(0x07f4,0x0022); \ -+ Mcupanel_RegSet(0x07f5,0x0001); \ -+ Mcupanel_RegSet(0x07f0,0x0000); \ -+} while(0) -+ -+#define __slcd_special_on() \ -+do { \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_clear_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(100); \ -+ if (jzfb.bus == 18) {\ -+ Mcupanel_RegSet(0x0606,0x0000); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0007,0x0001); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0110,0x0001); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0100,0x17b0); \ -+ Mcupanel_RegSet(0x0101,0x0147); \ -+ Mcupanel_RegSet(0x0102,0x019d); \ -+ Mcupanel_RegSet(0x0103,0x8600); \ -+ Mcupanel_RegSet(0x0281,0x0010); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0102,0x01bd); \ -+ udelay(10); \ -+ /************initial************/\ -+ Mcupanel_RegSet(0x0000,0x0000); \ -+ Mcupanel_RegSet(0x0001,0x0000); \ -+ Mcupanel_RegSet(0x0002,0x0400); \ -+ Mcupanel_RegSet(0x0003,0x1288); /*up:0x1288 down:0x12B8 left:0x1290 right:0x12A0*/ \ -+ Mcupanel_RegSet(0x0006,0x0000); \ -+ Mcupanel_RegSet(0x0008,0x0503); \ -+ Mcupanel_RegSet(0x0009,0x0001); \ -+ Mcupanel_RegSet(0x000b,0x0010); \ -+ Mcupanel_RegSet(0x000c,0x0000); \ -+ Mcupanel_RegSet(0x000f,0x0000); \ -+ Mcupanel_RegSet(0x0007,0x0001); \ -+ Mcupanel_RegSet(0x0010,0x0010); \ -+ Mcupanel_RegSet(0x0011,0x0202); \ -+ Mcupanel_RegSet(0x0012,0x0300); \ -+ Mcupanel_RegSet(0x0020,0x021e); \ -+ Mcupanel_RegSet(0x0021,0x0202); \ -+ Mcupanel_RegSet(0x0022,0x0100); \ -+ Mcupanel_RegSet(0x0090,0x0000); \ -+ Mcupanel_RegSet(0x0092,0x0000); \ -+ Mcupanel_RegSet(0x0100,0x16b0); \ -+ Mcupanel_RegSet(0x0101,0x0147); \ -+ Mcupanel_RegSet(0x0102,0x01bd); \ -+ Mcupanel_RegSet(0x0103,0x2c00); \ -+ Mcupanel_RegSet(0x0107,0x0000); \ -+ Mcupanel_RegSet(0x0110,0x0001); \ -+ Mcupanel_RegSet(0x0210,0x0000); \ -+ Mcupanel_RegSet(0x0211,0x00ef); \ -+ Mcupanel_RegSet(0x0212,0x0000); \ -+ Mcupanel_RegSet(0x0213,0x018f); \ -+ Mcupanel_RegSet(0x0280,0x0000); \ -+ Mcupanel_RegSet(0x0281,0x0001); \ -+ Mcupanel_RegSet(0x0282,0x0000); \ -+ GAMMA(); \ -+ Mcupanel_RegSet(0x0007,0x0173); \ -+ } else { \ -+ Mcupanel_RegSet(0x0600, 0x0001); /*soft reset*/ \ -+ mdelay(10); \ -+ Mcupanel_RegSet(0x0600, 0x0000); /*soft reset*/ \ -+ mdelay(10); \ -+ Mcupanel_RegSet(0x0606, 0x0000); /*i80-i/F Endian Control*/ \ -+ /*===User setting=== */ \ -+ Mcupanel_RegSet(0x0001, 0x0000);/* Driver Output Control-----0x0100 SM(bit10) | 0x400*/ \ -+ Mcupanel_RegSet(0x0002, 0x0100); /*LCD Driving Wave Control 0x0100 */ \ -+ if (jzfb.bpp == 16) \ -+ Mcupanel_RegSet(0x0003, 0x50A8);/*Entry Mode 0x1030*/ \ -+ else /*bpp = 18*/ \ -+ Mcupanel_RegSet(0x0003, 0x1010 | 0xC8); /*Entry Mode 0x1030*/ \ -+ /*#endif */ \ -+ Mcupanel_RegSet(0x0006, 0x0000); /*Outline Sharpening Control*/\ -+ Mcupanel_RegSet(0x0008, 0x0808); /*Sets the number of lines for front/back porch period*/\ -+ Mcupanel_RegSet(0x0009, 0x0001); /*Display Control 3 */\ -+ Mcupanel_RegSet(0x000B, 0x0010); /*Low Power Control*/\ -+ Mcupanel_RegSet(0x000C, 0x0000); /*External Display Interface Control 1 /*0x0001*/\ -+ Mcupanel_RegSet(0x000F, 0x0000); /*External Display Interface Control 2 */\ -+ Mcupanel_RegSet(0x0400, 0xB104);/*Base Image Number of Line---GS(bit15) | 0x8000*/ \ -+ Mcupanel_RegSet(0x0401, 0x0001); /*Base Image Display 0x0001*/\ -+ Mcupanel_RegSet(0x0404, 0x0000); /*Base Image Vertical Scroll Control 0x0000*/\ -+ Mcupanel_RegSet(0x0500, 0x0000); /*Partial Image 1: Display Position*/\ -+ Mcupanel_RegSet(0x0501, 0x0000); /*RAM Address (Start Line Address) */\ -+ Mcupanel_RegSet(0x0502, 0x018f); /*RAM Address (End Line Address) */ \ -+ Mcupanel_RegSet(0x0503, 0x0000); /*Partial Image 2: Display Position RAM Address*/\ -+ Mcupanel_RegSet(0x0504, 0x0000); /*RAM Address (Start Line Address) */\ -+ Mcupanel_RegSet(0x0505, 0x0000); /*RAM Address (End Line Address)*/\ -+ /*Panel interface control===*/\ -+ Mcupanel_RegSet(0x0010, 0x0011); /*Division Ratio,Clocks per Line 14 */\ -+ mdelay(10); \ -+ Mcupanel_RegSet(0x0011, 0x0202); /*Division Ratio,Clocks per Line*/\ -+ Mcupanel_RegSet(0x0012, 0x0300); /*Sets low power VCOM drive period. */\ -+ mdelay(10); \ -+ Mcupanel_RegSet(0x0020, 0x021e); /*Panel Interface Control 4 */\ -+ Mcupanel_RegSet(0x0021, 0x0202); /*Panel Interface Control 5 */\ -+ Mcupanel_RegSet(0x0022, 0x0100); /*Panel Interface Control 6*/\ -+ Mcupanel_RegSet(0x0090, 0x0000); /*Frame Marker Control */\ -+ Mcupanel_RegSet(0x0092, 0x0000); /*MDDI Sub-display Control */\ -+ /*===Gamma setting=== */\ -+ Mcupanel_RegSet(0x0300, 0x0101); /*γ Control*/\ -+ Mcupanel_RegSet(0x0301, 0x0000); /*γ Control*/\ -+ Mcupanel_RegSet(0x0302, 0x0016); /*γ Control*/\ -+ Mcupanel_RegSet(0x0303, 0x2913); /*γ Control*/\ -+ Mcupanel_RegSet(0x0304, 0x260B); /*γ Control*/\ -+ Mcupanel_RegSet(0x0305, 0x0101); /*γ Control*/\ -+ Mcupanel_RegSet(0x0306, 0x1204); /*γ Control*/\ -+ Mcupanel_RegSet(0x0307, 0x0415); /*γ Control*/\ -+ Mcupanel_RegSet(0x0308, 0x0205); /*γ Control*/\ -+ Mcupanel_RegSet(0x0309, 0x0303); /*γ Control*/\ -+ Mcupanel_RegSet(0x030a, 0x0E05); /*γ Control*/\ -+ Mcupanel_RegSet(0x030b, 0x0D01); /*γ Control*/\ -+ Mcupanel_RegSet(0x030c, 0x010D); /*γ Control*/\ -+ Mcupanel_RegSet(0x030d, 0x050E); /*γ Control*/\ -+ Mcupanel_RegSet(0x030e, 0x0303); /*γ Control*/\ -+ Mcupanel_RegSet(0x030f, 0x0502); /*γ Control*/\ -+ /*===Power on sequence===*/\ -+ Mcupanel_RegSet(0x0007, 0x0001); /*Display Control 1*/\ -+ Mcupanel_RegSet(0x0110, 0x0001); /*Power supply startup enable bit*/\ -+ Mcupanel_RegSet(0x0112, 0x0060); /*Power Control 7*/\ -+ Mcupanel_RegSet(0x0100, 0x16B0); /*Power Control 1 */\ -+ Mcupanel_RegSet(0x0101, 0x0115); /*Power Control 2*/\ -+ Mcupanel_RegSet(0x0102, 0x0119); /*Starts VLOUT3,Sets the VREG1OUT.*/\ -+ mdelay(50); \ -+ Mcupanel_RegSet(0x0103, 0x2E00); /*set the amplitude of VCOM*/\ -+ mdelay(50);\ -+ Mcupanel_RegSet(0x0282, 0x0093);/*0x008E);/*0x0093); /*VCOMH voltage*/\ -+ Mcupanel_RegSet(0x0281, 0x000A); /*Selects the factor of VREG1OUT to generate VCOMH. */\ -+ Mcupanel_RegSet(0x0102, 0x01BE); /*Starts VLOUT3,Sets the VREG1OUT.*/\ -+ mdelay(10);\ -+ /*Address */\ -+ Mcupanel_RegSet(0x0210, 0x0000); /*Window Horizontal RAM Address Start*/\ -+ Mcupanel_RegSet(0x0211, 0x00ef); /*Window Horizontal RAM Address End*/\ -+ Mcupanel_RegSet(0x0212, 0x0000); /*Window Vertical RAM Address Start*/\ -+ Mcupanel_RegSet(0x0213, 0x018f); /*Window Vertical RAM Address End */\ -+ Mcupanel_RegSet(0x0200, 0x0000); /*RAM Address Set (Horizontal Address)*/\ -+ Mcupanel_RegSet(0x0201, 0x018f); /*RAM Address Set (Vertical Address)*/ \ -+ /*===Display_On_Function===*/\ -+ Mcupanel_RegSet(0x0007, 0x0021); /*Display Control 1 */\ -+ mdelay(50); /*40*/\ -+ Mcupanel_RegSet(0x0007, 0x0061); /*Display Control 1 */\ -+ mdelay(50); /*100*/\ -+ Mcupanel_RegSet(0x0007, 0x0173); /*Display Control 1 */\ -+ mdelay(50); /*300*/\ -+ }\ -+ Mcupanel_Command(0x0202); /*Write Data to GRAM */ \ -+ udelay(10);\ -+ Mcupanel_SetAddr(0,0);\ -+ udelay(100);\ -+} while(0) -+ -+#define __slcd_special_pin_init() \ -+do { \ -+ __gpio_as_output(PIN_CS_N); \ -+ __gpio_as_output(PIN_RESET_N); \ -+ __gpio_clear_pin(PIN_CS_N); /* Clear CS */ \ -+ __gpio_as_output(PIN_POWER_N); \ -+ mdelay(100); \ -+} while(0) -+ -+#endif /*CONFIG_JZ_SLCD_SPFD5420A*/ -+ -+#ifndef __slcd_special_pin_init -+#define __slcd_special_pin_init() -+#endif -+#ifndef __slcd_special_on -+#define __slcd_special_on() -+#endif -+#ifndef __slcd_special_off -+#define __slcd_special_off() -+#endif -+ -+/* -+ * Platform specific definition -+ */ -+#if defined(CONFIG_SOC_JZ4740) -+#if defined(CONFIG_JZ4740_PAVO) -+#define GPIO_PWM 123 /* GP_D27 */ -+#define PWM_CHN 4 /* pwm channel */ -+#define PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __slcd_set_backlight_level(n)\ -+do { \ -+ __gpio_as_output(32*3+27); \ -+ __gpio_set_pin(32*3+27); \ -+} while (0) -+ -+#define __slcd_close_backlight() \ -+do { \ -+ __gpio_as_output(GPIO_PWM); \ -+ __gpio_clear_pin(GPIO_PWM); \ -+} while (0) -+ -+#else -+ -+#define __slcd_set_backlight_level(n) -+#define __slcd_close_backlight() -+ -+#endif /* #if defined(CONFIG_MIPS_JZ4740_PAVO) */ -+ -+#define __slcd_display_pin_init() \ -+do { \ -+ __slcd_special_pin_init(); \ -+} while (0) -+ -+#define __slcd_display_on() \ -+do { \ -+ __slcd_special_on(); \ -+ __slcd_set_backlight_level(80); \ -+} while (0) -+ -+#define __slcd_display_off() \ -+do { \ -+ __slcd_special_off(); \ -+ __slcd_close_backlight(); \ -+} while (0) -+ -+#endif /* CONFIG_SOC_JZ4740 */ -+#endif /*__JZSLCD_H__*/ -+ -diff --git a/drivers/video/jz4750_lcd.c b/drivers/video/jz4750_lcd.c -new file mode 100644 -index 0000000..05a7799 ---- /dev/null -+++ b/drivers/video/jz4750_lcd.c -@@ -0,0 +1,2229 @@ -+/* -+ * linux/drivers/video/jz4750_lcd.c -- Ingenic Jz4750 LCD frame buffer device -+ * -+ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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. -+ */ -+ -+/* -+ * -------------------------------- -+ * NOTE: -+ * This LCD driver support TFT16 TFT32 LCD, not support STN and Special TFT LCD -+ * now. -+ * It seems not necessory to support STN and Special TFT. -+ * If it's necessary, update this driver in the future. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "console/fbcon.h" -+ -+#include "jz4750_lcd.h" -+#include "jz4750_tve.h" -+ -+#ifdef CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A -+#include "jz_kgm_spfd5420a.h" -+#endif -+ -+MODULE_DESCRIPTION("Jz4750 LCD Controller driver"); -+MODULE_AUTHOR("Wolfgang Wang, "); -+MODULE_LICENSE("GPL"); -+ -+ -+//#define DEBUG -+#undef DEBUG -+ -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) -+#else -+#define dprintk(x...) -+#define print_dbg(f, arg...) do {} while (0) -+#endif -+ -+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) -+ -+struct lcd_cfb_info { -+ struct fb_info fb; -+ struct display_switch *dispsw; -+ signed int currcon; -+ int func_use_count; -+ -+ struct { -+ u16 red, green, blue; -+ } palette[NR_PALETTE]; -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+static struct lcd_cfb_info *jz4750fb_info; -+static struct jz4750_lcd_dma_desc *dma_desc_base; -+static struct jz4750_lcd_dma_desc *dma0_desc_palette, *dma0_desc0, *dma0_desc1, *dma1_desc0, *dma1_desc1; -+#define DMA_DESC_NUM 6 -+ -+static unsigned char *lcd_palette; -+static unsigned char *lcd_frame0; -+static unsigned char *lcd_frame1; -+ -+static struct jz4750_lcd_dma_desc *dma0_desc_cmd0, *dma0_desc_cmd; -+static unsigned char *lcd_cmdbuf ; -+ -+static void jz4750fb_set_mode( struct jz4750lcd_info * lcd_info ); -+static void jz4750fb_deep_set_mode( struct jz4750lcd_info * lcd_info ); -+ -+ -+ -+struct jz4750lcd_info jz4750_lcd_panel = { -+#if defined(CONFIG_JZ4750_LCD_SAMSUNG_LTP400WQF02) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -+ LCD_CFG_MODE_TFT_18BIT | /* output 18bpp */ -+ LCD_CFG_HSP | /* Hsync polarity: active low */ -+ LCD_CFG_VSP, /* Vsync polarity: leading edge is falling edge */ -+ .slcd_cfg = 0, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 480, 272, 60, 41, 10, 2, 2, 2, 2, -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -+ }, -+#elif defined(CONFIG_JZ4750_LCD_AUO_A043FL01V2) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -+ LCD_CFG_MODE_TFT_24BIT | /* output 18bpp */ -+ LCD_CFG_HSP | /* Hsync polarity: active low */ -+ LCD_CFG_VSP, /* Vsync polarity: leading edge is falling edge */ -+ .slcd_cfg = 0, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 480, 272, 60, 41, 10, 8, 4, 4, 2, -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+// LCD_OSDC_F1EN | /* enable Foreground1 */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {16, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -+ .fg1 = {16, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -+ }, -+#elif defined(CONFIG_JZ4750_LCD_TOPPOLY_TD043MGEB1) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -+ LCD_CFG_MODE_TFT_24BIT | /* output 18bpp */ -+ LCD_CFG_HSP | /* Hsync polarity: active low */ -+ LCD_CFG_VSP, /* Vsync polarity: leading edge is falling edge */ -+ .slcd_cfg = 0, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 800, 480, 60, 1, 1, 40, 215, 10, 34, -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+// LCD_OSDC_F1EN | /* enable Foreground1 */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0xff, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32, 0, 0, 800, 480}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 800, 480}, /* bpp, x, y, w, h */ -+ }, -+#elif defined(CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_SLCD | /* Underrun recover*/ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_SLCD, /* TFT Smart LCD panel */ -+ .slcd_cfg = SLCD_CFG_DWIDTH_16BIT | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING | SLCD_CFG_TYPE_PARALLEL, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 240, 320, 60, 0, 0, 0, 0, 0, 0, -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+// LCD_OSDC_F1EN | /* enable Foreground0 */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32, 0, 0, 240, 320}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 240, 320}, /* bpp, x, y, w, h */ -+ }, -+ -+#elif defined(CONFIG_JZ4750_LCD_FOXCONN_PT035TN01) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -+// LCD_CFG_MODE_TFT_18BIT | /* output 18bpp */ -+ LCD_CFG_MODE_TFT_24BIT | /* output 24bpp */ -+ LCD_CFG_HSP | /* Hsync polarity: active low */ -+ LCD_CFG_VSP | /* Vsync polarity: leading edge is falling edge */ -+ LCD_CFG_PCP, /* Pix-CLK polarity: data translations at falling edge */ -+ .slcd_cfg = 0, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 320, 240, 80, 1, 1, 10, 50, 10, 13 -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+// LCD_OSDC_F1EN | /* enable Foreground1 */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -+ }, -+#elif defined(CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_SERIAL_TFT | /* Serial TFT panel */ -+ LCD_CFG_MODE_TFT_18BIT | /* output 18bpp */ -+ LCD_CFG_HSP | /* Hsync polarity: active low */ -+ LCD_CFG_VSP | /* Vsync polarity: leading edge is falling edge */ -+ LCD_CFG_PCP, /* Pix-CLK polarity: data translations at falling edge */ -+ .slcd_cfg = 0, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 320, 240, 60, 1, 1, 10, 50, 10, 13 -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -+ }, -+#elif defined(CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A) -+ .panel = { -+// .cfg = LCD_CFG_LCDPIN_SLCD | LCD_CFG_RECOVER | /* Underrun recover*/ -+ .cfg = LCD_CFG_LCDPIN_SLCD | /* Underrun recover*/ -+// LCD_CFG_DITHER | /* dither */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_SLCD, /* TFT Smart LCD panel */ -+ .slcd_cfg = SLCD_CFG_DWIDTH_18BIT | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING | SLCD_CFG_TYPE_PARALLEL, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+ 400, 240, 60, 0, 0, 0, 0, 0, 0, -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+// LCD_OSDC_ALPHAMD | /* alpha blending mode */ -+// LCD_OSDC_F1EN | /* enable Foreground1 */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+// .fg0 = {32, 0, 0, 400, 240}, /* bpp, x, y, w, h */ -+ .fg0 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 400, 240}, /* bpp, x, y, w, h */ -+ }, -+#elif defined(CONFIG_JZ4750D_VGA_DISPLAY) -+ .panel = { -+ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER |/* Underrun recover */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -+ LCD_CFG_MODE_TFT_24BIT | /* output 18bpp */ -+ LCD_CFG_HSP | /* Hsync polarity: active low */ -+ LCD_CFG_VSP, /* Vsync polarity: leading edge is falling edge */ -+ .slcd_cfg = 0, -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -+// 800, 600, 60, 128, 4, 40, 88, 0, 23 -+ 640, 480, 54, 96, 2, 16, 48, 10, 33 -+// 1280, 720, 50, 152, 15, 22, 200, 14, 1 -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+// LCD_OSDC_F1EN | /* enable Foreground1 */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = 0, -+ .bgcolor = 0x000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80001000, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32, 0, 0, 640, 480}, /* bpp, x, y, w, h */ -+ .fg1 = {32, 0, 0, 640, 480}, /* bpp, x, y, w, h */ -+ }, -+#else -+#error "Select LCD panel first!!!" -+#endif -+}; -+ -+struct jz4750lcd_info jz4750_info_tve = { -+ .panel = { -+ .cfg = LCD_CFG_TVEN | /* output to tve */ -+ LCD_CFG_NEWDES | /* 8words descriptor */ -+ LCD_CFG_RECOVER | /* underrun protect */ -+ LCD_CFG_MODE_INTER_CCIR656, /* Interlace CCIR656 mode */ -+ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst */ -+ TVE_WIDTH_PAL, TVE_HEIGHT_PAL, TVE_FREQ_PAL, 0, 0, 0, 0, 0, 0, -+ }, -+ .osd = { -+ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -+// LCD_OSDC_ALPHAEN | /* enable alpha */ -+ LCD_OSDC_F0EN, /* enable Foreground0 */ -+ .osd_ctrl = 0, /* disable ipu, */ -+ .rgb_ctrl = LCD_RGBC_YCC, /* enable RGB => YUV */ -+ .bgcolor = 0x00000000, /* set background color Black */ -+ .colorkey0 = 0, /* disable colorkey */ -+ .colorkey1 = 0, /* disable colorkey */ -+ .alpha = 0xA0, /* alpha value */ -+ .ipu_restart = 0x80000100, /* ipu restart */ -+ .fg_change = FG_CHANGE_ALL, /* change all initially */ -+ .fg0 = {32,}, /* */ -+ .fg0 = {32,}, -+ }, -+}; -+ -+ -+struct jz4750lcd_info *jz4750_lcd_info = &jz4750_lcd_panel; /* default output to lcd panel */ -+ -+#ifdef DEBUG -+static void print_lcdc_registers(void) /* debug */ -+{ -+ /* LCD Controller Resgisters */ -+ printk("REG_LCD_CFG:\t0x%08x\n", REG_LCD_CFG); -+ printk("REG_LCD_CTRL:\t0x%08x\n", REG_LCD_CTRL); -+ printk("REG_LCD_STATE:\t0x%08x\n", REG_LCD_STATE); -+ printk("REG_LCD_OSDC:\t0x%08x\n", REG_LCD_OSDC); -+ printk("REG_LCD_OSDCTRL:\t0x%08x\n", REG_LCD_OSDCTRL); -+ printk("REG_LCD_OSDS:\t0x%08x\n", REG_LCD_OSDS); -+ printk("REG_LCD_BGC:\t0x%08x\n", REG_LCD_BGC); -+ printk("REG_LCD_KEK0:\t0x%08x\n", REG_LCD_KEY0); -+ printk("REG_LCD_KEY1:\t0x%08x\n", REG_LCD_KEY1); -+ printk("REG_LCD_ALPHA:\t0x%08x\n", REG_LCD_ALPHA); -+ printk("REG_LCD_IPUR:\t0x%08x\n", REG_LCD_IPUR); -+ printk("REG_LCD_VAT:\t0x%08x\n", REG_LCD_VAT); -+ printk("REG_LCD_DAH:\t0x%08x\n", REG_LCD_DAH); -+ printk("REG_LCD_DAV:\t0x%08x\n", REG_LCD_DAV); -+ printk("REG_LCD_XYP0:\t0x%08x\n", REG_LCD_XYP0); -+ printk("REG_LCD_XYP1:\t0x%08x\n", REG_LCD_XYP1); -+ printk("REG_LCD_SIZE0:\t0x%08x\n", REG_LCD_SIZE0); -+ printk("REG_LCD_SIZE1:\t0x%08x\n", REG_LCD_SIZE1); -+ printk("REG_LCD_RGBC\t0x%08x\n", REG_LCD_RGBC); -+ printk("REG_LCD_VSYNC:\t0x%08x\n", REG_LCD_VSYNC); -+ printk("REG_LCD_HSYNC:\t0x%08x\n", REG_LCD_HSYNC); -+ printk("REG_LCD_PS:\t0x%08x\n", REG_LCD_PS); -+ printk("REG_LCD_CLS:\t0x%08x\n", REG_LCD_CLS); -+ printk("REG_LCD_SPL:\t0x%08x\n", REG_LCD_SPL); -+ printk("REG_LCD_REV:\t0x%08x\n", REG_LCD_REV); -+ printk("REG_LCD_IID:\t0x%08x\n", REG_LCD_IID); -+ printk("REG_LCD_DA0:\t0x%08x\n", REG_LCD_DA0); -+ printk("REG_LCD_SA0:\t0x%08x\n", REG_LCD_SA0); -+ printk("REG_LCD_FID0:\t0x%08x\n", REG_LCD_FID0); -+ printk("REG_LCD_CMD0:\t0x%08x\n", REG_LCD_CMD0); -+ printk("REG_LCD_OFFS0:\t0x%08x\n", REG_LCD_OFFS0); -+ printk("REG_LCD_PW0:\t0x%08x\n", REG_LCD_PW0); -+ printk("REG_LCD_CNUM0:\t0x%08x\n", REG_LCD_CNUM0); -+ printk("REG_LCD_DESSIZE0:\t0x%08x\n", REG_LCD_DESSIZE0); -+ printk("REG_LCD_DA1:\t0x%08x\n", REG_LCD_DA1); -+ printk("REG_LCD_SA1:\t0x%08x\n", REG_LCD_SA1); -+ printk("REG_LCD_FID1:\t0x%08x\n", REG_LCD_FID1); -+ printk("REG_LCD_CMD1:\t0x%08x\n", REG_LCD_CMD1); -+ printk("REG_LCD_OFFS1:\t0x%08x\n", REG_LCD_OFFS1); -+ printk("REG_LCD_PW1:\t0x%08x\n", REG_LCD_PW1); -+ printk("REG_LCD_CNUM1:\t0x%08x\n", REG_LCD_CNUM1); -+ printk("REG_LCD_DESSIZE1:\t0x%08x\n", REG_LCD_DESSIZE1); -+ printk("==================================\n"); -+ printk("REG_LCD_VSYNC:\t%d:%d\n", REG_LCD_VSYNC>>16, REG_LCD_VSYNC&0xfff); -+ printk("REG_LCD_HSYNC:\t%d:%d\n", REG_LCD_HSYNC>>16, REG_LCD_HSYNC&0xfff); -+ printk("REG_LCD_VAT:\t%d:%d\n", REG_LCD_VAT>>16, REG_LCD_VAT&0xfff); -+ printk("REG_LCD_DAH:\t%d:%d\n", REG_LCD_DAH>>16, REG_LCD_DAH&0xfff); -+ printk("REG_LCD_DAV:\t%d:%d\n", REG_LCD_DAV>>16, REG_LCD_DAV&0xfff); -+ printk("==================================\n"); -+ -+ /* Smart LCD Controller Resgisters */ -+ printk("REG_SLCD_CFG:\t0x%08x\n", REG_SLCD_CFG); -+ printk("REG_SLCD_CTRL:\t0x%08x\n", REG_SLCD_CTRL); -+ printk("REG_SLCD_STATE:\t0x%08x\n", REG_SLCD_STATE); -+ printk("==================================\n"); -+ -+ /* TVE Controller Resgisters */ -+ printk("REG_TVE_CTRL:\t0x%08x\n", REG_TVE_CTRL); -+ printk("REG_TVE_FRCFG:\t0x%08x\n", REG_TVE_FRCFG); -+ printk("REG_TVE_SLCFG1:\t0x%08x\n", REG_TVE_SLCFG1); -+ printk("REG_TVE_SLCFG2:\t0x%08x\n", REG_TVE_SLCFG2); -+ printk("REG_TVE_SLCFG3:\t0x%08x\n", REG_TVE_SLCFG3); -+ printk("REG_TVE_LTCFG1:\t0x%08x\n", REG_TVE_LTCFG1); -+ printk("REG_TVE_LTCFG2:\t0x%08x\n", REG_TVE_LTCFG2); -+ printk("REG_TVE_CFREQ:\t0x%08x\n", REG_TVE_CFREQ); -+ printk("REG_TVE_CPHASE:\t0x%08x\n", REG_TVE_CPHASE); -+ printk("REG_TVE_CBCRCFG:\t0x%08x\n", REG_TVE_CBCRCFG); -+ printk("REG_TVE_WSSCR:\t0x%08x\n", REG_TVE_WSSCR); -+ printk("REG_TVE_WSSCFG1:\t0x%08x\n", REG_TVE_WSSCFG1); -+ printk("REG_TVE_WSSCFG2:\t0x%08x\n", REG_TVE_WSSCFG2); -+ printk("REG_TVE_WSSCFG3:\t0x%08x\n", REG_TVE_WSSCFG3); -+ -+ printk("==================================\n"); -+ -+ if ( 1 ) { -+ unsigned int * pii = (unsigned int *)dma_desc_base; -+ int i, j; -+ for (j=0;j< DMA_DESC_NUM ; j++) { -+ printk("dma_desc%d(0x%08x):\n", j, (unsigned int)pii); -+ for (i =0; i<8; i++ ) { -+ printk("\t\t0x%08x\n", *pii++); -+ } -+ } -+ } -+} -+#else -+#define print_lcdc_registers() -+#endif -+ -+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -+{ -+ chan &= 0xffff; -+ chan >>= 16 - bf->length; -+ return chan << bf->offset; -+} -+ -+static int jz4750fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -+ u_int transp, struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ unsigned short *ptr, ctmp; -+ -+// print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); -+ if (regno >= NR_PALETTE) -+ return 1; -+ -+ cfb->palette[regno].red = red ; -+ cfb->palette[regno].green = green; -+ cfb->palette[regno].blue = blue; -+ if (cfb->fb.var.bits_per_pixel <= 16) { -+ red >>= 8; -+ green >>= 8; -+ blue >>= 8; -+ -+ red &= 0xff; -+ green &= 0xff; -+ blue &= 0xff; -+ } -+ switch (cfb->fb.var.bits_per_pixel) { -+ case 1: -+ case 2: -+ case 4: -+ case 8: -+ if (((jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_MASK) == LCD_CFG_MODE_SINGLE_MSTN ) || -+ ((jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_MASK) == LCD_CFG_MODE_DUAL_MSTN )) { -+ ctmp = (77L * red + 150L * green + 29L * blue) >> 8; -+ ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | -+ (ctmp >> 3); -+ } else { -+ /* RGB 565 */ -+ if (((red >> 3) == 0) && ((red >> 2) != 0)) -+ red = 1 << 3; -+ if (((blue >> 3) == 0) && ((blue >> 2) != 0)) -+ blue = 1 << 3; -+ ctmp = ((red >> 3) << 11) -+ | ((green >> 2) << 5) | (blue >> 3); -+ } -+ -+ ptr = (unsigned short *)lcd_palette; -+ ptr = (unsigned short *)(((u32)ptr)|0xa0000000); -+ ptr[regno] = ctmp; -+ -+ break; -+ -+ case 15: -+ if (regno < 16) -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ ((red >> 3) << 10) | -+ ((green >> 3) << 5) | -+ (blue >> 3); -+ break; -+ case 16: -+ if (regno < 16) { -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ ((red >> 3) << 11) | -+ ((green >> 2) << 5) | -+ (blue >> 3); -+ } -+ break; -+ case 17 ... 32: -+ if (regno < 16) -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ (red << 16) | -+ (green << 8) | -+ (blue << 0); -+ -+/* if (regno < 16) { -+ unsigned val; -+ val = chan_to_field(red, &cfb->fb.var.red); -+ val |= chan_to_field(green, &cfb->fb.var.green); -+ val |= chan_to_field(blue, &cfb->fb.var.blue); -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = val; -+ } -+*/ -+ -+ break; -+ } -+ return 0; -+} -+ -+ -+/* -+ * switch to tve mode from lcd mode -+ * mode: -+ * PANEL_MODE_TVE_PAL: switch to TVE_PAL mode -+ * PANEL_MODE_TVE_NTSC: switch to TVE_NTSC mode -+ */ -+static void jz4750lcd_info_switch_to_TVE(int mode) -+{ -+ struct jz4750lcd_info *info; -+ struct jz4750lcd_osd_t *osd_lcd; -+ int x, y, w, h; -+ -+ info = jz4750_lcd_info = &jz4750_info_tve; -+ osd_lcd = &jz4750_lcd_panel.osd; -+ -+ switch ( mode ) { -+ case PANEL_MODE_TVE_PAL: -+ info->panel.cfg |= LCD_CFG_TVEPEH; /* TVE PAL enable extra halfline signal */ -+ info->panel.w = TVE_WIDTH_PAL; -+ info->panel.h = TVE_HEIGHT_PAL; -+ info->panel.fclk = TVE_FREQ_PAL; -+ w = ( osd_lcd->fg0.w < TVE_WIDTH_PAL )? osd_lcd->fg0.w:TVE_WIDTH_PAL; -+ h = ( osd_lcd->fg0.h < TVE_HEIGHT_PAL )?osd_lcd->fg0.h:TVE_HEIGHT_PAL; -+ x = ((TVE_WIDTH_PAL - w) >> 2) << 1; -+ y = ((TVE_HEIGHT_PAL - h) >> 2) << 1; -+// x = 0; -+// y = 0; -+ info->osd.fg0.bpp = osd_lcd->fg0.bpp; -+ info->osd.fg0.x = x; -+ info->osd.fg0.y = y; -+ info->osd.fg0.w = w; -+ info->osd.fg0.h = h; -+ w = ( osd_lcd->fg1.w < TVE_WIDTH_PAL )? osd_lcd->fg1.w:TVE_WIDTH_PAL; -+ h = ( osd_lcd->fg1.h < TVE_HEIGHT_PAL )?osd_lcd->fg1.h:TVE_HEIGHT_PAL; -+ x = ((TVE_WIDTH_PAL-w) >> 2) << 1; -+ y = ((TVE_HEIGHT_PAL-h) >> 2) << 1; -+ info->osd.fg1.bpp = 32; /* use RGB888 in TVE mode*/ -+ info->osd.fg1.x = x; -+ info->osd.fg1.y = y; -+ info->osd.fg1.w = w; -+ info->osd.fg1.h = h; -+ break; -+ case PANEL_MODE_TVE_NTSC: -+ info->panel.cfg &= ~LCD_CFG_TVEPEH; /* TVE NTSC disable extra halfline signal */ -+ info->panel.w = TVE_WIDTH_NTSC; -+ info->panel.h = TVE_HEIGHT_NTSC; -+ info->panel.fclk = TVE_FREQ_NTSC; -+ w = ( osd_lcd->fg0.w < TVE_WIDTH_NTSC )? osd_lcd->fg0.w:TVE_WIDTH_NTSC; -+ h = ( osd_lcd->fg0.h < TVE_HEIGHT_NTSC)?osd_lcd->fg0.h:TVE_HEIGHT_NTSC; -+ x = ((TVE_WIDTH_NTSC - w) >> 2) << 1; -+ y = ((TVE_HEIGHT_NTSC - h) >> 2) << 1; -+// x = 0; -+// y = 0; -+ info->osd.fg0.bpp = osd_lcd->fg0.bpp; -+ info->osd.fg0.x = x; -+ info->osd.fg0.y = y; -+ info->osd.fg0.w = w; -+ info->osd.fg0.h = h; -+ w = ( osd_lcd->fg1.w < TVE_WIDTH_NTSC )? osd_lcd->fg1.w:TVE_WIDTH_NTSC; -+ h = ( osd_lcd->fg1.h < TVE_HEIGHT_NTSC)?osd_lcd->fg1.h:TVE_HEIGHT_NTSC; -+ x = ((TVE_WIDTH_NTSC - w) >> 2) << 1; -+ y = ((TVE_HEIGHT_NTSC - h) >> 2) << 1; -+ info->osd.fg1.bpp = 32; /* use RGB888 int TVE mode */ -+ info->osd.fg1.x = x; -+ info->osd.fg1.y = y; -+ info->osd.fg1.w = w; -+ info->osd.fg1.h = h; -+ break; -+ default: -+ printk("%s, %s: Unknown tve mode\n", __FILE__, __FUNCTION__); -+ } -+} -+ -+static int jz4750fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) -+{ -+ int ret = 0; -+ -+ void __user *argp = (void __user *)arg; -+ -+// struct jz4750lcd_info *lcd_info = jz4750_lcd_info; -+ -+ -+ switch (cmd) { -+ case FBIOSETBACKLIGHT: -+ __lcd_set_backlight_level(arg); /* We support 8 levels here. */ -+ break; -+ case FBIODISPON: -+ REG_LCD_STATE = 0; /* clear lcdc status */ -+ __lcd_slcd_special_on(); -+ __lcd_clr_dis(); -+ __lcd_set_ena(); /* enable lcdc */ -+ __lcd_display_on(); -+ break; -+ case FBIODISPOFF: -+ __lcd_display_off(); -+ if ( jz4750_lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD || -+ jz4750_lcd_info->panel.cfg & LCD_CFG_TVEN ) /* */ -+ __lcd_clr_ena(); /* Smart lcd and TVE mode only support quick disable */ -+ else -+ __lcd_set_dis(); /* regular disable */ -+ break; -+ case FBIOPRINT_REG: -+ print_lcdc_registers(); -+ break; -+ case FBIO_GET_MODE: -+ print_dbg("fbio get mode\n"); -+ if (copy_to_user(argp, jz4750_lcd_info, sizeof(struct jz4750lcd_info))) -+ return -EFAULT; -+ break; -+ case FBIO_SET_MODE: -+ print_dbg("fbio set mode\n"); -+ if (copy_from_user(jz4750_lcd_info, argp, sizeof(struct jz4750lcd_info))) -+ return -EFAULT; -+ /* set mode */ -+ jz4750fb_set_mode(jz4750_lcd_info); -+ break; -+ case FBIO_DEEP_SET_MODE: -+ print_dbg("fbio deep set mode\n"); -+ if (copy_from_user(jz4750_lcd_info, argp, sizeof(struct jz4750lcd_info))) -+ return -EFAULT; -+ jz4750fb_deep_set_mode(jz4750_lcd_info); -+ break; -+#ifdef CONFIG_FB_JZ4750_TVE -+ case FBIO_MODE_SWITCH: -+ print_dbg("lcd mode switch between tve and lcd, arg=%lu\n", arg); -+ switch ( arg ) { -+ case PANEL_MODE_TVE_PAL: /* switch to TVE_PAL mode */ -+ case PANEL_MODE_TVE_NTSC: /* switch to TVE_NTSC mode */ -+ jz4750lcd_info_switch_to_TVE(arg); -+ jz4750tve_init(arg); /* tve controller init */ -+ udelay(100); -+ jz4750tve_enable_tve(); -+ /* turn off lcd backlight */ -+ __lcd_display_off(); -+ break; -+ case PANEL_MODE_LCD_PANEL: /* switch to LCD mode */ -+ default : -+ /* turn off TVE, turn off DACn... */ -+ jz4750tve_disable_tve(); -+ jz4750_lcd_info = &jz4750_lcd_panel; -+ /* turn on lcd backlight */ -+ __lcd_display_on(); -+ break; -+ } -+ jz4750fb_deep_set_mode(jz4750_lcd_info); -+ break; -+ case FBIO_GET_TVE_MODE: -+ print_dbg("fbio get TVE mode\n"); -+ if (copy_to_user(argp, jz4750_tve_info, sizeof(struct jz4750tve_info))) -+ return -EFAULT; -+ break; -+ case FBIO_SET_TVE_MODE: -+ print_dbg("fbio set TVE mode\n"); -+ if (copy_from_user(jz4750_tve_info, argp, sizeof(struct jz4750tve_info))) -+ return -EFAULT; -+ /* set tve mode */ -+ jz4750tve_set_tve_mode(jz4750_tve_info); -+ break; -+#endif -+ default: -+ printk("%s, unknown command(0x%x)", __FILE__, cmd); -+ break; -+ } -+ -+ return ret; -+} -+ -+/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -+static int jz4750fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -+ -+ /* frame buffer memory */ -+ start = cfb->fb.fix.smem_start; -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ off += start; -+ -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -+ -+#if 1 -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -+// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Back */ -+#endif -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot)) { -+ return -EAGAIN; -+ } -+ return 0; -+} -+ -+/* checks var and eventually tweaks it to something supported, -+ * DO NOT MODIFY PAR */ -+static int jz4750fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ printk("jz4750fb_check_var, not implement\n"); -+ return 0; -+} -+ -+ -+/* -+ * set the video mode according to info->var -+ */ -+static int jz4750fb_set_par(struct fb_info *info) -+{ -+ printk("jz4750fb_set_par, not implemented\n"); -+ return 0; -+} -+ -+ -+/* -+ * (Un)Blank the display. -+ * Fix me: should we use VESA value? -+ */ -+static int jz4750fb_blank(int blank_mode, struct fb_info *info) -+{ -+ dprintk("jz4750 fb_blank %d %p", blank_mode, info); -+ switch (blank_mode) { -+ case FB_BLANK_UNBLANK: -+ //case FB_BLANK_NORMAL: -+ /* Turn on panel */ -+ __lcd_set_ena(); -+ __lcd_display_on(); -+ break; -+ -+ case FB_BLANK_NORMAL: -+ case FB_BLANK_VSYNC_SUSPEND: -+ case FB_BLANK_HSYNC_SUSPEND: -+ case FB_BLANK_POWERDOWN: -+#if 0 -+ /* Turn off panel */ -+ __lcd_display_off(); -+ __lcd_set_dis(); -+#endif -+ break; -+ default: -+ break; -+ -+ } -+ return 0; -+} -+ -+/* -+ * pan display -+ */ -+static int jz4750fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ int dy; -+ -+ if (!var || !cfb) { -+ return -EINVAL; -+ } -+ -+ if (var->xoffset - cfb->fb.var.xoffset) { -+ /* No support for X panning for now! */ -+ return -EINVAL; -+ } -+ -+ dy = var->yoffset; -+ print_dbg("var.yoffset: %d", dy); -+ if (dy) { -+ dma1_desc0->databuf = (unsigned int)virt_to_phys((void *)lcd_frame0 + (cfb->fb.fix.line_length * dy)); -+ dma_cache_wback((unsigned int)(dma1_desc0), sizeof(struct jz4750_lcd_dma_desc)); -+ -+ } -+ else { -+ dma1_desc0->databuf = (unsigned int)virt_to_phys((void *)lcd_frame0); -+ dma_cache_wback((unsigned int)(dma1_desc0), sizeof(struct jz4750_lcd_dma_desc)); -+ } -+ -+ return 0; -+} -+ -+ -+/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ -+static struct fb_ops jz4750fb_ops = { -+ .owner = THIS_MODULE, -+ .fb_setcolreg = jz4750fb_setcolreg, -+ .fb_check_var = jz4750fb_check_var, -+ .fb_set_par = jz4750fb_set_par, -+ .fb_blank = jz4750fb_blank, -+ .fb_pan_display = jz4750fb_pan_display, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+ .fb_mmap = jz4750fb_mmap, -+ .fb_ioctl = jz4750fb_ioctl, -+}; -+ -+static int jz4750fb_set_var(struct fb_var_screeninfo *var, int con, -+ struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ struct jz4750lcd_info *lcd_info = jz4750_lcd_info; -+ int chgvar = 0; -+ -+ var->height = lcd_info->osd.fg0.h; /* tve mode */ -+ var->width = lcd_info->osd.fg0.w; -+ var->bits_per_pixel = lcd_info->osd.fg0.bpp; -+ -+ var->vmode = FB_VMODE_NONINTERLACED; -+ var->activate = cfb->fb.var.activate; -+ var->xres = var->width; -+ var->yres = var->height; -+ var->xres_virtual = var->width; -+ var->yres_virtual = var->height; -+ var->xoffset = 0; -+ var->yoffset = 0; -+ var->pixclock = 0; -+ var->left_margin = 0; -+ var->right_margin = 0; -+ var->upper_margin = 0; -+ var->lower_margin = 0; -+ var->hsync_len = 0; -+ var->vsync_len = 0; -+ var->sync = 0; -+ var->activate &= ~FB_ACTIVATE_TEST; -+ -+ /* -+ * CONUPDATE and SMOOTH_XPAN are equal. However, -+ * SMOOTH_XPAN is only used internally by fbcon. -+ */ -+ if (var->vmode & FB_VMODE_CONUPDATE) { -+ var->vmode |= FB_VMODE_YWRAP; -+ var->xoffset = cfb->fb.var.xoffset; -+ var->yoffset = cfb->fb.var.yoffset; -+ } -+ -+ if (var->activate & FB_ACTIVATE_TEST) -+ return 0; -+ -+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) -+ return -EINVAL; -+ -+ if (cfb->fb.var.xres != var->xres) -+ chgvar = 1; -+ if (cfb->fb.var.yres != var->yres) -+ chgvar = 1; -+ if (cfb->fb.var.xres_virtual != var->xres_virtual) -+ chgvar = 1; -+ if (cfb->fb.var.yres_virtual != var->yres_virtual) -+ chgvar = 1; -+ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) -+ chgvar = 1; -+ -+ //display = fb_display + con; -+ -+ var->red.msb_right = 0; -+ var->green.msb_right = 0; -+ var->blue.msb_right = 0; -+ -+ switch(var->bits_per_pixel){ -+ case 1: /* Mono */ -+ cfb->fb.fix.visual = FB_VISUAL_MONO01; -+ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ break; -+ case 2: /* Mono */ -+ var->red.offset = 0; -+ var->red.length = 2; -+ var->green.offset = 0; -+ var->green.length = 2; -+ var->blue.offset = 0; -+ var->blue.length = 2; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ break; -+ case 4: /* PSEUDOCOLOUR*/ -+ var->red.offset = 0; -+ var->red.length = 4; -+ var->green.offset = 0; -+ var->green.length = 4; -+ var->blue.offset = 0; -+ var->blue.length = 4; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = var->xres / 2; -+ break; -+ case 8: /* PSEUDOCOLOUR, 256 */ -+ var->red.offset = 0; -+ var->red.length = 8; -+ var->green.offset = 0; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = var->xres ; -+ break; -+ case 15: /* DIRECTCOLOUR, 32k */ -+ var->bits_per_pixel = 15; -+ var->red.offset = 10; -+ var->red.length = 5; -+ var->green.offset = 5; -+ var->green.length = 5; -+ var->blue.offset = 0; -+ var->blue.length = 5; -+ -+ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 2; -+ break; -+ case 16: /* DIRECTCOLOUR, 64k */ -+ var->bits_per_pixel = 16; -+ var->red.offset = 11; -+ var->red.length = 5; -+ var->green.offset = 5; -+ var->green.length = 6; -+ var->blue.offset = 0; -+ var->blue.length = 5; -+ -+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 2; -+ break; -+ case 17 ... 32: -+ /* DIRECTCOLOUR, 256 */ -+ var->bits_per_pixel = 32; -+ -+ var->red.offset = 16; -+ var->red.length = 8; -+ var->green.offset = 8; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ var->transp.offset = 24; -+ var->transp.length = 8; -+ -+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 4; -+ break; -+ -+ default: /* in theory this should never happen */ -+ printk(KERN_WARNING "%s: don't support for %dbpp\n", -+ cfb->fb.fix.id, var->bits_per_pixel); -+ break; -+ } -+ -+ cfb->fb.var = *var; -+ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; -+ -+ /* -+ * Update the old var. The fbcon drivers still use this. -+ * Once they are using cfb->fb.var, this can be dropped. -+ * --rmk -+ */ -+ //display->var = cfb->fb.var; -+ /* -+ * If we are setting all the virtual consoles, also set the -+ * defaults used to create new consoles. -+ */ -+ fb_set_cmap(&cfb->fb.cmap, &cfb->fb); -+ dprintk("jz4750fb_set_var: after fb_set_cmap...\n"); -+ -+ return 0; -+} -+ -+static struct lcd_cfb_info * jz4750fb_alloc_fb_info(void) -+{ -+ struct lcd_cfb_info *cfb; -+ -+ cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); -+ -+ if (!cfb) -+ return NULL; -+ -+ jz4750fb_info = cfb; -+ -+ memset(cfb, 0, sizeof(struct lcd_cfb_info) ); -+ -+ cfb->currcon = -1; -+ -+ -+ strcpy(cfb->fb.fix.id, "jz-lcd"); -+ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; -+ cfb->fb.fix.type_aux = 0; -+ cfb->fb.fix.xpanstep = 1; -+ cfb->fb.fix.ypanstep = 1; -+ cfb->fb.fix.ywrapstep = 0; -+ cfb->fb.fix.accel = FB_ACCEL_NONE; -+ -+ cfb->fb.var.nonstd = 0; -+ cfb->fb.var.activate = FB_ACTIVATE_NOW; -+ cfb->fb.var.height = -1; -+ cfb->fb.var.width = -1; -+ cfb->fb.var.accel_flags = FB_ACCELF_TEXT; -+ -+ cfb->fb.fbops = &jz4750fb_ops; -+ cfb->fb.flags = FBINFO_FLAG_DEFAULT; -+ -+ cfb->fb.pseudo_palette = (void *)(cfb + 1); -+ -+ switch (jz4750_lcd_info->osd.fg0.bpp) { -+ case 1: -+ fb_alloc_cmap(&cfb->fb.cmap, 4, 0); -+ break; -+ case 2: -+ fb_alloc_cmap(&cfb->fb.cmap, 8, 0); -+ break; -+ case 4: -+ fb_alloc_cmap(&cfb->fb.cmap, 32, 0); -+ break; -+ case 8: -+ -+ default: -+ fb_alloc_cmap(&cfb->fb.cmap, 256, 0); -+ break; -+ } -+ dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); -+ -+ return cfb; -+} -+ -+/* -+ * Map screen memory -+ */ -+static int jz4750fb_map_smem(struct lcd_cfb_info *cfb) -+{ -+ unsigned long page; -+ unsigned int page_shift, needroom, needroom1, bpp, w, h; -+ -+ bpp = jz4750_lcd_info->osd.fg0.bpp; -+ if ( bpp == 18 || bpp == 24) -+ bpp = 32; -+ if ( bpp == 15 ) -+ bpp = 16; -+#ifndef CONFIG_FB_JZ4750_TVE -+ w = jz4750_lcd_info->osd.fg0.w; -+ h = jz4750_lcd_info->osd.fg0.h; -+#else -+ w = ( jz4750_lcd_info->osd.fg0.w > TVE_WIDTH_PAL )?jz4750_lcd_info->osd.fg0.w:TVE_WIDTH_PAL; -+ h = ( jz4750_lcd_info->osd.fg0.h > TVE_HEIGHT_PAL )?jz4750_lcd_info->osd.fg0.h:TVE_HEIGHT_PAL; -+#endif -+ needroom1 = needroom = ((w * bpp + 7) >> 3) * h; -+#if defined(CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER) -+ bpp = jz4750_lcd_info->osd.fg1.bpp; -+ if ( bpp == 18 || bpp == 24) -+ bpp = 32; -+ if ( bpp == 15 ) -+ bpp = 16; -+ -+#ifndef CONFIG_FB_JZ4750_TVE -+ w = jz4750_lcd_info->osd.fg1.w; -+ h = jz4750_lcd_info->osd.fg1.h; -+#else -+ w = ( jz4750_lcd_info->osd.fg1.w > TVE_WIDTH_PAL )?jz4750_lcd_info->osd.fg1.w:TVE_WIDTH_PAL; -+ h = ( jz4750_lcd_info->osd.fg1.h > TVE_HEIGHT_PAL )?jz4750_lcd_info->osd.fg1.h:TVE_HEIGHT_PAL; -+#endif -+ needroom += ((w * bpp + 7) >> 3) * h; -+#endif // two layer -+ -+ -+ for (page_shift = 0; page_shift < 12; page_shift++) -+ if ((PAGE_SIZE << page_shift) >= needroom) -+ break; -+ lcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -+ lcd_frame0 = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ -+ if ((!lcd_palette) || (!lcd_frame0)) -+ return -ENOMEM; -+ memset((void *)lcd_palette, 0, PAGE_SIZE); -+ memset((void *)lcd_frame0, 0, PAGE_SIZE << page_shift); -+ -+ dma_desc_base = (struct jz4750_lcd_dma_desc *)((void*)lcd_palette + ((PALETTE_SIZE+3)/4)*4); -+ -+#if defined(CONFIG_FB_JZ4750_SLCD) -+ -+ lcd_cmdbuf = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -+ memset((void *)lcd_cmdbuf, 0, PAGE_SIZE); -+ -+ { int data, i, *ptr; -+ ptr = (unsigned int *)lcd_cmdbuf; -+ data = WR_GRAM_CMD; -+ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -+ for(i = 0; i < 3; i++){ -+ ptr[i] = data; -+ } -+ } -+#endif -+ -+#if defined(CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER) -+ lcd_frame1 = lcd_frame0 + needroom1; -+#endif -+ -+ /* -+ * Set page reserved so that mmap will work. This is necessary -+ * since we'll be remapping normal memory. -+ */ -+ page = (unsigned long)lcd_palette; -+ SetPageReserved(virt_to_page((void*)page)); -+ -+ for (page = (unsigned long)lcd_frame0; -+ page < PAGE_ALIGN((unsigned long)lcd_frame0 + (PAGE_SIZE<fb.fix.smem_start = virt_to_phys((void *)lcd_frame0); -+ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); /* page_shift/2 ??? */ -+ cfb->fb.screen_base = -+ (unsigned char *)(((unsigned int)lcd_frame0&0x1fffffff) | 0xa0000000); -+ -+ if (!cfb->fb.screen_base) { -+ printk("jz4750fb, %s: unable to map screen memory\n", cfb->fb.fix.id); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void jz4750fb_free_fb_info(struct lcd_cfb_info *cfb) -+{ -+ if (cfb) { -+ fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -+ kfree(cfb); -+ } -+} -+ -+static void jz4750fb_unmap_smem(struct lcd_cfb_info *cfb) -+{ -+ struct page * map = NULL; -+ unsigned char *tmp; -+ unsigned int page_shift, needroom, bpp, w, h; -+ -+ bpp = jz4750_lcd_info->osd.fg0.bpp; -+ if ( bpp == 18 || bpp == 24) -+ bpp = 32; -+ if ( bpp == 15 ) -+ bpp = 16; -+ w = jz4750_lcd_info->osd.fg0.w; -+ h = jz4750_lcd_info->osd.fg0.h; -+ needroom = ((w * bpp + 7) >> 3) * h; -+#if defined(CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER) -+ bpp = jz4750_lcd_info->osd.fg1.bpp; -+ if ( bpp == 18 || bpp == 24) -+ bpp = 32; -+ if ( bpp == 15 ) -+ bpp = 16; -+ w = jz4750_lcd_info->osd.fg1.w; -+ h = jz4750_lcd_info->osd.fg1.h; -+ needroom += ((w * bpp + 7) >> 3) * h; -+#endif -+ -+ for (page_shift = 0; page_shift < 12; page_shift++) -+ if ((PAGE_SIZE << page_shift) >= needroom) -+ break; -+ -+ if (cfb && cfb->fb.screen_base) { -+ iounmap(cfb->fb.screen_base); -+ cfb->fb.screen_base = NULL; -+ release_mem_region(cfb->fb.fix.smem_start, -+ cfb->fb.fix.smem_len); -+ } -+ -+ if (lcd_palette) { -+ map = virt_to_page(lcd_palette); -+ clear_bit(PG_reserved, &map->flags); -+ free_pages((int)lcd_palette, 0); -+ } -+ -+ if (lcd_frame0) { -+ for (tmp=(unsigned char *)lcd_frame0; -+ tmp < lcd_frame0 + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ clear_bit(PG_reserved, &map->flags); -+ } -+ free_pages((int)lcd_frame0, page_shift); -+ } -+} -+ -+/* initial dma descriptors */ -+static void jz4750fb_descriptor_init( struct jz4750lcd_info * lcd_info ) -+{ -+ unsigned int pal_size; -+ -+ switch ( lcd_info->osd.fg0.bpp ) { -+ case 1: -+ pal_size = 4; -+ break; -+ case 2: -+ pal_size = 8; -+ break; -+ case 4: -+ pal_size = 32; -+ break; -+ case 8: -+ default: -+ pal_size = 512; -+ } -+ -+ pal_size /= 4; -+ -+ dma0_desc_palette = dma_desc_base + 0; -+ dma0_desc0 = dma_desc_base + 1; -+ dma0_desc1 = dma_desc_base + 2; -+ dma0_desc_cmd0 = dma_desc_base + 3; /* use only once */ -+ dma0_desc_cmd = dma_desc_base + 4; -+ dma1_desc0 = dma_desc_base + 5; -+ dma1_desc1 = dma_desc_base + 6; -+ -+ /* -+ * Normal TFT panel's DMA Chan0: -+ * TO LCD Panel: -+ * no palette: dma0_desc0 <<==>> dma0_desc0 -+ * palette : dma0_desc_palette <<==>> dma0_desc0 -+ * TO TV Encoder: -+ * no palette: dma0_desc0 <<==>> dma0_desc1 -+ * palette: dma0_desc_palette --> dma0_desc0 -+ * --> dma0_desc1 --> dma0_desc_palette --> ... -+ * -+ * SMART LCD TFT panel(dma0_desc_cmd)'s DMA Chan0: -+ * TO LCD Panel: -+ * no palette: dma0_desc_cmd <<==>> dma0_desc0 -+ * palette : dma0_desc_palette --> dma0_desc_cmd -+ * --> dma0_desc0 --> dma0_desc_palette --> ... -+ * TO TV Encoder: -+ * no palette: dma0_desc_cmd --> dma0_desc0 -+ * --> dma0_desc1 --> dma0_desc_cmd --> ... -+ * palette: dma0_desc_palette --> dma0_desc_cmd -+ * --> dma0_desc0 --> dma0_desc1 -+ * --> dma0_desc_palette --> ... -+ * DMA Chan1: -+ * TO LCD Panel: -+ * dma1_desc0 <<==>> dma1_desc0 -+ * TO TV Encoder: -+ * dma1_desc0 <<==>> dma1_desc1 -+ */ -+ -+#if defined(CONFIG_FB_JZ4750_SLCD) -+ /* First CMD descriptors, use only once, cmd_num isn't 0 */ -+ dma0_desc_cmd0->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ dma0_desc_cmd0->databuf = (unsigned int)virt_to_phys((void *)lcd_cmdbuf); -+ dma0_desc_cmd0->frame_id = (unsigned int)0x0da0cad0; /* dma0's cmd0 */ -+ dma0_desc_cmd0->cmd = LCD_CMD_CMD | 3; /* command */ -+ dma0_desc_cmd0->offsize = 0; -+ dma0_desc_cmd0->page_width = 0; -+ dma0_desc_cmd0->cmd_num = 3; -+ -+ /* Dummy Command Descriptor, cmd_num is 0 */ -+ dma0_desc_cmd->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ dma0_desc_cmd->databuf = 0; -+ dma0_desc_cmd->frame_id = (unsigned int)0x0da000cd; /* dma0's cmd0 */ -+ dma0_desc_cmd->cmd = LCD_CMD_CMD | 0; /* dummy command */ -+ dma0_desc_cmd->cmd_num = 0; -+ dma0_desc_cmd->offsize = 0; -+ dma0_desc_cmd->page_width = 0; -+ -+ /* Palette Descriptor */ -+ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd0); -+#else -+ /* Palette Descriptor */ -+ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+#endif -+ dma0_desc_palette->databuf = (unsigned int)virt_to_phys((void *)lcd_palette); -+ dma0_desc_palette->frame_id = (unsigned int)0xaaaaaaaa; -+ dma0_desc_palette->cmd = LCD_CMD_PAL | pal_size; /* Palette Descriptor */ -+ -+ /* DMA0 Descriptor0 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc1); -+ else{ /* Normal TFT LCD */ -+#if defined(CONFIG_FB_JZ4750_SLCD) -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -+#else -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+#endif -+ } -+ -+ dma0_desc0->databuf = virt_to_phys((void *)lcd_frame0); -+ dma0_desc0->frame_id = (unsigned int)0x0000da00; /* DMA0'0 */ -+ -+ /* DMA0 Descriptor1 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -+ -+ -+ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup */ -+ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_palette); -+ else -+#if defined(CONFIG_FB_JZ4750_SLCD) /* for smatlcd */ -+ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -+#else -+ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+#endif -+ dma0_desc1->frame_id = (unsigned int)0x0000da01; /* DMA0'1 */ -+ } -+ -+ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup */ -+ REG_LCD_DA0 = virt_to_phys(dma0_desc_palette); -+ else { -+#if defined(CONFIG_FB_JZ4750_SLCD) /* for smartlcd */ -+ REG_LCD_DA0 = virt_to_phys(dma0_desc_cmd0); //smart lcd -+#else -+ REG_LCD_DA0 = virt_to_phys(dma0_desc0); //tft -+#endif -+ } -+ -+ /* DMA1 Descriptor0 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -+ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc1); -+ else /* Normal TFT LCD */ -+ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -+ -+ dma1_desc0->databuf = virt_to_phys((void *)lcd_frame1); -+ dma1_desc0->frame_id = (unsigned int)0x0000da10; /* DMA1'0 */ -+ -+ /* DMA1 Descriptor1 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -+ dma1_desc1->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -+ dma1_desc1->frame_id = (unsigned int)0x0000da11; /* DMA1'1 */ -+ } -+ -+ REG_LCD_DA1 = virt_to_phys(dma1_desc0); /* set Dma-chan1's Descripter Addrress */ -+ dma_cache_wback_inv((unsigned int)(dma_desc_base), (DMA_DESC_NUM)*sizeof(struct jz4750_lcd_dma_desc)); -+ -+#if 0 -+ /* Palette Descriptor */ -+ if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) -+// dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -+ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd1); -+ else -+ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ dma0_desc_palette->databuf = (unsigned int)virt_to_phys((void *)lcd_palette); -+ dma0_desc_palette->frame_id = (unsigned int)0xaaaaaaaa; -+ dma0_desc_palette->cmd = LCD_CMD_PAL | pal_size; /* Palette Descriptor */ -+ -+ /* Dummy Command Descriptor, cmd_num is 0 */ -+ dma0_desc_cmd->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ dma0_desc_cmd->databuf = (unsigned int)virt_to_phys((void *)lcd_cmdbuf); -+ dma0_desc_cmd->frame_id = (unsigned int)0x0da0cad0; /* dma0's cmd0 */ -+ dma0_desc_cmd->cmd = LCD_CMD_CMD | 3; /* dummy command */ -+ dma0_desc_cmd->offsize = 0; /* dummy command */ -+ dma0_desc_cmd->page_width = 0; /* dummy command */ -+ dma0_desc_cmd->cmd_num = 3; -+ -+//--------------------------------- -+ dma0_desc_cmd1->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ dma0_desc_cmd1->databuf = 0; -+ dma0_desc_cmd1->frame_id = (unsigned int)0x0da0cad1; /* dma0's cmd0 */ -+ dma0_desc_cmd1->cmd = LCD_CMD_CMD | 0; /* dummy command */ -+ dma0_desc_cmd1->cmd_num = 0; -+ dma0_desc_cmd1->offsize = 0; /* dummy command */ -+ dma0_desc_cmd1->page_width = 0; /* dummy command */ -+//----------------------------------- -+ /* DMA0 Descriptor0 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc1); -+ else{ /* Normal TFT LCD */ -+ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup?? */ -+// dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_palette); //tft -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); // smart lcd -+ else if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd1); -+// dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -+ else -+ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ } -+ -+ dma0_desc0->databuf = virt_to_phys((void *)lcd_frame0); -+ dma0_desc0->frame_id = (unsigned int)0x0000da00; /* DMA0'0 */ -+ -+ /* DMA0 Descriptor1 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -+ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup?? */ -+ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_palette); -+ -+ else if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) -+ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -+ else -+ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -+ dma0_desc1->frame_id = (unsigned int)0x0000da01; /* DMA0'1 */ -+ } -+ -+ /* DMA1 Descriptor0 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -+ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc1); -+ else /* Normal TFT LCD */ -+ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -+ -+ dma1_desc0->databuf = virt_to_phys((void *)lcd_frame1); -+ dma1_desc0->frame_id = (unsigned int)0x0000da10; /* DMA1'0 */ -+ -+ /* DMA1 Descriptor1 */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -+ dma1_desc1->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -+ dma1_desc1->frame_id = (unsigned int)0x0000da11; /* DMA1'1 */ -+ } -+ -+ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup?? */ -+ REG_LCD_DA0 = virt_to_phys(dma0_desc_palette); -+ else -+// REG_LCD_DA0 = virt_to_phys(dma0_desc_cmd); //smart lcd -+ REG_LCD_DA0 = virt_to_phys(dma0_desc0); //tft -+ REG_LCD_DA1 = virt_to_phys(dma1_desc0); /* set Dma-chan1's Descripter Addrress */ -+ dma_cache_wback_inv((unsigned int)(dma_desc_base), (DMA_DESC_NUM)*sizeof(struct jz4750_lcd_dma_desc)); -+#endif -+} -+ -+static void jz4750fb_set_panel_mode( struct jz4750lcd_info * lcd_info ) -+{ -+ struct jz4750lcd_panel_t *panel = &lcd_info->panel; -+#ifdef CONFIG_JZ4750D_VGA_DISPLAY -+ REG_TVE_CTRL |= TVE_CTRL_DAPD; -+ REG_TVE_CTRL &= ~( TVE_CTRL_DAPD1 | TVE_CTRL_DAPD2 | TVE_CTRL_DAPD3); -+#endif -+ /* set bpp */ -+ lcd_info->panel.ctrl &= ~LCD_CTRL_BPP_MASK; -+ if ( lcd_info->osd.fg0.bpp == 1 ) -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_1; -+ else if ( lcd_info->osd.fg0.bpp == 2 ) -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_2; -+ else if ( lcd_info->osd.fg0.bpp == 4 ) -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_4; -+ else if ( lcd_info->osd.fg0.bpp == 8 ) -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_8; -+ else if ( lcd_info->osd.fg0.bpp == 15 ) -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_16 | LCD_CTRL_RGB555; -+ else if ( lcd_info->osd.fg0.bpp == 16 ) -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_16 | LCD_CTRL_RGB565; -+ else if ( lcd_info->osd.fg0.bpp > 16 && lcd_info->osd.fg0.bpp < 32+1 ) { -+ lcd_info->osd.fg0.bpp = 32; -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_18_24; -+ } -+ else { -+ printk("The BPP %d is not supported\n", lcd_info->osd.fg0.bpp); -+ lcd_info->osd.fg0.bpp = 32; -+ lcd_info->panel.ctrl |= LCD_CTRL_BPP_18_24; -+ } -+ -+ lcd_info->panel.cfg |= LCD_CFG_NEWDES; /* use 8words descriptor always */ -+ -+ REG_LCD_CTRL = lcd_info->panel.ctrl; /* LCDC Controll Register */ -+ REG_LCD_CFG = lcd_info->panel.cfg; /* LCDC Configure Register */ -+ REG_SLCD_CFG = lcd_info->panel.slcd_cfg; /* Smart LCD Configure Register */ -+ -+ if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) /* enable Smart LCD DMA */ -+ REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; -+ -+ switch ( lcd_info->panel.cfg & LCD_CFG_MODE_MASK ) { -+ case LCD_CFG_MODE_GENERIC_TFT: -+ case LCD_CFG_MODE_INTER_CCIR656: -+ case LCD_CFG_MODE_NONINTER_CCIR656: -+ case LCD_CFG_MODE_SLCD: -+ default: /* only support TFT16 TFT32, not support STN and Special TFT by now(10-06-2008)*/ -+ REG_LCD_VAT = (((panel->blw + panel->w + panel->elw + panel->hsw)) << 16) | (panel->vsw + panel->bfw + panel->h + panel->efw); -+ REG_LCD_DAH = ((panel->hsw + panel->blw) << 16) | (panel->hsw + panel->blw + panel->w); -+ REG_LCD_DAV = ((panel->vsw + panel->bfw) << 16) | (panel->vsw + panel->bfw + panel->h); -+ REG_LCD_HSYNC = (0 << 16) | panel->hsw; -+ REG_LCD_VSYNC = (0 << 16) | panel->vsw; -+ break; -+ } -+} -+ -+ -+static void jz4750fb_set_osd_mode( struct jz4750lcd_info * lcd_info ) -+{ -+ dprintk("%s, %d\n", __FILE__, __LINE__ ); -+ lcd_info->osd.osd_ctrl &= ~(LCD_OSDCTRL_OSDBPP_MASK); -+ if ( lcd_info->osd.fg1.bpp == 15 ) -+ lcd_info->osd.osd_ctrl |= LCD_OSDCTRL_OSDBPP_15_16|LCD_OSDCTRL_RGB555; -+ else if ( lcd_info->osd.fg1.bpp == 16 ) -+ lcd_info->osd.osd_ctrl |= LCD_OSDCTRL_OSDBPP_15_16|LCD_OSDCTRL_RGB565; -+ else { -+ lcd_info->osd.fg1.bpp = 32; -+ lcd_info->osd.osd_ctrl |= LCD_OSDCTRL_OSDBPP_18_24; -+ } -+ -+ REG_LCD_OSDC = lcd_info->osd.osd_cfg; /* F0, F1, alpha, */ -+ -+ REG_LCD_OSDCTRL = lcd_info->osd.osd_ctrl; /* IPUEN, bpp */ -+ REG_LCD_RGBC = lcd_info->osd.rgb_ctrl; -+ REG_LCD_BGC = lcd_info->osd.bgcolor; -+ REG_LCD_KEY0 = lcd_info->osd.colorkey0; -+ REG_LCD_KEY1 = lcd_info->osd.colorkey1; -+ REG_LCD_ALPHA = lcd_info->osd.alpha; -+ REG_LCD_IPUR = lcd_info->osd.ipu_restart; -+} -+ -+static void jz4750fb_foreground_resize( struct jz4750lcd_info * lcd_info ) -+{ -+ int fg0_line_size, fg0_frm_size, fg1_line_size, fg1_frm_size; -+ /* -+ * NOTE: -+ * Foreground change sequence: -+ * 1. Change Position Registers -> LCD_OSDCTL.Change; -+ * 2. LCD_OSDCTRL.Change -> descripter->Size -+ * Foreground, only one of the following can be change at one time: -+ * 1. F0 size; -+ * 2. F0 position -+ * 3. F1 size -+ * 4. F1 position -+ */ -+ -+ /* -+ * The rules of f0, f1's position: -+ * f0.x + f0.w <= panel.w; -+ * f0.y + f0.h <= panel.h; -+ * -+ * When output is LCD panel, fg.y and fg.h can be odd number or even number. -+ * When output is TVE, as the TVE has odd frame and even frame, -+ * to simplified operation, fg.y and fg.h should be even number always. -+ * -+ */ -+ -+ /* Foreground 0 */ -+ if ( lcd_info->osd.fg0.x >= lcd_info->panel.w ) -+ lcd_info->osd.fg0.x = lcd_info->panel.w; -+ if ( lcd_info->osd.fg0.y >= lcd_info->panel.h ) -+ lcd_info->osd.fg0.y = lcd_info->panel.h; -+ if ( lcd_info->osd.fg0.x + lcd_info->osd.fg0.w > lcd_info->panel.w ) -+ lcd_info->osd.fg0.w = lcd_info->panel.w - lcd_info->osd.fg0.x; -+ if ( lcd_info->osd.fg0.y + lcd_info->osd.fg0.h > lcd_info->panel.h ) -+ lcd_info->osd.fg0.h = lcd_info->panel.h - lcd_info->osd.fg0.y; -+ /* Foreground 1 */ -+ /* Case TVE ??? TVE 720x573 or 720x480*/ -+ if ( lcd_info->osd.fg1.x >= lcd_info->panel.w ) -+ lcd_info->osd.fg1.x = lcd_info->panel.w; -+ if ( lcd_info->osd.fg1.y >= lcd_info->panel.h ) -+ lcd_info->osd.fg1.y = lcd_info->panel.h; -+ if ( lcd_info->osd.fg1.x + lcd_info->osd.fg1.w > lcd_info->panel.w ) -+ lcd_info->osd.fg1.w = lcd_info->panel.w - lcd_info->osd.fg1.x; -+ if ( lcd_info->osd.fg1.y + lcd_info->osd.fg1.h > lcd_info->panel.h ) -+ lcd_info->osd.fg1.h = lcd_info->panel.h - lcd_info->osd.fg1.y; -+ -+// fg0_line_size = lcd_info->osd.fg0.w*((lcd_info->osd.fg0.bpp+7)/8); -+ fg0_line_size = (lcd_info->osd.fg0.w*(lcd_info->osd.fg0.bpp)/8); -+ fg0_line_size = ((fg0_line_size+3)>>2)<<2; /* word aligned */ -+ fg0_frm_size = fg0_line_size * lcd_info->osd.fg0.h; -+ -+ fg1_line_size = lcd_info->osd.fg1.w*((lcd_info->osd.fg1.bpp+7)/8); -+ fg1_line_size = ((fg1_line_size+3)>>2)<<2; /* word aligned */ -+ fg1_frm_size = fg1_line_size * lcd_info->osd.fg1.h; -+ -+ if ( lcd_info->osd.fg_change ) { -+ if ( lcd_info->osd.fg_change & FG0_CHANGE_POSITION ) { /* F1 change position */ -+ REG_LCD_XYP0 = lcd_info->osd.fg0.y << 16 | lcd_info->osd.fg0.x; -+ } -+ if ( lcd_info->osd.fg_change & FG1_CHANGE_POSITION ) { /* F1 change position */ -+ REG_LCD_XYP1 = lcd_info->osd.fg1.y << 16 | lcd_info->osd.fg1.x; -+ } -+ -+ /* set change */ -+ if ( !(lcd_info->osd.osd_ctrl & LCD_OSDCTRL_IPU) && -+ (lcd_info->osd.fg_change != FG_CHANGE_ALL) ) -+ REG_LCD_OSDCTRL |= LCD_OSDCTRL_CHANGES; -+ -+ /* wait change ready??? */ -+// while ( REG_LCD_OSDS & LCD_OSDS_READY ) /* fix in the future, Wolfgang, 06-20-2008 */ -+ print_dbg("wait LCD_OSDS_READY\n"); -+ -+ if ( lcd_info->osd.fg_change & FG0_CHANGE_SIZE ) { /* change FG0 size */ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* output to TV */ -+ dma0_desc0->cmd = dma0_desc1->cmd = (fg0_frm_size/4)/2; -+ dma0_desc0->offsize = dma0_desc1->offsize -+ = fg0_line_size/4; -+ dma0_desc0->page_width = dma0_desc1->page_width -+ = fg0_line_size/4; -+ dma0_desc1->databuf = virt_to_phys((void *)(lcd_frame0 + fg0_line_size)); -+ REG_LCD_DA0 = virt_to_phys(dma0_desc0); //tft -+ } -+ else { -+ dma0_desc0->cmd = dma0_desc1->cmd = fg0_frm_size/4; -+ dma0_desc0->offsize = dma0_desc1->offsize =0; -+ dma0_desc0->page_width = dma0_desc1->page_width = 0; -+ } -+ -+ dma0_desc0->desc_size = dma0_desc1->desc_size -+ = lcd_info->osd.fg0.h << 16 | lcd_info->osd.fg0.w; -+ REG_LCD_SIZE0 = (lcd_info->osd.fg0.h<<16)|lcd_info->osd.fg0.w; -+ -+ } -+ -+ if ( lcd_info->osd.fg_change & FG1_CHANGE_SIZE ) { /* change FG1 size*/ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* output to TV */ -+ dma1_desc0->cmd = dma1_desc1->cmd = (fg1_frm_size/4)/2; -+ dma1_desc0->offsize = dma1_desc1->offsize = fg1_line_size/4; -+ dma1_desc0->page_width = dma1_desc1->page_width = fg1_line_size/4; -+ dma1_desc1->databuf = virt_to_phys((void *)(lcd_frame1 + fg1_line_size)); -+ REG_LCD_DA1 = virt_to_phys(dma0_desc1); //tft -+ -+ } -+ else { -+ dma1_desc0->cmd = dma1_desc1->cmd = fg1_frm_size/4; -+ dma1_desc0->offsize = dma1_desc1->offsize = 0; -+ dma1_desc0->page_width = dma1_desc1->page_width = 0; -+ } -+ -+ dma1_desc0->desc_size = dma1_desc1->desc_size -+ = lcd_info->osd.fg1.h << 16 | lcd_info->osd.fg1.w; -+ REG_LCD_SIZE1 = lcd_info->osd.fg1.h << 16|lcd_info->osd.fg1.w; -+ } -+ -+ dma_cache_wback((unsigned int)(dma_desc_base), (DMA_DESC_NUM)*sizeof(struct jz4750_lcd_dma_desc)); -+ lcd_info->osd.fg_change = FG_NOCHANGE; /* clear change flag */ -+ } -+} -+ -+static void jz4750fb_change_clock( struct jz4750lcd_info * lcd_info ) -+{ -+ -+#if defined(CONFIG_FPGA) -+ REG_LCD_REV = 0x00000004; -+ printk("Fuwa test, pixclk divide REG_LCD_REV=0x%08x\n", REG_LCD_REV); -+ printk("Fuwa test, pixclk %d\n", JZ_EXTAL/(((REG_LCD_REV&0xFF)+1)*2)); -+#else -+ unsigned int val = 0; -+ unsigned int pclk; -+ /* Timing setting */ -+ __cpm_stop_lcd(); -+ -+ val = lcd_info->panel.fclk; /* frame clk */ -+ -+ if ( (lcd_info->panel.cfg & LCD_CFG_MODE_MASK) != LCD_CFG_MODE_SERIAL_TFT) { -+ pclk = val * (lcd_info->panel.w + lcd_info->panel.hsw + lcd_info->panel.elw + lcd_info->panel.blw) * (lcd_info->panel.h + lcd_info->panel.vsw + lcd_info->panel.efw + lcd_info->panel.bfw); /* Pixclk */ -+ } -+ else { -+ /* serial mode: Hsync period = 3*Width_Pixel */ -+ pclk = val * (lcd_info->panel.w*3 + lcd_info->panel.hsw + lcd_info->panel.elw + lcd_info->panel.blw) * (lcd_info->panel.h + lcd_info->panel.vsw + lcd_info->panel.efw + lcd_info->panel.bfw); /* Pixclk */ -+ } -+ -+ /********* In TVE mode PCLK = 27MHz ***********/ -+ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* LCDC output to TVE */ -+ REG_CPM_LPCDR |= CPM_LPCDR_LTCS; -+ pclk = 27000000; -+ val = __cpm_get_pllout2() / pclk; /* pclk */ -+ val--; -+ __cpm_set_pixdiv(val); -+ -+ dprintk("REG_CPM_LPCDR = 0x%08x\n", REG_CPM_LPCDR); -+#if defined(CONFIG_SOC_JZ4750) /* Jz4750D don't use LCLK */ -+ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ -+ -+ val =(__cpm_get_pllout()) / val; -+ if ( val > 0x1f ) { -+ printk("lcd clock divide is too large, set it to 0x1f\n"); -+ val = 0x1f; -+ } -+ __cpm_set_ldiv( val ); -+#endif -+ __cpm_select_pixclk_tve(); -+ -+ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -+ } -+ else { /* LCDC output to LCD panel */ -+ val = __cpm_get_pllout2() / pclk; /* pclk */ -+ val--; -+ dprintk("ratio: val = %d\n", val); -+ if ( val > 0x7ff ) { -+ printk("pixel clock divid is too large, set it to 0x7ff\n"); -+ val = 0x7ff; -+ } -+ -+ __cpm_set_pixdiv(val); -+ -+ dprintk("REG_CPM_LPCDR = 0x%08x\n", REG_CPM_LPCDR); -+#if defined(CONFIG_SOC_JZ4750) /* Jz4750D don't use LCLK */ -+ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ -+ val =__cpm_get_pllout2() / val; -+ if ( val > 0x1f ) { -+ printk("lcd clock divide is too large, set it to 0x1f\n"); -+ val = 0x1f; -+ } -+ __cpm_set_ldiv( val ); -+#endif -+ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -+ -+ } -+ -+ dprintk("REG_CPM_LPCDR=0x%08x\n", REG_CPM_LPCDR); -+ dprintk("REG_CPM_CPCCR=0x%08x\n", REG_CPM_CPCCR); -+ -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ printk("LCDC: PixClock:%d\n", jz_clocks.pixclk); -+ -+#if defined(CONFIG_SOC_JZ4750) /* Jz4750D don't use LCLK */ -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ printk("LCDC: LcdClock:%d\n", jz_clocks.lcdclk); -+#endif -+ __cpm_start_lcd(); -+ udelay(1000); -+ /* -+ * set lcd device clock and lcd pixel clock. -+ * what about TVE mode??? -+ * -+ */ -+#endif -+ -+} -+ -+/* -+ * jz4750fb_set_mode(), set osd configure, resize foreground -+ * -+ */ -+static void jz4750fb_set_mode( struct jz4750lcd_info * lcd_info ) -+{ -+ struct lcd_cfb_info *cfb = jz4750fb_info; -+ -+ jz4750fb_set_osd_mode(lcd_info); -+ jz4750fb_foreground_resize(lcd_info); -+ jz4750fb_set_var(&cfb->fb.var, -1, &cfb->fb); -+} -+ -+/* -+ * jz4750fb_deep_set_mode, -+ * -+ */ -+static void jz4750fb_deep_set_mode( struct jz4750lcd_info * lcd_info ) -+{ -+ /* configurate sequence: -+ * 1. disable lcdc. -+ * 2. init frame descriptor. -+ * 3. set panel mode -+ * 4. set osd mode -+ * 5. start lcd clock in CPM -+ * 6. enable lcdc. -+ */ -+ -+ __lcd_clr_ena(); /* Quick Disable */ -+ lcd_info->osd.fg_change = FG_CHANGE_ALL; /* change FG0, FG1 size, postion??? */ -+ jz4750fb_descriptor_init(lcd_info); -+ jz4750fb_set_panel_mode(lcd_info); -+ jz4750fb_set_mode(lcd_info); -+ jz4750fb_change_clock(lcd_info); -+ __lcd_set_ena(); /* enable lcdc */ -+} -+ -+ -+static irqreturn_t jz4750fb_interrupt_handler(int irq, void *dev_id) -+{ -+ unsigned int state; -+ static int irqcnt=0; -+ -+ state = REG_LCD_STATE; -+ dprintk("In the lcd interrupt handler, state=0x%x\n", state); -+ -+ if (state & LCD_STATE_EOF) /* End of frame */ -+ REG_LCD_STATE = state & ~LCD_STATE_EOF; -+ -+ if (state & LCD_STATE_IFU0) { -+ printk("%s, InFiFo0 underrun\n", __FUNCTION__); -+ REG_LCD_STATE = state & ~LCD_STATE_IFU0; -+ } -+ -+ if (state & LCD_STATE_IFU1) { -+ printk("%s, InFiFo1 underrun\n", __FUNCTION__); -+ REG_LCD_STATE = state & ~LCD_STATE_IFU1; -+ } -+ -+ if (state & LCD_STATE_OFU) { /* Out fifo underrun */ -+ REG_LCD_STATE = state & ~LCD_STATE_OFU; -+ if ( irqcnt++ > 100 ) { -+ __lcd_disable_ofu_intr(); -+ printk("disable Out FiFo underrun irq.\n"); -+ } -+ printk("%s, Out FiFo underrun.\n", __FUNCTION__); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+#ifdef CONFIG_PM -+ -+/* -+ * Suspend the LCDC. -+ */ -+static int jzfb_suspend(void) -+{ -+ __lcd_clr_ena(); /* Quick Disable */ -+ __lcd_display_off(); -+ __cpm_stop_lcd(); -+ -+ return 0; -+} -+ -+/* -+ * Resume the LCDC. -+ */ -+static int jzfb_resume(void) -+{ -+ __cpm_start_lcd(); -+ __gpio_set_pin(GPIO_DISP_OFF_N); -+ __lcd_special_on(); -+ __lcd_set_ena(); -+ mdelay(200); -+ __lcd_set_backlight_level(80); -+ -+ return 0; -+} -+ -+/* -+ * Power management hook. Note that we won't be called from IRQ context, -+ * unlike the blank functions above, so we may sleep. -+ */ -+static int jzlcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct lcd_cfb_info *cfb = pm_dev->data; -+ -+ if (!cfb) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jzfb_suspend(); -+ break; -+ -+ case PM_RESUME: -+ ret = jzfb_resume(); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#else -+#define jzfb_suspend NULL -+#define jzfb_resume NULL -+#endif /* CONFIG_PM */ -+ -+/* The following routine is only for test */ -+ -+#ifdef DEBUG -+static void test_gpio(int gpio_num, int delay) { -+ __gpio_as_output(gpio_num); -+ while(1) { -+ __gpio_set_pin(gpio_num); -+ udelay(delay); -+ __gpio_clear_pin(gpio_num); -+ udelay(delay); -+ } -+} -+static void display_v_color_bar(int w, int h, int bpp) { -+ int i, j, wpl, data = 0; -+ int *ptr; -+ ptr = (int *)lcd_frame0; -+// ptr = (int *)lcd_frame1; -+ wpl = w*bpp/32; -+ if (!(bpp > 8)) -+ switch(bpp){ -+ case 1: -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i++) { -+ *ptr++ = 0x00ff00ff; -+ } -+ break; -+ case 2: -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i++) { -+ data = (i%4)*0x55555555; -+ *ptr++ = data; -+ } -+ break; -+ case 4: -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i++) { -+ data = (i%16)*0x11111111; -+ *ptr++ = data; -+ } -+ break; -+ case 8: -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i+=2) { -+ data = (i%(256))*0x01010101; -+ *ptr++ = data; -+ *ptr++ = data; -+ } -+ break; -+ } -+ else { -+ switch(bpp) { -+ case 16: -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i++) { -+ if((i/4)%8==0) -+ *ptr++ = 0xffffffff; -+ else if ((i/4)%8==1) -+ *ptr++ = 0xf800f800; -+ else if ((i/4)%8==2) -+ *ptr++ = 0xffe0ffe0; -+ else if ((i/4)%8==3) -+ *ptr++ = 0x07e007e0; -+ else if ((i/4)%8==4) -+ *ptr++ = 0x07ff07ff; -+ else if ((i/4)%8==5) -+ *ptr++ = 0x001f001f; -+ else if ((i/4)%8==6) -+ *ptr++ = 0xf81ff81f; -+ else if ((i/4)%8==7) -+ *ptr++ = 0x00000000; -+ } -+ break; -+ case 18: -+ case 24: -+ case 32: -+ default: -+#if 1 -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i++) { -+ if((i/8)%8==7) -+ *ptr++ = 0xffffff; -+ else if ((i/8)%8==1) -+ *ptr++ = 0xff0000; -+ else if ((i/8)%8==2) -+ *ptr++ = 0xffff00; -+ else if ((i/8)%8==3) -+ *ptr++ = 0x00ff00; -+ else if ((i/8)%8==4) -+ *ptr++ = 0x00ffff; -+ else if ((i/8)%8==5) -+ *ptr++ = 0x0000ff; -+ else if ((i/8)%8==6) -+ *ptr++ = 0xff00ff; -+ else if ((i/8)%8==0) -+ *ptr++ = 0x000000; -+ } -+#else -+ for (j = 0;j < h; j++) -+ for (i = 0;i < wpl; i++) { -+ if((i/8)%8==7) -+ *ptr++ = 0x00ff0000; -+ else if ((i/8)%8==1) -+ *ptr++ = 0xffff0000; -+ else if ((i/8)%8==2) -+ *ptr++ = 0x20ff0000; -+ else if ((i/8)%8==3) -+ *ptr++ = 0x40ff0000; -+ else if ((i/8)%8==4) -+ *ptr++ = 0x60ff0000; -+ else if ((i/8)%8==5) -+ *ptr++ = 0x80ff0000; -+ else if ((i/8)%8==6) -+ *ptr++ = 0xa0ff0000; -+ else if ((i/8)%8==0) -+ *ptr++ = 0xc0ff0000; -+ } -+#endif -+ break; -+ } -+ } -+} -+static void display_h_color_bar(int w, int h, int bpp) { -+ int i, data = 0; -+ int *ptr; -+ int wpl; //word_per_line -+ ptr = (int *)lcd_frame0; -+// ptr = (int *)lcd_frame1; -+ wpl = w*bpp/32; -+ if (!(bpp > 8)) -+ for (i = 0;i < wpl*h;i++) { -+ switch(bpp){ -+ case 1: -+ if(i%(wpl*8)==0) -+ data = ((i/(wpl*8))%2)*0xffffffff; -+ *ptr++ = data; -+ break; -+ case 2: -+ if(i%(wpl*8)==0) -+ data = ((i/(wpl*8))%4)*0x55555555; -+ *ptr++ = data; -+ break; -+ case 4: -+ if(i%(wpl*8)==0) -+ data = ((i/(wpl*8))%16)*0x11111111; -+ *ptr++ = data; -+ break; -+ case 8: -+ if(i%(wpl*8)==0) -+ data = ((i/(wpl*8))%256)*0x01010101; -+ *ptr++ = data; -+ break; -+ } -+ } -+ else { -+ -+ switch(bpp) { -+ case 15: -+ case 16: -+ for (i = 0;i < wpl*h;i++) { -+ if (((i/(wpl*8)) % 8) == 0) -+ *ptr++ = 0xffffffff; -+ else if (((i/(wpl*8)) % 8) == 1) -+ *ptr++ = 0xf800f800; -+ else if (((i/(wpl*8)) % 8) == 2) -+ *ptr++ = 0xffe0ffe0; -+ else if (((i/(wpl*8)) % 8) == 3) -+ *ptr++ = 0x07e007e0; -+ else if (((i/(wpl*8)) % 8) == 4) -+ *ptr++ = 0x07ff07ff; -+ else if (((i/(wpl*8)) % 8) == 5) -+ *ptr++ = 0x001f001f; -+ else if (((i/(wpl*8)) % 8) == 6) -+ *ptr++ = 0xf81ff81f; -+ else if (((i/(wpl*8)) % 8) == 7) -+ *ptr++ = 0x00000000; -+ } -+ break; -+ case 18: -+ case 24: -+ case 32: -+ default: -+ for (i = 0;i < wpl*h;i++) { -+ if (((i/(wpl*8)) % 8) == 7) -+ *ptr++ = 0xffffff; -+ else if (((i/(wpl*8)) % 8) == 2) -+ *ptr++ = 0xff0000; -+ else if (((i/(wpl*8)) % 8) == 4) -+ *ptr++ = 0xffff00; -+ else if (((i/(wpl*8)) % 8) == 6) -+ *ptr++ = 0x00ff00; -+ else if (((i/(wpl*8)) % 8) == 1) -+ *ptr++ = 0x00ffff; -+ else if (((i/(wpl*8)) % 8) == 3) -+ *ptr++ = 0x0000ff; -+ else if (((i/(wpl*8)) % 8) == 5) -+ *ptr++ = 0x000000; -+ else if (((i/(wpl*8)) % 8) == 0) -+ *ptr++ = 0xff00ff; -+ } -+ break; -+ } -+ -+ } -+ -+} -+#endif -+ -+static int __init jz4750fb_init(void) -+{ -+ struct lcd_cfb_info *cfb; -+ int err = 0; -+ -+ /* gpio init __gpio_as_lcd */ -+ if (jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_TFT_16BIT) -+ __gpio_as_lcd_16bit(); -+ else if (jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_TFT_24BIT) -+ __gpio_as_lcd_24bit(); -+ else -+ __gpio_as_lcd_18bit(); -+ /* In special mode, we only need init special pin, -+ * as general lcd pin has init in uboot */ -+#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+ switch (jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_MASK) { -+ case LCD_CFG_MODE_SPECIAL_TFT_1: -+ case LCD_CFG_MODE_SPECIAL_TFT_2: -+ case LCD_CFG_MODE_SPECIAL_TFT_3: -+ __gpio_as_lcd_special(); -+ break; -+ default: -+ ; -+ } -+#endif -+ if ( jz4750_lcd_info->osd.fg0.bpp > 16 && -+ jz4750_lcd_info->osd.fg0.bpp < 32 ) { -+ jz4750_lcd_info->osd.fg0.bpp = 32; -+ } -+ -+ switch ( jz4750_lcd_info->osd.fg1.bpp ) { -+ case 15: -+ case 16: -+ break; -+ case 17 ... 32: -+ jz4750_lcd_info->osd.fg1.bpp = 32; -+ break; -+ default: -+ printk("jz4750fb fg1 not support bpp(%d), force to 32bpp\n", -+ jz4750_lcd_info->osd.fg1.bpp); -+ jz4750_lcd_info->osd.fg1.bpp = 32; -+ } -+ __lcd_clr_dis(); -+ __lcd_clr_ena(); -+ -+ /* Configure SLCD module for setting smart lcd control registers */ -+#if defined(CONFIG_FB_JZ4750_SLCD) -+ __lcd_as_smart_lcd(); -+ __slcd_disable_dma(); -+ __init_slcd_bus(); /* Note: modify this depend on you lcd */ -+ -+#endif -+ /* init clk */ -+ jz4750fb_change_clock(jz4750_lcd_info); -+ __lcd_display_pin_init(); -+ __lcd_slcd_special_on(); -+ -+ cfb = jz4750fb_alloc_fb_info(); -+ if (!cfb) -+ goto failed; -+ -+ err = jz4750fb_map_smem(cfb); -+ if (err) -+ goto failed; -+ -+ jz4750fb_deep_set_mode( jz4750_lcd_info ); -+ -+ err = register_framebuffer(&cfb->fb); -+ if (err < 0) { -+ dprintk("jzfb_init(): register framebuffer err.\n"); -+ goto failed; -+ } -+ printk("fb%d: %s frame buffer device, using %dK of video memory\n", -+ cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); -+ -+ if (request_irq(IRQ_LCD, jz4750fb_interrupt_handler, IRQF_DISABLED, -+ "lcd", 0)) { -+ err = -EBUSY; -+ goto failed; -+ } -+ -+#ifdef CONFIG_PM -+ /* -+ * Note that the console registers this as well, but we want to -+ * power down the display prior to sleeping. -+ */ -+ cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzlcd_pm_callback); -+ if (cfb->pm) -+ cfb->pm->data = cfb; -+#endif -+ -+ __lcd_set_ena(); /* enalbe LCD Controller */ -+ __lcd_display_on(); -+ -+#ifdef DEBUG -+ display_h_color_bar(jz4750_lcd_info->osd.fg0.w, jz4750_lcd_info->osd.fg0.h, jz4750_lcd_info->osd.fg0.bpp); -+#endif -+ print_lcdc_registers(); -+ return 0; -+ -+failed: -+ print_dbg(); -+ jz4750fb_unmap_smem(cfb); -+ jz4750fb_free_fb_info(cfb); -+ -+ return err; -+} -+ -+#if 0 -+static int jzfb_remove(struct device *dev) -+{ -+ struct lcd_cfb_info *cfb = dev_get_drvdata(dev); -+ jzfb_unmap_smem(cfb); -+ jzfb_free_fb_info(cfb); -+ return 0; -+} -+#endif -+ -+#if 0 -+static struct device_driver jzfb_driver = { -+ .name = "jz-lcd", -+ .bus = &platform_bus_type, -+ .probe = jzfb_probe, -+ .remove = jzfb_remove, -+ .suspend = jzfb_suspend, -+ .resume = jzfb_resume, -+}; -+#endif -+ -+static void __exit jz4750fb_cleanup(void) -+{ -+ //driver_unregister(&jzfb_driver); -+ //jzfb_remove(); -+} -+ -+module_init(jz4750fb_init); -+module_exit(jz4750fb_cleanup); -diff --git a/drivers/video/jz4750_lcd.h b/drivers/video/jz4750_lcd.h -new file mode 100644 -index 0000000..2d07c43 ---- /dev/null -+++ b/drivers/video/jz4750_lcd.h -@@ -0,0 +1,785 @@ -+/* -+ * linux/drivers/video/jz4750_lcd.h -- Ingenic Jz4750 On-Chip LCD frame buffer device -+ * -+ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#ifndef __JZ4750_LCD_H__ -+#define __JZ4750_LCD_H__ -+ -+//#include -+ -+ -+#define NR_PALETTE 256 -+#define PALETTE_SIZE (NR_PALETTE*2) -+ -+/* use new descriptor(8 words) */ -+struct jz4750_lcd_dma_desc { -+ unsigned int next_desc; /* LCDDAx */ -+ unsigned int databuf; /* LCDSAx */ -+ unsigned int frame_id; /* LCDFIDx */ -+ unsigned int cmd; /* LCDCMDx */ -+ unsigned int offsize; /* Stride Offsize(in word) */ -+ unsigned int page_width; /* Stride Pagewidth(in word) */ -+ unsigned int cmd_num; /* Command Number(for SLCD) */ -+ unsigned int desc_size; /* Foreground Size */ -+}; -+ -+struct jz4750lcd_panel_t { -+ unsigned int cfg; /* panel mode and pin usage etc. */ -+ unsigned int slcd_cfg; /* Smart lcd configurations */ -+ unsigned int ctrl; /* lcd controll register */ -+ unsigned int w; /* Panel Width(in pixel) */ -+ unsigned int h; /* Panel Height(in line) */ -+ unsigned int fclk; /* frame clk */ -+ unsigned int hsw; /* hsync width, in pclk */ -+ unsigned int vsw; /* vsync width, in line count */ -+ unsigned int elw; /* end of line, in pclk */ -+ unsigned int blw; /* begin of line, in pclk */ -+ unsigned int efw; /* end of frame, in line count */ -+ unsigned int bfw; /* begin of frame, in line count */ -+}; -+ -+ -+struct jz4750lcd_fg_t { -+ int bpp; /* foreground bpp */ -+ int x; /* foreground start position x */ -+ int y; /* foreground start position y */ -+ int w; /* foreground width */ -+ int h; /* foreground height */ -+}; -+ -+struct jz4750lcd_osd_t { -+ unsigned int osd_cfg; /* OSDEN, ALHPAEN, F0EN, F1EN, etc */ -+ unsigned int osd_ctrl; /* IPUEN, OSDBPP, etc */ -+ unsigned int rgb_ctrl; /* RGB Dummy, RGB sequence, RGB to YUV */ -+ unsigned int bgcolor; /* background color(RGB888) */ -+ unsigned int colorkey0; /* foreground0's Colorkey enable, Colorkey value */ -+ unsigned int colorkey1; /* foreground1's Colorkey enable, Colorkey value */ -+ unsigned int alpha; /* ALPHAEN, alpha value */ -+ unsigned int ipu_restart; /* IPU Restart enable, ipu restart interval time */ -+ -+#define FG_NOCHANGE 0x0000 -+#define FG0_CHANGE_SIZE 0x0001 -+#define FG0_CHANGE_POSITION 0x0002 -+#define FG1_CHANGE_SIZE 0x0010 -+#define FG1_CHANGE_POSITION 0x0020 -+#define FG_CHANGE_ALL ( FG0_CHANGE_SIZE | FG0_CHANGE_POSITION | \ -+ FG1_CHANGE_SIZE | FG1_CHANGE_POSITION ) -+ int fg_change; -+ struct jz4750lcd_fg_t fg0; /* foreground 0 */ -+ struct jz4750lcd_fg_t fg1; /* foreground 1 */ -+}; -+ -+struct jz4750lcd_info { -+ struct jz4750lcd_panel_t panel; -+ struct jz4750lcd_osd_t osd; -+}; -+ -+ -+/* Jz LCDFB supported I/O controls. */ -+#define FBIOSETBACKLIGHT 0x4688 /* set back light level */ -+#define FBIODISPON 0x4689 /* display on */ -+#define FBIODISPOFF 0x468a /* display off */ -+#define FBIORESET 0x468b /* lcd reset */ -+#define FBIOPRINT_REG 0x468c /* print lcd registers(debug) */ -+#define FBIOROTATE 0x46a0 /* rotated fb */ -+#define FBIOGETBUFADDRS 0x46a1 /* get buffers addresses */ -+#define FBIO_GET_MODE 0x46a2 /* get lcd info */ -+#define FBIO_SET_MODE 0x46a3 /* set osd mode */ -+#define FBIO_DEEP_SET_MODE 0x46a4 /* set panel and osd mode */ -+#define FBIO_MODE_SWITCH 0x46a5 /* switch mode between LCD and TVE */ -+#define FBIO_GET_TVE_MODE 0x46a6 /* get tve info */ -+#define FBIO_SET_TVE_MODE 0x46a7 /* set tve mode */ -+ -+/* -+ * LCD panel specific definition -+ */ -+/* AUO */ -+#if defined(CONFIG_JZ4750_LCD_AUO_A043FL01V2) -+#if defined(CONFIG_JZ4750_APUS) /* board pavo */ -+ #define SPEN (32*3+29) /*LCD_CS*/ -+ #define SPCK (32*3+26) /*LCD_SCL*/ -+ #define SPDA (32*3+27) /*LCD_SDA*/ -+ #define LCD_RET (32*4+25) /*LCD_DISP_N use for lcd reset*/ -+#elif defined(CONFIG_JZ4750_FUWA) /* board pavo */ -+ #define SPEN (32*3+29) /*LCD_CS*/ -+ #define SPCK (32*3+26) /*LCD_SCL*/ -+ #define SPDA (32*3+27) /*LCD_SDA*/ -+ #define LCD_RET (32*5+2) /*LCD_DISP_N use for lcd reset*/ -+#elif defined(CONFIG_JZ4750D_CETUS) /* board pavo */ -+ #define SPEN (32*5+13) /*LCD_CS*/ -+ #define SPCK (32*5+10) /*LCD_SCL*/ -+ #define SPDA (32*5+11) /*LCD_SDA*/ -+ #define LCD_RET (32*4+18) /*LCD_DISP_N use for lcd reset*/ -+#else -+#error "driver/video/Jzlcd.h, please define SPI pins on your board." -+#endif -+ -+#define __spi_write_reg(reg, val) \ -+ do { \ -+ unsigned char no; \ -+ unsigned short value; \ -+ unsigned char a=0; \ -+ unsigned char b=0; \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ a=reg; \ -+ b=val; \ -+ __gpio_set_pin(SPEN); \ -+ __gpio_clear_pin(SPCK); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPDA); \ -+ __gpio_clear_pin(SPEN); \ -+ udelay(50); \ -+ value=((a<<8)|(b&0xFF)); \ -+ for(no=0;no<16;no++) \ -+ { \ -+ if((value&0x8000)==0x8000){ \ -+ __gpio_set_pin(SPDA);} \ -+ else{ \ -+ __gpio_clear_pin(SPDA); } \ -+ udelay(50); \ -+ __gpio_set_pin(SPCK); \ -+ value=(value<<1); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPCK); \ -+ } \ -+ __gpio_set_pin(SPEN); \ -+ udelay(400); \ -+ } while (0) -+#define __spi_read_reg(reg,val) \ -+ do{ \ -+ unsigned char no; \ -+ unsigned short value; \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ value = ((reg << 0) | (1 << 7)); \ -+ val = 0; \ -+ __gpio_as_output(SPDA); \ -+ __gpio_set_pin(SPEN); \ -+ __gpio_clear_pin(SPCK); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPDA); \ -+ __gpio_clear_pin(SPEN); \ -+ udelay(50); \ -+ for (no = 0; no < 16; no++ ) { \ -+ udelay(50); \ -+ if(no < 8) \ -+ { \ -+ if (value & 0x80) /* send data */ \ -+ __gpio_set_pin(SPDA); \ -+ else \ -+ __gpio_clear_pin(SPDA); \ -+ udelay(50); \ -+ __gpio_set_pin(SPCK); \ -+ value = (value << 1); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPCK); \ -+ if(no == 7) \ -+ __gpio_as_input(SPDA); \ -+ } \ -+ else \ -+ { \ -+ udelay(100); \ -+ __gpio_set_pin(SPCK); \ -+ udelay(50); \ -+ val = (val << 1); \ -+ val |= __gpio_get_pin(SPDA); \ -+ __gpio_clear_pin(SPCK); \ -+ } \ -+ } \ -+ __gpio_as_output(SPDA); \ -+ __gpio_set_pin(SPEN); \ -+ udelay(400); \ -+ } while(0) -+ -+#define __lcd_special_pin_init() \ -+ do { \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ __gpio_as_output(LCD_RET); \ -+ udelay(50); \ -+ __gpio_clear_pin(LCD_RET); \ -+ udelay(100); \ -+ __gpio_set_pin(LCD_RET); \ -+ } while (0) -+#define __lcd_special_on() \ -+ do { \ -+ udelay(50); \ -+ __gpio_clear_pin(LCD_RET); \ -+ udelay(100); \ -+ __gpio_set_pin(LCD_RET); \ -+} while (0) -+ -+ #define __lcd_special_off() \ -+ do { \ -+ __gpio_clear_pin(LCD_RET); \ -+ } while (0) -+ -+#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ -+ -+/* TRULY_TFTG320240DTSW */ -+#if defined(CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW_16BIT) || defined(CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW_18BIT) -+ -+#if defined(CONFIG_JZ4750_FUWA) -+#define LCD_RESET_PIN (32*3+25)// LCD_REV, GPD25 -+#else -+#error "Define LCD_RESET_PIN on your board" -+#endif -+ -+#define __lcd_special_on() \ -+do { \ -+ __gpio_as_output(32*3+30);\ -+ __gpio_clear_pin(32*3+30);\ -+ __gpio_as_output(LCD_RESET_PIN); \ -+ __gpio_set_pin(LCD_RESET_PIN); \ -+ udelay(100); \ -+ __gpio_clear_pin(LCD_RESET_PIN); \ -+ udelay(100); \ -+ __gpio_set_pin(LCD_RESET_PIN); \ -+} while (0) -+ -+#endif /* CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW */ -+ -+// Wolfgang 2008.02.23 -+#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA) || defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DUMMY) -+ -+#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA) -+#define PANEL_MODE 0x02 /* RGB Delta */ -+#elif defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DUMMY) -+#define PANEL_MODE 0x00 /* RGB Dummy */ -+#endif -+ -+#if defined(CONFIG_JZ4750_FUWA) /* board FuWa */ -+ #define SPEN (32*3+16) //LCD_D16 - GPD16 -+ #define SPCK (32*3+17) //LCD_D17 - GPD17 -+ #define SPDA (32*3+21) //LCD_DE - GPD21 -+ #define LCD_RET (32*3+25) //LCD_REV - GPD25 //use for lcd reset -+#else -+#error "please define SPI pins on your board." -+#endif -+ -+ #define __spi_write_reg1(reg, val) \ -+ do { \ -+ unsigned char no;\ -+ unsigned short value;\ -+ unsigned char a=0;\ -+ unsigned char b=0;\ -+ a=reg;\ -+ b=val;\ -+ __gpio_set_pin(SPEN);\ -+ udelay(100);\ -+ __gpio_clear_pin(SPCK);\ -+ __gpio_clear_pin(SPDA);\ -+ __gpio_clear_pin(SPEN);\ -+ udelay(25);\ -+ value=((a<<8)|(b&0xFF));\ -+ for(no=0;no<16;no++)\ -+ {\ -+ __gpio_clear_pin(SPCK);\ -+ if((value&0x8000)==0x8000)\ -+ __gpio_set_pin(SPDA);\ -+ else\ -+ __gpio_clear_pin(SPDA);\ -+ udelay(25);\ -+ __gpio_set_pin(SPCK);\ -+ value=(value<<1); \ -+ udelay(25);\ -+ }\ -+ __gpio_clear_pin(SPCK);\ -+ __gpio_set_pin(SPEN);\ -+ udelay(100);\ -+ } while (0) -+ -+ #define __spi_write_reg(reg, val) \ -+ do {\ -+ __spi_write_reg1((reg<<2), val); \ -+ udelay(100); \ -+ }while(0) -+ -+ #define __lcd_special_pin_init() \ -+ do { \ -+ __gpio_as_output(SPEN); /* use SPDA */\ -+ __gpio_as_output(SPCK); /* use SPCK */\ -+ __gpio_as_output(SPDA); /* use SPDA */\ -+ __gpio_as_output(SPDA); /* use reset */\ -+ __gpio_as_output(LCD_RET); /* use reset */\ -+ __gpio_set_pin(LCD_RET);\ -+ mdelay(15);\ -+ __gpio_clear_pin(LCD_RET);\ -+ mdelay(15);\ -+ __gpio_set_pin(LCD_RET);\ -+ } while (0) -+ -+ #define __lcd_special_on() \ -+ do { \ -+ mdelay(10); \ -+ __spi_write_reg(0x00, 0x10); \ -+ __spi_write_reg(0x01, 0xB1); \ -+ __spi_write_reg(0x00, 0x10); \ -+ __spi_write_reg(0x01, 0xB1); \ -+ __spi_write_reg(0x02, PANEL_MODE); /* RGBD MODE */ \ -+ __spi_write_reg(0x03, 0x01); /* Noninterlace*/ \ -+ mdelay(10); \ -+ } while (0) -+ -+ #define __lcd_special_off() \ -+ do { \ -+ } while (0) -+ -+#endif /* CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA */ -+ -+ -+#if defined(CONFIG_JZ4750_LCD_FOXCONN_PT035TN01) || defined(CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL) -+ -+#if defined(CONFIG_JZ4750_LCD_FOXCONN_PT035TN01) /* board FUWA */ -+#define MODE 0xcd /* 24bit parellel RGB */ -+#endif -+#if defined(CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL) -+#define MODE 0xc9 /* 8bit serial RGB */ -+#endif -+ -+#if defined(CONFIG_JZ4750_FUWA) /* board FuWa */ -+#if 0 -+ #define SPEN (32*5+7) //LCD_SPL GPF7 -+ #define SPCK (32*5+6) //LCD_CLS GPF6 -+ #define SPDA (32*5+5) //LCD_PS GPF5 -+ #define LCD_RET (32*5+4) //LCD_REV GPF4 //use for lcd reset -+#endif -+ #define SPEN (32*3+29) /*LCD_CS*/ -+ #define SPCK (32*3+26) /*LCD_SCL*/ -+ #define SPDA (32*3+27) /*LCD_SDA*/ -+ #define LCD_RET (32*4+25) /*LCD_DISP_N use for lcd reset*/ -+#elif defined(CONFIG_JZ4750D_FUWA1)/* board FuWa */ -+ #define SPEN (32*4+0) /*LCD_CS*/ -+ #define SPCK (32*4+9) /*LCD_SCL*/ -+ #define SPDA (32*4+1) /*LCD_SDA*/ -+ #define LCD_RET (32*4+3) /*LCD_DISP_N use for lcd reset*/ -+#else -+#error "driver/video/Jzlcd.h, please define SPI pins on your board." -+#endif -+ -+ #define __spi_write_reg1(reg, val) \ -+ do { \ -+ unsigned char no;\ -+ unsigned short value;\ -+ unsigned char a=0;\ -+ unsigned char b=0;\ -+ a=reg;\ -+ b=val;\ -+ __gpio_set_pin(SPEN);\ -+ __gpio_set_pin(SPCK);\ -+ __gpio_clear_pin(SPDA);\ -+ __gpio_clear_pin(SPEN);\ -+ udelay(25);\ -+ value=((a<<8)|(b&0xFF));\ -+ for(no=0;no<16;no++)\ -+ {\ -+ __gpio_clear_pin(SPCK);\ -+ if((value&0x8000)==0x8000)\ -+ __gpio_set_pin(SPDA);\ -+ else\ -+ __gpio_clear_pin(SPDA);\ -+ udelay(25);\ -+ __gpio_set_pin(SPCK);\ -+ value=(value<<1); \ -+ udelay(25);\ -+ }\ -+ __gpio_set_pin(SPEN);\ -+ udelay(100);\ -+ } while (0) -+ -+ #define __spi_write_reg(reg, val) \ -+ do {\ -+ __spi_write_reg1((reg<<2|2), val); \ -+ udelay(100); \ -+ }while(0) -+ -+ #define __lcd_special_pin_init() \ -+ do { \ -+ __gpio_as_output(SPEN); /* use SPDA */\ -+ __gpio_as_output(SPCK); /* use SPCK */\ -+ __gpio_as_output(SPDA); /* use SPDA */\ -+ __gpio_as_output(LCD_RET);\ -+ udelay(50);\ -+ __gpio_clear_pin(LCD_RET);\ -+ mdelay(150);\ -+ __gpio_set_pin(LCD_RET);\ -+ } while (0) -+ -+ #define __lcd_special_on() \ -+ do { \ -+ udelay(50);\ -+ __gpio_clear_pin(LCD_RET);\ -+ mdelay(150);\ -+ __gpio_set_pin(LCD_RET);\ -+ mdelay(10);\ -+ __spi_write_reg(0x00, 0x03); \ -+ __spi_write_reg(0x01, 0x40); \ -+ __spi_write_reg(0x02, 0x11); \ -+ __spi_write_reg(0x03, MODE); /* mode */ \ -+ __spi_write_reg(0x04, 0x32); \ -+ __spi_write_reg(0x05, 0x0e); \ -+ __spi_write_reg(0x07, 0x03); \ -+ __spi_write_reg(0x08, 0x08); \ -+ __spi_write_reg(0x09, 0x32); \ -+ __spi_write_reg(0x0A, 0x88); \ -+ __spi_write_reg(0x0B, 0xc6); \ -+ __spi_write_reg(0x0C, 0x20); \ -+ __spi_write_reg(0x0D, 0x20); \ -+ } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -+ -+/* __spi_write_reg(0x02, 0x03); \ -+ __spi_write_reg(0x06, 0x40); \ -+ __spi_write_reg(0x0a, 0x11); \ -+ __spi_write_reg(0x0e, 0xcd); \ -+ __spi_write_reg(0x12, 0x32); \ -+ __spi_write_reg(0x16, 0x0e); \ -+ __spi_write_reg(0x1e, 0x03); \ -+ __spi_write_reg(0x22, 0x08); \ -+ __spi_write_reg(0x26, 0x40); \ -+ __spi_write_reg(0x2a, 0x88); \ -+ __spi_write_reg(0x2e, 0x88); \ -+ __spi_write_reg(0x32, 0x20); \ -+ __spi_write_reg(0x36, 0x20); \ -+*/ -+// } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -+ -+ #define __lcd_special_off() \ -+ do { \ -+ __spi_write_reg(0x00, 0x03); \ -+ } while (0) -+ -+#endif /* CONFIG_JZ4750_LCD_FOXCONN_PT035TN01 or CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL */ -+ -+#if defined(CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W) -+static inline void CmdWrite(unsigned int cmd) -+{ -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); /* wait slcd ready */ -+ udelay(30); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -+} -+ -+static inline void DataWrite(unsigned int data) -+{ -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); /* wait slcd ready */ -+// udelay(30); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -+} -+ -+ -+static inline void delay(long delay_time) -+{ -+ long cnt; -+ -+// delay_time *= (384/8); -+ delay_time *= (43/8); -+ -+ for (cnt=0;cnt SETP 3 -+ CmdWrite(0x0000); -+ CmdWrite(0x01A0); -+ CmdWrite(0x3B01); -+ -+ CmdWrite(0x2809); -+ delay(1000); -+ CmdWrite(0x1900); -+ delay(1000); -+ CmdWrite(0x2110); -+ delay(1000); -+ CmdWrite(0x1805); -+ delay(1000); -+ CmdWrite(0x1E01); -+ delay(1000); -+ CmdWrite(0x1847); -+ delay(1000); -+ CmdWrite(0x1867); -+ delay(1000); -+ CmdWrite(0x18F7); -+ delay(1000); -+ CmdWrite(0x2100); -+ delay(1000); -+ CmdWrite(0x2809); -+ delay(1000); -+ CmdWrite(0x1A05); -+ delay(1000); -+ CmdWrite(0x19E8); -+ delay(1000); -+ CmdWrite(0x1F64); -+ delay(1000); -+ CmdWrite(0x2045); -+ delay(1000); -+ CmdWrite(0x1E81); -+ delay(1000); -+ CmdWrite(0x1B09); -+ delay(1000); -+ CmdWrite(0x0020); -+ delay(1000); -+ CmdWrite(0x0120); -+ delay(1000); -+ -+ CmdWrite(0x3B01); -+ delay(1000); -+ -+ /* Set Window(239,319), Set Cursor(239,319) */ -+ CmdWrite(0x0510); -+ CmdWrite(0x01C0); -+ CmdWrite(0x4500); -+ CmdWrite(0x46EF); -+ CmdWrite(0x4800); -+ CmdWrite(0x4700); -+ CmdWrite(0x4A3F); -+ CmdWrite(0x4901); -+ CmdWrite(0x42EF); -+ CmdWrite(0x443F); -+ CmdWrite(0x4301); -+ -+} -+ -+#if defined(CONFIG_JZ4750_FUWA) -+//#define PIN_CS_N (32*2+xx) /* a low voltage */ -+#define PIN_RD_N (32*3+21) /* LCD_DE: GP D21, a high voltage */ -+#define PIN_RESET_N (32*3+25) /* LCD_REV GP D25 */ -+#else -+#error "Define special lcd pins for your platform." -+#endif -+ -+#define __lcd_slcd_pin_init() \ -+ do { \ -+ __gpio_as_output(PIN_RD_N); /* RD#: LCD_REV */ \ -+ __gpio_as_output(PIN_RESET_N); /* RESET#: LCD_SPL */ \ -+ __gpio_set_pin(PIN_RD_N); /*set read signal high */ \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(100); \ -+ __gpio_clear_pin(PIN_RESET_N); \ -+ mdelay(100); \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ /* Configure SLCD module */ \ -+ REG_LCD_CTRL &= ~(LCD_CTRL_ENA|LCD_CTRL_DIS); /* disable lcdc */ \ -+ REG_LCD_CFG = LCD_CFG_LCDPIN_SLCD | 0x0D; /* LCM */ \ -+ REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; /* disable slcd dma */ \ -+ REG_SLCD_CFG = SLCD_CFG_DWIDTH_16BIT | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING | SLCD_CFG_TYPE_PARALLEL; \ -+ REG_LCD_REV = 0x04; /* lcd clock??? */ \ -+ printk("Fuwa test, pixclk divide REG_LCD_REV=0x%08x\n", REG_LCD_REV); \ -+}while (0) -+ -+#define __lcd_slcd_special_on() \ -+ do { \ -+ __lcd_slcd_pin_init(); \ -+ SlcdInit(); \ -+ REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; /* slcdc dma enable */ \ -+ } while (0) -+ -+#endif /* #if CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W */ -+ -+#ifndef __lcd_special_pin_init -+#define __lcd_special_pin_init() -+#endif -+#ifndef __lcd_special_on -+#define __lcd_special_on() -+#endif -+#ifndef __lcd_special_off -+#define __lcd_special_off() -+#endif -+ -+ -+/* -+ * Platform specific definition -+ */ -+#if defined(CONFIG_JZ4750D_VGA_DISPLAY) -+#define __lcd_display_pin_init() -+#define __lcd_display_on() -+#define __lcd_display_off() -+#elif defined(CONFIG_JZ4750_APUS)/* board apus */ -+#define __lcd_display_pin_init() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_VCC_EN_N); \ -+ __lcd_special_pin_init(); \ -+} while (0) -+#define __lcd_display_on() \ -+do { \ -+ __gpio_clear_pin(GPIO_LCD_VCC_EN_N); \ -+ __lcd_special_on(); \ -+ __lcd_set_backlight_level(80); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_close_backlight(); \ -+ __lcd_special_off(); \ -+} while (0) -+#elif defined(CONFIG_JZ4750D_CETUS)/* board apus */ -+#define __lcd_display_pin_init() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_VCC_EN_N); \ -+ __lcd_special_pin_init(); \ -+} while (0) -+#define __lcd_display_on() \ -+do { \ -+ __gpio_set_pin(GPIO_LCD_VCC_EN_N); \ -+ __lcd_special_on(); \ -+ __lcd_set_backlight_level(80); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_close_backlight(); \ -+ __lcd_special_off(); \ -+} while (0) -+ -+#else /* other boards */ -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __lcd_special_pin_init(); \ -+} while (0) -+#define __lcd_display_on() \ -+do { \ -+ __lcd_special_on(); \ -+ __lcd_set_backlight_level(80); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_close_backlight(); \ -+ __lcd_special_off(); \ -+} while (0) -+#endif /* APUS */ -+ -+ -+/***************************************************************************** -+ * LCD display pin dummy macros -+ *****************************************************************************/ -+ -+#ifndef __lcd_display_pin_init -+#define __lcd_display_pin_init() -+#endif -+#ifndef __lcd_slcd_special_on -+#define __lcd_slcd_special_on() -+#endif -+#ifndef __lcd_display_on -+#define __lcd_display_on() -+#endif -+#ifndef __lcd_display_off -+#define __lcd_display_off() -+#endif -+#ifndef __lcd_set_backlight_level -+#define __lcd_set_backlight_level(n) -+#endif -+ -+#endif /* __JZ4750_LCD_H__ */ -diff --git a/drivers/video/jz4750_tve.c b/drivers/video/jz4750_tve.c -new file mode 100644 -index 0000000..3a4ea61 ---- /dev/null -+++ b/drivers/video/jz4750_tve.c -@@ -0,0 +1,104 @@ -+ -+/* -+ * linux/drivers/video/jz4750_tve.c -- Ingenic Jz4750 TVE Controller operation -+ * interface. -+ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -+ * Author: Wolfgang Wang, -+ * -+ * 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 -+#include "jz4750_tve.h" -+ -+struct jz4750tve_info jz4750_tve_info_PAL = { -+ .ctrl = (4 << TVE_CTRL_YCDLY_BIT) | TVE_CTRL_SYNCT | TVE_CTRL_PAL | TVE_CTRL_SWRST, /* PAL, SVIDEO */ -+ .frcfg = (23 << TVE_FRCFG_L1ST_BIT) | (625 << TVE_FRCFG_NLINE_BIT), -+ .slcfg1 = (800<ctrl = (jz4750_tve_info->ctrl | TVE_CTRL_DAPD) & ( ~( TVE_CTRL_DAPD1 | TVE_CTRL_DAPD2)); -+ jz4750_tve_info->ctrl &= ~TVE_CTRL_SWRST; -+ REG_TVE_CTRL = jz4750_tve_info->ctrl; -+} -+ -+/* turn off TVE, turn off DACn... */ -+void jz4750tve_disable_tve(void) -+{ -+ jz4750_tve_info->ctrl &= ~TVE_CTRL_DAPD;/* DACn disabled??? */ -+ jz4750_tve_info->ctrl |= TVE_CTRL_SWRST;/* DACn disabled??? */ -+ REG_TVE_CTRL = jz4750_tve_info->ctrl; -+} -+ -+void jz4750tve_set_tve_mode( struct jz4750tve_info *tve ) -+{ -+ REG_TVE_CTRL = tve->ctrl; -+ REG_TVE_FRCFG = tve->frcfg; -+ REG_TVE_SLCFG1 = tve->slcfg1; -+ REG_TVE_SLCFG2 = tve->slcfg2; -+ REG_TVE_SLCFG3 = tve->slcfg3; -+ REG_TVE_LTCFG1 = tve->ltcfg1; -+ REG_TVE_LTCFG2 = tve->ltcfg2; -+ REG_TVE_CFREQ = tve->cfreq; -+ REG_TVE_CPHASE = tve->cphase; -+ REG_TVE_CBCRCFG = tve->cbcrcfg; -+ REG_TVE_WSSCR = tve->wsscr; -+ REG_TVE_WSSCFG1 = tve->wsscfg1; -+ REG_TVE_WSSCFG2 = tve->wsscfg2; -+ REG_TVE_WSSCFG3 = tve->wsscfg3; -+} -+ -+void jz4750tve_init( int tve_mode ) -+{ -+ switch ( tve_mode ) { -+ case PANEL_MODE_TVE_PAL: -+ jz4750_tve_info = &jz4750_tve_info_PAL; -+ break; -+ case PANEL_MODE_TVE_NTSC: -+ jz4750_tve_info = &jz4750_tve_info_NTSC; -+ break; -+ } -+ -+ jz4750tve_set_tve_mode( jz4750_tve_info ); -+// jz4750tve_enable_tve(); -+} -diff --git a/drivers/video/jz4750_tve.h b/drivers/video/jz4750_tve.h -new file mode 100644 -index 0000000..00eefe9 ---- /dev/null -+++ b/drivers/video/jz4750_tve.h -@@ -0,0 +1,45 @@ -+#ifndef __JZ4750_TVE_H__ -+#define __JZ4750_TVE_H__ -+ -+ -+#define PANEL_MODE_LCD_PANEL 0 -+#define PANEL_MODE_TVE_PAL 1 -+#define PANEL_MODE_TVE_NTSC 2 -+ -+/* TV parameter */ -+#define TVE_WIDTH_PAL 720 -+#define TVE_HEIGHT_PAL 573 -+#define TVE_FREQ_PAL 50 -+#define TVE_WIDTH_NTSC 720 -+#define TVE_HEIGHT_NTSC 482 -+#define TVE_FREQ_NTSC 60 -+ -+ -+/* Structure for TVE */ -+struct jz4750tve_info { -+ unsigned int ctrl; -+ unsigned int frcfg; -+ unsigned int slcfg1; -+ unsigned int slcfg2; -+ unsigned int slcfg3; -+ unsigned int ltcfg1; -+ unsigned int ltcfg2; -+ unsigned int cfreq; -+ unsigned int cphase; -+ unsigned int cbcrcfg; -+ unsigned int wsscr; -+ unsigned int wsscfg1; -+ unsigned int wsscfg2; -+ unsigned int wsscfg3; -+}; -+ -+extern struct jz4750tve_info *jz4750_tve_info; -+ -+extern void jz4750tve_enable_tve(void); -+extern void jz4750tve_disable_tve(void); -+ -+extern void jz4750tve_set_tve_mode( struct jz4750tve_info *tve ); -+extern void jz4750tve_init( int tve_mode ); -+ -+ -+#endif /* __JZ4750_TVE_H__ */ -diff --git a/drivers/video/jz_kgm_spfd5420a.h b/drivers/video/jz_kgm_spfd5420a.h -new file mode 100644 -index 0000000..33d8bd5 ---- /dev/null -+++ b/drivers/video/jz_kgm_spfd5420a.h -@@ -0,0 +1,385 @@ -+/* Set registers of smart lcd acording to the following routines -+ * Note: BUS width and CMD width and register value width -+ * This example: BUS is 8, 9, 16 or 18-bit; CMD and DATA is 16-bit -+ * Configure SLCD module to initialize smart lcd registers -+ -+ switch (bus) { -+ case 8: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -+ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_8bit(); -+ break; -+ case 9: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -+ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_9bit(); -+ break; -+ case 16: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_16 -+ | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_16bit(); -+ break; -+ case 18: -+ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_18 -+ | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW -+ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -+ | SLCD_CFG_TYPE_PARALLEL; -+ __gpio_as_slcd_18bit(); -+ break; -+ } -+ -+ static void Mcupanel_RegSet(unsigned int cmd, unsigned int data) -+ { -+ switch (bus) { -+ case 8: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -+ break; -+ case 9: -+ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -+ data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -+ break; -+ case 16: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -+ break; -+ case 18: -+ cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); -+ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); -+ break; -+ default: -+ printk("Don't support %d bit Bus\n", jzfb.bus ); -+ break; -+ } -+ } -+ -+ static void Mcupanel_Command(unsigned int cmd) { -+ switch (bus) { -+ case 8: -+ case 9: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -+ break; -+ case 16: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -+ break; -+ case 18: -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); -+ break; -+ default: -+ printk("Don't support %d bit Bus\n", jzfb.bus ); -+ break; -+ } -+ } -+ -+ *Display---------------------------------------- -+ Note: BUS and BPP, send data to gram data register to display -+ BUS: 8, 9, 16 or 18-bit; BPP: 8, 16, 18-bit -+ switch (bus) { -+ case 8: -+ switch (bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15: -+ case 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ case 9: -+ switch (bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15 ... 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_9_x2; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ case 16: -+ switch (bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15 ... 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ case 18: -+ switch (bpp) { -+ case 8: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -+ break; -+ case 15: -+ case 16: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -+ break; -+ case 17 ... 32: -+ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -+ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_18; -+ break; -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ break; -+ } -+ break; -+ default: -+ printk("Error: The BUS %d is not supported\n", jzfb.bus); -+ break; -+ } -+ dprintk("SLCD_CFG=0x%x\n", REG_SLCD_CFG); -+} -+ ************************************************************************************************/ -+ -+#ifndef __JZ_KGM_SPF5420A_H__ -+#define __JZ_KGM_SPF5420A_H__ -+ -+#include -+ -+#if defined(CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A) -+#define WR_GRAM_CMD 0x0202 -+ -+#if defined(CONFIG_JZ4750_FUWA) -+#define PIN_CS_N (32*3+24) // Chip select //GPD24; -+#define PIN_RESET_N (32*5+6) /* LCD_REV GPF6 */ -+#elif defined(CONFIG_JZ4750D_FUWA1) -+#define PIN_CS_N (32*3+24) // Chip select //GPD24; -+#define PIN_RESET_N (32*4+3) /* LCD_REV GPF6 */ -+#else -+#error "Define special lcd pins for your platform." -+#endif -+ -+/* Sent a command with data (18-bit bus, 16-bit index, 16-bit register value) */ -+static void Mcupanel_RegSet(unsigned int cmd, unsigned int data) -+{ -+ cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); -+ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -+ data = ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -+} -+ -+/* Sent a command without data (18-bit bus, 16-bit index) */ -+static void Mcupanel_Command(unsigned int cmd) { -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -+ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); -+} -+ -+/* Set the start address of screen, for example (0, 0) */ -+void Mcupanel_SetAddr(u32 x, u32 y) //u32 -+{ -+ Mcupanel_RegSet(0x200,x) ; -+ udelay(1); -+ Mcupanel_RegSet(0x201,y) ; -+ udelay(1); -+ Mcupanel_Command(0x202); -+ -+} -+ -+#undef __lcd_special_pin_init -+#define __lcd_special_pin_init() \ -+do { \ -+ __gpio_as_output(PIN_CS_N); \ -+ __gpio_as_output(PIN_RESET_N); \ -+ __gpio_clear_pin(PIN_CS_N); /* Clear CS */ \ -+ mdelay(100); \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_clear_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(100); \ -+} while(0) -+ -+ -+#define GAMMA() \ -+do { \ -+ Mcupanel_RegSet(0x0300,0x0101); \ -+ Mcupanel_RegSet(0x0301,0x0b27); \ -+ Mcupanel_RegSet(0x0302,0x132a); \ -+ Mcupanel_RegSet(0x0303,0x2a13); \ -+ Mcupanel_RegSet(0x0304,0x270b); \ -+ Mcupanel_RegSet(0x0305,0x0101); \ -+ Mcupanel_RegSet(0x0306,0x1205); \ -+ Mcupanel_RegSet(0x0307,0x0512); \ -+ Mcupanel_RegSet(0x0308,0x0005); \ -+ Mcupanel_RegSet(0x0309,0x0003); \ -+ Mcupanel_RegSet(0x030a,0x0f04); \ -+ Mcupanel_RegSet(0x030b,0x0f00); \ -+ Mcupanel_RegSet(0x030c,0x000f); \ -+ Mcupanel_RegSet(0x030d,0x040f); \ -+ Mcupanel_RegSet(0x030e,0x0300); \ -+ Mcupanel_RegSet(0x030f,0x0500); \ -+ /*** secorrect gamma2 ***/ \ -+ Mcupanel_RegSet(0x0400,0x3500); \ -+ Mcupanel_RegSet(0x0401,0x0001); \ -+ Mcupanel_RegSet(0x0404,0x0000); \ -+ Mcupanel_RegSet(0x0500,0x0000); \ -+ Mcupanel_RegSet(0x0501,0x0000); \ -+ Mcupanel_RegSet(0x0502,0x0000); \ -+ Mcupanel_RegSet(0x0503,0x0000); \ -+ Mcupanel_RegSet(0x0504,0x0000); \ -+ Mcupanel_RegSet(0x0505,0x0000); \ -+ Mcupanel_RegSet(0x0600,0x0000); \ -+ Mcupanel_RegSet(0x0606,0x0000); \ -+ Mcupanel_RegSet(0x06f0,0x0000); \ -+ Mcupanel_RegSet(0x07f0,0x5420); \ -+ Mcupanel_RegSet(0x07f3,0x288a); \ -+ Mcupanel_RegSet(0x07f4,0x0022); \ -+ Mcupanel_RegSet(0x07f5,0x0001); \ -+ Mcupanel_RegSet(0x07f0,0x0000); \ -+} while(0) -+ -+#define SlcdInit() \ -+do { \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_clear_pin(PIN_RESET_N); \ -+ mdelay(10); \ -+ __gpio_set_pin(PIN_RESET_N); \ -+ mdelay(100); \ -+ Mcupanel_RegSet(0x0600, 0x0001); /*soft reset*/ \ -+ mdelay(10); \ -+ Mcupanel_RegSet(0x0600, 0x0000); /*soft reset*/ \ -+ mdelay(10); \ -+ Mcupanel_RegSet(0x0606,0x0000); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0007,0x0001); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0110,0x0001); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0100,0x17b0); \ -+ Mcupanel_RegSet(0x0101,0x0147); \ -+ Mcupanel_RegSet(0x0102,0x019d); \ -+ Mcupanel_RegSet(0x0103,0x8600); \ -+ Mcupanel_RegSet(0x0281,0x0010); \ -+ udelay(10); \ -+ Mcupanel_RegSet(0x0102,0x01bd); \ -+ udelay(10); \ -+ /************initial************/\ -+ Mcupanel_RegSet(0x0000,0x0000); \ -+ Mcupanel_RegSet(0x0001,0x0000); \ -+ Mcupanel_RegSet(0x0002,0x0400); \ -+ Mcupanel_RegSet(0x0003,0x12b8); /*up:0x1288 down:0x12B8 left:0x1290 right:0x12A0*/ \ -+ Mcupanel_RegSet(0x0006,0x0000); \ -+ Mcupanel_RegSet(0x0008,0x0503); \ -+ Mcupanel_RegSet(0x0009,0x0001); \ -+ Mcupanel_RegSet(0x000b,0x0010); \ -+ Mcupanel_RegSet(0x000c,0x0000); \ -+ Mcupanel_RegSet(0x000f,0x0000); \ -+ Mcupanel_RegSet(0x0007,0x0001); \ -+ Mcupanel_RegSet(0x0010,0x0010); \ -+ Mcupanel_RegSet(0x0011,0x0202); \ -+ Mcupanel_RegSet(0x0012,0x0300); \ -+ Mcupanel_RegSet(0x0020,0x021e); \ -+ Mcupanel_RegSet(0x0021,0x0202); \ -+ Mcupanel_RegSet(0x0022,0x0100); \ -+ Mcupanel_RegSet(0x0090,0x0000); \ -+ Mcupanel_RegSet(0x0092,0x0000); \ -+ Mcupanel_RegSet(0x0100,0x16b0); \ -+ Mcupanel_RegSet(0x0101,0x0147); \ -+ Mcupanel_RegSet(0x0102,0x01bd); \ -+ Mcupanel_RegSet(0x0103,0x2c00); \ -+ Mcupanel_RegSet(0x0107,0x0000); \ -+ Mcupanel_RegSet(0x0110,0x0001); \ -+ Mcupanel_RegSet(0x0210,0x0000); \ -+ Mcupanel_RegSet(0x0211,0x00ef); \ -+ Mcupanel_RegSet(0x0212,0x0000); \ -+ Mcupanel_RegSet(0x0213,0x018f); \ -+ Mcupanel_RegSet(0x0280,0x0000); \ -+ Mcupanel_RegSet(0x0281,0x0001); \ -+ Mcupanel_RegSet(0x0282,0x0000); \ -+ GAMMA(); \ -+ Mcupanel_RegSet(0x0007,0x0173); \ -+ Mcupanel_Command(0x0202); /*Write Data to GRAM */ \ -+ udelay(10);\ -+ Mcupanel_SetAddr(0,0);\ -+ udelay(100);\ -+} while(0) -+ -+/*---- LCD Initial ----*/ -+#undef __lcd_slcd_pin_init -+#define __lcd_slcd_pin_init() \ -+ do { \ -+ __lcd_special_pin_init(); \ -+}while (0) -+ -+#undef __lcd_slcd_special_on -+#define __lcd_slcd_special_on() \ -+ do { \ -+ __lcd_slcd_pin_init(); \ -+ SlcdInit(); \ -+ REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; /* slcdc dma enable */ \ -+ } while (0) -+ -+#define __init_slcd_bus()\ -+do{\ -+ __slcd_set_data_18bit();\ -+ __slcd_set_cmd_18bit();\ -+ __slcd_set_cs_low();\ -+ __slcd_set_rs_low();\ -+ __slcd_set_clk_falling();\ -+ __slcd_set_parallel_type();\ -+}while(0) -+#endif /* #if CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A */ -+ -+#endif /* __JZ_KGM_SPF5420A_H__ */ -diff --git a/drivers/video/jz_toppoly_td043mgeb1.h b/drivers/video/jz_toppoly_td043mgeb1.h -new file mode 100644 -index 0000000..c66494e ---- /dev/null -+++ b/drivers/video/jz_toppoly_td043mgeb1.h -@@ -0,0 +1,264 @@ -+ -+#ifndef __JZ_KGM_TOPPOLY_TD043MGEB1_H__ -+#define __JZ_KGM_TOPPOLY_TD043MGEB1_H__ -+ -+#include -+ -+#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD043MGEB1) -+#if defined(CONFIG_JZ4750_APUS) /* board FuWa */ -+ #define SPEN (32*3+29) /*LCD_CS*/ -+ #define SPCK (32*3+26) /*LCD_SCL*/ -+ #define SPDA (32*3+27) /*LCD_SDA*/ -+ #define LCD_RET (32*4+23) /*LCD_DISP_N use for lcd reset*/ -+ #define LCD_STBY (32*4+25) /*LCD_STBY, use for lcd standby*/ -+#else -+#error "driver/video/Jzlcd.h, please define SPI pins on your board." -+#endif -+ -+#define __spi_write_reg(reg, val) \ -+ do { \ -+ unsigned char no; \ -+ unsigned short value; \ -+ unsigned char a=0; \ -+ unsigned char b=0; \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ a=reg; \ -+ b=val; \ -+ __gpio_set_pin(SPEN); \ -+ __gpio_clear_pin(SPCK); \ -+ udelay(500); \ -+ __gpio_clear_pin(SPDA); \ -+ __gpio_clear_pin(SPEN); \ -+ udelay(500); \ -+ value=((a<<8)|(b&0xFF)); \ -+ for(no=0;no<16;no++) \ -+ { \ -+ if((value&0x8000)==0x8000){ \ -+ __gpio_set_pin(SPDA);} \ -+ else{ \ -+ __gpio_clear_pin(SPDA); } \ -+ udelay(500); \ -+ __gpio_set_pin(SPCK); \ -+ value=(value<<1); \ -+ udelay(500); \ -+ __gpio_clear_pin(SPCK); \ -+ } \ -+ __gpio_set_pin(SPEN); \ -+ udelay(4000); \ -+ } while (0) -+#define __spi_read_reg(reg,val) \ -+ do{ \ -+ unsigned char no; \ -+ unsigned short value; \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ value = ((reg << 0) | (1 << 7)); \ -+ val = 0; \ -+ __gpio_as_output(SPDA); \ -+ __gpio_set_pin(SPEN); \ -+ __gpio_clear_pin(SPCK); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPDA); \ -+ __gpio_clear_pin(SPEN); \ -+ udelay(50); \ -+ for (no = 0; no < 16; no++ ) { \ -+ udelay(50); \ -+ if(no < 8) \ -+ { \ -+ if (value & 0x80) /* send data */ \ -+ __gpio_set_pin(SPDA); \ -+ else \ -+ __gpio_clear_pin(SPDA); \ -+ udelay(50); \ -+ __gpio_set_pin(SPCK); \ -+ value = (value << 1); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPCK); \ -+ if(no == 7) \ -+ __gpio_as_input(SPDA); \ -+ } \ -+ else \ -+ { \ -+ udelay(100); \ -+ __gpio_set_pin(SPCK); \ -+ udelay(50); \ -+ val = (val << 1); \ -+ val |= __gpio_get_pin(SPDA); \ -+ __gpio_clear_pin(SPCK); \ -+ } \ -+ } \ -+ __gpio_as_output(SPDA); \ -+ __gpio_set_pin(SPEN); \ -+ udelay(400); \ -+ } while(0) -+ -+#define __lcd_special_pin_init() \ -+ do { \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ __gpio_as_output(LCD_STBY); \ -+ __gpio_as_output(LCD_RET); \ -+ udelay(500); \ -+ __gpio_clear_pin(LCD_RET); \ -+ udelay(1000); \ -+ __gpio_set_pin(LCD_RET); \ -+ udelay(1000); \ -+ __gpio_set_pin(LCD_STBY); \ -+ udelay(1000); \ -+ } while (0) -+#define __lcd_special_on() \ -+ do { \ -+} while (0) -+ -+ #define __lcd_special_off() \ -+ do { \ -+ __gpio_clear_pin(LCD_RET); \ -+ } while (0) -+ -+#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ -+ -+#endif /* __JZ_KGM_TOPPOLY_TD043MGEB1_H__ */ -+/* 2.2 -+ __spi_write_reg(0x02, 0x07 ); \ -+ __spi_write_reg(0x03, 0x5f); \ -+ __spi_write_reg(0x04, 0x17); \ -+ __spi_write_reg(0x05, 0x20); \ -+ __spi_write_reg(0x06, 0x08); \ -+ __spi_write_reg(0x07, 0x26); \ -+ __spi_write_reg(0x08, 0x13); \ -+ __spi_write_reg(0x09, 0x33); \ -+ __spi_write_reg(0x0a, 0x20); \ -+ __spi_write_reg(0x0b, 0x20); \ -+ __spi_write_reg(0x0c, 0x20); \ -+ __spi_write_reg(0x0d, 0x20); \ -+ __spi_write_reg(0x0e, 0x10); \ -+ __spi_write_reg(0x0f, 0x10); \ -+ __spi_write_reg(0x10, 0x10); \ -+ __spi_write_reg(0x11, 0x15); \ -+ __spi_write_reg(0x12, 0xaa); \ -+ __spi_write_reg(0x13, 0xff); \ -+ __spi_write_reg(0x14, 0x86); \ -+ __spi_write_reg(0x15, 0x8e); \ -+ __spi_write_reg(0x16, 0xd6); \ -+ __spi_write_reg(0x17, 0xfe); \ -+ __spi_write_reg(0x18, 0x28); \ -+ __spi_write_reg(0x19, 0x52); \ -+ __spi_write_reg(0x1a, 0x7c); \ -+ __spi_write_reg(0x1b, 0xe9); \ -+ __spi_write_reg(0x1c, 0x42); \ -+ __spi_write_reg(0x1d, 0x88); \ -+ __spi_write_reg(0x1e, 0xb8); \ -+ __spi_write_reg(0x1f, 0xff); \ -+ __spi_write_reg(0x20, 0xf0); \ -+ __spi_write_reg(0x21, 0xf0); \ -+ __spi_write_reg(0x22, 0x07); \ -+*/ -+/* 3.1 -+ __spi_write_reg(0x02, 0x07); \ -+ __spi_write_reg(0x03, 0x5f); \ -+ __spi_write_reg(0x04, 0x17); \ -+ __spi_write_reg(0x05, 0x20); \ -+ __spi_write_reg(0x06, 0x08); \ -+ __spi_write_reg(0x07, 0x20); \ -+ __spi_write_reg(0x08, 0x20); \ -+ __spi_write_reg(0x09, 0x20); \ -+ __spi_write_reg(0x0a, 0x20); \ -+ __spi_write_reg(0x0b, 0x20); \ -+ __spi_write_reg(0x0c, 0x20); \ -+ __spi_write_reg(0x0d, 0x22); \ -+ __spi_write_reg(0x0e, 0x10); \ -+ __spi_write_reg(0x0f, 0x10); \ -+ __spi_write_reg(0x10, 0x10); \ -+ __spi_write_reg(0x11, 0x15); \ -+ __spi_write_reg(0x12, 0x6a); \ -+ __spi_write_reg(0x13, 0xff); \ -+ __spi_write_reg(0x14, 0x86); \ -+ __spi_write_reg(0x15, 0x7c); \ -+ __spi_write_reg(0x16, 0xc2); \ -+ __spi_write_reg(0x17, 0xd1); \ -+ __spi_write_reg(0x18, 0xf5); \ -+ __spi_write_reg(0x19, 0x25); \ -+ __spi_write_reg(0x1a, 0x4a); \ -+ __spi_write_reg(0x1b, 0xbf); \ -+ __spi_write_reg(0x1c, 0x15); \ -+ __spi_write_reg(0x1d, 0x6a); \ -+ __spi_write_reg(0x1e, 0xa4); \ -+ __spi_write_reg(0x1f, 0xff); \ -+ __spi_write_reg(0x20, 0xf0); \ -+ __spi_write_reg(0x21, 0xf0); \ -+ __spi_write_reg(0x22, 0x08); \ -+ */ -+ /* 2.5 -+ __spi_write_reg(0x02, 0x07); \ -+ __spi_write_reg(0x03, 0x5f); \ -+ __spi_write_reg(0x04, 0x17); \ -+ __spi_write_reg(0x05, 0x20); \ -+ __spi_write_reg(0x06, 0x08); \ -+ __spi_write_reg(0x07, 0x20); \ -+ __spi_write_reg(0x08, 0x20); \ -+ __spi_write_reg(0x09, 0x20); \ -+ __spi_write_reg(0x0a, 0x20); \ -+ __spi_write_reg(0x0b, 0x20); \ -+ __spi_write_reg(0x0c, 0x20); \ -+ __spi_write_reg(0x0d, 0x22); \ -+ __spi_write_reg(0x0e, 0x10); \ -+ __spi_write_reg(0x0f, 0x10); \ -+ __spi_write_reg(0x10, 0x10); \ -+ __spi_write_reg(0x11, 0x15); \ -+ __spi_write_reg(0x12, 0xaa); \ -+ __spi_write_reg(0x13, 0xff); \ -+ __spi_write_reg(0x14, 0x86); \ -+ __spi_write_reg(0x15, 0x89); \ -+ __spi_write_reg(0x16, 0xc6); \ -+ __spi_write_reg(0x17, 0xea); \ -+ __spi_write_reg(0x18, 0x0c); \ -+ __spi_write_reg(0x19, 0x33); \ -+ __spi_write_reg(0x1a, 0x5e); \ -+ __spi_write_reg(0x1b, 0xd0); \ -+ __spi_write_reg(0x1c, 0x33); \ -+ __spi_write_reg(0x1d, 0x7e); \ -+ __spi_write_reg(0x1e, 0xb3); \ -+ __spi_write_reg(0x1f, 0xff); \ -+ __spi_write_reg(0x20, 0xf0); \ -+ __spi_write_reg(0x21, 0xf0); \ -+ __spi_write_reg(0x22, 0x08); \ -+*/ -+/* -+ __spi_write_reg(0x02, 0x07); \ -+ __spi_write_reg(0x03, 0x5f); \ -+ __spi_write_reg(0x04, 0x17); \ -+ __spi_write_reg(0x05, 0x20); \ -+ __spi_write_reg(0x06, 0x08); \ -+ __spi_write_reg(0x07, 0x20); \ -+ __spi_write_reg(0x08, 0x20); \ -+ __spi_write_reg(0x09, 0x20); \ -+ __spi_write_reg(0x0a, 0x20); \ -+ __spi_write_reg(0x0b, 0x20); \ -+ __spi_write_reg(0x0c, 0x20); \ -+ __spi_write_reg(0x0d, 0x22); \ -+ __spi_write_reg(0x0e, 0x10); \ -+ __spi_write_reg(0x0f, 0x10); \ -+ __spi_write_reg(0x10, 0x10); \ -+ __spi_write_reg(0x11, 0x15); \ -+ __spi_write_reg(0x12, 0xaa); \ -+ __spi_write_reg(0x13, 0xff); \ -+ __spi_write_reg(0x14, 0x86); \ -+ __spi_write_reg(0x15, 0x84); \ -+ __spi_write_reg(0x16, 0xc3); \ -+ __spi_write_reg(0x17, 0xd8); \ -+ __spi_write_reg(0x18, 0x01); \ -+ __spi_write_reg(0x19, 0x28); \ -+ __spi_write_reg(0x1a, 0x53); \ -+ __spi_write_reg(0x1b, 0xc5); \ -+ __spi_write_reg(0x1c, 0x26); \ -+ __spi_write_reg(0x1d, 0x74); \ -+ __spi_write_reg(0x1e, 0xae); \ -+ __spi_write_reg(0x1f, 0xff); \ -+ __spi_write_reg(0x20, 0xf0); \ -+ __spi_write_reg(0x21, 0xf0); \ -+ __spi_write_reg(0x22, 0x08); \ -+ */ -diff --git a/drivers/video/jzlcd.c b/drivers/video/jzlcd.c -new file mode 100644 -index 0000000..357004a ---- /dev/null -+++ b/drivers/video/jzlcd.c -@@ -0,0 +1,1574 @@ -+/* -+ * linux/drivers/video/jzlcd.c -- Ingenic On-Chip LCD frame buffer device -+ * -+ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "console/fbcon.h" -+ -+#include "jzlcd.h" -+ -+#undef DEBUG -+//#define DEBUG -+#ifdef DEBUG -+#define dprintk(x...) printk(x) -+#else -+#define dprintk(x...) -+#endif -+ -+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) -+#ifdef DEBUG -+#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) -+#else -+#define print_dbg(f, arg...) do {} while (0) -+#endif -+ -+struct lcd_cfb_info { -+ struct fb_info fb; -+ struct display_switch *dispsw; -+ signed int currcon; -+ int func_use_count; -+ -+ struct { -+ u16 red, green, blue; -+ } palette[NR_PALETTE]; -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ struct task_struct *rotate_daemon_thread; -+#endif -+}; -+ -+static struct lcd_cfb_info *jzlcd_info; -+ -+struct jzfb_info { -+ unsigned int cfg; /* panel mode and pin usage etc. */ -+ unsigned int w; -+ unsigned int h; -+ unsigned int bpp; /* bit per pixel */ -+ unsigned int fclk; /* frame clk */ -+ unsigned int hsw; /* hsync width, in pclk */ -+ unsigned int vsw; /* vsync width, in line count */ -+ unsigned int elw; /* end of line, in pclk */ -+ unsigned int blw; /* begin of line, in pclk */ -+ unsigned int efw; /* end of frame, in line count */ -+ unsigned int bfw; /* begin of frame, in line count */ -+}; -+ -+static struct jzfb_info jzfb = { -+#if defined(CONFIG_JZLCD_SHARP_LQ035Q7) -+ MODE_TFT_SHARP | PCLK_N | VSYNC_N, -+ 240, 320, 16, 60, 1, 2, 1, 2, 0, 6 -+#endif -+#if defined(CONFIG_JZLCD_SAMSUNG_LTS350Q1) -+ MODE_TFT_SAMSUNG | PCLK_N, -+ 240, 320, 16, 60, 1, 2, (254-240), 0, 7, 0 -+#endif -+#if defined(CONFIG_JZLCD_SAMSUNG_LTV350QVF04) -+ MODE_TFT_GEN | HSYNC_N | VSYNC_N, -+ 320, 240, 16, 70, 19, 4, 20, 14, 18, 6 -+#endif -+#if defined(CONFIG_JZLCD_SAMSUNG_LTP400WQF01) -+ MODE_TFT_GEN | HSYNC_N | VSYNC_N, -+ 480, 272, 16, 60, 41, 10, 2, 2, 2, 2 -+#endif -+ -+#if defined(CONFIG_JZLCD_SAMSUNG_LTP400WQF02) -+ /* MODE_TFT_18BIT: JZ4740@ version */ -+ MODE_TFT_GEN | MODE_TFT_18BIT | HSYNC_N | VSYNC_N, -+ 480, 272, 32, 60, 41, 10, 2, 2, 2, 2 -+#endif -+#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW) -+ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, -+ 320, 240, 16, 85, 30, 3, 38, 20, 11, 8 -+#endif -+#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL) -+ MODE_8BIT_SERIAL_TFT | HSYNC_N | VSYNC_N | PCLK_N, -+ /* serial mode 280 lines, parallel mode 240 lines */ -+ 320, 280, 32, 60, (30*3), 3, (20*3), (38*3), 46, 23 -+#endif -+#if defined(CONFIG_JZLCD_AUO_A030FL01_V1) -+ MODE_TFT_GEN | MODE_TFT_18BIT | HSYNC_N | VSYNC_N, -+ 480, 272, 32, 60, 39, 10, 8, 4, 4, 2 -+#endif -+#if defined(CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E) -+ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N | DE_N, -+ 320, 240, 16, 60, 3, 3, 3, 3, 3, 85 /* 320x240 */ -+#endif -+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) -+ #if defined(CONFIG_JZ4740_PAVO) -+ MODE_TFT_GEN | HSYNC_N | VSYNC_N | MODE_TFT_18BIT | PCLK_N, -+ 320, 240, 18, 80, 1, 1, 10, 50, 10, 13 -+ #elif defined(CONFIG_JZ4740_QI_LB60) -+ MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N, -+ 320, 240, 32, 70, 1, 1, 273, 140, 1, 20 -+ #else -+ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, -+ 320, 240, 16, 110, 1, 1, 10, 50, 10, 13 -+ #endif -+#endif /* CONFIG_JZLCD_FOXCONN_PT035TN01 */ -+#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) -+ MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N, -+ 320, 240, 32, 60, 1, 1, 10, 50, 10, 13 -+#endif -+#if defined(CONFIG_JZLCD_HYNIX_HT10X21) -+ MODE_TFT_GEN | PCLK_N, -+ 1024, 768, 16, 45, 1, 1, 75, 0, 3, 0 -+#endif -+#if defined(CONFIG_JZLCD_TOSHIBA_LTM084P363) -+ MODE_TFT_GEN | PCLK_N, -+ 800, 600, 16, 50, 1, 2, 199, 0, 2, 0 -+#endif -+#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42) -+ MODE_TFT_SHARP | PCLK_N, -+ 800, 600, 16, 40, 1, 1, 255, 0, 34, 0 -+#endif -+#if defined(CONFIG_JZLCD_CSTN_800x600) -+ MODE_STN_COLOR_DUAL | STN_DAT_PIN8, -+ 800, 600, 16, 30, 8, 1, 0, 0, 0, 0 -+#endif -+#if defined(CONFIG_JZLCD_CSTN_320x240) -+ MODE_STN_COLOR_SINGLE | STN_DAT_PIN8, -+ 320, 240, 16, 120, 8, 1, 8, 0, 0, 0 -+#endif -+#if defined(CONFIG_JZLCD_MSTN_640x480) -+ MODE_STN_MONO_DUAL | STN_DAT_PIN4, -+ 640, 480, 8, 110, 4, 1, 4, 0, 0, 0 -+#endif -+#if defined(CONFIG_JZLCD_MSTN_320x240) -+ MODE_STN_MONO_SINGLE | STN_DAT_PIN4, -+ 320, 240, 8, 110, 4, 1, 4, 0, 0, 0 -+#endif -+#if defined(CONFIG_JZLCD_MSTN_480x320) -+ MODE_STN_MONO_SINGLE | STN_DAT_PIN8 -+#if defined(CONFIG_JZLCD_MSTN_INVERSE) -+ | DATA_INVERSE -+#endif -+ , 480, 320, 8, 65, 8, 1, 8, 0, 0, 0 -+#endif -+ -+#if defined(CONFIG_JZLCD_MSTN_240x128) -+ MODE_STN_MONO_SINGLE | STN_DAT_PIN1 -+#if defined(CONFIG_JZLCD_MSTN_INVERSE) -+ | DATA_INVERSE -+#endif -+ , 240, 128, 8, 100, 1, 1, 1, 0, 0, 0 -+#endif -+}; -+ -+static struct lcd_desc *lcd_desc_base; -+static struct lcd_desc *lcd_palette_desc; -+static struct lcd_desc *lcd_frame_desc0; -+static struct lcd_desc *lcd_frame_desc1; -+ -+static unsigned char *lcd_palette; -+static unsigned char *lcd_frame[CONFIG_JZLCD_FRAMEBUFFER_MAX]; -+struct jz_lcd_buffer_addrs_t jz_lcd_buffer_addrs; -+//extern struct display fb_display[MAX_NR_CONSOLES]; -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+static unsigned char *lcd_frame_user_fb; -+/* default rotate angle */ -+static volatile int rotate_angle = CONFIG_JZLCD_FRAMEBUFFER_DEFAULT_ROTATE_ANGLE; -+#endif -+ -+#ifdef DEBUG -+static void print_regs(void) /* debug */ -+{ -+ printk("REG_LCD_CFG:\t0x%8.8x\n", REG_LCD_CFG); -+ printk("REG_LCD_VSYNC:\t0x%8.8x\n", REG_LCD_VSYNC); -+ printk("REG_LCD_HSYNC:\t0x%8.8x\n", REG_LCD_HSYNC); -+ printk("REG_LCD_VAT:\t0x%8.8x\n", REG_LCD_VAT); -+ printk("REG_LCD_DAH:\t0x%8.8x\n", REG_LCD_DAH); -+ printk("REG_LCD_DAV:\t0x%8.8x\n", REG_LCD_DAV); -+ printk("REG_LCD_PS:\t0x%8.8x\n", REG_LCD_PS); -+ printk("REG_LCD_CLS:\t0x%8.8x\n", REG_LCD_CLS); -+ printk("REG_LCD_SPL:\t0x%8.8x\n", REG_LCD_SPL); -+ printk("REG_LCD_REV:\t0x%8.8x\n", REG_LCD_REV); -+ printk("REG_LCD_CTRL:\t0x%8.8x\n", REG_LCD_CTRL); -+ printk("REG_LCD_STATE:\t0x%8.8x\n", REG_LCD_STATE); -+ printk("REG_LCD_IID:\t0x%8.8x\n", REG_LCD_IID); -+ printk("REG_LCD_DA0:\t0x%8.8x\n", REG_LCD_DA0); -+ printk("REG_LCD_SA0:\t0x%8.8x\n", REG_LCD_SA0); -+ printk("REG_LCD_FID0:\t0x%8.8x\n", REG_LCD_FID0); -+ printk("REG_LCD_CMD0:\t0x%8.8x\n", REG_LCD_CMD0); -+ -+ printk("==================================\n"); -+ printk("REG_LCD_VSYNC:\t%d:%d\n", REG_LCD_VSYNC>>16, REG_LCD_VSYNC&0xfff); -+ printk("REG_LCD_HSYNC:\t%d:%d\n", REG_LCD_HSYNC>>16, REG_LCD_HSYNC&0xfff); -+ printk("REG_LCD_VAT:\t%d:%d\n", REG_LCD_VAT>>16, REG_LCD_VAT&0xfff); -+ printk("REG_LCD_DAH:\t%d:%d\n", REG_LCD_DAH>>16, REG_LCD_DAH&0xfff); -+ printk("REG_LCD_DAV:\t%d:%d\n", REG_LCD_DAV>>16, REG_LCD_DAV&0xfff); -+ printk("==================================\n"); -+ -+} -+#else -+#define print_regs() -+#endif -+ -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+static int jzfb_rotate_daemon_thread(void *info) -+{ -+ int i,j; -+ struct fb_info *fb = &jzlcd_info->fb; -+ -+ while (!kthread_should_stop()) { -+#if (CONFIG_JZLCD_FRAMEBUFFER_BPP == 8) -+ unsigned char *plcd_frame = (unsigned char *)lcd_frame[0]; -+ unsigned char *pfb = (unsigned char *) (fb->screen_base); -+#elif (CONFIG_JZLCD_FRAMEBUFFER_BPP == 16) -+ unsigned short *plcd_frame = (unsigned short *)lcd_frame[0]; -+ unsigned short *pfb = (unsigned short *) (fb->screen_base); -+#elif (CONFIG_JZLCD_FRAMEBUFFER_BPP == 32) -+ unsigned int *plcd_frame = (unsigned int *)lcd_frame[0]; -+ unsigned int *pfb = (unsigned int *) (fb->screen_base); -+#else -+#error "ERROR, rotate not support this bpp." -+#endif -+ switch ( rotate_angle ) { -+ case FB_ROTATE_UR: -+ printk("%s, Warning, this shouldn't reache\n", __FUNCTION__); -+ ssleep(1); -+ break; -+ case FB_ROTATE_UD: /* cost about 30ms, can be accelrated by dma in the future */ -+ plcd_frame += jzfb.w*jzfb.h -1; -+ for (i=0;ivar.height+1; i++) { -+ for (j=1; j < fb->var.width+1; j++) -+ plcd_frame[j*fb->var.height-i] = *pfb++; -+ } -+ msleep(100); /* sleep 100ms */ -+ break; -+ case FB_ROTATE_CCW: /* cost about 80ms */ -+ for (i=0;ivar.height;i++) { -+ for ( j=fb->var.width-1;j>=0;j--) -+ plcd_frame[j*fb->var.height+i] = *pfb++; -+ } -+ msleep(100); /* sleep 100ms */ -+ break; -+ default: /* FB_ROTATE_UR */ -+ dprintk("Unknown rotate(%d) type\n", rotate_angle); -+ ssleep(1); -+ } -+ -+ dma_cache_wback_inv((unsigned int)(lcd_frame_user_fb), fb->fix.smem_len); -+ } -+ return 0; -+} -+/* -+ * rotate param angle: -+ * 0: FB_ROTATE_UR, 0'C -+ * 1: FB_ROTATE_CW, 90'C -+ * 2: FB_ROTATE_UD, 180'C -+ * 3: FB_ROTATE_CCW, 270'C -+ */ -+static int jzfb_rotate_change( int angle ) -+{ -+ struct fb_info *fb = &jzlcd_info->fb; -+ -+ /* clear frame buffer */ -+ memset((void*)lcd_frame_user_fb, 0x00, fb->fix.smem_len); -+ switch ( angle ) { -+ case FB_ROTATE_UR: -+ fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.w; -+ fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.h; -+ /* change lcd controller's data buffer to lcd_frame_user_fb*/ -+ lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame_user_fb); -+ if ( rotate_angle != FB_ROTATE_UR ) -+ kthread_stop(jzlcd_info->rotate_daemon_thread); -+ rotate_angle = angle; -+ break; -+ case FB_ROTATE_UD: -+ case FB_ROTATE_CW: -+ case FB_ROTATE_CCW: -+ if ( angle == FB_ROTATE_UD ) { -+ fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.w; -+ fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.h; -+ } -+ else { /* CW, CCW */ -+ fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.h; -+ fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.w; -+ } -+ /* change lcd controller's data buffer to lcd_frame[0]*/ -+ lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame[0]); -+ if ( rotate_angle == FB_ROTATE_UR || \ -+ jzlcd_info->rotate_daemon_thread == NULL) -+ jzlcd_info->rotate_daemon_thread = kthread_run( jzfb_rotate_daemon_thread, jzlcd_info, "%s", "jzlcd-rotate-daemon"); /* start rotate daemon */ -+ rotate_angle = angle; -+ break; -+ default: -+ printk("Invalid angle(%d)\n", (unsigned int)angle); -+ } -+ fb->fix.line_length = fb->var.xres * CONFIG_JZLCD_FRAMEBUFFER_BPP/8; -+ dma_cache_wback_inv((unsigned int)(lcd_frame_desc0), sizeof(struct lcd_desc)); -+ return 0; -+} -+ -+void jzfb_fb_rotate(struct fb_info *fbi, int angle) -+{ -+ jzfb_rotate_change( angle/90 ); -+} -+#endif /* #if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ -+ -+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -+{ -+ chan &= 0xffff; -+ chan >>= 16 - bf->length; -+ return chan << bf->offset; -+} -+ -+static int jzfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -+ u_int transp, struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ unsigned short *ptr, ctmp; -+ -+// print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); -+ if (regno >= NR_PALETTE) -+ return 1; -+ -+ cfb->palette[regno].red = red ; -+ cfb->palette[regno].green = green; -+ cfb->palette[regno].blue = blue; -+ if (cfb->fb.var.bits_per_pixel <= 16) { -+ red >>= 8; -+ green >>= 8; -+ blue >>= 8; -+ -+ red &= 0xff; -+ green &= 0xff; -+ blue &= 0xff; -+ } -+ switch (cfb->fb.var.bits_per_pixel) { -+ case 1: -+ case 2: -+ case 4: -+ case 8: -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { -+ ctmp = (77L * red + 150L * green + 29L * blue) >> 8; -+ ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | -+ (ctmp >> 3); -+ } else { -+ /* RGB 565 */ -+ if (((red >> 3) == 0) && ((red >> 2) != 0)) -+ red = 1 << 3; -+ if (((blue >> 3) == 0) && ((blue >> 2) != 0)) -+ blue = 1 << 3; -+ ctmp = ((red >> 3) << 11) -+ | ((green >> 2) << 5) | (blue >> 3); -+ } -+ -+ ptr = (unsigned short *)lcd_palette; -+ ptr = (unsigned short *)(((u32)ptr)|0xa0000000); -+ ptr[regno] = ctmp; -+ -+ break; -+ -+ case 15: -+ if (regno < 16) -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ ((red >> 3) << 10) | -+ ((green >> 3) << 5) | -+ (blue >> 3); -+ break; -+ case 16: -+ if (regno < 16) { -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ ((red >> 3) << 11) | -+ ((green >> 2) << 5) | -+ (blue >> 3); -+ } -+ break; -+ case 18: -+ case 24: -+ case 32: -+ if (regno < 16) -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = -+ (red << 16) | -+ (green << 8) | -+ (blue << 0); -+ -+/* if (regno < 16) { -+ unsigned val; -+ val = chan_to_field(red, &cfb->fb.var.red); -+ val |= chan_to_field(green, &cfb->fb.var.green); -+ val |= chan_to_field(blue, &cfb->fb.var.blue); -+ ((u32 *)cfb->fb.pseudo_palette)[regno] = val; -+ } -+*/ -+ -+ break; -+ } -+ return 0; -+} -+ -+ -+static int jzfb_ioctl (struct fb_info *fb, unsigned int cmd, unsigned long arg ) -+{ -+ int ret = 0; -+ void __user *argp = (void __user *)arg; -+ -+ switch (cmd) { -+ case FBIOSETBACKLIGHT: -+ __lcd_set_backlight_level(arg); /* We support 8 levels here. */ -+ break; -+ case FBIODISPON: -+ __lcd_display_on(); -+ break; -+ case FBIODISPOFF: -+ __lcd_display_off(); -+ break; -+ case FBIOPRINT_REGS: -+ print_regs(); -+ break; -+ case FBIOGETBUFADDRS: -+ if ( copy_to_user(argp, &jz_lcd_buffer_addrs, -+ sizeof(struct jz_lcd_buffer_addrs_t)) ) -+ return -EFAULT; -+ break; -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ case FBIOROTATE: -+ ret = jzfb_rotate_change(arg); -+ break; -+#endif /* defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ -+ default: -+ printk("Warn: Command(%x) not support\n", cmd); -+ ret = -1; -+ break; -+ } -+ return ret; -+ -+} -+ -+/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -+static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -+ -+ /* frame buffer memory */ -+ start = cfb->fb.fix.smem_start; -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ off += start; -+ -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -+ -+#if 1 -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -+// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Through */ -+#endif -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot)) { -+ return -EAGAIN; -+ } -+ return 0; -+} -+ -+/* checks var and eventually tweaks it to something supported, -+ * DO NOT MODIFY PAR */ -+static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ print_dbg("jzfb_check_var"); -+ return 0; -+} -+ -+ -+/* -+ * set the video mode according to info->var -+ */ -+static int jzfb_set_par(struct fb_info *info) -+{ -+ print_dbg("jzfb_set_par"); -+ return 0; -+} -+ -+ -+/* -+ * (Un)Blank the display. -+ * Fix me: should we use VESA value? -+ */ -+static int jzfb_blank(int blank_mode, struct fb_info *info) -+{ -+ -+ dprintk("fb_blank %d %p", blank_mode, info); -+ -+ switch (blank_mode) { -+ -+ case FB_BLANK_UNBLANK: -+ //case FB_BLANK_NORMAL: -+ /* Turn on panel */ -+ __lcd_set_ena(); -+ __lcd_display_on(); -+ break; -+ -+ case FB_BLANK_NORMAL: -+ case FB_BLANK_VSYNC_SUSPEND: -+ case FB_BLANK_HSYNC_SUSPEND: -+ case FB_BLANK_POWERDOWN: -+#if 0 -+ /* Turn off panel */ -+ __lcd_set_dis(); -+ __lcd_display_off(); -+#endif -+ break; -+ default: -+ break; -+ -+ } -+ return 0; -+} -+ -+/* -+ * pan display -+ */ -+static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ int dy; -+ -+ if (!var || !cfb) { -+ return -EINVAL; -+ } -+ -+ if (var->xoffset - cfb->fb.var.xoffset) { -+ /* No support for X panning for now! */ -+ return -EINVAL; -+ } -+ -+ dy = var->yoffset - cfb->fb.var.yoffset; -+ print_dbg("var.yoffset: %d", dy); -+ if (dy) { -+ -+ print_dbg("Panning screen of %d lines", dy); -+ -+ lcd_frame_desc0->databuf += (cfb->fb.fix.line_length * dy); -+ /* TODO: Wait for current frame to finished */ -+ } -+ -+ return 0; -+} -+ -+ -+/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ -+static struct fb_ops jzfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_setcolreg = jzfb_setcolreg, -+ .fb_check_var = jzfb_check_var, -+ .fb_set_par = jzfb_set_par, -+ .fb_blank = jzfb_blank, -+ .fb_pan_display = jzfb_pan_display, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+ .fb_mmap = jzfb_mmap, -+ .fb_ioctl = jzfb_ioctl, -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ .fb_rotate = jzfb_fb_rotate, -+#endif -+}; -+ -+static int jzfb_set_var(struct fb_var_screeninfo *var, int con, -+ struct fb_info *info) -+{ -+ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -+ int chgvar = 0; -+ -+ var->height = jzfb.h ; -+ var->width = jzfb.w ; -+ var->bits_per_pixel = jzfb.bpp; -+ -+ var->vmode = FB_VMODE_NONINTERLACED; -+ var->activate = cfb->fb.var.activate; -+ var->xres = var->width; -+ var->yres = var->height; -+ var->xres_virtual = var->width; -+ var->yres_virtual = var->height; -+ var->xoffset = 0; -+ var->yoffset = 0; -+ var->pixclock = 0; -+ var->left_margin = 0; -+ var->right_margin = 0; -+ var->upper_margin = 0; -+ var->lower_margin = 0; -+ var->hsync_len = 0; -+ var->vsync_len = 0; -+ var->sync = 0; -+ var->activate &= ~FB_ACTIVATE_TEST; -+ -+ /* -+ * CONUPDATE and SMOOTH_XPAN are equal. However, -+ * SMOOTH_XPAN is only used internally by fbcon. -+ */ -+ if (var->vmode & FB_VMODE_CONUPDATE) { -+ var->vmode |= FB_VMODE_YWRAP; -+ var->xoffset = cfb->fb.var.xoffset; -+ var->yoffset = cfb->fb.var.yoffset; -+ } -+ -+ if (var->activate & FB_ACTIVATE_TEST) -+ return 0; -+ -+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) -+ return -EINVAL; -+ -+ if (cfb->fb.var.xres != var->xres) -+ chgvar = 1; -+ if (cfb->fb.var.yres != var->yres) -+ chgvar = 1; -+ if (cfb->fb.var.xres_virtual != var->xres_virtual) -+ chgvar = 1; -+ if (cfb->fb.var.yres_virtual != var->yres_virtual) -+ chgvar = 1; -+ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) -+ chgvar = 1; -+ -+ var->red.msb_right = 0; -+ var->green.msb_right = 0; -+ var->blue.msb_right = 0; -+ -+ switch(var->bits_per_pixel){ -+ case 1: /* Mono */ -+ cfb->fb.fix.visual = FB_VISUAL_MONO01; -+ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ break; -+ case 2: /* Mono */ -+ var->red.offset = 0; -+ var->red.length = 2; -+ var->green.offset = 0; -+ var->green.length = 2; -+ var->blue.offset = 0; -+ var->blue.length = 2; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ break; -+ case 4: /* PSEUDOCOLOUR*/ -+ var->red.offset = 0; -+ var->red.length = 4; -+ var->green.offset = 0; -+ var->green.length = 4; -+ var->blue.offset = 0; -+ var->blue.length = 4; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = var->xres / 2; -+ break; -+ case 8: /* PSEUDOCOLOUR, 256 */ -+ var->red.offset = 0; -+ var->red.length = 8; -+ var->green.offset = 0; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ -+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ cfb->fb.fix.line_length = var->xres ; -+ break; -+ case 15: /* DIRECTCOLOUR, 32k */ -+ var->bits_per_pixel = 15; -+ var->red.offset = 10; -+ var->red.length = 5; -+ var->green.offset = 5; -+ var->green.length = 5; -+ var->blue.offset = 0; -+ var->blue.length = 5; -+ -+ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 2; -+ break; -+ case 16: /* DIRECTCOLOUR, 64k */ -+ var->bits_per_pixel = 16; -+ var->red.offset = 11; -+ var->red.length = 5; -+ var->green.offset = 5; -+ var->green.length = 6; -+ var->blue.offset = 0; -+ var->blue.length = 5; -+ -+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 2; -+ break; -+ case 18: -+ case 24: -+ case 32: -+ /* DIRECTCOLOUR, 16M */ -+ var->bits_per_pixel = 32; -+ -+ var->red.offset = 16; -+ var->red.length = 8; -+ var->green.offset = 8; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ var->transp.offset = 24; -+ var->transp.length = 8; -+ -+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -+ cfb->fb.fix.line_length = var->xres_virtual * 4; -+ break; -+ -+ default: /* in theory this should never happen */ -+ printk(KERN_WARNING "%s: don't support for %dbpp\n", -+ cfb->fb.fix.id, var->bits_per_pixel); -+ break; -+ } -+ -+ cfb->fb.var = *var; -+ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; -+ -+ /* -+ * Update the old var. The fbcon drivers still use this. -+ * Once they are using cfb->fb.var, this can be dropped. -+ * --rmk -+ */ -+ //display->var = cfb->fb.var; -+ /* -+ * If we are setting all the virtual consoles, also set the -+ * defaults used to create new consoles. -+ */ -+ fb_set_cmap(&cfb->fb.cmap, &cfb->fb); -+ dprintk("jzfb_set_var: after fb_set_cmap...\n"); -+ -+ return 0; -+} -+ -+static struct lcd_cfb_info * jzfb_alloc_fb_info(void) -+{ -+ struct lcd_cfb_info *cfb; -+ -+ cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); -+ -+ if (!cfb) -+ return NULL; -+ -+ jzlcd_info = cfb; -+ -+ memset(cfb, 0, sizeof(struct lcd_cfb_info) ); -+ -+ cfb->currcon = -1; -+ -+ -+ strcpy(cfb->fb.fix.id, "jz-lcd"); -+ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; -+ cfb->fb.fix.type_aux = 0; -+ cfb->fb.fix.xpanstep = 1; -+ cfb->fb.fix.ypanstep = 1; -+ cfb->fb.fix.ywrapstep = 0; -+ cfb->fb.fix.accel = FB_ACCEL_NONE; -+ -+ cfb->fb.var.nonstd = 0; -+ cfb->fb.var.activate = FB_ACTIVATE_NOW; -+ cfb->fb.var.height = -1; -+ cfb->fb.var.width = -1; -+ cfb->fb.var.accel_flags = FB_ACCELF_TEXT; -+ -+ cfb->fb.fbops = &jzfb_ops; -+ cfb->fb.flags = FBINFO_FLAG_DEFAULT; -+ -+ cfb->fb.pseudo_palette = (void *)(cfb + 1); -+ -+ switch (jzfb.bpp) { -+ case 1: -+ fb_alloc_cmap(&cfb->fb.cmap, 4, 0); -+ break; -+ case 2: -+ fb_alloc_cmap(&cfb->fb.cmap, 8, 0); -+ break; -+ case 4: -+ fb_alloc_cmap(&cfb->fb.cmap, 32, 0); -+ break; -+ case 8: -+ -+ default: -+ fb_alloc_cmap(&cfb->fb.cmap, 256, 0); -+ break; -+ } -+ dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); -+ -+ return cfb; -+} -+ -+/* -+ * Map screen memory -+ */ -+static int jzfb_map_smem(struct lcd_cfb_info *cfb) -+{ -+ struct page * map = NULL; -+ unsigned char *tmp; -+ unsigned int page_shift, needroom, t; -+#if defined(CONFIG_SOC_JZ4740) -+ if (jzfb.bpp == 18 || jzfb.bpp == 24) -+ t = 32; -+ else -+ t = jzfb.bpp; -+#else -+ if (jzfb.bpp == 15) -+ t = 16; -+ else -+ t = jzfb.bpp; -+#endif -+ -+ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -+ for (page_shift = 0; page_shift < 12; page_shift++) -+ if ((PAGE_SIZE << page_shift) >= needroom) -+ break; -+ -+ /* lcd_palette room total 4KB: -+ * 0 -- 512: lcd palette -+ * 1024 -- [1024+16*3]: lcd descripters -+ * [1024+16*3] -- 4096: reserved -+ */ -+ lcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -+ if ((!lcd_palette)) -+ return -ENOMEM; -+ -+ memset((void *)lcd_palette, 0, PAGE_SIZE); -+ map = virt_to_page(lcd_palette); -+ set_bit(PG_reserved, &map->flags); -+ lcd_desc_base = (struct lcd_desc *)(lcd_palette + 1024); -+ -+ jz_lcd_buffer_addrs.fb_num = CONFIG_JZLCD_FRAMEBUFFER_MAX; -+ printk("jzlcd use %d framebuffer:\n", CONFIG_JZLCD_FRAMEBUFFER_MAX); -+ /* alloc frame buffer space */ -+ for ( t = 0; t < CONFIG_JZLCD_FRAMEBUFFER_MAX; t++ ) { -+ lcd_frame[t] = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ if ((!lcd_frame[t])) { -+ printk("no mem for fb[%d]\n", t); -+ return -ENOMEM; -+ } -+// memset((void *)lcd_frame[t], 0, PAGE_SIZE << page_shift); -+ for (tmp=(unsigned char *)lcd_frame[t]; -+ tmp < lcd_frame[t] + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ set_bit(PG_reserved, &map->flags); -+ } -+ jz_lcd_buffer_addrs.fb_phys_addr[t] = virt_to_phys((void *)lcd_frame[t]); -+ printk("jzlcd fb[%d] phys addr =0x%08x\n", -+ t, jz_lcd_buffer_addrs.fb_phys_addr[t]); -+ } -+#if !defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ cfb->fb.fix.smem_start = virt_to_phys((void *)lcd_frame[0]); -+ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); -+ cfb->fb.screen_base = -+ (unsigned char *)(((unsigned int)lcd_frame[0] & 0x1fffffff) | 0xa0000000); -+#else /* Framebuffer rotate */ -+ lcd_frame_user_fb = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -+ if ((!lcd_frame_user_fb)) { -+ printk("no mem for fb[%d]\n", t); -+ return -ENOMEM; -+ } -+ memset((void *)lcd_frame_user_fb, 0, PAGE_SIZE << page_shift); -+ for (tmp=(unsigned char *)lcd_frame_user_fb; -+ tmp < lcd_frame_user_fb + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ set_bit(PG_reserved, &map->flags); -+ } -+ -+ printk("Rotate userfb phys addr =0x%08x\n", -+ (unsigned int)virt_to_phys((void *)lcd_frame_user_fb)); -+ cfb->fb.fix.smem_start = virt_to_phys((void *)lcd_frame_user_fb); -+ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); -+ cfb->fb.screen_base = (unsigned char *)(((unsigned int)lcd_frame_user_fb & 0x1fffffff) | 0xa0000000); -+ -+#endif /* #if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ -+ if (!cfb->fb.screen_base) { -+ printk("%s: unable to map screen memory\n", cfb->fb.fix.id); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void jzfb_free_fb_info(struct lcd_cfb_info *cfb) -+{ -+ if (cfb) { -+ fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -+ kfree(cfb); -+ } -+} -+ -+static void jzfb_unmap_smem(struct lcd_cfb_info *cfb) -+{ -+ struct page * map = NULL; -+ unsigned char *tmp; -+ unsigned int page_shift, needroom, t; -+#if defined(CONFIG_SOC_JZ4740) -+ if (jzfb.bpp == 18 || jzfb.bpp == 24) -+ t = 32; -+ else -+ t = jzfb.bpp; -+#else -+ if (jzfb.bpp == 15) -+ t = 16; -+ else -+ t = jzfb.bpp; -+#endif -+ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -+ for (page_shift = 0; page_shift < 12; page_shift++) -+ if ((PAGE_SIZE << page_shift) >= needroom) -+ break; -+ -+ if (cfb && cfb->fb.screen_base) { -+ iounmap(cfb->fb.screen_base); -+ cfb->fb.screen_base = NULL; -+ release_mem_region(cfb->fb.fix.smem_start, -+ cfb->fb.fix.smem_len); -+ } -+ -+ if (lcd_palette) { -+ map = virt_to_page(lcd_palette); -+ clear_bit(PG_reserved, &map->flags); -+ free_pages((int)lcd_palette, 0); -+ } -+ -+ for ( t=0; t < CONFIG_JZLCD_FRAMEBUFFER_MAX; t++ ) { -+ if (lcd_frame[t]) { -+ for (tmp=(unsigned char *)lcd_frame[t]; -+ tmp < lcd_frame[t] + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ clear_bit(PG_reserved, &map->flags); -+ } -+ free_pages((int)lcd_frame[t], page_shift); -+ } -+ } -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ if (lcd_frame_user_fb) { -+ for (tmp=(unsigned char *)lcd_frame_user_fb; -+ tmp < lcd_frame_user_fb + (PAGE_SIZE << page_shift); -+ tmp += PAGE_SIZE) { -+ map = virt_to_page(tmp); -+ clear_bit(PG_reserved, &map->flags); -+ } -+ free_pages((int)lcd_frame_user_fb, page_shift); -+ } -+ -+#endif -+} -+ -+static void lcd_descriptor_init(void) -+{ -+ int i; -+ unsigned int pal_size; -+ unsigned int frm_size, ln_size; -+ unsigned char dual_panel = 0; -+ -+ i = jzfb.bpp; -+#if defined(CONFIG_SOC_JZ4740) -+ if (i == 18 || i == 24) -+ i = 32; -+#else -+ if (i == 15) -+ i = 16; -+#endif -+ frm_size = (jzfb.w*jzfb.h*i)>>3; -+ ln_size = (jzfb.w*i)>>3; -+ -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { -+ dual_panel = 1; -+ frm_size >>= 1; -+ } -+ -+ frm_size = frm_size / 4; -+ ln_size = ln_size / 4; -+ -+ switch (jzfb.bpp) { -+ case 1: -+ pal_size = 4; -+ break; -+ case 2: -+ pal_size = 8; -+ break; -+ case 4: -+ pal_size = 32; -+ break; -+ case 8: -+ default: -+ pal_size = 512; -+ } -+ -+ pal_size /= 4; -+ -+ lcd_frame_desc0 = lcd_desc_base + 0; -+ lcd_frame_desc1 = lcd_desc_base + 1; -+ lcd_palette_desc = lcd_desc_base + 2; -+ -+ jz_lcd_buffer_addrs.lcd_desc_phys_addr = (unsigned int)virt_to_phys(lcd_frame_desc0); -+ -+ /* Palette Descriptor */ -+ lcd_palette_desc->next_desc = (int)virt_to_phys(lcd_frame_desc0); -+ lcd_palette_desc->databuf = (int)virt_to_phys((void *)lcd_palette); -+ lcd_palette_desc->frame_id = (unsigned int)0xdeadbeaf; -+ lcd_palette_desc->cmd = pal_size|LCD_CMD_PAL; /* Palette Descriptor */ -+ -+ /* Frame Descriptor 0 */ -+ if (jzfb.bpp <= 8) -+ lcd_frame_desc0->next_desc = (int)virt_to_phys(lcd_palette_desc); -+ else -+ lcd_frame_desc0->next_desc = (int)virt_to_phys(lcd_frame_desc0); -+ lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame[0]); -+ lcd_frame_desc0->frame_id = (unsigned int)0xbeafbeaf; -+ lcd_frame_desc0->cmd = LCD_CMD_SOFINT | LCD_CMD_EOFINT | frm_size; -+ dma_cache_wback_inv((unsigned int)(lcd_palette_desc),0x10); -+ dma_cache_wback_inv((unsigned int)(lcd_frame_desc0),0x10); -+ -+ if (!(dual_panel)) -+ return; -+ -+ /* Frame Descriptor 1 */ -+ lcd_frame_desc1->next_desc = (int)virt_to_phys(lcd_frame_desc1); -+ lcd_frame_desc1->databuf = virt_to_phys((void *)(lcd_frame[0] + frm_size * 4)); -+ lcd_frame_desc1->frame_id = (unsigned int)0xdeaddead; -+ lcd_frame_desc1->cmd = LCD_CMD_SOFINT | LCD_CMD_EOFINT | frm_size; -+ dma_cache_wback_inv((unsigned int)(lcd_frame_desc1),0x10); -+} -+ -+static int lcd_hw_init(void) -+{ -+ unsigned int val = 0; -+ unsigned int pclk; -+ unsigned int stnH; -+ int ret = 0; -+ -+ /* Setting Control register */ -+ switch (jzfb.bpp) { -+ case 1: -+ val |= LCD_CTRL_BPP_1; -+ break; -+ case 2: -+ val |= LCD_CTRL_BPP_2; -+ break; -+ case 4: -+ val |= LCD_CTRL_BPP_4; -+ break; -+ case 8: -+ val |= LCD_CTRL_BPP_8; -+ break; -+ case 15: -+ val |= LCD_CTRL_RGB555; -+ case 16: -+ val |= LCD_CTRL_BPP_16; -+ break; -+#if defined(CONFIG_SOC_JZ4740) -+ case 17 ... 32: -+ val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */ -+ break; -+#endif -+ default: -+ printk("The BPP %d is not supported\n", jzfb.bpp); -+ val |= LCD_CTRL_BPP_16; -+ break; -+ } -+ -+ switch (jzfb.cfg & MODE_MASK) { -+ case MODE_STN_MONO_DUAL: -+ case MODE_STN_COLOR_DUAL: -+ case MODE_STN_MONO_SINGLE: -+ case MODE_STN_COLOR_SINGLE: -+ switch (jzfb.bpp) { -+ case 1: -+ case 2: -+ val |= LCD_CTRL_FRC_2; -+ break; -+ case 4: -+ val |= LCD_CTRL_FRC_4; -+ break; -+ case 8: -+ default: -+ val |= LCD_CTRL_FRC_16; -+ break; -+ } -+ break; -+ } -+ -+ val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ -+ -+ switch (jzfb.cfg & MODE_MASK) { -+ case MODE_STN_MONO_DUAL: -+ case MODE_STN_COLOR_DUAL: -+ case MODE_STN_MONO_SINGLE: -+ case MODE_STN_COLOR_SINGLE: -+ switch (jzfb.cfg & STN_DAT_PINMASK) { -+#define align2(n) (n)=((((n)+1)>>1)<<1) -+#define align4(n) (n)=((((n)+3)>>2)<<2) -+#define align8(n) (n)=((((n)+7)>>3)<<3) -+ case STN_DAT_PIN1: -+ /* Do not adjust the hori-param value. */ -+ break; -+ case STN_DAT_PIN2: -+ align2(jzfb.hsw); -+ align2(jzfb.elw); -+ align2(jzfb.blw); -+ break; -+ case STN_DAT_PIN4: -+ align4(jzfb.hsw); -+ align4(jzfb.elw); -+ align4(jzfb.blw); -+ break; -+ case STN_DAT_PIN8: -+ align8(jzfb.hsw); -+ align8(jzfb.elw); -+ align8(jzfb.blw); -+ break; -+ } -+ break; -+ } -+ -+ val |= 1 << 26; /* Output FIFO underrun protection */ -+ REG_LCD_CTRL = val; -+ -+ switch (jzfb.cfg & MODE_MASK) { -+ case MODE_STN_MONO_DUAL: -+ case MODE_STN_COLOR_DUAL: -+ case MODE_STN_MONO_SINGLE: -+ case MODE_STN_COLOR_SINGLE: -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) -+ stnH = jzfb.h >> 1; -+ else -+ stnH = jzfb.h; -+ -+ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; -+ REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw); -+ -+ /* Screen setting */ -+ REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw); -+ REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w); -+ REG_LCD_DAV = (0 << 16) | (stnH); -+ -+ /* AC BIAs signal */ -+ REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw); -+ -+ break; -+ -+ case MODE_TFT_GEN: -+ case MODE_TFT_SHARP: -+ case MODE_TFT_CASIO: -+ case MODE_TFT_SAMSUNG: -+ case MODE_8BIT_SERIAL_TFT: -+ case MODE_TFT_18BIT: -+ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; -+#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42) -+ REG_LCD_DAV = (0 << 16) | ( jzfb.h ); -+#else -+ REG_LCD_DAV = ((jzfb.vsw + jzfb.bfw) << 16) | (jzfb.vsw + jzfb.bfw + jzfb.h); -+#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ -+ REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw); -+ REG_LCD_HSYNC = (0 << 16) | jzfb.hsw; -+ REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w); -+ break; -+ } -+ -+ switch (jzfb.cfg & MODE_MASK) { -+ case MODE_TFT_SAMSUNG: -+ { -+ unsigned int total, tp_s, tp_e, ckv_s, ckv_e; -+ unsigned int rev_s, rev_e, inv_s, inv_e; -+ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; -+ tp_s = jzfb.blw + jzfb.w + 1; -+ tp_e = tp_s + 1; -+ ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); -+ ckv_e = tp_s + total; -+ rev_s = tp_s - 11; /* -11.5 clk */ -+ rev_e = rev_s + total; -+ inv_s = tp_s; -+ inv_e = inv_s + total; -+ REG_LCD_CLS = (tp_s << 16) | tp_e; -+ REG_LCD_PS = (ckv_s << 16) | ckv_e; -+ REG_LCD_SPL = (rev_s << 16) | rev_e; -+ REG_LCD_REV = (inv_s << 16) | inv_e; -+ jzfb.cfg |= STFT_REVHI | STFT_SPLHI; -+ break; -+ } -+ case MODE_TFT_SHARP: -+ { -+ unsigned int total, cls_s, cls_e, ps_s, ps_e; -+ unsigned int spl_s, spl_e, rev_s, rev_e; -+ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; -+#if !defined(CONFIG_JZLCD_INNOLUX_AT080TN42) -+ spl_s = 1; -+ spl_e = spl_s + 1; -+ cls_s = 0; -+ cls_e = total - 60; /* > 4us (pclk = 80ns) */ -+ ps_s = cls_s; -+ ps_e = cls_e; -+ rev_s = total - 40; /* > 3us (pclk = 80ns) */ -+ rev_e = rev_s + total; -+ jzfb.cfg |= STFT_PSHI; -+#else /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ -+ spl_s = total - 5; /* LD */ -+ spl_e = total - 3; -+ cls_s = 32; /* CKV */ -+ cls_e = 145; -+ ps_s = 0; /* OEV */ -+ ps_e = 45; -+ rev_s = 0; /* POL */ -+ rev_e = 0; -+#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ -+ REG_LCD_SPL = (spl_s << 16) | spl_e; -+ REG_LCD_CLS = (cls_s << 16) | cls_e; -+ REG_LCD_PS = (ps_s << 16) | ps_e; -+ REG_LCD_REV = (rev_s << 16) | rev_e; -+ break; -+ } -+ case MODE_TFT_CASIO: -+ break; -+ } -+ -+ /* Configure the LCD panel */ -+ REG_LCD_CFG = jzfb.cfg; -+ -+ /* Timing setting */ -+ __cpm_stop_lcd(); -+ -+ val = jzfb.fclk; /* frame clk */ -+ -+ if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) { -+ pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * -+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ -+ } -+ else { -+ /* serial mode: Hsync period = 3*Width_Pixel */ -+ pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) * -+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ -+ } -+ -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) -+ pclk = (pclk * 3); -+ -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -+ pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4); -+ -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -+ pclk >>= 1; -+#if defined(CONFIG_SOC_JZ4730) -+ val = __cpm_get_pllout() / pclk; -+ REG_CPM_CFCR2 = val - 1; -+ val = __cpm_get_pllout() / (pclk * 4); -+ val = __cpm_divisor_encode(val); -+ __cpm_set_lcdclk_div(val); -+ REG_CPM_CFCR |= CPM_CFCR_UPE; -+#elif defined(CONFIG_SOC_JZ4740) -+ val = ( __cpm_get_pllout2()) / pclk; -+ val--; -+ if ( val > 0x3ff ) { -+ printk("pixel clock divid is too large, set it to 0x3ff\n"); -+ val = 0x3ff; -+ } -+ __cpm_set_pixdiv(val); -+ -+ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ -+ val =__cpm_get_pllout() / val; -+ if ( val > 0x1f ) { -+ printk("lcd clock divide is too large, set it to 0x1f\n"); -+ val = 0x1f; -+ } -+ __cpm_set_ldiv( val ); -+ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -+ -+#else -+ printk("drivers/video/Jzlcd.c, CONFIG_MIPS, please set chip type.\n"); -+#endif /*#ifdef CONFIG_MIPS_JZ4730 */ -+ -+ jz_clocks.pixclk = __cpm_get_pixclk(); -+ jz_clocks.lcdclk = __cpm_get_lcdclk(); -+ printk("LCDC: PixClock:%d LcdClock:%d\n", -+ jz_clocks.pixclk, jz_clocks.lcdclk); -+ -+ __cpm_start_lcd(); -+ udelay(1000); -+ return ret; -+} -+ -+static irqreturn_t lcd_interrupt_handler(int irq, void *dev_id) -+{ -+ unsigned int state; -+ -+ state = REG_LCD_STATE; -+ -+ if (state & LCD_STATE_EOF) /* End of frame */ -+ REG_LCD_STATE = state & ~LCD_STATE_EOF; -+ -+ if (state & LCD_STATE_IFU0) { -+ dprintk("InFiFo0 underrun\n"); -+ REG_LCD_STATE = state & ~LCD_STATE_IFU0; -+ } -+ -+ if (state & LCD_STATE_OFU) { /* Out fifo underrun */ -+ REG_LCD_STATE = state & ~LCD_STATE_OFU; -+ dprintk("Out FiFo underrun.\n"); -+ } -+ return IRQ_HANDLED; -+} -+ -+#ifdef CONFIG_PM -+ -+/* -+ * Suspend the LCDC. -+ */ -+static int jzfb_suspend(void) -+{ -+ __lcd_clr_ena(); /* Quick Disable */ -+ __lcd_display_off(); -+ __cpm_stop_lcd(); -+ -+ return 0; -+} -+ -+/* -+ * Resume the LCDC. -+ */ -+#ifdef CONFIG_SOC_JZ4730 -+static int jzfb_resume(void) -+{ -+ __cpm_start_lcd(); -+ -+ __lcd_display_pin_init(); -+ -+ __lcd_display_on(); -+ -+ lcd_hw_init(); -+ -+ if (jzfb.bpp <= 8) -+ REG_LCD_DA0 = virt_to_phys(lcd_palette_desc); -+ else -+ REG_LCD_DA0 = virt_to_phys(lcd_frame_desc0); -+ -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -+ REG_LCD_DA1 = virt_to_phys(lcd_frame_desc1); -+ -+ __lcd_set_ena(); -+ return 0; -+} -+ -+#else -+/* -+ * Resume the LCDC. -+ */ -+static int jzfb_resume(void) -+{ -+ __cpm_start_lcd(); -+ __gpio_set_pin(GPIO_DISP_OFF_N); -+ __lcd_special_on(); -+ __lcd_set_ena(); -+ mdelay(200); -+ __lcd_set_backlight_level(80); -+ -+ return 0; -+} -+#endif /* CONFIG_MIPS_JZ4730 */ -+ -+/* -+ * Power management hook. Note that we won't be called from IRQ context, -+ * unlike the blank functions above, so we may sleep. -+ */ -+static int jzlcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct lcd_cfb_info *cfb = pm_dev->data; -+ -+ if (!cfb) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jzfb_suspend(); -+ break; -+ -+ case PM_RESUME: -+ ret = jzfb_resume(); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#else -+#define jzfb_suspend NULL -+#define jzfb_resume NULL -+#endif /* CONFIG_PM */ -+ -+static int __init jzfb_init(void) -+{ -+ struct lcd_cfb_info *cfb; -+ int err = 0; -+ -+ /* In special mode, we only need init special pin, -+ * as general lcd pin has init in uboot */ -+#if defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) -+ switch (jzfb.cfg & MODE_MASK) { -+ case LCD_CFG_MODE_SPECIAL_TFT_1: -+ case LCD_CFG_MODE_SPECIAL_TFT_2: -+ case LCD_CFG_MODE_SPECIAL_TFT_3: -+ __gpio_as_lcd_special(); -+ break; -+ default: -+ ; -+ } -+#endif -+ __lcd_display_pin_init(); -+ -+ cfb = jzfb_alloc_fb_info(); -+ if (!cfb) -+ goto failed; -+ -+ err = jzfb_map_smem(cfb); -+ if (err) -+ goto failed; -+ -+ jzfb_set_var(&cfb->fb.var, -1, &cfb->fb); -+ -+ lcd_descriptor_init(); -+ -+ err = lcd_hw_init(); -+ if (err) -+ goto failed; -+ -+ if (jzfb.bpp <= 8) -+ REG_LCD_DA0 = virt_to_phys(lcd_palette_desc); -+ else -+ REG_LCD_DA0 = virt_to_phys(lcd_frame_desc0); -+ -+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -+ REG_LCD_DA1 = virt_to_phys(lcd_frame_desc1); -+ -+ __lcd_set_ena(); -+ -+ if (request_irq(IRQ_LCD, lcd_interrupt_handler, IRQF_DISABLED, -+ "lcd", 0)) { -+ err = -EBUSY; -+ goto failed; -+ } -+ -+ __lcd_enable_ofu_intr(); /* enable OutFifo underrun */ -+// __lcd_enable_ifu0_intr(); /* needn't enable InFifo underrun */ -+ -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ jzfb_rotate_change(rotate_angle); -+ /* sleep n??? */ -+#endif -+ err = register_framebuffer(&cfb->fb); -+ if (err < 0) { -+ dprintk("jzfb_init(): register framebuffer err.\n"); -+ goto failed; -+ } -+ -+ printk("fb%d: %s frame buffer device, using %dK of video memory\n", -+ cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); -+ -+#ifdef CONFIG_PM -+ /* -+ * Note that the console registers this as well, but we want to -+ * power down the display prior to sleeping. -+ */ -+ cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzlcd_pm_callback); -+ if (cfb->pm) -+ cfb->pm->data = cfb; -+#endif -+ -+ __lcd_display_off(); -+ -+ return 0; -+ -+failed: -+ jzfb_unmap_smem(cfb); -+ jzfb_free_fb_info(cfb); -+ -+ return err; -+} -+ -+#if 0 -+static int jzfb_remove(struct device *dev) -+{ -+ struct lcd_cfb_info *cfb = dev_get_drvdata(dev); -+ jzfb_unmap_smem(cfb); -+ jzfb_free_fb_info(cfb); -+ return 0; -+} -+#endif -+ -+#if 0 -+static struct device_driver jzfb_driver = { -+ .name = "jz-lcd", -+ .bus = &platform_bus_type, -+ .probe = jzfb_probe, -+ .remove = jzfb_remove, -+ .suspend = jzfb_suspend, -+ .resume = jzfb_resume, -+}; -+#endif -+ -+static void __exit jzfb_cleanup(void) -+{ -+#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -+ kthread_stop(jzlcd_info->rotate_daemon_thread); -+#endif -+// driver_unregister(&jzfb_driver); -+// jzfb_remove(); -+} -+ -+module_init(jzfb_init); -+module_exit(jzfb_cleanup); -+ -+MODULE_DESCRIPTION("JzSOC LCD Controller driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/video/jzlcd.h b/drivers/video/jzlcd.h -new file mode 100644 -index 0000000..a4ef75f ---- /dev/null -+++ b/drivers/video/jzlcd.h -@@ -0,0 +1,800 @@ -+/* -+ * linux/drivers/video/jzlcd.h -- Ingenic On-Chip LCD frame buffer device -+ * -+ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#ifndef __JZLCD_H__ -+#define __JZLCD_H__ -+ -+#include -+ -+#define NR_PALETTE 256 -+ -+struct lcd_desc{ -+ unsigned int next_desc; /* LCDDAx */ -+ unsigned int databuf; /* LCDSAx */ -+ unsigned int frame_id; /* LCDFIDx */ -+ unsigned int cmd; /* LCDCMDx */ -+}; -+ -+#define MODE_MASK 0x0f -+#define MODE_TFT_GEN 0x00 -+#define MODE_TFT_SHARP 0x01 -+#define MODE_TFT_CASIO 0x02 -+#define MODE_TFT_SAMSUNG 0x03 -+#define MODE_CCIR656_NONINT 0x04 -+#define MODE_CCIR656_INT 0x05 -+#define MODE_STN_COLOR_SINGLE 0x08 -+#define MODE_STN_MONO_SINGLE 0x09 -+#define MODE_STN_COLOR_DUAL 0x0a -+#define MODE_STN_MONO_DUAL 0x0b -+#define MODE_8BIT_SERIAL_TFT 0x0c -+ -+#define MODE_TFT_18BIT (1<<7) -+ -+#define STN_DAT_PIN1 (0x00 << 4) -+#define STN_DAT_PIN2 (0x01 << 4) -+#define STN_DAT_PIN4 (0x02 << 4) -+#define STN_DAT_PIN8 (0x03 << 4) -+#define STN_DAT_PINMASK STN_DAT_PIN8 -+ -+#define STFT_PSHI (1 << 15) -+#define STFT_CLSHI (1 << 14) -+#define STFT_SPLHI (1 << 13) -+#define STFT_REVHI (1 << 12) -+ -+#define SYNC_MASTER (0 << 16) -+#define SYNC_SLAVE (1 << 16) -+ -+#define DE_P (0 << 9) -+#define DE_N (1 << 9) -+ -+#define PCLK_P (0 << 10) -+#define PCLK_N (1 << 10) -+ -+#define HSYNC_P (0 << 11) -+#define HSYNC_N (1 << 11) -+ -+#define VSYNC_P (0 << 8) -+#define VSYNC_N (1 << 8) -+ -+#define DATA_NORMAL (0 << 17) -+#define DATA_INVERSE (1 << 17) -+ -+ -+/* Jz LCDFB supported I/O controls. */ -+#define FBIOSETBACKLIGHT 0x4688 -+#define FBIODISPON 0x4689 -+#define FBIODISPOFF 0x468a -+#define FBIORESET 0x468b -+#define FBIOPRINT_REGS 0x468c -+#define FBIOGETBUFADDRS 0x468d -+#define FBIOROTATE 0x46a0 /* rotated fb */ -+ -+struct jz_lcd_buffer_addrs_t { -+ int fb_num; -+ unsigned int lcd_desc_phys_addr; -+ unsigned int fb_phys_addr[CONFIG_JZLCD_FRAMEBUFFER_MAX]; -+}; -+ -+ -+/* -+ * LCD panel specific definition -+ */ -+#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW) -+ -+#if defined(CONFIG_JZ4730_PMP) -+#define LCD_RESET_PIN 63 -+#endif -+ -+#define __lcd_special_on() \ -+do { \ -+ __gpio_set_pin(LCD_RESET_PIN); \ -+ __gpio_as_output(LCD_RESET_PIN); \ -+ __gpio_clear_pin(LCD_RESET_PIN); \ -+ udelay(100); \ -+ __gpio_set_pin(LCD_RESET_PIN); \ -+} while (0) -+ -+#endif /* CONFIG_JZLCD_TRULY_TFTG320240DTSW */ -+ -+#if defined(CONFIG_JZLCD_SAMSUNG_LTV350QVF04) -+ -+#if defined(CONFIG_JZ4730_FPRINT) -+#define PortSDI 60 -+#define PortSCL 61 -+#define PortCS 62 -+#define PortRST 63 -+#define PortSht 64 -+#endif -+ -+#if defined(CONFIG_JZ4730_GPS) -+#define PortSDI 74 -+#define PortSCL 72 -+#define PortCS 73 -+#define PortRST 60 -+#define PortSht 59 -+#endif -+ -+#ifndef PortSDI -+#define PortSDI 0 -+#endif -+#ifndef PortSCL -+#define PortSCL 0 -+#endif -+#ifndef PortCS -+#define PortCS 0 -+#endif -+#ifndef PortRST -+#define PortRST 0 -+#endif -+#ifndef PortSht -+#define PortSht 0 -+#endif -+ -+#define __lcd_special_pin_init() \ -+do { \ -+ __gpio_as_output(PortSDI); /* SDI */\ -+ __gpio_as_output(PortSCL); /* SCL */ \ -+ __gpio_as_output(PortCS); /* CS */ \ -+ __gpio_as_output(PortRST); /* Reset */ \ -+ __gpio_as_output(PortSht); /* Shut Down # */ \ -+ __gpio_set_pin(PortCS); \ -+ __gpio_set_pin(PortSCL); \ -+ __gpio_set_pin(PortSDI); \ -+} while (0) -+ -+#define __spi_out(val) \ -+do { \ -+ int __i__; \ -+ unsigned int _t_ = (val); \ -+ __gpio_clear_pin(PortCS); \ -+ udelay(25); \ -+ for (__i__ = 0; __i__ < 24; __i__++ ) { \ -+ __gpio_clear_pin(PortSCL); \ -+ if (_t_ & 0x800000) \ -+ __gpio_set_pin(PortSDI); \ -+ else \ -+ __gpio_clear_pin(PortSDI); \ -+ _t_ <<= 1; \ -+ udelay(25); \ -+ __gpio_set_pin(PortSCL); \ -+ udelay(25); \ -+ } \ -+ __gpio_set_pin(PortCS); \ -+ udelay(25); \ -+ __gpio_set_pin(PortSDI); \ -+ udelay(25); \ -+ __gpio_set_pin(PortSCL); \ -+} while (0) -+ -+#define __spi_id_op_data(rs, rw, val) \ -+ __spi_out((0x1d<<18)|((rs)<<17)|((rw)<<16)|(val)) -+ -+#define __spi_write_reg(reg, val) \ -+do { \ -+ __spi_id_op_data(0, 0, (reg)); \ -+ __spi_id_op_data(1, 0, (val)); \ -+} while (0) -+ -+#define __lcd_special_on() \ -+do { \ -+ __gpio_set_pin(PortSht); \ -+ __gpio_clear_pin(PortRST); \ -+ mdelay(10); \ -+ __gpio_set_pin(PortRST); \ -+ mdelay(1); \ -+ __spi_write_reg(0x09, 0); \ -+ mdelay(10); \ -+ __spi_write_reg(0x09, 0x4000); \ -+ __spi_write_reg(0x0a, 0x2000); \ -+ mdelay(40); \ -+ __spi_write_reg(0x09, 0x4055); \ -+ mdelay(50); \ -+ __spi_write_reg(0x01, 0x409d); \ -+ __spi_write_reg(0x02, 0x0204); \ -+ __spi_write_reg(0x03, 0x0100); \ -+ __spi_write_reg(0x04, 0x3000); \ -+ __spi_write_reg(0x05, 0x4003); \ -+ __spi_write_reg(0x06, 0x000a); \ -+ __spi_write_reg(0x07, 0x0021); \ -+ __spi_write_reg(0x08, 0x0c00); \ -+ __spi_write_reg(0x10, 0x0103); \ -+ __spi_write_reg(0x11, 0x0301); \ -+ __spi_write_reg(0x12, 0x1f0f); \ -+ __spi_write_reg(0x13, 0x1f0f); \ -+ __spi_write_reg(0x14, 0x0707); \ -+ __spi_write_reg(0x15, 0x0307); \ -+ __spi_write_reg(0x16, 0x0707); \ -+ __spi_write_reg(0x17, 0x0000); \ -+ __spi_write_reg(0x18, 0x0004); \ -+ __spi_write_reg(0x19, 0x0000); \ -+ mdelay(60); \ -+ __spi_write_reg(0x09, 0x4a55); \ -+ __spi_write_reg(0x05, 0x5003); \ -+} while (0) -+ -+#define __lcd_special_off() \ -+do { \ -+ __spi_write_reg(0x09, 0x4055); \ -+ __spi_write_reg(0x05, 0x4003); \ -+ __spi_write_reg(0x0a, 0x0000); \ -+ mdelay(10); \ -+ __spi_write_reg(0x09, 0x4000); \ -+ __gpio_clear_pin(PortSht); \ -+} while (0) -+ -+#endif /* CONFIG_JZLCD_SAMSUNG_LTV350QVF04 */ -+ -+#if defined(CONFIG_JZLCD_AUO_A030FL01_V1) -+#if defined(CONFIG_JZ4740_PAVO) /* board pavo */ -+ #define SPEN (32*1+18) /*LCD_CS*/ -+ #define SPCK (32*1+17) /*LCD_SCL*/ -+ #define SPDA (32*2+12) /*LCD_SDA*/ -+ #define LCD_RET (32*2+23) /*use for lcd reset*/ -+#elif defined(CONFIG_JZ4740_LYRA) /* board lyra */ -+ #define SPEN (32*3+19) //LCD_CS -+ #define SPCK (32*3+18) //LCD_SCL -+ #define SPDA (32*3+20) //LCD_SDA -+ #define LCD_RET (32*3+31) //use for lcd reset -+#else -+#error "driver/video/Jzlcd.h, please define SPI pins on your board." -+#endif -+ -+#define __spi_write_reg(reg, val) \ -+ do { \ -+ unsigned char no; \ -+ unsigned short value; \ -+ unsigned char a=0; \ -+ unsigned char b=0; \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ a=reg; \ -+ b=val; \ -+ __gpio_set_pin(SPEN); \ -+ __gpio_clear_pin(SPCK); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPDA); \ -+ __gpio_clear_pin(SPEN); \ -+ udelay(50); \ -+ value=((a<<8)|(b&0xFF)); \ -+ for(no=0;no<16;no++) \ -+ { \ -+ if((value&0x8000)==0x8000){ \ -+ __gpio_set_pin(SPDA);} \ -+ else{ \ -+ __gpio_clear_pin(SPDA); } \ -+ udelay(400); \ -+ __gpio_set_pin(SPCK); \ -+ value=(value<<1); \ -+ udelay(50); \ -+ __gpio_clear_pin(SPCK); \ -+ } \ -+ __gpio_set_pin(SPEN); \ -+ udelay(400); \ -+ } while (0) -+#define __spi_read_reg(reg,val) \ -+ do{ \ -+ unsigned char no; \ -+ unsigned short value; \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ value = ((reg << 0) | (1 << 7)); \ -+ val = 0; \ -+ __gpio_as_output(SPDA); \ -+ __gpio_set_pin(SPEN); \ -+ __gpio_set_pin(SPCK); \ -+ udelay(1); \ -+ __gpio_clear_pin(SPDA); \ -+ __gpio_clear_pin(SPEN); \ -+ udelay(1); \ -+ for (no = 0; no < 16; no++ ) { \ -+ __gpio_clear_pin(SPCK); \ -+ udelay(1); \ -+ if(no < 8) \ -+ { \ -+ if (value & 0x80) /* send data */ \ -+ __gpio_set_pin(SPDA); \ -+ else \ -+ __gpio_clear_pin(SPDA); \ -+ value = (value << 1); \ -+ udelay(1); \ -+ __gpio_set_pin(SPCK); \ -+ udelay(1); \ -+ } \ -+ else \ -+ { \ -+ __gpio_as_input(SPDA); \ -+ udelay(1); \ -+ __gpio_set_pin(SPCK); \ -+ udelay(1); \ -+ val = (val << 1); \ -+ val |= __gpio_get_pin(SPDA); \ -+ udelay(1); \ -+ } \ -+ udelay(400); \ -+ } \ -+ __gpio_as_output(SPDA); \ -+ __gpio_set_pin(SPEN); \ -+ udelay(400); \ -+ } while(0) -+ -+#define __lcd_special_pin_init() \ -+ do { \ -+ __gpio_as_output(SPEN); /* use SPDA */ \ -+ __gpio_as_output(SPCK); /* use SPCK */ \ -+ __gpio_as_output(SPDA); /* use SPDA */ \ -+ __gpio_as_output(LCD_RET); \ -+ udelay(50); \ -+ __gpio_clear_pin(LCD_RET); \ -+ udelay(100); \ -+ __gpio_set_pin(LCD_RET); \ -+ } while (0) -+#define __lcd_special_on() \ -+ do { \ -+ udelay(50); \ -+ __gpio_clear_pin(LCD_RET); \ -+ udelay(100); \ -+ __gpio_set_pin(LCD_RET); \ -+ __spi_write_reg(0x0D, 0x44); \ -+ __spi_write_reg(0x0D, 0x4D); \ -+ __spi_write_reg(0x0B, 0x06); \ -+ __spi_write_reg(0x40, 0xC0); \ -+ __spi_write_reg(0x42, 0x43); \ -+ __spi_write_reg(0x44, 0x28); \ -+ __spi_write_reg(0x0D, 0x4F); \ -+} while (0) -+ -+ #define __lcd_special_off() \ -+ do { \ -+ __spi_write_reg(0x04, 0x4C); \ -+ } while (0) -+ -+#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ -+ -+//#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) -+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) || defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) -+ -+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) /* board pmp */ -+ #if defined(CONFIG_JZ4740_QI_LB60) -+ #define MODE 0xc9 -+ #else -+ #define MODE 0xcd /* 24bit parellel RGB */ -+ #endif -+#endif -+#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) -+#define MODE 0xc9 /* 8bit serial RGB */ -+#endif -+ -+#if defined(CONFIG_JZ4730_PMP) -+ #define SPEN 60 //LCD_SPL -+ #define SPCK 61 //LCD_CLS -+ #define SPDA 62 //LCD_PS -+ #define LCD_RET 63 //LCD_REV //use for lcd reset -+#elif defined(CONFIG_JZ4740_LEO) /* board leo */ -+ #define SPEN (32*1+18) //LCD_SPL -+ #define SPCK (32*1+17) //LCD_CLS -+ #define SPDA (32*2+22) //LCD_PS -+ #define LCD_RET (32*2+23) //LCD_REV //use for lcd reset -+#elif defined(CONFIG_JZ4740_PAVO) /* board pavo */ -+ #define SPEN (32*1+18) //LCD_SPL -+ #define SPCK (32*1+17) //LCD_CLS -+ #define SPDA (32*2+12) //LCD_D12 -+ #define LCD_RET (32*2+23) //LCD_REV, GPC23 -+#elif defined(CONFIG_JZ4740_QI_LB60) -+ #define SPEN (32*2+21) //LCD_SPL -+ #define SPCK (32*2+23) //LCD_CLS -+ #define SPDA (32*2+22) //LCD_D12 -+ #define LCD_RET (32*3+27) -+#if 0 /*old driver*/ -+ #define SPEN (32*1+18) //LCD_SPL -+ #define SPCK (32*1+17) //LCD_CLS -+ #define SPDA (32*2+12) //LCD_D12 -+ #define LCD_RET (32*3+27) //PWM4 //use for lcd reset -+#endif -+#else -+#error "driver/video/Jzlcd.h, please define SPI pins on your board." -+#endif -+ -+ #define __spi_write_reg1(reg, val) \ -+ do { \ -+ unsigned char no;\ -+ unsigned short value;\ -+ unsigned char a=0;\ -+ unsigned char b=0;\ -+ a=reg;\ -+ b=val;\ -+ __gpio_set_pin(SPEN);\ -+ __gpio_set_pin(SPCK);\ -+ __gpio_clear_pin(SPDA);\ -+ __gpio_clear_pin(SPEN);\ -+ udelay(25);\ -+ value=((a<<8)|(b&0xFF));\ -+ for(no=0;no<16;no++)\ -+ {\ -+ __gpio_clear_pin(SPCK);\ -+ if((value&0x8000)==0x8000)\ -+ __gpio_set_pin(SPDA);\ -+ else\ -+ __gpio_clear_pin(SPDA);\ -+ udelay(25);\ -+ __gpio_set_pin(SPCK);\ -+ value=(value<<1); \ -+ udelay(25);\ -+ }\ -+ __gpio_set_pin(SPEN);\ -+ udelay(100);\ -+ } while (0) -+ -+ #define __spi_write_reg(reg, val) \ -+ do {\ -+ __spi_write_reg1((reg<<2|2), val); \ -+ udelay(100); \ -+ }while(0) -+ -+ #define __lcd_special_pin_init() \ -+ do { \ -+ __gpio_as_output(SPEN); /* use SPDA */\ -+ __gpio_as_output(SPCK); /* use SPCK */\ -+ __gpio_as_output(SPDA); /* use SPDA */\ -+ __gpio_as_output(LCD_RET);\ -+ udelay(50);\ -+ __gpio_clear_pin(LCD_RET);\ -+ mdelay(150);\ -+ __gpio_set_pin(LCD_RET);\ -+ } while (0) -+ -+ #define __lcd_special_on() \ -+ do { \ -+ udelay(50);\ -+ __gpio_clear_pin(LCD_RET);\ -+ mdelay(150);\ -+ __gpio_set_pin(LCD_RET);\ -+ mdelay(10);\ -+ __spi_write_reg(0x00, 0x03); \ -+ __spi_write_reg(0x01, 0x40); \ -+ __spi_write_reg(0x02, 0x11); \ -+ __spi_write_reg(0x03, MODE); /* mode */ \ -+ __spi_write_reg(0x04, 0x32); \ -+ __spi_write_reg(0x05, 0x0e); \ -+ __spi_write_reg(0x07, 0x03); \ -+ __spi_write_reg(0x08, 0x08); \ -+ __spi_write_reg(0x09, 0x32); \ -+ __spi_write_reg(0x0A, 0x88); \ -+ __spi_write_reg(0x0B, 0xc6); \ -+ __spi_write_reg(0x0C, 0x20); \ -+ __spi_write_reg(0x0D, 0x20); \ -+ } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -+ -+/* __spi_write_reg(0x02, 0x03); \ -+ __spi_write_reg(0x06, 0x40); \ -+ __spi_write_reg(0x0a, 0x11); \ -+ __spi_write_reg(0x0e, 0xcd); \ -+ __spi_write_reg(0x12, 0x32); \ -+ __spi_write_reg(0x16, 0x0e); \ -+ __spi_write_reg(0x1e, 0x03); \ -+ __spi_write_reg(0x22, 0x08); \ -+ __spi_write_reg(0x26, 0x40); \ -+ __spi_write_reg(0x2a, 0x88); \ -+ __spi_write_reg(0x2e, 0x88); \ -+ __spi_write_reg(0x32, 0x20); \ -+ __spi_write_reg(0x36, 0x20); \ -+*/ -+// } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -+ -+ #define __lcd_special_off() \ -+ do { \ -+ __spi_write_reg(0x00, 0x03); \ -+ } while (0) -+ -+#endif /* CONFIG_JZLCD_FOXCONN_PT035TN01 or CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL */ -+ -+ -+#ifndef __lcd_special_pin_init -+#define __lcd_special_pin_init() -+#endif -+#ifndef __lcd_special_on -+#define __lcd_special_on() -+#endif -+#ifndef __lcd_special_off -+#define __lcd_special_off() -+#endif -+ -+ -+/* -+ * Platform specific definition -+ */ -+ -+#if defined(CONFIG_JZ4730_GPS) -+ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ ; \ -+} while (0) -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __lcd_special_pin_init(); \ -+ __gpio_as_output(94); /* PWM0 pin */ \ -+ __gpio_as_output(95); /* PWM1 pin */ \ -+} while (0) -+ -+#define __lcd_display_on() \ -+do { \ -+ __lcd_special_on(); \ -+ __gpio_set_pin(94); /* PWM0 pin */ \ -+ __gpio_set_pin(95); /* PWM1 pin */ \ -+ __lcd_set_backlight_level(8); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_special_off(); \ -+} while (0) -+ -+#endif /* CONFIG_JZ4730_GPS */ -+ -+#if defined(CONFIG_JZ4730_FPRINT) -+ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ REG_PWM_DUT(0) = n; \ -+ REG_PWM_PER(0) = 7; \ -+ REG_PWM_CTR(0) = 0x81; \ -+} while (0) -+ -+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __lcd_special_pin_init();\ -+ __gpio_as_pwm();\ -+ __lcd_set_backlight_level(8);\ -+} while (0) -+ -+#define __lcd_display_on() \ -+do { \ -+ __lcd_set_backlight_level(8); \ -+ __lcd_special_on();\ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_set_backlight_level(0); \ -+ __lcd_special_off();\ -+} while (0) -+ -+#else -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __gpio_as_output(GPIO_DISP_OFF_N); \ -+ __gpio_as_pwm(); \ -+ __lcd_set_backlight_level(8); \ -+} while (0) -+ -+#define __lcd_display_on() \ -+do { \ -+ __lcd_set_backlight_level(8); \ -+ __gpio_set_pin(GPIO_DISP_OFF_N); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_set_backlight_level(0); \ -+ __gpio_clear_pin(GPIO_DISP_OFF_N); \ -+} while (0) -+#endif -+ -+#endif /* CONFIG_JZ4730_FPRINT */ -+ -+#if defined(CONFIG_JZ4730_LIBRA) -+ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+} while (0) -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __lcd_special_pin_init(); \ -+ __gpio_clear_pin(100); \ -+ __gpio_as_output(100); \ -+ __gpio_as_output(94); \ -+ __gpio_as_output(95); \ -+ __lcd_set_backlight_level(8); \ -+} while (0) -+ -+#define __lcd_display_on() \ -+do { \ -+ __lcd_special_on(); \ -+ __gpio_set_pin(100); \ -+ __gpio_set_pin(94); \ -+ __gpio_set_pin(95); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_special_off(); \ -+ __gpio_clear_pin(100); \ -+ __gpio_clear_pin(94); \ -+ __gpio_clear_pin(95); \ -+} while (0) -+ -+#endif /* CONFIG_JZ4730_LIBRA */ -+ -+#if defined(CONFIG_JZ4730_PMP) -+ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ REG_PWM_DUT(0) = n; \ -+ REG_PWM_PER(0) = 7; \ -+ REG_PWM_CTR(0) = 0x81; \ -+} while (0) -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __gpio_as_output(GPIO_DISP_OFF_N); \ -+ __gpio_as_pwm(); \ -+ __lcd_set_backlight_level(10); \ -+ __lcd_special_pin_init(); \ -+} while (0) -+ -+#define __lcd_display_on() \ -+do { \ -+ __lcd_special_on(); \ -+ __lcd_set_backlight_level(8); \ -+ __gpio_set_pin(GPIO_DISP_OFF_N); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_special_off(); \ -+ __lcd_set_backlight_level(0); \ -+ __gpio_clear_pin(GPIO_DISP_OFF_N); \ -+} while (0) -+ -+#endif /* CONFIG_JZ4730_PMP */ -+ -+/*#if defined(CONFIG_JZ4740_LEO) || defined(CONFIG_JZ4740_PAVO)*/ -+#if defined(CONFIG_SOC_JZ4740) -+#if defined(CONFIG_JZ4740_PAVO) || defined(CONFIG_JZ4740_LYRA) || defined(CONFIG_JZ4740_QI_LB60) -+#define GPIO_PWM 123 /* GP_D27 */ -+#define PWM_CHN 4 /* pwm channel */ -+#define PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __lcd_set_backlight_level(n)\ -+do { \ -+__gpio_as_output(32*3+27); \ -+__gpio_set_pin(32*3+27); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+__gpio_as_output(GPIO_PWM); \ -+__gpio_clear_pin(GPIO_PWM); \ -+} while (0) -+ -+#elif defined(CONFIG_JZ4720_VIRGO) -+#define GPIO_PWM 119 /* GP_D23 */ -+#define PWM_CHN 0 /* pwm channel */ -+#define PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+/*#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_pwm(0); \ -+ __tcu_disable_pwm_output(PWM_CHN); \ -+ __tcu_stop_counter(PWM_CHN); \ -+ __tcu_init_pwm_output_high(PWM_CHN); \ -+ __tcu_set_pwm_output_shutdown_abrupt(PWM_CHN); \ -+ __tcu_select_clk_div1(PWM_CHN); \ -+ __tcu_mask_full_match_irq(PWM_CHN); \ -+ __tcu_mask_half_match_irq(PWM_CHN); \ -+ __tcu_set_count(PWM_CHN,0); \ -+ __tcu_set_full_data(PWM_CHN,__cpm_get_extalclk()/1000); \ -+ __tcu_set_half_data(PWM_CHN,__cpm_get_extalclk()/1000*n/100); \ -+ __tcu_enable_pwm_output(PWM_CHN); \ -+ __tcu_select_extalclk(PWM_CHN); \ -+ __tcu_start_counter(PWM_CHN); \ -+} while (0) -+*/ -+ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_output(GPIO_PWM); \ -+ __gpio_set_pin(GPIO_PWM); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+__gpio_as_output(GPIO_PWM); \ -+__gpio_clear_pin(GPIO_PWM); \ -+} while (0) -+ -+#else -+#define __lcd_set_backlight_level(n) -+#define __lcd_close_backlight() -+ -+#endif /* #if defined(CONFIG_MIPS_JZ4740_PAVO) */ -+ -+#define __lcd_display_pin_init() \ -+do { \ -+ __gpio_as_output(GPIO_DISP_OFF_N); \ -+ __cpm_start_tcu(); \ -+ __lcd_special_pin_init(); \ -+} while (0) -+/* __lcd_set_backlight_level(100); \*/ -+#define __lcd_display_on() \ -+do { \ -+ __gpio_set_pin(GPIO_DISP_OFF_N); \ -+ __lcd_special_on(); \ -+ __lcd_set_backlight_level(20); \ -+} while (0) -+ -+#define __lcd_display_off() \ -+do { \ -+ __lcd_special_off(); \ -+ __lcd_close_backlight(); \ -+ __gpio_clear_pin(GPIO_DISP_OFF_N); \ -+} while (0) -+ -+#endif /* CONFIG_MIPS_JZ4740_LEO */ -+ -+#if defined(CONFIG_JZLCD_MSTN_240x128) -+ -+#if 0 /* The final version does not use software emulation of VCOM. */ -+ -+#define GPIO_VSYNC 59 -+#define GPIO_VCOM 90 -+ -+#define REG_VCOM REG_GPIO_GPDR((GPIO_VCOM>>5)) -+#define VCOM_BIT (1 << (GPIO_VCOM & 0x1f)) -+static unsigned int vcom_static; -+static void vsync_irq(int irq, void *dev_id, struct pt_regs *reg) -+{ -+ vcom_static = REG_VCOM; -+ vcom_static ^= VCOM_BIT; -+ REG_VCOM = vcom_static; -+} -+ -+#define __lcd_display_pin_init() \ -+ __gpio_as_irq_rise_edge(GPIO_VSYNC); \ -+ __gpio_as_output(GPIO_VCOM); \ -+ { \ -+ static int inited = 0; \ -+ if (!inited) { \ -+ inited = 1; \ -+ if (request_irq(IRQ_GPIO_0 + GPIO_VSYNC, vsync_irq, SA_INTERRUPT, \ -+ "vsync", 0)) { \ -+ err = -EBUSY; \ -+ goto failed; \ -+ }}} -+ -+#endif -+ -+/* We uses AC BIAs pin to generate VCOM signal, so above code should be removed. -+ */ -+#endif -+/***************************************************************************** -+ * LCD display pin dummy macros -+ *****************************************************************************/ -+#ifndef __lcd_display_pin_init -+#define __lcd_display_pin_init() -+#endif -+#ifndef __lcd_display_on -+#define __lcd_display_on() -+#endif -+#ifndef __lcd_display_off -+#define __lcd_display_off() -+#endif -+#ifndef __lcd_set_backlight_level -+#define __lcd_set_backlight_level(n) -+#endif -+ -+#endif /* __JZLCD_H__ */ -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index b1ccc04..64eb1ab 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -45,6 +45,15 @@ comment "Watchdog Device Drivers" - - # Architecture Independent - -+config JZ_WDT -+ bool 'JzSoC On-Chip watchdog' -+ help -+ Watchdog timer embedded into JZSOC chips. This will reboot your -+ system when the timeout is reached. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called jz_wdt. -+ - config SOFT_WATCHDOG - tristate "Software watchdog" - help -diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile -index 3d77429..e217064 100644 ---- a/drivers/watchdog/Makefile -+++ b/drivers/watchdog/Makefile -@@ -10,6 +10,9 @@ - # that also fails then you can fall back to the software watchdog - # to give you some cover. - -+# JZ-watchdog timer -+obj-$(CONFIG_JZ_WDT) += jz_wdt.o -+ - # ISA-based Watchdog Cards - obj-$(CONFIG_PCWATCHDOG) += pcwd.o - obj-$(CONFIG_MIXCOMWD) += mixcomwd.o -diff --git a/drivers/watchdog/jz_wdt.c b/drivers/watchdog/jz_wdt.c -new file mode 100644 -index 0000000..593bb87 ---- /dev/null -+++ b/drivers/watchdog/jz_wdt.c -@@ -0,0 +1,203 @@ -+/* -+ * linux/drivers/char/jz_wdt.c -+ * -+ * Watchdog driver for the Ingenic JzSOC -+ * -+ * Author: Wei Jianli -+ * -+ * 2005 (c) Ingenic Semiconductor. This file is licensed under the -+ * terms of the GNU General Public License version 2. This program is -+ * licensed "as is" without any warranty of any kind, whether express -+ * or implied. -+ */ -+ -+#include -+//#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ -+ -+static unsigned int timer_margin = TIMER_MARGIN; /* in seconds */ -+static unsigned int timer_rate; -+static unsigned int pre_margin; -+static unsigned long jz_wdt_users = 0; -+ -+#ifdef MODULE -+MODULE_PARM(timer_margin, "i"); -+#endif -+ -+static void -+jz_wdt_ping(void) -+{ -+ printk("jz_wdt_ping\n"); -+ /* reload counter with (new) margin */ -+#ifdef CONFIG_SOC_JZ4730 -+ pre_margin = 0xffffffff - timer_rate * timer_margin; -+ __wdt_set_count(pre_margin); -+#endif -+#ifdef CONFIG_SOC_JZ4740 -+ pre_margin = timer_rate * timer_margin; -+ __wdt_set_count(0); -+ __wdt_set_data(pre_margin); -+#endif -+} -+ -+/* -+ * Allow only one person to hold it open -+ */ -+ -+static int -+jz_wdt_open(struct inode *inode, struct file *file) -+{ -+ if (test_and_set_bit(1, &jz_wdt_users)) -+ return -EBUSY; -+ -+ printk("jz_wdt_open\n"); -+#ifdef CONFIG_SOC_JZ4730 -+ if (REG_CPM_OCR & CPM_OCR_EXT_RTC_CLK) -+ timer_rate = 32768; -+ else -+ timer_rate = JZ_EXTAL/128; -+#endif -+ -+#ifdef CONFIG_SOC_JZ4740 -+ /* Initialize the wdt clocks */ -+ __wdt_select_rtcclk(); -+ __wdt_select_clk_div1024(); -+ __tcu_start_wdt_clock(); -+ timer_rate = 32; /* 32768 / 1024 */ -+#endif -+ -+ jz_wdt_ping(); -+ __wdt_start(); -+ -+ return 0; -+} -+ -+static int -+jz_wdt_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * Shut off the timer. -+ * Lock it in if it's a module and we defined ...NOWAYOUT -+ */ -+ jz_wdt_ping(); -+#ifndef CONFIG_WATCHDOG_NOWAYOUT -+ /* SW can't stop wdt once it was started */ -+#endif -+ jz_wdt_users = 0; -+ return 0; -+} -+ -+static ssize_t -+jz_wdt_write(struct file *file, const char *data, size_t len, loff_t * ppos) -+{ -+ /* Can't seek (pwrite) on this device */ -+ if (ppos != &file->f_pos) -+ return -ESPIPE; -+ -+ printk("jz_wdt_write\n"); -+ -+ /* Refresh counter */ -+ if (len) { -+ jz_wdt_ping(); -+ return 1; -+ } -+ return 0; -+} -+ -+static int -+jz_wdt_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ int new_margin; -+ static struct watchdog_info ident = { -+ .identity = "JzSOC Watchdog", -+ .options = WDIOF_SETTIMEOUT, -+ .firmware_version = 0, -+ }; -+ -+ switch (cmd) { -+ default: -+ return -ENOIOCTLCMD; -+ case WDIOC_GETSUPPORT: -+ return copy_to_user((struct watchdog_info *) arg, &ident, -+ sizeof (ident)); -+ case WDIOC_GETSTATUS: -+ return put_user(0, (int *) arg); -+ case WDIOC_GETBOOTSTATUS: -+#ifdef CONFIG_SOC_JZ4730 -+ return put_user(REG_CPM_RSTR, (int *) arg); -+#endif -+#ifdef CONFIG_SOC_JZ4740 -+ return put_user(REG_RTC_HWRSR, (int *) arg); -+#endif -+ case WDIOC_KEEPALIVE: -+ jz_wdt_ping(); -+ return 0; -+ case WDIOC_SETTIMEOUT: -+ if (get_user(new_margin, (int *) arg)) -+ return -EFAULT; -+ if (new_margin < 1) -+ return -EINVAL; -+ timer_margin = new_margin; -+ jz_wdt_ping(); -+ /* Fall */ -+ case WDIOC_GETTIMEOUT: -+ return put_user(timer_margin, (int *) arg); -+ } -+} -+ -+static struct file_operations jz_wdt_fops = { -+ .owner = THIS_MODULE, -+ .write = jz_wdt_write, -+ .ioctl = jz_wdt_ioctl, -+ .open = jz_wdt_open, -+ .release = jz_wdt_release, -+}; -+ -+static struct miscdevice jz_wdt_miscdev = { -+ .minor = WATCHDOG_MINOR, -+ .name = "jz_wdt", -+ .fops = &jz_wdt_fops -+}; -+ -+static int __init -+jz_wdt_init(void) -+{ -+ int ret; -+ -+ ret = misc_register(&jz_wdt_miscdev); -+ -+ if (ret) -+ return ret; -+ -+ printk("JzSOC Watchdog Timer: timer margin %d sec\n", timer_margin); -+ -+ return 0; -+} -+ -+static void __exit -+jz_wdt_exit(void) -+{ -+ misc_deregister(&jz_wdt_miscdev); -+} -+ -+module_init(jz_wdt_init); -+module_exit(jz_wdt_exit); -+ -+MODULE_AUTHOR("Wei Jianli"); -+MODULE_LICENSE("GPL"); -diff --git a/include/asm-mips/jzsoc.h b/include/asm-mips/jzsoc.h -new file mode 100644 -index 0000000..54df338 ---- /dev/null -+++ b/include/asm-mips/jzsoc.h -@@ -0,0 +1,49 @@ -+/* -+ * linux/include/asm-mips/jzsoc.h -+ * -+ * Ingenic's JZXXXX SoC common include. -+ * -+ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZSOC_H__ -+#define __ASM_JZSOC_H__ -+ -+/* -+ * SoC include -+ */ -+ -+#ifdef CONFIG_SOC_JZ4730 -+#include -+#endif -+ -+#ifdef CONFIG_SOC_JZ4740 -+#include -+#endif -+ -+#ifdef CONFIG_SOC_JZ4750 -+#include -+#endif -+ -+#ifdef CONFIG_SOC_JZ4750D -+#include -+#endif -+ -+/* -+ * Generic I/O routines -+ */ -+#define readb(addr) (*(volatile unsigned char *)(addr)) -+#define readw(addr) (*(volatile unsigned short *)(addr)) -+#define readl(addr) (*(volatile unsigned int *)(addr)) -+ -+#define writeb(b,addr) ((*(volatile unsigned char *)(addr)) = (b)) -+#define writew(b,addr) ((*(volatile unsigned short *)(addr)) = (b)) -+#define writel(b,addr) ((*(volatile unsigned int *)(addr)) = (b)) -+ -+#endif /* __ASM_JZSOC_H__ */ -diff --git a/include/asm-mips/mach-jz4730/board-pmp.h b/include/asm-mips/mach-jz4730/board-pmp.h -new file mode 100644 -index 0000000..44475d2 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/board-pmp.h -@@ -0,0 +1,83 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/board-pmp.h -+ * -+ * JZ4730-based PMP board ver 2.x definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_PMP_H__ -+#define __ASM_JZ4730_PMP_H__ -+ -+/*====================================================================== -+ * EXTAL frequency -+ */ -+#define JZ_EXTAL 12000000 /* EXTAL: 12 MHz */ -+#define JZ_EXTAL2 32768 /* EXTAL2: 32.768 KHz */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_PW_I 97 -+#define GPIO_PW_O 66 -+#define GPIO_LED_EN 92 -+#define GPIO_DISP_OFF_N 93 -+#define GPIO_PWM0 94 -+#define GPIO_RTC_IRQ 96 -+#define GPIO_USB_CLK_EN 29 -+#define GPIO_CHARG_STAT 125 -+#define GPIO_TS_PENIRQ 98 -+#define GPIO_UDC_HOTPLUG 86 -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+#define MSC_WP_PIN 82 -+#define MSC_POWEREN_PIN 91 -+#define MSC_HOTPLUG_PIN 90 -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + MSC_HOTPLUG_PIN) -+ -+/* enable slot power */ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_input(MSC_WP_PIN); \ -+ __gpio_as_output(MSC_POWEREN_PIN); \ -+} while (0) -+ -+/* enable slot power */ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(MSC_POWEREN_PIN); \ -+} while (0) -+ -+/* disable slot power */ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(MSC_POWEREN_PIN); \ -+} while (0) -+ -+/* detect card insertion or not */ -+#define __msc_card_detected(slot) \ -+({ \ -+ int ret; \ -+ if (slot == 0) { \ -+ __gpio_mask_irq(MSC_HOTPLUG_IRQ); \ -+ __gpio_as_input(MSC_HOTPLUG_PIN); \ -+ ret = __gpio_get_pin(MSC_HOTPLUG_PIN); \ -+ __gpio_unmask_irq(MSC_HOTPLUG_IRQ); \ -+ } \ -+ else { \ -+ ret = 1; \ -+ } \ -+ ret = !ret; \ -+ ret; \ -+}) -+ -+#endif /* __ASM_JZ4730_PMP_H__ */ -diff --git a/include/asm-mips/mach-jz4730/clock.h b/include/asm-mips/mach-jz4730/clock.h -new file mode 100644 -index 0000000..16971d0 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/clock.h -@@ -0,0 +1,184 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/clock.h -+ * -+ * JZ4730 clocks definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_CLOCK_H__ -+#define __ASM_JZ4730_CLOCK_H__ -+ -+#ifndef JZ_EXTAL -+#define JZ_EXTAL 3686400 -+#endif -+ -+#ifndef JZ_EXTAL2 -+#define JZ_EXTAL2 32768 -+#endif -+ -+/* -+ * JZ4730 clocks structure -+ */ -+typedef struct { -+ unsigned int iclk; /* CPU core clock */ -+ unsigned int sclk; /* AHB bus clock */ -+ unsigned int mclk; /* Memory bus clock */ -+ unsigned int pclk; /* APB bus clock */ -+ unsigned int devclk; /* Devcie clock to specific modules */ -+ unsigned int rtcclk; /* RTC module clock */ -+ unsigned int uartclk; /* UART module clock */ -+ unsigned int lcdclk; /* LCD module clock */ -+ unsigned int pixclk; /* LCD pixel clock */ -+ unsigned int usbclk; /* USB module clock */ -+ unsigned int i2sclk; /* I2S module clock */ -+ unsigned int mscclk; /* MMC/SD module clock */ -+} jz_clocks_t; -+ -+extern jz_clocks_t jz_clocks; -+ -+ -+static __inline__ unsigned int __cpm_get_pllout(void) -+{ -+ unsigned int nf, nr, no, pllout; -+ unsigned long plcr = REG_CPM_PLCR1; -+ unsigned long od[4] = {1, 2, 2, 4}; -+ if (plcr & CPM_PLCR1_PLL1EN) { -+ nf = (plcr & CPM_PLCR1_PLL1FD_MASK) >> CPM_PLCR1_PLL1FD_BIT; -+ nr = (plcr & CPM_PLCR1_PLL1RD_MASK) >> CPM_PLCR1_PLL1RD_BIT; -+ no = od[((plcr & CPM_PLCR1_PLL1OD_MASK) >> CPM_PLCR1_PLL1OD_BIT)]; -+ pllout = (JZ_EXTAL) / ((nr+2) * no) * (nf+2); -+ } else -+ pllout = JZ_EXTAL; -+ return pllout; -+} -+ -+static __inline__ unsigned int __cpm_get_iclk(void) -+{ -+ unsigned int iclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned long cfcr = REG_CPM_CFCR; -+ unsigned long plcr = REG_CPM_PLCR1; -+ if (plcr & CPM_PLCR1_PLL1EN) -+ iclk = __cpm_get_pllout() / -+ div[(cfcr & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT]; -+ else -+ iclk = JZ_EXTAL; -+ return iclk; -+} -+ -+static __inline__ unsigned int __cpm_get_sclk(void) -+{ -+ unsigned int sclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned long cfcr = REG_CPM_CFCR; -+ unsigned long plcr = REG_CPM_PLCR1; -+ if (plcr & CPM_PLCR1_PLL1EN) -+ sclk = __cpm_get_pllout() / -+ div[(cfcr & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT]; -+ else -+ sclk = JZ_EXTAL; -+ return sclk; -+} -+ -+static __inline__ unsigned int __cpm_get_mclk(void) -+{ -+ unsigned int mclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned long cfcr = REG_CPM_CFCR; -+ unsigned long plcr = REG_CPM_PLCR1; -+ if (plcr & CPM_PLCR1_PLL1EN) -+ mclk = __cpm_get_pllout() / -+ div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT]; -+ else -+ mclk = JZ_EXTAL; -+ return mclk; -+} -+ -+static __inline__ unsigned int __cpm_get_pclk(void) -+{ -+ unsigned int devclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned long cfcr = REG_CPM_CFCR; -+ unsigned long plcr = REG_CPM_PLCR1; -+ if (plcr & CPM_PLCR1_PLL1EN) -+ devclk = __cpm_get_pllout() / -+ div[(cfcr & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT]; -+ else -+ devclk = JZ_EXTAL; -+ return devclk; -+} -+ -+static __inline__ unsigned int __cpm_get_lcdclk(void) -+{ -+ unsigned int lcdclk; -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ unsigned long cfcr = REG_CPM_CFCR; -+ unsigned long plcr = REG_CPM_PLCR1; -+ if (plcr & CPM_PLCR1_PLL1EN) -+ lcdclk = __cpm_get_pllout() / -+ div[(cfcr & CPM_CFCR_LFR_MASK) >> CPM_CFCR_LFR_BIT]; -+ else -+ lcdclk = JZ_EXTAL; -+ return lcdclk; -+} -+ -+static __inline__ unsigned int __cpm_get_pixclk(void) -+{ -+ unsigned int pixclk; -+ unsigned long cfcr2 = REG_CPM_CFCR2; -+ pixclk = __cpm_get_pllout() / (cfcr2 + 1); -+ return pixclk; -+} -+ -+static __inline__ unsigned int __cpm_get_devclk(void) -+{ -+ return JZ_EXTAL; -+} -+ -+static __inline__ unsigned int __cpm_get_rtcclk(void) -+{ -+ return JZ_EXTAL2; -+} -+ -+static __inline__ unsigned int __cpm_get_uartclk(void) -+{ -+ return JZ_EXTAL; -+} -+ -+static __inline__ unsigned int __cpm_get_usbclk(void) -+{ -+ unsigned int usbclk; -+ unsigned long cfcr = REG_CPM_CFCR; -+ if (cfcr & CPM_CFCR_UCS) -+ usbclk = 48000000; -+ else -+ usbclk = __cpm_get_pllout() / -+ (((cfcr &CPM_CFCR_UFR_MASK) >> CPM_CFCR_UFR_BIT) + 1); -+ return usbclk; -+} -+ -+static __inline__ unsigned int __cpm_get_i2sclk(void) -+{ -+ unsigned int i2sclk; -+ unsigned long cfcr = REG_CPM_CFCR; -+ i2sclk = __cpm_get_pllout() / -+ ((cfcr & CPM_CFCR_I2S) ? 2: 1); -+ return i2sclk; -+} -+ -+static __inline__ unsigned int __cpm_get_mscclk(void) -+{ -+ if (REG_CPM_CFCR & CPM_CFCR_MSC) -+ return 24000000; -+ else -+ return 16000000; -+} -+ -+#endif /* __ASM_JZ4730_CLOCK_H__ */ -diff --git a/include/asm-mips/mach-jz4730/dma.h b/include/asm-mips/mach-jz4730/dma.h -new file mode 100644 -index 0000000..511152e ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/dma.h -@@ -0,0 +1,272 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/dma.h -+ * -+ * JZ4730 DMA definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_DMA_H__ -+#define __ASM_JZ4730_DMA_H__ -+ -+#include -+#include /* need byte IO */ -+#include /* And spinlocks */ -+#include -+#include -+ -+#define DMA_UNIT_32 32 -+#define DMA_UNIT_16 16 -+ -+ -+/* block-mode EOP: high DREQ: high DACK: low*/ -+#define DMA_BLOCK_CONF \ -+ DMAC_DCCSR_TM | \ -+ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN | \ -+ DMAC_DCCSR_ERDM_HLEVEL | DMAC_DCCSR_EACKS -+ -+/* single-mode EOP: high DREQ: high DACK: low */ -+#define DMA_SINGLE_CONF \ -+ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN | \ -+ DMAC_DCCSR_ERDM_HLEVEL | DMAC_DCCSR_EACKS -+ -+#define DMA_8bit_RX_CONF \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_8 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_8bit_TX_CONF \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_8 | \ -+ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_16bit_RX_CONF \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_16bit_TX_CONF \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_16 | \ -+ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_32bit_RX_CONF \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_32b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_32bit_TX_CONF \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_32b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_16BYTE_RX_CONF \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_8 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_16BYTE_TX_CONF \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_8 | \ -+ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_AIC_32_16BYTE_TX_CMD \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_AIC_32_16BYTE_RX_CMD \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -+ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_AIC_16BIT_TX_CMD \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -+ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_AIC_16BIT_RX_CMD \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -+ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_RX_CMD \ -+ DMAC_DCCSR_DAM | \ -+ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -+ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_TX_CMD \ -+ DMAC_DCCSR_SAM | \ -+ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -+ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -+ -+/* DMA Device ID's follow */ -+enum { -+ DMA_ID_UART0_TX = 0, -+ DMA_ID_UART0_RX, -+ DMA_ID_UART1_TX, -+ DMA_ID_UART1_RX, -+ DMA_ID_UART2_TX, -+ DMA_ID_UART2_RX, -+ DMA_ID_UART3_TX, -+ DMA_ID_UART3_RX, -+ DMA_ID_SSI_TX, -+ DMA_ID_SSI_RX, -+ DMA_ID_MSC_TX, -+ DMA_ID_MSC_RX, -+ DMA_ID_AIC_TX, -+ DMA_ID_AIC_RX, -+ DMA_ID_BLOCK, /* DREQ */ -+ DMA_ID_SINGLE, /* DREQ */ -+ DMA_ID_PCMCIA0_TX, -+ DMA_ID_PCMCIA0_RX, -+ DMA_ID_PCMCIA1_TX, -+ DMA_ID_PCMCIA2_RX, -+ DMA_ID_AUTO, -+ DMA_ID_RAW_SET, -+ NUM_DMA_DEV -+}; -+ -+/* dummy DCCSR bit, i386 style DMA macros compitable */ -+#define DMA_MODE_READ 0 /* I/O to memory, no autoinit, -+ * increment, single mode */ -+#define DMA_MODE_WRITE 1 /* memory to I/O, no autoinit, -+ * increment, single mode */ -+#define DMA_MODE_CASCADE 2 /* pass thru DREQ->HRQ, -+ * DACK<-HLDA only */ -+#define DMA_AUTOINIT 3 -+#define DMA_MODE_MASK 3 -+ -+struct jz_dma_chan { -+ int dev_id; /* this channel is allocated if >=0, -+ * free otherwise */ -+ unsigned int io; -+ const char *dev_str; -+ int irq; -+ void *irq_dev; -+ unsigned int fifo_addr; -+ unsigned int mode; -+ unsigned int source; -+}; -+ -+extern struct jz_dma_chan jz_dma_table[]; -+ -+extern int jz_request_dma(int dev_id, -+ const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id); -+extern void jz_free_dma(unsigned int dmanr); -+ -+extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data); -+extern void dump_jz_dma_channel(unsigned int dmanr); -+ -+extern void enable_dma(unsigned int dmanr); -+extern void disable_dma(unsigned int dmanr); -+extern void set_dma_addr(unsigned int dmanr, unsigned int a); -+extern void set_dma_count(unsigned int dmanr, unsigned int count); -+extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -+extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern int get_dma_residue(unsigned int dmanr); -+ -+extern spinlock_t dma_spin_lock; -+ -+static __inline__ unsigned long claim_dma_lock(void) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&dma_spin_lock, flags); -+ return flags; -+} -+ -+static __inline__ void release_dma_lock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&dma_spin_lock, flags); -+} -+ -+/* Clear the 'DMA Pointer Flip Flop'. -+ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -+ */ -+#define clear_dma_ff(channel) -+ -+static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -+{ -+ if (dmanr > NUM_DMA -+ || jz_dma_table[dmanr].dev_id < 0) -+ return NULL; -+ return &jz_dma_table[dmanr]; -+} -+ -+static __inline__ int dma_halted(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 1; -+ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -+} -+ -+static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ return chan->mode; -+} -+ -+static __inline__ void clear_dma_done(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+} -+ -+static __inline__ void clear_dma_halt(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -+ REG_DMAC_DMACR &= ~(DMAC_DMACR_HTR); -+} -+static __inline__ void clear_dma_flag(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+ REG_DMAC_DMACR &= ~(DMAC_DMACR_HTR | DMAC_DMACR_AER); -+} -+ -+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -+{ -+} -+ -+static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ unsigned long dccsr; -+ if (!chan) -+ return 0; -+ -+ dccsr = REG_DMAC_DCCSR(chan->io); -+ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -+} -+ -+static __inline__ int get_dma_done_irq(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return -1; -+ -+ return chan->irq; -+} -+ -+#endif /* __ASM_JZ4730_DMA_H__ */ -diff --git a/include/asm-mips/mach-jz4730/jz4730.h b/include/asm-mips/mach-jz4730/jz4730.h -new file mode 100644 -index 0000000..5688f01 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/jz4730.h -@@ -0,0 +1,40 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/jz4730.h -+ * -+ * JZ4730 common definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_H__ -+#define __ASM_JZ4730_H__ -+ -+#include -+#include -+#include -+#include -+ -+/*------------------------------------------------------------------ -+ * Platform definitions -+ */ -+#ifdef CONFIG_JZ4730_PMP -+#include -+#endif -+ -+/* Add other platform definition here ... */ -+ -+ -+/*------------------------------------------------------------------ -+ * Follows are related to platform definitions -+ */ -+ -+#include -+#include -+ -+#endif /* __ASM_JZ4730_H__ */ -diff --git a/include/asm-mips/mach-jz4730/misc.h b/include/asm-mips/mach-jz4730/misc.h -new file mode 100644 -index 0000000..ea01474 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/misc.h -@@ -0,0 +1,28 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/misc.h -+ * -+ * JZ4730 miscillaneous definitions. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_MISC_H__ -+#define __ASM_JZ4730_MISC_H__ -+ -+/* -+ * I2C routines -+ */ -+ -+extern void i2c_open(void); -+extern void i2c_close(void); -+extern void i2c_setclk(unsigned int i2cclk); -+extern int i2c_read(unsigned char, unsigned char *, unsigned char, int); -+extern int i2c_write(unsigned char, unsigned char *, unsigned char, int); -+ -+#endif /* __ASM_JZ4730_MISC_H__ */ -diff --git a/include/asm-mips/mach-jz4730/ops.h b/include/asm-mips/mach-jz4730/ops.h -new file mode 100644 -index 0000000..625419e ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/ops.h -@@ -0,0 +1,2541 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/ops.h -+ * -+ * JZ4730 module operations definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_OPS_H__ -+#define __ASM_JZ4730_OPS_H__ -+ -+/*************************************************************************** -+ * MSC -+ ***************************************************************************/ -+ -+#define __msc_start_op() \ -+ ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -+ -+#define __msc_set_resto(to) ( REG_MSC_RESTO = to ) -+#define __msc_set_rdto(to) ( REG_MSC_RDTO = to ) -+#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd ) -+#define __msc_set_arg(arg) ( REG_MSC_ARG = arg ) -+#define __msc_set_nob(nob) ( REG_MSC_NOB = nob ) -+#define __msc_get_nob() ( REG_MSC_NOB ) -+#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len ) -+#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat ) -+#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT ) -+#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT ) -+ -+#define __msc_set_cmdat_bus_width1() \ -+do { \ -+ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_bus_width4() \ -+do { \ -+ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN ) -+#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT ) -+#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY ) -+#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN ) -+ -+/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -+#define __msc_set_cmdat_res_format(r) \ -+do { \ -+ REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -+ REG_MSC_CMDAT |= (r); \ -+} while(0) -+ -+#define __msc_clear_cmdat() \ -+ REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -+ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -+ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -+ -+#define __msc_get_imask() ( REG_MSC_IMASK ) -+#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff ) -+#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 ) -+#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES ) -+#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES ) -+#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE ) -+#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE ) -+ -+/* n=0,1,2,3,4,5,6,7 */ -+#define __msc_set_clkrt(n) \ -+do { \ -+ REG_MSC_CLKRT = n; \ -+} while(0) -+ -+#define __msc_get_ireg() ( REG_MSC_IREG ) -+#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ ) -+#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ ) -+#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE ) -+#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE ) -+ -+#define __msc_get_stat() ( REG_MSC_STAT ) -+#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0) -+#define __msc_stat_crc_err() \ -+ ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -+#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR ) -+#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR ) -+#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES ) -+#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES ) -+#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ ) -+ -+#define __msc_rd_resfifo() ( REG_MSC_RES ) -+#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO ) -+#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v ) -+ -+#define __msc_reset() \ -+do { \ -+ REG_MSC_STRPCL = MSC_STRPCL_RESET; \ -+ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \ -+} while (0) -+ -+#define __msc_start_clk() \ -+do { \ -+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \ -+} while (0) -+ -+#define __msc_stop_clk() \ -+do { \ -+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -+} while (0) -+ -+#define MMC_CLK 19169200 -+#define SD_CLK 24576000 -+ -+/* msc_clk should little than pclk and little than clk retrieve from card */ -+#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -+do { \ -+ unsigned int rate, pclk, i; \ -+ pclk = dev_clk; \ -+ rate = type?SD_CLK:MMC_CLK; \ -+ if (msc_clk && msc_clk < pclk) \ -+ pclk = msc_clk; \ -+ i = 0; \ -+ while (pclk < rate) \ -+ { \ -+ i ++; \ -+ rate >>= 1; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+/* divide rate to little than or equal to 400kHz */ -+#define __msc_calc_slow_clk_divisor(type, lv) \ -+do { \ -+ unsigned int rate, i; \ -+ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -+ i = 0; \ -+ while (rate > 0) \ -+ { \ -+ rate >>= 1; \ -+ i ++; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+/*************************************************************************** -+ * RTC -+ ***************************************************************************/ -+ -+#define __rtc_start() ( REG_RTC_RCR |= RTC_RCR_START ) -+#define __rtc_stop() ( REG_RTC_RCR &= ~RTC_RCR_START ) -+ -+#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -+#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -+#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -+#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -+ -+#define __rtc_enable_1hz_irq() ( REG_RTC_RCR |= RTC_RCR_HZIE ) -+#define __rtc_disable_1hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_HZIE ) -+ -+#define __rtc_is_alarm_flag() ( REG_RTC_RCR & RTC_RCR_AF ) -+#define __rtc_is_1hz_flag() ( REG_RTC_RCR & RTC_RCR_HZ ) -+#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -+#define __rtc_clear_1hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_HZ ) -+ -+#define __rtc_set_second(s) ( REG_RTC_RSR = (s) ) -+#define __rtc_get_second() REG_RTC_RSR -+#define __rtc_set_alarm(s) ( REG_RTC_RSAR = (s) ) -+#define __rtc_get_alarm() REG_RTC_RSAR -+ -+#define __rtc_adjust_1hz(f32k) \ -+ ( REG_RTC_RGR = (REG_RTC_RGR & ~(RTC_REG_DIV_MASK | RTC_RGR_ADJ_MASK)) | f32k | 0 ) -+#define __rtc_lock_1hz() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -+ -+ -+/*************************************************************************** -+ * FIR -+ ***************************************************************************/ -+ -+/* enable/disable fir unit */ -+#define __fir_enable() ( REG_FIR_CR1 |= FIR_CR1_FIRUE ) -+#define __fir_disable() ( REG_FIR_CR1 &= ~FIR_CR1_FIRUE ) -+ -+/* enable/disable address comparison */ -+#define __fir_enable_ac() ( REG_FIR_CR1 |= FIR_CR1_ACE ) -+#define __fir_disable_ac() ( REG_FIR_CR1 &= ~FIR_CR1_ACE ) -+ -+/* select frame end mode as underrun or normal */ -+#define __fir_set_eous() ( REG_FIR_CR1 |= FIR_CR1_EOUS ) -+#define __fir_clear_eous() ( REG_FIR_CR1 &= ~FIR_CR1_EOUS ) -+ -+/* enable/disable transmitter idle interrupt */ -+#define __fir_enable_tii() ( REG_FIR_CR1 |= FIR_CR1_TIIE ) -+#define __fir_disable_tii() ( REG_FIR_CR1 &= ~FIR_CR1_TIIE ) -+ -+/* enable/disable transmit FIFO service request interrupt */ -+#define __fir_enable_tfi() ( REG_FIR_CR1 |= FIR_CR1_TFIE ) -+#define __fir_disable_tfi() ( REG_FIR_CR1 &= ~FIR_CR1_TFIE ) -+ -+/* enable/disable receive FIFO service request interrupt */ -+#define __fir_enable_rfi() ( REG_FIR_CR1 |= FIR_CR1_RFIE ) -+#define __fir_disable_rfi() ( REG_FIR_CR1 &= ~FIR_CR1_RFIE ) -+ -+/* enable/disable tx function */ -+#define __fir_tx_enable() ( REG_FIR_CR1 |= FIR_CR1_TXE ) -+#define __fir_tx_disable() ( REG_FIR_CR1 &= ~FIR_CR1_TXE ) -+ -+/* enable/disable rx function */ -+#define __fir_rx_enable() ( REG_FIR_CR1 |= FIR_CR1_RXE ) -+#define __fir_rx_disable() ( REG_FIR_CR1 &= ~FIR_CR1_RXE ) -+ -+ -+/* enable/disable serial infrared interaction pulse (SIP) */ -+#define __fir_enable_sip() ( REG_FIR_CR2 |= FIR_CR2_SIPE ) -+#define __fir_disable_sip() ( REG_FIR_CR2 &= ~FIR_CR2_SIPE ) -+ -+/* un-inverted CRC value is sent out */ -+#define __fir_enable_bcrc() ( REG_FIR_CR2 |= FIR_CR2_BCRC ) -+ -+/* inverted CRC value is sent out */ -+#define __fir_disable_bcrc() ( REG_FIR_CR2 &= ~FIR_CR2_BCRC ) -+ -+/* enable/disable Transmit Frame Length Register */ -+#define __fir_enable_tflr() ( REG_FIR_CR2 |= FIR_CR2_TFLRS ) -+#define __fir_disable_tflr() ( REG_FIR_CR2 &= ~FIR_CR2_TFLRS ) -+ -+/* Preamble is transmitted in idle state */ -+#define __fir_set_iss() ( REG_FIR_CR2 |= FIR_CR2_ISS ) -+ -+/* Abort symbol is transmitted in idle state */ -+#define __fir_clear_iss() ( REG_FIR_CR2 &= ~FIR_CR2_ISS ) -+ -+/* enable/disable loopback mode */ -+#define __fir_enable_loopback() ( REG_FIR_CR2 |= FIR_CR2_LMS ) -+#define __fir_disable_loopback() ( REG_FIR_CR2 &= ~FIR_CR2_LMS ) -+ -+/* select transmit pin polarity */ -+#define __fir_tpp_negative() ( REG_FIR_CR2 |= FIR_CR2_TPPS ) -+#define __fir_tpp_positive() ( REG_FIR_CR2 &= ~FIR_CR2_TPPS ) -+ -+/* select receive pin polarity */ -+#define __fir_rpp_negative() ( REG_FIR_CR2 |= FIR_CR2_RPPS ) -+#define __fir_rpp_positive() ( REG_FIR_CR2 &= ~FIR_CR2_RPPS ) -+ -+/* n=16,32,64,128 */ -+#define __fir_set_txfifo_trigger(n) \ -+do { \ -+ REG_FIR_CR2 &= ~FIR_CR2_TTRG_MASK; \ -+ REG_FIR_CR2 |= FIR_CR2_TTRG_##n; \ -+} while (0) -+ -+/* n=16,32,64,128 */ -+#define __fir_set_rxfifo_trigger(n) \ -+do { \ -+ REG_FIR_CR2 &= ~FIR_CR2_RTRG_MASK; \ -+ REG_FIR_CR2 |= FIR_CR2_RTRG_##n; \ -+} while (0) -+ -+ -+/* FIR status checking */ -+ -+#define __fir_test_rfw() ( REG_FIR_SR & FIR_SR_RFW ) -+#define __fir_test_rfa() ( REG_FIR_SR & FIR_SR_RFA ) -+#define __fir_test_tfrtl() ( REG_FIR_SR & FIR_SR_TFRTL ) -+#define __fir_test_rfrtl() ( REG_FIR_SR & FIR_SR_RFRTL ) -+#define __fir_test_urun() ( REG_FIR_SR & FIR_SR_URUN ) -+#define __fir_test_rfte() ( REG_FIR_SR & FIR_SR_RFTE ) -+#define __fir_test_orun() ( REG_FIR_SR & FIR_SR_ORUN ) -+#define __fir_test_crce() ( REG_FIR_SR & FIR_SR_CRCE ) -+#define __fir_test_fend() ( REG_FIR_SR & FIR_SR_FEND ) -+#define __fir_test_tff() ( REG_FIR_SR & FIR_SR_TFF ) -+#define __fir_test_rfe() ( REG_FIR_SR & FIR_SR_RFE ) -+#define __fir_test_tidle() ( REG_FIR_SR & FIR_SR_TIDLE ) -+#define __fir_test_rb() ( REG_FIR_SR & FIR_SR_RB ) -+ -+#define __fir_clear_status() \ -+do { \ -+ REG_FIR_SR |= FIR_SR_RFW | FIR_SR_RFA | FIR_SR_URUN; \ -+} while (0) -+ -+#define __fir_clear_rfw() ( REG_FIR_SR |= FIR_SR_RFW ) -+#define __fir_clear_rfa() ( REG_FIR_SR |= FIR_SR_RFA ) -+#define __fir_clear_urun() ( REG_FIR_SR |= FIR_SR_URUN ) -+ -+#define __fir_set_tflr(len) \ -+do { \ -+ REG_FIR_TFLR = len; \ -+} while (0) -+ -+#define __fir_set_addr(a) ( REG_FIR_AR = (a) ) -+ -+#define __fir_write_data(data) ( REG_FIR_TDR = data ) -+#define __fir_read_data(data) ( data = REG_FIR_RDR ) -+ -+/*************************************************************************** -+ * SCC -+ ***************************************************************************/ -+ -+#define __scc_enable(base) ( REG_SCC_CR(base) |= SCC_CR_SCCE ) -+#define __scc_disable(base) ( REG_SCC_CR(base) &= ~SCC_CR_SCCE ) -+ -+#define __scc_set_tx_mode(base) ( REG_SCC_CR(base) |= SCC_CR_TRS ) -+#define __scc_set_rx_mode(base) ( REG_SCC_CR(base) &= ~SCC_CR_TRS ) -+ -+#define __scc_enable_t2r(base) ( REG_SCC_CR(base) |= SCC_CR_T2R ) -+#define __scc_disable_t2r(base) ( REG_SCC_CR(base) &= ~SCC_CR_T2R ) -+ -+#define __scc_clk_as_devclk(base) \ -+do { \ -+ REG_SCC_CR(base) &= ~SCC_CR_FDIV_MASK; \ -+ REG_SCC_CR(base) |= SCC_CR_FDIV_1; \ -+} while (0) -+ -+#define __scc_clk_as_half_devclk(base) \ -+do { \ -+ REG_SCC_CR(base) &= ~SCC_CR_FDIV_MASK; \ -+ REG_SCC_CR(base) |= SCC_CR_FDIV_2; \ -+} while (0) -+ -+/* n=1,4,8,14 */ -+#define __scc_set_fifo_trigger(base, n) \ -+do { \ -+ REG_SCC_CR(base) &= ~SCC_CR_TRIG_MASK; \ -+ REG_SCC_CR(base) |= SCC_CR_TRIG_##n; \ -+} while (0) -+ -+#define __scc_set_protocol(base, p) \ -+do { \ -+ if (p) \ -+ REG_SCC_CR(base) |= SCC_CR_TP; \ -+ else \ -+ REG_SCC_CR(base) &= ~SCC_CR_TP; \ -+} while (0) -+ -+#define __scc_flush_fifo(base) ( REG_SCC_CR(base) |= SCC_CR_FLUSH ) -+ -+#define __scc_set_invert_mode(base) ( REG_SCC_CR(base) |= SCC_CR_CONV ) -+#define __scc_set_direct_mode(base) ( REG_SCC_CR(base) &= ~SCC_CR_CONV ) -+ -+#define SCC_ERR_INTRS \ -+ ( SCC_CR_ECIE | SCC_CR_EPIE | SCC_CR_RETIE | SCC_CR_EOIE ) -+#define SCC_ALL_INTRS \ -+ ( SCC_CR_TXIE | SCC_CR_RXIE | SCC_CR_TENDIE | SCC_CR_RTOIE | \ -+ SCC_CR_ECIE | SCC_CR_EPIE | SCC_CR_RETIE | SCC_CR_EOIE ) -+ -+#define __scc_enable_err_intrs(base) ( REG_SCC_CR(base) |= SCC_ERR_INTRS ) -+#define __scc_disable_err_intrs(base) ( REG_SCC_CR(base) &= ~SCC_ERR_INTRS ) -+ -+#define SCC_ALL_ERRORS \ -+ ( SCC_SR_ORER | SCC_SR_RTO | SCC_SR_PER | SCC_SR_RETR_3 | SCC_SR_ECNTO) -+ -+#define __scc_clear_errors(base) ( REG_SCC_SR(base) &= ~SCC_ALL_ERRORS ) -+ -+#define __scc_enable_all_intrs(base) ( REG_SCC_CR(base) |= SCC_ALL_INTRS ) -+#define __scc_disable_all_intrs(base) ( REG_SCC_CR(base) &= ~SCC_ALL_INTRS ) -+ -+#define __scc_enable_tx_intr(base) ( REG_SCC_CR(base) |= SCC_CR_TXIE | SCC_CR_TENDIE ) -+#define __scc_disable_tx_intr(base) ( REG_SCC_CR(base) &= ~(SCC_CR_TXIE | SCC_CR_TENDIE) ) -+ -+#define __scc_enable_rx_intr(base) ( REG_SCC_CR(base) |= SCC_CR_RXIE) -+#define __scc_disable_rx_intr(base) ( REG_SCC_CR(base) &= ~SCC_CR_RXIE) -+ -+#define __scc_set_tsend(base) ( REG_SCC_CR(base) |= SCC_CR_TSEND ) -+#define __scc_clear_tsend(base) ( REG_SCC_CR(base) &= ~SCC_CR_TSEND ) -+ -+#define __scc_set_clockstop(base) ( REG_SCC_CR(base) |= SCC_CR_CLKSTP ) -+#define __scc_clear_clockstop(base) ( REG_SCC_CR(base) &= ~SCC_CR_CLKSTP ) -+ -+#define __scc_clockstop_low(base) \ -+do { \ -+ REG_SCC_CR(base) &= ~SCC_CR_PX_MASK; \ -+ REG_SCC_CR(base) |= SCC_CR_PX_STOP_LOW; \ -+} while (0) -+ -+#define __scc_clockstop_high(base) \ -+do { \ -+ REG_SCC_CR(base) &= ~SCC_CR_PX_MASK; \ -+ REG_SCC_CR(base) |= SCC_CR_PX_STOP_HIGH; \ -+} while (0) -+ -+ -+/* SCC status checking */ -+#define __scc_check_transfer_status(base) ( REG_SCC_SR(base) & SCC_SR_TRANS ) -+#define __scc_check_rx_overrun_error(base) ( REG_SCC_SR(base) & SCC_SR_ORER ) -+#define __scc_check_rx_timeout(base) ( REG_SCC_SR(base) & SCC_SR_RTO ) -+#define __scc_check_parity_error(base) ( REG_SCC_SR(base) & SCC_SR_PER ) -+#define __scc_check_txfifo_trigger(base) ( REG_SCC_SR(base) & SCC_SR_TFTG ) -+#define __scc_check_rxfifo_trigger(base) ( REG_SCC_SR(base) & SCC_SR_RFTG ) -+#define __scc_check_tx_end(base) ( REG_SCC_SR(base) & SCC_SR_TEND ) -+#define __scc_check_retx_3(base) ( REG_SCC_SR(base) & SCC_SR_RETR_3 ) -+#define __scc_check_ecnt_overflow(base) ( REG_SCC_SR(base) & SCC_SR_ECNTO ) -+ -+ -+/*************************************************************************** -+ * WDT -+ ***************************************************************************/ -+ -+#define __wdt_set_count(count) ( REG_WDT_WTCNT = (count) ) -+#define __wdt_start() ( REG_WDT_WTCSR |= WDT_WTCSR_START ) -+#define __wdt_stop() ( REG_WDT_WTCSR &= ~WDT_WTCSR_START ) -+ -+ -+/*************************************************************************** -+ * OST -+ ***************************************************************************/ -+ -+#define __ost_enable_all() ( REG_OST_TER |= 0x07 ) -+#define __ost_disable_all() ( REG_OST_TER &= ~0x07 ) -+#define __ost_enable_channel(n) ( REG_OST_TER |= (1 << (n)) ) -+#define __ost_disable_channel(n) ( REG_OST_TER &= ~(1 << (n)) ) -+#define __ost_set_reload(n, val) ( REG_OST_TRDR(n) = (val) ) -+#define __ost_set_count(n, val) ( REG_OST_TCNT(n) = (val) ) -+#define __ost_get_count(n) ( REG_OST_TCNT(n) ) -+#define __ost_set_clock(n, cs) \ -+do { \ -+ REG_OST_TCSR(n) &= ~OST_TCSR_CKS_MASK; \ -+ REG_OST_TCSR(n) |= cs; \ -+} while (0) -+#define __ost_set_mode(n, val) ( REG_OST_TCSR(n) = (val) ) -+#define __ost_enable_interrupt(n) ( REG_OST_TCSR(n) |= OST_TCSR_UIE ) -+#define __ost_disable_interrupt(n) ( REG_OST_TCSR(n) &= ~OST_TCSR_UIE ) -+#define __ost_uf_detected(n) ( REG_OST_TCSR(n) & OST_TCSR_UF ) -+#define __ost_clear_uf(n) ( REG_OST_TCSR(n) &= ~OST_TCSR_UF ) -+#define __ost_is_busy(n) ( REG_OST_TCSR(n) & OST_TCSR_BUSY ) -+#define __ost_clear_busy(n) ( REG_OST_TCSR(n) &= ~OST_TCSR_BUSY ) -+ -+ -+/*************************************************************************** -+ * UART -+ ***************************************************************************/ -+ -+#define __uart_enable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -+#define __uart_disable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -+ -+#define __uart_enable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -+#define __uart_disable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -+ -+#define __uart_enable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -+#define __uart_disable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -+ -+#define __uart_enable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -+#define __uart_disable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -+ -+#define __uart_set_8n1(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -+ -+#define __uart_set_baud(n, devclk, baud) \ -+ do { \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -+ } while (0) -+ -+#define __uart_parity_error(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -+ -+#define __uart_clear_errors(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -+ -+#define __uart_transmit_fifo_empty(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -+ -+#define __uart_transmit_end(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -+ -+#define __uart_transmit_char(n, ch) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -+ -+#define __uart_receive_fifo_full(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_ready(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_char(n) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -+ -+#define __uart_disable_irda() \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -+#define __uart_enable_irda() \ -+ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -+ -+ -+/*************************************************************************** -+ * INTC -+ ***************************************************************************/ -+#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -+#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -+#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) -+ -+/*************************************************************************** -+ * CIM -+ ***************************************************************************/ -+ -+#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -+#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -+ -+#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT ) -+#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT ) -+ -+#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP ) -+#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP ) -+ -+#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP ) -+#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP ) -+ -+#define __cim_sample_data_at_pclk_falling_edge() \ -+ ( REG_CIM_CFG |= CIM_CFG_PCP ) -+#define __cim_sample_data_at_pclk_rising_edge() \ -+ ( REG_CIM_CFG &= ~CIM_CFG_PCP ) -+ -+#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO ) -+#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO ) -+ -+#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC ) -+#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC ) -+ -+/* n=0-7 */ -+#define __cim_set_data_packing_mode(n) \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \ -+ REG_CIM_CFG |= (CIM_CFG_PACK_##n); \ -+} while (0) -+ -+#define __cim_enable_ccir656_progressive_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_CPM; \ -+} while (0) -+ -+#define __cim_enable_ccir656_interlace_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_CIM; \ -+} while (0) -+ -+#define __cim_enable_gated_clock_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_GCM; \ -+} while (0) -+ -+#define __cim_enable_nongated_clock_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \ -+} while (0) -+ -+/* sclk:system bus clock -+ * mclk: CIM master clock -+ */ -+#define __cim_set_master_clk(sclk, mclk) \ -+do { \ -+ REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \ -+ REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \ -+} while (0) -+ -+#define __cim_enable_sof_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM ) -+#define __cim_disable_sof_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM ) -+ -+#define __cim_enable_eof_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM ) -+#define __cim_disable_eof_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM ) -+ -+#define __cim_enable_stop_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM ) -+#define __cim_disable_stop_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM ) -+ -+#define __cim_enable_trig_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM ) -+#define __cim_disable_trig_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM ) -+ -+#define __cim_enable_rxfifo_overflow_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM ) -+#define __cim_disable_rxfifo_overflow_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM ) -+ -+/* n=1-16 */ -+#define __cim_set_frame_rate(n) \ -+do { \ -+ REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \ -+ REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \ -+} while (0) -+ -+#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN ) -+#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN ) -+ -+#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST ) -+#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST ) -+ -+/* n=4,8,12,16,20,24,28,32 */ -+#define __cim_set_rxfifo_trigger(n) \ -+do { \ -+ REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \ -+ REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \ -+} while (0) -+ -+#define __cim_clear_state() ( REG_CIM_STATE = 0 ) -+ -+#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD ) -+#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY ) -+#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG ) -+#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF ) -+#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF ) -+#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP ) -+#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF ) -+#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF ) -+ -+#define __cim_get_iid() ( REG_CIM_IID ) -+#define __cim_get_image_data() ( REG_CIM_RXFIFO ) -+#define __cim_get_dam_cmd() ( REG_CIM_CMD ) -+ -+#define __cim_set_da(a) ( REG_CIM_DA = (a) ) -+ -+/*************************************************************************** -+ * PWM -+ ***************************************************************************/ -+ -+/* n is the pwm channel (0,1,..) */ -+#define __pwm_enable_module(n) ( REG_PWM_CTR(n) |= PWM_CTR_EN ) -+#define __pwm_disable_module(n) ( REG_PWM_CTR(n) &= ~PWM_CTR_EN ) -+#define __pwm_graceful_shutdown_mode(n) ( REG_PWM_CTR(n) &= ~PWM_CTR_SD ) -+#define __pwm_abrupt_shutdown_mode(n) ( REG_PWM_CTR(n) |= PWM_CTR_SD ) -+#define __pwm_set_full_duty(n) ( REG_PWM_DUT(n) |= PWM_DUT_FDUTY ) -+ -+#define __pwm_set_prescale(n, p) \ -+ ( REG_PWM_CTR(n) = ((REG_PWM_CTR(n) & ~PWM_CTR_PRESCALE_MASK) | (p) ) ) -+#define __pwm_set_period(n, p) \ -+ ( REG_PWM_PER(n) = ( (REG_PWM_PER(n) & ~PWM_PER_PERIOD_MASK) | (p) ) ) -+#define __pwm_set_duty(n, d) \ -+ ( REG_PWM_DUT(n) = ( (REG_PWM_DUT(n) & ~(PWM_DUT_FDUTY | PWM_DUT_DUTY_MASK)) | (d) ) ) -+ -+/*************************************************************************** -+ * EMC -+ ***************************************************************************/ -+ -+#define __emc_enable_split() ( REG_EMC_BCR = EMC_BCR_BRE ) -+#define __emc_disable_split() ( REG_EMC_BCR = 0 ) -+ -+#define __emc_smem_bus_width(n) /* 8, 16 or 32*/ \ -+ ( REG_EMC_SMCR = (REG_EMC_SMCR & EMC_SMCR_BW_MASK) | \ -+ EMC_SMCR_BW_##n##BIT ) -+#define __emc_smem_byte_control() \ -+ ( REG_EMC_SMCR = (REG_EMC_SMCR | EMC_SMCR_BCM ) -+#define __emc_normal_smem() \ -+ ( REG_EMC_SMCR = (REG_EMC_SMCR & ~EMC_SMCR_SMT ) -+#define __emc_burst_smem() \ -+ ( REG_EMC_SMCR = (REG_EMC_SMCR | EMC_SMCR_SMT ) -+#define __emc_smem_burstlen(n) /* 4, 8, 16 or 32 */ \ -+ ( REG_EMC_SMCR = (REG_EMC_SMCR & EMC_SMCR_BL_MASK) | (EMC_SMCR_BL_##n ) -+ -+/*************************************************************************** -+ * GPIO -+ ***************************************************************************/ -+ -+/* p is the port number (0,1,2,3) -+ * o is the pin offset (0-31) inside the port -+ * n is the absolute number of a pin (0-124), regardless of the port -+ * m is the interrupt manner (low/high/falling/rising) -+ */ -+ -+#define __gpio_port_data(p) ( REG_GPIO_GPDR(p) ) -+ -+#define __gpio_port_as_output(p, o) \ -+do { \ -+ unsigned int tmp; \ -+ REG_GPIO_GPIER(p) &= ~(1 << (o)); \ -+ REG_GPIO_GPDIR(p) |= (1 << (o)); \ -+ if (o < 16) { \ -+ tmp = REG_GPIO_GPALR(p); \ -+ tmp &= ~(3 << ((o) << 1)); \ -+ REG_GPIO_GPALR(p) = tmp; \ -+ } else { \ -+ tmp = REG_GPIO_GPAUR(p); \ -+ tmp &= ~(3 << (((o) - 16)<< 1)); \ -+ REG_GPIO_GPAUR(p) = tmp; \ -+ } \ -+} while (0) -+ -+#define __gpio_port_as_input(p, o) \ -+do { \ -+ unsigned int tmp; \ -+ REG_GPIO_GPIER(p) &= ~(1 << (o)); \ -+ REG_GPIO_GPDIR(p) &= ~(1 << (o)); \ -+ if (o < 16) { \ -+ tmp = REG_GPIO_GPALR(p); \ -+ tmp &= ~(3 << ((o) << 1)); \ -+ REG_GPIO_GPALR(p) = tmp; \ -+ } else { \ -+ tmp = REG_GPIO_GPAUR(p); \ -+ tmp &= ~(3 << (((o) - 16)<< 1)); \ -+ REG_GPIO_GPAUR(p) = tmp; \ -+ } \ -+} while (0) -+ -+#define __gpio_as_output(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_output(p, o); \ -+} while (0) -+ -+#define __gpio_as_input(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_input(p, o); \ -+} while (0) -+ -+#define __gpio_set_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_data(p) |= (1 << o); \ -+} while (0) -+ -+#define __gpio_clear_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_data(p) &= ~(1 << o); \ -+} while (0) -+ -+static __inline__ unsigned int __gpio_get_pin(unsigned int n) -+{ -+ unsigned int p, o; -+ p = (n) / 32; -+ o = (n) % 32; -+ if (__gpio_port_data(p) & (1 << o)) -+ return 1; -+ else -+ return 0; -+} -+ -+#define __gpio_set_irq_detect_manner(p, o, m) \ -+do { \ -+ unsigned int tmp; \ -+ if (o < 16) { \ -+ tmp = REG_GPIO_GPIDLR(p); \ -+ tmp &= ~(3 << ((o) << 1)); \ -+ tmp |= ((m) << ((o) << 1)); \ -+ REG_GPIO_GPIDLR(p) = tmp; \ -+ } else { \ -+ tmp = REG_GPIO_GPIDUR(p); \ -+ tmp &= ~(3 << (((o)-16) << 1)); \ -+ tmp |= ((m) << (((o)-16) << 1)); \ -+ REG_GPIO_GPIDUR(p) = tmp; \ -+ } \ -+} while (0) -+ -+#define __gpio_port_as_irq(p, o, m) \ -+do { \ -+ __gpio_port_as_input(p, o); \ -+ __gpio_set_irq_detect_manner(p, o, m); \ -+} while (0) -+ -+#define __gpio_as_irq(n, m) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_irq(p, o, m); \ -+} while (0) -+ -+ -+#define __gpio_as_irq_high_level(n) __gpio_as_irq(n, GPIO_IRQ_HILEVEL) -+#define __gpio_as_irq_low_level(n) __gpio_as_irq(n, GPIO_IRQ_LOLEVEL) -+#define __gpio_as_irq_fall_edge(n) __gpio_as_irq(n, GPIO_IRQ_FALLEDG) -+#define __gpio_as_irq_rise_edge(n) __gpio_as_irq(n, GPIO_IRQ_RAISEDG) -+ -+ -+#define __gpio_mask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_GPIER(p) &= ~(1 << o); \ -+} while (0) -+ -+#define __gpio_unmask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_GPIER(p) |= (1 << o); \ -+} while (0) -+ -+#define __gpio_ack_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_GPFR(p) |= (1 << o); \ -+} while (0) -+ -+ -+static __inline__ unsigned int __gpio_get_irq(void) -+{ -+ unsigned int tmp, i; -+ -+ tmp = REG_GPIO_GPFR(3); -+ for (i=0; i<32; i++) -+ if (tmp & (1 << i)) -+ return 0x60 + i; -+ tmp = REG_GPIO_GPFR(2); -+ for (i=0; i<32; i++) -+ if (tmp & (1 << i)) -+ return 0x40 + i; -+ tmp = REG_GPIO_GPFR(1); -+ for (i=0; i<32; i++) -+ if (tmp & (1 << i)) -+ return 0x20 + i; -+ tmp = REG_GPIO_GPFR(0); -+ for (i=0; i<32; i++) -+ if (tmp & (1 << i)) -+ return i; -+ return 0; -+} -+ -+#define __gpio_group_irq(n) \ -+({ \ -+ register int tmp, i; \ -+ tmp = REG_GPIO_GPFR((n)); \ -+ for (i=31;i>=0;i--) \ -+ if (tmp & (1 << i)) \ -+ break; \ -+ i; \ -+}) -+ -+#define __gpio_enable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_GPPUR(p) |= (1 << o); \ -+} while (0) -+ -+#define __gpio_disable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_GPPUR(p) &= ~(1 << o); \ -+} while (0) -+ -+ -+/* Init the alternate function pins */ -+ -+ -+#define __gpio_as_ssi() \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0xFC00FFFF; \ -+ REG_GPIO_GPALR(2) |= 0x01550000; \ -+} while (0) -+ -+#define __gpio_as_uart3() \ -+do { \ -+ REG_GPIO_GPAUR(0) &= 0xFFFF0000; \ -+ REG_GPIO_GPAUR(0) |= 0x00005555; \ -+} while (0) -+ -+#define __gpio_as_uart2() \ -+do { \ -+ REG_GPIO_GPALR(3) &= 0x3FFFFFFF; \ -+ REG_GPIO_GPALR(3) |= 0x40000000; \ -+ REG_GPIO_GPAUR(3) &= 0xF3FFFFFF; \ -+ REG_GPIO_GPAUR(3) |= 0x04000000; \ -+} while (0) -+ -+#define __gpio_as_uart1() \ -+do { \ -+ REG_GPIO_GPAUR(0) &= 0xFFF0FFFF; \ -+ REG_GPIO_GPAUR(0) |= 0x00050000; \ -+} while (0) -+ -+#define __gpio_as_uart0() \ -+do { \ -+ REG_GPIO_GPAUR(3) &= 0x0FFFFFFF; \ -+ REG_GPIO_GPAUR(3) |= 0x50000000; \ -+} while (0) -+ -+ -+#define __gpio_as_scc0() \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0xFFFFFFCC; \ -+ REG_GPIO_GPALR(2) |= 0x00000011; \ -+} while (0) -+ -+#define __gpio_as_scc1() \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0xFFFFFF33; \ -+ REG_GPIO_GPALR(2) |= 0x00000044; \ -+} while (0) -+ -+#define __gpio_as_scc() \ -+do { \ -+ __gpio_as_scc0(); \ -+ __gpio_as_scc1(); \ -+} while (0) -+ -+#define __gpio_as_dma() \ -+do { \ -+ REG_GPIO_GPALR(0) &= 0x00FFFFFF; \ -+ REG_GPIO_GPALR(0) |= 0x55000000; \ -+ REG_GPIO_GPAUR(0) &= 0xFF0FFFFF; \ -+ REG_GPIO_GPAUR(0) |= 0x00500000; \ -+} while (0) -+ -+#define __gpio_as_msc() \ -+do { \ -+ REG_GPIO_GPALR(1) &= 0xFFFF000F; \ -+ REG_GPIO_GPALR(1) |= 0x00005550; \ -+} while (0) -+ -+#define __gpio_as_pcmcia() \ -+do { \ -+ REG_GPIO_GPAUR(2) &= 0xF000FFFF; \ -+ REG_GPIO_GPAUR(2) |= 0x05550000; \ -+} while (0) -+ -+#define __gpio_as_emc(csmask) \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0x3FFFFFFF; \ -+ REG_GPIO_GPALR(2) |= 0x40000000; \ -+ REG_GPIO_GPAUR(2) &= 0xFFFF0000; \ -+ REG_GPIO_GPAUR(2) |= 0x00005555; \ -+} while (0) -+ -+#define __gpio_as_lcd_slave() \ -+do { \ -+ REG_GPIO_GPALR(1) &= 0x0000FFFF; \ -+ REG_GPIO_GPALR(1) |= 0x55550000; \ -+ REG_GPIO_GPAUR(1) &= 0x00000000; \ -+ REG_GPIO_GPAUR(1) |= 0x55555555; \ -+} while (0) -+ -+#define __gpio_as_lcd_master() \ -+do { \ -+ REG_GPIO_GPALR(1) &= 0x0000FFFF; \ -+ REG_GPIO_GPALR(1) |= 0x55550000; \ -+ REG_GPIO_GPAUR(1) &= 0x00000000; \ -+ REG_GPIO_GPAUR(1) |= 0x556A5555; \ -+} while (0) -+ -+#define __gpio_as_usb() \ -+do { \ -+ REG_GPIO_GPAUR(0) &= 0x00FFFFFF; \ -+ REG_GPIO_GPAUR(0) |= 0x55000000; \ -+} while (0) -+ -+#define __gpio_as_ac97() \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0xC3FF03FF; \ -+ REG_GPIO_GPALR(2) |= 0x24005400; \ -+} while (0) -+ -+#define __gpio_as_i2s_slave() \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \ -+ REG_GPIO_GPALR(2) |= 0x14005100; \ -+} while (0) -+ -+#define __gpio_as_i2s_master() \ -+do { \ -+ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \ -+ REG_GPIO_GPALR(2) |= 0x28005100; \ -+} while (0) -+ -+#define __gpio_as_eth() \ -+do { \ -+ REG_GPIO_GPAUR(3) &= 0xFC000000; \ -+ REG_GPIO_GPAUR(3) |= 0x01555555; \ -+} while (0) -+ -+#define __gpio_as_pwm() \ -+do { \ -+ REG_GPIO_GPAUR(2) &= 0x0FFFFFFF; \ -+ REG_GPIO_GPAUR(2) |= 0x50000000; \ -+} while (0) -+ -+#define __gpio_as_ps2() \ -+do { \ -+ REG_GPIO_GPALR(1) &= 0xFFFFFFF0; \ -+ REG_GPIO_GPALR(1) |= 0x00000005; \ -+} while (0) -+ -+#define __gpio_as_uprt() \ -+do { \ -+ REG_GPIO_GPALR(1) &= 0x0000000F; \ -+ REG_GPIO_GPALR(1) |= 0x55555550; \ -+ REG_GPIO_GPALR(3) &= 0xC0000000; \ -+ REG_GPIO_GPALR(3) |= 0x15555555; \ -+} while (0) -+ -+#define __gpio_as_cim() \ -+do { \ -+ REG_GPIO_GPALR(0) &= 0xFF000000; \ -+ REG_GPIO_GPALR(0) |= 0x00555555; \ -+} while (0) -+ -+/*************************************************************************** -+ * HARB -+ ***************************************************************************/ -+ -+#define __harb_usb0_udc() \ -+do { \ -+ REG_HARB_HAPOR &= ~HARB_HAPOR_UCHSEL; \ -+} while (0) -+ -+#define __harb_usb0_uhc() \ -+do { \ -+ REG_HARB_HAPOR |= HARB_HAPOR_UCHSEL; \ -+} while (0) -+ -+#define __harb_set_priority(n) \ -+do { \ -+ REG_HARB_HAPOR = ((REG_HARB_HAPOR & ~HARB_HAPOR_PRIO_MASK) | n); \ -+} while (0) -+ -+/*************************************************************************** -+ * I2C -+ ***************************************************************************/ -+ -+#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -+#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -+ -+#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -+#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -+#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -+#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -+ -+#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -+#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -+#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -+ -+#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -+#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -+#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -+ -+#define __i2c_set_clk(dev_clk, i2c_clk) \ -+ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -+ -+#define __i2c_read() ( REG_I2C_DR ) -+#define __i2c_write(val) ( REG_I2C_DR = (val) ) -+ -+/*************************************************************************** -+ * UDC -+ ***************************************************************************/ -+ -+#define __udc_set_16bit_phy() ( REG_UDC_DevCFGR |= UDC_DevCFGR_PI ) -+#define __udc_set_8bit_phy() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_PI ) -+ -+#define __udc_enable_sync_frame() ( REG_UDC_DevCFGR |= UDC_DevCFGR_SS ) -+#define __udc_disable_sync_frame() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_SS ) -+ -+#define __udc_self_powered() ( REG_UDC_DevCFGR |= UDC_DevCFGR_SP ) -+#define __udc_bus_powered() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_SP ) -+ -+#define __udc_enable_remote_wakeup() ( REG_UDC_DevCFGR |= UDC_DevCFGR_RW ) -+#define __udc_disable_remote_wakeup() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_RW ) -+ -+#define __udc_set_speed_high() \ -+do { \ -+ REG_UDC_DevCFGR &= ~UDC_DevCFGR_SPD_MASK; \ -+ REG_UDC_DevCFGR |= UDC_DevCFGR_SPD_HS; \ -+} while (0) -+ -+#define __udc_set_speed_full() \ -+do { \ -+ REG_UDC_DevCFGR &= ~UDC_DevCFGR_SPD_MASK; \ -+ REG_UDC_DevCFGR |= UDC_DevCFGR_SPD_FS; \ -+} while (0) -+ -+#define __udc_set_speed_low() \ -+do { \ -+ REG_UDC_DevCFGR &= ~UDC_DevCFGR_SPD_MASK; \ -+ REG_UDC_DevCFGR |= UDC_DevCFGR_SPD_LS; \ -+} while (0) -+ -+ -+#define __udc_set_dma_mode() ( REG_UDC_DevCR |= UDC_DevCR_DM ) -+#define __udc_set_slave_mode() ( REG_UDC_DevCR &= ~UDC_DevCR_DM ) -+#define __udc_set_big_endian() ( REG_UDC_DevCR |= UDC_DevCR_BE ) -+#define __udc_set_little_endian() ( REG_UDC_DevCR &= ~UDC_DevCR_BE ) -+#define __udc_generate_resume() ( REG_UDC_DevCR |= UDC_DevCR_RES ) -+#define __udc_clear_resume() ( REG_UDC_DevCR &= ~UDC_DevCR_RES ) -+ -+ -+#define __udc_get_enumarated_speed() ( REG_UDC_DevSR & UDC_DevSR_ENUMSPD_MASK ) -+#define __udc_suspend_detected() ( REG_UDC_DevSR & UDC_DevSR_SUSP ) -+#define __udc_get_alternate_setting() ( (REG_UDC_DevSR & UDC_DevSR_ALT_MASK) >> UDC_DevSR_ALT_BIT ) -+#define __udc_get_interface_number() ( (REG_UDC_DevSR & UDC_DevSR_INTF_MASK) >> UDC_DevSR_INTF_BIT ) -+#define __udc_get_config_number() ( (REG_UDC_DevSR & UDC_DevSR_CFG_MASK) >> UDC_DevSR_CFG_BIT ) -+ -+ -+#define __udc_sof_detected(r) ( (r) & UDC_DevIntR_SOF ) -+#define __udc_usb_suspend_detected(r) ( (r) & UDC_DevIntR_US ) -+#define __udc_usb_reset_detected(r) ( (r) & UDC_DevIntR_UR ) -+#define __udc_set_interface_detected(r) ( (r) & UDC_DevIntR_SI ) -+#define __udc_set_config_detected(r) ( (r) & UDC_DevIntR_SC ) -+ -+#define __udc_clear_sof() ( REG_UDC_DevIntR |= UDC_DevIntR_SOF ) -+#define __udc_clear_usb_suspend() ( REG_UDC_DevIntR |= UDC_DevIntR_US ) -+#define __udc_clear_usb_reset() ( REG_UDC_DevIntR |= UDC_DevIntR_UR ) -+#define __udc_clear_set_interface() ( REG_UDC_DevIntR |= UDC_DevIntR_SI ) -+#define __udc_clear_set_config() ( REG_UDC_DevIntR |= UDC_DevIntR_SC ) -+ -+#define __udc_mask_sof() ( REG_UDC_DevIntMR |= UDC_DevIntR_SOF ) -+#define __udc_mask_usb_suspend() ( REG_UDC_DevIntMR |= UDC_DevIntR_US ) -+#define __udc_mask_usb_reset() ( REG_UDC_DevIntMR |= UDC_DevIntR_UR ) -+#define __udc_mask_set_interface() ( REG_UDC_DevIntMR |= UDC_DevIntR_SI ) -+#define __udc_mask_set_config() ( REG_UDC_DevIntMR |= UDC_DevIntR_SC ) -+#define __udc_mask_all_dev_intrs() \ -+ ( REG_UDC_DevIntMR = UDC_DevIntR_SOF | UDC_DevIntR_US | \ -+ UDC_DevIntR_UR | UDC_DevIntR_SI | UDC_DevIntR_SC ) -+ -+#define __udc_unmask_sof() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_SOF ) -+#define __udc_unmask_usb_suspend() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_US ) -+#define __udc_unmask_usb_reset() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_UR ) -+#define __udc_unmask_set_interface() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_SI ) -+#define __udc_unmask_set_config() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_SC ) -+#if 0 -+#define __udc_unmask_all_dev_intrs() \ -+ ( REG_UDC_DevIntMR = ~(UDC_DevIntR_SOF | UDC_DevIntR_US | \ -+ UDC_DevIntR_UR | UDC_DevIntR_SI | UDC_DevIntR_SC) ) -+#else -+#define __udc_unmask_all_dev_intrs() \ -+ ( REG_UDC_DevIntMR = 0x00000000 ) -+#endif -+ -+ -+#define __udc_ep0out_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 0)) & 0x1 ) -+#define __udc_ep5out_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 5)) & 0x1 ) -+#define __udc_ep6out_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 6)) & 0x1 ) -+#define __udc_ep7out_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 7)) & 0x1 ) -+ -+#define __udc_ep0in_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 0)) & 0x1 ) -+#define __udc_ep1in_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 1)) & 0x1 ) -+#define __udc_ep2in_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 2)) & 0x1 ) -+#define __udc_ep3in_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 3)) & 0x1 ) -+#define __udc_ep4in_irq_detected(epintr) \ -+ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 4)) & 0x1 ) -+ -+ -+#define __udc_mask_ep0out_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 0)) ) -+#define __udc_mask_ep5out_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 5)) ) -+#define __udc_mask_ep6out_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 6)) ) -+#define __udc_mask_ep7out_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 7)) ) -+ -+#define __udc_unmask_ep0out_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 0)) ) -+#define __udc_unmask_ep5out_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 5)) ) -+#define __udc_unmask_ep6out_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 6)) ) -+#define __udc_unmask_ep7out_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 7)) ) -+ -+#define __udc_mask_ep0in_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 0)) ) -+#define __udc_mask_ep1in_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 1)) ) -+#define __udc_mask_ep2in_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 2)) ) -+#define __udc_mask_ep3in_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 3)) ) -+#define __udc_mask_ep4in_irq() \ -+ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 4)) ) -+ -+#define __udc_unmask_ep0in_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 0)) ) -+#define __udc_unmask_ep1in_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 1)) ) -+#define __udc_unmask_ep2in_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 2)) ) -+#define __udc_unmask_ep3in_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 3)) ) -+#define __udc_unmask_ep4in_irq() \ -+ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 4)) ) -+ -+#define __udc_mask_all_ep_intrs() \ -+ ( REG_UDC_EPIntMR = 0xffffffff ) -+#define __udc_unmask_all_ep_intrs() \ -+ ( REG_UDC_EPIntMR = 0x00000000 ) -+ -+ -+/* ep0 only CTRL, ep1 only INTR, ep2/3/5/6 only BULK, ep4/7 only ISO */ -+#define __udc_config_endpoint_type() \ -+do { \ -+ REG_UDC_EP0InCR = (REG_UDC_EP0InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_CTRL; \ -+ REG_UDC_EP0OutCR = (REG_UDC_EP0OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_CTRL; \ -+ REG_UDC_EP1InCR = (REG_UDC_EP1InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_INTR; \ -+ REG_UDC_EP2InCR = (REG_UDC_EP2InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -+ REG_UDC_EP3InCR = (REG_UDC_EP3InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -+ REG_UDC_EP4InCR = (REG_UDC_EP4InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_ISO; \ -+ REG_UDC_EP5OutCR = (REG_UDC_EP5OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -+ REG_UDC_EP6OutCR = (REG_UDC_EP6OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -+ REG_UDC_EP7OutCR = (REG_UDC_EP7OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_ISO; \ -+} while (0) -+ -+#define __udc_enable_ep0out_snoop_mode() ( REG_UDC_EP0OutCR |= UDC_EPCR_SN ) -+#define __udc_enable_ep5out_snoop_mode() ( REG_UDC_EP5OutCR |= UDC_EPCR_SN ) -+#define __udc_enable_ep6out_snoop_mode() ( REG_UDC_EP6OutCR |= UDC_EPCR_SN ) -+#define __udc_enable_ep7out_snoop_mode() ( REG_UDC_EP7OutCR |= UDC_EPCR_SN ) -+ -+#define __udc_disable_ep0out_snoop_mode() ( REG_UDC_EP0OutCR &= ~UDC_EPCR_SN ) -+#define __udc_disable_ep5out_snoop_mode() ( REG_UDC_EP5OutCR &= ~UDC_EPCR_SN ) -+#define __udc_disable_ep6out_snoop_mode() ( REG_UDC_EP6OutCR &= ~UDC_EPCR_SN ) -+#define __udc_disable_ep7out_snoop_mode() ( REG_UDC_EP7OutCR &= ~UDC_EPCR_SN ) -+ -+#define __udc_flush_ep0in_fifo() ( REG_UDC_EP0InCR |= UDC_EPCR_F ) -+#define __udc_flush_ep1in_fifo() ( REG_UDC_EP1InCR |= UDC_EPCR_F ) -+#define __udc_flush_ep2in_fifo() ( REG_UDC_EP2InCR |= UDC_EPCR_F ) -+#define __udc_flush_ep3in_fifo() ( REG_UDC_EP3InCR |= UDC_EPCR_F ) -+#define __udc_flush_ep4in_fifo() ( REG_UDC_EP4InCR |= UDC_EPCR_F ) -+ -+#define __udc_unflush_ep0in_fifo() ( REG_UDC_EP0InCR &= ~UDC_EPCR_F ) -+#define __udc_unflush_ep1in_fifo() ( REG_UDC_EP1InCR &= ~UDC_EPCR_F ) -+#define __udc_unflush_ep2in_fifo() ( REG_UDC_EP2InCR &= ~UDC_EPCR_F ) -+#define __udc_unflush_ep3in_fifo() ( REG_UDC_EP3InCR &= ~UDC_EPCR_F ) -+#define __udc_unflush_ep4in_fifo() ( REG_UDC_EP4InCR &= ~UDC_EPCR_F ) -+ -+#define __udc_enable_ep0in_stall() ( REG_UDC_EP0InCR |= UDC_EPCR_S ) -+#define __udc_enable_ep0out_stall() ( REG_UDC_EP0OutCR |= UDC_EPCR_S ) -+#define __udc_enable_ep1in_stall() ( REG_UDC_EP1InCR |= UDC_EPCR_S ) -+#define __udc_enable_ep2in_stall() ( REG_UDC_EP2InCR |= UDC_EPCR_S ) -+#define __udc_enable_ep3in_stall() ( REG_UDC_EP3InCR |= UDC_EPCR_S ) -+#define __udc_enable_ep4in_stall() ( REG_UDC_EP4InCR |= UDC_EPCR_S ) -+#define __udc_enable_ep5out_stall() ( REG_UDC_EP5OutCR |= UDC_EPCR_S ) -+#define __udc_enable_ep6out_stall() ( REG_UDC_EP6OutCR |= UDC_EPCR_S ) -+#define __udc_enable_ep7out_stall() ( REG_UDC_EP7OutCR |= UDC_EPCR_S ) -+ -+#define __udc_disable_ep0in_stall() ( REG_UDC_EP0InCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep0out_stall() ( REG_UDC_EP0OutCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep1in_stall() ( REG_UDC_EP1InCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep2in_stall() ( REG_UDC_EP2InCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep3in_stall() ( REG_UDC_EP3InCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep4in_stall() ( REG_UDC_EP4InCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep5out_stall() ( REG_UDC_EP5OutCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep6out_stall() ( REG_UDC_EP6OutCR &= ~UDC_EPCR_S ) -+#define __udc_disable_ep7out_stall() ( REG_UDC_EP7OutCR &= ~UDC_EPCR_S ) -+ -+ -+#define __udc_ep0out_packet_size() \ -+ ( (REG_UDC_EP0OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -+#define __udc_ep5out_packet_size() \ -+ ( (REG_UDC_EP5OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -+#define __udc_ep6out_packet_size() \ -+ ( (REG_UDC_EP6OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -+#define __udc_ep7out_packet_size() \ -+ ( (REG_UDC_EP7OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -+ -+#define __udc_ep0in_received_intoken() ( (REG_UDC_EP0InSR & UDC_EPSR_IN) ) -+#define __udc_ep1in_received_intoken() ( (REG_UDC_EP1InSR & UDC_EPSR_IN) ) -+#define __udc_ep2in_received_intoken() ( (REG_UDC_EP2InSR & UDC_EPSR_IN) ) -+#define __udc_ep3in_received_intoken() ( (REG_UDC_EP3InSR & UDC_EPSR_IN) ) -+#define __udc_ep4in_received_intoken() ( (REG_UDC_EP4InSR & UDC_EPSR_IN) ) -+ -+#define __udc_ep0out_received_none() \ -+ ( (REG_UDC_EP0OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -+#define __udc_ep0out_received_data() \ -+ ( (REG_UDC_EP0OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -+#define __udc_ep0out_received_setup() \ -+ ( (REG_UDC_EP0OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -+ -+#define __udc_ep5out_received_none() \ -+ ( (REG_UDC_EP5OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -+#define __udc_ep5out_received_data() \ -+ ( (REG_UDC_EP5OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -+#define __udc_ep5out_received_setup() \ -+ ( (REG_UDC_EP5OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -+ -+#define __udc_ep6out_received_none() \ -+ ( (REG_UDC_EP6OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -+#define __udc_ep6out_received_data() \ -+ ( (REG_UDC_EP6OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -+#define __udc_ep6out_received_setup() \ -+ ( (REG_UDC_EP6OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -+ -+#define __udc_ep7out_received_none() \ -+ ( (REG_UDC_EP7OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -+#define __udc_ep7out_received_data() \ -+ ( (REG_UDC_EP7OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -+#define __udc_ep7out_received_setup() \ -+ ( (REG_UDC_EP7OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -+ -+/* ep7out ISO only */ -+#define __udc_ep7out_get_pid() \ -+ ( (REG_UDC_EP7OutSR & UDC_EPSR_PID_MASK) >> UDC_EPSR_PID_BIT ) -+ -+ -+#define __udc_ep0in_set_buffer_size(n) ( REG_UDC_EP0InBSR = (n) ) -+#define __udc_ep1in_set_buffer_size(n) ( REG_UDC_EP1InBSR = (n) ) -+#define __udc_ep2in_set_buffer_size(n) ( REG_UDC_EP2InBSR = (n) ) -+#define __udc_ep3in_set_buffer_size(n) ( REG_UDC_EP3InBSR = (n) ) -+#define __udc_ep4in_set_buffer_size(n) ( REG_UDC_EP4InBSR = (n) ) -+ -+#define __udc_ep0out_get_frame_number(n) ( UDC_EP0OutPFNR ) -+#define __udc_ep5out_get_frame_number(n) ( UDC_EP5OutPFNR ) -+#define __udc_ep6out_get_frame_number(n) ( UDC_EP6OutPFNR ) -+#define __udc_ep7out_get_frame_number(n) ( UDC_EP7OutPFNR ) -+ -+ -+#define __udc_ep0in_set_max_packet_size(n) ( REG_UDC_EP0InMPSR = (n) ) -+#define __udc_ep0out_set_max_packet_size(n) ( REG_UDC_EP0OutMPSR = (n) ) -+#define __udc_ep1in_set_max_packet_size(n) ( REG_UDC_EP1InMPSR = (n) ) -+#define __udc_ep2in_set_max_packet_size(n) ( REG_UDC_EP2InMPSR = (n) ) -+#define __udc_ep3in_set_max_packet_size(n) ( REG_UDC_EP3InMPSR = (n) ) -+#define __udc_ep4in_set_max_packet_size(n) ( REG_UDC_EP4InMPSR = (n) ) -+#define __udc_ep5out_set_max_packet_size(n) ( REG_UDC_EP5OutMPSR = (n) ) -+#define __udc_ep6out_set_max_packet_size(n) ( REG_UDC_EP6OutMPSR = (n) ) -+#define __udc_ep7out_set_max_packet_size(n) ( REG_UDC_EP7OutMPSR = (n) ) -+ -+/* set to 0xFFFF for UDC */ -+#define __udc_set_setup_command_address(n) ( REG_UDC_STCMAR = (n) ) -+ -+/* Init and configure EPxInfR(x=0,1,2,3,4,5,6,7) -+ * c: Configuration number to which this endpoint belongs -+ * i: Interface number to which this endpoint belongs -+ * a: Alternate setting to which this endpoint belongs -+ * p: max Packet size of this endpoint -+ */ -+ -+#define __udc_ep0info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP0InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP0InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP0InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP0InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP0InfR |= UDC_EPInfR_EPT_CTRL; \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP0InfR |= UDC_EPInfR_EPD_OUT; \ -+ REG_UDC_EP0InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP0InfR |= (0 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep1info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP1InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP1InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP1InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP1InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP1InfR |= UDC_EPInfR_EPT_INTR; \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP1InfR |= UDC_EPInfR_EPD_IN; \ -+ REG_UDC_EP1InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP1InfR |= (1 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep2info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP2InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP2InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP2InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP2InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP2InfR |= UDC_EPInfR_EPT_BULK; \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP2InfR |= UDC_EPInfR_EPD_IN; \ -+ REG_UDC_EP2InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP2InfR |= (2 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep3info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP3InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP3InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP3InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP3InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP3InfR |= UDC_EPInfR_EPT_BULK; \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP3InfR |= UDC_EPInfR_EPD_IN; \ -+ REG_UDC_EP3InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP3InfR |= (3 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep4info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP4InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP4InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP4InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP4InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP4InfR |= UDC_EPInfR_EPT_ISO; \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP4InfR |= UDC_EPInfR_EPD_IN; \ -+ REG_UDC_EP4InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP4InfR |= (4 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep5info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP5InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP5InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP5InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP5InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP5InfR |= UDC_EPInfR_EPT_BULK; \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP5InfR |= UDC_EPInfR_EPD_OUT; \ -+ REG_UDC_EP5InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP5InfR |= (5 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep6info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP6InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP6InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP6InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP6InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP6InfR |= UDC_EPInfR_EPT_BULK; \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP6InfR |= UDC_EPInfR_EPD_OUT; \ -+ REG_UDC_EP6InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP6InfR |= (6 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+#define __udc_ep7info_init(c,i,a,p) \ -+do { \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_MPS_MASK; \ -+ REG_UDC_EP7InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_ALTS_MASK; \ -+ REG_UDC_EP7InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_IFN_MASK; \ -+ REG_UDC_EP7InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_CGN_MASK; \ -+ REG_UDC_EP7InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_EPT_MASK; \ -+ REG_UDC_EP7InfR |= UDC_EPInfR_EPT_ISO; \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_EPD; \ -+ REG_UDC_EP7InfR |= UDC_EPInfR_EPD_OUT; \ -+ REG_UDC_EP7InfR &= ~UDC_EPInfR_EPN_MASK; \ -+ REG_UDC_EP7InfR |= (7 << UDC_EPInfR_EPN_BIT); \ -+} while (0) -+ -+ -+/*************************************************************************** -+ * DMAC -+ ***************************************************************************/ -+ -+/* n is the DMA channel (0 - 7) */ -+ -+#define __dmac_enable_all_channels() \ -+ ( REG_DMAC_DMACR |= DMAC_DMACR_DME | DMAC_DMACR_PR_ROUNDROBIN ) -+#define __dmac_disable_all_channels() \ -+ ( REG_DMAC_DMACR &= ~DMAC_DMACR_DME ) -+ -+/* p=0,1,2,3 */ -+#define __dmac_set_priority(p) \ -+do { \ -+ REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \ -+ REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \ -+} while (0) -+ -+#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HTR ) -+#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AER ) -+ -+#define __dmac_enable_channel(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_CHDE ) -+#define __dmac_disable_channel(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_CHDE ) -+#define __dmac_channel_enabled(n) \ -+ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_CHDE ) -+ -+#define __dmac_channel_enable_irq(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_TCIE ) -+#define __dmac_channel_disable_irq(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TCIE ) -+ -+#define __dmac_channel_transmit_halt_detected(n) \ -+ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_HLT ) -+#define __dmac_channel_transmit_end_detected(n) \ -+ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_TC ) -+#define __dmac_channel_address_error_detected(n) \ -+ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_AR ) -+ -+#define __dmac_channel_clear_transmit_halt(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT ) -+#define __dmac_channel_clear_transmit_end(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TC ) -+#define __dmac_channel_clear_address_error(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR ) -+ -+#define __dmac_channel_set_single_mode(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TM ) -+#define __dmac_channel_set_block_mode(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_TM ) -+ -+#define __dmac_channel_set_transfer_unit_32bit(n) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_32b; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16bit(n) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_16b; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_8bit(n) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_8b; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16byte(n) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_16B; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_32byte(n) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_32B; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_dest_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DWDH_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DWDH_##w; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_src_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_SWDH_MASK; \ -+ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_SWDH_##w; \ -+} while (0) -+ -+/* v=0-15 */ -+#define __dmac_channel_set_rdil(n,v) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_RDIL_MASK; \ -+ REG_DMAC_DCCSR(n) |= ((v) << DMAC_DCCSR_RDIL_BIT); \ -+} while (0) -+ -+#define __dmac_channel_dest_addr_fixed(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DAM ) -+#define __dmac_channel_dest_addr_increment(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DAM ) -+ -+#define __dmac_channel_src_addr_fixed(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_SAM ) -+#define __dmac_channel_src_addr_increment(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_SAM ) -+ -+#define __dmac_channel_set_eop_high(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_EOPM ) -+#define __dmac_channel_set_eop_low(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_EOPM ) -+ -+#define __dmac_channel_set_erdm(n,m) \ -+do { \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_SWDH_MASK; \ -+ REG_DMAC_DCCSR(n) |= ((m) << DMAC_DCCSR_ERDM_BIT); \ -+} while (0) -+ -+#define __dmac_channel_set_eackm(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_EACKM ) -+#define __dmac_channel_clear_eackm(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_EACKM ) -+ -+#define __dmac_channel_set_eacks(n) \ -+ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_EACKS ) -+#define __dmac_channel_clear_eacks(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_EACKS ) -+ -+ -+#define __dmac_channel_irq_detected(n) \ -+ ( REG_DMAC_DCCSR(n) & (DMAC_DCCSR_TC | DMAC_DCCSR_AR) ) -+ -+static __inline__ int __dmac_get_irq(void) -+{ -+ int i; -+ for (i=0;i> AIC_SR_TFL_BIT ) -+#define __aic_get_receive_count() \ -+ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -+ -+#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -+#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -+#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -+#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -+#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -+ -+#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -+ -+#define CODEC_READ_CMD (1 << 19) -+#define CODEC_WRITE_CMD (0 << 19) -+#define CODEC_REG_INDEX_BIT 12 -+#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -+#define CODEC_REG_DATA_BIT 4 -+#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -+ -+#define __ac97_out_rcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_wcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_data(value) \ -+do { \ -+ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -+} while (0) -+ -+#define __ac97_in_data() \ -+ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -+ -+#define __ac97_in_status_addr() \ -+ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -+ -+#define __i2s_set_sample_rate(i2sclk, sync) \ -+ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -+ -+#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -+#define __aic_read_rfifo() ( REG_AIC_DR ) -+ -+// -+// Define next ops for AC97 compatible -+// -+ -+#define AC97_ACSR AIC_ACSR -+ -+#define __ac97_enable() __aic_enable(); __aic_select_ac97() -+#define __ac97_disable() __aic_disable() -+#define __ac97_reset() __aic_reset() -+ -+#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __ac97_enable_record() __aic_enable_record() -+#define __ac97_disable_record() __aic_disable_record() -+#define __ac97_enable_replay() __aic_enable_replay() -+#define __ac97_disable_replay() __aic_disable_replay() -+#define __ac97_enable_loopback() __aic_enable_loopback() -+#define __ac97_disable_loopback() __aic_disable_loopback() -+ -+#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -+#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __ac97_transmit_request() __aic_transmit_request() -+#define __ac97_receive_request() __aic_receive_request() -+#define __ac97_transmit_underrun() __aic_transmit_underrun() -+#define __ac97_receive_overrun() __aic_receive_overrun() -+ -+#define __ac97_clear_errors() __aic_clear_errors() -+ -+#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -+#define __ac97_get_receive_count() __aic_get_receive_count() -+ -+#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -+#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -+#define __ac97_read_rfifo() __aic_read_rfifo() -+ -+// -+// Define next ops for I2S compatible -+// -+ -+#define I2S_ACSR AIC_I2SSR -+ -+#define __i2s_enable() __aic_enable(); __aic_select_i2s() -+#define __i2s_disable() __aic_disable() -+#define __i2s_reset() __aic_reset() -+ -+#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __i2s_enable_record() __aic_enable_record() -+#define __i2s_disable_record() __aic_disable_record() -+#define __i2s_enable_replay() __aic_enable_replay() -+#define __i2s_disable_replay() __aic_disable_replay() -+#define __i2s_enable_loopback() __aic_enable_loopback() -+#define __i2s_disable_loopback() __aic_disable_loopback() -+ -+#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -+#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __i2s_transmit_request() __aic_transmit_request() -+#define __i2s_receive_request() __aic_receive_request() -+#define __i2s_transmit_underrun() __aic_transmit_underrun() -+#define __i2s_receive_overrun() __aic_receive_overrun() -+ -+#define __i2s_clear_errors() __aic_clear_errors() -+ -+#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -+#define __i2s_get_receive_count() __aic_get_receive_count() -+ -+#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -+#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -+#define __i2s_read_rfifo() __aic_read_rfifo() -+ -+#define __i2s_reset_codec() \ -+ do { \ -+ __gpio_as_output(70); /* SDATA_OUT */ \ -+ __gpio_as_input(71); /* SDATA_IN */ \ -+ __gpio_as_output(78); /* SYNC */ \ -+ __gpio_as_output(69); /* RESET# */ \ -+ __gpio_clear_pin(70); \ -+ __gpio_clear_pin(71); \ -+ __gpio_clear_pin(78); \ -+ __gpio_clear_pin(69); \ -+ __gpio_as_i2s_master(); \ -+ } while (0) -+ -+ -+/*************************************************************************** -+ * LCD -+ ***************************************************************************/ -+ -+#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS ) -+#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS ) -+ -+#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA ) -+#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA ) -+ -+/* n=1,2,4,8,16 */ -+#define __lcd_set_bpp(n) \ -+ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n ) -+ -+/* n=4,8,16 */ -+#define __lcd_set_burst_length(n) \ -+do { \ -+ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \ -+ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \ -+} while (0) -+ -+#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 ) -+#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 ) -+ -+#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP ) -+#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP ) -+ -+/* n=2,4,16 */ -+#define __lcd_set_stn_frc(n) \ -+do { \ -+ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \ -+ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \ -+} while (0) -+ -+ -+#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN ) -+#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN ) -+ -+#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN ) -+#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN ) -+ -+#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM ) -+#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM ) -+ -+#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM ) -+#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM ) -+ -+#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM ) -+#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM ) -+ -+#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 ) -+#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 ) -+ -+#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 ) -+#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 ) -+ -+#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM ) -+#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM ) -+ -+#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM ) -+#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM ) -+ -+ -+/* LCD status register indication */ -+ -+#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD ) -+#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD ) -+#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 ) -+#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 ) -+#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU ) -+#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF ) -+#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF ) -+ -+#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU ) -+#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF ) -+#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF ) -+ -+#define __lcd_panel_white() ( REG_LCD_DEV |= LCD_DEV_WHITE ) -+#define __lcd_panel_black() ( REG_LCD_DEV &= ~LCD_DEV_WHITE ) -+ -+/* n=1,2,4,8 for single mono-STN -+ * n=4,8 for dual mono-STN -+ */ -+#define __lcd_set_panel_datawidth(n) \ -+do { \ -+ REG_LCD_DEV &= ~LCD_DEV_PDW_MASK; \ -+ REG_LCD_DEV |= LCD_DEV_PDW_n##; \ -+} while (0) -+ -+/* m=LCD_DEV_MODE_GENERUIC_TFT_xxx */ -+#define __lcd_set_panel_mode(m) \ -+do { \ -+ REG_LCD_DEV &= ~LCD_DEV_MODE_MASK; \ -+ REG_LCD_DEV |= (m); \ -+} while(0) -+ -+/* n = 0-255 */ -+#define __lcd_disable_ac_bias() ( REG_LCD_IO = 0xff ) -+#define __lcd_set_ac_bias(n) \ -+do { \ -+ REG_LCD_IO &= ~LCD_IO_ACB_MASK; \ -+ REG_LCD_IO |= ((n) << LCD_IO_ACB_BIT); \ -+} while(0) -+ -+#define __lcd_io_set_dir() ( REG_LCD_IO |= LCD_IO_DIR ) -+#define __lcd_io_clr_dir() ( REG_LCD_IO &= ~LCD_IO_DIR ) -+ -+#define __lcd_io_set_dep() ( REG_LCD_IO |= LCD_IO_DEP ) -+#define __lcd_io_clr_dep() ( REG_LCD_IO &= ~LCD_IO_DEP ) -+ -+#define __lcd_io_set_vsp() ( REG_LCD_IO |= LCD_IO_VSP ) -+#define __lcd_io_clr_vsp() ( REG_LCD_IO &= ~LCD_IO_VSP ) -+ -+#define __lcd_io_set_hsp() ( REG_LCD_IO |= LCD_IO_HSP ) -+#define __lcd_io_clr_hsp() ( REG_LCD_IO &= ~LCD_IO_HSP ) -+ -+#define __lcd_io_set_pcp() ( REG_LCD_IO |= LCD_IO_PCP ) -+#define __lcd_io_clr_pcp() ( REG_LCD_IO &= ~LCD_IO_PCP ) -+ -+#define __lcd_vsync_get_vps() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT ) -+ -+#define __lcd_vsync_get_vpe() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -+#define __lcd_vsync_set_vpe(n) \ -+do { \ -+ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -+ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hps() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -+#define __lcd_hsync_set_hps(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hpe() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -+#define __lcd_hsync_set_hpe(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_ht() \ -+ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -+#define __lcd_vat_set_ht(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_vt() \ -+ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -+#define __lcd_vat_set_vt(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hds() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -+#define __lcd_dah_set_hds(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hde() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -+#define __lcd_dah_set_hde(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vds() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -+#define __lcd_dav_set_vds(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vde() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -+#define __lcd_dav_set_vde(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -+} while (0) -+ -+#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -+#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -+ -+#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -+#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -+ -+#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -+#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -+ -+#define __lcd_cmd0_get_len() \ -+ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+#define __lcd_cmd1_get_len() \ -+ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+ -+ -+ -+/*************************************************************************** -+ * DES -+ ***************************************************************************/ -+ -+ -+/*************************************************************************** -+ * CPM -+ ***************************************************************************/ -+#define __cpm_plcr1_fd() \ -+ ((REG_CPM_PLCR1 & CPM_PLCR1_PLL1FD_MASK) >> CPM_PLCR1_PLL1FD_BIT) -+#define __cpm_plcr1_rd() \ -+ ((REG_CPM_PLCR1 & CPM_PLCR1_PLL1RD_MASK) >> CPM_PLCR1_PLL1RD_BIT) -+#define __cpm_plcr1_od() \ -+ ((REG_CPM_PLCR1 & CPM_PLCR1_PLL1OD_MASK) >> CPM_PLCR1_PLL1OD_BIT) -+#define __cpm_cfcr_mfr() \ -+ ((REG_CPM_CFCR & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT) -+#define __cpm_cfcr_pfr() \ -+ ((REG_CPM_CFCR & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT) -+#define __cpm_cfcr_sfr() \ -+ ((REG_CPM_CFCR & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT) -+#define __cpm_cfcr_ifr() \ -+ ((REG_CPM_CFCR & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT) -+ -+static __inline__ unsigned int __cpm_divisor_encode(unsigned int n) -+{ -+ unsigned int encode[10] = {1,2,3,4,6,8,12,16,24,32}; -+ int i; -+ for (i=0;i<10;i++) -+ if (n < encode[i]) -+ break; -+ return i; -+} -+ -+#define __cpm_set_mclk_div(n) \ -+do { \ -+ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_MFR_MASK) | \ -+ ((n) << (CPM_CFCR_MFR_BIT)); \ -+} while (0) -+ -+#define __cpm_set_pclk_div(n) \ -+do { \ -+ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_PFR_MASK) | \ -+ ((n) << (CPM_CFCR_PFR_BIT)); \ -+} while (0) -+ -+#define __cpm_set_sclk_div(n) \ -+do { \ -+ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_SFR_MASK) | \ -+ ((n) << (CPM_CFCR_SFR_BIT)); \ -+} while (0) -+ -+#define __cpm_set_iclk_div(n) \ -+do { \ -+ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_IFR_MASK) | \ -+ ((n) << (CPM_CFCR_IFR_BIT)); \ -+} while (0) -+ -+#define __cpm_set_lcdclk_div(n) \ -+do { \ -+ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_LFR_MASK) | \ -+ ((n) << (CPM_CFCR_LFR_BIT)); \ -+} while (0) -+ -+#define __cpm_enable_cko1() (REG_CPM_CFCR |= CPM_CFCR_CKOEN1) -+#define __cpm_enable_cko2() (REG_CPM_CFCR |= CPM_CFCR_CKOEN2) -+#define __cpm_disable_cko1() (REG_CPM_CFCR &= ~CPM_CFCR_CKOEN1) -+#define __cpm_disable_cko2() (REG_CPM_CFCR &= ~CPM_CFCR_CKOEN2) -+ -+#define __cpm_select_msc_clk(type) \ -+do { \ -+ if (type == 0) \ -+ REG_CPM_CFCR &= ~CPM_CFCR_MSC; \ -+ else \ -+ REG_CPM_CFCR |= CPM_CFCR_MSC; \ -+ REG_CPM_CFCR |= CPM_CFCR_UPE; \ -+} while(0) -+ -+#define __cpm_idle_mode() \ -+ (REG_CPM_LPCR = (REG_CPM_LPCR & ~CPM_LPCR_LPM_MASK) | \ -+ CPM_LPCR_LPM_IDLE) -+#define __cpm_sleep_mode() \ -+ (REG_CPM_LPCR = (REG_CPM_LPCR & ~CPM_LPCR_LPM_MASK) | \ -+ CPM_LPCR_LPM_SLEEP) -+#define __cpm_hibernate_mode() \ -+ (REG_CPM_LPCR = (REG_CPM_LPCR & ~CPM_LPCR_LPM_MASK) | \ -+ CPM_LPCR_LPM_HIBERNATE) -+ -+#define __cpm_start_uart0() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART0)) -+#define __cpm_start_uart1() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART1)) -+#define __cpm_start_uart2() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART2)) -+#define __cpm_start_uart3() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART3)) -+#define __cpm_start_ost() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_OST)) -+#define __cpm_start_dmac() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_DMAC)) -+#define __cpm_start_uhc() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UHC)) -+#define __cpm_start_lcd() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_LCD)) -+#define __cpm_start_i2c() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_I2C)) -+#define __cpm_start_aic_pclk() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_AICPCLK)) -+#define __cpm_start_aic_bitclk() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_AICBCLK)) -+#define __cpm_start_pwm0() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_PWM0)) -+#define __cpm_start_pwm1() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_PWM1)) -+#define __cpm_start_ssi() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_SSI)) -+#define __cpm_start_msc() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_MSC)) -+#define __cpm_start_scc() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_SCC)) -+#define __cpm_start_eth() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_ETH)) -+#define __cpm_start_kbc() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_KBC)) -+#define __cpm_start_cim() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_CIM)) -+#define __cpm_start_udc() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UDC)) -+#define __cpm_start_uprt() \ -+ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UPRT)) -+#define __cpm_start_all() (REG_CPM_MSCR = 0) -+ -+#define __cpm_stop_uart0() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART0)) -+#define __cpm_stop_uart1() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART1)) -+#define __cpm_stop_uart2() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART2)) -+#define __cpm_stop_uart3() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART3)) -+#define __cpm_stop_ost() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_OST)) -+#define __cpm_stop_dmac() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_DMAC)) -+#define __cpm_stop_uhc() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UHC)) -+#define __cpm_stop_lcd() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_LCD)) -+#define __cpm_stop_i2c() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_I2C)) -+#define __cpm_stop_aic_pclk() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_AICPCLK)) -+#define __cpm_stop_aic_bitclk() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_AICBCLK)) -+#define __cpm_stop_pwm0() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_PWM0)) -+#define __cpm_stop_pwm1() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_PWM1)) -+#define __cpm_stop_ssi() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_SSI)) -+#define __cpm_stop_msc() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_MSC)) -+#define __cpm_stop_scc() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_SCC)) -+#define __cpm_stop_eth() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_ETH)) -+#define __cpm_stop_kbc() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_KBC)) -+#define __cpm_stop_cim() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_CIM)) -+#define __cpm_stop_udc() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UDC)) -+#define __cpm_stop_uprt() \ -+ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UPRT)) -+#define __cpm_stop_all() (REG_CPM_MSCR = 0xffffffff) -+ -+#define __cpm_set_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ if (p == 0) \ -+ REG_CPM_GSR0 |= (1 << o); \ -+ else if (p == 1) \ -+ REG_CPM_GSR1 |= (1 << o); \ -+ else if (p == 2) \ -+ REG_CPM_GSR2 |= (1 << o); \ -+ else if (p == 3) \ -+ REG_CPM_GSR3 |= (1 << o); \ -+} while (0) -+ -+#define __cpm_clear_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ if (p == 0) \ -+ REG_CPM_GSR0 &= ~(1 << o); \ -+ else if (p == 1) \ -+ REG_CPM_GSR1 &= ~(1 << o); \ -+ else if (p == 2) \ -+ REG_CPM_GSR2 &= ~(1 << o); \ -+ else if (p == 3) \ -+ REG_CPM_GSR3 &= ~(1 << o); \ -+} while (0) -+ -+ -+/*************************************************************************** -+ * SSI -+ ***************************************************************************/ -+ -+#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE ) -+#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE ) -+#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL ) -+ -+#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK ) -+ -+#define __ssi_select_ce2() \ -+do { \ -+ REG_SSI_CR0 |= SSI_CR0_FSEL; \ -+ REG_SSI_CR1 &= ~SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_select_gpc() \ -+do { \ -+ REG_SSI_CR0 &= ~SSI_CR0_FSEL; \ -+ REG_SSI_CR1 |= SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_enable_tx_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE ) -+ -+#define __ssi_disable_tx_intr() \ -+ ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -+ -+#define __ssi_enable_rx_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE ) -+ -+#define __ssi_disable_rx_intr() \ -+ ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -+ -+#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP ) -+#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP ) -+ -+#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV ) -+#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV ) -+ -+#define __ssi_finish_receive() \ -+ ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_disable_recvfinish() \ -+ ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH ) -+#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH ) -+ -+#define __ssi_flush_fifo() \ -+ ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -+ -+#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN ) -+ -+#define __ssi_spi_format() \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \ -+ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -+ REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -+} while (0) -+ -+/* TI's SSP format, must clear SSI_CR1.UNFIN */ -+#define __ssi_ssp_format() \ -+do { \ -+ REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -+ REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \ -+} while (0) -+ -+/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -+#define __ssi_microwire_format() \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \ -+ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -+ REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -+ REG_SSI_CR0 &= ~SSI_CR0_RFINE; \ -+} while (0) -+ -+/* CE# level (FRMHL), CE# in interval time (ITFRM), -+ clock phase and polarity (PHA POL), -+ interval time (SSIITR), interval characters/frame (SSIICR) */ -+ -+ /* frmhl,endian,mcom,flen,pha,pol MASK */ -+#define SSICR1_MISC_MASK \ -+ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -+ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \ -+ -+#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \ -+do { \ -+ REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \ -+ REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \ -+ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -+ ((pha) << 1) | (pol); \ -+} while(0) -+ -+/* Transfer with MSB or LSB first */ -+#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST ) -+#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST ) -+ -+#define __ssi_set_frame_length(n) \ -+ REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4) -+ -+/* n = 1 - 16 */ -+#define __ssi_set_microwire_command_length(n) \ -+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) ) -+ -+/* Set the clock phase for SPI */ -+#define __ssi_set_spi_clock_phase(n) \ -+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | ((n&0x1) << 1 ))) -+ -+/* Set the clock polarity for SPI */ -+#define __ssi_set_spi_clock_polarity(n) \ -+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | ((n&0x1) << 0 ))) -+ -+/* n = 1,4,8,14 */ -+#define __ssi_set_tx_trigger(n) \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \ -+ REG_SSI_CR1 |= SSI_CR1_TTRG_##n; \ -+} while (0) -+ -+/* n = 1,4,8,14 */ -+#define __ssi_set_rx_trigger(n) \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_RTRG_MASK; \ -+ REG_SSI_CR1 |= SSI_CR1_RTRG_##n; \ -+} while (0) -+ -+#define __ssi_get_txfifo_count() \ -+ ( (REG_SSI_SR & SSI_SR_TFIFONUM_MASK) >> SSI_SR_TFIFONUM_BIT ) -+ -+#define __ssi_get_rxfifo_count() \ -+ ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -+ -+#define __ssi_clear_errors() \ -+ ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -+ -+#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END ) -+#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY ) -+ -+#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF ) -+#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE ) -+#define __ssi_rxfifo_noempty() ( REG_SSI_SR & SSI_SR_RFHF ) -+#define __ssi_rxfifo_half_full() ( REG_SSI_SR & SSI_SR_RFHF ) -+#define __ssi_txfifo_half_empty() ( REG_SSI_SR & SSI_SR_TFHE ) -+#define __ssi_underrun() ( REG_SSI_SR & SSI_SR_UNDR ) -+#define __ssi_overrun() ( REG_SSI_SR & SSI_SR_OVER ) -+ -+#define __ssi_set_clk(dev_clk, ssi_clk) \ -+ ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 ) -+ -+#define __ssi_receive_data() REG_SSI_DR -+#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) ) -+ -+#endif /* __ASM_JZ4730_OPS_H__ */ -diff --git a/include/asm-mips/mach-jz4730/regs.h b/include/asm-mips/mach-jz4730/regs.h -new file mode 100644 -index 0000000..86bde91 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/regs.h -@@ -0,0 +1,2550 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/regs.h -+ * -+ * JZ4730 registers definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_REGS_H__ -+#define __ASM_JZ4730_REGS_H__ -+ -+#if defined(__ASSEMBLY__) || defined(__LANGUAGE_ASSEMBLY) -+#define REG8(addr) (addr) -+#define REG16(addr) (addr) -+#define REG32(addr) (addr) -+#else -+#define REG8(addr) *((volatile unsigned char *)(addr)) -+#define REG16(addr) *((volatile unsigned short *)(addr)) -+#define REG32(addr) *((volatile unsigned int *)(addr)) -+#endif -+ -+#define HARB_BASE 0xB3000000 -+#define EMC_BASE 0xB3010000 -+#define DMAC_BASE 0xB3020000 -+#define UHC_BASE 0xB3030000 -+#define UDC_BASE 0xB3040000 -+#define LCD_BASE 0xB3050000 -+#define CIM_BASE 0xB3060000 -+#define ETH_BASE 0xB3100000 -+#define NBM_BASE 0xB3F00000 -+ -+#define CPM_BASE 0xB0000000 -+#define INTC_BASE 0xB0001000 -+#define OST_BASE 0xB0002000 -+#define RTC_BASE 0xB0003000 -+#define WDT_BASE 0xB0004000 -+#define GPIO_BASE 0xB0010000 -+#define AIC_BASE 0xB0020000 -+#define MSC_BASE 0xB0021000 -+#define UART0_BASE 0xB0030000 -+#define UART1_BASE 0xB0031000 -+#define UART2_BASE 0xB0032000 -+#define UART3_BASE 0xB0033000 -+#define FIR_BASE 0xB0040000 -+#define SCC_BASE 0xB0041000 -+#define SCC0_BASE 0xB0041000 -+#define I2C_BASE 0xB0042000 -+#define SSI_BASE 0xB0043000 -+#define SCC1_BASE 0xB0044000 -+#define PWM0_BASE 0xB0050000 -+#define PWM1_BASE 0xB0051000 -+#define DES_BASE 0xB0060000 -+#define UPRT_BASE 0xB0061000 -+#define KBC_BASE 0xB0062000 -+ -+ -+ -+ -+/************************************************************************* -+ * MSC -+ *************************************************************************/ -+#define MSC_STRPCL (MSC_BASE + 0x000) -+#define MSC_STAT (MSC_BASE + 0x004) -+#define MSC_CLKRT (MSC_BASE + 0x008) -+#define MSC_CMDAT (MSC_BASE + 0x00C) -+#define MSC_RESTO (MSC_BASE + 0x010) -+#define MSC_RDTO (MSC_BASE + 0x014) -+#define MSC_BLKLEN (MSC_BASE + 0x018) -+#define MSC_NOB (MSC_BASE + 0x01C) -+#define MSC_SNOB (MSC_BASE + 0x020) -+#define MSC_IMASK (MSC_BASE + 0x024) -+#define MSC_IREG (MSC_BASE + 0x028) -+#define MSC_CMD (MSC_BASE + 0x02C) -+#define MSC_ARG (MSC_BASE + 0x030) -+#define MSC_RES (MSC_BASE + 0x034) -+#define MSC_RXFIFO (MSC_BASE + 0x038) -+#define MSC_TXFIFO (MSC_BASE + 0x03C) -+ -+#define REG_MSC_STRPCL REG16(MSC_STRPCL) -+#define REG_MSC_STAT REG32(MSC_STAT) -+#define REG_MSC_CLKRT REG16(MSC_CLKRT) -+#define REG_MSC_CMDAT REG32(MSC_CMDAT) -+#define REG_MSC_RESTO REG16(MSC_RESTO) -+#define REG_MSC_RDTO REG16(MSC_RDTO) -+#define REG_MSC_BLKLEN REG16(MSC_BLKLEN) -+#define REG_MSC_NOB REG16(MSC_NOB) -+#define REG_MSC_SNOB REG16(MSC_SNOB) -+#define REG_MSC_IMASK REG16(MSC_IMASK) -+#define REG_MSC_IREG REG16(MSC_IREG) -+#define REG_MSC_CMD REG8(MSC_CMD) -+#define REG_MSC_ARG REG32(MSC_ARG) -+#define REG_MSC_RES REG16(MSC_RES) -+#define REG_MSC_RXFIFO REG32(MSC_RXFIFO) -+#define REG_MSC_TXFIFO REG32(MSC_TXFIFO) -+ -+/* MSC Clock and Control Register (MSC_STRPCL) */ -+ -+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -+#define MSC_STRPCL_START_READWAIT (1 << 5) -+#define MSC_STRPCL_STOP_READWAIT (1 << 4) -+#define MSC_STRPCL_RESET (1 << 3) -+#define MSC_STRPCL_START_OP (1 << 2) -+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -+ -+/* MSC Status Register (MSC_STAT) */ -+ -+#define MSC_STAT_IS_RESETTING (1 << 15) -+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -+#define MSC_STAT_PRG_DONE (1 << 13) -+#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -+#define MSC_STAT_END_CMD_RES (1 << 11) -+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -+#define MSC_STAT_IS_READWAIT (1 << 9) -+#define MSC_STAT_CLK_EN (1 << 8) -+#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -+#define MSC_STAT_CRC_RES_ERR (1 << 5) -+#define MSC_STAT_CRC_READ_ERROR (1 << 4) -+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -+#define MSC_STAT_TIME_OUT_RES (1 << 1) -+#define MSC_STAT_TIME_OUT_READ (1 << 0) -+ -+/* MSC Bus Clock Control Register (MSC_CLKRT) */ -+ -+#define MSC_CLKRT_CLK_RATE_BIT 0 -+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -+ -+/* MSC Command Sequence Control Register (MSC_CMDAT) */ -+ -+#define MSC_CMDAT_IO_ABORT (1 << 11) -+#define MSC_CMDAT_BUS_WIDTH_BIT 9 -+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -+ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -+ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -+ #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) -+ #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) -+#define MSC_CMDAT_DMA_EN (1 << 8) -+#define MSC_CMDAT_INIT (1 << 7) -+#define MSC_CMDAT_BUSY (1 << 6) -+#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -+#define MSC_CMDAT_WRITE (1 << 4) -+#define MSC_CMDAT_READ (0 << 4) -+#define MSC_CMDAT_DATA_EN (1 << 3) -+#define MSC_CMDAT_RESPONSE_BIT 0 -+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -+ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -+ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -+ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -+ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -+ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -+ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -+ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -+ -+#define CMDAT_DMA_EN (1 << 8) -+#define CMDAT_INIT (1 << 7) -+#define CMDAT_BUSY (1 << 6) -+#define CMDAT_STREAM (1 << 5) -+#define CMDAT_WRITE (1 << 4) -+#define CMDAT_DATA_EN (1 << 3) -+ -+/* MSC Interrupts Mask Register (MSC_IMASK) */ -+ -+#define MSC_IMASK_SDIO (1 << 7) -+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IMASK_END_CMD_RES (1 << 2) -+#define MSC_IMASK_PRG_DONE (1 << 1) -+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -+ -+ -+/* MSC Interrupts Status Register (MSC_IREG) */ -+ -+#define MSC_IREG_SDIO (1 << 7) -+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IREG_END_CMD_RES (1 << 2) -+#define MSC_IREG_PRG_DONE (1 << 1) -+#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -+ -+ -+ -+ -+/************************************************************************* -+ * RTC -+ *************************************************************************/ -+#define RTC_RCR (RTC_BASE + 0x00) -+#define RTC_RSR (RTC_BASE + 0x04) -+#define RTC_RSAR (RTC_BASE + 0x08) -+#define RTC_RGR (RTC_BASE + 0x0c) -+ -+#define REG_RTC_RCR REG32(RTC_RCR) -+#define REG_RTC_RSR REG32(RTC_RSR) -+#define REG_RTC_RSAR REG32(RTC_RSAR) -+#define REG_RTC_RGR REG32(RTC_RGR) -+ -+#define RTC_RCR_HZ (1 << 6) -+#define RTC_RCR_HZIE (1 << 5) -+#define RTC_RCR_AF (1 << 4) -+#define RTC_RCR_AIE (1 << 3) -+#define RTC_RCR_AE (1 << 2) -+#define RTC_RCR_START (1 << 0) -+ -+#define RTC_RGR_LOCK (1 << 31) -+#define RTC_RGR_ADJ_BIT 16 -+#define RTC_RGR_ADJ_MASK (0x3ff << RTC_RGR_ADJ_BIT) -+#define RTC_RGR_DIV_BIT 0 -+#define RTC_REG_DIV_MASK (0xff << RTC_RGR_DIV_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * FIR -+ *************************************************************************/ -+#define FIR_TDR (FIR_BASE + 0x000) -+#define FIR_RDR (FIR_BASE + 0x004) -+#define FIR_TFLR (FIR_BASE + 0x008) -+#define FIR_AR (FIR_BASE + 0x00C) -+#define FIR_CR1 (FIR_BASE + 0x010) -+#define FIR_CR2 (FIR_BASE + 0x014) -+#define FIR_SR (FIR_BASE + 0x018) -+ -+#define REG_FIR_TDR REG8(FIR_TDR) -+#define REG_FIR_RDR REG8(FIR_RDR) -+#define REG_FIR_TFLR REG16(FIR_TFLR) -+#define REG_FIR_AR REG8(FIR_AR) -+#define REG_FIR_CR1 REG8(FIR_CR1) -+#define REG_FIR_CR2 REG16(FIR_CR2) -+#define REG_FIR_SR REG16(FIR_SR) -+ -+/* FIR Control Register 1 (FIR_CR1) */ -+ -+#define FIR_CR1_FIRUE (1 << 7) -+#define FIR_CR1_ACE (1 << 6) -+#define FIR_CR1_EOUS (1 << 5) -+#define FIR_CR1_TIIE (1 << 4) -+#define FIR_CR1_TFIE (1 << 3) -+#define FIR_CR1_RFIE (1 << 2) -+#define FIR_CR1_TXE (1 << 1) -+#define FIR_CR1_RXE (1 << 0) -+ -+/* FIR Control Register 2 (FIR_CR2) */ -+ -+#define FIR_CR2_SIPE (1 << 10) -+#define FIR_CR2_BCRC (1 << 9) -+#define FIR_CR2_TFLRS (1 << 8) -+#define FIR_CR2_ISS (1 << 7) -+#define FIR_CR2_LMS (1 << 6) -+#define FIR_CR2_TPPS (1 << 5) -+#define FIR_CR2_RPPS (1 << 4) -+#define FIR_CR2_TTRG_BIT 2 -+#define FIR_CR2_TTRG_MASK (0x3 << FIR_CR2_TTRG_BIT) -+ #define FIR_CR2_TTRG_16 (0 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 16 */ -+ #define FIR_CR2_TTRG_32 (1 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 32 */ -+ #define FIR_CR2_TTRG_64 (2 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 64 */ -+ #define FIR_CR2_TTRG_128 (3 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 128 */ -+#define FIR_CR2_RTRG_BIT 0 -+#define FIR_CR2_RTRG_MASK (0x3 << FIR_CR2_RTRG_BIT) -+ #define FIR_CR2_RTRG_16 (0 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 16 */ -+ #define FIR_CR2_RTRG_32 (1 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 32 */ -+ #define FIR_CR2_RTRG_64 (2 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 64 */ -+ #define FIR_CR2_RTRG_128 (3 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 128 */ -+ -+/* FIR Status Register (FIR_SR) */ -+ -+#define FIR_SR_RFW (1 << 12) -+#define FIR_SR_RFA (1 << 11) -+#define FIR_SR_TFRTL (1 << 10) -+#define FIR_SR_RFRTL (1 << 9) -+#define FIR_SR_URUN (1 << 8) -+#define FIR_SR_RFTE (1 << 7) -+#define FIR_SR_ORUN (1 << 6) -+#define FIR_SR_CRCE (1 << 5) -+#define FIR_SR_FEND (1 << 4) -+#define FIR_SR_TFF (1 << 3) -+#define FIR_SR_RFE (1 << 2) -+#define FIR_SR_TIDLE (1 << 1) -+#define FIR_SR_RB (1 << 0) -+ -+ -+ -+ -+/************************************************************************* -+ * SCC -+ *************************************************************************/ -+#define SCC_DR(base) ((base) + 0x000) -+#define SCC_FDR(base) ((base) + 0x004) -+#define SCC_CR(base) ((base) + 0x008) -+#define SCC1_CR(base) ((base) + 0x008) -+#define SCC_SR(base) ((base) + 0x00C) -+#define SCC_TFR(base) ((base) + 0x010) -+#define SCC_EGTR(base) ((base) + 0x014) -+#define SCC_ECR(base) ((base) + 0x018) -+#define SCC_RTOR(base) ((base) + 0x01C) -+ -+#define REG_SCC_DR(base) REG8(SCC_DR(base)) -+#define REG_SCC_FDR(base) REG8(SCC_FDR(base)) -+#define REG_SCC_CR(base) REG32(SCC_CR(base)) -+#define REG_SCC1_CR(base) REG32(SCC1_CR(base)) -+#define REG_SCC_SR(base) REG16(SCC_SR(base)) -+#define REG_SCC_TFR(base) REG16(SCC_TFR(base)) -+#define REG_SCC_EGTR(base) REG8(SCC_EGTR(base)) -+#define REG_SCC_ECR(base) REG32(SCC_ECR(base)) -+#define REG_SCC_RTOR(base) REG8(SCC_RTOR(base)) -+ -+/* SCC FIFO Data Count Register (SCC_FDR) */ -+ -+#define SCC_FDR_EMPTY 0x00 -+#define SCC_FDR_FULL 0x10 -+ -+/* SCC Control Register (SCC_CR) */ -+ -+#define SCC_CR_SCCE (1 << 31) -+#define SCC_CR_TRS (1 << 30) -+#define SCC_CR_T2R (1 << 29) -+#define SCC_CR_FDIV_BIT 24 -+#define SCC_CR_FDIV_MASK (0x3 << SCC_CR_FDIV_BIT) -+ #define SCC_CR_FDIV_1 (0 << SCC_CR_FDIV_BIT) /* SCC_CLK frequency is the same as device clock */ -+ #define SCC_CR_FDIV_2 (1 << SCC_CR_FDIV_BIT) /* SCC_CLK frequency is half of device clock */ -+#define SCC_CR_FLUSH (1 << 23) -+#define SCC_CR_TRIG_BIT 16 -+#define SCC_CR_TRIG_MASK (0x3 << SCC_CR_TRIG_BIT) -+ #define SCC_CR_TRIG_1 (0 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 1 */ -+ #define SCC_CR_TRIG_4 (1 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 4 */ -+ #define SCC_CR_TRIG_8 (2 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 8 */ -+ #define SCC_CR_TRIG_14 (3 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 14 */ -+#define SCC_CR_TP (1 << 15) -+#define SCC_CR_CONV (1 << 14) -+#define SCC_CR_TXIE (1 << 13) -+#define SCC_CR_RXIE (1 << 12) -+#define SCC_CR_TENDIE (1 << 11) -+#define SCC_CR_RTOIE (1 << 10) -+#define SCC_CR_ECIE (1 << 9) -+#define SCC_CR_EPIE (1 << 8) -+#define SCC_CR_RETIE (1 << 7) -+#define SCC_CR_EOIE (1 << 6) -+#define SCC_CR_TSEND (1 << 3) -+#define SCC_CR_PX_BIT 1 -+#define SCC_CR_PX_MASK (0x3 << SCC_CR_PX_BIT) -+ #define SCC_CR_PX_NOT_SUPPORT (0 << SCC_CR_PX_BIT) /* SCC does not support clock stop */ -+ #define SCC_CR_PX_STOP_LOW (1 << SCC_CR_PX_BIT) /* SCC_CLK stops at state low */ -+ #define SCC_CR_PX_STOP_HIGH (2 << SCC_CR_PX_BIT) /* SCC_CLK stops at state high */ -+#define SCC_CR_CLKSTP (1 << 0) -+ -+/* SCC Status Register (SCC_SR) */ -+ -+#define SCC_SR_TRANS (1 << 15) -+#define SCC_SR_ORER (1 << 12) -+#define SCC_SR_RTO (1 << 11) -+#define SCC_SR_PER (1 << 10) -+#define SCC_SR_TFTG (1 << 9) -+#define SCC_SR_RFTG (1 << 8) -+#define SCC_SR_TEND (1 << 7) -+#define SCC_SR_RETR_3 (1 << 4) -+#define SCC_SR_ECNTO (1 << 0) -+ -+ -+ -+ -+/************************************************************************* -+ * ETH -+ *************************************************************************/ -+#define ETH_BMR (ETH_BASE + 0x1000) -+#define ETH_TPDR (ETH_BASE + 0x1004) -+#define ETH_RPDR (ETH_BASE + 0x1008) -+#define ETH_RAR (ETH_BASE + 0x100C) -+#define ETH_TAR (ETH_BASE + 0x1010) -+#define ETH_SR (ETH_BASE + 0x1014) -+#define ETH_CR (ETH_BASE + 0x1018) -+#define ETH_IER (ETH_BASE + 0x101C) -+#define ETH_MFCR (ETH_BASE + 0x1020) -+#define ETH_CTAR (ETH_BASE + 0x1050) -+#define ETH_CRAR (ETH_BASE + 0x1054) -+#define ETH_MCR (ETH_BASE + 0x0000) -+#define ETH_MAHR (ETH_BASE + 0x0004) -+#define ETH_MALR (ETH_BASE + 0x0008) -+#define ETH_HTHR (ETH_BASE + 0x000C) -+#define ETH_HTLR (ETH_BASE + 0x0010) -+#define ETH_MIAR (ETH_BASE + 0x0014) -+#define ETH_MIDR (ETH_BASE + 0x0018) -+#define ETH_FCR (ETH_BASE + 0x001C) -+#define ETH_VTR1 (ETH_BASE + 0x0020) -+#define ETH_VTR2 (ETH_BASE + 0x0024) -+#define ETH_WKFR (ETH_BASE + 0x0028) -+#define ETH_PMTR (ETH_BASE + 0x002C) -+ -+#define REG_ETH_BMR REG32(ETH_BMR) -+#define REG_ETH_TPDR REG32(ETH_TPDR) -+#define REG_ETH_RPDR REG32(ETH_RPDR) -+#define REG_ETH_RAR REG32(ETH_RAR) -+#define REG_ETH_TAR REG32(ETH_TAR) -+#define REG_ETH_SR REG32(ETH_SR) -+#define REG_ETH_CR REG32(ETH_CR) -+#define REG_ETH_IER REG32(ETH_IER) -+#define REG_ETH_MFCR REG32(ETH_MFCR) -+#define REG_ETH_CTAR REG32(ETH_CTAR) -+#define REG_ETH_CRAR REG32(ETH_CRAR) -+#define REG_ETH_MCR REG32(ETH_MCR) -+#define REG_ETH_MAHR REG32(ETH_MAHR) -+#define REG_ETH_MALR REG32(ETH_MALR) -+#define REG_ETH_HTHR REG32(ETH_HTHR) -+#define REG_ETH_HTLR REG32(ETH_HTLR) -+#define REG_ETH_MIAR REG32(ETH_MIAR) -+#define REG_ETH_MIDR REG32(ETH_MIDR) -+#define REG_ETH_FCR REG32(ETH_FCR) -+#define REG_ETH_VTR1 REG32(ETH_VTR1) -+#define REG_ETH_VTR2 REG32(ETH_VTR2) -+#define REG_ETH_WKFR REG32(ETH_WKFR) -+#define REG_ETH_PMTR REG32(ETH_PMTR) -+ -+/* Bus Mode Register (ETH_BMR) */ -+ -+#define ETH_BMR_DBO (1 << 20) -+#define ETH_BMR_PBL_BIT 8 -+#define ETH_BMR_PBL_MASK (0x3f << ETH_BMR_PBL_BIT) -+ #define ETH_BMR_PBL_1 (0x1 << ETH_BMR_PBL_BIT) -+ #define ETH_BMR_PBL_4 (0x4 << ETH_BMR_PBL_BIT) -+#define ETH_BMR_BLE (1 << 7) -+#define ETH_BMR_DSL_BIT 2 -+#define ETH_BMR_DSL_MASK (0x1f << ETH_BMR_DSL_BIT) -+ #define ETH_BMR_DSL_0 (0x0 << ETH_BMR_DSL_BIT) -+ #define ETH_BMR_DSL_1 (0x1 << ETH_BMR_DSL_BIT) -+ #define ETH_BMR_DSL_2 (0x2 << ETH_BMR_DSL_BIT) -+ #define ETH_BMR_DSL_4 (0x4 << ETH_BMR_DSL_BIT) -+ #define ETH_BMR_DSL_8 (0x8 << ETH_BMR_DSL_BIT) -+#define ETH_BMR_SWR (1 << 0) -+ -+/* DMA Status Register (ETH_SR) */ -+ -+#define ETH_SR_EB_BIT 23 -+#define ETH_SR_EB_MASK (0x7 << ETH_SR_EB_BIT) -+ #define ETH_SR_EB_TX_ABORT (0x1 << ETH_SR_EB_BIT) -+ #define ETH_SR_EB_RX_ABORT (0x2 << ETH_SR_EB_BIT) -+#define ETH_SR_TS_BIT 20 -+#define ETH_SR_TS_MASK (0x7 << ETH_SR_TS_BIT) -+ #define ETH_SR_TS_STOP (0x0 << ETH_SR_TS_BIT) -+ #define ETH_SR_TS_FTD (0x1 << ETH_SR_TS_BIT) -+ #define ETH_SR_TS_WEOT (0x2 << ETH_SR_TS_BIT) -+ #define ETH_SR_TS_QDAT (0x3 << ETH_SR_TS_BIT) -+ #define ETH_SR_TS_SUSPEND (0x6 << ETH_SR_TS_BIT) -+ #define ETH_SR_TS_CTD (0x7 << ETH_SR_TS_BIT) -+#define ETH_SR_RS_BIT 17 -+#define ETH_SR_RS_MASK (0x7 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_STOP (0x0 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_FRD (0x1 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_CEOR (0x2 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_WRP (0x3 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_SUSPEND (0x4 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_CRD (0x5 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_FCF (0x6 << ETH_SR_RS_BIT) -+ #define ETH_SR_RS_QRF (0x7 << ETH_SR_RS_BIT) -+#define ETH_SR_NIS (1 << 16) -+#define ETH_SR_AIS (1 << 15) -+#define ETH_SR_ERI (1 << 14) -+#define ETH_SR_FBE (1 << 13) -+#define ETH_SR_ETI (1 << 10) -+#define ETH_SR_RWT (1 << 9) -+#define ETH_SR_RPS (1 << 8) -+#define ETH_SR_RU (1 << 7) -+#define ETH_SR_RI (1 << 6) -+#define ETH_SR_UNF (1 << 5) -+#define ETH_SR_TJT (1 << 3) -+#define ETH_SR_TU (1 << 2) -+#define ETH_SR_TPS (1 << 1) -+#define ETH_SR_TI (1 << 0) -+ -+/* Control (Operation Mode) Register (ETH_CR) */ -+ -+#define ETH_CR_TTM (1 << 22) -+#define ETH_CR_SF (1 << 21) -+#define ETH_CR_TR_BIT 14 -+#define ETH_CR_TR_MASK (0x3 << ETH_CR_TR_BIT) -+#define ETH_CR_ST (1 << 13) -+#define ETH_CR_OSF (1 << 2) -+#define ETH_CR_SR (1 << 1) -+ -+/* Interrupt Enable Register (ETH_IER) */ -+ -+#define ETH_IER_NI (1 << 16) -+#define ETH_IER_AI (1 << 15) -+#define ETH_IER_ERE (1 << 14) -+#define ETH_IER_FBE (1 << 13) -+#define ETH_IER_ET (1 << 10) -+#define ETH_IER_RWE (1 << 9) -+#define ETH_IER_RS (1 << 8) -+#define ETH_IER_RU (1 << 7) -+#define ETH_IER_RI (1 << 6) -+#define ETH_IER_UN (1 << 5) -+#define ETH_IER_TJ (1 << 3) -+#define ETH_IER_TU (1 << 2) -+#define ETH_IER_TS (1 << 1) -+#define ETH_IER_TI (1 << 0) -+ -+/* Missed Frame and Buffer Overflow Counter Register (ETH_MFCR) */ -+ -+#define ETH_MFCR_OVERFLOW_BIT 17 -+#define ETH_MFCR_OVERFLOW_MASK (0x7ff << ETH_MFCR_OVERFLOW_BIT) -+#define ETH_MFCR_MFC_BIT 0 -+#define ETH_MFCR_MFC_MASK (0xffff << ETH_MFCR_MFC_BIT) -+ -+/* MAC Control Register (ETH_MCR) */ -+ -+#define ETH_MCR_RA (1 << 31) -+#define ETH_MCR_HBD (1 << 28) -+#define ETH_MCR_PS (1 << 27) -+#define ETH_MCR_DRO (1 << 23) -+#define ETH_MCR_OM_BIT 21 -+#define ETH_MCR_OM_MASK (0x3 << ETH_MCR_OM_BIT) -+ #define ETH_MCR_OM_NORMAL (0x0 << ETH_MCR_OM_BIT) -+ #define ETH_MCR_OM_INTERNAL (0x1 << ETH_MCR_OM_BIT) -+ #define ETH_MCR_OM_EXTERNAL (0x2 << ETH_MCR_OM_BIT) -+#define ETH_MCR_F (1 << 20) -+#define ETH_MCR_PM (1 << 19) -+#define ETH_MCR_PR (1 << 18) -+#define ETH_MCR_IF (1 << 17) -+#define ETH_MCR_PB (1 << 16) -+#define ETH_MCR_HO (1 << 15) -+#define ETH_MCR_HP (1 << 13) -+#define ETH_MCR_LCC (1 << 12) -+#define ETH_MCR_DBF (1 << 11) -+#define ETH_MCR_DTRY (1 << 10) -+#define ETH_MCR_ASTP (1 << 8) -+#define ETH_MCR_BOLMT_BIT 6 -+#define ETH_MCR_BOLMT_MASK (0x3 << ETH_MCR_BOLMT_BIT) -+ #define ETH_MCR_BOLMT_10 (0 << ETH_MCR_BOLMT_BIT) -+ #define ETH_MCR_BOLMT_8 (1 << ETH_MCR_BOLMT_BIT) -+ #define ETH_MCR_BOLMT_4 (2 << ETH_MCR_BOLMT_BIT) -+ #define ETH_MCR_BOLMT_1 (3 << ETH_MCR_BOLMT_BIT) -+#define ETH_MCR_DC (1 << 5) -+#define ETH_MCR_TE (1 << 3) -+#define ETH_MCR_RE (1 << 2) -+ -+/* MII Address Register (ETH_MIAR) */ -+ -+#define ETH_MIAR_PHY_ADDR_BIT 11 -+#define ETH_MIAR_PHY_ADDR_MASK (0x1f << ETH_MIAR_PHY_ADDR_BIT) -+#define ETH_MIAR_MII_REG_BIT 6 -+#define ETH_MIAR_MII_REG_MASK (0x1f << ETH_MIAR_MII_REG_BIT) -+#define ETH_MIAR_MII_WRITE (1 << 1) -+#define ETH_MIAR_MII_BUSY (1 << 0) -+ -+/* Flow Control Register (ETH_FCR) */ -+ -+#define ETH_FCR_PAUSE_TIME_BIT 16 -+#define ETH_FCR_PAUSE_TIME_MASK (0xffff << ETH_FCR_PAUSE_TIME_BIT) -+#define ETH_FCR_PCF (1 << 2) -+#define ETH_FCR_FCE (1 << 1) -+#define ETH_FCR_BUSY (1 << 0) -+ -+/* PMT Control and Status Register (ETH_PMTR) */ -+ -+#define ETH_PMTR_GU (1 << 9) -+#define ETH_PMTR_RF (1 << 6) -+#define ETH_PMTR_MF (1 << 5) -+#define ETH_PMTR_RWK (1 << 2) -+#define ETH_PMTR_MPK (1 << 1) -+ -+/* Receive Descriptor 0 (ETH_RD0) Bits */ -+ -+#define ETH_RD0_OWN (1 << 31) -+#define ETH_RD0_FF (1 << 30) -+#define ETH_RD0_FL_BIT 16 -+#define ETH_RD0_FL_MASK (0x3fff << ETH_RD0_FL_BIT) -+#define ETH_RD0_ES (1 << 15) -+#define ETH_RD0_DE (1 << 14) -+#define ETH_RD0_LE (1 << 12) -+#define ETH_RD0_RF (1 << 11) -+#define ETH_RD0_MF (1 << 10) -+#define ETH_RD0_FD (1 << 9) -+#define ETH_RD0_LD (1 << 8) -+#define ETH_RD0_TL (1 << 7) -+#define ETH_RD0_CS (1 << 6) -+#define ETH_RD0_FT (1 << 5) -+#define ETH_RD0_WT (1 << 4) -+#define ETH_RD0_ME (1 << 3) -+#define ETH_RD0_DB (1 << 2) -+#define ETH_RD0_CE (1 << 1) -+ -+/* Receive Descriptor 1 (ETH_RD1) Bits */ -+ -+#define ETH_RD1_RER (1 << 25) -+#define ETH_RD1_RCH (1 << 24) -+#define ETH_RD1_RBS2_BIT 11 -+#define ETH_RD1_RBS2_MASK (0x7ff << ETH_RD1_RBS2_BIT) -+#define ETH_RD1_RBS1_BIT 0 -+#define ETH_RD1_RBS1_MASK (0x7ff << ETH_RD1_RBS1_BIT) -+ -+/* Transmit Descriptor 0 (ETH_TD0) Bits */ -+ -+#define ETH_TD0_OWN (1 << 31) -+#define ETH_TD0_FA (1 << 15) -+#define ETH_TD0_LOC (1 << 11) -+#define ETH_TD0_NC (1 << 10) -+#define ETH_TD0_LC (1 << 9) -+#define ETH_TD0_EC (1 << 8) -+#define ETH_TD0_HBF (1 << 7) -+#define ETH_TD0_CC_BIT 3 -+#define ETH_TD0_CC_MASK (0xf << ETH_TD0_CC_BIT) -+#define ETH_TD0_ED (1 << 2) -+#define ETH_TD0_UF (1 << 1) -+#define ETH_TD0_DF (1 << 0) -+ -+/* Transmit Descriptor 1 (ETH_TD1) Bits */ -+ -+#define ETH_TD1_IC (1 << 31) -+#define ETH_TD1_LS (1 << 30) -+#define ETH_TD1_FS (1 << 29) -+#define ETH_TD1_AC (1 << 26) -+#define ETH_TD1_TER (1 << 25) -+#define ETH_TD1_TCH (1 << 24) -+#define ETH_TD1_DPD (1 << 23) -+#define ETH_TD1_TBS2_BIT 11 -+#define ETH_TD1_TBS2_MASK (0x7ff << ETH_TD1_TBS2_BIT) -+#define ETH_TD1_TBS1_BIT 0 -+#define ETH_TD1_TBS1_MASK (0x7ff << ETH_TD1_TBS1_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * WDT -+ *************************************************************************/ -+#define WDT_WTCSR (WDT_BASE + 0x00) -+#define WDT_WTCNT (WDT_BASE + 0x04) -+ -+#define REG_WDT_WTCSR REG8(WDT_WTCSR) -+#define REG_WDT_WTCNT REG32(WDT_WTCNT) -+ -+#define WDT_WTCSR_START (1 << 4) -+ -+ -+ -+ -+/************************************************************************* -+ * OST -+ *************************************************************************/ -+#define OST_TER (OST_BASE + 0x00) -+#define OST_TRDR(n) (OST_BASE + 0x10 + ((n) * 0x20)) -+#define OST_TCNT(n) (OST_BASE + 0x14 + ((n) * 0x20)) -+#define OST_TCSR(n) (OST_BASE + 0x18 + ((n) * 0x20)) -+#define OST_TCRB(n) (OST_BASE + 0x1c + ((n) * 0x20)) -+ -+#define REG_OST_TER REG8(OST_TER) -+#define REG_OST_TRDR(n) REG32(OST_TRDR((n))) -+#define REG_OST_TCNT(n) REG32(OST_TCNT((n))) -+#define REG_OST_TCSR(n) REG16(OST_TCSR((n))) -+#define REG_OST_TCRB(n) REG32(OST_TCRB((n))) -+ -+#define OST_TCSR_BUSY (1 << 7) -+#define OST_TCSR_UF (1 << 6) -+#define OST_TCSR_UIE (1 << 5) -+#define OST_TCSR_CKS_BIT 0 -+#define OST_TCSR_CKS_MASK (0x07 << OST_TCSR_CKS_BIT) -+ #define OST_TCSR_CKS_PCLK_4 (0 << OST_TCSR_CKS_BIT) -+ #define OST_TCSR_CKS_PCLK_16 (1 << OST_TCSR_CKS_BIT) -+ #define OST_TCSR_CKS_PCLK_64 (2 << OST_TCSR_CKS_BIT) -+ #define OST_TCSR_CKS_PCLK_256 (3 << OST_TCSR_CKS_BIT) -+ #define OST_TCSR_CKS_RTCCLK (4 << OST_TCSR_CKS_BIT) -+ #define OST_TCSR_CKS_EXTAL (5 << OST_TCSR_CKS_BIT) -+ -+#define OST_TCSR0 OST_TCSR(0) -+#define OST_TCSR1 OST_TCSR(1) -+#define OST_TCSR2 OST_TCSR(2) -+#define OST_TRDR0 OST_TRDR(0) -+#define OST_TRDR1 OST_TRDR(1) -+#define OST_TRDR2 OST_TRDR(2) -+#define OST_TCNT0 OST_TCNT(0) -+#define OST_TCNT1 OST_TCNT(1) -+#define OST_TCNT2 OST_TCNT(2) -+#define OST_TCRB0 OST_TCRB(0) -+#define OST_TCRB1 OST_TCRB(1) -+#define OST_TCRB2 OST_TCRB(2) -+ -+/************************************************************************* -+ * UART -+ *************************************************************************/ -+ -+#define IRDA_BASE UART0_BASE -+#define UART_BASE UART0_BASE -+#define UART_OFF 0x1000 -+ -+/* register offset */ -+#define OFF_RDR (0x00) /* R 8b H'xx */ -+#define OFF_TDR (0x00) /* W 8b H'xx */ -+#define OFF_DLLR (0x00) /* RW 8b H'00 */ -+#define OFF_DLHR (0x04) /* RW 8b H'00 */ -+#define OFF_IER (0x04) /* RW 8b H'00 */ -+#define OFF_ISR (0x08) /* R 8b H'01 */ -+#define OFF_FCR (0x08) /* W 8b H'00 */ -+#define OFF_LCR (0x0C) /* RW 8b H'00 */ -+#define OFF_MCR (0x10) /* RW 8b H'00 */ -+#define OFF_LSR (0x14) /* R 8b H'00 */ -+#define OFF_MSR (0x18) /* R 8b H'00 */ -+#define OFF_SPR (0x1C) /* RW 8b H'00 */ -+#define OFF_MCR (0x10) /* RW 8b H'00 */ -+#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */ -+ -+/* register address */ -+#define UART0_RDR (UART0_BASE + OFF_RDR) -+#define UART0_TDR (UART0_BASE + OFF_TDR) -+#define UART0_DLLR (UART0_BASE + OFF_DLLR) -+#define UART0_DLHR (UART0_BASE + OFF_DLHR) -+#define UART0_IER (UART0_BASE + OFF_IER) -+#define UART0_ISR (UART0_BASE + OFF_ISR) -+#define UART0_FCR (UART0_BASE + OFF_FCR) -+#define UART0_LCR (UART0_BASE + OFF_LCR) -+#define UART0_MCR (UART0_BASE + OFF_MCR) -+#define UART0_LSR (UART0_BASE + OFF_LSR) -+#define UART0_MSR (UART0_BASE + OFF_MSR) -+#define UART0_SPR (UART0_BASE + OFF_SPR) -+#define UART0_SIRCR (UART0_BASE + OFF_SIRCR) -+ -+#define UART1_RDR (UART1_BASE + OFF_RDR) -+#define UART1_TDR (UART1_BASE + OFF_TDR) -+#define UART1_DLLR (UART1_BASE + OFF_DLLR) -+#define UART1_DLHR (UART1_BASE + OFF_DLHR) -+#define UART1_IER (UART1_BASE + OFF_IER) -+#define UART1_ISR (UART1_BASE + OFF_ISR) -+#define UART1_FCR (UART1_BASE + OFF_FCR) -+#define UART1_LCR (UART1_BASE + OFF_LCR) -+#define UART1_MCR (UART1_BASE + OFF_MCR) -+#define UART1_LSR (UART1_BASE + OFF_LSR) -+#define UART1_MSR (UART1_BASE + OFF_MSR) -+#define UART1_SPR (UART1_BASE + OFF_SPR) -+#define UART1_SIRCR (UART1_BASE + OFF_SIRCR) -+ -+#define UART2_RDR (UART2_BASE + OFF_RDR) -+#define UART2_TDR (UART2_BASE + OFF_TDR) -+#define UART2_DLLR (UART2_BASE + OFF_DLLR) -+#define UART2_DLHR (UART2_BASE + OFF_DLHR) -+#define UART2_IER (UART2_BASE + OFF_IER) -+#define UART2_ISR (UART2_BASE + OFF_ISR) -+#define UART2_FCR (UART2_BASE + OFF_FCR) -+#define UART2_LCR (UART2_BASE + OFF_LCR) -+#define UART2_MCR (UART2_BASE + OFF_MCR) -+#define UART2_LSR (UART2_BASE + OFF_LSR) -+#define UART2_MSR (UART2_BASE + OFF_MSR) -+#define UART2_SPR (UART2_BASE + OFF_SPR) -+#define UART2_SIRCR (UART2_BASE + OFF_SIRCR) -+ -+#define UART3_RDR (UART3_BASE + OFF_RDR) -+#define UART3_TDR (UART3_BASE + OFF_TDR) -+#define UART3_DLLR (UART3_BASE + OFF_DLLR) -+#define UART3_DLHR (UART3_BASE + OFF_DLHR) -+#define UART3_IER (UART3_BASE + OFF_IER) -+#define UART3_ISR (UART3_BASE + OFF_ISR) -+#define UART3_FCR (UART3_BASE + OFF_FCR) -+#define UART3_LCR (UART3_BASE + OFF_LCR) -+#define UART3_MCR (UART3_BASE + OFF_MCR) -+#define UART3_LSR (UART3_BASE + OFF_LSR) -+#define UART3_MSR (UART3_BASE + OFF_MSR) -+#define UART3_SPR (UART3_BASE + OFF_SPR) -+#define UART3_SIRCR (UART3_BASE + OFF_SIRCR) -+ -+/* -+ * Define macros for UARTIER -+ * UART Interrupt Enable Register -+ */ -+#define UARTIER_RIE (1 << 0) /* 0: receive fifo "full" interrupt disable */ -+#define UARTIER_TIE (1 << 1) /* 0: transmit fifo "empty" interrupt disable */ -+#define UARTIER_RLIE (1 << 2) /* 0: receive line status interrupt disable */ -+#define UARTIER_MIE (1 << 3) /* 0: modem status interrupt disable */ -+#define UARTIER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */ -+ -+/* -+ * Define macros for UARTISR -+ * UART Interrupt Status Register -+ */ -+#define UARTISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */ -+#define UARTISR_IID (7 << 1) /* Source of Interrupt */ -+#define UARTISR_IID_MSI (0 << 1) /* Modem status interrupt */ -+#define UARTISR_IID_THRI (1 << 1) /* Transmitter holding register empty */ -+#define UARTISR_IID_RDI (2 << 1) /* Receiver data interrupt */ -+#define UARTISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */ -+#define UARTISR_FFMS (3 << 6) /* FIFO mode select, set when UARTFCR.FE is set to 1 */ -+#define UARTISR_FFMS_NO_FIFO (0 << 6) -+#define UARTISR_FFMS_FIFO_MODE (3 << 6) -+ -+/* -+ * Define macros for UARTFCR -+ * UART FIFO Control Register -+ */ -+#define UARTFCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */ -+#define UARTFCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */ -+#define UARTFCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */ -+#define UARTFCR_DMS (1 << 3) /* 0: disable DMA mode */ -+#define UARTFCR_UUE (1 << 4) /* 0: disable UART */ -+#define UARTFCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */ -+#define UARTFCR_RTRG_1 (0 << 6) -+#define UARTFCR_RTRG_4 (1 << 6) -+#define UARTFCR_RTRG_8 (2 << 6) -+#define UARTFCR_RTRG_15 (3 << 6) -+ -+/* -+ * Define macros for UARTLCR -+ * UART Line Control Register -+ */ -+#define UARTLCR_WLEN (3 << 0) /* word length */ -+#define UARTLCR_WLEN_5 (0 << 0) -+#define UARTLCR_WLEN_6 (1 << 0) -+#define UARTLCR_WLEN_7 (2 << 0) -+#define UARTLCR_WLEN_8 (3 << 0) -+#define UARTLCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 -+ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ -+#define UARTLCR_PE (1 << 3) /* 0: parity disable */ -+#define UARTLCR_PROE (1 << 4) /* 0: even parity 1: odd parity */ -+#define UARTLCR_SPAR (1 << 5) /* 0: sticky parity disable */ -+#define UARTLCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */ -+#define UARTLCR_DLAB (1 << 7) /* 0: access UARTRDR/TDR/IER 1: access UARTDLLR/DLHR */ -+ -+/* -+ * Define macros for UARTLSR -+ * UART Line Status Register -+ */ -+#define UARTLSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */ -+#define UARTLSR_ORER (1 << 1) /* 0: no overrun error */ -+#define UARTLSR_PER (1 << 2) /* 0: no parity error */ -+#define UARTLSR_FER (1 << 3) /* 0; no framing error */ -+#define UARTLSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */ -+#define UARTLSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */ -+#define UARTLSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */ -+#define UARTLSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */ -+ -+/* -+ * Define macros for UARTMCR -+ * UART Modem Control Register -+ */ -+#define UARTMCR_DTR (1 << 0) /* 0: DTR_ ouput high */ -+#define UARTMCR_RTS (1 << 1) /* 0: RTS_ output high */ -+#define UARTMCR_OUT1 (1 << 2) /* 0: UARTMSR.RI is set to 0 and RI_ input high */ -+#define UARTMCR_OUT2 (1 << 3) /* 0: UARTMSR.DCD is set to 0 and DCD_ input high */ -+#define UARTMCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */ -+#define UARTMCR_MCE (1 << 7) /* 0: modem function is disable */ -+ -+/* -+ * Define macros for UARTMSR -+ * UART Modem Status Register -+ */ -+#define UARTMSR_DCTS (1 << 0) /* 0: no change on CTS_ pin since last read of UARTMSR */ -+#define UARTMSR_DDSR (1 << 1) /* 0: no change on DSR_ pin since last read of UARTMSR */ -+#define UARTMSR_DRI (1 << 2) /* 0: no change on RI_ pin since last read of UARTMSR */ -+#define UARTMSR_DDCD (1 << 3) /* 0: no change on DCD_ pin since last read of UARTMSR */ -+#define UARTMSR_CTS (1 << 4) /* 0: CTS_ pin is high */ -+#define UARTMSR_DSR (1 << 5) /* 0: DSR_ pin is high */ -+#define UARTMSR_RI (1 << 6) /* 0: RI_ pin is high */ -+#define UARTMSR_DCD (1 << 7) /* 0: DCD_ pin is high */ -+ -+/* -+ * Define macros for SIRCR -+ * Slow IrDA Control Register -+ */ -+#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: IrDA mode */ -+#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: IrDA mode */ -+#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length -+ 1: 0 pulse width is 1.6us for 115.2Kbps */ -+#define SIRCR_TXPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */ -+#define SIRCR_RXPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */ -+ -+ -+ -+/************************************************************************* -+ * INTC -+ *************************************************************************/ -+#define INTC_ISR (INTC_BASE + 0x00) -+#define INTC_IMR (INTC_BASE + 0x04) -+#define INTC_IMSR (INTC_BASE + 0x08) -+#define INTC_IMCR (INTC_BASE + 0x0c) -+#define INTC_IPR (INTC_BASE + 0x10) -+ -+#define REG_INTC_ISR REG32(INTC_ISR) -+#define REG_INTC_IMR REG32(INTC_IMR) -+#define REG_INTC_IMSR REG32(INTC_IMSR) -+#define REG_INTC_IMCR REG32(INTC_IMCR) -+#define REG_INTC_IPR REG32(INTC_IPR) -+ -+#define IRQ_I2C 1 -+#define IRQ_PS2 2 -+#define IRQ_UPRT 3 -+#define IRQ_CORE 4 -+#define IRQ_UART3 6 -+#define IRQ_UART2 7 -+#define IRQ_UART1 8 -+#define IRQ_UART0 9 -+#define IRQ_SCC1 10 -+#define IRQ_SCC0 11 -+#define IRQ_UDC 12 -+#define IRQ_UHC 13 -+#define IRQ_MSC 14 -+#define IRQ_RTC 15 -+#define IRQ_FIR 16 -+#define IRQ_SSI 17 -+#define IRQ_CIM 18 -+#define IRQ_ETH 19 -+#define IRQ_AIC 20 -+#define IRQ_DMAC 21 -+#define IRQ_OST2 22 -+#define IRQ_OST1 23 -+#define IRQ_OST0 24 -+#define IRQ_GPIO3 25 -+#define IRQ_GPIO2 26 -+#define IRQ_GPIO1 27 -+#define IRQ_GPIO0 28 -+#define IRQ_LCD 30 -+ -+ -+ -+ -+/************************************************************************* -+ * CIM -+ *************************************************************************/ -+#define CIM_CFG (CIM_BASE + 0x0000) -+#define CIM_CTRL (CIM_BASE + 0x0004) -+#define CIM_STATE (CIM_BASE + 0x0008) -+#define CIM_IID (CIM_BASE + 0x000C) -+#define CIM_RXFIFO (CIM_BASE + 0x0010) -+#define CIM_DA (CIM_BASE + 0x0020) -+#define CIM_FA (CIM_BASE + 0x0024) -+#define CIM_FID (CIM_BASE + 0x0028) -+#define CIM_CMD (CIM_BASE + 0x002C) -+ -+#define REG_CIM_CFG REG32(CIM_CFG) -+#define REG_CIM_CTRL REG32(CIM_CTRL) -+#define REG_CIM_STATE REG32(CIM_STATE) -+#define REG_CIM_IID REG32(CIM_IID) -+#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -+#define REG_CIM_DA REG32(CIM_DA) -+#define REG_CIM_FA REG32(CIM_FA) -+#define REG_CIM_FID REG32(CIM_FID) -+#define REG_CIM_CMD REG32(CIM_CMD) -+ -+/* CIM Configuration Register (CIM_CFG) */ -+ -+#define CIM_CFG_INV_DAT (1 << 15) -+#define CIM_CFG_VSP (1 << 14) -+#define CIM_CFG_HSP (1 << 13) -+#define CIM_CFG_PCP (1 << 12) -+#define CIM_CFG_DUMMY_ZERO (1 << 9) -+#define CIM_CFG_EXT_VSYNC (1 << 8) -+#define CIM_CFG_PACK_BIT 4 -+#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) -+#define CIM_CFG_DSM_BIT 0 -+#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -+ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -+ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -+ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -+ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ -+ -+/* CIM Control Register (CIM_CTRL) */ -+ -+#define CIM_CTRL_MCLKDIV_BIT 24 -+#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) -+#define CIM_CTRL_FRC_BIT 16 -+#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -+ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -+ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -+ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -+ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -+ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -+ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -+ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -+ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -+ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -+ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -+ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -+ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -+ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -+ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -+ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -+ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -+#define CIM_CTRL_VDDM (1 << 13) -+#define CIM_CTRL_DMA_SOFM (1 << 12) -+#define CIM_CTRL_DMA_EOFM (1 << 11) -+#define CIM_CTRL_DMA_STOPM (1 << 10) -+#define CIM_CTRL_RXF_TRIGM (1 << 9) -+#define CIM_CTRL_RXF_OFM (1 << 8) -+#define CIM_CTRL_RXF_TRIG_BIT 4 -+#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) -+ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ -+ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ -+ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ -+ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ -+ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ -+ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ -+ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ -+ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ -+#define CIM_CTRL_DMA_EN (1 << 2) -+#define CIM_CTRL_RXF_RST (1 << 1) -+#define CIM_CTRL_ENA (1 << 0) -+ -+/* CIM State Register (CIM_STATE) */ -+ -+#define CIM_STATE_DMA_SOF (1 << 6) -+#define CIM_STATE_DMA_EOF (1 << 5) -+#define CIM_STATE_DMA_STOP (1 << 4) -+#define CIM_STATE_RXF_OF (1 << 3) -+#define CIM_STATE_RXF_TRIG (1 << 2) -+#define CIM_STATE_RXF_EMPTY (1 << 1) -+#define CIM_STATE_VDD (1 << 0) -+ -+/* CIM DMA Command Register (CIM_CMD) */ -+ -+#define CIM_CMD_SOFINT (1 << 31) -+#define CIM_CMD_EOFINT (1 << 30) -+#define CIM_CMD_STOP (1 << 28) -+#define CIM_CMD_LEN_BIT 0 -+#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * PWM -+ *************************************************************************/ -+#define PWM_CTR(n) (PWM##n##_BASE + 0x000) -+#define PWM_PER(n) (PWM##n##_BASE + 0x004) -+#define PWM_DUT(n) (PWM##n##_BASE + 0x008) -+ -+#define REG_PWM_CTR(n) REG8(PWM_CTR(n)) -+#define REG_PWM_PER(n) REG16(PWM_PER(n)) -+#define REG_PWM_DUT(n) REG16(PWM_DUT(n)) -+ -+/* PWM Control Register (PWM_CTR) */ -+ -+#define PWM_CTR_EN (1 << 7) -+#define PWM_CTR_SD (1 << 6) -+#define PWM_CTR_PRESCALE_BIT 0 -+#define PWM_CTR_PRESCALE_MASK (0x3f << PWM_CTR_PRESCALE_BIT) -+ -+/* PWM Period Register (PWM_PER) */ -+ -+#define PWM_PER_PERIOD_BIT 0 -+#define PWM_PER_PERIOD_MASK (0x3ff << PWM_PER_PERIOD_BIT) -+ -+/* PWM Duty Register (PWM_DUT) */ -+ -+#define PWM_DUT_FDUTY (1 << 10) -+#define PWM_DUT_DUTY_BIT 0 -+#define PWM_DUT_DUTY_MASK (0x3ff << PWM_DUT_DUTY_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * EMC -+ *************************************************************************/ -+#define EMC_BCR (EMC_BASE + 0x00) -+#define EMC_SMCR0 (EMC_BASE + 0x10) -+#define EMC_SMCR1 (EMC_BASE + 0x14) -+#define EMC_SMCR2 (EMC_BASE + 0x18) -+#define EMC_SMCR3 (EMC_BASE + 0x1c) -+#define EMC_SMCR4 (EMC_BASE + 0x20) -+#define EMC_SMCR5 (EMC_BASE + 0x24) -+#define EMC_SMCR6 (EMC_BASE + 0x28) -+#define EMC_SMCR7 (EMC_BASE + 0x2c) -+#define EMC_SACR0 (EMC_BASE + 0x30) -+#define EMC_SACR1 (EMC_BASE + 0x34) -+#define EMC_SACR2 (EMC_BASE + 0x38) -+#define EMC_SACR3 (EMC_BASE + 0x3c) -+#define EMC_SACR4 (EMC_BASE + 0x40) -+#define EMC_SACR5 (EMC_BASE + 0x44) -+#define EMC_SACR6 (EMC_BASE + 0x48) -+#define EMC_SACR7 (EMC_BASE + 0x4c) -+#define EMC_NFCSR (EMC_BASE + 0x50) -+#define EMC_NFECC (EMC_BASE + 0x54) -+#define EMC_PCCR1 (EMC_BASE + 0x60) -+#define EMC_PCCR2 (EMC_BASE + 0x64) -+#define EMC_PCCR3 (EMC_BASE + 0x68) -+#define EMC_PCCR4 (EMC_BASE + 0x6c) -+#define EMC_DMCR (EMC_BASE + 0x80) -+#define EMC_RTCSR (EMC_BASE + 0x84) -+#define EMC_RTCNT (EMC_BASE + 0x88) -+#define EMC_RTCOR (EMC_BASE + 0x8c) -+#define EMC_DMAR1 (EMC_BASE + 0x90) -+#define EMC_DMAR2 (EMC_BASE + 0x94) -+#define EMC_DMAR3 (EMC_BASE + 0x98) -+#define EMC_DMAR4 (EMC_BASE + 0x9c) -+ -+#define EMC_SDMR0 (EMC_BASE + 0xa000) -+#define EMC_SDMR1 (EMC_BASE + 0xb000) -+#define EMC_SDMR2 (EMC_BASE + 0xc000) -+#define EMC_SDMR3 (EMC_BASE + 0xd000) -+ -+#define REG_EMC_BCR REG32(EMC_BCR) -+#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -+#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -+#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -+#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -+#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -+#define REG_EMC_SMCR5 REG32(EMC_SMCR5) -+#define REG_EMC_SMCR6 REG32(EMC_SMCR6) -+#define REG_EMC_SMCR7 REG32(EMC_SMCR7) -+#define REG_EMC_SACR0 REG32(EMC_SACR0) -+#define REG_EMC_SACR1 REG32(EMC_SACR1) -+#define REG_EMC_SACR2 REG32(EMC_SACR2) -+#define REG_EMC_SACR3 REG32(EMC_SACR3) -+#define REG_EMC_SACR4 REG32(EMC_SACR4) -+#define REG_EMC_SACR5 REG32(EMC_SACR5) -+#define REG_EMC_SACR6 REG32(EMC_SACR6) -+#define REG_EMC_SACR7 REG32(EMC_SACR7) -+#define REG_EMC_NFCSR REG32(EMC_NFCSR) -+#define REG_EMC_NFECC REG32(EMC_NFECC) -+#define REG_EMC_DMCR REG32(EMC_DMCR) -+#define REG_EMC_RTCSR REG16(EMC_RTCSR) -+#define REG_EMC_RTCNT REG16(EMC_RTCNT) -+#define REG_EMC_RTCOR REG16(EMC_RTCOR) -+#define REG_EMC_DMAR1 REG32(EMC_DMAR1) -+#define REG_EMC_DMAR2 REG32(EMC_DMAR2) -+#define REG_EMC_DMAR3 REG32(EMC_DMAR3) -+#define REG_EMC_DMAR4 REG32(EMC_DMAR4) -+#define REG_EMC_PCCR1 REG32(EMC_PCCR1) -+#define REG_EMC_PCCR2 REG32(EMC_PCCR2) -+#define REG_EMC_PCCR3 REG32(EMC_PCCR3) -+#define REG_EMC_PCCR4 REG32(EMC_PCCR4) -+ -+ -+#define EMC_BCR_BRE (1 << 1) -+ -+#define EMC_SMCR_STRV_BIT 24 -+#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -+#define EMC_SMCR_TAW_BIT 20 -+#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -+#define EMC_SMCR_TBP_BIT 16 -+#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -+#define EMC_SMCR_TAH_BIT 12 -+#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -+#define EMC_SMCR_TAS_BIT 8 -+#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -+#define EMC_SMCR_BW_BIT 6 -+#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -+#define EMC_SMCR_BCM (1 << 3) -+#define EMC_SMCR_BL_BIT 1 -+#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -+#define EMC_SMCR_SMT (1 << 0) -+ -+#define EMC_SACR_BASE_BIT 8 -+#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -+#define EMC_SACR_MASK_BIT 0 -+#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -+ -+#define EMC_NFCSR_RB (1 << 7) -+#define EMC_NFCSR_BOOT_SEL_BIT 4 -+#define EMC_NFCSR_BOOT_SEL_MASK (0x07 << EMC_NFCSR_BOOT_SEL_BIT) -+#define EMC_NFCSR_ERST (1 << 3) -+#define EMC_NFCSR_ECCE (1 << 2) -+#define EMC_NFCSR_FCE (1 << 1) -+#define EMC_NFCSR_NFE (1 << 0) -+ -+#define EMC_NFECC_ECC2_BIT 16 -+#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT) -+#define EMC_NFECC_ECC1_BIT 8 -+#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT) -+#define EMC_NFECC_ECC0_BIT 0 -+#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT) -+ -+#define EMC_DMCR_BW_BIT 31 -+#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -+#define EMC_DMCR_CA_BIT 26 -+#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -+#define EMC_DMCR_RMODE (1 << 25) -+#define EMC_DMCR_RFSH (1 << 24) -+#define EMC_DMCR_MRSET (1 << 23) -+#define EMC_DMCR_RA_BIT 20 -+#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -+#define EMC_DMCR_BA_BIT 19 -+#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -+#define EMC_DMCR_PDM (1 << 18) -+#define EMC_DMCR_EPIN (1 << 17) -+#define EMC_DMCR_TRAS_BIT 13 -+#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -+#define EMC_DMCR_RCD_BIT 11 -+#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -+#define EMC_DMCR_TPC_BIT 8 -+#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -+#define EMC_DMCR_TRWL_BIT 5 -+#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -+#define EMC_DMCR_TRC_BIT 2 -+#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -+#define EMC_DMCR_TCL_BIT 0 -+#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -+ -+#define EMC_RTCSR_CMF (1 << 7) -+#define EMC_RTCSR_CKS_BIT 0 -+#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -+ -+#define EMC_DMAR_BASE_BIT 8 -+#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -+#define EMC_DMAR_MASK_BIT 0 -+#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -+ -+#define EMC_SDMR_BM (1 << 9) -+#define EMC_SDMR_OM_BIT 7 -+#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -+ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -+#define EMC_SDMR_CAS_BIT 4 -+#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -+#define EMC_SDMR_BT_BIT 3 -+#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -+ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) -+ #define EMC_SDMR_BT_INTR (1 << EMC_SDMR_BT_BIT) -+#define EMC_SDMR_BL_BIT 0 -+#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -+ -+#define EMC_SDMR_CAS2_16BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS2_32BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+#define EMC_SDMR_CAS3_16BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS3_32BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+ -+#define EMC_PCCR12_AMW (1 << 31) -+#define EMC_PCCR12_AMAS_BIT 28 -+#define EMC_PCCR12_AMAS_MASK (0x07 << EMC_PCCR12_AMAS_BIT) -+#define EMC_PCCR12_AMAH_BIT 24 -+#define EMC_PCCR12_AMAH_MASK (0x07 << EMC_PCCR12_AMAH_BIT) -+#define EMC_PCCR12_AMPW_BIT 20 -+#define EMC_PCCR12_AMPW_MASK (0x0f << EMC_PCCR12_AMPW_BIT) -+#define EMC_PCCR12_AMRT_BIT 16 -+#define EMC_PCCR12_AMRT_MASK (0x0f << EMC_PCCR12_AMRT_BIT) -+#define EMC_PCCR12_CMW (1 << 15) -+#define EMC_PCCR12_CMAS_BIT 12 -+#define EMC_PCCR12_CMAS_MASK (0x07 << EMC_PCCR12_CMAS_BIT) -+#define EMC_PCCR12_CMAH_BIT 8 -+#define EMC_PCCR12_CMAH_MASK (0x07 << EMC_PCCR12_CMAH_BIT) -+#define EMC_PCCR12_CMPW_BIT 4 -+#define EMC_PCCR12_CMPW_MASK (0x0f << EMC_PCCR12_CMPW_BIT) -+#define EMC_PCCR12_CMRT_BIT 0 -+#define EMC_PCCR12_CMRT_MASK (0x07 << EMC_PCCR12_CMRT_BIT) -+ -+#define EMC_PCCR34_DRS_BIT 16 -+#define EMC_PCCR34_DRS_MASK (0x03 << EMC_PCCR34_DRS_BIT) -+ #define EMC_PCCR34_DRS_SPKR (1 << EMC_PCCR34_DRS_BIT) -+ #define EMC_PCCR34_DRS_IOIS16 (2 << EMC_PCCR34_DRS_BIT) -+ #define EMC_PCCR34_DRS_INPACK (3 << EMC_PCCR34_DRS_BIT) -+#define EMC_PCCR34_IOIS16 (1 << 15) -+#define EMC_PCCR34_IOW (1 << 14) -+#define EMC_PCCR34_TCB_BIT 12 -+#define EMC_PCCR34_TCB_MASK (0x03 << EMC_PCCR34_TCB_BIT) -+#define EMC_PCCR34_IORT_BIT 8 -+#define EMC_PCCR34_IORT_MASK (0x07 << EMC_PCCR34_IORT_BIT) -+#define EMC_PCCR34_IOAE_BIT 6 -+#define EMC_PCCR34_IOAE_MASK (0x03 << EMC_PCCR34_IOAE_BIT) -+ #define EMC_PCCR34_IOAE_NONE (0 << EMC_PCCR34_IOAE_BIT) -+ #define EMC_PCCR34_IOAE_1 (1 << EMC_PCCR34_IOAE_BIT) -+ #define EMC_PCCR34_IOAE_2 (2 << EMC_PCCR34_IOAE_BIT) -+ #define EMC_PCCR34_IOAE_5 (3 << EMC_PCCR34_IOAE_BIT) -+#define EMC_PCCR34_IOAH_BIT 4 -+#define EMC_PCCR34_IOAH_MASK (0x03 << EMC_PCCR34_IOAH_BIT) -+ #define EMC_PCCR34_IOAH_NONE (0 << EMC_PCCR34_IOAH_BIT) -+ #define EMC_PCCR34_IOAH_1 (1 << EMC_PCCR34_IOAH_BIT) -+ #define EMC_PCCR34_IOAH_2 (2 << EMC_PCCR34_IOAH_BIT) -+ #define EMC_PCCR34_IOAH_5 (3 << EMC_PCCR34_IOAH_BIT) -+#define EMC_PCCR34_IOPW_BIT 0 -+#define EMC_PCCR34_IOPW_MASK (0x0f << EMC_PCCR34_IOPW_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * GPIO -+ *************************************************************************/ -+#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30)) -+#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) -+#define GPIO_GPODR(n) (GPIO_BASE + (0x08 + (n)*0x30)) -+#define GPIO_GPPUR(n) (GPIO_BASE + (0x0c + (n)*0x30)) -+#define GPIO_GPALR(n) (GPIO_BASE + (0x10 + (n)*0x30)) -+#define GPIO_GPAUR(n) (GPIO_BASE + (0x14 + (n)*0x30)) -+#define GPIO_GPIDLR(n) (GPIO_BASE + (0x18 + (n)*0x30)) -+#define GPIO_GPIDUR(n) (GPIO_BASE + (0x1c + (n)*0x30)) -+#define GPIO_GPIER(n) (GPIO_BASE + (0x20 + (n)*0x30)) -+#define GPIO_GPIMR(n) (GPIO_BASE + (0x24 + (n)*0x30)) -+#define GPIO_GPFR(n) (GPIO_BASE + (0x28 + (n)*0x30)) -+ -+#define REG_GPIO_GPDR(n) REG32(GPIO_GPDR((n))) -+#define REG_GPIO_GPDIR(n) REG32(GPIO_GPDIR((n))) -+#define REG_GPIO_GPODR(n) REG32(GPIO_GPODR((n))) -+#define REG_GPIO_GPPUR(n) REG32(GPIO_GPPUR((n))) -+#define REG_GPIO_GPALR(n) REG32(GPIO_GPALR((n))) -+#define REG_GPIO_GPAUR(n) REG32(GPIO_GPAUR((n))) -+#define REG_GPIO_GPIDLR(n) REG32(GPIO_GPIDLR((n))) -+#define REG_GPIO_GPIDUR(n) REG32(GPIO_GPIDUR((n))) -+#define REG_GPIO_GPIER(n) REG32(GPIO_GPIER((n))) -+#define REG_GPIO_GPIMR(n) REG32(GPIO_GPIMR((n))) -+#define REG_GPIO_GPFR(n) REG32(GPIO_GPFR((n))) -+ -+#define GPIO_IRQ_LOLEVEL 0 -+#define GPIO_IRQ_HILEVEL 1 -+#define GPIO_IRQ_FALLEDG 2 -+#define GPIO_IRQ_RAISEDG 3 -+ -+#define IRQ_GPIO_0 48 -+#define NUM_GPIO 128 -+ -+#define GPIO_GPDR0 GPIO_GPDR(0) -+#define GPIO_GPDR1 GPIO_GPDR(1) -+#define GPIO_GPDR2 GPIO_GPDR(2) -+#define GPIO_GPDR3 GPIO_GPDR(3) -+#define GPIO_GPDIR0 GPIO_GPDIR(0) -+#define GPIO_GPDIR1 GPIO_GPDIR(1) -+#define GPIO_GPDIR2 GPIO_GPDIR(2) -+#define GPIO_GPDIR3 GPIO_GPDIR(3) -+#define GPIO_GPODR0 GPIO_GPODR(0) -+#define GPIO_GPODR1 GPIO_GPODR(1) -+#define GPIO_GPODR2 GPIO_GPODR(2) -+#define GPIO_GPODR3 GPIO_GPODR(3) -+#define GPIO_GPPUR0 GPIO_GPPUR(0) -+#define GPIO_GPPUR1 GPIO_GPPUR(1) -+#define GPIO_GPPUR2 GPIO_GPPUR(2) -+#define GPIO_GPPUR3 GPIO_GPPUR(3) -+#define GPIO_GPALR0 GPIO_GPALR(0) -+#define GPIO_GPALR1 GPIO_GPALR(1) -+#define GPIO_GPALR2 GPIO_GPALR(2) -+#define GPIO_GPALR3 GPIO_GPALR(3) -+#define GPIO_GPAUR0 GPIO_GPAUR(0) -+#define GPIO_GPAUR1 GPIO_GPAUR(1) -+#define GPIO_GPAUR2 GPIO_GPAUR(2) -+#define GPIO_GPAUR3 GPIO_GPAUR(3) -+#define GPIO_GPIDLR0 GPIO_GPIDLR(0) -+#define GPIO_GPIDLR1 GPIO_GPIDLR(1) -+#define GPIO_GPIDLR2 GPIO_GPIDLR(2) -+#define GPIO_GPIDLR3 GPIO_GPIDLR(3) -+#define GPIO_GPIDUR0 GPIO_GPIDUR(0) -+#define GPIO_GPIDUR1 GPIO_GPIDUR(1) -+#define GPIO_GPIDUR2 GPIO_GPIDUR(2) -+#define GPIO_GPIDUR3 GPIO_GPIDUR(3) -+#define GPIO_GPIER0 GPIO_GPIER(0) -+#define GPIO_GPIER1 GPIO_GPIER(1) -+#define GPIO_GPIER2 GPIO_GPIER(2) -+#define GPIO_GPIER3 GPIO_GPIER(3) -+#define GPIO_GPIMR0 GPIO_GPIMR(0) -+#define GPIO_GPIMR1 GPIO_GPIMR(1) -+#define GPIO_GPIMR2 GPIO_GPIMR(2) -+#define GPIO_GPIMR3 GPIO_GPIMR(3) -+#define GPIO_GPFR0 GPIO_GPFR(0) -+#define GPIO_GPFR1 GPIO_GPFR(1) -+#define GPIO_GPFR2 GPIO_GPFR(2) -+#define GPIO_GPFR3 GPIO_GPFR(3) -+ -+ -+/************************************************************************* -+ * HARB -+ *************************************************************************/ -+#define HARB_HAPOR (HARB_BASE + 0x000) -+#define HARB_HMCTR (HARB_BASE + 0x010) -+#define HARB_HME8H (HARB_BASE + 0x014) -+#define HARB_HMCR1 (HARB_BASE + 0x018) -+#define HARB_HMER2 (HARB_BASE + 0x01C) -+#define HARB_HMER3 (HARB_BASE + 0x020) -+#define HARB_HMLTR (HARB_BASE + 0x024) -+ -+#define REG_HARB_HAPOR REG32(HARB_HAPOR) -+#define REG_HARB_HMCTR REG32(HARB_HMCTR) -+#define REG_HARB_HME8H REG32(HARB_HME8H) -+#define REG_HARB_HMCR1 REG32(HARB_HMCR1) -+#define REG_HARB_HMER2 REG32(HARB_HMER2) -+#define REG_HARB_HMER3 REG32(HARB_HMER3) -+#define REG_HARB_HMLTR REG32(HARB_HMLTR) -+ -+/* HARB Priority Order Register (HARB_HAPOR) */ -+ -+#define HARB_HAPOR_UCHSEL (1 << 7) -+#define HARB_HAPOR_PRIO_BIT 0 -+#define HARB_HAPOR_PRIO_MASK (0xf << HARB_HAPOR_PRIO_BIT) -+ -+/* AHB Monitor Control Register (HARB_HMCTR) */ -+ -+#define HARB_HMCTR_HET3_BIT 20 -+#define HARB_HMCTR_HET3_MASK (0xf << HARB_HMCTR_HET3_BIT) -+#define HARB_HMCTR_HMS3_BIT 16 -+#define HARB_HMCTR_HMS3_MASK (0xf << HARB_HMCTR_HMS3_BIT) -+#define HARB_HMCTR_HET2_BIT 12 -+#define HARB_HMCTR_HET2_MASK (0xf << HARB_HMCTR_HET2_BIT) -+#define HARB_HMCTR_HMS2_BIT 8 -+#define HARB_HMCTR_HMS2_MASK (0xf << HARB_HMCTR_HMS2_BIT) -+#define HARB_HMCTR_HOVF3 (1 << 7) -+#define HARB_HMCTR_HOVF2 (1 << 6) -+#define HARB_HMCTR_HOVF1 (1 << 5) -+#define HARB_HMCTR_HRST (1 << 4) -+#define HARB_HMCTR_HEE3 (1 << 2) -+#define HARB_HMCTR_HEE2 (1 << 1) -+#define HARB_HMCTR_HEE1 (1 << 0) -+ -+/* AHB Monitor Event 8bits High Register (HARB_HME8H) */ -+ -+#define HARB_HME8H_HC8H1_BIT 16 -+#define HARB_HME8H_HC8H1_MASK (0xff << HARB_HME8H_HC8H1_BIT) -+#define HARB_HME8H_HC8H2_BIT 8 -+#define HARB_HME8H_HC8H2_MASK (0xff << HARB_HME8H_HC8H2_BIT) -+#define HARB_HME8H_HC8H3_BIT 0 -+#define HARB_HME8H_HC8H3_MASK (0xff << HARB_HME8H_HC8H3_BIT) -+ -+/* AHB Monitor Latency Register (HARB_HMLTR) */ -+ -+#define HARB_HMLTR_HLT2_BIT 16 -+#define HARB_HMLTR_HLT2_MASK (0xffff << HARB_HMLTR_HLT2_BIT) -+#define HARB_HMLTR_HLT3_BIT 0 -+#define HARB_HMLTR_HLT3_MASK (0xffff << HARB_HMLTR_HLT3_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * I2C -+ *************************************************************************/ -+#define I2C_DR (I2C_BASE + 0x000) -+#define I2C_CR (I2C_BASE + 0x004) -+#define I2C_SR (I2C_BASE + 0x008) -+#define I2C_GR (I2C_BASE + 0x00C) -+ -+#define REG_I2C_DR REG8(I2C_DR) -+#define REG_I2C_CR REG8(I2C_CR) -+#define REG_I2C_SR REG8(I2C_SR) -+#define REG_I2C_GR REG16(I2C_GR) -+ -+/* I2C Control Register (I2C_CR) */ -+ -+#define I2C_CR_IEN (1 << 4) -+#define I2C_CR_STA (1 << 3) -+#define I2C_CR_STO (1 << 2) -+#define I2C_CR_AC (1 << 1) -+#define I2C_CR_I2CE (1 << 0) -+ -+/* I2C Status Register (I2C_SR) */ -+ -+#define I2C_SR_STX (1 << 4) -+#define I2C_SR_BUSY (1 << 3) -+#define I2C_SR_TEND (1 << 2) -+#define I2C_SR_DRF (1 << 1) -+#define I2C_SR_ACKF (1 << 0) -+ -+ -+ -+ -+/************************************************************************* -+ * UDC -+ *************************************************************************/ -+#define UDC_EP0InCR (UDC_BASE + 0x00) -+#define UDC_EP0InSR (UDC_BASE + 0x04) -+#define UDC_EP0InBSR (UDC_BASE + 0x08) -+#define UDC_EP0InMPSR (UDC_BASE + 0x0c) -+#define UDC_EP0InDesR (UDC_BASE + 0x14) -+#define UDC_EP1InCR (UDC_BASE + 0x20) -+#define UDC_EP1InSR (UDC_BASE + 0x24) -+#define UDC_EP1InBSR (UDC_BASE + 0x28) -+#define UDC_EP1InMPSR (UDC_BASE + 0x2c) -+#define UDC_EP1InDesR (UDC_BASE + 0x34) -+#define UDC_EP2InCR (UDC_BASE + 0x40) -+#define UDC_EP2InSR (UDC_BASE + 0x44) -+#define UDC_EP2InBSR (UDC_BASE + 0x48) -+#define UDC_EP2InMPSR (UDC_BASE + 0x4c) -+#define UDC_EP2InDesR (UDC_BASE + 0x54) -+#define UDC_EP3InCR (UDC_BASE + 0x60) -+#define UDC_EP3InSR (UDC_BASE + 0x64) -+#define UDC_EP3InBSR (UDC_BASE + 0x68) -+#define UDC_EP3InMPSR (UDC_BASE + 0x6c) -+#define UDC_EP3InDesR (UDC_BASE + 0x74) -+#define UDC_EP4InCR (UDC_BASE + 0x80) -+#define UDC_EP4InSR (UDC_BASE + 0x84) -+#define UDC_EP4InBSR (UDC_BASE + 0x88) -+#define UDC_EP4InMPSR (UDC_BASE + 0x8c) -+#define UDC_EP4InDesR (UDC_BASE + 0x94) -+ -+#define UDC_EP0OutCR (UDC_BASE + 0x200) -+#define UDC_EP0OutSR (UDC_BASE + 0x204) -+#define UDC_EP0OutPFNR (UDC_BASE + 0x208) -+#define UDC_EP0OutMPSR (UDC_BASE + 0x20c) -+#define UDC_EP0OutSBPR (UDC_BASE + 0x210) -+#define UDC_EP0OutDesR (UDC_BASE + 0x214) -+#define UDC_EP5OutCR (UDC_BASE + 0x2a0) -+#define UDC_EP5OutSR (UDC_BASE + 0x2a4) -+#define UDC_EP5OutPFNR (UDC_BASE + 0x2a8) -+#define UDC_EP5OutMPSR (UDC_BASE + 0x2ac) -+#define UDC_EP5OutDesR (UDC_BASE + 0x2b4) -+#define UDC_EP6OutCR (UDC_BASE + 0x2c0) -+#define UDC_EP6OutSR (UDC_BASE + 0x2c4) -+#define UDC_EP6OutPFNR (UDC_BASE + 0x2c8) -+#define UDC_EP6OutMPSR (UDC_BASE + 0x2cc) -+#define UDC_EP6OutDesR (UDC_BASE + 0x2d4) -+#define UDC_EP7OutCR (UDC_BASE + 0x2e0) -+#define UDC_EP7OutSR (UDC_BASE + 0x2e4) -+#define UDC_EP7OutPFNR (UDC_BASE + 0x2e8) -+#define UDC_EP7OutMPSR (UDC_BASE + 0x2ec) -+#define UDC_EP7OutDesR (UDC_BASE + 0x2f4) -+ -+#define UDC_DevCFGR (UDC_BASE + 0x400) -+#define UDC_DevCR (UDC_BASE + 0x404) -+#define UDC_DevSR (UDC_BASE + 0x408) -+#define UDC_DevIntR (UDC_BASE + 0x40c) -+#define UDC_DevIntMR (UDC_BASE + 0x410) -+#define UDC_EPIntR (UDC_BASE + 0x414) -+#define UDC_EPIntMR (UDC_BASE + 0x418) -+ -+#define UDC_STCMAR (UDC_BASE + 0x500) -+#define UDC_EP0InfR (UDC_BASE + 0x504) -+#define UDC_EP1InfR (UDC_BASE + 0x508) -+#define UDC_EP2InfR (UDC_BASE + 0x50c) -+#define UDC_EP3InfR (UDC_BASE + 0x510) -+#define UDC_EP4InfR (UDC_BASE + 0x514) -+#define UDC_EP5InfR (UDC_BASE + 0x518) -+#define UDC_EP6InfR (UDC_BASE + 0x51c) -+#define UDC_EP7InfR (UDC_BASE + 0x520) -+ -+#define UDC_TXCONFIRM (UDC_BASE + 0x41C) -+#define UDC_TXZLP (UDC_BASE + 0x420) -+#define UDC_RXCONFIRM (UDC_BASE + 0x41C) -+ -+#define UDC_RXFIFO (UDC_BASE + 0x800) -+#define UDC_TXFIFOEP0 (UDC_BASE + 0x840) -+ -+#define REG_UDC_EP0InCR REG32(UDC_EP0InCR) -+#define REG_UDC_EP0InSR REG32(UDC_EP0InSR) -+#define REG_UDC_EP0InBSR REG32(UDC_EP0InBSR) -+#define REG_UDC_EP0InMPSR REG32(UDC_EP0InMPSR) -+#define REG_UDC_EP0InDesR REG32(UDC_EP0InDesR) -+#define REG_UDC_EP1InCR REG32(UDC_EP1InCR) -+#define REG_UDC_EP1InSR REG32(UDC_EP1InSR) -+#define REG_UDC_EP1InBSR REG32(UDC_EP1InBSR) -+#define REG_UDC_EP1InMPSR REG32(UDC_EP1InMPSR) -+#define REG_UDC_EP1InDesR REG32(UDC_EP1InDesR) -+#define REG_UDC_EP2InCR REG32(UDC_EP2InCR) -+#define REG_UDC_EP2InSR REG32(UDC_EP2InSR) -+#define REG_UDC_EP2InBSR REG32(UDC_EP2InBSR) -+#define REG_UDC_EP2InMPSR REG32(UDC_EP2InMPSR) -+#define REG_UDC_EP2InDesR REG32(UDC_EP2InDesR) -+#define REG_UDC_EP3InCR REG32(UDC_EP3InCR) -+#define REG_UDC_EP3InSR REG32(UDC_EP3InSR) -+#define REG_UDC_EP3InBSR REG32(UDC_EP3InBSR) -+#define REG_UDC_EP3InMPSR REG32(UDC_EP3InMPSR) -+#define REG_UDC_EP3InDesR REG32(UDC_EP3InDesR) -+#define REG_UDC_EP4InCR REG32(UDC_EP4InCR) -+#define REG_UDC_EP4InSR REG32(UDC_EP4InSR) -+#define REG_UDC_EP4InBSR REG32(UDC_EP4InBSR) -+#define REG_UDC_EP4InMPSR REG32(UDC_EP4InMPSR) -+#define REG_UDC_EP4InDesR REG32(UDC_EP4InDesR) -+ -+#define REG_UDC_EP0OutCR REG32(UDC_EP0OutCR) -+#define REG_UDC_EP0OutSR REG32(UDC_EP0OutSR) -+#define REG_UDC_EP0OutPFNR REG32(UDC_EP0OutPFNR) -+#define REG_UDC_EP0OutMPSR REG32(UDC_EP0OutMPSR) -+#define REG_UDC_EP0OutSBPR REG32(UDC_EP0OutSBPR) -+#define REG_UDC_EP0OutDesR REG32(UDC_EP0OutDesR) -+#define REG_UDC_EP5OutCR REG32(UDC_EP5OutCR) -+#define REG_UDC_EP5OutSR REG32(UDC_EP5OutSR) -+#define REG_UDC_EP5OutPFNR REG32(UDC_EP5OutPFNR) -+#define REG_UDC_EP5OutMPSR REG32(UDC_EP5OutMPSR) -+#define REG_UDC_EP5OutDesR REG32(UDC_EP5OutDesR) -+#define REG_UDC_EP6OutCR REG32(UDC_EP6OutCR) -+#define REG_UDC_EP6OutSR REG32(UDC_EP6OutSR) -+#define REG_UDC_EP6OutPFNR REG32(UDC_EP6OutPFNR) -+#define REG_UDC_EP6OutMPSR REG32(UDC_EP6OutMPSR) -+#define REG_UDC_EP6OutDesR REG32(UDC_EP6OutDesR) -+#define REG_UDC_EP7OutCR REG32(UDC_EP7OutCR) -+#define REG_UDC_EP7OutSR REG32(UDC_EP7OutSR) -+#define REG_UDC_EP7OutPFNR REG32(UDC_EP7OutPFNR) -+#define REG_UDC_EP7OutMPSR REG32(UDC_EP7OutMPSR) -+#define REG_UDC_EP7OutDesR REG32(UDC_EP7OutDesR) -+ -+#define REG_UDC_DevCFGR REG32(UDC_DevCFGR) -+#define REG_UDC_DevCR REG32(UDC_DevCR) -+#define REG_UDC_DevSR REG32(UDC_DevSR) -+#define REG_UDC_DevIntR REG32(UDC_DevIntR) -+#define REG_UDC_DevIntMR REG32(UDC_DevIntMR) -+#define REG_UDC_EPIntR REG32(UDC_EPIntR) -+#define REG_UDC_EPIntMR REG32(UDC_EPIntMR) -+ -+#define REG_UDC_STCMAR REG32(UDC_STCMAR) -+#define REG_UDC_EP0InfR REG32(UDC_EP0InfR) -+#define REG_UDC_EP1InfR REG32(UDC_EP1InfR) -+#define REG_UDC_EP2InfR REG32(UDC_EP2InfR) -+#define REG_UDC_EP3InfR REG32(UDC_EP3InfR) -+#define REG_UDC_EP4InfR REG32(UDC_EP4InfR) -+#define REG_UDC_EP5InfR REG32(UDC_EP5InfR) -+#define REG_UDC_EP6InfR REG32(UDC_EP6InfR) -+#define REG_UDC_EP7InfR REG32(UDC_EP7InfR) -+ -+#define UDC_DevCFGR_PI (1 << 5) -+#define UDC_DevCFGR_SS (1 << 4) -+#define UDC_DevCFGR_SP (1 << 3) -+#define UDC_DevCFGR_RW (1 << 2) -+#define UDC_DevCFGR_SPD_BIT 0 -+#define UDC_DevCFGR_SPD_MASK (0x03 << UDC_DevCFGR_SPD_BIT) -+ #define UDC_DevCFGR_SPD_HS (0 << UDC_DevCFGR_SPD_BIT) -+ #define UDC_DevCFGR_SPD_LS (2 << UDC_DevCFGR_SPD_BIT) -+ #define UDC_DevCFGR_SPD_FS (3 << UDC_DevCFGR_SPD_BIT) -+ -+#define UDC_DevCR_DM (1 << 9) -+#define UDC_DevCR_BE (1 << 5) -+#define UDC_DevCR_RES (1 << 0) -+ -+#define UDC_DevSR_ENUMSPD_BIT 13 -+#define UDC_DevSR_ENUMSPD_MASK (0x03 << UDC_DevSR_ENUMSPD_BIT) -+ #define UDC_DevSR_ENUMSPD_HS (0 << UDC_DevSR_ENUMSPD_BIT) -+ #define UDC_DevSR_ENUMSPD_LS (2 << UDC_DevSR_ENUMSPD_BIT) -+ #define UDC_DevSR_ENUMSPD_FS (3 << UDC_DevSR_ENUMSPD_BIT) -+#define UDC_DevSR_SUSP (1 << 12) -+#define UDC_DevSR_ALT_BIT 8 -+#define UDC_DevSR_ALT_MASK (0x0f << UDC_DevSR_ALT_BIT) -+#define UDC_DevSR_INTF_BIT 4 -+#define UDC_DevSR_INTF_MASK (0x0f << UDC_DevSR_INTF_BIT) -+#define UDC_DevSR_CFG_BIT 0 -+#define UDC_DevSR_CFG_MASK (0x0f << UDC_DevSR_CFG_BIT) -+ -+#define UDC_DevIntR_ENUM (1 << 6) -+#define UDC_DevIntR_SOF (1 << 5) -+#define UDC_DevIntR_US (1 << 4) -+#define UDC_DevIntR_UR (1 << 3) -+#define UDC_DevIntR_SI (1 << 1) -+#define UDC_DevIntR_SC (1 << 0) -+ -+#define UDC_EPIntR_OUTEP_BIT 16 -+#define UDC_EPIntR_OUTEP_MASK (0xffff << UDC_EPIntR_OUTEP_BIT) -+#define UDC_EPIntR_OUTEP0 0x00010000 -+#define UDC_EPIntR_OUTEP5 0x00200000 -+#define UDC_EPIntR_OUTEP6 0x00400000 -+#define UDC_EPIntR_OUTEP7 0x00800000 -+#define UDC_EPIntR_INEP_BIT 0 -+#define UDC_EPIntR_INEP_MASK (0xffff << UDC_EPIntR_INEP_BIT) -+#define UDC_EPIntR_INEP0 0x00000001 -+#define UDC_EPIntR_INEP1 0x00000002 -+#define UDC_EPIntR_INEP2 0x00000004 -+#define UDC_EPIntR_INEP3 0x00000008 -+#define UDC_EPIntR_INEP4 0x00000010 -+ -+ -+#define UDC_EPIntMR_OUTEP_BIT 16 -+#define UDC_EPIntMR_OUTEP_MASK (0xffff << UDC_EPIntMR_OUTEP_BIT) -+#define UDC_EPIntMR_INEP_BIT 0 -+#define UDC_EPIntMR_INEP_MASK (0xffff << UDC_EPIntMR_INEP_BIT) -+ -+#define UDC_EPCR_ET_BIT 4 -+#define UDC_EPCR_ET_MASK (0x03 << UDC_EPCR_ET_BIT) -+ #define UDC_EPCR_ET_CTRL (0 << UDC_EPCR_ET_BIT) -+ #define UDC_EPCR_ET_ISO (1 << UDC_EPCR_ET_BIT) -+ #define UDC_EPCR_ET_BULK (2 << UDC_EPCR_ET_BIT) -+ #define UDC_EPCR_ET_INTR (3 << UDC_EPCR_ET_BIT) -+#define UDC_EPCR_SN (1 << 2) -+#define UDC_EPCR_F (1 << 1) -+#define UDC_EPCR_S (1 << 0) -+ -+#define UDC_EPSR_RXPKTSIZE_BIT 11 -+#define UDC_EPSR_RXPKTSIZE_MASK (0x7ff << UDC_EPSR_RXPKTSIZE_BIT) -+#define UDC_EPSR_IN (1 << 6) -+#define UDC_EPSR_OUT_BIT 4 -+#define UDC_EPSR_OUT_MASK (0x03 << UDC_EPSR_OUT_BIT) -+ #define UDC_EPSR_OUT_NONE (0 << UDC_EPSR_OUT_BIT) -+ #define UDC_EPSR_OUT_RCVDATA (1 << UDC_EPSR_OUT_BIT) -+ #define UDC_EPSR_OUT_RCVSETUP (2 << UDC_EPSR_OUT_BIT) -+#define UDC_EPSR_PID_BIT 0 -+#define UDC_EPSR_PID_MASK (0x0f << UDC_EPSR_PID_BIT) -+ -+#define UDC_EPInfR_MPS_BIT 19 -+#define UDC_EPInfR_MPS_MASK (0x3ff << UDC_EPInfR_MPS_BIT) -+#define UDC_EPInfR_ALTS_BIT 15 -+#define UDC_EPInfR_ALTS_MASK (0x0f << UDC_EPInfR_ALTS_BIT) -+#define UDC_EPInfR_IFN_BIT 11 -+#define UDC_EPInfR_IFN_MASK (0x0f << UDC_EPInfR_IFN_BIT) -+#define UDC_EPInfR_CGN_BIT 7 -+#define UDC_EPInfR_CGN_MASK (0x0f << UDC_EPInfR_CGN_BIT) -+#define UDC_EPInfR_EPT_BIT 5 -+#define UDC_EPInfR_EPT_MASK (0x03 << UDC_EPInfR_EPT_BIT) -+ #define UDC_EPInfR_EPT_CTRL (0 << UDC_EPInfR_EPT_BIT) -+ #define UDC_EPInfR_EPT_ISO (1 << UDC_EPInfR_EPT_BIT) -+ #define UDC_EPInfR_EPT_BULK (2 << UDC_EPInfR_EPT_BIT) -+ #define UDC_EPInfR_EPT_INTR (3 << UDC_EPInfR_EPT_BIT) -+#define UDC_EPInfR_EPD (1 << 4) -+ #define UDC_EPInfR_EPD_OUT (0 << 4) -+ #define UDC_EPInfR_EPD_IN (1 << 4) -+ -+#define UDC_EPInfR_EPN_BIT 0 -+#define UDC_EPInfR_EPN_MASK (0xf << UDC_EPInfR_EPN_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * DMAC -+ *************************************************************************/ -+#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) -+#define DMAC_DDAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) -+#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) -+#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) -+#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) -+#define DMAC_DMAIPR (DMAC_BASE + 0xf8) -+#define DMAC_DMACR (DMAC_BASE + 0xfc) -+ -+#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n))) -+#define REG_DMAC_DDAR(n) REG32(DMAC_DDAR((n))) -+#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n))) -+#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n))) -+#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) -+#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR) -+#define REG_DMAC_DMACR REG32(DMAC_DMACR) -+ -+#define DMAC_DRSR_RS_BIT 0 -+#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_EXTREXTR (0 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_PCMCIAOUT (4 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_PCMCIAIN (5 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_DESOUT (10 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_DESIN (11 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART3OUT (14 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART3IN (15 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART2OUT (16 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART2IN (17 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART1OUT (18 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART1IN (19 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_OST2 (28 << DMAC_DRSR_RS_BIT) -+ -+#define DMAC_DCCSR_EACKS (1 << 31) -+#define DMAC_DCCSR_EACKM (1 << 30) -+#define DMAC_DCCSR_ERDM_BIT 28 -+#define DMAC_DCCSR_ERDM_MASK (0x03 << DMAC_DCCSR_ERDM_BIT) -+ #define DMAC_DCCSR_ERDM_LLEVEL (0 << DMAC_DCCSR_ERDM_BIT) -+ #define DMAC_DCCSR_ERDM_FEDGE (1 << DMAC_DCCSR_ERDM_BIT) -+ #define DMAC_DCCSR_ERDM_HLEVEL (2 << DMAC_DCCSR_ERDM_BIT) -+ #define DMAC_DCCSR_ERDM_REDGE (3 << DMAC_DCCSR_ERDM_BIT) -+#define DMAC_DCCSR_EOPM (1 << 27) -+#define DMAC_DCCSR_SAM (1 << 23) -+#define DMAC_DCCSR_DAM (1 << 22) -+#define DMAC_DCCSR_RDIL_BIT 16 -+#define DMAC_DCCSR_RDIL_MASK (0x0f << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_IGN (0 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_2 (1 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_4 (2 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_8 (3 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_12 (4 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_16 (5 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_20 (6 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_24 (7 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_28 (8 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_32 (9 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_48 (10 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_60 (11 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_64 (12 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_124 (13 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_128 (14 << DMAC_DCCSR_RDIL_BIT) -+ #define DMAC_DCCSR_RDIL_200 (15 << DMAC_DCCSR_RDIL_BIT) -+#define DMAC_DCCSR_SWDH_BIT 14 -+#define DMAC_DCCSR_SWDH_MASK (0x03 << DMAC_DCCSR_SWDH_BIT) -+ #define DMAC_DCCSR_SWDH_32 (0 << DMAC_DCCSR_SWDH_BIT) -+ #define DMAC_DCCSR_SWDH_8 (1 << DMAC_DCCSR_SWDH_BIT) -+ #define DMAC_DCCSR_SWDH_16 (2 << DMAC_DCCSR_SWDH_BIT) -+#define DMAC_DCCSR_DWDH_BIT 12 -+#define DMAC_DCCSR_DWDH_MASK (0x03 << DMAC_DCCSR_DWDH_BIT) -+ #define DMAC_DCCSR_DWDH_32 (0 << DMAC_DCCSR_DWDH_BIT) -+ #define DMAC_DCCSR_DWDH_8 (1 << DMAC_DCCSR_DWDH_BIT) -+ #define DMAC_DCCSR_DWDH_16 (2 << DMAC_DCCSR_DWDH_BIT) -+#define DMAC_DCCSR_DS_BIT 8 -+#define DMAC_DCCSR_DS_MASK (0x07 << DMAC_DCCSR_DS_BIT) -+ #define DMAC_DCCSR_DS_32b (0 << DMAC_DCCSR_DS_BIT) -+ #define DMAC_DCCSR_DS_8b (1 << DMAC_DCCSR_DS_BIT) -+ #define DMAC_DCCSR_DS_16b (2 << DMAC_DCCSR_DS_BIT) -+ #define DMAC_DCCSR_DS_16B (3 << DMAC_DCCSR_DS_BIT) -+ #define DMAC_DCCSR_DS_32B (4 << DMAC_DCCSR_DS_BIT) -+#define DMAC_DCCSR_TM (1 << 7) -+#define DMAC_DCCSR_AR (1 << 4) -+#define DMAC_DCCSR_TC (1 << 3) -+#define DMAC_DCCSR_HLT (1 << 2) -+#define DMAC_DCCSR_TCIE (1 << 1) -+#define DMAC_DCCSR_CHDE (1 << 0) -+ -+#define DMAC_DMAIPR_CINT_BIT 8 -+#define DMAC_DMAIPR_CINT_MASK (0xff << DMAC_DMAIPR_CINT_BIT) -+ -+#define DMAC_DMACR_PR_BIT 8 -+#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_01234567 (0 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_02314675 (1 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_20136457 (2 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_ROUNDROBIN (3 << DMAC_DMACR_PR_BIT) -+#define DMAC_DMACR_HTR (1 << 3) -+#define DMAC_DMACR_AER (1 << 2) -+#define DMAC_DMACR_DME (1 << 0) -+ -+#define IRQ_DMA_0 32 -+#define NUM_DMA 6 -+ -+#define DMAC_DSAR0 DMAC_DSAR(0) -+#define DMAC_DDAR0 DMAC_DDAR(0) -+#define DMAC_DTCR0 DMAC_DTCR(0) -+#define DMAC_DRSR0 DMAC_DRSR(0) -+#define DMAC_DCCSR0 DMAC_DCCSR(0) -+ -+#define DMAC_DSAR1 DMAC_DSAR(1) -+#define DMAC_DDAR1 DMAC_DDAR(1) -+#define DMAC_DTCR1 DMAC_DTCR(1) -+#define DMAC_DRSR1 DMAC_DRSR(1) -+#define DMAC_DCCSR1 DMAC_DCCSR(1) -+ -+#define DMAC_DSAR2 DMAC_DSAR(2) -+#define DMAC_DDAR2 DMAC_DDAR(2) -+#define DMAC_DTCR2 DMAC_DTCR(2) -+#define DMAC_DRSR2 DMAC_DRSR(2) -+#define DMAC_DCCSR2 DMAC_DCCSR(2) -+ -+#define DMAC_DSAR3 DMAC_DSAR(3) -+#define DMAC_DDAR3 DMAC_DDAR(3) -+#define DMAC_DTCR3 DMAC_DTCR(3) -+#define DMAC_DRSR3 DMAC_DRSR(3) -+#define DMAC_DCCSR3 DMAC_DCCSR(3) -+ -+#define DMAC_DSAR4 DMAC_DSAR(4) -+#define DMAC_DDAR4 DMAC_DDAR(4) -+#define DMAC_DTCR4 DMAC_DTCR(4) -+#define DMAC_DRSR4 DMAC_DRSR(4) -+#define DMAC_DCCSR4 DMAC_DCCSR(4) -+ -+#define DMAC_DSAR5 DMAC_DSAR(5) -+#define DMAC_DDAR5 DMAC_DDAR(5) -+#define DMAC_DTCR5 DMAC_DTCR(5) -+#define DMAC_DRSR5 DMAC_DRSR(5) -+#define DMAC_DCCSR5 DMAC_DCCSR(5) -+ -+#define DMAC_DSAR6 DMAC_DSAR(6) -+#define DMAC_DDAR6 DMAC_DDAR(6) -+#define DMAC_DTCR6 DMAC_DTCR(6) -+#define DMAC_DRSR6 DMAC_DRSR(6) -+#define DMAC_DCCSR6 DMAC_DCCSR(6) -+ -+#define DMAC_DSAR7 DMAC_DSAR(7) -+#define DMAC_DDAR7 DMAC_DDAR(7) -+#define DMAC_DTCR7 DMAC_DTCR(7) -+#define DMAC_DRSR7 DMAC_DRSR(7) -+#define DMAC_DCCSR7 DMAC_DCCSR(7) -+ -+ -+ -+/************************************************************************* -+ * AIC -+ *************************************************************************/ -+#define AIC_FR (AIC_BASE + 0x000) -+#define AIC_CR (AIC_BASE + 0x004) -+#define AIC_ACCR1 (AIC_BASE + 0x008) -+#define AIC_ACCR2 (AIC_BASE + 0x00C) -+#define AIC_I2SCR (AIC_BASE + 0x010) -+#define AIC_SR (AIC_BASE + 0x014) -+#define AIC_ACSR (AIC_BASE + 0x018) -+#define AIC_I2SSR (AIC_BASE + 0x01C) -+#define AIC_ACCAR (AIC_BASE + 0x020) -+#define AIC_ACCDR (AIC_BASE + 0x024) -+#define AIC_ACSAR (AIC_BASE + 0x028) -+#define AIC_ACSDR (AIC_BASE + 0x02C) -+#define AIC_I2SDIV (AIC_BASE + 0x030) -+#define AIC_DR (AIC_BASE + 0x034) -+ -+#define REG_AIC_FR REG32(AIC_FR) -+#define REG_AIC_CR REG32(AIC_CR) -+#define REG_AIC_ACCR1 REG32(AIC_ACCR1) -+#define REG_AIC_ACCR2 REG32(AIC_ACCR2) -+#define REG_AIC_I2SCR REG32(AIC_I2SCR) -+#define REG_AIC_SR REG32(AIC_SR) -+#define REG_AIC_ACSR REG32(AIC_ACSR) -+#define REG_AIC_I2SSR REG32(AIC_I2SSR) -+#define REG_AIC_ACCAR REG32(AIC_ACCAR) -+#define REG_AIC_ACCDR REG32(AIC_ACCDR) -+#define REG_AIC_ACSAR REG32(AIC_ACSAR) -+#define REG_AIC_ACSDR REG32(AIC_ACSDR) -+#define REG_AIC_I2SDIV REG32(AIC_I2SDIV) -+#define REG_AIC_DR REG32(AIC_DR) -+ -+/* AIC Controller Configuration Register (AIC_FR) */ -+ -+#define AIC_FR_RFTH_BIT 12 -+#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT) -+#define AIC_FR_TFTH_BIT 8 -+#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT) -+#define AIC_FR_AUSEL (1 << 4) -+#define AIC_FR_RST (1 << 3) -+#define AIC_FR_BCKD (1 << 2) -+#define AIC_FR_SYNCD (1 << 1) -+#define AIC_FR_ENB (1 << 0) -+ -+/* AIC Controller Common Control Register (AIC_CR) */ -+ -+#define AIC_CR_RDMS (1 << 15) -+#define AIC_CR_TDMS (1 << 14) -+#define AIC_CR_FLUSH (1 << 8) -+#define AIC_CR_EROR (1 << 6) -+#define AIC_CR_ETUR (1 << 5) -+#define AIC_CR_ERFS (1 << 4) -+#define AIC_CR_ETFS (1 << 3) -+#define AIC_CR_ENLBF (1 << 2) -+#define AIC_CR_ERPL (1 << 1) -+#define AIC_CR_EREC (1 << 0) -+ -+/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -+ -+#define AIC_ACCR1_RS_BIT 16 -+#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -+ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit */ -+ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit */ -+ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit */ -+ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit */ -+ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit */ -+ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit */ -+#define AIC_ACCR1_XS_BIT 0 -+#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -+ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit */ -+ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit */ -+ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit */ -+ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit */ -+ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit */ -+ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit */ -+ -+/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -+ -+#define AIC_ACCR2_ERSTO (1 << 18) -+#define AIC_ACCR2_ESADR (1 << 17) -+#define AIC_ACCR2_ECADT (1 << 16) -+#define AIC_ACCR2_OASS_BIT 8 -+#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -+ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_IASS_BIT 6 -+#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -+ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_SO (1 << 3) -+#define AIC_ACCR2_SR (1 << 2) -+#define AIC_ACCR2_SS (1 << 1) -+#define AIC_ACCR2_SA (1 << 0) -+ -+/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -+ -+#define AIC_I2SCR_STPBK (1 << 12) -+#define AIC_I2SCR_WL_BIT 1 -+#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -+ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -+ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -+ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -+ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -+ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -+#define AIC_I2SCR_AMSL (1 << 0) -+ -+/* AIC Controller FIFO Status Register (AIC_SR) */ -+ -+#define AIC_SR_RFL_BIT 24 -+#define AIC_SR_RFL_MASK (0x1f << AIC_SR_RFL_BIT) -+#define AIC_SR_TFL_BIT 8 -+#define AIC_SR_TFL_MASK (0x1f << AIC_SR_TFL_BIT) -+#define AIC_SR_ROR (1 << 6) -+#define AIC_SR_TUR (1 << 5) -+#define AIC_SR_RFS (1 << 4) -+#define AIC_SR_TFS (1 << 3) -+ -+/* AIC Controller AC-link Status Register (AIC_ACSR) */ -+ -+#define AIC_ACSR_CRDY (1 << 20) -+#define AIC_ACSR_CLPM (1 << 19) -+#define AIC_ACSR_RSTO (1 << 18) -+#define AIC_ACSR_SADR (1 << 17) -+#define AIC_ACSR_CADT (1 << 16) -+ -+/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -+ -+#define AIC_I2SSR_BSY (1 << 2) -+ -+/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -+ -+#define AIC_ACCAR_CAR_BIT 0 -+#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -+ -+/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -+ -+#define AIC_ACCDR_CDR_BIT 0 -+#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -+ -+/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -+ -+#define AIC_ACSAR_SAR_BIT 0 -+#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -+ -+/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -+ -+#define AIC_ACSDR_SDR_BIT 0 -+#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -+ -+/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -+ -+#define AIC_I2SDIV_DIV_BIT 0 -+#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -+ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -+ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -+ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -+ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -+ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -+ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -+ -+ -+ -+ -+/************************************************************************* -+ * LCD -+ *************************************************************************/ -+#define LCD_CFG (LCD_BASE + 0x00) -+#define LCD_VSYNC (LCD_BASE + 0x04) -+#define LCD_HSYNC (LCD_BASE + 0x08) -+#define LCD_VAT (LCD_BASE + 0x0c) -+#define LCD_DAH (LCD_BASE + 0x10) -+#define LCD_DAV (LCD_BASE + 0x14) -+#define LCD_PS (LCD_BASE + 0x18) -+#define LCD_CLS (LCD_BASE + 0x1c) -+#define LCD_SPL (LCD_BASE + 0x20) -+#define LCD_REV (LCD_BASE + 0x24) -+#define LCD_CTRL (LCD_BASE + 0x30) -+#define LCD_STATE (LCD_BASE + 0x34) -+#define LCD_IID (LCD_BASE + 0x38) -+#define LCD_DA0 (LCD_BASE + 0x40) -+#define LCD_SA0 (LCD_BASE + 0x44) -+#define LCD_FID0 (LCD_BASE + 0x48) -+#define LCD_CMD0 (LCD_BASE + 0x4c) -+#define LCD_DA1 (LCD_BASE + 0x50) -+#define LCD_SA1 (LCD_BASE + 0x54) -+#define LCD_FID1 (LCD_BASE + 0x58) -+#define LCD_CMD1 (LCD_BASE + 0x5c) -+ -+#define REG_LCD_CFG REG32(LCD_CFG) -+#define REG_LCD_VSYNC REG32(LCD_VSYNC) -+#define REG_LCD_HSYNC REG32(LCD_HSYNC) -+#define REG_LCD_VAT REG32(LCD_VAT) -+#define REG_LCD_DAH REG32(LCD_DAH) -+#define REG_LCD_DAV REG32(LCD_DAV) -+#define REG_LCD_PS REG32(LCD_PS) -+#define REG_LCD_CLS REG32(LCD_CLS) -+#define REG_LCD_SPL REG32(LCD_SPL) -+#define REG_LCD_REV REG32(LCD_REV) -+#define REG_LCD_CTRL REG32(LCD_CTRL) -+#define REG_LCD_STATE REG32(LCD_STATE) -+#define REG_LCD_IID REG32(LCD_IID) -+#define REG_LCD_DA0 REG32(LCD_DA0) -+#define REG_LCD_SA0 REG32(LCD_SA0) -+#define REG_LCD_FID0 REG32(LCD_FID0) -+#define REG_LCD_CMD0 REG32(LCD_CMD0) -+#define REG_LCD_DA1 REG32(LCD_DA1) -+#define REG_LCD_SA1 REG32(LCD_SA1) -+#define REG_LCD_FID1 REG32(LCD_FID1) -+#define REG_LCD_CMD1 REG32(LCD_CMD1) -+ -+#define LCD_CFG_PDW_BIT 4 -+#define LCD_CFG_PDW_MASK (0x03 << LCD_DEV_PDW_BIT) -+ #define LCD_CFG_PDW_1 (0 << LCD_DEV_PDW_BIT) -+ #define LCD_CFG_PDW_2 (1 << LCD_DEV_PDW_BIT) -+ #define LCD_CFG_PDW_4 (2 << LCD_DEV_PDW_BIT) -+ #define LCD_CFG_PDW_8 (3 << LCD_DEV_PDW_BIT) -+#define LCD_CFG_MODE_BIT 0 -+#define LCD_CFG_MODE_MASK (0x0f << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_SHARP_HR (1 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_DEV_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_DEV_MODE_BIT) -+ -+#define LCD_VSYNC_VPS_BIT 16 -+#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT) -+#define LCD_VSYNC_VPE_BIT 0 -+#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT) -+ -+#define LCD_HSYNC_HPS_BIT 16 -+#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT) -+#define LCD_HSYNC_HPE_BIT 0 -+#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT) -+ -+#define LCD_VAT_HT_BIT 16 -+#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT) -+#define LCD_VAT_VT_BIT 0 -+#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT) -+ -+#define LCD_DAH_HDS_BIT 16 -+#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT) -+#define LCD_DAH_HDE_BIT 0 -+#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT) -+ -+#define LCD_DAV_VDS_BIT 16 -+#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT) -+#define LCD_DAV_VDE_BIT 0 -+#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT) -+ -+#define LCD_CTRL_BST_BIT 28 -+#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -+ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) -+ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) -+ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) -+#define LCD_CTRL_RGB555 (1 << 27) -+#define LCD_CTRL_OFUP (1 << 26) -+#define LCD_CTRL_FRC_BIT 24 -+#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -+ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) -+ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) -+ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) -+#define LCD_CTRL_PDD_BIT 16 -+#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -+#define LCD_CTRL_EOFM (1 << 13) -+#define LCD_CTRL_SOFM (1 << 12) -+#define LCD_CTRL_OFUM (1 << 11) -+#define LCD_CTRL_IFUM0 (1 << 10) -+#define LCD_CTRL_IFUM1 (1 << 9) -+#define LCD_CTRL_LDDM (1 << 8) -+#define LCD_CTRL_QDM (1 << 7) -+#define LCD_CTRL_BEDN (1 << 6) -+#define LCD_CTRL_PEDN (1 << 5) -+#define LCD_CTRL_DIS (1 << 4) -+#define LCD_CTRL_ENA (1 << 3) -+#define LCD_CTRL_BPP_BIT 0 -+#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) -+ -+#define LCD_STATE_QD (1 << 7) -+#define LCD_STATE_EOF (1 << 5) -+#define LCD_STATE_SOF (1 << 4) -+#define LCD_STATE_OFU (1 << 3) -+#define LCD_STATE_IFU0 (1 << 2) -+#define LCD_STATE_IFU1 (1 << 1) -+#define LCD_STATE_LDD (1 << 0) -+ -+#define LCD_CMD_SOFINT (1 << 31) -+#define LCD_CMD_EOFINT (1 << 30) -+#define LCD_CMD_PAL (1 << 28) -+#define LCD_CMD_LEN_BIT 0 -+#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * DES -+ *************************************************************************/ -+#define DES_CR1 (DES_BASE + 0x000) -+#define DES_CR2 (DES_BASE + 0x004) -+#define DES_SR (DES_BASE + 0x008) -+#define DES_K1L (DES_BASE + 0x010) -+#define DES_K1R (DES_BASE + 0x014) -+#define DES_K2L (DES_BASE + 0x018) -+#define DES_K2R (DES_BASE + 0x01C) -+#define DES_K3L (DES_BASE + 0x020) -+#define DES_K3R (DES_BASE + 0x024) -+#define DES_IVL (DES_BASE + 0x028) -+#define DES_IVR (DES_BASE + 0x02C) -+#define DES_DIN (DES_BASE + 0x030) -+#define DES_DOUT (DES_BASE + 0x034) -+ -+#define REG_DES_CR1 REG32(DES_CR1) -+#define REG_DES_CR2 REG32(DES_CR2) -+#define REG_DES_SR REG32(DES_SR) -+#define REG_DES_K1L REG32(DES_K1L) -+#define REG_DES_K1R REG32(DES_K1R) -+#define REG_DES_K2L REG32(DES_K2L) -+#define REG_DES_K2R REG32(DES_K2R) -+#define REG_DES_K3L REG32(DES_K3L) -+#define REG_DES_K3R REG32(DES_K3R) -+#define REG_DES_IVL REG32(DES_IVL) -+#define REG_DES_IVR REG32(DES_IVR) -+#define REG_DES_DIN REG32(DES_DIN) -+#define REG_DES_DOUT REG32(DES_DOUT) -+ -+/* DES Control Register 1 (DES_CR1) */ -+ -+#define DES_CR1_EN (1 << 0) -+ -+/* DES Control Register 2 (DES_CR2) */ -+ -+#define DES_CR2_ENDEC (1 << 3) -+#define DES_CR2_MODE (1 << 2) -+#define DES_CR2_ALG (1 << 1) -+#define DES_CR2_DMAE (1 << 0) -+ -+/* DES State Register (DES_SR) */ -+ -+#define DES_SR_IN_FULL (1 << 5) -+#define DES_SR_IN_LHF (1 << 4) -+#define DES_SR_IN_EMPTY (1 << 3) -+#define DES_SR_OUT_FULL (1 << 2) -+#define DES_SR_OUT_GHF (1 << 1) -+#define DES_SR_OUT_EMPTY (1 << 0) -+ -+ -+ -+ -+/************************************************************************* -+ * CPM -+ *************************************************************************/ -+#define CPM_CFCR (CPM_BASE+0x00) -+#define CPM_PLCR1 (CPM_BASE+0x10) -+#define CPM_OCR (CPM_BASE+0x1c) -+#define CPM_CFCR2 (CPM_BASE+0x60) -+#define CPM_LPCR (CPM_BASE+0x04) -+#define CPM_RSTR (CPM_BASE+0x08) -+#define CPM_MSCR (CPM_BASE+0x20) -+#define CPM_SCR (CPM_BASE+0x24) -+#define CPM_WRER (CPM_BASE+0x28) -+#define CPM_WFER (CPM_BASE+0x2c) -+#define CPM_WER (CPM_BASE+0x30) -+#define CPM_WSR (CPM_BASE+0x34) -+#define CPM_GSR0 (CPM_BASE+0x38) -+#define CPM_GSR1 (CPM_BASE+0x3c) -+#define CPM_GSR2 (CPM_BASE+0x40) -+#define CPM_SPR (CPM_BASE+0x44) -+#define CPM_GSR3 (CPM_BASE+0x48) -+ -+#define REG_CPM_CFCR REG32(CPM_CFCR) -+#define REG_CPM_PLCR1 REG32(CPM_PLCR1) -+#define REG_CPM_OCR REG32(CPM_OCR) -+#define REG_CPM_CFCR2 REG32(CPM_CFCR2) -+#define REG_CPM_LPCR REG32(CPM_LPCR) -+#define REG_CPM_RSTR REG32(CPM_RSTR) -+#define REG_CPM_MSCR REG32(CPM_MSCR) -+#define REG_CPM_SCR REG32(CPM_SCR) -+#define REG_CPM_WRER REG32(CPM_WRER) -+#define REG_CPM_WFER REG32(CPM_WFER) -+#define REG_CPM_WER REG32(CPM_WER) -+#define REG_CPM_WSR REG32(CPM_WSR) -+#define REG_CPM_GSR0 REG32(CPM_GSR0) -+#define REG_CPM_GSR1 REG32(CPM_GSR1) -+#define REG_CPM_GSR2 REG32(CPM_GSR2) -+#define REG_CPM_SPR REG32(CPM_SPR) -+#define REG_CPM_GSR3 REG32(CPM_GSR3) -+ -+#define CPM_CFCR_SSI (1 << 31) -+#define CPM_CFCR_LCD (1 << 30) -+#define CPM_CFCR_I2S (1 << 29) -+#define CPM_CFCR_UCS (1 << 28) -+#define CPM_CFCR_UFR_BIT 25 -+#define CPM_CFCR_UFR_MASK (0x07 << CPM_CFCR_UFR_BIT) -+#define CPM_CFCR_MSC (1 << 24) -+#define CPM_CFCR_CKOEN2 (1 << 23) -+#define CPM_CFCR_CKOEN1 (1 << 22) -+#define CPM_CFCR_UPE (1 << 20) -+#define CPM_CFCR_MFR_BIT 16 -+#define CPM_CFCR_MFR_MASK (0x0f << CPM_CFCR_MFR_BIT) -+#define CPM_CFCR_LFR_BIT 12 -+#define CPM_CFCR_LFR_MASK (0x0f << CPM_CFCR_LFR_BIT) -+#define CPM_CFCR_PFR_BIT 8 -+#define CPM_CFCR_PFR_MASK (0x0f << CPM_CFCR_PFR_BIT) -+#define CPM_CFCR_SFR_BIT 4 -+#define CPM_CFCR_SFR_MASK (0x0f << CPM_CFCR_SFR_BIT) -+#define CPM_CFCR_IFR_BIT 0 -+#define CPM_CFCR_IFR_MASK (0x0f << CPM_CFCR_IFR_BIT) -+ -+#define CPM_PLCR1_PLL1FD_BIT 23 -+#define CPM_PLCR1_PLL1FD_MASK (0x1ff << CPM_PLCR1_PLL1FD_BIT) -+#define CPM_PLCR1_PLL1RD_BIT 18 -+#define CPM_PLCR1_PLL1RD_MASK (0x1f << CPM_PLCR1_PLL1RD_BIT) -+#define CPM_PLCR1_PLL1OD_BIT 16 -+#define CPM_PLCR1_PLL1OD_MASK (0x03 << CPM_PLCR1_PLL1OD_BIT) -+#define CPM_PLCR1_PLL1S (1 << 10) -+#define CPM_PLCR1_PLL1BP (1 << 9) -+#define CPM_PLCR1_PLL1EN (1 << 8) -+#define CPM_PLCR1_PLL1ST_BIT 0 -+#define CPM_PLCR1_PLL1ST_MASK (0xff << CPM_PLCR1_PLL1ST_BIT) -+ -+#define CPM_OCR_O1ST_BIT 16 -+#define CPM_OCR_O1ST_MASK (0xff << CPM_OCR_O1ST_BIT) -+#define CPM_OCR_EXT_RTC_CLK (1<<8) -+#define CPM_OCR_SUSPEND_PHY1 (1<<7) -+#define CPM_OCR_SUSPEND_PHY0 (1<<6) -+ -+#define CPM_CFCR2_PXFR_BIT 0 -+#define CPM_CFCR2_PXFR_MASK (0x1ff << CPM_CFCR2_PXFR_BIT) -+ -+#define CPM_LPCR_DUTY_BIT 3 -+#define CPM_LPCR_DUTY_MASK (0x1f << CPM_LPCR_DUTY_BIT) -+#define CPM_LPCR_DOZE (1 << 2) -+#define CPM_LPCR_LPM_BIT 0 -+#define CPM_LPCR_LPM_MASK (0x03 << CPM_LPCR_LPM_BIT) -+ #define CPM_LPCR_LPM_IDLE (0 << CPM_LPCR_LPM_BIT) -+ #define CPM_LPCR_LPM_SLEEP (1 << CPM_LPCR_LPM_BIT) -+ #define CPM_LPCR_LPM_HIBERNATE (2 << CPM_LPCR_LPM_BIT) -+ -+#define CPM_RSTR_SR (1 << 2) -+#define CPM_RSTR_WR (1 << 1) -+#define CPM_RSTR_HR (1 << 0) -+ -+#define CPM_MSCR_MSTP_BIT 0 -+#define CPM_MSCR_MSTP_MASK (0x1ffffff << CPM_MSCR_MSTP_BIT) -+ #define CPM_MSCR_MSTP_UART0 0 -+ #define CPM_MSCR_MSTP_UART1 1 -+ #define CPM_MSCR_MSTP_UART2 2 -+ #define CPM_MSCR_MSTP_OST 3 -+ #define CPM_MSCR_MSTP_DMAC 5 -+ #define CPM_MSCR_MSTP_UHC 6 -+ #define CPM_MSCR_MSTP_LCD 7 -+ #define CPM_MSCR_MSTP_I2C 8 -+ #define CPM_MSCR_MSTP_AICPCLK 9 -+ #define CPM_MSCR_MSTP_PWM0 10 -+ #define CPM_MSCR_MSTP_PWM1 11 -+ #define CPM_MSCR_MSTP_SSI 12 -+ #define CPM_MSCR_MSTP_MSC 13 -+ #define CPM_MSCR_MSTP_SCC 14 -+ #define CPM_MSCR_MSTP_AICBCLK 18 -+ #define CPM_MSCR_MSTP_UART3 20 -+ #define CPM_MSCR_MSTP_ETH 21 -+ #define CPM_MSCR_MSTP_KBC 22 -+ #define CPM_MSCR_MSTP_CIM 23 -+ #define CPM_MSCR_MSTP_UDC 24 -+ #define CPM_MSCR_MSTP_UPRT 25 -+ -+#define CPM_SCR_O1SE (1 << 4) -+#define CPM_SCR_HGP (1 << 3) -+#define CPM_SCR_HZP (1 << 2) -+#define CPM_SCR_HZM (1 << 1) -+ -+#define CPM_WRER_RE_BIT 0 -+#define CPM_WRER_RE_MASK (0xffff << CPM_WRER_RE_BIT) -+ -+#define CPM_WFER_FE_BIT 0 -+#define CPM_WFER_FE_MASK (0xffff << CPM_WFER_FE_BIT) -+ -+#define CPM_WER_WERTC (1 << 31) -+#define CPM_WER_WEETH (1 << 30) -+#define CPM_WER_WE_BIT 0 -+#define CPM_WER_WE_MASK (0xffff << CPM_WER_WE_BIT) -+ -+#define CPM_WSR_WSRTC (1 << 31) -+#define CPM_WSR_WSETH (1 << 30) -+#define CPM_WSR_WS_BIT 0 -+#define CPM_WSR_WS_MASK (0xffff << CPM_WSR_WS_BIT) -+ -+ -+ -+ -+/************************************************************************* -+ * SSI -+ *************************************************************************/ -+#define SSI_DR (SSI_BASE + 0x000) -+#define SSI_CR0 (SSI_BASE + 0x004) -+#define SSI_CR1 (SSI_BASE + 0x008) -+#define SSI_SR (SSI_BASE + 0x00C) -+#define SSI_ITR (SSI_BASE + 0x010) -+#define SSI_ICR (SSI_BASE + 0x014) -+#define SSI_GR (SSI_BASE + 0x018) -+ -+#define REG_SSI_DR REG32(SSI_DR) -+#define REG_SSI_CR0 REG16(SSI_CR0) -+#define REG_SSI_CR1 REG32(SSI_CR1) -+#define REG_SSI_SR REG32(SSI_SR) -+#define REG_SSI_ITR REG16(SSI_ITR) -+#define REG_SSI_ICR REG8(SSI_ICR) -+#define REG_SSI_GR REG16(SSI_GR) -+ -+/* SSI Data Register (SSI_DR) */ -+ -+#define SSI_DR_GPC_BIT 0 -+#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -+ -+/* SSI Control Register 0 (SSI_CR0) */ -+ -+#define SSI_CR0_SSIE (1 << 15) -+#define SSI_CR0_TIE (1 << 14) -+#define SSI_CR0_RIE (1 << 13) -+#define SSI_CR0_TEIE (1 << 12) -+#define SSI_CR0_REIE (1 << 11) -+#define SSI_CR0_LOOP (1 << 10) -+#define SSI_CR0_RFINE (1 << 9) -+#define SSI_CR0_RFINC (1 << 8) -+#define SSI_CR0_FSEL (1 << 6) -+#define SSI_CR0_TFLUSH (1 << 2) -+#define SSI_CR0_RFLUSH (1 << 1) -+#define SSI_CR0_DISREV (1 << 0) -+ -+/* SSI Control Register 1 (SSI_CR1) */ -+ -+#define SSI_CR1_FRMHL_BIT 30 -+#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -+ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -+#define SSI_CR1_TFVCK_BIT 28 -+#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -+#define SSI_CR1_TCKFI_BIT 26 -+#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -+#define SSI_CR1_LFST (1 << 25) -+#define SSI_CR1_ITFRM (1 << 24) -+#define SSI_CR1_UNFIN (1 << 23) -+#define SSI_CR1_MULTS (1 << 22) -+#define SSI_CR1_FMAT_BIT 20 -+#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -+ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -+ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -+ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -+ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -+#define SSI_CR1_MCOM_BIT 12 -+#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -+ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -+ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -+ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -+ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -+ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -+ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -+ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -+ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -+ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -+ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -+ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -+ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -+ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -+ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -+ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -+ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -+#define SSI_CR1_TTRG_BIT 10 -+#define SSI_CR1_TTRG_MASK (0x3 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT)/* Less than or equal to 1 */ -+ #define SSI_CR1_TTRG_4 (1 << SSI_CR1_TTRG_BIT) /* Less than or equal to 4 */ -+ #define SSI_CR1_TTRG_8 (2 << SSI_CR1_TTRG_BIT) /* Less than or equal to 8 */ -+ #define SSI_CR1_TTRG_14 (3 << SSI_CR1_TTRG_BIT) /* Less than or equal to 14 */ -+#define SSI_CR1_RTRG_BIT 8 -+#define SSI_CR1_RTRG_MASK (0x3 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT) /* More than or equal to 1 */ -+ #define SSI_CR1_RTRG_4 (1 << SSI_CR1_RTRG_BIT) /* More than or equal to 4 */ -+ #define SSI_CR1_RTRG_8 (2 << SSI_CR1_RTRG_BIT) /* More than or equal to 8 */ -+ #define SSI_CR1_RTRG_14 (3 << SSI_CR1_RTRG_BIT) /* More than or equal to 14 */ -+#define SSI_CR1_FLEN_BIT 4 -+#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -+#define SSI_CR1_PHA (1 << 1) -+#define SSI_CR1_POL (1 << 0) -+ -+/* SSI Status Register (SSI_SR) */ -+ -+#define SSI_SR_TFIFONUM_BIT 13 -+#define SSI_SR_TFIFONUM_MASK (0x1f << SSI_SR_TFIFONUM_BIT) -+#define SSI_SR_RFIFONUM_BIT 8 -+#define SSI_SR_RFIFONUM_MASK (0x1f << SSI_SR_RFIFONUM_BIT) -+#define SSI_SR_END (1 << 7) -+#define SSI_SR_BUSY (1 << 6) -+#define SSI_SR_TFF (1 << 5) -+#define SSI_SR_RFE (1 << 4) -+#define SSI_SR_TFHE (1 << 3) -+#define SSI_SR_RFHF (1 << 2) -+#define SSI_SR_UNDR (1 << 1) -+#define SSI_SR_OVER (1 << 0) -+ -+/* SSI Interval Time Control Register (SSI_ITR) */ -+ -+#define SSI_ITR_CNTCLK (1 << 15) -+#define SSI_ITR_IVLTM_BIT 0 -+#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -+ -+#endif /* __ASM_JZ4730_REGS_H__ */ -diff --git a/include/asm-mips/mach-jz4730/serial.h b/include/asm-mips/mach-jz4730/serial.h -new file mode 100644 -index 0000000..4a0afc3 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/serial.h -@@ -0,0 +1,33 @@ -+/* -+ * linux/include/asm-mips/mach-jz4730/serial.h -+ * -+ * JZ4730 serial port definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4730_SERIAL_H__ -+#define __ASM_JZ4730_SERIAL_H__ -+ -+#define JZ_BASE_BAUD (JZ_EXTAL/16) -+#define JZ_SERIAL_PORT_DEFNS \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART1, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART1_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART2, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART2_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART3, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART3_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -+ -+#endif /* __ASM_JZ4730_SERIAL_H__ */ -diff --git a/include/asm-mips/mach-jz4730/war.h b/include/asm-mips/mach-jz4730/war.h -new file mode 100644 -index 0000000..3a5bc17 ---- /dev/null -+++ b/include/asm-mips/mach-jz4730/war.h -@@ -0,0 +1,25 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -+ */ -+#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -+#define __ASM_MIPS_MACH_JZ4740_WAR_H -+ -+#define R4600_V1_INDEX_ICACHEOP_WAR 0 -+#define R4600_V1_HIT_CACHEOP_WAR 0 -+#define R4600_V2_HIT_CACHEOP_WAR 0 -+#define R5432_CP0_INTERRUPT_WAR 0 -+#define BCM1250_M3_WAR 0 -+#define SIBYTE_1956_WAR 0 -+#define MIPS4K_ICACHE_REFILL_WAR 0 -+#define MIPS_CACHE_SYNC_WAR 0 -+#define TX49XX_ICACHE_INDEX_INV_WAR 0 -+#define RM9000_CDEX_SMP_WAR 0 -+#define ICACHE_REFILLS_WORKAROUND_WAR 0 -+#define R10000_LLSC_WAR 0 -+#define MIPS34K_MISSED_ITLB_WAR 0 -+ -+#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -diff --git a/include/asm-mips/mach-jz4740/board-dipper.h b/include/asm-mips/mach-jz4740/board-dipper.h -new file mode 100644 -index 0000000..ae84f24 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/board-dipper.h -@@ -0,0 +1,69 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/board-dipper.h -+ * -+ * JZ4725-based (16bit) Dipper board ver 1.x definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4725_DIPPER_H__ -+#define __ASM_JZ4725_DIPPER_H__ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+/*====================================================================== -+ * GPIO JZ4725 -+ */ -+#define GPIO_SD_VCC_EN_N 85 /* GPC21 */ -+#define GPIO_SD_CD_N 91 /* GPC27 */ -+#define GPIO_SD_WP 112 /* GPD16 */ -+#define GPIO_USB_DETE 124 /* GPD28 */ -+#define GPIO_DC_DETE_N 103 /* GPD7 */ -+#define GPIO_CHARG_STAT_N 86 /* GPC22 */ -+#define GPIO_DISP_OFF_N 118 /* GPD22 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC_WP_PIN GPIO_SD_WP -+#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -+ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+} while (0) -+ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4740_DIPPER_H__ */ -diff --git a/include/asm-mips/mach-jz4740/board-leo.h b/include/asm-mips/mach-jz4740/board-leo.h -new file mode 100644 -index 0000000..4b883e2 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/board-leo.h -@@ -0,0 +1,56 @@ -+#ifndef __ASM_JZ4740_LEO_H__ -+#define __ASM_JZ4740_LEO_H__ -+ -+/* -+ * Define your board specific codes here !!! -+ */ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_DISP_OFF_N 100 -+#define GPIO_SD_VCC_EN_N 119 -+#define GPIO_SD_CD_N 120 -+#define GPIO_SD_WP 111 -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC_WP_PIN GPIO_SD_WP -+#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -+ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+} while (0) -+ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4740_BOARD_LEO_H__ */ -diff --git a/include/asm-mips/mach-jz4740/board-lyra.h b/include/asm-mips/mach-jz4740/board-lyra.h -new file mode 100644 -index 0000000..29e0ce0 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/board-lyra.h -@@ -0,0 +1,70 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/board-lyra.h -+ * -+ * JZ4740-based LYRA board ver 2.x definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4740_LYRA_H__ -+#define __ASM_JZ4740_LYRA_H__ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ -+#define GPIO_SD_CD_N 110 /* GPD14 */ -+#define GPIO_SD_WP 112 /* GPD16 */ -+#define GPIO_USB_DETE 102 /* GPD6 */ -+#define GPIO_DC_DETE_N 103 /* GPD7 */ -+#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -+#define GPIO_DISP_OFF_N 118 /* GPD22 */ -+#define GPIO_LED_EN 124 /* GPD28 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC_WP_PIN GPIO_SD_WP -+#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -+ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+} while (0) -+ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (!(__gpio_get_pin(GPIO_SD_CD_N))) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4740_LYRA_H__ */ -diff --git a/include/asm-mips/mach-jz4740/board-pavo.h b/include/asm-mips/mach-jz4740/board-pavo.h -new file mode 100644 -index 0000000..f33831b ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/board-pavo.h -@@ -0,0 +1,70 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/board-pavo.h -+ * -+ * JZ4730-based PAVO board ver 2.x definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4740_PAVO_H__ -+#define __ASM_JZ4740_PAVO_H__ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ -+#define GPIO_SD_CD_N 110 /* GPD14 */ -+#define GPIO_SD_WP 112 /* GPD16 */ -+#define GPIO_USB_DETE 102 /* GPD6 */ -+#define GPIO_DC_DETE_N 103 /* GPD7 */ -+#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -+#define GPIO_DISP_OFF_N 118 /* GPD22 */ -+#define GPIO_LED_EN 124 /* GPD28 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC_WP_PIN GPIO_SD_WP -+#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -+ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+} while (0) -+ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4740_PAVO_H__ */ -diff --git a/include/asm-mips/mach-jz4740/board-virgo.h b/include/asm-mips/mach-jz4740/board-virgo.h -new file mode 100644 -index 0000000..acd7bb7 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/board-virgo.h -@@ -0,0 +1,67 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/board-virgo.h -+ * -+ * JZ4720-based VIRGO board ver 1.x definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4720_VIRGO_H__ -+#define __ASM_JZ4720_VIRGO_H__ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+/*====================================================================== -+ * GPIO VIRGO(JZ4720) -+ */ -+#define GPIO_SD_VCC_EN_N 115 /* GPD19 */ -+#define GPIO_SD_CD_N 116 /* GPD20 */ -+#define GPIO_USB_DETE 114 /* GPD18 */ -+#define GPIO_DC_DETE_N 120 /* GPD24 */ -+#define GPIO_DISP_OFF_N 118 /* GPD22 */ -+#define GPIO_LED_EN 117 /* GPD21 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -+ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+} while (0) -+ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4720_VIRGO_H__ */ -diff --git a/include/asm-mips/mach-jz4740/clock.h b/include/asm-mips/mach-jz4740/clock.h -new file mode 100644 -index 0000000..11ffe88 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/clock.h -@@ -0,0 +1,173 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/clock.h -+ * -+ * JZ4740 clocks definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4740_CLOCK_H__ -+#define __ASM_JZ4740_CLOCK_H__ -+ -+#ifndef JZ_EXTAL -+//#define JZ_EXTAL 3686400 /* 3.6864 MHz */ -+#define JZ_EXTAL 12000000 /* 3.6864 MHz */ -+#endif -+#ifndef JZ_EXTAL2 -+#define JZ_EXTAL2 32768 /* 32.768 KHz */ -+#endif -+ -+/* -+ * JZ4740 clocks structure -+ */ -+typedef struct { -+ unsigned int cclk; /* CPU clock */ -+ unsigned int hclk; /* System bus clock */ -+ unsigned int pclk; /* Peripheral bus clock */ -+ unsigned int mclk; /* Flash/SRAM/SDRAM clock */ -+ unsigned int lcdclk; /* LCDC module clock */ -+ unsigned int pixclk; /* LCD pixel clock */ -+ unsigned int i2sclk; /* AIC module clock */ -+ unsigned int usbclk; /* USB module clock */ -+ unsigned int mscclk; /* MSC module clock */ -+ unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -+ unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ -+} jz_clocks_t; -+ -+extern jz_clocks_t jz_clocks; -+ -+ -+/* PLL output frequency */ -+static __inline__ unsigned int __cpm_get_pllout(void) -+{ -+ unsigned long m, n, no, pllout; -+ unsigned long cppcr = REG_CPM_CPPCR; -+ unsigned long od[4] = {1, 2, 2, 4}; -+ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { -+ m = __cpm_get_pllm() + 2; -+ n = __cpm_get_plln() + 2; -+ no = od[__cpm_get_pllod()]; -+ pllout = ((JZ_EXTAL) / (n * no)) * m; -+ } else -+ pllout = JZ_EXTAL; -+ return pllout; -+} -+ -+/* PLL output frequency for MSC/I2S/LCD/USB */ -+static __inline__ unsigned int __cpm_get_pllout2(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_PCS) -+ return __cpm_get_pllout(); -+ else -+ return __cpm_get_pllout()/2; -+} -+ -+/* CPU core clock */ -+static __inline__ unsigned int __cpm_get_cclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_cdiv()]; -+} -+ -+/* AHB system bus clock */ -+static __inline__ unsigned int __cpm_get_hclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_hdiv()]; -+} -+ -+/* Memory bus clock */ -+static __inline__ unsigned int __cpm_get_mclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_mdiv()]; -+} -+ -+/* APB peripheral bus clock */ -+static __inline__ unsigned int __cpm_get_pclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_pdiv()]; -+} -+ -+/* LCDC module clock */ -+static __inline__ unsigned int __cpm_get_lcdclk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); -+} -+ -+/* LCD pixel clock */ -+static __inline__ unsigned int __cpm_get_pixclk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); -+} -+ -+/* I2S clock */ -+static __inline__ unsigned int __cpm_get_i2sclk(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { -+ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); -+ } -+ else { -+ return JZ_EXTAL; -+ } -+} -+ -+/* USB clock */ -+static __inline__ unsigned int __cpm_get_usbclk(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { -+ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); -+ } -+ else { -+ return JZ_EXTAL; -+ } -+} -+ -+/* MSC clock */ -+static __inline__ unsigned int __cpm_get_mscclk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_mscdiv() + 1); -+} -+ -+/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -+static __inline__ unsigned int __cpm_get_extalclk(void) -+{ -+ return JZ_EXTAL; -+} -+ -+/* RTC clock for CPM,INTC,RTC,TCU,WDT */ -+static __inline__ unsigned int __cpm_get_rtcclk(void) -+{ -+ return JZ_EXTAL2; -+} -+ -+/* -+ * Output 24MHz for SD and 16MHz for MMC. -+ */ -+static inline void __cpm_select_msc_clk(int sd) -+{ -+ unsigned int pllout2 = __cpm_get_pllout2(); -+ unsigned int div = 0; -+ -+ if (sd) { -+ div = pllout2 / 24000000; -+ } -+ else { -+ div = pllout2 / 16000000; -+ } -+ -+ REG_CPM_MSCCDR = div - 1; -+} -+ -+#endif /* __ASM_JZ4740_CLOCK_H__ */ -diff --git a/include/asm-mips/mach-jz4740/dma.h b/include/asm-mips/mach-jz4740/dma.h -new file mode 100644 -index 0000000..b82b984 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/dma.h -@@ -0,0 +1,265 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/dma.h -+ * -+ * JZ4740 DMA definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4740_DMA_H__ -+#define __ASM_JZ4740_DMA_H__ -+ -+#include -+#include /* need byte IO */ -+#include /* And spinlocks */ -+#include -+#include -+ -+/* -+ * Descriptor structure for JZ4740 DMA engine -+ * Note: this structure must always be aligned to a 16-bytes boundary. -+ */ -+ -+typedef struct { -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+ volatile u32 dsadr; /* DSAR value for the current transfer */ -+ volatile u32 dtadr; /* DTAR value for the current transfer */ -+ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -+} jz_dma_desc; -+ -+ -+/* DMA Device ID's follow */ -+enum { -+ DMA_ID_UART0_TX = 0, -+ DMA_ID_UART0_RX, -+ DMA_ID_SSI_TX, -+ DMA_ID_SSI_RX, -+ DMA_ID_AIC_TX, -+ DMA_ID_AIC_RX, -+ DMA_ID_MSC_TX, -+ DMA_ID_MSC_RX, -+ DMA_ID_TCU_OVERFLOW, -+ DMA_ID_AUTO, -+ DMA_ID_RAW_SET, -+ DMA_ID_MAX -+}; -+ -+/* DMA modes, simulated by sw */ -+#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ -+#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ -+#define DMA_AUTOINIT 0x2 -+#define DMA_MODE_MASK 0x3 -+ -+struct jz_dma_chan { -+ int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ -+ unsigned int io; /* DMA channel number */ -+ const char *dev_str; /* string describes the DMA channel */ -+ int irq; /* DMA irq number */ -+ void *irq_dev; /* DMA private device structure */ -+ unsigned int fifo_addr; /* physical fifo address of the requested device */ -+ unsigned int cntl; /* DMA controll */ -+ unsigned int mode; /* DMA configuration */ -+ unsigned int source; /* DMA request source */ -+}; -+ -+extern struct jz_dma_chan jz_dma_table[]; -+ -+ -+#define DMA_8BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_8BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_32_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_32_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+extern int jz_request_dma(int dev_id, -+ const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id); -+extern void jz_free_dma(unsigned int dmanr); -+ -+extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data); -+extern void dump_jz_dma_channel(unsigned int dmanr); -+ -+extern void enable_dma(unsigned int dmanr); -+extern void disable_dma(unsigned int dmanr); -+extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); -+extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); -+extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -+extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern unsigned int get_dma_residue(unsigned int dmanr); -+ -+extern spinlock_t dma_spin_lock; -+ -+static __inline__ unsigned long claim_dma_lock(void) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&dma_spin_lock, flags); -+ return flags; -+} -+ -+static __inline__ void release_dma_lock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&dma_spin_lock, flags); -+} -+ -+/* Clear the 'DMA Pointer Flip Flop'. -+ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -+ */ -+#define clear_dma_ff(channel) -+ -+static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -+{ -+ if (dmanr > MAX_DMA_NUM -+ || jz_dma_table[dmanr].dev_id < 0) -+ return NULL; -+ return &jz_dma_table[dmanr]; -+} -+ -+static __inline__ int dma_halted(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 1; -+ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -+} -+ -+static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ return chan->mode; -+} -+ -+static __inline__ void clear_dma_done(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+} -+ -+static __inline__ void clear_dma_halt(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -+ REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT); -+} -+ -+static __inline__ void clear_dma_flag(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+ REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); -+} -+ -+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -+{ -+} -+ -+static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -+{ -+ unsigned long dccsr; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ dccsr = REG_DMAC_DCCSR(chan->io); -+ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+} -+ -+static __inline__ int get_dma_done_irq(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return -1; -+ return chan->irq; -+} -+ -+#endif /* __ASM_JZ4740_DMA_H__ */ -diff --git a/include/asm-mips/mach-jz4740/jz4740.h b/include/asm-mips/mach-jz4740/jz4740.h -new file mode 100644 -index 0000000..d38d5f1 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/jz4740.h -@@ -0,0 +1,60 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/jz4740.h -+ * -+ * JZ4740 common definition. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4740_H__ -+#define __ASM_JZ4740_H__ -+ -+#include -+#include -+#include -+#include -+ -+/*------------------------------------------------------------------ -+ * Platform definitions -+ */ -+#ifdef CONFIG_JZ4740_PAVO -+#include -+#endif -+ -+#ifdef CONFIG_JZ4740_LEO -+#include -+#endif -+ -+#ifdef CONFIG_JZ4740_LYRA -+#include -+#endif -+ -+#ifdef CONFIG_JZ4725_DIPPER -+#include -+#endif -+ -+#ifdef CONFIG_JZ4720_VIRGO -+#include -+#endif -+ -+#ifdef CONFIG_JZ4740_QI_LB60 -+#include -+#endif -+ -+/* Add other platform definition here ... */ -+ -+ -+/*------------------------------------------------------------------ -+ * Follows are related to platform definitions -+ */ -+ -+#include -+#include -+ -+#endif /* __ASM_JZ4740_H__ */ -diff --git a/include/asm-mips/mach-jz4740/misc.h b/include/asm-mips/mach-jz4740/misc.h -new file mode 100644 -index 0000000..8f14a5a ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/misc.h -@@ -0,0 +1,43 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/misc.h -+ * -+ * Ingenic's JZ4740 common include. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4740_MISC_H__ -+#define __ASM_JZ4740_MISC_H__ -+ -+/*========================================================== -+ * I2C -+ *===========================================================*/ -+ -+#define I2C_EEPROM_DEV 0xA /* b'1010 */ -+#define I2C_RTC_DEV 0xD /* b'1101 */ -+#define DIMM0_SPD_ADDR 0 -+#define DIMM1_SPD_ADDR 1 -+#define DIMM2_SPD_ADDR 2 -+#define DIMM3_SPD_ADDR 3 -+#define JZ_HCI_ADDR 7 -+ -+#define DIMM_SPD_LEN 128 -+#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ -+#define I2C_RTC_LEN 16 -+#define HCI_MAC_OFFSET 64 -+ -+extern void i2c_open(void); -+extern void i2c_close(void); -+extern void i2c_setclk(unsigned int i2cclk); -+extern int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+extern int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+ -+#endif /* __ASM_JZ4740_MISC_H__ */ -diff --git a/include/asm-mips/mach-jz4740/ops.h b/include/asm-mips/mach-jz4740/ops.h -new file mode 100644 -index 0000000..6ff050a ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/ops.h -@@ -0,0 +1,2224 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/ops.h -+ * -+ * Ingenic's JZ4740 common include. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef __JZ4740_OPS_H__ -+#define __JZ4740_OPS_H__ -+ -+/* -+ * Definition of Module Operations -+ */ -+ -+/*************************************************************************** -+ * GPIO -+ ***************************************************************************/ -+ -+//------------------------------------------------------ -+// GPIO Pins Description -+// -+// PORT 0: -+// -+// PIN/BIT N FUNC0 FUNC1 -+// 0 D0 - -+// 1 D1 - -+// 2 D2 - -+// 3 D3 - -+// 4 D4 - -+// 5 D5 - -+// 6 D6 - -+// 7 D7 - -+// 8 D8 - -+// 9 D9 - -+// 10 D10 - -+// 11 D11 - -+// 12 D12 - -+// 13 D13 - -+// 14 D14 - -+// 15 D15 - -+// 16 D16 - -+// 17 D17 - -+// 18 D18 - -+// 19 D19 - -+// 20 D20 - -+// 21 D21 - -+// 22 D22 - -+// 23 D23 - -+// 24 D24 - -+// 25 D25 - -+// 26 D26 - -+// 27 D27 - -+// 28 D28 - -+// 29 D29 - -+// 30 D30 - -+// 31 D31 - -+// -+//------------------------------------------------------ -+// PORT 1: -+// -+// PIN/BIT N FUNC0 FUNC1 -+// 0 A0 - -+// 1 A1 - -+// 2 A2 - -+// 3 A3 - -+// 4 A4 - -+// 5 A5 - -+// 6 A6 - -+// 7 A7 - -+// 8 A8 - -+// 9 A9 - -+// 10 A10 - -+// 11 A11 - -+// 12 A12 - -+// 13 A13 - -+// 14 A14 - -+// 15 A15/CL - -+// 16 A16/AL - -+// 17 LCD_CLS A21 -+// 18 LCD_SPL A22 -+// 19 DCS# - -+// 20 RAS# - -+// 21 CAS# - -+// 22 RDWE#/BUFD# - -+// 23 CKE - -+// 24 CKO - -+// 25 CS1# - -+// 26 CS2# - -+// 27 CS3# - -+// 28 CS4# - -+// 29 RD# - -+// 30 WR# - -+// 31 WE0# - -+// -+// Note: PIN15&16 are CL&AL when connecting to NAND flash. -+//------------------------------------------------------ -+// PORT 2: -+// -+// PIN/BIT N FUNC0 FUNC1 -+// 0 LCD_D0 - -+// 1 LCD_D1 - -+// 2 LCD_D2 - -+// 3 LCD_D3 - -+// 4 LCD_D4 - -+// 5 LCD_D5 - -+// 6 LCD_D6 - -+// 7 LCD_D7 - -+// 8 LCD_D8 - -+// 9 LCD_D9 - -+// 10 LCD_D10 - -+// 11 LCD_D11 - -+// 12 LCD_D12 - -+// 13 LCD_D13 - -+// 14 LCD_D14 - -+// 15 LCD_D15 - -+// 16 LCD_D16 - -+// 17 LCD_D17 - -+// 18 LCD_PCLK - -+// 19 LCD_HSYNC - -+// 20 LCD_VSYNC - -+// 21 LCD_DE - -+// 22 LCD_PS A19 -+// 23 LCD_REV A20 -+// 24 WE1# - -+// 25 WE2# - -+// 26 WE3# - -+// 27 WAIT# - -+// 28 FRE# - -+// 29 FWE# - -+// 30(NOTE:FRB#) - - -+// 31 - - -+// -+// NOTE(1): PIN30 is used for FRB# when connecting to NAND flash. -+//------------------------------------------------------ -+// PORT 3: -+// -+// PIN/BIT N FUNC0 FUNC1 -+// 0 CIM_D0 - -+// 1 CIM_D1 - -+// 2 CIM_D2 - -+// 3 CIM_D3 - -+// 4 CIM_D4 - -+// 5 CIM_D5 - -+// 6 CIM_D6 - -+// 7 CIM_D7 - -+// 8 MSC_CMD - -+// 9 MSC_CLK - -+// 10 MSC_D0 - -+// 11 MSC_D1 - -+// 12 MSC_D2 - -+// 13 MSC_D3 - -+// 14 CIM_MCLK - -+// 15 CIM_PCLK - -+// 16 CIM_VSYNC - -+// 17 CIM_HSYNC - -+// 18 SSI_CLK SCLK_RSTN -+// 19 SSI_CE0# BIT_CLK(AIC) -+// 20 SSI_DT SDATA_OUT(AIC) -+// 21 SSI_DR SDATA_IN(AIC) -+// 22 SSI_CE1#&GPC SYNC(AIC) -+// 23 PWM0 I2C_SDA -+// 24 PWM1 I2C_SCK -+// 25 PWM2 UART0_TxD -+// 26 PWM3 UART0_RxD -+// 27 PWM4 A17 -+// 28 PWM5 A18 -+// 29 - - -+// 30 PWM6 UART0_CTS/UART1_RxD -+// 31 PWM7 UART0_RTS/UART1_TxD -+// -+////////////////////////////////////////////////////////// -+ -+/* -+ * p is the port number (0,1,2,3) -+ * o is the pin offset (0-31) inside the port -+ * n is the absolute number of a pin (0-127), regardless of the port -+ */ -+ -+//------------------------------------------- -+// Function Pins Mode -+ -+#define __gpio_as_func0(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXSELC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_func1(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+} while (0) -+ -+/* -+ * D0 ~ D31, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, -+ * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# -+ */ -+#define __gpio_as_sdram_32bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -+ REG_GPIO_PXSELC(0) = 0xffffffff; \ -+ REG_GPIO_PXPES(0) = 0xffffffff; \ -+ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ -+ REG_GPIO_PXSELC(1) = 0x81f9ffff; \ -+ REG_GPIO_PXPES(1) = 0x81f9ffff; \ -+ REG_GPIO_PXFUNS(2) = 0x07000000; \ -+ REG_GPIO_PXSELC(2) = 0x07000000; \ -+ REG_GPIO_PXPES(2) = 0x07000000; \ -+} while (0) -+ -+/* -+ * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, -+ * RDWE#, CKO#, WE0#, WE1# -+ */ -+#define __gpio_as_sdram_16bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0x5442bfaa; \ -+ REG_GPIO_PXSELC(0) = 0x5442bfaa; \ -+ REG_GPIO_PXPES(0) = 0x5442bfaa; \ -+ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ -+ REG_GPIO_PXSELC(1) = 0x81f9ffff; \ -+ REG_GPIO_PXPES(1) = 0x81f9ffff; \ -+ REG_GPIO_PXFUNS(2) = 0x01000000; \ -+ REG_GPIO_PXSELC(2) = 0x01000000; \ -+ REG_GPIO_PXPES(2) = 0x01000000; \ -+} while (0) -+ -+/* -+ * CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# -+ */ -+#define __gpio_as_nand() \ -+do { \ -+ REG_GPIO_PXFUNS(1) = 0x02018000; \ -+ REG_GPIO_PXSELC(1) = 0x02018000; \ -+ REG_GPIO_PXPES(1) = 0x02018000; \ -+ REG_GPIO_PXFUNS(2) = 0x30000000; \ -+ REG_GPIO_PXSELC(2) = 0x30000000; \ -+ REG_GPIO_PXPES(2) = 0x30000000; \ -+ REG_GPIO_PXFUNC(2) = 0x40000000; \ -+ REG_GPIO_PXSELC(2) = 0x40000000; \ -+ REG_GPIO_PXDIRC(2) = 0x40000000; \ -+ REG_GPIO_PXPES(2) = 0x40000000; \ -+ REG_GPIO_PXFUNS(1) = 0x00400000; \ -+ REG_GPIO_PXSELC(1) = 0x00400000; \ -+} while (0) -+ -+/* -+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 -+ */ -+#define __gpio_as_nor_8bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0x000000ff; \ -+ REG_GPIO_PXSELC(0) = 0x000000ff; \ -+ REG_GPIO_PXPES(0) = 0x000000ff; \ -+ REG_GPIO_PXFUNS(1) = 0x7041ffff; \ -+ REG_GPIO_PXSELC(1) = 0x7041ffff; \ -+ REG_GPIO_PXPES(1) = 0x7041ffff; \ -+ REG_GPIO_PXFUNS(1) = 0x00060000; \ -+ REG_GPIO_PXSELS(1) = 0x00060000; \ -+ REG_GPIO_PXPES(1) = 0x00060000; \ -+ REG_GPIO_PXFUNS(2) = 0x08000000; \ -+ REG_GPIO_PXSELC(2) = 0x08000000; \ -+ REG_GPIO_PXPES(2) = 0x08000000; \ -+ REG_GPIO_PXFUNS(2) = 0x00c00000; \ -+ REG_GPIO_PXSELS(2) = 0x00c00000; \ -+ REG_GPIO_PXPES(2) = 0x00c00000; \ -+ REG_GPIO_PXFUNS(3) = 0x18000000; \ -+ REG_GPIO_PXSELS(3) = 0x18000000; \ -+ REG_GPIO_PXPES(3) = 0x18000000; \ -+} while (0) -+ -+/* -+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 -+ */ -+#define __gpio_as_nor_16bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -+ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -+ REG_GPIO_PXPES(0) = 0x0000ffff; \ -+ REG_GPIO_PXFUNS(1) = 0x7041ffff; \ -+ REG_GPIO_PXSELC(1) = 0x7041ffff; \ -+ REG_GPIO_PXPES(1) = 0x7041ffff; \ -+ REG_GPIO_PXFUNS(1) = 0x00060000; \ -+ REG_GPIO_PXSELS(1) = 0x00060000; \ -+ REG_GPIO_PXPES(1) = 0x00060000; \ -+ REG_GPIO_PXFUNS(2) = 0x08000000; \ -+ REG_GPIO_PXSELC(2) = 0x08000000; \ -+ REG_GPIO_PXPES(2) = 0x08000000; \ -+ REG_GPIO_PXFUNS(2) = 0x00c00000; \ -+ REG_GPIO_PXSELS(2) = 0x00c00000; \ -+ REG_GPIO_PXPES(2) = 0x00c00000; \ -+ REG_GPIO_PXFUNS(3) = 0x18000000; \ -+ REG_GPIO_PXSELS(3) = 0x18000000; \ -+ REG_GPIO_PXPES(3) = 0x18000000; \ -+} while (0) -+ -+/* -+ * UART0_TxD, UART_RxD0 -+ */ -+#define __gpio_as_uart0() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x06000000; \ -+ REG_GPIO_PXSELS(3) = 0x06000000; \ -+ REG_GPIO_PXPES(3) = 0x06000000; \ -+} while (0) -+ -+/* -+ * UART0_CTS, UART0_RTS -+ */ -+#define __gpio_as_ctsrts() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0xc0000000; \ -+ REG_GPIO_PXSELS(3) = 0xc0000000; \ -+ REG_GPIO_PXTRGC(3) = 0xc0000000; \ -+ REG_GPIO_PXPES(3) = 0xc0000000; \ -+} while (0) -+ -+/* -+ * UART1_TxD, UART1_RxD1 -+ */ -+#define __gpio_as_uart1() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0xc0000000; \ -+ REG_GPIO_PXSELC(3) = 0xc0000000; \ -+ REG_GPIO_PXTRGS(3) = 0xc0000000; \ -+ REG_GPIO_PXPES(3) = 0xc0000000; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_16bit() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x003cffff; \ -+ REG_GPIO_PXSELC(2) = 0x003cffff; \ -+ REG_GPIO_PXPES(2) = 0x003cffff; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_18bit() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x003fffff; \ -+ REG_GPIO_PXSELC(2) = 0x003fffff; \ -+ REG_GPIO_PXPES(2) = 0x003fffff; \ -+} while (0) -+ -+/* -+ * LCD_PS, LCD_REV, LCD_CLS, LCD_SPL -+ */ -+#define __gpio_as_lcd_special() \ -+do { \ -+ REG_GPIO_PXFUNS(1) = 0x00060000; \ -+ REG_GPIO_PXSELC(1) = 0x00060000; \ -+ REG_GPIO_PXPES(1) = 0x00060000; \ -+ REG_GPIO_PXFUNS(2) = 0x00c00000; \ -+ REG_GPIO_PXSELC(2) = 0x00c00000; \ -+ REG_GPIO_PXPES(2) = 0x00c00000; \ -+} while (0) -+ -+/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ -+#define __gpio_as_slcd_8bit() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x001800ff; \ -+ REG_GPIO_PXSELC(2) = 0x001800ff; \ -+} while (0) -+ -+/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ -+#define __gpio_as_slcd_9bit() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x001801ff; \ -+ REG_GPIO_PXSELC(2) = 0x001801ff; \ -+} while (0) -+ -+/* LCD_D0~LCD_D15, SLCD_RS, SLCD_CS */ -+#define __gpio_as_slcd_16bit() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x0018ffff; \ -+ REG_GPIO_PXSELC(2) = 0x0018ffff; \ -+} while (0) -+ -+/* LCD_D0~LCD_D17, SLCD_RS, SLCD_CS */ -+#define __gpio_as_slcd_18bit() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x001bffff; \ -+ REG_GPIO_PXSELC(2) = 0x001bffff; \ -+} while (0) -+ -+/* -+ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC -+ */ -+#define __gpio_as_cim() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x0003c0ff; \ -+ REG_GPIO_PXSELC(3) = 0x0003c0ff; \ -+ REG_GPIO_PXPES(3) = 0x0003c0ff; \ -+} while (0) -+ -+/* -+ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET -+ */ -+#define __gpio_as_aic() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x007c0000; \ -+ REG_GPIO_PXSELS(3) = 0x007c0000; \ -+ REG_GPIO_PXPES(3) = 0x007c0000; \ -+} while (0) -+ -+/* -+ * MSC_CMD, MSC_CLK, MSC_D0 ~ MSC_D3 -+ */ -+#define __gpio_as_msc() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x00003f00; \ -+ REG_GPIO_PXSELC(3) = 0x00003f00; \ -+ REG_GPIO_PXPES(3) = 0x00003f00; \ -+} while (0) -+ -+/* -+ * SSI_CS0, SSI_CLK, SSI_DT, SSI_DR -+ */ -+#define __gpio_as_ssi() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003c0000; \ -+ REG_GPIO_PXSELC(3) = 0x003c0000; \ -+ REG_GPIO_PXPES(3) = 0x003c0000; \ -+} while (0) -+ -+/* -+ * I2C_SCK, I2C_SDA -+ */ -+#define __gpio_as_i2c() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x01800000; \ -+ REG_GPIO_PXSELS(3) = 0x01800000; \ -+ REG_GPIO_PXPES(3) = 0x01800000; \ -+} while (0) -+ -+/* -+ * PWM0 -+ */ -+#define __gpio_as_pwm0() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x00800000; \ -+ REG_GPIO_PXSELC(3) = 0x00800000; \ -+ REG_GPIO_PXPES(3) = 0x00800000; \ -+} while (0) -+ -+/* -+ * PWM1 -+ */ -+#define __gpio_as_pwm1() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x01000000; \ -+ REG_GPIO_PXSELC(3) = 0x01000000; \ -+ REG_GPIO_PXPES(3) = 0x01000000; \ -+} while (0) -+ -+/* -+ * PWM2 -+ */ -+#define __gpio_as_pwm2() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x02000000; \ -+ REG_GPIO_PXSELC(3) = 0x02000000; \ -+ REG_GPIO_PXPES(3) = 0x02000000; \ -+} while (0) -+ -+/* -+ * PWM3 -+ */ -+#define __gpio_as_pwm3() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x04000000; \ -+ REG_GPIO_PXSELC(3) = 0x04000000; \ -+ REG_GPIO_PXPES(3) = 0x04000000; \ -+} while (0) -+ -+/* -+ * PWM4 -+ */ -+#define __gpio_as_pwm4() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x08000000; \ -+ REG_GPIO_PXSELC(3) = 0x08000000; \ -+ REG_GPIO_PXPES(3) = 0x08000000; \ -+} while (0) -+ -+/* -+ * PWM5 -+ */ -+#define __gpio_as_pwm5() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x10000000; \ -+ REG_GPIO_PXSELC(3) = 0x10000000; \ -+ REG_GPIO_PXPES(3) = 0x10000000; \ -+} while (0) -+ -+/* -+ * PWM6 -+ */ -+#define __gpio_as_pwm6() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x40000000; \ -+ REG_GPIO_PXSELC(3) = 0x40000000; \ -+ REG_GPIO_PXPES(3) = 0x40000000; \ -+} while (0) -+ -+/* -+ * PWM7 -+ */ -+#define __gpio_as_pwm7() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x80000000; \ -+ REG_GPIO_PXSELC(3) = 0x80000000; \ -+ REG_GPIO_PXPES(3) = 0x80000000; \ -+} while (0) -+ -+/* -+ * n = 0 ~ 7 -+ */ -+#define __gpio_as_pwm(n) __gpio_as_pwm##n() -+ -+//------------------------------------------- -+// GPIO or Interrupt Mode -+ -+#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) -+ -+#define __gpio_port_as_output(p, o) \ -+do { \ -+ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -+ REG_GPIO_PXSELC(p) = (1 << (o)); \ -+ REG_GPIO_PXDIRS(p) = (1 << (o)); \ -+} while (0) -+ -+#define __gpio_port_as_input(p, o) \ -+do { \ -+ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -+ REG_GPIO_PXSELC(p) = (1 << (o)); \ -+ REG_GPIO_PXDIRC(p) = (1 << (o)); \ -+} while (0) -+ -+#define __gpio_as_output(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_output(p, o); \ -+} while (0) -+ -+#define __gpio_as_input(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_input(p, o); \ -+} while (0) -+ -+#define __gpio_set_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXDATS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_clear_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXDATC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_get_pin(n) \ -+({ \ -+ unsigned int p, o, v; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ if (__gpio_get_port(p) & (1 << o)) \ -+ v = 1; \ -+ else \ -+ v = 0; \ -+ v; \ -+}) -+ -+#define __gpio_as_irq_high_level(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRS(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_low_level(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRC(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_rise_edge(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRS(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_fall_edge(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRC(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_mask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_unmask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_ack_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_get_irq() \ -+({ \ -+ unsigned int p, i, tmp, v = 0; \ -+ for (p = 3; p >= 0; p--) { \ -+ tmp = REG_GPIO_PXFLG(p); \ -+ for (i = 0; i < 32; i++) \ -+ if (tmp & (1 << i)) \ -+ v = (32*p + i); \ -+ } \ -+ v; \ -+}) -+ -+#define __gpio_group_irq(n) \ -+({ \ -+ register int tmp, i; \ -+ tmp = REG_GPIO_PXFLG((n)); \ -+ for (i=31;i>=0;i--) \ -+ if (tmp & (1 << i)) \ -+ break; \ -+ i; \ -+}) -+ -+#define __gpio_enable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXPEC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_disable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXPES(p) = (1 << o); \ -+} while (0) -+ -+ -+/*************************************************************************** -+ * CPM -+ ***************************************************************************/ -+#define __cpm_get_pllm() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) -+#define __cpm_get_plln() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) -+#define __cpm_get_pllod() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) -+ -+#define __cpm_get_cdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) -+#define __cpm_get_hdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) -+#define __cpm_get_pdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) -+#define __cpm_get_mdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) -+#define __cpm_get_ldiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) -+#define __cpm_get_udiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) -+#define __cpm_get_i2sdiv() \ -+ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) -+#define __cpm_get_pixdiv() \ -+ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) -+#define __cpm_get_mscdiv() \ -+ ((REG_CPM_MSCCDR & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) -+#define __cpm_get_uhcdiv() \ -+ ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) -+#define __cpm_get_ssidiv() \ -+ ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) -+ -+#define __cpm_set_cdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) -+#define __cpm_set_hdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) -+#define __cpm_set_pdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) -+#define __cpm_set_mdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) -+#define __cpm_set_ldiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) -+#define __cpm_set_udiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) -+#define __cpm_set_i2sdiv(v) \ -+ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) -+#define __cpm_set_pixdiv(v) \ -+ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) -+#define __cpm_set_mscdiv(v) \ -+ (REG_CPM_MSCCDR = (REG_CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) -+#define __cpm_set_uhcdiv(v) \ -+ (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) -+#define __cpm_ssiclk_select_exclk() \ -+ (REG_CPM_SSICDR &= ~CPM_SSICDR_SCS) -+#define __cpm_ssiclk_select_pllout() \ -+ (REG_CPM_SSICDR |= CPM_SSICDR_SCS) -+#define __cpm_set_ssidiv(v) \ -+ (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) -+ -+#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) -+#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) -+#define __cpm_enable_cko() (REG_CPM_CPCCR |= CPM_CPCCR_CLKOEN) -+#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) -+#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) -+#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) -+#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) -+#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) -+ -+#define __cpm_pll_is_on() (REG_CPM_CPPCR & CPM_CPPCR_PLLS) -+#define __cpm_pll_bypass() (REG_CPM_CPPCR |= CPM_CPPCR_PLLBP) -+#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) -+ -+#define __cpm_get_cclk_doze_duty() \ -+ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) -+#define __cpm_set_cclk_doze_duty(v) \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) -+ -+#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) -+#define __cpm_idle_mode() \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) -+#define __cpm_sleep_mode() \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -+ -+#define __cpm_stop_all() (REG_CPM_CLKGR = 0x7fff) -+#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -+#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -+#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) -+#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -+#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -+#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -+#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) -+#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -+#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC) -+#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) -+#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -+#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI) -+#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -+#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -+#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -+#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) -+ -+#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -+#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) -+#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) -+#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -+#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) -+#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) -+#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) -+#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -+#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) -+#define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC) -+#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -+#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) -+#define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI) -+#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) -+#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) -+#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -+#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) -+ -+#define __cpm_get_o1st() \ -+ ((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT) -+#define __cpm_set_o1st(v) \ -+ (REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT))) -+#define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_SUSPEND) -+#define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE) -+ -+ -+/*************************************************************************** -+ * TCU -+ ***************************************************************************/ -+// where 'n' is the TCU channel -+#define __tcu_select_extalclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) -+#define __tcu_select_rtcclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) -+#define __tcu_select_pclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) -+ -+#define __tcu_select_clk_div1(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) -+#define __tcu_select_clk_div4(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) -+#define __tcu_select_clk_div16(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) -+#define __tcu_select_clk_div64(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) -+#define __tcu_select_clk_div256(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) -+#define __tcu_select_clk_div1024(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) -+ -+#define __tcu_enable_pwm_output(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN ) -+#define __tcu_disable_pwm_output(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN ) -+ -+#define __tcu_init_pwm_output_high(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH ) -+#define __tcu_init_pwm_output_low(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH ) -+ -+#define __tcu_set_pwm_output_shutdown_graceful(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD ) -+#define __tcu_set_pwm_output_shutdown_abrupt(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD ) -+ -+#define __tcu_start_counter(n) ( REG_TCU_TESR |= (1 << (n)) ) -+#define __tcu_stop_counter(n) ( REG_TCU_TECR |= (1 << (n)) ) -+ -+#define __tcu_half_match_flag(n) ( REG_TCU_TFR & (1 << ((n) + 16)) ) -+#define __tcu_full_match_flag(n) ( REG_TCU_TFR & (1 << (n)) ) -+#define __tcu_set_half_match_flag(n) ( REG_TCU_TFSR = (1 << ((n) + 16)) ) -+#define __tcu_set_full_match_flag(n) ( REG_TCU_TFSR = (1 << (n)) ) -+#define __tcu_clear_half_match_flag(n) ( REG_TCU_TFCR = (1 << ((n) + 16)) ) -+#define __tcu_clear_full_match_flag(n) ( REG_TCU_TFCR = (1 << (n)) ) -+#define __tcu_mask_half_match_irq(n) ( REG_TCU_TMSR = (1 << ((n) + 16)) ) -+#define __tcu_mask_full_match_irq(n) ( REG_TCU_TMSR = (1 << (n)) ) -+#define __tcu_unmask_half_match_irq(n) ( REG_TCU_TMCR = (1 << ((n) + 16)) ) -+#define __tcu_unmask_full_match_irq(n) ( REG_TCU_TMCR = (1 << (n)) ) -+ -+#define __tcu_wdt_clock_stopped() ( REG_TCU_TSR & TCU_TSSR_WDTSC ) -+#define __tcu_timer_clock_stopped(n) ( REG_TCU_TSR & (1 << (n)) ) -+ -+#define __tcu_start_wdt_clock() ( REG_TCU_TSCR = TCU_TSSR_WDTSC ) -+#define __tcu_start_timer_clock(n) ( REG_TCU_TSCR = (1 << (n)) ) -+ -+#define __tcu_stop_wdt_clock() ( REG_TCU_TSSR = TCU_TSSR_WDTSC ) -+#define __tcu_stop_timer_clock(n) ( REG_TCU_TSSR = (1 << (n)) ) -+ -+#define __tcu_get_count(n) ( REG_TCU_TCNT((n)) ) -+#define __tcu_set_count(n,v) ( REG_TCU_TCNT((n)) = (v) ) -+#define __tcu_set_full_data(n,v) ( REG_TCU_TDFR((n)) = (v) ) -+#define __tcu_set_half_data(n,v) ( REG_TCU_TDHR((n)) = (v) ) -+ -+ -+/*************************************************************************** -+ * WDT -+ ***************************************************************************/ -+#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) -+#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) -+#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) -+#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) -+ -+#define __wdt_select_extalclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) -+#define __wdt_select_rtcclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) -+#define __wdt_select_pclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) -+ -+#define __wdt_select_clk_div1() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) -+#define __wdt_select_clk_div4() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) -+#define __wdt_select_clk_div16() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) -+#define __wdt_select_clk_div64() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) -+#define __wdt_select_clk_div256() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) -+#define __wdt_select_clk_div1024() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) -+ -+ -+/*************************************************************************** -+ * UART -+ ***************************************************************************/ -+ -+#define __uart_enable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -+#define __uart_disable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -+ -+#define __uart_enable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -+#define __uart_disable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -+ -+#define __uart_enable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -+#define __uart_disable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -+ -+#define __uart_enable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -+#define __uart_disable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -+ -+#define __uart_set_8n1(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -+ -+#define __uart_set_baud(n, devclk, baud) \ -+ do { \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -+ } while (0) -+ -+#define __uart_parity_error(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -+ -+#define __uart_clear_errors(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -+ -+#define __uart_transmit_fifo_empty(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -+ -+#define __uart_transmit_end(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -+ -+#define __uart_transmit_char(n, ch) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -+ -+#define __uart_receive_fifo_full(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_ready(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_char(n) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -+ -+#define __uart_disable_irda() \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -+#define __uart_enable_irda() \ -+ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -+ -+ -+/*************************************************************************** -+ * DMAC -+ ***************************************************************************/ -+ -+/* n is the DMA channel (0 - 5) */ -+ -+#define __dmac_enable_module() \ -+ ( REG_DMAC_DMACR |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_RR ) -+#define __dmac_disable_module() \ -+ ( REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE ) -+ -+/* p=0,1,2,3 */ -+#define __dmac_set_priority(p) \ -+do { \ -+ REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \ -+ REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \ -+} while (0) -+ -+#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HLT ) -+#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AR ) -+ -+#define __dmac_enable_descriptor(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) -+#define __dmac_disable_descriptor(n) \ -+ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) -+ -+#define __dmac_enable_channel(n) \ -+ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN ) -+#define __dmac_disable_channel(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN ) -+#define __dmac_channel_enabled(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) -+ -+#define __dmac_channel_enable_irq(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) -+#define __dmac_channel_disable_irq(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) -+ -+#define __dmac_channel_transmit_halt_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) -+#define __dmac_channel_transmit_end_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) -+#define __dmac_channel_address_error_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) -+#define __dmac_channel_count_terminated_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) -+#define __dmac_channel_descriptor_invalid_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) -+ -+#define __dmac_channel_clear_transmit_halt(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT ) -+#define __dmac_channel_clear_transmit_end(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) -+#define __dmac_channel_clear_address_error(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR ) -+#define __dmac_channel_clear_count_terminated(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) -+#define __dmac_channel_clear_descriptor_invalid(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) -+ -+#define __dmac_channel_set_single_mode(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TM ) -+#define __dmac_channel_set_block_mode(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TM ) -+ -+#define __dmac_channel_set_transfer_unit_32bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_8bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16byte(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_32byte(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_dest_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_src_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ -+} while (0) -+ -+/* v=0-15 */ -+#define __dmac_channel_set_rdil(n,v) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ -+ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ -+} while (0) -+ -+#define __dmac_channel_dest_addr_fixed(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) -+#define __dmac_channel_dest_addr_increment(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) -+ -+#define __dmac_channel_src_addr_fixed(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) -+#define __dmac_channel_src_addr_increment(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) -+ -+#define __dmac_channel_set_doorbell(n) \ -+ ( REG_DMAC_DMADBSR = (1 << (n)) ) -+ -+#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR & (1 << (n)) ) -+#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR &= ~(1 << (n)) ) -+ -+static __inline__ int __dmac_get_irq(void) -+{ -+ int i; -+ for (i = 0; i < MAX_DMA_NUM; i++) -+ if (__dmac_channel_irq_detected(i)) -+ return i; -+ return -1; -+} -+ -+ -+/*************************************************************************** -+ * AIC (AC'97 & I2S Controller) -+ ***************************************************************************/ -+ -+#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) -+#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) -+ -+#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) -+#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) -+ -+#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) -+#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) -+ -+#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) -+#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) -+#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) -+ -+#define __aic_reset() \ -+do { \ -+ REG_AIC_FR |= AIC_FR_RST; \ -+} while(0) -+ -+ -+#define __aic_set_transmit_trigger(n) \ -+do { \ -+ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ -+ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ -+} while(0) -+ -+#define __aic_set_receive_trigger(n) \ -+do { \ -+ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ -+ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ -+} while(0) -+ -+#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) -+#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) -+#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) -+#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) -+#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) -+#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) -+ -+#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) -+#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) -+ -+#define __aic_enable_transmit_intr() \ -+ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) -+#define __aic_disable_transmit_intr() \ -+ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) -+#define __aic_enable_receive_intr() \ -+ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) -+#define __aic_disable_receive_intr() \ -+ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) -+ -+#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) -+#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) -+#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) -+#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) -+ -+#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) -+#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) -+#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) -+#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) -+#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) -+#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) -+ -+#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 -+#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 -+#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 -+#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 -+#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 -+#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 -+ -+#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 -+#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 -+#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 -+#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 -+#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 -+#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 -+ -+#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) -+#define __ac97_set_xs_mono() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ -+} while(0) -+#define __ac97_set_xs_stereo() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ -+} while(0) -+ -+/* In fact, only stereo is support now. */ -+#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) -+#define __ac97_set_rs_mono() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ -+} while(0) -+#define __ac97_set_rs_stereo() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ -+} while(0) -+ -+#define __ac97_warm_reset_codec() \ -+ do { \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ -+ udelay(2); \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ -+ } while (0) -+ -+#define __ac97_cold_reset_codec() \ -+ do { \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ -+ udelay(2); \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ -+ } while (0) -+ -+/* n=8,16,18,20 */ -+#define __ac97_set_iass(n) \ -+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) -+#define __ac97_set_oass(n) \ -+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) -+ -+#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) -+#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) -+ -+/* n=8,16,18,20,24 */ -+/*#define __i2s_set_sample_size(n) \ -+ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ -+ -+#define __i2s_set_oss_sample_size(n) \ -+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) -+#define __i2s_set_iss_sample_size(n) \ -+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) -+ -+#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) -+#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) -+ -+#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) -+#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) -+#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) -+#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) -+ -+#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) -+ -+#define __aic_get_transmit_resident() \ -+ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) -+#define __aic_get_receive_count() \ -+ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -+ -+#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -+#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -+#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -+#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -+#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -+#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) -+#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) -+ -+#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -+ -+#define CODEC_READ_CMD (1 << 19) -+#define CODEC_WRITE_CMD (0 << 19) -+#define CODEC_REG_INDEX_BIT 12 -+#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -+#define CODEC_REG_DATA_BIT 4 -+#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -+ -+#define __ac97_out_rcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_wcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_data(value) \ -+do { \ -+ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -+} while (0) -+ -+#define __ac97_in_data() \ -+ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -+ -+#define __ac97_in_status_addr() \ -+ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -+ -+#define __i2s_set_sample_rate(i2sclk, sync) \ -+ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -+ -+#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -+#define __aic_read_rfifo() ( REG_AIC_DR ) -+ -+#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) -+#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) -+ -+// -+// Define next ops for AC97 compatible -+// -+ -+#define AC97_ACSR AIC_ACSR -+ -+#define __ac97_enable() __aic_enable(); __aic_select_ac97() -+#define __ac97_disable() __aic_disable() -+#define __ac97_reset() __aic_reset() -+ -+#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __ac97_enable_record() __aic_enable_record() -+#define __ac97_disable_record() __aic_disable_record() -+#define __ac97_enable_replay() __aic_enable_replay() -+#define __ac97_disable_replay() __aic_disable_replay() -+#define __ac97_enable_loopback() __aic_enable_loopback() -+#define __ac97_disable_loopback() __aic_disable_loopback() -+ -+#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -+#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __ac97_transmit_request() __aic_transmit_request() -+#define __ac97_receive_request() __aic_receive_request() -+#define __ac97_transmit_underrun() __aic_transmit_underrun() -+#define __ac97_receive_overrun() __aic_receive_overrun() -+ -+#define __ac97_clear_errors() __aic_clear_errors() -+ -+#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -+#define __ac97_get_receive_count() __aic_get_receive_count() -+ -+#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -+#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -+#define __ac97_read_rfifo() __aic_read_rfifo() -+ -+// -+// Define next ops for I2S compatible -+// -+ -+#define I2S_ACSR AIC_I2SSR -+ -+#define __i2s_enable() __aic_enable(); __aic_select_i2s() -+#define __i2s_disable() __aic_disable() -+#define __i2s_reset() __aic_reset() -+ -+#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __i2s_enable_record() __aic_enable_record() -+#define __i2s_disable_record() __aic_disable_record() -+#define __i2s_enable_replay() __aic_enable_replay() -+#define __i2s_disable_replay() __aic_disable_replay() -+#define __i2s_enable_loopback() __aic_enable_loopback() -+#define __i2s_disable_loopback() __aic_disable_loopback() -+ -+#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -+#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __i2s_transmit_request() __aic_transmit_request() -+#define __i2s_receive_request() __aic_receive_request() -+#define __i2s_transmit_underrun() __aic_transmit_underrun() -+#define __i2s_receive_overrun() __aic_receive_overrun() -+ -+#define __i2s_clear_errors() __aic_clear_errors() -+ -+#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -+#define __i2s_get_receive_count() __aic_get_receive_count() -+ -+#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -+#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -+#define __i2s_read_rfifo() __aic_read_rfifo() -+ -+#define __i2s_reset_codec() \ -+ do { \ -+ } while (0) -+ -+ -+/*************************************************************************** -+ * ICDC -+ ***************************************************************************/ -+#define __i2s_internal_codec() __aic_internal_codec() -+#define __i2s_external_codec() __aic_external_codec() -+ -+/*************************************************************************** -+ * INTC -+ ***************************************************************************/ -+#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -+#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -+#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) -+ -+ -+/*************************************************************************** -+ * I2C -+ ***************************************************************************/ -+ -+#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -+#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -+ -+#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -+#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -+#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -+#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -+ -+#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -+#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -+#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -+ -+#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -+#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -+#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -+ -+#define __i2c_set_clk(dev_clk, i2c_clk) \ -+ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -+ -+#define __i2c_read() ( REG_I2C_DR ) -+#define __i2c_write(val) ( REG_I2C_DR = (val) ) -+ -+ -+/*************************************************************************** -+ * MSC -+ ***************************************************************************/ -+ -+#define __msc_start_op() \ -+ ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -+ -+#define __msc_set_resto(to) ( REG_MSC_RESTO = to ) -+#define __msc_set_rdto(to) ( REG_MSC_RDTO = to ) -+#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd ) -+#define __msc_set_arg(arg) ( REG_MSC_ARG = arg ) -+#define __msc_set_nob(nob) ( REG_MSC_NOB = nob ) -+#define __msc_get_nob() ( REG_MSC_NOB ) -+#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len ) -+#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat ) -+#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT ) -+#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT ) -+ -+#define __msc_set_cmdat_bus_width1() \ -+do { \ -+ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_bus_width4() \ -+do { \ -+ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN ) -+#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT ) -+#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY ) -+#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN ) -+ -+/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -+#define __msc_set_cmdat_res_format(r) \ -+do { \ -+ REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -+ REG_MSC_CMDAT |= (r); \ -+} while(0) -+ -+#define __msc_clear_cmdat() \ -+ REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -+ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -+ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -+ -+#define __msc_get_imask() ( REG_MSC_IMASK ) -+#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff ) -+#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 ) -+#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES ) -+#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES ) -+#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE ) -+#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE ) -+ -+/* n=0,1,2,3,4,5,6,7 */ -+#define __msc_set_clkrt(n) \ -+do { \ -+ REG_MSC_CLKRT = n; \ -+} while(0) -+ -+#define __msc_get_ireg() ( REG_MSC_IREG ) -+#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ ) -+#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ ) -+#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE ) -+#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE ) -+ -+#define __msc_get_stat() ( REG_MSC_STAT ) -+#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0) -+#define __msc_stat_crc_err() \ -+ ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -+#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR ) -+#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR ) -+#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES ) -+#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES ) -+#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ ) -+ -+#define __msc_rd_resfifo() ( REG_MSC_RES ) -+#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO ) -+#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v ) -+ -+#define __msc_reset() \ -+do { \ -+ REG_MSC_STRPCL = MSC_STRPCL_RESET; \ -+ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \ -+} while (0) -+ -+#define __msc_start_clk() \ -+do { \ -+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \ -+} while (0) -+ -+#define __msc_stop_clk() \ -+do { \ -+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -+} while (0) -+ -+#define MMC_CLK 19169200 -+#define SD_CLK 24576000 -+ -+/* msc_clk should little than pclk and little than clk retrieve from card */ -+#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -+do { \ -+ unsigned int rate, pclk, i; \ -+ pclk = dev_clk; \ -+ rate = type?SD_CLK:MMC_CLK; \ -+ if (msc_clk && msc_clk < pclk) \ -+ pclk = msc_clk; \ -+ i = 0; \ -+ while (pclk < rate) \ -+ { \ -+ i ++; \ -+ rate >>= 1; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+/* divide rate to little than or equal to 400kHz */ -+#define __msc_calc_slow_clk_divisor(type, lv) \ -+do { \ -+ unsigned int rate, i; \ -+ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -+ i = 0; \ -+ while (rate > 0) \ -+ { \ -+ rate >>= 1; \ -+ i ++; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+ -+/*************************************************************************** -+ * SSI -+ ***************************************************************************/ -+ -+#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE ) -+#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE ) -+#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL ) -+ -+#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK ) -+ -+#define __ssi_select_ce2() \ -+do { \ -+ REG_SSI_CR0 |= SSI_CR0_FSEL; \ -+ REG_SSI_CR1 &= ~SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_select_gpc() \ -+do { \ -+ REG_SSI_CR0 &= ~SSI_CR0_FSEL; \ -+ REG_SSI_CR1 |= SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_enable_tx_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE ) -+ -+#define __ssi_disable_tx_intr() \ -+ ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -+ -+#define __ssi_enable_rx_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE ) -+ -+#define __ssi_disable_rx_intr() \ -+ ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -+ -+#define __ssi_enable_txfifo_half_empty_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_TIE ) -+#define __ssi_disable_txfifo_half_empty_intr() \ -+ ( REG_SSI_CR0 &= ~SSI_CR0_TIE ) -+#define __ssi_enable_tx_error_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_TEIE ) -+#define __ssi_disable_tx_error_intr() \ -+ ( REG_SSI_CR0 &= ~SSI_CR0_TEIE ) -+ -+#define __ssi_enable_rxfifo_half_full_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_RIE ) -+#define __ssi_disable_rxfifo_half_full_intr() \ -+ ( REG_SSI_CR0 &= ~SSI_CR0_RIE ) -+#define __ssi_enable_rx_error_intr() \ -+ ( REG_SSI_CR0 |= SSI_CR0_REIE ) -+#define __ssi_disable_rx_error_intr() \ -+ ( REG_SSI_CR0 &= ~SSI_CR0_REIE ) -+ -+#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP ) -+#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP ) -+ -+#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV ) -+#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV ) -+ -+#define __ssi_finish_receive() \ -+ ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_disable_recvfinish() \ -+ ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH ) -+#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH ) -+ -+#define __ssi_flush_fifo() \ -+ ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -+ -+#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN ) -+#define __ssi_wait_transmit() ( REG_SSI_CR1 |= SSI_CR1_UNFIN ) -+ -+#define __ssi_spi_format() \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \ -+ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -+ REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -+} while (0) -+ -+/* TI's SSP format, must clear SSI_CR1.UNFIN */ -+#define __ssi_ssp_format() \ -+do { \ -+ REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -+ REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \ -+} while (0) -+ -+/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -+#define __ssi_microwire_format() \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \ -+ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -+ REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -+ REG_SSI_CR0 &= ~SSI_CR0_RFINE; \ -+} while (0) -+ -+/* CE# level (FRMHL), CE# in interval time (ITFRM), -+ clock phase and polarity (PHA POL), -+ interval time (SSIITR), interval characters/frame (SSIICR) */ -+ -+ /* frmhl,endian,mcom,flen,pha,pol MASK */ -+#define SSICR1_MISC_MASK \ -+ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -+ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \ -+ -+#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \ -+do { \ -+ REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \ -+ REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \ -+ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -+ ((pha) << 1) | (pol); \ -+} while(0) -+ -+/* Transfer with MSB or LSB first */ -+#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST ) -+#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST ) -+ -+#define __ssi_set_frame_length(n) \ -+ REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4) -+ -+/* n = 1 - 16 */ -+#define __ssi_set_microwire_command_length(n) \ -+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) ) -+ -+/* Set the clock phase for SPI */ -+#define __ssi_set_spi_clock_phase(n) \ -+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | ((n&0x1)<< 1))) -+ -+/* Set the clock polarity for SPI */ -+#define __ssi_set_spi_clock_polarity(n) \ -+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | (n&0x1)) ) -+ -+/* n = ix8 */ -+#define __ssi_set_tx_trigger(n) \ -+do { \ -+ REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \ -+ REG_SSI_CR1 |= (n/8)<> SSI_SR_TFIFONUM_BIT ) -+ -+#define __ssi_get_rxfifo_count() \ -+ ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -+ -+#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END ) -+#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY ) -+ -+#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF ) -+#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE ) -+#define __ssi_rxfifo_half_full() ( REG_SSI_SR & SSI_SR_RFHF ) -+#define __ssi_txfifo_half_empty() ( REG_SSI_SR & SSI_SR_TFHE ) -+#define __ssi_underrun() ( REG_SSI_SR & SSI_SR_UNDR ) -+#define __ssi_overrun() ( REG_SSI_SR & SSI_SR_OVER ) -+#define __ssi_clear_underrun() ( REG_SSI_SR = ~SSI_SR_UNDR ) -+#define __ssi_clear_overrun() ( REG_SSI_SR = ~SSI_SR_OVER ) -+#define __ssi_clear_errors() \ -+ ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -+ -+ -+#define __ssi_set_clk(dev_clk, ssi_clk) \ -+ ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 ) -+ -+#define __ssi_receive_data() REG_SSI_DR -+#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) ) -+ -+ -+/*************************************************************************** -+ * CIM -+ ***************************************************************************/ -+ -+#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -+#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -+ -+#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT ) -+#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT ) -+ -+#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP ) -+#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP ) -+ -+#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP ) -+#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP ) -+ -+#define __cim_sample_data_at_pclk_falling_edge() \ -+ ( REG_CIM_CFG |= CIM_CFG_PCP ) -+#define __cim_sample_data_at_pclk_rising_edge() \ -+ ( REG_CIM_CFG &= ~CIM_CFG_PCP ) -+ -+#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO ) -+#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO ) -+ -+#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC ) -+#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC ) -+ -+/* n=0-7 */ -+#define __cim_set_data_packing_mode(n) \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \ -+ REG_CIM_CFG |= (CIM_CFG_PACK_##n); \ -+} while (0) -+ -+#define __cim_enable_ccir656_progressive_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_CPM; \ -+} while (0) -+ -+#define __cim_enable_ccir656_interlace_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_CIM; \ -+} while (0) -+ -+#define __cim_enable_gated_clock_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_GCM; \ -+} while (0) -+ -+#define __cim_enable_nongated_clock_mode() \ -+do { \ -+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -+ REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \ -+} while (0) -+ -+/* sclk:system bus clock -+ * mclk: CIM master clock -+ */ -+#define __cim_set_master_clk(sclk, mclk) \ -+do { \ -+ REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \ -+ REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \ -+} while (0) -+ -+#define __cim_enable_sof_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM ) -+#define __cim_disable_sof_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM ) -+ -+#define __cim_enable_eof_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM ) -+#define __cim_disable_eof_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM ) -+ -+#define __cim_enable_stop_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM ) -+#define __cim_disable_stop_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM ) -+ -+#define __cim_enable_trig_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM ) -+#define __cim_disable_trig_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM ) -+ -+#define __cim_enable_rxfifo_overflow_intr() \ -+ ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM ) -+#define __cim_disable_rxfifo_overflow_intr() \ -+ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM ) -+ -+/* n=1-16 */ -+#define __cim_set_frame_rate(n) \ -+do { \ -+ REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \ -+ REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \ -+} while (0) -+ -+#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN ) -+#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN ) -+ -+#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST ) -+#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST ) -+ -+/* n=4,8,12,16,20,24,28,32 */ -+#define __cim_set_rxfifo_trigger(n) \ -+do { \ -+ REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \ -+ REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \ -+} while (0) -+ -+#define __cim_clear_state() ( REG_CIM_STATE = 0 ) -+ -+#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD ) -+#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY ) -+#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG ) -+#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF ) -+#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF ) -+#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP ) -+#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF ) -+#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF ) -+ -+#define __cim_get_iid() ( REG_CIM_IID ) -+#define __cim_get_image_data() ( REG_CIM_RXFIFO ) -+#define __cim_get_dam_cmd() ( REG_CIM_CMD ) -+ -+#define __cim_set_da(a) ( REG_CIM_DA = (a) ) -+ -+/*************************************************************************** -+ * LCD -+ ***************************************************************************/ -+#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= (1<> LCD_VSYNC_VPS_BIT ) -+ -+#define __lcd_vsync_get_vpe() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -+#define __lcd_vsync_set_vpe(n) \ -+do { \ -+ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -+ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hps() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -+#define __lcd_hsync_set_hps(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hpe() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -+#define __lcd_hsync_set_hpe(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_ht() \ -+ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -+#define __lcd_vat_set_ht(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_vt() \ -+ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -+#define __lcd_vat_set_vt(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hds() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -+#define __lcd_dah_set_hds(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hde() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -+#define __lcd_dah_set_hde(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vds() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -+#define __lcd_dav_set_vds(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vde() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -+#define __lcd_dav_set_vde(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -+} while (0) -+ -+#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -+#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -+ -+#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -+#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -+ -+#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -+#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -+ -+#define __lcd_cmd0_get_len() \ -+ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+#define __lcd_cmd1_get_len() \ -+ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+ -+/******************************************************* -+ * SMART LCD -+ *******************************************************/ -+ -+#define __slcd_dma_enable() (REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN) -+#define __slcd_dma_disable() \ -+do {\ -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); \ -+ REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; \ -+} while(0) -+ -+/******************************************************* -+ * SMART LCD -+ *******************************************************/ -+ -+#define __slcd_dma_enable() (REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN) -+#define __slcd_dma_disable() \ -+do {\ -+ while (REG_SLCD_STATE & SLCD_STATE_BUSY); \ -+ REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; \ -+} while(0) -+ -+/*************************************************************************** -+ * RTC ops -+ ***************************************************************************/ -+ -+#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) -+#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) -+#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) -+#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -+#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -+#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -+#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -+#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) -+#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) -+ -+#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) -+#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) -+#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) -+#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -+ -+#define __rtc_get_second() ( REG_RTC_RSR ) -+#define __rtc_set_second(v) ( REG_RTC_RSR = v ) -+ -+#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) -+#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) -+ -+#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) -+#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -+#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) -+#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) -+#define __rtc_set_adjc_val(v) \ -+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) -+#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) -+#define __rtc_set_nc1Hz_val(v) \ -+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) -+ -+#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) -+ -+#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) -+#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) -+#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) -+#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) -+ -+#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) -+#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) -+ -+#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) -+#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) -+#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) -+#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) -+#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) -+ -+#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) -+#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) -+ -+ -+ -+#endif /* __JZ4740_OPS_H__ */ -diff --git a/include/asm-mips/mach-jz4740/regs.h b/include/asm-mips/mach-jz4740/regs.h -new file mode 100644 -index 0000000..07528bc ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/regs.h -@@ -0,0 +1,2392 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/regs.h -+ * -+ * Ingenic's JZ4740 common include. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __JZ4740_REGS_H__ -+#define __JZ4740_REGS_H__ -+ -+#if defined(__ASSEMBLY__) || defined(__LANGUAGE_ASSEMBLY) -+#define REG8(addr) (addr) -+#define REG16(addr) (addr) -+#define REG32(addr) (addr) -+#else -+#define REG8(addr) *((volatile unsigned char *)(addr)) -+#define REG16(addr) *((volatile unsigned short *)(addr)) -+#define REG32(addr) *((volatile unsigned int *)(addr)) -+#endif -+ -+/* -+ * Define the module base addresses -+ */ -+#define CPM_BASE 0xB0000000 -+#define INTC_BASE 0xB0001000 -+#define TCU_BASE 0xB0002000 -+#define WDT_BASE 0xB0002000 -+#define RTC_BASE 0xB0003000 -+#define GPIO_BASE 0xB0010000 -+#define AIC_BASE 0xB0020000 -+#define ICDC_BASE 0xB0020000 -+#define MSC_BASE 0xB0021000 -+#define UART0_BASE 0xB0030000 -+#define UART1_BASE 0xB0031000 -+#define I2C_BASE 0xB0042000 -+#define SSI_BASE 0xB0043000 -+#define SADC_BASE 0xB0070000 -+#define EMC_BASE 0xB3010000 -+#define DMAC_BASE 0xB3020000 -+#define UHC_BASE 0xB3030000 -+#define UDC_BASE 0xB3040000 -+#define LCD_BASE 0xB3050000 -+#define SLCD_BASE 0xB3050000 -+#define CIM_BASE 0xB3060000 -+#define IPU_BASE 0xB3080000 -+#define ETH_BASE 0xB3100000 -+ -+ -+/************************************************************************* -+ * INTC (Interrupt Controller) -+ *************************************************************************/ -+#define INTC_ISR (INTC_BASE + 0x00) -+#define INTC_IMR (INTC_BASE + 0x04) -+#define INTC_IMSR (INTC_BASE + 0x08) -+#define INTC_IMCR (INTC_BASE + 0x0c) -+#define INTC_IPR (INTC_BASE + 0x10) -+ -+#define REG_INTC_ISR REG32(INTC_ISR) -+#define REG_INTC_IMR REG32(INTC_IMR) -+#define REG_INTC_IMSR REG32(INTC_IMSR) -+#define REG_INTC_IMCR REG32(INTC_IMCR) -+#define REG_INTC_IPR REG32(INTC_IPR) -+ -+// 1st-level interrupts -+#define IRQ_I2C 1 -+#define IRQ_UHC 3 -+#define IRQ_UART1 8 -+#define IRQ_UART0 9 -+#define IRQ_SADC 12 -+#define IRQ_MSC 14 -+#define IRQ_RTC 15 -+#define IRQ_SSI 16 -+#define IRQ_CIM 17 -+#define IRQ_AIC 18 -+#define IRQ_ETH 19 -+#define IRQ_DMAC 20 -+#define IRQ_TCU2 21 -+#define IRQ_TCU1 22 -+#define IRQ_TCU0 23 -+#define IRQ_UDC 24 -+#define IRQ_GPIO3 25 -+#define IRQ_GPIO2 26 -+#define IRQ_GPIO1 27 -+#define IRQ_GPIO0 28 -+#define IRQ_IPU 29 -+#define IRQ_LCD 30 -+ -+// 2nd-level interrupts -+#define IRQ_DMA_0 32 /* 32 to 37 for DMAC channel 0 to 5 */ -+#define IRQ_GPIO_0 48 /* 48 to 175 for GPIO pin 0 to 127 */ -+ -+#define NUM_DMA 6 -+#define NUM_GPIO 128 -+/************************************************************************* -+ * RTC -+ *************************************************************************/ -+#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */ -+#define RTC_RSR (RTC_BASE + 0x04) /* RTC Second Register */ -+#define RTC_RSAR (RTC_BASE + 0x08) /* RTC Second Alarm Register */ -+#define RTC_RGR (RTC_BASE + 0x0c) /* RTC Regulator Register */ -+ -+#define RTC_HCR (RTC_BASE + 0x20) /* Hibernate Control Register */ -+#define RTC_HWFCR (RTC_BASE + 0x24) /* Hibernate Wakeup Filter Counter Reg */ -+#define RTC_HRCR (RTC_BASE + 0x28) /* Hibernate Reset Counter Register */ -+#define RTC_HWCR (RTC_BASE + 0x2c) /* Hibernate Wakeup Control Register */ -+#define RTC_HWRSR (RTC_BASE + 0x30) /* Hibernate Wakeup Status Register */ -+#define RTC_HSPR (RTC_BASE + 0x34) /* Hibernate Scratch Pattern Register */ -+ -+#define REG_RTC_RCR REG32(RTC_RCR) -+#define REG_RTC_RSR REG32(RTC_RSR) -+#define REG_RTC_RSAR REG32(RTC_RSAR) -+#define REG_RTC_RGR REG32(RTC_RGR) -+#define REG_RTC_HCR REG32(RTC_HCR) -+#define REG_RTC_HWFCR REG32(RTC_HWFCR) -+#define REG_RTC_HRCR REG32(RTC_HRCR) -+#define REG_RTC_HWCR REG32(RTC_HWCR) -+#define REG_RTC_HWRSR REG32(RTC_HWRSR) -+#define REG_RTC_HSPR REG32(RTC_HSPR) -+ -+/* RTC Control Register */ -+#define RTC_RCR_WRDY_BIT 7 -+#define RTC_RCR_WRDY (1 << 7) /* Write Ready Flag */ -+#define RTC_RCR_1HZ_BIT 6 -+#define RTC_RCR_1HZ (1 << RTC_RCR_1HZ_BIT) /* 1Hz Flag */ -+#define RTC_RCR_1HZIE (1 << 5) /* 1Hz Interrupt Enable */ -+#define RTC_RCR_AF_BIT 4 -+#define RTC_RCR_AF (1 << RTC_RCR_AF_BIT) /* Alarm Flag */ -+#define RTC_RCR_AIE (1 << 3) /* Alarm Interrupt Enable */ -+#define RTC_RCR_AE (1 << 2) /* Alarm Enable */ -+#define RTC_RCR_RTCE (1 << 0) /* RTC Enable */ -+ -+/* RTC Regulator Register */ -+#define RTC_RGR_LOCK (1 << 31) /* Lock Bit */ -+#define RTC_RGR_ADJC_BIT 16 -+#define RTC_RGR_ADJC_MASK (0x3ff << RTC_RGR_ADJC_BIT) -+#define RTC_RGR_NC1HZ_BIT 0 -+#define RTC_RGR_NC1HZ_MASK (0xffff << RTC_RGR_NC1HZ_BIT) -+ -+/* Hibernate Control Register */ -+#define RTC_HCR_PD (1 << 0) /* Power Down */ -+ -+/* Hibernate Wakeup Filter Counter Register */ -+#define RTC_HWFCR_BIT 5 -+#define RTC_HWFCR_MASK (0x7ff << RTC_HWFCR_BIT) -+ -+/* Hibernate Reset Counter Register */ -+#define RTC_HRCR_BIT 5 -+#define RTC_HRCR_MASK (0x7f << RTC_HRCR_BIT) -+ -+/* Hibernate Wakeup Control Register */ -+#define RTC_HWCR_EALM (1 << 0) /* RTC alarm wakeup enable */ -+ -+/* Hibernate Wakeup Status Register */ -+#define RTC_HWRSR_HR (1 << 5) /* Hibernate reset */ -+#define RTC_HWRSR_PPR (1 << 4) /* PPR reset */ -+#define RTC_HWRSR_PIN (1 << 1) /* Wakeup pin status bit */ -+#define RTC_HWRSR_ALM (1 << 0) /* RTC alarm status bit */ -+ -+ -+/************************************************************************* -+ * CPM (Clock reset and Power control Management) -+ *************************************************************************/ -+#define CPM_CPCCR (CPM_BASE+0x00) -+#define CPM_CPPCR (CPM_BASE+0x10) -+#define CPM_I2SCDR (CPM_BASE+0x60) -+#define CPM_LPCDR (CPM_BASE+0x64) -+#define CPM_MSCCDR (CPM_BASE+0x68) -+#define CPM_UHCCDR (CPM_BASE+0x6C) -+#define CPM_SSICDR (CPM_BASE+0x74) -+ -+#define CPM_LCR (CPM_BASE+0x04) -+#define CPM_CLKGR (CPM_BASE+0x20) -+#define CPM_SCR (CPM_BASE+0x24) -+ -+#define CPM_HCR (CPM_BASE+0x30) -+#define CPM_HWFCR (CPM_BASE+0x34) -+#define CPM_HRCR (CPM_BASE+0x38) -+#define CPM_HWCR (CPM_BASE+0x3c) -+#define CPM_HWSR (CPM_BASE+0x40) -+#define CPM_HSPR (CPM_BASE+0x44) -+ -+#define CPM_RSR (CPM_BASE+0x08) -+ -+ -+#define REG_CPM_CPCCR REG32(CPM_CPCCR) -+#define REG_CPM_CPPCR REG32(CPM_CPPCR) -+#define REG_CPM_I2SCDR REG32(CPM_I2SCDR) -+#define REG_CPM_LPCDR REG32(CPM_LPCDR) -+#define REG_CPM_MSCCDR REG32(CPM_MSCCDR) -+#define REG_CPM_UHCCDR REG32(CPM_UHCCDR) -+#define REG_CPM_SSICDR REG32(CPM_SSICDR) -+ -+#define REG_CPM_LCR REG32(CPM_LCR) -+#define REG_CPM_CLKGR REG32(CPM_CLKGR) -+#define REG_CPM_SCR REG32(CPM_SCR) -+#define REG_CPM_HCR REG32(CPM_HCR) -+#define REG_CPM_HWFCR REG32(CPM_HWFCR) -+#define REG_CPM_HRCR REG32(CPM_HRCR) -+#define REG_CPM_HWCR REG32(CPM_HWCR) -+#define REG_CPM_HWSR REG32(CPM_HWSR) -+#define REG_CPM_HSPR REG32(CPM_HSPR) -+ -+#define REG_CPM_RSR REG32(CPM_RSR) -+ -+ -+/* Clock Control Register */ -+#define CPM_CPCCR_I2CS (1 << 31) -+#define CPM_CPCCR_CLKOEN (1 << 30) -+#define CPM_CPCCR_UCS (1 << 29) -+#define CPM_CPCCR_UDIV_BIT 23 -+#define CPM_CPCCR_UDIV_MASK (0x3f << CPM_CPCCR_UDIV_BIT) -+#define CPM_CPCCR_CE (1 << 22) -+#define CPM_CPCCR_PCS (1 << 21) -+#define CPM_CPCCR_LDIV_BIT 16 -+#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT) -+#define CPM_CPCCR_MDIV_BIT 12 -+#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT) -+#define CPM_CPCCR_PDIV_BIT 8 -+#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT) -+#define CPM_CPCCR_HDIV_BIT 4 -+#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT) -+#define CPM_CPCCR_CDIV_BIT 0 -+#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT) -+ -+/* I2S Clock Divider Register */ -+#define CPM_I2SCDR_I2SDIV_BIT 0 -+#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT) -+ -+/* LCD Pixel Clock Divider Register */ -+#define CPM_LPCDR_PIXDIV_BIT 0 -+#define CPM_LPCDR_PIXDIV_MASK (0x7ff << CPM_LPCDR_PIXDIV_BIT) -+ -+/* MSC Clock Divider Register */ -+#define CPM_MSCCDR_MSCDIV_BIT 0 -+#define CPM_MSCCDR_MSCDIV_MASK (0x1f << CPM_MSCCDR_MSCDIV_BIT) -+ -+/* UHC Clock Divider Register */ -+#define CPM_UHCCDR_UHCDIV_BIT 0 -+#define CPM_UHCCDR_UHCDIV_MASK (0xf << CPM_UHCCDR_UHCDIV_BIT) -+ -+/* SSI Clock Divider Register */ -+#define CPM_SSICDR_SCS (1<<31) /* SSI clock source selection, 0:EXCLK, 1: PLL */ -+#define CPM_SSICDR_SSIDIV_BIT 0 -+#define CPM_SSICDR_SSIDIV_MASK (0xf << CPM_SSICDR_SSIDIV_BIT) -+ -+/* PLL Control Register */ -+#define CPM_CPPCR_PLLM_BIT 23 -+#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT) -+#define CPM_CPPCR_PLLN_BIT 18 -+#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT) -+#define CPM_CPPCR_PLLOD_BIT 16 -+#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT) -+#define CPM_CPPCR_PLLS (1 << 10) -+#define CPM_CPPCR_PLLBP (1 << 9) -+#define CPM_CPPCR_PLLEN (1 << 8) -+#define CPM_CPPCR_PLLST_BIT 0 -+#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT) -+ -+/* Low Power Control Register */ -+#define CPM_LCR_DOZE_DUTY_BIT 3 -+#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT) -+#define CPM_LCR_DOZE_ON (1 << 2) -+#define CPM_LCR_LPM_BIT 0 -+#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT) -+ #define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT) -+ #define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT) -+ -+/* Clock Gate Register */ -+#define CPM_CLKGR_UART1 (1 << 15) -+#define CPM_CLKGR_UHC (1 << 14) -+#define CPM_CLKGR_IPU (1 << 13) -+#define CPM_CLKGR_DMAC (1 << 12) -+#define CPM_CLKGR_UDC (1 << 11) -+#define CPM_CLKGR_LCD (1 << 10) -+#define CPM_CLKGR_CIM (1 << 9) -+#define CPM_CLKGR_SADC (1 << 8) -+#define CPM_CLKGR_MSC (1 << 7) -+#define CPM_CLKGR_AIC1 (1 << 6) -+#define CPM_CLKGR_AIC2 (1 << 5) -+#define CPM_CLKGR_SSI (1 << 4) -+#define CPM_CLKGR_I2C (1 << 3) -+#define CPM_CLKGR_RTC (1 << 2) -+#define CPM_CLKGR_TCU (1 << 1) -+#define CPM_CLKGR_UART0 (1 << 0) -+ -+/* Sleep Control Register */ -+#define CPM_SCR_O1ST_BIT 8 -+#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT) -+#define CPM_SCR_USBPHY_ENABLE (1 << 6) -+#define CPM_SCR_OSC_ENABLE (1 << 4) -+ -+/* Hibernate Control Register */ -+#define CPM_HCR_PD (1 << 0) -+ -+/* Wakeup Filter Counter Register in Hibernate Mode */ -+#define CPM_HWFCR_TIME_BIT 0 -+#define CPM_HWFCR_TIME_MASK (0x3ff << CPM_HWFCR_TIME_BIT) -+ -+/* Reset Counter Register in Hibernate Mode */ -+#define CPM_HRCR_TIME_BIT 0 -+#define CPM_HRCR_TIME_MASK (0x7f << CPM_HRCR_TIME_BIT) -+ -+/* Wakeup Control Register in Hibernate Mode */ -+#define CPM_HWCR_WLE_LOW (0 << 2) -+#define CPM_HWCR_WLE_HIGH (1 << 2) -+#define CPM_HWCR_PIN_WAKEUP (1 << 1) -+#define CPM_HWCR_RTC_WAKEUP (1 << 0) -+ -+/* Wakeup Status Register in Hibernate Mode */ -+#define CPM_HWSR_WSR_PIN (1 << 1) -+#define CPM_HWSR_WSR_RTC (1 << 0) -+ -+/* Reset Status Register */ -+#define CPM_RSR_HR (1 << 2) -+#define CPM_RSR_WR (1 << 1) -+#define CPM_RSR_PR (1 << 0) -+ -+ -+/************************************************************************* -+ * TCU (Timer Counter Unit) -+ *************************************************************************/ -+#define TCU_TSR (TCU_BASE + 0x1C) /* Timer Stop Register */ -+#define TCU_TSSR (TCU_BASE + 0x2C) /* Timer Stop Set Register */ -+#define TCU_TSCR (TCU_BASE + 0x3C) /* Timer Stop Clear Register */ -+#define TCU_TER (TCU_BASE + 0x10) /* Timer Counter Enable Register */ -+#define TCU_TESR (TCU_BASE + 0x14) /* Timer Counter Enable Set Register */ -+#define TCU_TECR (TCU_BASE + 0x18) /* Timer Counter Enable Clear Register */ -+#define TCU_TFR (TCU_BASE + 0x20) /* Timer Flag Register */ -+#define TCU_TFSR (TCU_BASE + 0x24) /* Timer Flag Set Register */ -+#define TCU_TFCR (TCU_BASE + 0x28) /* Timer Flag Clear Register */ -+#define TCU_TMR (TCU_BASE + 0x30) /* Timer Mask Register */ -+#define TCU_TMSR (TCU_BASE + 0x34) /* Timer Mask Set Register */ -+#define TCU_TMCR (TCU_BASE + 0x38) /* Timer Mask Clear Register */ -+#define TCU_TDFR0 (TCU_BASE + 0x40) /* Timer Data Full Register */ -+#define TCU_TDHR0 (TCU_BASE + 0x44) /* Timer Data Half Register */ -+#define TCU_TCNT0 (TCU_BASE + 0x48) /* Timer Counter Register */ -+#define TCU_TCSR0 (TCU_BASE + 0x4C) /* Timer Control Register */ -+#define TCU_TDFR1 (TCU_BASE + 0x50) -+#define TCU_TDHR1 (TCU_BASE + 0x54) -+#define TCU_TCNT1 (TCU_BASE + 0x58) -+#define TCU_TCSR1 (TCU_BASE + 0x5C) -+#define TCU_TDFR2 (TCU_BASE + 0x60) -+#define TCU_TDHR2 (TCU_BASE + 0x64) -+#define TCU_TCNT2 (TCU_BASE + 0x68) -+#define TCU_TCSR2 (TCU_BASE + 0x6C) -+#define TCU_TDFR3 (TCU_BASE + 0x70) -+#define TCU_TDHR3 (TCU_BASE + 0x74) -+#define TCU_TCNT3 (TCU_BASE + 0x78) -+#define TCU_TCSR3 (TCU_BASE + 0x7C) -+#define TCU_TDFR4 (TCU_BASE + 0x80) -+#define TCU_TDHR4 (TCU_BASE + 0x84) -+#define TCU_TCNT4 (TCU_BASE + 0x88) -+#define TCU_TCSR4 (TCU_BASE + 0x8C) -+#define TCU_TDFR5 (TCU_BASE + 0x90) -+#define TCU_TDHR5 (TCU_BASE + 0x94) -+#define TCU_TCNT5 (TCU_BASE + 0x98) -+#define TCU_TCSR5 (TCU_BASE + 0x9C) -+ -+#define REG_TCU_TSR REG32(TCU_TSR) -+#define REG_TCU_TSSR REG32(TCU_TSSR) -+#define REG_TCU_TSCR REG32(TCU_TSCR) -+#define REG_TCU_TER REG8(TCU_TER) -+#define REG_TCU_TESR REG8(TCU_TESR) -+#define REG_TCU_TECR REG8(TCU_TECR) -+#define REG_TCU_TFR REG32(TCU_TFR) -+#define REG_TCU_TFSR REG32(TCU_TFSR) -+#define REG_TCU_TFCR REG32(TCU_TFCR) -+#define REG_TCU_TMR REG32(TCU_TMR) -+#define REG_TCU_TMSR REG32(TCU_TMSR) -+#define REG_TCU_TMCR REG32(TCU_TMCR) -+#define REG_TCU_TDFR0 REG16(TCU_TDFR0) -+#define REG_TCU_TDHR0 REG16(TCU_TDHR0) -+#define REG_TCU_TCNT0 REG16(TCU_TCNT0) -+#define REG_TCU_TCSR0 REG16(TCU_TCSR0) -+#define REG_TCU_TDFR1 REG16(TCU_TDFR1) -+#define REG_TCU_TDHR1 REG16(TCU_TDHR1) -+#define REG_TCU_TCNT1 REG16(TCU_TCNT1) -+#define REG_TCU_TCSR1 REG16(TCU_TCSR1) -+#define REG_TCU_TDFR2 REG16(TCU_TDFR2) -+#define REG_TCU_TDHR2 REG16(TCU_TDHR2) -+#define REG_TCU_TCNT2 REG16(TCU_TCNT2) -+#define REG_TCU_TCSR2 REG16(TCU_TCSR2) -+#define REG_TCU_TDFR3 REG16(TCU_TDFR3) -+#define REG_TCU_TDHR3 REG16(TCU_TDHR3) -+#define REG_TCU_TCNT3 REG16(TCU_TCNT3) -+#define REG_TCU_TCSR3 REG16(TCU_TCSR3) -+#define REG_TCU_TDFR4 REG16(TCU_TDFR4) -+#define REG_TCU_TDHR4 REG16(TCU_TDHR4) -+#define REG_TCU_TCNT4 REG16(TCU_TCNT4) -+#define REG_TCU_TCSR4 REG16(TCU_TCSR4) -+ -+// n = 0,1,2,3,4,5 -+#define TCU_TDFR(n) (TCU_BASE + (0x40 + (n)*0x10)) /* Timer Data Full Reg */ -+#define TCU_TDHR(n) (TCU_BASE + (0x44 + (n)*0x10)) /* Timer Data Half Reg */ -+#define TCU_TCNT(n) (TCU_BASE + (0x48 + (n)*0x10)) /* Timer Counter Reg */ -+#define TCU_TCSR(n) (TCU_BASE + (0x4C + (n)*0x10)) /* Timer Control Reg */ -+ -+#define REG_TCU_TDFR(n) REG16(TCU_TDFR((n))) -+#define REG_TCU_TDHR(n) REG16(TCU_TDHR((n))) -+#define REG_TCU_TCNT(n) REG16(TCU_TCNT((n))) -+#define REG_TCU_TCSR(n) REG16(TCU_TCSR((n))) -+ -+// Register definitions -+#define TCU_TCSR_PWM_SD (1 << 9) -+#define TCU_TCSR_PWM_INITL_HIGH (1 << 8) -+#define TCU_TCSR_PWM_EN (1 << 7) -+#define TCU_TCSR_PRESCALE_BIT 3 -+#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT) -+ #define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT) -+ #define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT) -+ #define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT) -+ #define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT) -+ #define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT) -+ #define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT) -+#define TCU_TCSR_EXT_EN (1 << 2) -+#define TCU_TCSR_RTC_EN (1 << 1) -+#define TCU_TCSR_PCK_EN (1 << 0) -+ -+#define TCU_TER_TCEN5 (1 << 5) -+#define TCU_TER_TCEN4 (1 << 4) -+#define TCU_TER_TCEN3 (1 << 3) -+#define TCU_TER_TCEN2 (1 << 2) -+#define TCU_TER_TCEN1 (1 << 1) -+#define TCU_TER_TCEN0 (1 << 0) -+ -+#define TCU_TESR_TCST5 (1 << 5) -+#define TCU_TESR_TCST4 (1 << 4) -+#define TCU_TESR_TCST3 (1 << 3) -+#define TCU_TESR_TCST2 (1 << 2) -+#define TCU_TESR_TCST1 (1 << 1) -+#define TCU_TESR_TCST0 (1 << 0) -+ -+#define TCU_TECR_TCCL5 (1 << 5) -+#define TCU_TECR_TCCL4 (1 << 4) -+#define TCU_TECR_TCCL3 (1 << 3) -+#define TCU_TECR_TCCL2 (1 << 2) -+#define TCU_TECR_TCCL1 (1 << 1) -+#define TCU_TECR_TCCL0 (1 << 0) -+ -+#define TCU_TFR_HFLAG5 (1 << 21) -+#define TCU_TFR_HFLAG4 (1 << 20) -+#define TCU_TFR_HFLAG3 (1 << 19) -+#define TCU_TFR_HFLAG2 (1 << 18) -+#define TCU_TFR_HFLAG1 (1 << 17) -+#define TCU_TFR_HFLAG0 (1 << 16) -+#define TCU_TFR_FFLAG5 (1 << 5) -+#define TCU_TFR_FFLAG4 (1 << 4) -+#define TCU_TFR_FFLAG3 (1 << 3) -+#define TCU_TFR_FFLAG2 (1 << 2) -+#define TCU_TFR_FFLAG1 (1 << 1) -+#define TCU_TFR_FFLAG0 (1 << 0) -+ -+#define TCU_TFSR_HFLAG5 (1 << 21) -+#define TCU_TFSR_HFLAG4 (1 << 20) -+#define TCU_TFSR_HFLAG3 (1 << 19) -+#define TCU_TFSR_HFLAG2 (1 << 18) -+#define TCU_TFSR_HFLAG1 (1 << 17) -+#define TCU_TFSR_HFLAG0 (1 << 16) -+#define TCU_TFSR_FFLAG5 (1 << 5) -+#define TCU_TFSR_FFLAG4 (1 << 4) -+#define TCU_TFSR_FFLAG3 (1 << 3) -+#define TCU_TFSR_FFLAG2 (1 << 2) -+#define TCU_TFSR_FFLAG1 (1 << 1) -+#define TCU_TFSR_FFLAG0 (1 << 0) -+ -+#define TCU_TFCR_HFLAG5 (1 << 21) -+#define TCU_TFCR_HFLAG4 (1 << 20) -+#define TCU_TFCR_HFLAG3 (1 << 19) -+#define TCU_TFCR_HFLAG2 (1 << 18) -+#define TCU_TFCR_HFLAG1 (1 << 17) -+#define TCU_TFCR_HFLAG0 (1 << 16) -+#define TCU_TFCR_FFLAG5 (1 << 5) -+#define TCU_TFCR_FFLAG4 (1 << 4) -+#define TCU_TFCR_FFLAG3 (1 << 3) -+#define TCU_TFCR_FFLAG2 (1 << 2) -+#define TCU_TFCR_FFLAG1 (1 << 1) -+#define TCU_TFCR_FFLAG0 (1 << 0) -+ -+#define TCU_TMR_HMASK5 (1 << 21) -+#define TCU_TMR_HMASK4 (1 << 20) -+#define TCU_TMR_HMASK3 (1 << 19) -+#define TCU_TMR_HMASK2 (1 << 18) -+#define TCU_TMR_HMASK1 (1 << 17) -+#define TCU_TMR_HMASK0 (1 << 16) -+#define TCU_TMR_FMASK5 (1 << 5) -+#define TCU_TMR_FMASK4 (1 << 4) -+#define TCU_TMR_FMASK3 (1 << 3) -+#define TCU_TMR_FMASK2 (1 << 2) -+#define TCU_TMR_FMASK1 (1 << 1) -+#define TCU_TMR_FMASK0 (1 << 0) -+ -+#define TCU_TMSR_HMST5 (1 << 21) -+#define TCU_TMSR_HMST4 (1 << 20) -+#define TCU_TMSR_HMST3 (1 << 19) -+#define TCU_TMSR_HMST2 (1 << 18) -+#define TCU_TMSR_HMST1 (1 << 17) -+#define TCU_TMSR_HMST0 (1 << 16) -+#define TCU_TMSR_FMST5 (1 << 5) -+#define TCU_TMSR_FMST4 (1 << 4) -+#define TCU_TMSR_FMST3 (1 << 3) -+#define TCU_TMSR_FMST2 (1 << 2) -+#define TCU_TMSR_FMST1 (1 << 1) -+#define TCU_TMSR_FMST0 (1 << 0) -+ -+#define TCU_TMCR_HMCL5 (1 << 21) -+#define TCU_TMCR_HMCL4 (1 << 20) -+#define TCU_TMCR_HMCL3 (1 << 19) -+#define TCU_TMCR_HMCL2 (1 << 18) -+#define TCU_TMCR_HMCL1 (1 << 17) -+#define TCU_TMCR_HMCL0 (1 << 16) -+#define TCU_TMCR_FMCL5 (1 << 5) -+#define TCU_TMCR_FMCL4 (1 << 4) -+#define TCU_TMCR_FMCL3 (1 << 3) -+#define TCU_TMCR_FMCL2 (1 << 2) -+#define TCU_TMCR_FMCL1 (1 << 1) -+#define TCU_TMCR_FMCL0 (1 << 0) -+ -+#define TCU_TSR_WDTS (1 << 16) -+#define TCU_TSR_STOP5 (1 << 5) -+#define TCU_TSR_STOP4 (1 << 4) -+#define TCU_TSR_STOP3 (1 << 3) -+#define TCU_TSR_STOP2 (1 << 2) -+#define TCU_TSR_STOP1 (1 << 1) -+#define TCU_TSR_STOP0 (1 << 0) -+ -+#define TCU_TSSR_WDTSS (1 << 16) -+#define TCU_TSSR_STPS5 (1 << 5) -+#define TCU_TSSR_STPS4 (1 << 4) -+#define TCU_TSSR_STPS3 (1 << 3) -+#define TCU_TSSR_STPS2 (1 << 2) -+#define TCU_TSSR_STPS1 (1 << 1) -+#define TCU_TSSR_STPS0 (1 << 0) -+ -+#define TCU_TSSR_WDTSC (1 << 16) -+#define TCU_TSSR_STPC5 (1 << 5) -+#define TCU_TSSR_STPC4 (1 << 4) -+#define TCU_TSSR_STPC3 (1 << 3) -+#define TCU_TSSR_STPC2 (1 << 2) -+#define TCU_TSSR_STPC1 (1 << 1) -+#define TCU_TSSR_STPC0 (1 << 0) -+ -+ -+/************************************************************************* -+ * WDT (WatchDog Timer) -+ *************************************************************************/ -+#define WDT_TDR (WDT_BASE + 0x00) -+#define WDT_TCER (WDT_BASE + 0x04) -+#define WDT_TCNT (WDT_BASE + 0x08) -+#define WDT_TCSR (WDT_BASE + 0x0C) -+ -+#define REG_WDT_TDR REG16(WDT_TDR) -+#define REG_WDT_TCER REG8(WDT_TCER) -+#define REG_WDT_TCNT REG16(WDT_TCNT) -+#define REG_WDT_TCSR REG16(WDT_TCSR) -+ -+// Register definition -+#define WDT_TCSR_PRESCALE_BIT 3 -+#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT) -+ #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT) -+ #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT) -+ #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT) -+ #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT) -+ #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT) -+ #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT) -+#define WDT_TCSR_EXT_EN (1 << 2) -+#define WDT_TCSR_RTC_EN (1 << 1) -+#define WDT_TCSR_PCK_EN (1 << 0) -+ -+#define WDT_TCER_TCEN (1 << 0) -+ -+ -+/************************************************************************* -+ * DMAC (DMA Controller) -+ *************************************************************************/ -+ -+#define MAX_DMA_NUM 6 /* max 6 channels */ -+ -+#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) /* DMA source address */ -+#define DMAC_DTAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) /* DMA target address */ -+#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) /* DMA transfer count */ -+#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) /* DMA request source */ -+#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ -+#define DMAC_DCMD(n) (DMAC_BASE + (0x14 + (n) * 0x20)) /* DMA command */ -+#define DMAC_DDA(n) (DMAC_BASE + (0x18 + (n) * 0x20)) /* DMA descriptor address */ -+#define DMAC_DMACR (DMAC_BASE + 0x0300) /* DMA control register */ -+#define DMAC_DMAIPR (DMAC_BASE + 0x0304) /* DMA interrupt pending */ -+#define DMAC_DMADBR (DMAC_BASE + 0x0308) /* DMA doorbell */ -+#define DMAC_DMADBSR (DMAC_BASE + 0x030C) /* DMA doorbell set */ -+ -+// channel 0 -+#define DMAC_DSAR0 DMAC_DSAR(0) -+#define DMAC_DTAR0 DMAC_DTAR(0) -+#define DMAC_DTCR0 DMAC_DTCR(0) -+#define DMAC_DRSR0 DMAC_DRSR(0) -+#define DMAC_DCCSR0 DMAC_DCCSR(0) -+#define DMAC_DCMD0 DMAC_DCMD(0) -+#define DMAC_DDA0 DMAC_DDA(0) -+ -+// channel 1 -+#define DMAC_DSAR1 DMAC_DSAR(1) -+#define DMAC_DTAR1 DMAC_DTAR(1) -+#define DMAC_DTCR1 DMAC_DTCR(1) -+#define DMAC_DRSR1 DMAC_DRSR(1) -+#define DMAC_DCCSR1 DMAC_DCCSR(1) -+#define DMAC_DCMD1 DMAC_DCMD(1) -+#define DMAC_DDA1 DMAC_DDA(1) -+ -+// channel 2 -+#define DMAC_DSAR2 DMAC_DSAR(2) -+#define DMAC_DTAR2 DMAC_DTAR(2) -+#define DMAC_DTCR2 DMAC_DTCR(2) -+#define DMAC_DRSR2 DMAC_DRSR(2) -+#define DMAC_DCCSR2 DMAC_DCCSR(2) -+#define DMAC_DCMD2 DMAC_DCMD(2) -+#define DMAC_DDA2 DMAC_DDA(2) -+ -+// channel 3 -+#define DMAC_DSAR3 DMAC_DSAR(3) -+#define DMAC_DTAR3 DMAC_DTAR(3) -+#define DMAC_DTCR3 DMAC_DTCR(3) -+#define DMAC_DRSR3 DMAC_DRSR(3) -+#define DMAC_DCCSR3 DMAC_DCCSR(3) -+#define DMAC_DCMD3 DMAC_DCMD(3) -+#define DMAC_DDA3 DMAC_DDA(3) -+ -+// channel 4 -+#define DMAC_DSAR4 DMAC_DSAR(4) -+#define DMAC_DTAR4 DMAC_DTAR(4) -+#define DMAC_DTCR4 DMAC_DTCR(4) -+#define DMAC_DRSR4 DMAC_DRSR(4) -+#define DMAC_DCCSR4 DMAC_DCCSR(4) -+#define DMAC_DCMD4 DMAC_DCMD(4) -+#define DMAC_DDA4 DMAC_DDA(4) -+ -+// channel 5 -+#define DMAC_DSAR5 DMAC_DSAR(5) -+#define DMAC_DTAR5 DMAC_DTAR(5) -+#define DMAC_DTCR5 DMAC_DTCR(5) -+#define DMAC_DRSR5 DMAC_DRSR(5) -+#define DMAC_DCCSR5 DMAC_DCCSR(5) -+#define DMAC_DCMD5 DMAC_DCMD(5) -+#define DMAC_DDA5 DMAC_DDA(5) -+ -+#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n))) -+#define REG_DMAC_DTAR(n) REG32(DMAC_DTAR((n))) -+#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n))) -+#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n))) -+#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) -+#define REG_DMAC_DCMD(n) REG32(DMAC_DCMD((n))) -+#define REG_DMAC_DDA(n) REG32(DMAC_DDA((n))) -+#define REG_DMAC_DMACR REG32(DMAC_DMACR) -+#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR) -+#define REG_DMAC_DMADBR REG32(DMAC_DMADBR) -+#define REG_DMAC_DMADBSR REG32(DMAC_DMADBSR) -+ -+// DMA request source register -+#define DMAC_DRSR_RS_BIT 0 -+#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_TCU (28 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_SADC (29 << DMAC_DRSR_RS_BIT) -+ #define DMAC_DRSR_RS_SLCD (30 << DMAC_DRSR_RS_BIT) -+ -+// DMA channel control/status register -+#define DMAC_DCCSR_NDES (1 << 31) /* descriptor (0) or not (1) ? */ -+#define DMAC_DCCSR_CDOA_BIT 16 /* copy of DMA offset address */ -+#define DMAC_DCCSR_CDOA_MASK (0xff << DMAC_DCCSR_CDOA_BIT) -+#define DMAC_DCCSR_INV (1 << 6) /* descriptor invalid */ -+#define DMAC_DCCSR_AR (1 << 4) /* address error */ -+#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ -+#define DMAC_DCCSR_HLT (1 << 2) /* DMA halted */ -+#define DMAC_DCCSR_CT (1 << 1) /* count terminated */ -+#define DMAC_DCCSR_EN (1 << 0) /* channel enable bit */ -+ -+// DMA channel command register -+#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ -+#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ -+#define DMAC_DCMD_RDIL_BIT 16 /* request detection interval length */ -+#define DMAC_DCMD_RDIL_MASK (0x0f << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_IGN (0 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_2 (1 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_4 (2 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_8 (3 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_12 (4 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_16 (5 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_20 (6 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_24 (7 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_28 (8 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_32 (9 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_48 (10 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_60 (11 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_64 (12 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_124 (13 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_128 (14 << DMAC_DCMD_RDIL_BIT) -+ #define DMAC_DCMD_RDIL_200 (15 << DMAC_DCMD_RDIL_BIT) -+#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ -+#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT) -+ #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) -+ #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) -+ #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) -+#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ -+#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT) -+ #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) -+ #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) -+ #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) -+#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ -+#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT) -+ #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) -+ #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) -+ #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) -+ #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) -+ #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) -+#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ -+#define DMAC_DCMD_DES_V (1 << 4) /* descriptor valid flag */ -+#define DMAC_DCMD_DES_VM (1 << 3) /* descriptor valid mask: 1:support V-bit */ -+#define DMAC_DCMD_DES_VIE (1 << 2) /* DMA valid error interrupt enable */ -+#define DMAC_DCMD_TIE (1 << 1) /* DMA transfer interrupt enable */ -+#define DMAC_DCMD_LINK (1 << 0) /* descriptor link enable */ -+ -+// DMA descriptor address register -+#define DMAC_DDA_BASE_BIT 12 /* descriptor base address */ -+#define DMAC_DDA_BASE_MASK (0x0fffff << DMAC_DDA_BASE_BIT) -+#define DMAC_DDA_OFFSET_BIT 4 /* descriptor offset address */ -+#define DMAC_DDA_OFFSET_MASK (0x0ff << DMAC_DDA_OFFSET_BIT) -+ -+// DMA control register -+#define DMAC_DMACR_PR_BIT 8 /* channel priority mode */ -+#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_012345 (0 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_023145 (1 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_201345 (2 << DMAC_DMACR_PR_BIT) -+ #define DMAC_DMACR_PR_RR (3 << DMAC_DMACR_PR_BIT) /* round robin */ -+#define DMAC_DMACR_HLT (1 << 3) /* DMA halt flag */ -+#define DMAC_DMACR_AR (1 << 2) /* address error flag */ -+#define DMAC_DMACR_DMAE (1 << 0) /* DMA enable bit */ -+ -+// DMA doorbell register -+#define DMAC_DMADBR_DB5 (1 << 5) /* doorbell for channel 5 */ -+#define DMAC_DMADBR_DB4 (1 << 5) /* doorbell for channel 4 */ -+#define DMAC_DMADBR_DB3 (1 << 5) /* doorbell for channel 3 */ -+#define DMAC_DMADBR_DB2 (1 << 5) /* doorbell for channel 2 */ -+#define DMAC_DMADBR_DB1 (1 << 5) /* doorbell for channel 1 */ -+#define DMAC_DMADBR_DB0 (1 << 5) /* doorbell for channel 0 */ -+ -+// DMA doorbell set register -+#define DMAC_DMADBSR_DBS5 (1 << 5) /* enable doorbell for channel 5 */ -+#define DMAC_DMADBSR_DBS4 (1 << 5) /* enable doorbell for channel 4 */ -+#define DMAC_DMADBSR_DBS3 (1 << 5) /* enable doorbell for channel 3 */ -+#define DMAC_DMADBSR_DBS2 (1 << 5) /* enable doorbell for channel 2 */ -+#define DMAC_DMADBSR_DBS1 (1 << 5) /* enable doorbell for channel 1 */ -+#define DMAC_DMADBSR_DBS0 (1 << 5) /* enable doorbell for channel 0 */ -+ -+// DMA interrupt pending register -+#define DMAC_DMAIPR_CIRQ5 (1 << 5) /* irq pending status for channel 5 */ -+#define DMAC_DMAIPR_CIRQ4 (1 << 4) /* irq pending status for channel 4 */ -+#define DMAC_DMAIPR_CIRQ3 (1 << 3) /* irq pending status for channel 3 */ -+#define DMAC_DMAIPR_CIRQ2 (1 << 2) /* irq pending status for channel 2 */ -+#define DMAC_DMAIPR_CIRQ1 (1 << 1) /* irq pending status for channel 1 */ -+#define DMAC_DMAIPR_CIRQ0 (1 << 0) /* irq pending status for channel 0 */ -+ -+ -+/************************************************************************* -+ * GPIO (General-Purpose I/O Ports) -+ *************************************************************************/ -+#define MAX_GPIO_NUM 128 -+ -+//n = 0,1,2,3 -+#define GPIO_PXPIN(n) (GPIO_BASE + (0x00 + (n)*0x100)) /* PIN Level Register */ -+#define GPIO_PXDAT(n) (GPIO_BASE + (0x10 + (n)*0x100)) /* Port Data Register */ -+#define GPIO_PXDATS(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Data Set Register */ -+#define GPIO_PXDATC(n) (GPIO_BASE + (0x18 + (n)*0x100)) /* Port Data Clear Register */ -+#define GPIO_PXIM(n) (GPIO_BASE + (0x20 + (n)*0x100)) /* Interrupt Mask Register */ -+#define GPIO_PXIMS(n) (GPIO_BASE + (0x24 + (n)*0x100)) /* Interrupt Mask Set Reg */ -+#define GPIO_PXIMC(n) (GPIO_BASE + (0x28 + (n)*0x100)) /* Interrupt Mask Clear Reg */ -+#define GPIO_PXPE(n) (GPIO_BASE + (0x30 + (n)*0x100)) /* Pull Enable Register */ -+#define GPIO_PXPES(n) (GPIO_BASE + (0x34 + (n)*0x100)) /* Pull Enable Set Reg. */ -+#define GPIO_PXPEC(n) (GPIO_BASE + (0x38 + (n)*0x100)) /* Pull Enable Clear Reg. */ -+#define GPIO_PXFUN(n) (GPIO_BASE + (0x40 + (n)*0x100)) /* Function Register */ -+#define GPIO_PXFUNS(n) (GPIO_BASE + (0x44 + (n)*0x100)) /* Function Set Register */ -+#define GPIO_PXFUNC(n) (GPIO_BASE + (0x48 + (n)*0x100)) /* Function Clear Register */ -+#define GPIO_PXSEL(n) (GPIO_BASE + (0x50 + (n)*0x100)) /* Select Register */ -+#define GPIO_PXSELS(n) (GPIO_BASE + (0x54 + (n)*0x100)) /* Select Set Register */ -+#define GPIO_PXSELC(n) (GPIO_BASE + (0x58 + (n)*0x100)) /* Select Clear Register */ -+#define GPIO_PXDIR(n) (GPIO_BASE + (0x60 + (n)*0x100)) /* Direction Register */ -+#define GPIO_PXDIRS(n) (GPIO_BASE + (0x64 + (n)*0x100)) /* Direction Set Register */ -+#define GPIO_PXDIRC(n) (GPIO_BASE + (0x68 + (n)*0x100)) /* Direction Clear Register */ -+#define GPIO_PXTRG(n) (GPIO_BASE + (0x70 + (n)*0x100)) /* Trigger Register */ -+#define GPIO_PXTRGS(n) (GPIO_BASE + (0x74 + (n)*0x100)) /* Trigger Set Register */ -+#define GPIO_PXTRGC(n) (GPIO_BASE + (0x78 + (n)*0x100)) /* Trigger Set Register */ -+#define GPIO_PXFLG(n) (GPIO_BASE + (0x80 + (n)*0x100)) /* Port Flag Register */ -+#define GPIO_PXFLGC(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Flag Clear Register */ -+ -+#define REG_GPIO_PXPIN(n) REG32(GPIO_PXPIN((n))) /* PIN level */ -+#define REG_GPIO_PXDAT(n) REG32(GPIO_PXDAT((n))) /* 1: interrupt pending */ -+#define REG_GPIO_PXDATS(n) REG32(GPIO_PXDATS((n))) -+#define REG_GPIO_PXDATC(n) REG32(GPIO_PXDATC((n))) -+#define REG_GPIO_PXIM(n) REG32(GPIO_PXIM((n))) /* 1: mask pin interrupt */ -+#define REG_GPIO_PXIMS(n) REG32(GPIO_PXIMS((n))) -+#define REG_GPIO_PXIMC(n) REG32(GPIO_PXIMC((n))) -+#define REG_GPIO_PXPE(n) REG32(GPIO_PXPE((n))) /* 1: disable pull up/down */ -+#define REG_GPIO_PXPES(n) REG32(GPIO_PXPES((n))) -+#define REG_GPIO_PXPEC(n) REG32(GPIO_PXPEC((n))) -+#define REG_GPIO_PXFUN(n) REG32(GPIO_PXFUN((n))) /* 0:GPIO or intr, 1:FUNC */ -+#define REG_GPIO_PXFUNS(n) REG32(GPIO_PXFUNS((n))) -+#define REG_GPIO_PXFUNC(n) REG32(GPIO_PXFUNC((n))) -+#define REG_GPIO_PXSEL(n) REG32(GPIO_PXSEL((n))) /* 0:GPIO/Fun0,1:intr/fun1*/ -+#define REG_GPIO_PXSELS(n) REG32(GPIO_PXSELS((n))) -+#define REG_GPIO_PXSELC(n) REG32(GPIO_PXSELC((n))) -+#define REG_GPIO_PXDIR(n) REG32(GPIO_PXDIR((n))) /* 0:input/low-level-trig/falling-edge-trig, 1:output/high-level-trig/rising-edge-trig */ -+#define REG_GPIO_PXDIRS(n) REG32(GPIO_PXDIRS((n))) -+#define REG_GPIO_PXDIRC(n) REG32(GPIO_PXDIRC((n))) -+#define REG_GPIO_PXTRG(n) REG32(GPIO_PXTRG((n))) /* 0:level-trigger, 1:edge-trigger */ -+#define REG_GPIO_PXTRGS(n) REG32(GPIO_PXTRGS((n))) -+#define REG_GPIO_PXTRGC(n) REG32(GPIO_PXTRGC((n))) -+#define REG_GPIO_PXFLG(n) REG32(GPIO_PXFLG((n))) /* interrupt flag */ -+#define REG_GPIO_PXFLGC(n) REG32(GPIO_PXFLGC((n))) /* interrupt flag */ -+ -+ -+/************************************************************************* -+ * UART -+ *************************************************************************/ -+ -+#define IRDA_BASE UART0_BASE -+#define UART_BASE UART0_BASE -+#define UART_OFF 0x1000 -+ -+/* Register Offset */ -+#define OFF_RDR (0x00) /* R 8b H'xx */ -+#define OFF_TDR (0x00) /* W 8b H'xx */ -+#define OFF_DLLR (0x00) /* RW 8b H'00 */ -+#define OFF_DLHR (0x04) /* RW 8b H'00 */ -+#define OFF_IER (0x04) /* RW 8b H'00 */ -+#define OFF_ISR (0x08) /* R 8b H'01 */ -+#define OFF_FCR (0x08) /* W 8b H'00 */ -+#define OFF_LCR (0x0C) /* RW 8b H'00 */ -+#define OFF_MCR (0x10) /* RW 8b H'00 */ -+#define OFF_LSR (0x14) /* R 8b H'00 */ -+#define OFF_MSR (0x18) /* R 8b H'00 */ -+#define OFF_SPR (0x1C) /* RW 8b H'00 */ -+#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */ -+#define OFF_UMR (0x24) /* RW 8b H'00, UART M Register */ -+#define OFF_UACR (0x28) /* RW 8b H'00, UART Add Cycle Register */ -+ -+/* Register Address */ -+#define UART0_RDR (UART0_BASE + OFF_RDR) -+#define UART0_TDR (UART0_BASE + OFF_TDR) -+#define UART0_DLLR (UART0_BASE + OFF_DLLR) -+#define UART0_DLHR (UART0_BASE + OFF_DLHR) -+#define UART0_IER (UART0_BASE + OFF_IER) -+#define UART0_ISR (UART0_BASE + OFF_ISR) -+#define UART0_FCR (UART0_BASE + OFF_FCR) -+#define UART0_LCR (UART0_BASE + OFF_LCR) -+#define UART0_MCR (UART0_BASE + OFF_MCR) -+#define UART0_LSR (UART0_BASE + OFF_LSR) -+#define UART0_MSR (UART0_BASE + OFF_MSR) -+#define UART0_SPR (UART0_BASE + OFF_SPR) -+#define UART0_SIRCR (UART0_BASE + OFF_SIRCR) -+#define UART0_UMR (UART0_BASE + OFF_UMR) -+#define UART0_UACR (UART0_BASE + OFF_UACR) -+ -+/* -+ * Define macros for UARTIER -+ * UART Interrupt Enable Register -+ */ -+#define UARTIER_RIE (1 << 0) /* 0: receive fifo full interrupt disable */ -+#define UARTIER_TIE (1 << 1) /* 0: transmit fifo empty interrupt disable */ -+#define UARTIER_RLIE (1 << 2) /* 0: receive line status interrupt disable */ -+#define UARTIER_MIE (1 << 3) /* 0: modem status interrupt disable */ -+#define UARTIER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */ -+ -+/* -+ * Define macros for UARTISR -+ * UART Interrupt Status Register -+ */ -+#define UARTISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */ -+#define UARTISR_IID (7 << 1) /* Source of Interrupt */ -+#define UARTISR_IID_MSI (0 << 1) /* Modem status interrupt */ -+#define UARTISR_IID_THRI (1 << 1) /* Transmitter holding register empty */ -+#define UARTISR_IID_RDI (2 << 1) /* Receiver data interrupt */ -+#define UARTISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */ -+#define UARTISR_IID_RTO (6 << 1) /* Receive timeout */ -+#define UARTISR_FFMS (3 << 6) /* FIFO mode select, set when UARTFCR.FE is set to 1 */ -+#define UARTISR_FFMS_NO_FIFO (0 << 6) -+#define UARTISR_FFMS_FIFO_MODE (3 << 6) -+ -+/* -+ * Define macros for UARTFCR -+ * UART FIFO Control Register -+ */ -+#define UARTFCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */ -+#define UARTFCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */ -+#define UARTFCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */ -+#define UARTFCR_DMS (1 << 3) /* 0: disable DMA mode */ -+#define UARTFCR_UUE (1 << 4) /* 0: disable UART */ -+#define UARTFCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */ -+#define UARTFCR_RTRG_1 (0 << 6) -+#define UARTFCR_RTRG_4 (1 << 6) -+#define UARTFCR_RTRG_8 (2 << 6) -+#define UARTFCR_RTRG_15 (3 << 6) -+ -+/* -+ * Define macros for UARTLCR -+ * UART Line Control Register -+ */ -+#define UARTLCR_WLEN (3 << 0) /* word length */ -+#define UARTLCR_WLEN_5 (0 << 0) -+#define UARTLCR_WLEN_6 (1 << 0) -+#define UARTLCR_WLEN_7 (2 << 0) -+#define UARTLCR_WLEN_8 (3 << 0) -+#define UARTLCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 -+ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ -+#define UARTLCR_STOP1 (0 << 2) -+#define UARTLCR_STOP2 (1 << 2) -+#define UARTLCR_PE (1 << 3) /* 0: parity disable */ -+#define UARTLCR_PROE (1 << 4) /* 0: even parity 1: odd parity */ -+#define UARTLCR_SPAR (1 << 5) /* 0: sticky parity disable */ -+#define UARTLCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */ -+#define UARTLCR_DLAB (1 << 7) /* 0: access UARTRDR/TDR/IER 1: access UARTDLLR/DLHR */ -+ -+/* -+ * Define macros for UARTLSR -+ * UART Line Status Register -+ */ -+#define UARTLSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */ -+#define UARTLSR_ORER (1 << 1) /* 0: no overrun error */ -+#define UARTLSR_PER (1 << 2) /* 0: no parity error */ -+#define UARTLSR_FER (1 << 3) /* 0; no framing error */ -+#define UARTLSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */ -+#define UARTLSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */ -+#define UARTLSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */ -+#define UARTLSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */ -+ -+/* -+ * Define macros for UARTMCR -+ * UART Modem Control Register -+ */ -+#define UARTMCR_RTS (1 << 1) /* 0: RTS_ output high, 1: RTS_ output low */ -+#define UARTMCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */ -+#define UARTMCR_MCE (1 << 7) /* 0: modem function is disable */ -+ -+/* -+ * Define macros for UARTMSR -+ * UART Modem Status Register -+ */ -+#define UARTMSR_CCTS (1 << 0) /* 1: a change on CTS_ pin */ -+#define UARTMSR_CTS (1 << 4) /* 0: CTS_ pin is high */ -+ -+/* -+ * Define macros for SIRCR -+ * Slow IrDA Control Register -+ */ -+#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: SIR mode */ -+#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: SIR mode */ -+#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length -+ 1: 0 pulse width is 1.6us for 115.2Kbps */ -+#define SIRCR_TDPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */ -+#define SIRCR_RDPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */ -+ -+ -+/************************************************************************* -+ * AIC (AC97/I2S Controller) -+ *************************************************************************/ -+#define AIC_FR (AIC_BASE + 0x000) -+#define AIC_CR (AIC_BASE + 0x004) -+#define AIC_ACCR1 (AIC_BASE + 0x008) -+#define AIC_ACCR2 (AIC_BASE + 0x00C) -+#define AIC_I2SCR (AIC_BASE + 0x010) -+#define AIC_SR (AIC_BASE + 0x014) -+#define AIC_ACSR (AIC_BASE + 0x018) -+#define AIC_I2SSR (AIC_BASE + 0x01C) -+#define AIC_ACCAR (AIC_BASE + 0x020) -+#define AIC_ACCDR (AIC_BASE + 0x024) -+#define AIC_ACSAR (AIC_BASE + 0x028) -+#define AIC_ACSDR (AIC_BASE + 0x02C) -+#define AIC_I2SDIV (AIC_BASE + 0x030) -+#define AIC_DR (AIC_BASE + 0x034) -+ -+#define REG_AIC_FR REG32(AIC_FR) -+#define REG_AIC_CR REG32(AIC_CR) -+#define REG_AIC_ACCR1 REG32(AIC_ACCR1) -+#define REG_AIC_ACCR2 REG32(AIC_ACCR2) -+#define REG_AIC_I2SCR REG32(AIC_I2SCR) -+#define REG_AIC_SR REG32(AIC_SR) -+#define REG_AIC_ACSR REG32(AIC_ACSR) -+#define REG_AIC_I2SSR REG32(AIC_I2SSR) -+#define REG_AIC_ACCAR REG32(AIC_ACCAR) -+#define REG_AIC_ACCDR REG32(AIC_ACCDR) -+#define REG_AIC_ACSAR REG32(AIC_ACSAR) -+#define REG_AIC_ACSDR REG32(AIC_ACSDR) -+#define REG_AIC_I2SDIV REG32(AIC_I2SDIV) -+#define REG_AIC_DR REG32(AIC_DR) -+ -+/* AIC Controller Configuration Register (AIC_FR) */ -+ -+#define AIC_FR_RFTH_BIT 12 /* Receive FIFO Threshold */ -+#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT) -+#define AIC_FR_TFTH_BIT 8 /* Transmit FIFO Threshold */ -+#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT) -+#define AIC_FR_LSMP (1 << 6) /* Play Zero sample or last sample */ -+#define AIC_FR_ICDC (1 << 5) /* External(0) or Internal CODEC(1) */ -+#define AIC_FR_AUSEL (1 << 4) /* AC97(0) or I2S/MSB-justified(1) */ -+#define AIC_FR_RST (1 << 3) /* AIC registers reset */ -+#define AIC_FR_BCKD (1 << 2) /* I2S BIT_CLK direction, 0:input,1:output */ -+#define AIC_FR_SYNCD (1 << 1) /* I2S SYNC direction, 0:input,1:output */ -+#define AIC_FR_ENB (1 << 0) /* AIC enable bit */ -+ -+/* AIC Controller Common Control Register (AIC_CR) */ -+ -+#define AIC_CR_OSS_BIT 19 /* Output Sample Size from memory (AIC V2 only) */ -+#define AIC_CR_OSS_MASK (0x7 << AIC_CR_OSS_BIT) -+ #define AIC_CR_OSS_8BIT (0x0 << AIC_CR_OSS_BIT) -+ #define AIC_CR_OSS_16BIT (0x1 << AIC_CR_OSS_BIT) -+ #define AIC_CR_OSS_18BIT (0x2 << AIC_CR_OSS_BIT) -+ #define AIC_CR_OSS_20BIT (0x3 << AIC_CR_OSS_BIT) -+ #define AIC_CR_OSS_24BIT (0x4 << AIC_CR_OSS_BIT) -+#define AIC_CR_ISS_BIT 16 /* Input Sample Size from memory (AIC V2 only) */ -+#define AIC_CR_ISS_MASK (0x7 << AIC_CR_ISS_BIT) -+ #define AIC_CR_ISS_8BIT (0x0 << AIC_CR_ISS_BIT) -+ #define AIC_CR_ISS_16BIT (0x1 << AIC_CR_ISS_BIT) -+ #define AIC_CR_ISS_18BIT (0x2 << AIC_CR_ISS_BIT) -+ #define AIC_CR_ISS_20BIT (0x3 << AIC_CR_ISS_BIT) -+ #define AIC_CR_ISS_24BIT (0x4 << AIC_CR_ISS_BIT) -+#define AIC_CR_RDMS (1 << 15) /* Receive DMA enable */ -+#define AIC_CR_TDMS (1 << 14) /* Transmit DMA enable */ -+#define AIC_CR_M2S (1 << 11) /* Mono to Stereo enable */ -+#define AIC_CR_ENDSW (1 << 10) /* Endian switch enable */ -+#define AIC_CR_AVSTSU (1 << 9) /* Signed <-> Unsigned toggle enable */ -+#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ -+#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ -+#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ -+#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ -+#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ -+#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ -+#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ -+#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ -+ -+/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -+ -+#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ -+#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -+ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ -+ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ -+ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ -+ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ -+ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ -+ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ -+#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ -+#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -+ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ -+ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ -+ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ -+ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ -+ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ -+ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ -+ -+/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -+ -+#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ -+#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ -+#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ -+#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ -+#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -+ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ -+#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -+ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ -+#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ -+#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ -+#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ -+ -+/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -+ -+#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ -+#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ -+#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -+ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -+ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -+ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -+ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -+ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -+#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ -+ -+/* AIC Controller FIFO Status Register (AIC_SR) */ -+ -+#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ -+#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) -+#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ -+#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) -+#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ -+#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ -+#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ -+#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ -+ -+/* AIC Controller AC-link Status Register (AIC_ACSR) */ -+ -+#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ -+#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ -+#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ -+#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ -+#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ -+#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ -+ -+/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -+ -+#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ -+ -+/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -+ -+#define AIC_ACCAR_CAR_BIT 0 -+#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -+ -+/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -+ -+#define AIC_ACCDR_CDR_BIT 0 -+#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -+ -+/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -+ -+#define AIC_ACSAR_SAR_BIT 0 -+#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -+ -+/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -+ -+#define AIC_ACSDR_SDR_BIT 0 -+#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -+ -+/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -+ -+#define AIC_I2SDIV_DIV_BIT 0 -+#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -+ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -+ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -+ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -+ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -+ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -+ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -+ -+ -+/************************************************************************* -+ * ICDC (Internal CODEC) -+ *************************************************************************/ -+#define ICDC_CR (ICDC_BASE + 0x0400) /* ICDC Control Register */ -+#define ICDC_APWAIT (ICDC_BASE + 0x0404) /* Anti-Pop WAIT Stage Timing Control Register */ -+#define ICDC_APPRE (ICDC_BASE + 0x0408) /* Anti-Pop HPEN-PRE Stage Timing Control Register */ -+#define ICDC_APHPEN (ICDC_BASE + 0x040C) /* Anti-Pop HPEN Stage Timing Control Register */ -+#define ICDC_APSR (ICDC_BASE + 0x0410) /* Anti-Pop Status Register */ -+#define ICDC_CDCCR1 (ICDC_BASE + 0x0080) -+#define ICDC_CDCCR2 (ICDC_BASE + 0x0084) -+ -+#define REG_ICDC_CR REG32(ICDC_CR) -+#define REG_ICDC_APWAIT REG32(ICDC_APWAIT) -+#define REG_ICDC_APPRE REG32(ICDC_APPRE) -+#define REG_ICDC_APHPEN REG32(ICDC_APHPEN) -+#define REG_ICDC_APSR REG32(ICDC_APSR) -+#define REG_ICDC_CDCCR1 REG32(ICDC_CDCCR1) -+#define REG_ICDC_CDCCR2 REG32(ICDC_CDCCR2) -+ -+/* ICDC Control Register */ -+#define ICDC_CR_LINVOL_BIT 24 /* LINE Input Volume Gain: GAIN=LINVOL*1.5-34.5 */ -+#define ICDC_CR_LINVOL_MASK (0x1f << ICDC_CR_LINVOL_BIT) -+#define ICDC_CR_ASRATE_BIT 20 /* Audio Sample Rate */ -+#define ICDC_CR_ASRATE_MASK (0x0f << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_8000 (0x0 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_11025 (0x1 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_12000 (0x2 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_16000 (0x3 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_22050 (0x4 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_24000 (0x5 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_32000 (0x6 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_44100 (0x7 << ICDC_CR_ASRATE_BIT) -+ #define ICDC_CR_ASRATE_48000 (0x8 << ICDC_CR_ASRATE_BIT) -+#define ICDC_CR_MICBG_BIT 18 /* MIC Boost Gain */ -+#define ICDC_CR_MICBG_MASK (0x3 << ICDC_CR_MICBG_BIT) -+ #define ICDC_CR_MICBG_0DB (0x0 << ICDC_CR_MICBG_BIT) -+ #define ICDC_CR_MICBG_6DB (0x1 << ICDC_CR_MICBG_BIT) -+ #define ICDC_CR_MICBG_12DB (0x2 << ICDC_CR_MICBG_BIT) -+ #define ICDC_CR_MICBG_20DB (0x3 << ICDC_CR_MICBG_BIT) -+#define ICDC_CR_HPVOL_BIT 16 /* Headphone Volume Gain */ -+#define ICDC_CR_HPVOL_MASK (0x3 << ICDC_CR_HPVOL_BIT) -+ #define ICDC_CR_HPVOL_0DB (0x0 << ICDC_CR_HPVOL_BIT) -+ #define ICDC_CR_HPVOL_2DB (0x1 << ICDC_CR_HPVOL_BIT) -+ #define ICDC_CR_HPVOL_4DB (0x2 << ICDC_CR_HPVOL_BIT) -+ #define ICDC_CR_HPVOL_6DB (0x3 << ICDC_CR_HPVOL_BIT) -+#define ICDC_CR_ELINEIN (1 << 13) /* Enable LINE Input */ -+#define ICDC_CR_EMIC (1 << 12) /* Enable MIC Input */ -+#define ICDC_CR_SW1ON (1 << 11) /* Switch 1 in CODEC is on */ -+#define ICDC_CR_EADC (1 << 10) /* Enable ADC */ -+#define ICDC_CR_SW2ON (1 << 9) /* Switch 2 in CODEC is on */ -+#define ICDC_CR_EDAC (1 << 8) /* Enable DAC */ -+#define ICDC_CR_HPMUTE (1 << 5) /* Headphone Mute */ -+#define ICDC_CR_HPTON (1 << 4) /* Headphone Amplifier Trun On */ -+#define ICDC_CR_HPTOFF (1 << 3) /* Headphone Amplifier Trun Off */ -+#define ICDC_CR_TAAP (1 << 2) /* Turn Around of the Anti-Pop Procedure */ -+#define ICDC_CR_EAP (1 << 1) /* Enable Anti-Pop Procedure */ -+#define ICDC_CR_SUSPD (1 << 0) /* CODEC Suspend */ -+ -+/* Anti-Pop WAIT Stage Timing Control Register */ -+#define ICDC_APWAIT_WAITSN_BIT 0 -+#define ICDC_APWAIT_WAITSN_MASK (0x7ff << ICDC_APWAIT_WAITSN_BIT) -+ -+/* Anti-Pop HPEN-PRE Stage Timing Control Register */ -+#define ICDC_APPRE_PRESN_BIT 0 -+#define ICDC_APPRE_PRESN_MASK (0x1ff << ICDC_APPRE_PRESN_BIT) -+ -+/* Anti-Pop HPEN Stage Timing Control Register */ -+#define ICDC_APHPEN_HPENSN_BIT 0 -+#define ICDC_APHPEN_HPENSN_MASK (0x3fff << ICDC_APHPEN_HPENSN_BIT) -+ -+/* Anti-Pop Status Register */ -+#define ICDC_SR_HPST_BIT 14 /* Headphone Amplifier State */ -+#define ICDC_SR_HPST_MASK (0x7 << ICDC_SR_HPST_BIT) -+#define ICDC_SR_HPST_HP_OFF (0x0 << ICDC_SR_HPST_BIT) /* HP amplifier is off */ -+#define ICDC_SR_HPST_TON_WAIT (0x1 << ICDC_SR_HPST_BIT) /* wait state in turn-on */ -+ #define ICDC_SR_HPST_TON_PRE (0x2 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-on */ -+#define ICDC_SR_HPST_TON_HPEN (0x3 << ICDC_SR_HPST_BIT) /* HP enable state in turn-on */ -+ #define ICDC_SR_HPST_TOFF_HPEN (0x4 << ICDC_SR_HPST_BIT) /* HP enable state in turn-off */ -+ #define ICDC_SR_HPST_TOFF_PRE (0x5 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-off */ -+ #define ICDC_SR_HPST_TOFF_WAIT (0x6 << ICDC_SR_HPST_BIT) /* wait state in turn-off */ -+ #define ICDC_SR_HPST_HP_ON (0x7 << ICDC_SR_HPST_BIT) /* HP amplifier is on */ -+#define ICDC_SR_SNCNT_BIT 0 /* Sample Number Counter */ -+#define ICDC_SR_SNCNT_MASK (0x3fff << ICDC_SR_SNCNT_BIT) -+ -+ -+/************************************************************************* -+ * I2C -+ *************************************************************************/ -+#define I2C_DR (I2C_BASE + 0x000) -+#define I2C_CR (I2C_BASE + 0x004) -+#define I2C_SR (I2C_BASE + 0x008) -+#define I2C_GR (I2C_BASE + 0x00C) -+ -+#define REG_I2C_DR REG8(I2C_DR) -+#define REG_I2C_CR REG8(I2C_CR) -+#define REG_I2C_SR REG8(I2C_SR) -+#define REG_I2C_GR REG16(I2C_GR) -+ -+/* I2C Control Register (I2C_CR) */ -+ -+#define I2C_CR_IEN (1 << 4) -+#define I2C_CR_STA (1 << 3) -+#define I2C_CR_STO (1 << 2) -+#define I2C_CR_AC (1 << 1) -+#define I2C_CR_I2CE (1 << 0) -+ -+/* I2C Status Register (I2C_SR) */ -+ -+#define I2C_SR_STX (1 << 4) -+#define I2C_SR_BUSY (1 << 3) -+#define I2C_SR_TEND (1 << 2) -+#define I2C_SR_DRF (1 << 1) -+#define I2C_SR_ACKF (1 << 0) -+ -+ -+/************************************************************************* -+ * SSI -+ *************************************************************************/ -+#define SSI_DR (SSI_BASE + 0x000) -+#define SSI_CR0 (SSI_BASE + 0x004) -+#define SSI_CR1 (SSI_BASE + 0x008) -+#define SSI_SR (SSI_BASE + 0x00C) -+#define SSI_ITR (SSI_BASE + 0x010) -+#define SSI_ICR (SSI_BASE + 0x014) -+#define SSI_GR (SSI_BASE + 0x018) -+ -+#define REG_SSI_DR REG32(SSI_DR) -+#define REG_SSI_CR0 REG16(SSI_CR0) -+#define REG_SSI_CR1 REG32(SSI_CR1) -+#define REG_SSI_SR REG32(SSI_SR) -+#define REG_SSI_ITR REG16(SSI_ITR) -+#define REG_SSI_ICR REG8(SSI_ICR) -+#define REG_SSI_GR REG16(SSI_GR) -+ -+/* SSI Data Register (SSI_DR) */ -+ -+#define SSI_DR_GPC_BIT 0 -+#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -+ -+/* SSI Control Register 0 (SSI_CR0) */ -+ -+#define SSI_CR0_SSIE (1 << 15) -+#define SSI_CR0_TIE (1 << 14) -+#define SSI_CR0_RIE (1 << 13) -+#define SSI_CR0_TEIE (1 << 12) -+#define SSI_CR0_REIE (1 << 11) -+#define SSI_CR0_LOOP (1 << 10) -+#define SSI_CR0_RFINE (1 << 9) -+#define SSI_CR0_RFINC (1 << 8) -+#define SSI_CR0_FSEL (1 << 6) -+#define SSI_CR0_TFLUSH (1 << 2) -+#define SSI_CR0_RFLUSH (1 << 1) -+#define SSI_CR0_DISREV (1 << 0) -+ -+/* SSI Control Register 1 (SSI_CR1) */ -+ -+#define SSI_CR1_FRMHL_BIT 30 -+#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -+ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -+#define SSI_CR1_TFVCK_BIT 28 -+#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -+#define SSI_CR1_TCKFI_BIT 26 -+#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -+#define SSI_CR1_LFST (1 << 25) -+#define SSI_CR1_ITFRM (1 << 24) -+#define SSI_CR1_UNFIN (1 << 23) -+#define SSI_CR1_MULTS (1 << 22) -+#define SSI_CR1_FMAT_BIT 20 -+#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -+ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -+ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -+ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -+ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -+#define SSI_CR1_TTRG_BIT 16 -+#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_8 (1 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_16 (2 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_24 (3 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_32 (4 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_40 (5 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_48 (6 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_56 (7 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_64 (8 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_72 (9 << SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_80 (10<< SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_88 (11<< SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_96 (12<< SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_104 (13<< SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_112 (14<< SSI_CR1_TTRG_BIT) -+ #define SSI_CR1_TTRG_120 (15<< SSI_CR1_TTRG_BIT) -+#define SSI_CR1_MCOM_BIT 12 -+#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -+ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -+ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -+ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -+ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -+ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -+ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -+ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -+ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -+ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -+ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -+ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -+ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -+ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -+ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -+ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -+ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -+#define SSI_CR1_RTRG_BIT 8 -+#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_8 (1 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_16 (2 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_24 (3 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_32 (4 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_40 (5 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_48 (6 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_56 (7 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_64 (8 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_72 (9 << SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_80 (10<< SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_88 (11<< SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_96 (12<< SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_104 (13<< SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_112 (14<< SSI_CR1_RTRG_BIT) -+ #define SSI_CR1_RTRG_120 (15<< SSI_CR1_RTRG_BIT) -+#define SSI_CR1_FLEN_BIT 4 -+#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -+#define SSI_CR1_PHA (1 << 1) -+#define SSI_CR1_POL (1 << 0) -+ -+/* SSI Status Register (SSI_SR) */ -+ -+#define SSI_SR_TFIFONUM_BIT 16 -+#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) -+#define SSI_SR_RFIFONUM_BIT 8 -+#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) -+#define SSI_SR_END (1 << 7) -+#define SSI_SR_BUSY (1 << 6) -+#define SSI_SR_TFF (1 << 5) -+#define SSI_SR_RFE (1 << 4) -+#define SSI_SR_TFHE (1 << 3) -+#define SSI_SR_RFHF (1 << 2) -+#define SSI_SR_UNDR (1 << 1) -+#define SSI_SR_OVER (1 << 0) -+ -+/* SSI Interval Time Control Register (SSI_ITR) */ -+ -+#define SSI_ITR_CNTCLK (1 << 15) -+#define SSI_ITR_IVLTM_BIT 0 -+#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -+ -+ -+/************************************************************************* -+ * MSC -+ *************************************************************************/ -+#define MSC_STRPCL (MSC_BASE + 0x000) -+#define MSC_STAT (MSC_BASE + 0x004) -+#define MSC_CLKRT (MSC_BASE + 0x008) -+#define MSC_CMDAT (MSC_BASE + 0x00C) -+#define MSC_RESTO (MSC_BASE + 0x010) -+#define MSC_RDTO (MSC_BASE + 0x014) -+#define MSC_BLKLEN (MSC_BASE + 0x018) -+#define MSC_NOB (MSC_BASE + 0x01C) -+#define MSC_SNOB (MSC_BASE + 0x020) -+#define MSC_IMASK (MSC_BASE + 0x024) -+#define MSC_IREG (MSC_BASE + 0x028) -+#define MSC_CMD (MSC_BASE + 0x02C) -+#define MSC_ARG (MSC_BASE + 0x030) -+#define MSC_RES (MSC_BASE + 0x034) -+#define MSC_RXFIFO (MSC_BASE + 0x038) -+#define MSC_TXFIFO (MSC_BASE + 0x03C) -+ -+#define REG_MSC_STRPCL REG16(MSC_STRPCL) -+#define REG_MSC_STAT REG32(MSC_STAT) -+#define REG_MSC_CLKRT REG16(MSC_CLKRT) -+#define REG_MSC_CMDAT REG32(MSC_CMDAT) -+#define REG_MSC_RESTO REG16(MSC_RESTO) -+#define REG_MSC_RDTO REG16(MSC_RDTO) -+#define REG_MSC_BLKLEN REG16(MSC_BLKLEN) -+#define REG_MSC_NOB REG16(MSC_NOB) -+#define REG_MSC_SNOB REG16(MSC_SNOB) -+#define REG_MSC_IMASK REG16(MSC_IMASK) -+#define REG_MSC_IREG REG16(MSC_IREG) -+#define REG_MSC_CMD REG8(MSC_CMD) -+#define REG_MSC_ARG REG32(MSC_ARG) -+#define REG_MSC_RES REG16(MSC_RES) -+#define REG_MSC_RXFIFO REG32(MSC_RXFIFO) -+#define REG_MSC_TXFIFO REG32(MSC_TXFIFO) -+ -+/* MSC Clock and Control Register (MSC_STRPCL) */ -+ -+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -+#define MSC_STRPCL_START_READWAIT (1 << 5) -+#define MSC_STRPCL_STOP_READWAIT (1 << 4) -+#define MSC_STRPCL_RESET (1 << 3) -+#define MSC_STRPCL_START_OP (1 << 2) -+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -+ -+/* MSC Status Register (MSC_STAT) */ -+ -+#define MSC_STAT_IS_RESETTING (1 << 15) -+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -+#define MSC_STAT_PRG_DONE (1 << 13) -+#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -+#define MSC_STAT_END_CMD_RES (1 << 11) -+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -+#define MSC_STAT_IS_READWAIT (1 << 9) -+#define MSC_STAT_CLK_EN (1 << 8) -+#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -+#define MSC_STAT_CRC_RES_ERR (1 << 5) -+#define MSC_STAT_CRC_READ_ERROR (1 << 4) -+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -+#define MSC_STAT_TIME_OUT_RES (1 << 1) -+#define MSC_STAT_TIME_OUT_READ (1 << 0) -+ -+/* MSC Bus Clock Control Register (MSC_CLKRT) */ -+ -+#define MSC_CLKRT_CLK_RATE_BIT 0 -+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -+ -+/* MSC Command Sequence Control Register (MSC_CMDAT) */ -+ -+#define MSC_CMDAT_IO_ABORT (1 << 11) -+#define MSC_CMDAT_BUS_WIDTH_BIT 9 -+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -+ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -+ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -+ #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) -+ #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) -+#define MSC_CMDAT_DMA_EN (1 << 8) -+#define MSC_CMDAT_INIT (1 << 7) -+#define MSC_CMDAT_BUSY (1 << 6) -+#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -+#define MSC_CMDAT_WRITE (1 << 4) -+#define MSC_CMDAT_READ (0 << 4) -+#define MSC_CMDAT_DATA_EN (1 << 3) -+#define MSC_CMDAT_RESPONSE_BIT 0 -+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -+ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -+ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -+ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -+ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -+ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -+ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -+ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -+ -+#define CMDAT_DMA_EN (1 << 8) -+#define CMDAT_INIT (1 << 7) -+#define CMDAT_BUSY (1 << 6) -+#define CMDAT_STREAM (1 << 5) -+#define CMDAT_WRITE (1 << 4) -+#define CMDAT_DATA_EN (1 << 3) -+ -+/* MSC Interrupts Mask Register (MSC_IMASK) */ -+ -+#define MSC_IMASK_SDIO (1 << 7) -+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IMASK_END_CMD_RES (1 << 2) -+#define MSC_IMASK_PRG_DONE (1 << 1) -+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -+ -+ -+/* MSC Interrupts Status Register (MSC_IREG) */ -+ -+#define MSC_IREG_SDIO (1 << 7) -+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IREG_END_CMD_RES (1 << 2) -+#define MSC_IREG_PRG_DONE (1 << 1) -+#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -+ -+ -+/************************************************************************* -+ * EMC (External Memory Controller) -+ *************************************************************************/ -+#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ -+#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ -+#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ -+#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ -+#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ -+#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ -+#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ -+#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ -+#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ -+#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ -+ -+#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ -+#define EMC_NFECR (EMC_BASE + 0x100) /* NAND Flash ECC Control Register */ -+#define EMC_NFECC (EMC_BASE + 0x104) /* NAND Flash ECC Data Register */ -+#define EMC_NFPAR0 (EMC_BASE + 0x108) /* NAND Flash RS Parity 0 Register */ -+#define EMC_NFPAR1 (EMC_BASE + 0x10c) /* NAND Flash RS Parity 1 Register */ -+#define EMC_NFPAR2 (EMC_BASE + 0x110) /* NAND Flash RS Parity 2 Register */ -+#define EMC_NFINTS (EMC_BASE + 0x114) /* NAND Flash Interrupt Status Register */ -+#define EMC_NFINTE (EMC_BASE + 0x118) /* NAND Flash Interrupt Enable Register */ -+#define EMC_NFERR0 (EMC_BASE + 0x11c) /* NAND Flash RS Error Report 0 Register */ -+#define EMC_NFERR1 (EMC_BASE + 0x120) /* NAND Flash RS Error Report 1 Register */ -+#define EMC_NFERR2 (EMC_BASE + 0x124) /* NAND Flash RS Error Report 2 Register */ -+#define EMC_NFERR3 (EMC_BASE + 0x128) /* NAND Flash RS Error Report 3 Register */ -+ -+#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ -+#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ -+#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ -+#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ -+#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ -+#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ -+ -+ -+#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -+#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -+#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -+#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -+#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -+#define REG_EMC_SACR0 REG32(EMC_SACR0) -+#define REG_EMC_SACR1 REG32(EMC_SACR1) -+#define REG_EMC_SACR2 REG32(EMC_SACR2) -+#define REG_EMC_SACR3 REG32(EMC_SACR3) -+#define REG_EMC_SACR4 REG32(EMC_SACR4) -+ -+#define REG_EMC_NFCSR REG32(EMC_NFCSR) -+#define REG_EMC_NFECR REG32(EMC_NFECR) -+#define REG_EMC_NFECC REG32(EMC_NFECC) -+#define REG_EMC_NFPAR0 REG32(EMC_NFPAR0) -+#define REG_EMC_NFPAR1 REG32(EMC_NFPAR1) -+#define REG_EMC_NFPAR2 REG32(EMC_NFPAR2) -+#define REG_EMC_NFINTS REG32(EMC_NFINTS) -+#define REG_EMC_NFINTE REG32(EMC_NFINTE) -+#define REG_EMC_NFERR0 REG32(EMC_NFERR0) -+#define REG_EMC_NFERR1 REG32(EMC_NFERR1) -+#define REG_EMC_NFERR2 REG32(EMC_NFERR2) -+#define REG_EMC_NFERR3 REG32(EMC_NFERR3) -+ -+#define REG_EMC_DMCR REG32(EMC_DMCR) -+#define REG_EMC_RTCSR REG16(EMC_RTCSR) -+#define REG_EMC_RTCNT REG16(EMC_RTCNT) -+#define REG_EMC_RTCOR REG16(EMC_RTCOR) -+#define REG_EMC_DMAR0 REG32(EMC_DMAR0) -+ -+/* Static Memory Control Register */ -+#define EMC_SMCR_STRV_BIT 24 -+#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -+#define EMC_SMCR_TAW_BIT 20 -+#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -+#define EMC_SMCR_TBP_BIT 16 -+#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -+#define EMC_SMCR_TAH_BIT 12 -+#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -+#define EMC_SMCR_TAS_BIT 8 -+#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -+#define EMC_SMCR_BW_BIT 6 -+#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -+#define EMC_SMCR_BCM (1 << 3) -+#define EMC_SMCR_BL_BIT 1 -+#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -+#define EMC_SMCR_SMT (1 << 0) -+ -+/* Static Memory Bank Addr Config Reg */ -+#define EMC_SACR_BASE_BIT 8 -+#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -+#define EMC_SACR_MASK_BIT 0 -+#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -+ -+/* NAND Flash Control/Status Register */ -+#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ -+#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ -+#define EMC_NFCSR_NFCE3 (1 << 5) -+#define EMC_NFCSR_NFE3 (1 << 4) -+#define EMC_NFCSR_NFCE2 (1 << 3) -+#define EMC_NFCSR_NFE2 (1 << 2) -+#define EMC_NFCSR_NFCE1 (1 << 1) -+#define EMC_NFCSR_NFE1 (1 << 0) -+ -+/* NAND Flash ECC Control Register */ -+#define EMC_NFECR_PRDY (1 << 4) /* Parity Ready */ -+#define EMC_NFECR_RS_DECODING (0 << 3) /* RS is in decoding phase */ -+#define EMC_NFECR_RS_ENCODING (1 << 3) /* RS is in encoding phase */ -+#define EMC_NFECR_HAMMING (0 << 2) /* Select HAMMING Correction Algorithm */ -+#define EMC_NFECR_RS (1 << 2) /* Select RS Correction Algorithm */ -+#define EMC_NFECR_ERST (1 << 1) /* ECC Reset */ -+#define EMC_NFECR_ECCE (1 << 0) /* ECC Enable */ -+ -+/* NAND Flash ECC Data Register */ -+#define EMC_NFECC_ECC2_BIT 16 -+#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT) -+#define EMC_NFECC_ECC1_BIT 8 -+#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT) -+#define EMC_NFECC_ECC0_BIT 0 -+#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT) -+ -+/* NAND Flash Interrupt Status Register */ -+#define EMC_NFINTS_ERRCNT_BIT 29 /* Error Count */ -+#define EMC_NFINTS_ERRCNT_MASK (0x7 << EMC_NFINTS_ERRCNT_BIT) -+#define EMC_NFINTS_PADF (1 << 4) /* Padding Finished */ -+#define EMC_NFINTS_DECF (1 << 3) /* Decoding Finished */ -+#define EMC_NFINTS_ENCF (1 << 2) /* Encoding Finished */ -+#define EMC_NFINTS_UNCOR (1 << 1) /* Uncorrectable Error Occurred */ -+#define EMC_NFINTS_ERR (1 << 0) /* Error Occurred */ -+ -+/* NAND Flash Interrupt Enable Register */ -+#define EMC_NFINTE_PADFE (1 << 4) /* Padding Finished Interrupt Enable */ -+#define EMC_NFINTE_DECFE (1 << 3) /* Decoding Finished Interrupt Enable */ -+#define EMC_NFINTE_ENCFE (1 << 2) /* Encoding Finished Interrupt Enable */ -+#define EMC_NFINTE_UNCORE (1 << 1) /* Uncorrectable Error Occurred Intr Enable */ -+#define EMC_NFINTE_ERRE (1 << 0) /* Error Occurred Interrupt */ -+ -+/* NAND Flash RS Error Report Register */ -+#define EMC_NFERR_INDEX_BIT 16 /* Error Symbol Index */ -+#define EMC_NFERR_INDEX_MASK (0x1ff << EMC_NFERR_INDEX_BIT) -+#define EMC_NFERR_MASK_BIT 0 /* Error Symbol Value */ -+#define EMC_NFERR_MASK_MASK (0x1ff << EMC_NFERR_MASK_BIT) -+ -+ -+/* DRAM Control Register */ -+#define EMC_DMCR_BW_BIT 31 -+#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -+#define EMC_DMCR_CA_BIT 26 -+#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -+#define EMC_DMCR_RMODE (1 << 25) -+#define EMC_DMCR_RFSH (1 << 24) -+#define EMC_DMCR_MRSET (1 << 23) -+#define EMC_DMCR_RA_BIT 20 -+#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -+#define EMC_DMCR_BA_BIT 19 -+#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -+#define EMC_DMCR_PDM (1 << 18) -+#define EMC_DMCR_EPIN (1 << 17) -+#define EMC_DMCR_TRAS_BIT 13 -+#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -+#define EMC_DMCR_RCD_BIT 11 -+#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -+#define EMC_DMCR_TPC_BIT 8 -+#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -+#define EMC_DMCR_TRWL_BIT 5 -+#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -+#define EMC_DMCR_TRC_BIT 2 -+#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -+#define EMC_DMCR_TCL_BIT 0 -+#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -+ -+/* Refresh Time Control/Status Register */ -+#define EMC_RTCSR_CMF (1 << 7) -+#define EMC_RTCSR_CKS_BIT 0 -+#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -+ -+/* SDRAM Bank Address Configuration Register */ -+#define EMC_DMAR_BASE_BIT 8 -+#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -+#define EMC_DMAR_MASK_BIT 0 -+#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -+ -+/* Mode Register of SDRAM bank 0 */ -+#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ -+#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ -+#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -+ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -+#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ -+#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -+#define EMC_SDMR_BT_BIT 3 /* Burst Type */ -+#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -+ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ -+ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ -+#define EMC_SDMR_BL_BIT 0 /* Burst Length */ -+#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -+ -+#define EMC_SDMR_CAS2_16BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS2_32BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+#define EMC_SDMR_CAS3_16BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS3_32BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+ -+ -+/************************************************************************* -+ * CIM -+ *************************************************************************/ -+#define CIM_CFG (CIM_BASE + 0x0000) -+#define CIM_CTRL (CIM_BASE + 0x0004) -+#define CIM_STATE (CIM_BASE + 0x0008) -+#define CIM_IID (CIM_BASE + 0x000C) -+#define CIM_RXFIFO (CIM_BASE + 0x0010) -+#define CIM_DA (CIM_BASE + 0x0020) -+#define CIM_FA (CIM_BASE + 0x0024) -+#define CIM_FID (CIM_BASE + 0x0028) -+#define CIM_CMD (CIM_BASE + 0x002C) -+ -+#define REG_CIM_CFG REG32(CIM_CFG) -+#define REG_CIM_CTRL REG32(CIM_CTRL) -+#define REG_CIM_STATE REG32(CIM_STATE) -+#define REG_CIM_IID REG32(CIM_IID) -+#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -+#define REG_CIM_DA REG32(CIM_DA) -+#define REG_CIM_FA REG32(CIM_FA) -+#define REG_CIM_FID REG32(CIM_FID) -+#define REG_CIM_CMD REG32(CIM_CMD) -+ -+/* CIM Configuration Register (CIM_CFG) */ -+ -+#define CIM_CFG_INV_DAT (1 << 15) -+#define CIM_CFG_VSP (1 << 14) -+#define CIM_CFG_HSP (1 << 13) -+#define CIM_CFG_PCP (1 << 12) -+#define CIM_CFG_DUMMY_ZERO (1 << 9) -+#define CIM_CFG_EXT_VSYNC (1 << 8) -+#define CIM_CFG_PACK_BIT 4 -+#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) -+#define CIM_CFG_DSM_BIT 0 -+#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -+ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -+ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -+ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -+ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ -+ -+/* CIM Control Register (CIM_CTRL) */ -+ -+#define CIM_CTRL_MCLKDIV_BIT 24 -+#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) -+#define CIM_CTRL_FRC_BIT 16 -+#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -+ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -+ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -+ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -+ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -+ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -+ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -+ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -+ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -+ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -+ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -+ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -+ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -+ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -+ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -+ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -+ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -+#define CIM_CTRL_VDDM (1 << 13) -+#define CIM_CTRL_DMA_SOFM (1 << 12) -+#define CIM_CTRL_DMA_EOFM (1 << 11) -+#define CIM_CTRL_DMA_STOPM (1 << 10) -+#define CIM_CTRL_RXF_TRIGM (1 << 9) -+#define CIM_CTRL_RXF_OFM (1 << 8) -+#define CIM_CTRL_RXF_TRIG_BIT 4 -+#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) -+ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ -+ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ -+ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ -+ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ -+ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ -+ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ -+ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ -+ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ -+#define CIM_CTRL_DMA_EN (1 << 2) -+#define CIM_CTRL_RXF_RST (1 << 1) -+#define CIM_CTRL_ENA (1 << 0) -+ -+/* CIM State Register (CIM_STATE) */ -+ -+#define CIM_STATE_DMA_SOF (1 << 6) -+#define CIM_STATE_DMA_EOF (1 << 5) -+#define CIM_STATE_DMA_STOP (1 << 4) -+#define CIM_STATE_RXF_OF (1 << 3) -+#define CIM_STATE_RXF_TRIG (1 << 2) -+#define CIM_STATE_RXF_EMPTY (1 << 1) -+#define CIM_STATE_VDD (1 << 0) -+ -+/* CIM DMA Command Register (CIM_CMD) */ -+ -+#define CIM_CMD_SOFINT (1 << 31) -+#define CIM_CMD_EOFINT (1 << 30) -+#define CIM_CMD_STOP (1 << 28) -+#define CIM_CMD_LEN_BIT 0 -+#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -+ -+ -+/************************************************************************* -+ * SADC (Smart A/D Controller) -+ *************************************************************************/ -+ -+#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ -+#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ -+#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ -+#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ -+#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ -+#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ -+#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ -+#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ -+#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ -+ -+#define REG_SADC_ENA REG8(SADC_ENA) -+#define REG_SADC_CFG REG32(SADC_CFG) -+#define REG_SADC_CTRL REG8(SADC_CTRL) -+#define REG_SADC_STATE REG8(SADC_STATE) -+#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) -+#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) -+#define REG_SADC_TSDAT REG32(SADC_TSDAT) -+#define REG_SADC_BATDAT REG16(SADC_BATDAT) -+#define REG_SADC_SADDAT REG16(SADC_SADDAT) -+ -+/* ADC Enable Register */ -+#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ -+#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ -+#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ -+#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ -+ -+/* ADC Configure Register */ -+#define SADC_CFG_EXIN (1 << 30) -+#define SADC_CFG_CLKOUT_NUM_BIT 16 -+#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) -+#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ -+#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ -+#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) -+#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ -+#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) -+#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ -+#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) -+#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ -+#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ -+#define SADC_CFG_CMD_BIT 0 /* ADC Command */ -+#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) -+ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ -+ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ -+ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ -+ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ -+ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ -+ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ -+ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ -+ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ -+ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ -+ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ -+ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ -+ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ -+ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ -+ -+/* ADC Control Register */ -+#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ -+#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ -+#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ -+#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ -+#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ -+ -+/* ADC Status Register */ -+#define SADC_STATE_TSBUSY (1 << 7) /* TS A/D is working */ -+#define SADC_STATE_PBATBUSY (1 << 6) /* PBAT A/D is working */ -+#define SADC_STATE_SBUSY (1 << 5) /* SADCIN A/D is working */ -+#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ -+#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ -+#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ -+#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ -+#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ -+ -+/* ADC Touch Screen Data Register */ -+#define SADC_TSDAT_DATA0_BIT 0 -+#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) -+#define SADC_TSDAT_TYPE0 (1 << 15) -+#define SADC_TSDAT_DATA1_BIT 16 -+#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) -+#define SADC_TSDAT_TYPE1 (1 << 31) -+ -+ -+/************************************************************************* -+ * SLCD (Smart LCD Controller) -+ *************************************************************************/ -+ -+#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ -+#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ -+#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ -+#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ -+#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */ -+ -+#define REG_SLCD_CFG REG32(SLCD_CFG) -+#define REG_SLCD_CTRL REG8(SLCD_CTRL) -+#define REG_SLCD_STATE REG8(SLCD_STATE) -+#define REG_SLCD_DATA REG32(SLCD_DATA) -+#define REG_SLCD_FIFO REG32(SLCD_FIFO) -+ -+/* SLCD Configure Register */ -+#define SLCD_CFG_BURST_BIT 14 -+#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT) -+ #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT) -+ #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT) -+#define SLCD_CFG_DWIDTH_BIT 10 -+#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_16BIT (0 << 8) -+#define SLCD_CFG_CWIDTH_8BIT (1 << 8) -+#define SLCD_CFG_CWIDTH_18BIT (2 << 8) -+#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) -+#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) -+#define SLCD_CFG_RS_CMD_LOW (0 << 3) -+#define SLCD_CFG_RS_CMD_HIGH (1 << 3) -+#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) -+#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) -+#define SLCD_CFG_TYPE_PARALLEL (0 << 0) -+#define SLCD_CFG_TYPE_SERIAL (1 << 0) -+ -+/* SLCD Control Register */ -+#define SLCD_CTRL_DMA_EN (1 << 0) -+ -+/* SLCD Status Register */ -+#define SLCD_STATE_BUSY (1 << 0) -+ -+/* SLCD Data Register */ -+#define SLCD_DATA_RS_DATA (0 << 31) -+#define SLCD_DATA_RS_COMMAND (1 << 31) -+ -+/* SLCD FIFO Register */ -+#define SLCD_FIFO_RS_DATA (0 << 31) -+#define SLCD_FIFO_RS_COMMAND (1 << 31) -+ -+ -+/************************************************************************* -+ * LCD (LCD Controller) -+ *************************************************************************/ -+#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ -+#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ -+#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ -+#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ -+#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ -+#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ -+#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ -+#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ -+#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ -+#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ -+#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ -+#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ -+#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ -+#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ -+#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ -+#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ -+#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ -+#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ -+#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ -+#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ -+#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ -+ -+#define REG_LCD_CFG REG32(LCD_CFG) -+#define REG_LCD_VSYNC REG32(LCD_VSYNC) -+#define REG_LCD_HSYNC REG32(LCD_HSYNC) -+#define REG_LCD_VAT REG32(LCD_VAT) -+#define REG_LCD_DAH REG32(LCD_DAH) -+#define REG_LCD_DAV REG32(LCD_DAV) -+#define REG_LCD_PS REG32(LCD_PS) -+#define REG_LCD_CLS REG32(LCD_CLS) -+#define REG_LCD_SPL REG32(LCD_SPL) -+#define REG_LCD_REV REG32(LCD_REV) -+#define REG_LCD_CTRL REG32(LCD_CTRL) -+#define REG_LCD_STATE REG32(LCD_STATE) -+#define REG_LCD_IID REG32(LCD_IID) -+#define REG_LCD_DA0 REG32(LCD_DA0) -+#define REG_LCD_SA0 REG32(LCD_SA0) -+#define REG_LCD_FID0 REG32(LCD_FID0) -+#define REG_LCD_CMD0 REG32(LCD_CMD0) -+#define REG_LCD_DA1 REG32(LCD_DA1) -+#define REG_LCD_SA1 REG32(LCD_SA1) -+#define REG_LCD_FID1 REG32(LCD_FID1) -+#define REG_LCD_CMD1 REG32(LCD_CMD1) -+ -+/* LCD Configure Register */ -+#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ -+#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) -+ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) -+ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) -+#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ -+#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ -+#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ -+#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ -+#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ -+#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ -+#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ -+#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ -+#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ -+#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ -+#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ -+#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ -+#define LCD_CFG_HSP (1 << 11) /* HSYNC pority:0-active high,1-active low */ -+#define LCD_CFG_PCP (1 << 10) /* PCLK pority:0-rising,1-falling */ -+#define LCD_CFG_DEP (1 << 9) /* DE pority:0-active high,1-active low */ -+#define LCD_CFG_VSP (1 << 8) /* VSYNC pority:0-rising,1-falling */ -+#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ -+#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) -+#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ -+ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ -+ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ -+ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ -+#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ -+#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ -+ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) -+ /* JZ47XX defines */ -+ #define LCD_CFG_MODE_SHARP_HR (1 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_CFG_MODE_BIT) -+ -+ -+ -+/* Vertical Synchronize Register */ -+#define LCD_VSYNC_VPS_BIT 16 /* VSYNC pulse start in line clock, fixed to 0 */ -+#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT) -+#define LCD_VSYNC_VPE_BIT 0 /* VSYNC pulse end in line clock */ -+#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT) -+ -+/* Horizontal Synchronize Register */ -+#define LCD_HSYNC_HPS_BIT 16 /* HSYNC pulse start position in dot clock */ -+#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT) -+#define LCD_HSYNC_HPE_BIT 0 /* HSYNC pulse end position in dot clock */ -+#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT) -+ -+/* Virtual Area Setting Register */ -+#define LCD_VAT_HT_BIT 16 /* Horizontal Total size in dot clock */ -+#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT) -+#define LCD_VAT_VT_BIT 0 /* Vertical Total size in dot clock */ -+#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT) -+ -+/* Display Area Horizontal Start/End Point Register */ -+#define LCD_DAH_HDS_BIT 16 /* Horizontal display area start in dot clock */ -+#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT) -+#define LCD_DAH_HDE_BIT 0 /* Horizontal display area end in dot clock */ -+#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT) -+ -+/* Display Area Vertical Start/End Point Register */ -+#define LCD_DAV_VDS_BIT 16 /* Vertical display area start in line clock */ -+#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT) -+#define LCD_DAV_VDE_BIT 0 /* Vertical display area end in line clock */ -+#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT) -+ -+/* PS Signal Setting */ -+#define LCD_PS_PSS_BIT 16 /* PS signal start position in dot clock */ -+#define LCD_PS_PSS_MASK (0xffff << LCD_PS_PSS_BIT) -+#define LCD_PS_PSE_BIT 0 /* PS signal end position in dot clock */ -+#define LCD_PS_PSE_MASK (0xffff << LCD_PS_PSE_BIT) -+ -+/* CLS Signal Setting */ -+#define LCD_CLS_CLSS_BIT 16 /* CLS signal start position in dot clock */ -+#define LCD_CLS_CLSS_MASK (0xffff << LCD_CLS_CLSS_BIT) -+#define LCD_CLS_CLSE_BIT 0 /* CLS signal end position in dot clock */ -+#define LCD_CLS_CLSE_MASK (0xffff << LCD_CLS_CLSE_BIT) -+ -+/* SPL Signal Setting */ -+#define LCD_SPL_SPLS_BIT 16 /* SPL signal start position in dot clock */ -+#define LCD_SPL_SPLS_MASK (0xffff << LCD_SPL_SPLS_BIT) -+#define LCD_SPL_SPLE_BIT 0 /* SPL signal end position in dot clock */ -+#define LCD_SPL_SPLE_MASK (0xffff << LCD_SPL_SPLE_BIT) -+ -+/* REV Signal Setting */ -+#define LCD_REV_REVS_BIT 16 /* REV signal start position in dot clock */ -+#define LCD_REV_REVS_MASK (0xffff << LCD_REV_REVS_BIT) -+ -+/* LCD Control Register */ -+#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ -+#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -+ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ -+ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ -+ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ -+#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode */ -+#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode */ -+#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ -+#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ -+#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -+ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ -+ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ -+ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ -+#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ -+#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -+#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ -+#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ -+#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ -+#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ -+#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ -+#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ -+#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ -+#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ -+#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ -+#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ -+#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ -+#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ -+#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ -+ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ -+ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ -+ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ -+ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ -+ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ -+ -+/* LCD Status Register */ -+#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ -+#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ -+#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ -+#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ -+#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ -+#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ -+#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ -+ -+/* DMA Command Register */ -+#define LCD_CMD_SOFINT (1 << 31) -+#define LCD_CMD_EOFINT (1 << 30) -+#define LCD_CMD_PAL (1 << 28) -+#define LCD_CMD_LEN_BIT 0 -+#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT) -+ -+ -+/************************************************************************* -+ * USB Device -+ *************************************************************************/ -+#define USB_BASE UDC_BASE -+ -+#define USB_REG_FADDR (USB_BASE + 0x00) /* Function Address 8-bit */ -+#define USB_REG_POWER (USB_BASE + 0x01) /* Power Managemetn 8-bit */ -+#define USB_REG_INTRIN (USB_BASE + 0x02) /* Interrupt IN 16-bit */ -+#define USB_REG_INTROUT (USB_BASE + 0x04) /* Interrupt OUT 16-bit */ -+#define USB_REG_INTRINE (USB_BASE + 0x06) /* Intr IN enable 16-bit */ -+#define USB_REG_INTROUTE (USB_BASE + 0x08) /* Intr OUT enable 16-bit */ -+#define USB_REG_INTRUSB (USB_BASE + 0x0a) /* Interrupt USB 8-bit */ -+#define USB_REG_INTRUSBE (USB_BASE + 0x0b) /* Interrupt USB Enable 8-bit */ -+#define USB_REG_FRAME (USB_BASE + 0x0c) /* Frame number 16-bit */ -+#define USB_REG_INDEX (USB_BASE + 0x0e) /* Index register 8-bit */ -+#define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ -+ -+#define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ -+#define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ -+#define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ -+#define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ -+#define USB_REG_OUTMAXP (USB_BASE + 0x14) /* EP1 OUT Max Pkt Size 16-bit */ -+#define USB_REG_OUTCSR (USB_BASE + 0x16) /* EP1 OUT CSR LSB 8/16bit */ -+#define USB_REG_OUTCSRH (USB_BASE + 0x17) /* EP1 OUT CSR MSB 8-bit */ -+#define USB_REG_OUTCOUNT (USB_BASE + 0x18) /* bytes in EP0/1 OUT FIFO 16-bit */ -+ -+#define USB_FIFO_EP0 (USB_BASE + 0x20) -+#define USB_FIFO_EP1 (USB_BASE + 0x24) -+#define USB_FIFO_EP2 (USB_BASE + 0x28) -+ -+#define USB_REG_EPINFO (USB_BASE + 0x78) /* Endpoint information */ -+#define USB_REG_RAMINFO (USB_BASE + 0x79) /* RAM information */ -+ -+#define USB_REG_INTR (USB_BASE + 0x200) /* DMA pending interrupts */ -+#define USB_REG_CNTL1 (USB_BASE + 0x204) /* DMA channel 1 control */ -+#define USB_REG_ADDR1 (USB_BASE + 0x208) /* DMA channel 1 AHB memory addr */ -+#define USB_REG_COUNT1 (USB_BASE + 0x20c) /* DMA channel 1 byte count */ -+#define USB_REG_CNTL2 (USB_BASE + 0x214) /* DMA channel 2 control */ -+#define USB_REG_ADDR2 (USB_BASE + 0x218) /* DMA channel 2 AHB memory addr */ -+#define USB_REG_COUNT2 (USB_BASE + 0x21c) /* DMA channel 2 byte count */ -+ -+ -+/* Power register bit masks */ -+#define USB_POWER_SUSPENDM 0x01 -+#define USB_POWER_RESUME 0x04 -+#define USB_POWER_HSMODE 0x10 -+#define USB_POWER_HSENAB 0x20 -+#define USB_POWER_SOFTCONN 0x40 -+ -+/* Interrupt register bit masks */ -+#define USB_INTR_SUSPEND 0x01 -+#define USB_INTR_RESUME 0x02 -+#define USB_INTR_RESET 0x04 -+ -+#define USB_INTR_EP0 0x0001 -+#define USB_INTR_INEP1 0x0002 -+#define USB_INTR_INEP2 0x0004 -+#define USB_INTR_OUTEP1 0x0002 -+ -+/* CSR0 bit masks */ -+#define USB_CSR0_OUTPKTRDY 0x01 -+#define USB_CSR0_INPKTRDY 0x02 -+#define USB_CSR0_SENTSTALL 0x04 -+#define USB_CSR0_DATAEND 0x08 -+#define USB_CSR0_SETUPEND 0x10 -+#define USB_CSR0_SENDSTALL 0x20 -+#define USB_CSR0_SVDOUTPKTRDY 0x40 -+#define USB_CSR0_SVDSETUPEND 0x80 -+ -+/* Endpoint CSR register bits */ -+#define USB_INCSRH_AUTOSET 0x80 -+#define USB_INCSRH_ISO 0x40 -+#define USB_INCSRH_MODE 0x20 -+#define USB_INCSRH_DMAREQENAB 0x10 -+#define USB_INCSRH_DMAREQMODE 0x04 -+#define USB_INCSR_CDT 0x40 -+#define USB_INCSR_SENTSTALL 0x20 -+#define USB_INCSR_SENDSTALL 0x10 -+#define USB_INCSR_FF 0x08 -+#define USB_INCSR_UNDERRUN 0x04 -+#define USB_INCSR_FFNOTEMPT 0x02 -+#define USB_INCSR_INPKTRDY 0x01 -+#define USB_OUTCSRH_AUTOCLR 0x80 -+#define USB_OUTCSRH_ISO 0x40 -+#define USB_OUTCSRH_DMAREQENAB 0x20 -+#define USB_OUTCSRH_DNYT 0x10 -+#define USB_OUTCSRH_DMAREQMODE 0x08 -+#define USB_OUTCSR_CDT 0x80 -+#define USB_OUTCSR_SENTSTALL 0x40 -+#define USB_OUTCSR_SENDSTALL 0x20 -+#define USB_OUTCSR_FF 0x10 -+#define USB_OUTCSR_DATAERR 0x08 -+#define USB_OUTCSR_OVERRUN 0x04 -+#define USB_OUTCSR_FFFULL 0x02 -+#define USB_OUTCSR_OUTPKTRDY 0x01 -+ -+/* Testmode register bits */ -+#define USB_TEST_SE0NAK 0x01 -+#define USB_TEST_J 0x02 -+#define USB_TEST_K 0x04 -+#define USB_TEST_PACKET 0x08 -+ -+/* DMA control bits */ -+#define USB_CNTL_ENA 0x01 -+#define USB_CNTL_DIR_IN 0x02 -+#define USB_CNTL_MODE_1 0x04 -+#define USB_CNTL_INTR_EN 0x08 -+#define USB_CNTL_EP(n) ((n) << 4) -+#define USB_CNTL_BURST_0 (0 << 9) -+#define USB_CNTL_BURST_4 (1 << 9) -+#define USB_CNTL_BURST_8 (2 << 9) -+#define USB_CNTL_BURST_16 (3 << 9) -+ -+#endif /* __JZ4740_REGS_H__ */ -diff --git a/include/asm-mips/mach-jz4740/serial.h b/include/asm-mips/mach-jz4740/serial.h -new file mode 100644 -index 0000000..c4819b9 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/serial.h -@@ -0,0 +1,30 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/serial.h -+ * -+ * Ingenic's JZ4740 common include. -+ * -+ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_BOARD_SERIAL_H__ -+#define __ASM_BOARD_SERIAL_H__ -+ -+#ifndef CONFIG_SERIAL_MANY_PORTS -+#undef RS_TABLE_SIZE -+#define RS_TABLE_SIZE 1 -+#endif -+ -+#define JZ_BASE_BAUD (12000000/16) -+ -+#define JZ_SERIAL_PORT_DEFNS \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -+ -+#endif /* __ASM_BORAD_SERIAL_H__ */ -diff --git a/include/asm-mips/mach-jz4740/war.h b/include/asm-mips/mach-jz4740/war.h -new file mode 100644 -index 0000000..3a5bc17 ---- /dev/null -+++ b/include/asm-mips/mach-jz4740/war.h -@@ -0,0 +1,25 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -+ */ -+#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -+#define __ASM_MIPS_MACH_JZ4740_WAR_H -+ -+#define R4600_V1_INDEX_ICACHEOP_WAR 0 -+#define R4600_V1_HIT_CACHEOP_WAR 0 -+#define R4600_V2_HIT_CACHEOP_WAR 0 -+#define R5432_CP0_INTERRUPT_WAR 0 -+#define BCM1250_M3_WAR 0 -+#define SIBYTE_1956_WAR 0 -+#define MIPS4K_ICACHE_REFILL_WAR 0 -+#define MIPS_CACHE_SYNC_WAR 0 -+#define TX49XX_ICACHE_INDEX_INV_WAR 0 -+#define RM9000_CDEX_SMP_WAR 0 -+#define ICACHE_REFILLS_WORKAROUND_WAR 0 -+#define R10000_LLSC_WAR 0 -+#define MIPS34K_MISSED_ITLB_WAR 0 -+ -+#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -diff --git a/include/asm-mips/mach-jz4750/board-apus.h b/include/asm-mips/mach-jz4750/board-apus.h -new file mode 100644 -index 0000000..18bba40 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/board-apus.h -@@ -0,0 +1,119 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/board-apus.h -+ * -+ * JZ4750-based APUS board ver 1.x definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_APUS_H__ -+#define __ASM_JZ4750_APUS_H__ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 24000000 /* Main extal freq: 24 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_DISP_OFF_N (32*4+25) /* GPE25 */ -+#define GPIO_SD0_VCC_EN_N (32*2+10) /* GPC10 */ -+#define GPIO_SD0_CD_N (32*2+11) /* GPC11 */ -+#define GPIO_SD0_WP (32*2+12) /* GPC12 */ -+#define GPIO_SD1_VCC_EN_N (32*2+13) /* GPC13 */ -+#define GPIO_SD1_CD_N (32*2+14) /* GPC14 */ -+#define GPIO_USB_DETE (32*2+11) /* GPC15 */ -+#define GPIO_DC_DETE_N (32*2+8) /* GPC8 */ -+#define GPIO_CHARG_STAT_N (32*2+9) /* GPC9 */ -+#define GPIO_LCD_VCC_EN_N (32*3+30) /* GPC10 */ -+#define GPIO_LCD_PWM (32*4+24) /* GPE24 */ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+ -+/*====================================================================== -+ * LCD backlight -+ */ -+#define LCD_PWM_CHN 4 /* pwm channel */ -+#define LCD_PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_set_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_clear_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC0_WP_PIN GPIO_SD0_WP -+#define MSC0_HOTPLUG_PIN GPIO_SD0_CD_N -+#define MSC0_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD0_CD_N) -+ -+#define MSC1_WP_PIN GPIO_SD1_WP -+#define MSC1_HOTPLUG_PIN GPIO_SD1_CD_N -+#define MSC1_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD1_CD_N) -+ -+#define __msc0_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD0_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD0_CD_N); \ -+} while (0) -+ -+#define __msc0_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD0_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#define __msc1_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD1_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD1_CD_N); \ -+} while (0) -+ -+#define __msc1_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_card_detected(s) \ -+({ \ -+ int detected = 0; \ -+ if (__gpio_get_pin(GPIO_SD1_CD_N)) \ -+ detected = 1; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4750_APUS_H__ */ -diff --git a/include/asm-mips/mach-jz4750/board-fuwa.h b/include/asm-mips/mach-jz4750/board-fuwa.h -new file mode 100644 -index 0000000..8b6a199 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/board-fuwa.h -@@ -0,0 +1,93 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/board-fuwa.h -+ * -+ * JZ4750-based FUWA board ver 1.x definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_FUWA_H__ -+#define __ASM_JZ4750_FUWA_H__ -+ -+#define CONFIG_FPGA /* fuwa is an FPGA board */ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 48000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ -+#define GPIO_SD_CD_N 110 /* GPD14 */ -+#define GPIO_SD_WP 112 /* GPD16 */ -+#define GPIO_USB_DETE 102 /* GPD6 */ -+#define GPIO_DC_DETE_N 103 /* GPD7 */ -+#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -+#define GPIO_DISP_OFF_N 121 /* GPD25, LCD_REV */ -+#define GPIO_LED_EN 124 /* GPD28 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+/*====================================================================== -+ * LCD backlight -+ */ -+#define GPIO_LCD_PWM (32*4+20) /* GPE20 */ -+ -+#define LCD_PWM_CHN 0 /* pwm channel */ -+#define LCD_PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_set_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_clear_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC_WP_PIN GPIO_SD_WP -+#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -+#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -+ -+#define __msc_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD_CD_N); \ -+} while (0) -+ -+#define __msc_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -+} while (0) -+ -+#define __msc_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4750_FUWA_H__ */ -diff --git a/include/asm-mips/mach-jz4750/clock.h b/include/asm-mips/mach-jz4750/clock.h -new file mode 100644 -index 0000000..5747e45 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/clock.h -@@ -0,0 +1,204 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/clock.h -+ * -+ * JZ4750 clocks definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_CLOCK_H__ -+#define __ASM_JZ4750_CLOCK_H__ -+ -+#ifndef JZ_EXTAL -+#define JZ_EXTAL 12000000 /* 3.6864 MHz */ -+#endif -+#ifndef JZ_EXTAL2 -+#define JZ_EXTAL2 32768 /* 32.768 KHz */ -+#endif -+ -+/* -+ * JZ4750 clocks structure -+ */ -+typedef struct { -+ unsigned int cclk; /* CPU clock */ -+ unsigned int hclk; /* System bus clock */ -+ unsigned int pclk; /* Peripheral bus clock */ -+ unsigned int mclk; /* Flash/SRAM/SDRAM clock */ -+ unsigned int lcdclk; /* LCDC module clock */ -+ unsigned int pixclk; /* LCD pixel clock */ -+ unsigned int i2sclk; /* AIC module clock */ -+ unsigned int usbclk; /* USB module clock */ -+ unsigned int mscclk; /* MSC module clock */ -+ unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -+ unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ -+} jz_clocks_t; -+ -+extern jz_clocks_t jz_clocks; -+ -+ -+/* PLL output frequency */ -+static __inline__ unsigned int __cpm_get_pllout(void) -+{ -+ unsigned long m, n, no, pllout; -+ unsigned long cppcr = REG_CPM_CPPCR; -+ unsigned long od[4] = {1, 2, 2, 4}; -+ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { -+ m = __cpm_get_pllm() + 2; -+ n = __cpm_get_plln() + 2; -+ no = od[__cpm_get_pllod()]; -+ pllout = ((JZ_EXTAL) / (n * no)) * m; -+ } else -+ pllout = JZ_EXTAL; -+ return pllout; -+} -+ -+/* PLL output frequency for MSC/I2S/LCD/USB */ -+static __inline__ unsigned int __cpm_get_pllout2(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_PCS) -+ return __cpm_get_pllout(); -+ else -+ return __cpm_get_pllout()/2; -+} -+ -+/* CPU core clock */ -+static __inline__ unsigned int __cpm_get_cclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_cdiv()]; -+} -+ -+/* AHB system bus clock */ -+static __inline__ unsigned int __cpm_get_hclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_hdiv()]; -+} -+ -+/* Memory bus clock */ -+static __inline__ unsigned int __cpm_get_mclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_mdiv()]; -+} -+ -+/* APB peripheral bus clock */ -+static __inline__ unsigned int __cpm_get_pclk(void) -+{ -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_pdiv()]; -+} -+ -+/* LCDC module clock */ -+static __inline__ unsigned int __cpm_get_lcdclk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); -+} -+ -+/* LCD pixel clock */ -+static __inline__ unsigned int __cpm_get_pixclk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); -+} -+ -+/* I2S clock */ -+static __inline__ unsigned int __cpm_get_i2sclk(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { -+ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); -+ } -+ else { -+ return JZ_EXTAL; -+ } -+} -+ -+/* USB clock */ -+static __inline__ unsigned int __cpm_get_usbclk(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { -+ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); -+ } -+ else { -+ return JZ_EXTAL; -+ } -+} -+ -+/* -+ * MSC clock -+ * @n: the index of MMC/SD controller -+ */ -+static __inline__ unsigned int __cpm_get_mscclk(int n) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_mscdiv(n) + 1); -+} -+ -+/* EXTAL clock */ -+static __inline__ unsigned int __cpm_get_extalclk0(void) -+{ -+ return JZ_EXTAL; -+} -+ -+/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -+static __inline__ unsigned int __cpm_get_extalclk(void) -+{ -+#if defined(CONFIG_FPGA) -+ return JZ_EXTAL; -+#else -+ if (REG_CPM_CPCCR & CPM_CPCCR_ECS) -+ return __cpm_get_extalclk0()/2; -+ else -+ return __cpm_get_extalclk0(); -+#endif -+} -+ -+/* RTC clock for CPM,INTC,RTC,TCU,WDT */ -+static __inline__ unsigned int __cpm_get_rtcclk(void) -+{ -+ return JZ_EXTAL2; -+} -+ -+/* -+ * Output 24MHz for SD and 16MHz for MMC. -+ * @n: the index of MMC/SD controller -+ */ -+static inline void __cpm_select_msc_clk(int n, int sd) -+{ -+ unsigned int pllout2 = __cpm_get_pllout2(); -+ unsigned int div = 0; -+ -+ if (sd) { -+ div = pllout2 / 24000000; -+ } -+ else { -+ div = pllout2 / 16000000; -+ } -+ -+ REG_CPM_MSCCDR(n) = div - 1; -+ REG_CPM_CPCCR |= CPM_CPCCR_CE; -+} -+ -+/* -+ * Output 48MHz for high speed card. -+ */ -+static inline void __cpm_select_msc_clk_high(int n, int sd) -+{ -+ unsigned int pllout2 = __cpm_get_pllout2(); -+ unsigned int div = 0; -+ -+ div = pllout2 / 48000000; -+ -+ REG_CPM_MSCCDR(n) = div - 1; -+ REG_CPM_CPCCR |= CPM_CPCCR_CE; -+} -+ -+#endif /* __ASM_JZ4750_CLOCK_H__ */ -diff --git a/include/asm-mips/mach-jz4750/dma.h b/include/asm-mips/mach-jz4750/dma.h -new file mode 100644 -index 0000000..fc1f2c8 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/dma.h -@@ -0,0 +1,307 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/dma.h -+ * -+ * JZ4750 DMA definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_DMA_H__ -+#define __ASM_JZ4750_DMA_H__ -+ -+#include -+#include /* need byte IO */ -+#include /* And spinlocks */ -+#include -+#include -+ -+/* -+ * Descriptor structure for JZ4750 DMA engine -+ * Note: this structure must always be aligned to a 16-bytes boundary. -+ */ -+ -+/* old descriptor 4-word */ -+typedef struct { -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+ volatile u32 dsadr; /* DSAR value for the current transfer */ -+ volatile u32 dtadr; /* DTAR value for the current transfer */ -+ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -+} jz_dma_desc; -+ -+/* new descriptor 8-word */ -+typedef struct { -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+ volatile u32 dsadr; /* DSAR value for the current transfer */ -+ volatile u32 dtadr; /* DTAR value for the current transfer */ -+ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -+ volatile u32 dstrd; /* DMA source and target stride address */ -+ volatile u32 dreqt; /* DMA request type for current transfer */ -+ volatile u32 reserved0; /* Reserved */ -+ volatile u32 reserved1; /* Reserved */ -+} jz_dma_desc_8word; -+ -+/* DMA Device ID's follow */ -+enum { -+ DMA_ID_EXT = 0, /* External request with DREQn */ -+ DMA_ID_NAND, /* NAND DMA request */ -+ DMA_ID_BCH_ENC, /* BCH Encoding DMA request */ -+ DMA_ID_BCH_DEC, /* BCH Decoding DMA request */ -+ DMA_ID_AUTO, /* Auto-request */ -+// DMA_ID_TSSI_RX, /* TSSI receive fifo full request */ -+ DMA_ID_UART3_TX, /* UART3 transmit-fifo-empty request */ -+ DMA_ID_UART3_RX, /* UART3 receve-fifo-full request */ -+ DMA_ID_UART2_TX, /* UART2 transmit-fifo-empty request */ -+ DMA_ID_UART2_RX, /* UART2 receve-fifo-full request */ -+ DMA_ID_UART1_TX, /* UART1 transmit-fifo-empty request */ -+ DMA_ID_UART1_RX, /* UART1 receve-fifo-full request */ -+ DMA_ID_UART0_TX, /* UART0 transmit-fifo-empty request */ -+ DMA_ID_UART0_RX, /* UART0 receve-fifo-full request */ -+ DMA_ID_SSI0_TX, /* SSI0 transmit-fifo-full request */ -+ DMA_ID_SSI0_RX, /* SSI0 receive-fifo-empty request */ -+ DMA_ID_AIC_TX, /* AIC transmit-fifo-full request */ -+ DMA_ID_AIC_RX, /* AIC receive-fifo-empty request */ -+ DMA_ID_MSC0_TX, /* MSC0 transmit-fifo-full request */ -+ DMA_ID_MSC0_RX, /* MSC0 receive-fifo-empty request */ -+ DMA_ID_TCU_OVERFLOW, /* TCU channel n overflow interrupt */ -+ DMA_ID_SADC, /* SADC transfer request */ -+ DMA_ID_MSC1_TX, /* MSC1 transmit-fifo-full request */ -+ DMA_ID_MSC1_RX, /* MSC1 receive-fifo-empty request */ -+ DMA_ID_SSI1_TX, /* SSI1 transmit-fifo-full request */ -+ DMA_ID_SSI1_RX, /* SSI1 receive-fifo-empty request */ -+ DMA_ID_PCM_TX, /* PM transmit-fifo-full request */ -+ DMA_ID_PCM_RX, /* PM receive-fifo-empty request */ -+ DMA_ID_RAW_SET, -+ DMA_ID_MAX -+}; -+ -+/* DMA modes, simulated by sw */ -+#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ -+#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ -+#define DMA_AUTOINIT 0x2 -+#define DMA_MODE_MASK 0x3 -+ -+struct jz_dma_chan { -+ int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ -+ unsigned int io; /* DMA channel number */ -+ const char *dev_str; /* string describes the DMA channel */ -+ int irq; /* DMA irq number */ -+ void *irq_dev; /* DMA private device structure */ -+ unsigned int fifo_addr; /* physical fifo address of the requested device */ -+ unsigned int cntl; /* DMA controll */ -+ unsigned int mode; /* DMA configuration */ -+ unsigned int source; /* DMA request source */ -+}; -+ -+extern struct jz_dma_chan jz_dma_table[]; -+ -+ -+#define DMA_8BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_8BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_32_32BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+#define DMA_AIC_32_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_32_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_TX_CMD_UC \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+extern int jz_request_dma(int dev_id, -+ const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id); -+extern void jz_free_dma(unsigned int dmanr); -+ -+extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data); -+extern void dump_jz_dma_channel(unsigned int dmanr); -+ -+extern void enable_dma(unsigned int dmanr); -+extern void disable_dma(unsigned int dmanr); -+extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); -+extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); -+extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -+extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern void jz_set_dma_src_width(int dmanr, int nbit); -+extern void jz_set_dma_dest_width(int dmanr, int nbit); -+extern void jz_set_dma_block_size(int dmanr, int nbyte); -+extern unsigned int get_dma_residue(unsigned int dmanr); -+ -+extern spinlock_t dma_spin_lock; -+ -+static __inline__ unsigned long claim_dma_lock(void) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&dma_spin_lock, flags); -+ return flags; -+} -+ -+static __inline__ void release_dma_lock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&dma_spin_lock, flags); -+} -+ -+/* Clear the 'DMA Pointer Flip Flop'. -+ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -+ */ -+#define clear_dma_ff(channel) -+ -+static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -+{ -+ if (dmanr > MAX_DMA_NUM -+ || jz_dma_table[dmanr].dev_id < 0) -+ return NULL; -+ return &jz_dma_table[dmanr]; -+} -+ -+static __inline__ int dma_halted(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 1; -+ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -+} -+ -+static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ return chan->mode; -+} -+ -+static __inline__ void clear_dma_done(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+} -+ -+static __inline__ void clear_dma_halt(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -+ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT); -+} -+ -+static __inline__ void clear_dma_flag(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); -+} -+ -+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -+{ -+} -+ -+static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -+{ -+ unsigned long dccsr; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ dccsr = REG_DMAC_DCCSR(chan->io); -+ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+} -+ -+static __inline__ int get_dma_done_irq(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return -1; -+ return chan->irq; -+} -+ -+#endif /* __ASM_JZ4750_DMA_H__ */ -diff --git a/include/asm-mips/mach-jz4750/jz4750.h b/include/asm-mips/mach-jz4750/jz4750.h -new file mode 100644 -index 0000000..9517780 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/jz4750.h -@@ -0,0 +1,44 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/jz4750.h -+ * -+ * JZ4750 common definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_H__ -+#define __ASM_JZ4750_H__ -+ -+#include -+#include -+#include -+#include -+ -+/*------------------------------------------------------------------ -+ * Platform definitions -+ */ -+#ifdef CONFIG_JZ4750_FUWA -+#include -+#endif -+ -+#ifdef CONFIG_JZ4750_APUS -+#include -+#endif -+ -+/* Add other platform definition here ... */ -+ -+ -+/*------------------------------------------------------------------ -+ * Follows are related to platform definitions -+ */ -+ -+#include -+#include -+ -+#endif /* __ASM_JZ4750_H__ */ -diff --git a/include/asm-mips/mach-jz4750/misc.h b/include/asm-mips/mach-jz4750/misc.h -new file mode 100644 -index 0000000..f6c75c9 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/misc.h -@@ -0,0 +1,44 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/misc.h -+ * -+ * Ingenic's JZ4750 common include. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_MISC_H__ -+#define __ASM_JZ4750_MISC_H__ -+ -+/*========================================================== -+ * I2C -+ *===========================================================*/ -+ -+#define I2C_EEPROM_DEV 0xA /* b'1010 */ -+#define I2C_RTC_DEV 0xD /* b'1101 */ -+#define DIMM0_SPD_ADDR 0 -+#define DIMM1_SPD_ADDR 1 -+#define DIMM2_SPD_ADDR 2 -+#define DIMM3_SPD_ADDR 3 -+#define JZ_HCI_ADDR 7 -+ -+#define DIMM_SPD_LEN 128 -+#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ -+#define I2C_RTC_LEN 16 -+#define HCI_MAC_OFFSET 64 -+ -+extern void i2c_open(void); -+extern void i2c_close(void); -+extern void i2c_setclk(unsigned int i2cclk); -+ -+extern int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+extern int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+ -+#endif /* __ASM_JZ4750_MISC_H__ */ -diff --git a/include/asm-mips/mach-jz4750/ops.h b/include/asm-mips/mach-jz4750/ops.h -new file mode 100644 -index 0000000..c345ed2 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/ops.h -@@ -0,0 +1,3570 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750/ops.h -+ * -+ * JZ4750 register definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef __JZ4750_OPS_H__ -+#define __JZ4750_OPS_H__ -+ -+/* -+ * Definition of Module Operations -+ */ -+ -+/*************************************************************************** -+ * EMC -+ ***************************************************************************/ -+#define is_share_mode() ((REG_EMC_BCR & EMC_BCR_BSR_MASK) == EMC_BCR_BSR_SHARE) -+#define is_normal_order() (!(REG_EMC_BCR & EMC_BCR_PK_SEL)) -+ -+/*************************************************************************** -+ * GPIO -+ ***************************************************************************/ -+ -+//------------------------------------------------------ -+// GPIO Pins Description -+// -+// PORT 0: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 D0 - -+// 1 D1 - -+// 2 D2 - -+// 3 D3 - -+// 4 D4 - -+// 5 D5 - -+// 6 D6 - -+// 7 D7 - -+// 8 D8 - -+// 9 D9 - -+// 10 D10 - -+// 11 D11 - -+// 12 D12 - -+// 13 D13 - -+// 14 D14 - -+// 15 D15 - -+// 16 D16 - -+// 17 D17 - -+// 18 D18 - -+// 19 D19 - -+// 20 D20 - -+// 21 D21 - -+// 22 D22 - -+// 23 D23 - -+// 24 D24 - -+// 25 D25 - -+// 26 D26 - -+// 27 D27 - -+// 28 D28 - -+// 29 D29 - -+// 30 D30 - -+// 31 D31 - -+// -+//------------------------------------------------------ -+// PORT 1: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 A0 - -+// 1 A1 - -+// 2 A2 - -+// 3 A3 - -+// 4 A4 - -+// 5 A5 - -+// 6 A6 - -+// 7 A7 - -+// 8 A8 - -+// 9 A9 - -+// 10 A10 - -+// 11 A11 - -+// 12 A12 - -+// 13 A13 - -+// 14 A14 - -+// 15 A15/CLE SA3 -+// 16 DCS0# - -+// 17 RAS# - -+// 18 CAS# - -+// 19 RDWE#/BUFD# - -+// 20 WE0# - -+// 21 WE1# - -+// 22 WE2# - -+// 23 WE3# - -+// 24 CKO - Note1 -+// 25 CKE - -+// 26 SSI0_CLK - -+// 27 SSI0_DT - -+// 28 SSI0_DR - -+// 29 SSI0_CE0# - -+// 30 SSI0_CE1#_GPC - -+// 31 SSI0_CE2# - -+// -+// Note1: BIT24: it is CKO when chip is reset -+// -+//------------------------------------------------------ -+// PORT 2: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 SD0 A20 -+// 1 SD1 A21 -+// 2 SD2 A22 -+// 3 SD3 A23 -+// 4 SD4 A24 -+// 5 SD5 A25 -+// 6 SD6 - -+// 7 SD7 - -+// 8 SD8 TSDI0 -+// 9 SD9 TSDI1 -+// 10 SD10 TSDI2 -+// 11 SD11 TSDI3 -+// 12 SD12 TSDI4 -+// 13 SD13 TSDI5 -+// 14 SD14 TSDI6 -+// 15 SD15 TSDI7 -+// 16 A16/ALE SA4 -+// 17 SA0 A17 -+// 18 SA1 A18 -+// 19 SA2 A19 -+// 20 WAIT# - Note2 -+// 21 CS1# - -+// 22 CS2# - -+// 23 CS3# - -+// 24 CS4# - -+// 25 RD# - -+// 26 WR# - -+// 27 FRB# - Note3 -+// 28 FRE# - -+// 29 FWE# - -+// 30 BOOT_SEL0 - Note4 -+// 31 BOOT_SEL1 - Note5 -+// -+// Note2: BIT20: it is WAIT# pin when chip is reset -+// -+// Note3: BIT27: when NAND is used, it should connect to NANF FRB#. -+// -+// Note4: BIT30: it is BOOT_SEL0 when chip is reset, it can used as output GPIO. -+// -+// Note5: BIT31: it is BOOT_SEL1 when chip is reset, it can used as general GPIO. -+// -+//------------------------------------------------------ -+// PORT 3: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 LCD_D0 - -+// 1 LCD_D1 - -+// 2 LCD_D2 - -+// 3 LCD_D3 - -+// 4 LCD_D4 - -+// 5 LCD_D5 - -+// 6 LCD_D6 - -+// 7 LCD_D7 - -+// 8 LCD_D8 - -+// 9 LCD_D9 - -+// 10 LCD_D10 - -+// 11 LCD_D11 - -+// 12 LCD_D12 - -+// 13 LCD_D13 - -+// 14 LCD_D14 - -+// 15 LCD_D15 - -+// 16 LCD_D16 - -+// 17 LCD_D17 - -+// 18 LCD_PCLK - -+// 19 LCD_HSYNC - -+// 20 LCD_VSYNC - -+// 21 LCD_DE - -+// 22 LCD_CLS - -+// 23 LCD_SPL - -+// 24 LCD_PS - -+// 25 LCD_REV - -+// 26 SSI1_CLK - -+// 27 SSI1_DT - -+// 28 SSI1_DR - -+// 29 SSI1_CE0# - -+// 30 SSI1_CE1# - -+// 31 - - -+// -+//------------------------------------------------------ -+// PORT 4: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 CIM_D0 - -+// 1 CIM_D1 - -+// 2 CIM_D2 - -+// 3 CIM_D3 - -+// 4 CIM_D4 - -+// 5 CIM_D5 - -+// 6 CIM_D6 - -+// 7 CIM_D7 - -+// 8 CIM_MCLK - -+// 9 CIM_PCLK - -+// 10 CIM_VSYNC - -+// 11 CIM_HSYNC - -+// 12 I2C_SDA - -+// 13 I2C_SCK - -+// 14 - - -+// 15 - - -+// 16 UART1_RxD - -+// 17 UART1_TxD - -+// 18 UART1_CTS PCM_DIN -+// 19 UART1_RTS PCM_DOUT -+// 20 PWM0 PCM_CLK -+// 21 PWM1 PCM_SYN -+// 22 PWM2 SCLK_RSTN -+// 23 PWM3 BCLK -+// 24 PWM4 SYNC -+// 25 PWM5 OWI -+// 26 SDATO UART2_TxD -+// 27 SDATI UART2_RxD -+// 28 DCS1# - -+// 29 - - -+// 30 WKUP - Note6 -+// 31 - - Note7 -+// -+// Note6: BIT30: it is only used as input and interrupt, and with no pull-up and pull-down -+// -+// Note7: BIT31: it is used to select the function of UART or JTAG set by PESEL[31] -+// PESEL[31] = 0, select JTAG function -+// PESEL[31] = 1, select UART function -+// -+//------------------------------------------------------ -+// PORT 5: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 MSC0_D0 - -+// 1 MSC0_D1 - -+// 2 MSC0_D2 DREQ -+// 3 MSC0_D3 DACK -+// 4 MSC0_D4 UART0_RxD -+// 5 MSC0_D5 UART0_TxD -+// 6 MSC0_D6 UART0_CTS -+// 7 MSC0_D7 UART0_RTS -+// 8 MSC0_CLK - -+// 9 MSC0_CMD - -+// 10 MSC1_D0 - -+// 11 MSC1_D1 - -+// 12 MSC1_D2 - -+// 13 MSC1_D3 - -+// 14 MSC1_CLK - -+// 15 MSC1_CMD - -+// 16 UART3_RxD - -+// 17 UART3_TxD - -+// 18 UART3_CTS - -+// 19 UART3_RTS - -+// 20 TSCLK - -+// 21 TSSTR - -+// 22 TSFRM - -+// 23 TSFAIL - -+// 24 - - -+// 25 - - -+// 26 - - -+// 27 - - -+// 28 - - -+// 29 - - -+// 30 - - -+// 31 - - -+// -+////////////////////////////////////////////////////////// -+ -+/* -+ * p is the port number (0,1,2,3,4,5) -+ * o is the pin offset (0-31) inside the port -+ * n is the absolute number of a pin (0-191), regardless of the port -+ */ -+ -+//------------------------------------------- -+// Function Pins Mode -+ -+#define __gpio_as_func0(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXSELC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_func1(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+} while (0) -+ -+/* -+ * D0 ~ D31, A0 ~ A14, DCS0#, RAS#, CAS#, -+ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -+ */ -+#define __gpio_as_sdram_32bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -+ REG_GPIO_PXSELC(0) = 0xffffffff; \ -+ REG_GPIO_PXPES(0) = 0xffffffff; \ -+ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -+} while (0) -+ -+/* -+ * D0 ~ D15, A0 ~ A14, DCS0#, RAS#, CAS#, -+ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -+ */ -+#define __gpio_as_sdram_16bit() \ -+do { \ -+ if (is_normal_order()) { \ -+ /* 32/16-bit data normal order */ \ -+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -+ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -+ REG_GPIO_PXPES(0) = 0x0000ffff; \ -+ } else { \ -+ /* 16-bit data special order */ \ -+ REG_GPIO_PXFUNS(0) = 0x00ffff00; \ -+ REG_GPIO_PXSELC(0) = 0x00ffff00; \ -+ REG_GPIO_PXPES(0) = 0x00ffff00; \ -+ } \ -+ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -+} while (0) -+ -+/* -+ * D0 ~ D7, CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# -+ * @n: chip select number(1 ~ 4) -+ */ -+#define __gpio_as_nand_8bit(n) \ -+do { \ -+ if (!is_share_mode()) { \ -+ /* unshare mode */ \ -+ REG_GPIO_PXFUNS(2) = 0x000000ff; /* SD0~SD7 */ \ -+ REG_GPIO_PXSELS(2) = 0x000000ff; \ -+ REG_GPIO_PXPES(2) = 0x000000ff; \ -+ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(SA3) */ \ -+ REG_GPIO_PXSELS(1) = 0x00008000; \ -+ REG_GPIO_PXPES(1) = 0x00008000; \ -+ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(SA4) */ \ -+ REG_GPIO_PXSELS(2) = 0x00010000; \ -+ REG_GPIO_PXPES(2) = 0x00010000; \ -+ } else { \ -+ /* share mode */ \ -+ if (is_normal_order()) { \ -+ /* 32/16-bit data normal order */ \ -+ REG_GPIO_PXFUNS(0) = 0x000000ff; /* D0~D7 */ \ -+ REG_GPIO_PXSELC(0) = 0x000000ff; \ -+ REG_GPIO_PXPES(0) = 0x000000ff; \ -+ } else { \ -+ /* 16-bit data special order */ \ -+ REG_GPIO_PXFUNS(0) = 0x0000ff00; /* D0~D7 */ \ -+ REG_GPIO_PXSELC(0) = 0x0000ff00; \ -+ REG_GPIO_PXPES(0) = 0x0000ff00; \ -+ } \ -+ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(A15) */ \ -+ REG_GPIO_PXSELC(1) = 0x00008000; \ -+ REG_GPIO_PXPES(1) = 0x00008000; \ -+ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(A16) */ \ -+ REG_GPIO_PXSELC(2) = 0x00010000; \ -+ REG_GPIO_PXPES(2) = 0x00010000; \ -+ } \ -+ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -+ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -+ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -+ \ -+ REG_GPIO_PXFUNS(1) = 0x00080000; /* RDWE#/BUFD# */ \ -+ REG_GPIO_PXSELC(1) = 0x00080000; \ -+ REG_GPIO_PXPES(1) = 0x00080000; \ -+ REG_GPIO_PXFUNS(2) = 0x30000000; /* FRE#, FWE# */ \ -+ REG_GPIO_PXSELC(2) = 0x30000000; \ -+ REG_GPIO_PXPES(2) = 0x30000000; \ -+ REG_GPIO_PXFUNC(2) = 0x08000000; /* FRB#(input) */ \ -+ REG_GPIO_PXSELC(2) = 0x08000000; \ -+ REG_GPIO_PXDIRC(2) = 0x08000000; \ -+ REG_GPIO_PXPES(2) = 0x08000000; \ -+} while (0) -+ -+ -+/* -+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 -+ * @n: chip select number(1 ~ 4) -+ */ -+#define __gpio_as_nor_8bit(n) \ -+do { \ -+ if (is_normal_order()) { \ -+ /* 32/16-bit data normal order */ \ -+ REG_GPIO_PXFUNS(0) = 0x000000ff; \ -+ REG_GPIO_PXSELC(0) = 0x000000ff; \ -+ REG_GPIO_PXPES(0) = 0x000000ff; \ -+ } else { \ -+ /* 16-bit data special order */ \ -+ REG_GPIO_PXFUNS(0) = 0x0000ff00; \ -+ REG_GPIO_PXSELC(0) = 0x0000ff00; \ -+ REG_GPIO_PXPES(0) = 0x0000ff00; \ -+ } \ -+ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -+ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -+ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -+ \ -+ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -+ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -+ REG_GPIO_PXPES(1) = 0x0000ffff; \ -+ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -+ REG_GPIO_PXSELC(2) = 0x06110007; \ -+ REG_GPIO_PXPES(2) = 0x06110007; \ -+ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -+ REG_GPIO_PXSELS(2) = 0x000e0000; \ -+ REG_GPIO_PXPES(2) = 0x000e0000; \ -+} while (0) -+ -+/* -+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 -+ * @n: chip select number(1 ~ 4) -+ */ -+#define __gpio_as_nor_16bit(n) \ -+do { \ -+ if (is_normal_order()) { \ -+ /* 32/16-bit data normal order */ \ -+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -+ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -+ REG_GPIO_PXPES(0) = 0x0000ffff; \ -+ } else { \ -+ /* 16-bit data special order */ \ -+ REG_GPIO_PXFUNS(0) = 0x00ffff00; \ -+ REG_GPIO_PXSELC(0) = 0x00ffff00; \ -+ REG_GPIO_PXPES(0) = 0x00ffff00; \ -+ } \ -+ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -+ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -+ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -+ \ -+ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -+ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -+ REG_GPIO_PXPES(1) = 0x0000ffff; \ -+ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -+ REG_GPIO_PXSELC(2) = 0x06110007; \ -+ REG_GPIO_PXPES(2) = 0x06110007; \ -+ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -+ REG_GPIO_PXSELS(2) = 0x000e0000; \ -+ REG_GPIO_PXPES(2) = 0x000e0000; \ -+} while (0) -+ -+/* -+ * UART0_TxD, UART0_RxD -+ */ -+#define __gpio_as_uart0() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x00000030; \ -+ REG_GPIO_PXSELS(5) = 0x00000030; \ -+ REG_GPIO_PXPES(5) = 0x00000030; \ -+} while (0) -+ -+/* -+ * UART0_TxD, UART0_RxD, UART0_CTS, UART0_RTS -+ */ -+#define __gpio_as_uart0_ctsrts() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x000000f0; \ -+ REG_GPIO_PXSELS(5) = 0x000000f0; \ -+ REG_GPIO_PXPES(5) = 0x000000f0; \ -+} while (0) -+ -+/* -+ * UART1_TxD, UART1_RxD -+ */ -+#define __gpio_as_uart1() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00030000; \ -+ REG_GPIO_PXSELC(4) = 0x00030000; \ -+ REG_GPIO_PXPES(4) = 0x00030000; \ -+} while (0) -+ -+/* -+ * UART1_TxD, UART1_RxD, UART1_CTS, UART1_RTS -+ */ -+#define __gpio_as_uart1_ctsrts() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x000f0000; \ -+ REG_GPIO_PXSELC(4) = 0x000f0000; \ -+ REG_GPIO_PXPES(4) = 0x000f0000; \ -+} while (0) -+ -+/* -+ * UART2_TxD, UART2_RxD -+ */ -+#define __gpio_as_uart2() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x0c000000; \ -+ REG_GPIO_PXSELS(4) = 0x0c000000; \ -+ REG_GPIO_PXPES(4) = 0x0c000000; \ -+} while (0) -+ -+/* -+ * UART3_TxD, UART3_RxD -+ */ -+#define __gpio_as_uart3() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x00030000; \ -+ REG_GPIO_PXSELC(5) = 0x00030000; \ -+ REG_GPIO_PXPES(5) = 0x00030000; \ -+} while (0) -+ -+/* -+ * UART3_TxD, UART3_RxD, UART3_CTS, UART3_RTS -+ */ -+#define __gpio_as_uart3_ctsrts() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x000f0000; \ -+ REG_GPIO_PXSELC(5) = 0x000f0000; \ -+ REG_GPIO_PXPES(5) = 0x000f0000; \ -+} while (0) -+ -+/* -+ * TSCLK, TSSTR, TSFRM, TSFAIL, TSDI0~7 -+ */ -+#define __gpio_as_tssi() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x0000ff00; \ -+ REG_GPIO_PXSELS(2) = 0x0000ff00; \ -+ REG_GPIO_PXPES(2) = 0x0000ff00; \ -+ REG_GPIO_PXFUNS(5) = 0x00f00000; \ -+ REG_GPIO_PXSELC(5) = 0x00f00000; \ -+ REG_GPIO_PXPES(5) = 0x00f00000; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D7, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_8bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003c00ff; \ -+ REG_GPIO_PXSELC(3) = 0x003c00ff; \ -+ REG_GPIO_PXPES(3) = 0x003c00ff; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_16bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003cffff; \ -+ REG_GPIO_PXSELC(3) = 0x003cffff; \ -+ REG_GPIO_PXPES(3) = 0x003cffff; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_18bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003fffff; \ -+ REG_GPIO_PXSELC(3) = 0x003fffff; \ -+ REG_GPIO_PXPES(3) = 0x003fffff; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D17, LCD_D_R1, LCD_D_G0, LCD_D_G1, LCD_D_B1, -+ * LCD_D_R0, LCD_D_B0, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_24bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003fffff; \ -+ REG_GPIO_PXSELC(3) = 0x003fffff; \ -+ REG_GPIO_PXPES(3) = 0x003fffff; \ -+ REG_GPIO_PXFUNS(3) = 0x03c00000; \ -+ REG_GPIO_PXSELS(3) = 0x03c00000; \ -+ REG_GPIO_PXPES(3) = 0x03c00000; \ -+ REG_GPIO_PXFUNS(5) = 0x000c0000; \ -+ REG_GPIO_PXSELS(5) = 0x000c0000; \ -+ REG_GPIO_PXPES(5) = 0x000c0000; \ -+} while (0) -+ -+/* -+ * SLCD_DAT0~7, SLCD_CLK, SLCD_RS, SLCD_CS -+ */ -+#define __gpio_as_lcd_smart_pal_8bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x001c00ff; \ -+ REG_GPIO_PXSELC(3) = 0x001c00ff; \ -+ REG_GPIO_PXPES(3) = 0x001c00ff; \ -+} while (0) -+ -+/* -+ * SLCD_DAT0~15, SLCD_CLK, SLCD_RS, SLCD_CS -+ */ -+#define __gpio_as_lcd_smart_pal_15bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x001cffff; \ -+ REG_GPIO_PXSELC(3) = 0x001cffff; \ -+ REG_GPIO_PXPES(3) = 0x001cffff; \ -+} while (0) -+ -+/* -+ * SLCD_DAT0~17, SLCD_CLK, SLCD_RS, SLCD_CS -+ */ -+#define __gpio_as_lcd_smart_pal_17bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x001fffff; \ -+ REG_GPIO_PXSELC(3) = 0x001fffff; \ -+ REG_GPIO_PXPES(3) = 0x001fffff; \ -+} while (0) -+ -+/* -+ * SLCD_DAT15, SLCD_CLK, SLCD_RS, SLCD_CS -+ */ -+#define __gpio_as_lcd_smart_serial() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x001c8000; \ -+ REG_GPIO_PXSELC(3) = 0x001c8000; \ -+ REG_GPIO_PXPES(3) = 0x001c8000; \ -+} while (0) -+ -+/* -+ * LCD_CLS, LCD_SPL, LCD_PS, LCD_REV -+ */ -+#define __gpio_as_lcd_special() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x03C00000; \ -+ REG_GPIO_PXSELC(3) = 0x03C00000; \ -+ REG_GPIO_PXPES(3) = 0x03C00000; \ -+} while (0) -+ -+/* -+ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC -+ */ -+#define __gpio_as_cim() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00000fff; \ -+ REG_GPIO_PXSELC(4) = 0x00000fff; \ -+ REG_GPIO_PXPES(4) = 0x00000fff; \ -+} while (0) -+ -+/* -+ * SDATO, SDATI, BCLK, SYNC, SCLK_RSTN(gpio sepc) or -+ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET(aic spec) -+ */ -+#define __gpio_as_aic() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x0c000000; \ -+ REG_GPIO_PXSELS(4) = 0x0c000000; \ -+ REG_GPIO_PXPES(4) = 0x0c000000; \ -+ REG_GPIO_PXFUNS(4) = 0x00e00000; \ -+ REG_GPIO_PXSELC(4) = 0x00e00000; \ -+ REG_GPIO_PXPES(4) = 0x00e00000; \ -+} while (0) -+ -+/* -+ * PCM_DIN, PCM_DOUT, PCM_CLK, PCM_SYN -+*/ -+#define __gpio_as_pcm() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x003c0000; \ -+ REG_GPIO_PXSELS(4) = 0x003c0000; \ -+ REG_GPIO_PXPES(4) = 0x003c0000; \ -+} while (0) -+ -+/* -+ * OWI -+*/ -+#define __gpio_as_owi() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x02000000; \ -+ REG_GPIO_PXSELS(4) = 0x02000000; \ -+ REG_GPIO_PXPES(4) = 0x02000000; \ -+} while (0) -+ -+/* -+ * MSC0_CMD, MSC0_CLK, MSC0_D0 ~ MSC0_D3 -+ */ -+#define __gpio_as_msc0_4bit() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x0000030f; \ -+ REG_GPIO_PXSELC(5) = 0x0000030f; \ -+ REG_GPIO_PXPES(5) = 0x0000030f; \ -+} while (0) -+ -+/* -+ * MSC0_CMD, MSC0_CLK, MSC0_D0 ~ MSC0_D7 -+ */ -+#define __gpio_as_msc0_8bit() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x000003ff; \ -+ REG_GPIO_PXSELC(5) = 0x000003ff; \ -+ REG_GPIO_PXPES(5) = 0x000003ff; \ -+} while (0) -+ -+/* -+ * MSC1_CMD, MSC1_CLK, MSC1_D0 ~ MSC1_D3 -+ */ -+#define __gpio_as_msc1_4bit() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x0000fc00; \ -+ REG_GPIO_PXSELC(5) = 0x0000fc00; \ -+ REG_GPIO_PXPES(5) = 0x0000fc00; \ -+} while (0) -+ -+#define __gpio_as_msc __gpio_as_msc0_8bit /* default as msc0 8bit */ -+#define __gpio_as_msc0 __gpio_as_msc0_8bit /* msc0 default as 8bit */ -+#define __gpio_as_msc1 __gpio_as_msc1_4bit /* msc1 only support 4bit */ -+ -+/* -+ * SSI0_CE0, SSI0_CE1#_GPC, SSI0_CE2, SSI0_CLK, SSI0_DT, SSI0_DR -+ */ -+#define __gpio_as_ssi0() \ -+do { \ -+ REG_GPIO_PXFUNS(1) = 0xfc000000; \ -+ REG_GPIO_PXSELC(1) = 0xfc000000; \ -+ REG_GPIO_PXPES(1) = 0xfc000000; \ -+} while (0) -+ -+/* -+ * SSI1_CE0, SSI1_CE1, SSI1_CLK, SSI1_DT, SSI1_DR -+ */ -+#define __gpio_as_ssi1() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x7c000000; \ -+ REG_GPIO_PXSELC(3) = 0x7c000000; \ -+ REG_GPIO_PXPES(3) = 0x7c000000; \ -+} while (0) -+ -+/* n = 0(SSI0), 1(SSI1) */ -+#define __gpio_as_ssi(n) __gpio_as_ssi##n() -+ -+/* -+ * I2C_SCK, I2C_SDA -+ */ -+#define __gpio_as_i2c() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00003000; \ -+ REG_GPIO_PXSELC(4) = 0x00003000; \ -+ REG_GPIO_PXPES(4) = 0x00003000; \ -+} while (0) -+ -+/* -+ * PWM0 -+ */ -+#define __gpio_as_pwm0() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00100000; \ -+ REG_GPIO_PXSELC(4) = 0x00100000; \ -+ REG_GPIO_PXPES(4) = 0x00100000; \ -+} while (0) -+ -+/* -+ * PWM1 -+ */ -+#define __gpio_as_pwm1() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00200000; \ -+ REG_GPIO_PXSELC(4) = 0x00200000; \ -+ REG_GPIO_PXPES(4) = 0x00200000; \ -+} while (0) -+ -+/* -+ * PWM2 -+ */ -+#define __gpio_as_pwm2() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00400000; \ -+ REG_GPIO_PXSELC(4) = 0x00400000; \ -+ REG_GPIO_PXPES(4) = 0x00400000; \ -+} while (0) -+ -+/* -+ * PWM3 -+ */ -+#define __gpio_as_pwm3() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00800000; \ -+ REG_GPIO_PXSELC(4) = 0x00800000; \ -+ REG_GPIO_PXPES(4) = 0x00800000; \ -+} while (0) -+ -+/* -+ * PWM4 -+ */ -+#define __gpio_as_pwm4() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x01000000; \ -+ REG_GPIO_PXSELC(4) = 0x01000000; \ -+ REG_GPIO_PXPES(4) = 0x01000000; \ -+} while (0) -+ -+/* -+ * PWM5 -+ */ -+#define __gpio_as_pwm5() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x02000000; \ -+ REG_GPIO_PXSELC(4) = 0x02000000; \ -+ REG_GPIO_PXPES(4) = 0x02000000; \ -+} while (0) -+ -+/* -+ * n = 0 ~ 5 -+ */ -+#define __gpio_as_pwm(n) __gpio_as_pwm##n() -+ -+/* -+ * DREQ -+ */ -+#define __gpio_as_dreq() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x00000004; \ -+ REG_GPIO_PXSELS(5) = 0x00000004; \ -+ REG_GPIO_PXPES(5) = 0x00000004; \ -+} while (0) -+ -+/* -+ * DACK -+ */ -+#define __gpio_as_dack() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x00000008; \ -+ REG_GPIO_PXSELS(5) = 0x00000008; \ -+ REG_GPIO_PXPES(5) = 0x00000008; \ -+} while (0) -+ -+/* -+ * GPIO or Interrupt Mode -+ */ -+#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) -+ -+#define __gpio_port_as_output(p, o) \ -+do { \ -+ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -+ REG_GPIO_PXSELC(p) = (1 << (o)); \ -+ REG_GPIO_PXDIRS(p) = (1 << (o)); \ -+} while (0) -+ -+#define __gpio_port_as_input(p, o) \ -+do { \ -+ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -+ REG_GPIO_PXSELC(p) = (1 << (o)); \ -+ REG_GPIO_PXDIRC(p) = (1 << (o)); \ -+} while (0) -+ -+#define __gpio_as_output(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_output(p, o); \ -+} while (0) -+ -+#define __gpio_as_input(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_input(p, o); \ -+} while (0) -+ -+#define __gpio_set_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXDATS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_clear_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXDATC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_get_pin(n) \ -+({ \ -+ unsigned int p, o, v; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ if (__gpio_get_port(p) & (1 << o)) \ -+ v = 1; \ -+ else \ -+ v = 0; \ -+ v; \ -+}) -+ -+#define __gpio_as_irq_high_level(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRS(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_low_level(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRC(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_rise_edge(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRS(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_fall_edge(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRC(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_mask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_unmask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_ack_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_get_irq() \ -+({ \ -+ unsigned int p, i, tmp, v = 0; \ -+ for (p = 3; p >= 0; p--) { \ -+ tmp = REG_GPIO_PXFLG(p); \ -+ for (i = 0; i < 32; i++) \ -+ if (tmp & (1 << i)) \ -+ v = (32*p + i); \ -+ } \ -+ v; \ -+}) -+ -+#define __gpio_group_irq(n) \ -+({ \ -+ register int tmp, i; \ -+ tmp = REG_GPIO_PXFLG((n)); \ -+ for (i=31;i>=0;i--) \ -+ if (tmp & (1 << i)) \ -+ break; \ -+ i; \ -+}) -+ -+#define __gpio_enable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXPEC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_disable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXPES(p) = (1 << o); \ -+} while (0) -+ -+ -+/*************************************************************************** -+ * CPM -+ ***************************************************************************/ -+#define __cpm_get_pllm() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) -+#define __cpm_get_plln() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) -+#define __cpm_get_pllod() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) -+ -+#define __cpm_get_cdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) -+#define __cpm_get_hdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) -+#define __cpm_get_pdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) -+#define __cpm_get_mdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) -+#define __cpm_get_ldiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) -+#define __cpm_get_udiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) -+#define __cpm_get_i2sdiv() \ -+ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) -+#define __cpm_get_pixdiv() \ -+ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) -+#define __cpm_get_mscdiv(n) \ -+ ((REG_CPM_MSCCDR(n) & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) -+#define __cpm_get_uhcdiv() \ -+ ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) -+#define __cpm_get_ssidiv() \ -+ ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) -+#define __cpm_get_pcmdiv(v) \ -+ ((REG_CPM_PCMCDR & CPM_PCMCDR_PCMCD_MASK) >> CPM_PCMCDR_PCMCD_BIT) -+ -+#define __cpm_set_cdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) -+#define __cpm_set_hdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) -+#define __cpm_set_pdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) -+#define __cpm_set_mdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) -+#define __cpm_set_ldiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) -+#define __cpm_set_udiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) -+#define __cpm_set_i2sdiv(v) \ -+ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) -+#define __cpm_set_pixdiv(v) \ -+ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) -+#define __cpm_set_mscdiv(n, v) \ -+ (REG_CPM_MSCCDR(n) = (REG_CPM_MSCCDR(n) & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) -+#define __cpm_set_uhcdiv(v) \ -+ (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) -+#define __cpm_set_ssidiv(v) \ -+ (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) -+#define __cpm_set_pcmdiv(v) \ -+ (REG_CPM_PCMCDR = (REG_CPM_PCMCDR & ~CPM_PCMCDR_PCMCD_MASK) | ((v) << (CPM_PCMCDR_PCMCD_BIT))) -+ -+#define __cpm_select_pcmclk_pll() (REG_CPM_PCMCDR |= CPM_PCMCDR_PCMS) -+#define __cpm_select_pcmclk_exclk() (REG_CPM_PCMCDR &= ~CPM_PCMCDR_PCMS) -+#define __cpm_select_pixclk_ext() (REG_CPM_LPCDR |= CPM_LPCDR_LPCS) -+#define __cpm_select_pixclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LPCS) -+#define __cpm_select_tveclk_exclk() (REG_CPM_LPCDR |= CPM_CPCCR_LSCS) -+#define __cpm_select_tveclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LSCS) -+#define __cpm_select_pixclk_lcd() (REG_CPM_LPCDR &= ~CPM_LPCDR_LTCS) -+#define __cpm_select_pixclk_tve() (REG_CPM_LPCDR |= CPM_LPCDR_LTCS) -+#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) -+#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) -+#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) -+#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) -+ -+#define __cpm_enable_cko() -+#define __cpm_exclk_direct() (REG_CPM_CPCCR &= ~CPM_CPCCR_ECS) -+#define __cpm_exclk_div2() (REG_CPM_CPCCR |= CPM_CPCCR_ECS) -+#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) -+#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) -+#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) -+#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) -+ -+#define __cpm_pll_is_off() (REG_CPM_CPPSR & CPM_CPPSR_PLLOFF) -+#define __cpm_pll_is_on() (REG_CPM_CPPSR & CPM_CPPSR_PLLON) -+#define __cpm_pll_bypass() (REG_CPM_CPPSR |= CPM_CPPSR_PLLBP) -+ -+#define __cpm_get_cclk_doze_duty() \ -+ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) -+#define __cpm_set_cclk_doze_duty(v) \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) -+ -+#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) -+#define __cpm_idle_mode() \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) -+#define __cpm_sleep_mode() \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -+ -+#define __cpm_stop_all() (REG_CPM_CLKGR = 0x1fffffff) -+#define __cpm_stop_cimram() (REG_CPM_CLKGR |= CPM_CLKGR_CIMRAM) -+#define __cpm_stop_idct() (REG_CPM_CLKGR |= CPM_CLKGR_IDCT) -+#define __cpm_stop_db() (REG_CPM_CLKGR |= CPM_CLKGR_DB) -+#define __cpm_stop_me() (REG_CPM_CLKGR |= CPM_CLKGR_ME) -+#define __cpm_stop_mc() (REG_CPM_CLKGR |= CPM_CLKGR_MC) -+#define __cpm_stop_tve() (REG_CPM_CLKGR |= CPM_CLKGR_TVE) -+#define __cpm_stop_tssi() (REG_CPM_CLKGR |= CPM_CLKGR_TSSI) -+#define __cpm_stop_owi() (REG_CPM_CLKGR |= CPM_CLKGR_OWI) -+#define __cpm_stop_pcm() (REG_CPM_CLKGR |= CPM_CLKGR_PCM) -+#define __cpm_stop_uart3() (REG_CPM_CLKGR |= CPM_CLKGR_UART3) -+#define __cpm_stop_uart2() (REG_CPM_CLKGR |= CPM_CLKGR_UART2) -+#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -+#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -+#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) -+#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -+#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -+#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -+#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) -+#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -+#define __cpm_stop_msc(n) (REG_CPM_CLKGR |= CPM_CLKGR_MSC##n) -+#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) -+#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -+#define __cpm_stop_ssi(n) (REG_CPM_CLKGR |= CPM_CLKGR_SSI##n) -+#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -+#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -+#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -+#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) -+ -+#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -+#define __cpm_start_cimram() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIMRAM) -+#define __cpm_start_idct() (REG_CPM_CLKGR &= ~CPM_CLKGR_IDCT) -+#define __cpm_start_db() (REG_CPM_CLKGR &= ~CPM_CLKGR_DB) -+#define __cpm_start_me() (REG_CPM_CLKGR &= ~CPM_CLKGR_ME) -+#define __cpm_start_mc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MC) -+#define __cpm_start_tve() (REG_CPM_CLKGR &= ~CPM_CLKGR_TVE) -+#define __cpm_start_tssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_TSSI) -+#define __cpm_start_owi() (REG_CPM_CLKGR &= ~CPM_CLKGR_OWI) -+#define __cpm_start_pcm() (REG_CPM_CLKGR &= ~CPM_CLKGR_PCM) -+#define __cpm_start_uart3() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART3) -+#define __cpm_start_uart2() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART2) -+#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) -+#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) -+#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -+#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) -+#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) -+#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) -+#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -+#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) -+#define __cpm_start_msc(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC##n) -+#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -+#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) -+#define __cpm_start_ssi(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI##n) -+#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) -+#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) -+#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -+#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) -+ -+#define __cpm_get_o1st() \ -+ ((REG_CPM_OPCR & CPM_OPCR_O1ST_MASK) >> CPM_OPCR_O1ST_BIT) -+#define __cpm_set_o1st(v) \ -+ (REG_CPM_OPCR = (REG_CPM_OPCR & ~CPM_OPCR_O1ST_MASK) | ((v) << (CPM_OPCR_O1ST_BIT))) -+#define __cpm_enable_uhcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UHCPHY_DISABLE) -+#define __cpm_suspend_uhcphy() (REG_CPM_OPCR |= CPM_OPCR_UHCPHY_DISABLE) -+#define __cpm_enable_udcphy() (REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE) -+#define __cpm_suspend_udcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE) -+#define __cpm_enable_osc_in_sleep() (REG_CPM_OPCR |= CPM_OPCR_OSC_ENABLE) -+#define __cpm_disable_osc_in_sleep() (REG_CPM_OPCR &= ~CPM_OPCR_OSC_ENABLE) -+#define __cpm_select_rtcclk_rtc() (REG_CPM_OPCR |= CPM_OPCR_ERCS) -+#define __cpm_select_rtcclk_exclk() (REG_CPM_OPCR &= ~CPM_OPCR_ERCS) -+ -+ -+/*************************************************************************** -+ * TCU -+ ***************************************************************************/ -+// where 'n' is the TCU channel -+#define __tcu_select_extalclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) -+#define __tcu_select_rtcclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) -+#define __tcu_select_pclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) -+#define __tcu_disable_pclk(n) \ -+ REG_TCU_TCSR(n) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PCK_EN); -+#define __tcu_select_clk_div1(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) -+#define __tcu_select_clk_div4(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) -+#define __tcu_select_clk_div16(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) -+#define __tcu_select_clk_div64(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) -+#define __tcu_select_clk_div256(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) -+#define __tcu_select_clk_div1024(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) -+ -+#define __tcu_enable_pwm_output(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN) -+#define __tcu_disable_pwm_output(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN) -+ -+#define __tcu_init_pwm_output_high(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH) -+#define __tcu_init_pwm_output_low(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH) -+ -+#define __tcu_set_pwm_output_shutdown_graceful(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD) -+#define __tcu_set_pwm_output_shutdown_abrupt(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD) -+ -+#define __tcu_clear_counter_to_zero(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_CNT_CLRZ) -+ -+#define __tcu_ost_enabled() (REG_TCU_TER & TCU_TER_OSTEN) -+#define __tcu_enable_ost() (REG_TCU_TESR = TCU_TESR_OSTST) -+#define __tcu_disable_ost() (REG_TCU_TECR = TCU_TECR_OSTCL) -+ -+#define __tcu_counter_enabled(n) (REG_TCU_TER & (1 << (n))) -+#define __tcu_start_counter(n) (REG_TCU_TESR |= (1 << (n))) -+#define __tcu_stop_counter(n) (REG_TCU_TECR |= (1 << (n))) -+ -+#define __tcu_half_match_flag(n) (REG_TCU_TFR & (1 << ((n) + 16))) -+#define __tcu_full_match_flag(n) (REG_TCU_TFR & (1 << (n))) -+#define __tcu_set_half_match_flag(n) (REG_TCU_TFSR = (1 << ((n) + 16))) -+#define __tcu_set_full_match_flag(n) (REG_TCU_TFSR = (1 << (n))) -+#define __tcu_clear_half_match_flag(n) (REG_TCU_TFCR = (1 << ((n) + 16))) -+#define __tcu_clear_full_match_flag(n) (REG_TCU_TFCR = (1 << (n))) -+#define __tcu_mask_half_match_irq(n) (REG_TCU_TMSR = (1 << ((n) + 16))) -+#define __tcu_mask_full_match_irq(n) (REG_TCU_TMSR = (1 << (n))) -+#define __tcu_unmask_half_match_irq(n) (REG_TCU_TMCR = (1 << ((n) + 16))) -+#define __tcu_unmask_full_match_irq(n) (REG_TCU_TMCR = (1 << (n))) -+ -+#define __tcu_ost_match_flag() (REG_TCU_TFR & TCU_TFR_OSTFLAG) -+#define __tcu_set_ost_match_flag() (REG_TCU_TFSR = TCU_TFSR_OSTFST) -+#define __tcu_clear_ost_match_flag() (REG_TCU_TFCR = TCU_TFCR_OSTFCL) -+#define __tcu_ost_match_irq_masked() (REG_TCU_TMR & TCU_TMR_OSTMASK) -+#define __tcu_mask_ost_match_irq() (REG_TCU_TMSR = TCU_TMSR_OSTMST) -+#define __tcu_unmask_ost_match_irq() (REG_TCU_TMCR = TCU_TMCR_OSTMCL) -+ -+#define __tcu_wdt_clock_stopped() (REG_TCU_TSR & TCU_TSSR_WDTSC) -+#define __tcu_ost_clock_stopped() (REG_TCU_TSR & TCU_TSR_OST) -+#define __tcu_timer_clock_stopped(n) (REG_TCU_TSR & (1 << (n))) -+ -+#define __tcu_start_wdt_clock() (REG_TCU_TSCR = TCU_TSSR_WDTSC) -+#define __tcu_start_ost_clock() (REG_TCU_TSCR = TCU_TSCR_OSTSC) -+#define __tcu_start_timer_clock(n) (REG_TCU_TSCR = (1 << (n))) -+ -+#define __tcu_stop_wdt_clock() (REG_TCU_TSSR = TCU_TSSR_WDTSC) -+#define __tcu_stop_ost_clock() (REG_TCU_TSSR = TCU_TSSR_OSTSS) -+#define __tcu_stop_timer_clock(n) (REG_TCU_TSSR = (1 << (n))) -+ -+#define __tcu_get_count(n) (REG_TCU_TCNT((n))) -+#define __tcu_set_count(n,v) (REG_TCU_TCNT((n)) = (v)) -+#define __tcu_set_full_data(n,v) (REG_TCU_TDFR((n)) = (v)) -+#define __tcu_set_half_data(n,v) (REG_TCU_TDHR((n)) = (v)) -+ -+/* TCU2, counter 1, 2*/ -+#define __tcu_read_real_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -+#define __tcu_read_false_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -+#define __tcu_counter_busy(n) (REG_TCU_TSTR & (1 << (n))) -+#define __tcu_counter_ready(n) (REG_TCU_TSTR & (1 << (n))) -+ -+#define __tcu_set_read_real_value(n) (REG_TCU_TSTSR = (1 << ((n) + 16))) -+#define __tcu_set_read_false_value(n) (REG_TCU_TSTCR = (1 << ((n) + 16))) -+#define __tcu_set_counter_busy(n) (REG_TCU_TSTSR = (1 << (n))) -+#define __tcu_set_counter_ready(n) (REG_TCU_TSTCR = (1 << (n))) -+ -+/* ost counter */ -+#define __ostcu_set_pwm_output_shutdown_graceful() (REG_TCU_OSTCSR &= ~TCU_TCSR_PWM_SD) -+#define __ostcu_set_ost_output_shutdown_abrupt() (REG_TCU_OSTCSR |= TCU_TCSR_PWM_SD) -+#define __ostcu_select_clk_div1() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1) -+#define __ostcu_select_clk_div4() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE4) -+#define __ostcu_select_clk_div16() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE16) -+#define __ostcu_select_clk_div64() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE64) -+#define __ostcu_select_clk_div256() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE256) -+#define __ostcu_select_clk_div1024() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1024) -+#define __ostcu_select_rtcclk() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_RTC_EN) -+#define __ostcu_select_extalclk() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_EXT_EN) -+#define __ostcu_select_pclk() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_PCK_EN) -+ -+ -+/*************************************************************************** -+ * WDT -+ ***************************************************************************/ -+#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) -+#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) -+#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) -+#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) -+ -+#define __wdt_select_extalclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) -+#define __wdt_select_rtcclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) -+#define __wdt_select_pclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) -+ -+#define __wdt_select_clk_div1() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) -+#define __wdt_select_clk_div4() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) -+#define __wdt_select_clk_div16() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) -+#define __wdt_select_clk_div64() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) -+#define __wdt_select_clk_div256() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) -+#define __wdt_select_clk_div1024() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) -+ -+ -+/*************************************************************************** -+ * UART -+ ***************************************************************************/ -+ -+#define __uart_enable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -+#define __uart_disable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -+ -+#define __uart_enable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -+#define __uart_disable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -+ -+#define __uart_enable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -+#define __uart_disable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -+ -+#define __uart_enable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -+#define __uart_disable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -+ -+#define __uart_set_8n1(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -+ -+#define __uart_set_baud(n, devclk, baud) \ -+ do { \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -+ } while (0) -+ -+#define __uart_parity_error(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -+ -+#define __uart_clear_errors(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -+ -+#define __uart_transmit_fifo_empty(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -+ -+#define __uart_transmit_end(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -+ -+#define __uart_transmit_char(n, ch) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -+ -+#define __uart_receive_fifo_full(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_ready(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_char(n) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -+ -+#define __uart_disable_irda() \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -+#define __uart_enable_irda() \ -+ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -+ -+ -+/*************************************************************************** -+ * DMAC -+ ***************************************************************************/ -+ -+/* m is the DMA controller index (0, 1), n is the DMA channel index (0 - 11) */ -+ -+#define __dmac_enable_module(m) \ -+ ( REG_DMAC_DMACR(m) |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_012345 ) -+#define __dmac_disable_module(m) \ -+ ( REG_DMAC_DMACR(m) &= ~DMAC_DMACR_DMAE ) -+ -+/* p=0,1,2,3 */ -+#define __dmac_set_priority(m,p) \ -+do { \ -+ REG_DMAC_DMACR(m) &= ~DMAC_DMACR_PR_MASK; \ -+ REG_DMAC_DMACR(m) |= ((p) << DMAC_DMACR_PR_BIT); \ -+} while (0) -+ -+#define __dmac_test_halt_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_HLT ) -+#define __dmac_test_addr_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_AR ) -+ -+#define __dmac_channel_enable_clk(n) \ -+ REG_DMAC_DMACKE((n)/HALF_DMA_NUM) |= 1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM); -+ -+#define __dmac_enable_descriptor(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) -+#define __dmac_disable_descriptor(n) \ -+ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) -+ -+#define __dmac_enable_channel(n) \ -+do { \ -+ REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN; \ -+} while (0) -+#define __dmac_disable_channel(n) \ -+do { \ -+ REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN; \ -+} while (0) -+#define __dmac_channel_enabled(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) -+ -+#define __dmac_channel_enable_irq(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) -+#define __dmac_channel_disable_irq(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) -+ -+#define __dmac_channel_transmit_halt_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) -+#define __dmac_channel_transmit_end_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) -+#define __dmac_channel_address_error_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) -+#define __dmac_channel_count_terminated_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) -+#define __dmac_channel_descriptor_invalid_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) -+ -+#define __dmac_channel_clear_transmit_halt(n) \ -+ do { \ -+ /* clear both channel halt error and globle halt error */ \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT; \ -+ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_HLT; \ -+ } while (0) -+#define __dmac_channel_clear_transmit_end(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) -+#define __dmac_channel_clear_address_error(n) \ -+ do { \ -+ REG_DMAC_DDA(n) = 0; /* clear descriptor address register */ \ -+ REG_DMAC_DSAR(n) = 0; /* clear source address register */ \ -+ REG_DMAC_DTAR(n) = 0; /* clear target address register */ \ -+ /* clear both channel addr error and globle address error */ \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR; \ -+ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_AR; \ -+ } while (0) -+#define __dmac_channel_clear_count_terminated(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) -+#define __dmac_channel_clear_descriptor_invalid(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) -+ -+#define __dmac_channel_set_transfer_unit_32bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_8bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16byte(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_32byte(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_dest_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_src_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ -+} while (0) -+ -+/* v=0-15 */ -+#define __dmac_channel_set_rdil(n,v) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ -+ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ -+} while (0) -+ -+#define __dmac_channel_dest_addr_fixed(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) -+#define __dmac_channel_dest_addr_increment(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) -+ -+#define __dmac_channel_src_addr_fixed(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) -+#define __dmac_channel_src_addr_increment(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) -+ -+#define __dmac_channel_set_doorbell(n) \ -+ ( REG_DMAC_DMADBSR((n)/HALF_DMA_NUM) = (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -+ -+#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) & (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -+#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) &= ~(1 <<((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -+ -+static __inline__ int __dmac_get_irq(void) -+{ -+ int i; -+ for (i = 0; i < MAX_DMA_NUM; i++) -+ if (__dmac_channel_irq_detected(i)) -+ return i; -+ return -1; -+} -+ -+ -+/*************************************************************************** -+ * AIC (AC'97 & I2S Controller) -+ ***************************************************************************/ -+ -+#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) -+#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) -+ -+#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) -+#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) -+ -+#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) -+#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) -+ -+#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) -+#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) -+#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) -+ -+#define __aic_reset() \ -+do { \ -+ REG_AIC_FR |= AIC_FR_RST; \ -+} while(0) -+ -+ -+#define __aic_set_transmit_trigger(n) \ -+do { \ -+ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ -+ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ -+} while(0) -+ -+#define __aic_set_receive_trigger(n) \ -+do { \ -+ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ -+ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ -+} while(0) -+ -+#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) -+#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) -+#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) -+#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) -+#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) -+#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) -+ -+#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) -+#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) -+ -+#define __aic_enable_transmit_intr() \ -+ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) -+#define __aic_disable_transmit_intr() \ -+ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) -+#define __aic_enable_receive_intr() \ -+ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) -+#define __aic_disable_receive_intr() \ -+ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) -+ -+#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) -+#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) -+#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) -+#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) -+ -+#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) -+#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) -+#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) -+#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) -+#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) -+#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) -+ -+#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 -+#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 -+#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 -+#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 -+#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 -+#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 -+ -+#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 -+#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 -+#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 -+#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 -+#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 -+#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 -+ -+#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) -+#define __ac97_set_xs_mono() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ -+} while(0) -+#define __ac97_set_xs_stereo() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ -+} while(0) -+ -+/* In fact, only stereo is support now. */ -+#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) -+#define __ac97_set_rs_mono() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ -+} while(0) -+#define __ac97_set_rs_stereo() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ -+} while(0) -+ -+#define __ac97_warm_reset_codec() \ -+ do { \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ -+ udelay(2); \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ -+ } while (0) -+ -+#define __ac97_cold_reset_codec() \ -+ do { \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ -+ udelay(2); \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ -+ } while (0) -+ -+/* n=8,16,18,20 */ -+#define __ac97_set_iass(n) \ -+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) -+#define __ac97_set_oass(n) \ -+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) -+ -+#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) -+#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) -+ -+/* n=8,16,18,20,24 */ -+/*#define __i2s_set_sample_size(n) \ -+ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ -+ -+#define __i2s_set_oss_sample_size(n) \ -+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) -+#define __i2s_set_iss_sample_size(n) \ -+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) -+ -+#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) -+#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) -+ -+#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) -+#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) -+#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) -+#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) -+ -+#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) -+ -+#define __aic_get_transmit_resident() \ -+ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) -+#define __aic_get_receive_count() \ -+ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -+ -+#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -+#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -+#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -+#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -+#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -+#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) -+#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) -+ -+#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -+ -+#define CODEC_READ_CMD (1 << 19) -+#define CODEC_WRITE_CMD (0 << 19) -+#define CODEC_REG_INDEX_BIT 12 -+#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -+#define CODEC_REG_DATA_BIT 4 -+#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -+ -+#define __ac97_out_rcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_wcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_data(value) \ -+do { \ -+ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -+} while (0) -+ -+#define __ac97_in_data() \ -+ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -+ -+#define __ac97_in_status_addr() \ -+ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -+ -+#define __i2s_set_sample_rate(i2sclk, sync) \ -+ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -+ -+#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -+#define __aic_read_rfifo() ( REG_AIC_DR ) -+ -+#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) -+#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) -+ -+// -+// Define next ops for AC97 compatible -+// -+ -+#define AC97_ACSR AIC_ACSR -+ -+#define __ac97_enable() __aic_enable(); __aic_select_ac97() -+#define __ac97_disable() __aic_disable() -+#define __ac97_reset() __aic_reset() -+ -+#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __ac97_enable_record() __aic_enable_record() -+#define __ac97_disable_record() __aic_disable_record() -+#define __ac97_enable_replay() __aic_enable_replay() -+#define __ac97_disable_replay() __aic_disable_replay() -+#define __ac97_enable_loopback() __aic_enable_loopback() -+#define __ac97_disable_loopback() __aic_disable_loopback() -+ -+#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -+#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __ac97_transmit_request() __aic_transmit_request() -+#define __ac97_receive_request() __aic_receive_request() -+#define __ac97_transmit_underrun() __aic_transmit_underrun() -+#define __ac97_receive_overrun() __aic_receive_overrun() -+ -+#define __ac97_clear_errors() __aic_clear_errors() -+ -+#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -+#define __ac97_get_receive_count() __aic_get_receive_count() -+ -+#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -+#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -+#define __ac97_read_rfifo() __aic_read_rfifo() -+ -+// -+// Define next ops for I2S compatible -+// -+ -+#define I2S_ACSR AIC_I2SSR -+ -+#define __i2s_enable() __aic_enable(); __aic_select_i2s() -+#define __i2s_disable() __aic_disable() -+#define __i2s_reset() __aic_reset() -+ -+#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __i2s_enable_record() __aic_enable_record() -+#define __i2s_disable_record() __aic_disable_record() -+#define __i2s_enable_replay() __aic_enable_replay() -+#define __i2s_disable_replay() __aic_disable_replay() -+#define __i2s_enable_loopback() __aic_enable_loopback() -+#define __i2s_disable_loopback() __aic_disable_loopback() -+ -+#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -+#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __i2s_transmit_request() __aic_transmit_request() -+#define __i2s_receive_request() __aic_receive_request() -+#define __i2s_transmit_underrun() __aic_transmit_underrun() -+#define __i2s_receive_overrun() __aic_receive_overrun() -+ -+#define __i2s_clear_errors() __aic_clear_errors() -+ -+#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -+#define __i2s_get_receive_count() __aic_get_receive_count() -+ -+#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -+#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -+#define __i2s_read_rfifo() __aic_read_rfifo() -+ -+#define __i2s_reset_codec() \ -+ do { \ -+ } while (0) -+ -+/************************************************************************* -+ * PCM Controller operation -+ *************************************************************************/ -+ -+#define __pcm_enable() ( REG_PCM_CTL |= PCM_CTL_PCMEN ) -+#define __pcm_disable() ( REG_PCM_CTL &= ~PCM_CTL_PCMEN ) -+ -+#define __pcm_clk_enable() ( REG_PCM_CTL |= PCM_CTL_CLKEN ) -+#define __pcm_clk_disable() ( REG_PCM_CTL &= ~PCM_CTL_CLKEN ) -+ -+#define __pcm_reset() ( REG_PCM_CTL |= PCM_CTL_RST ) -+#define __pcm_flush_fifo() ( REG_PCM_CTL |= PCM_CTL_FLUSH ) -+ -+#define __pcm_enable_record() ( REG_PCM_CTL |= PCM_CTL_EREC ) -+#define __pcm_disable_record() ( REG_PCM_CTL &= ~PCM_CTL_EREC ) -+#define __pcm_enable_playback() ( REG_PCM_CTL |= PCM_CTL_ERPL ) -+#define __pcm_disable_playback() ( REG_PCM_CTL &= ~PCM_CTL_ERPL ) -+ -+#define __pcm_enable_rxfifo() __pcm_enable_record() -+#define __pcm_disable_rxfifo() __pcm_disable_record() -+#define __pcm_enable_txfifo() __pcm_enable_playback() -+#define __pcm_disable_txfifo() __pcm_disable_playback() -+ -+#define __pcm_last_sample() ( REG_PCM_CTL |= PCM_CTL_LSMP ) -+#define __pcm_zero_sample() ( REG_PCM_CTL &= ~PCM_CTL_LSMP ) -+ -+#define __pcm_enable_transmit_dma() ( REG_PCM_CTL |= PCM_CTL_ETDMA ) -+#define __pcm_disable_transmit_dma() ( REG_PCM_CTL &= ~PCM_CTL_ETDMA ) -+#define __pcm_enable_receive_dma() ( REG_PCM_CTL |= PCM_CTL_ERDMA ) -+#define __pcm_disable_receive_dma() ( REG_PCM_CTL &= ~PCM_CTL_ERDMA ) -+ -+#define __pcm_as_master() ( REG_PCM_CFG &= PCM_CFG_MODE ) -+#define __pcm_as_slave() ( REG_PCM_CFG |= ~PCM_CFG_MODE ) -+ -+#define __pcm_set_transmit_trigger(n) \ -+do { \ -+ REG_PCM_CFG &= ~PCM_CFG_TFTH_MASK; \ -+ REG_PCM_CFG |= ((n) << PCM_CFG_TFTH_BIT); \ -+} while(0) -+ -+#define __pcm_set_receive_trigger(n) \ -+do { \ -+ REG_PCM_CFG &= ~PCM_CFG_RFTH_MASK; \ -+ REG_PCM_CFG |= ((n) << PCM_CFG_RFTH_BIT); \ -+} while(0) -+ -+#define __pcm_omsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_OMSBPOS ) -+#define __pcm_omsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_OMSBPOS ) -+ -+#define __pcm_imsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_IMSBPOS ) -+#define __pcm_imsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_IMSBPOS ) -+ -+/* set input sample size 8 or 16*/ -+#define __pcm_set_iss(n) \ -+( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_ISS_MASK) | PCM_CFG_ISS_##n ) -+/* set output sample size 8 or 16*/ -+#define __pcm_set_oss(n) \ -+( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_OSS_MASK) | PCM_CFG_OSS_##n ) -+ -+#define __pcm_set_valid_slot(n) \ -+( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_SLOT_MASK) | PCM_CFG_SLOT_##n ) -+ -+#define __pcm_write_data(v) ( REG_PCM_DP = (v) ) -+#define __pcm_read_data() ( REG_PCM_DP ) -+ -+#define __pcm_enable_tfs_intr() ( REG_PCM_INTC |= PCM_INTC_ETFS ) -+#define __pcm_disable_tfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETFS ) -+ -+#define __pcm_enable_tur_intr() ( REG_PCM_INTC |= PCM_INTC_ETUR ) -+#define __pcm_disable_tur_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETUR ) -+ -+#define __pcm_enable_rfs_intr() ( REG_PCM_INTC |= PCM_INTC_ERFS ) -+#define __pcm_disable_rfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ERFS ) -+ -+#define __pcm_enable_ror_intr() ( REG_PCM_INTC |= PCM_INTC_EROR ) -+#define __pcm_disable_ror_intr() ( REG_PCM_INTC &= ~PCM_INTC_EROR ) -+ -+#define __pcm_ints_valid_tx() \ -+( ((REG_PCM_INTS & PCM_INTS_TFL_MASK) >> PCM_INTS_TFL_BIT) ) -+#define __pcm_ints_valid_rx() \ -+( ((REG_PCM_INTS & PCM_INTS_RFL_MASK) >> PCM_INTS_RFL_BIT) ) -+ -+#define __pcm_set_clk_div(n) \ -+( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_CLKDIV_MASK) | ((n) << PCM_DIV_CLKDIV_BIT) ) -+ -+/* sysclk(cpm_pcm_sysclk) Hz is created by cpm logic, and pcmclk Hz is the pcm in/out clock wanted */ -+#define __pcm_set_clk_rate(sysclk, pcmclk) \ -+__pcm_set_clk_div(((sysclk) / (pcmclk) - 1)) -+ -+#define __pcm_set_sync_div(n) \ -+( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNDIV_MASK) | ((n) << PCM_DIV_SYNDIV_BIT) ) -+ -+/* pcmclk is source clock Hz, and sync is the frame sync clock Hz wanted */ -+#define __pcm_set_sync_rate(pcmclk, sync) \ -+__pcm_set_sync_div(((pcmclk) / (8 * (sync)) - 1)) -+ -+ /* set sync length in pcmclk n = 0 ... 63 */ -+#define __pcm_set_sync_len(n) \ -+( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNL_MASK) | (n << PCM_DIV_SYNL_BIT) ) -+ -+ -+/*************************************************************************** -+ * ICDC -+ ***************************************************************************/ -+#define __i2s_internal_codec() __aic_internal_codec() -+#define __i2s_external_codec() __aic_external_codec() -+ -+#define __icdc_clk_ready() ( REG_ICDC_CKCFG & ICDC_CKCFG_CKRDY ) -+#define __icdc_sel_adc() ( REG_ICDC_CKCFG |= ICDC_CKCFG_SELAD ) -+#define __icdc_sel_dac() ( REG_ICDC_CKCFG &= ~ICDC_CKCFG_SELAD ) -+ -+#define __icdc_set_rgwr() ( REG_ICDC_RGADW |= ICDC_RGADW_RGWR ) -+#define __icdc_clear_rgwr() ( REG_ICDC_RGADW &= ~ICDC_RGADW_RGWR ) -+#define __icdc_rgwr_ready() ( REG_ICDC_RGADW & ICDC_RGADW_RGWR ) -+ -+#define __icdc_set_addr(n) \ -+do { \ -+ REG_ICDC_RGADW &= ~ICDC_RGADW_RGADDR_MASK; \ -+ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGADDR_BIT; \ -+} while(0) -+ -+#define __icdc_set_cmd(n) \ -+do { \ -+ REG_ICDC_RGADW &= ~ICDC_RGADW_RGDIN_MASK; \ -+ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGDIN_BIT; \ -+} while(0) -+ -+#define __icdc_irq_pending() ( REG_ICDC_RGDATA & ICDC_RGDATA_IRQ ) -+#define __icdc_get_value() ( REG_ICDC_RGDATA & ICDC_RGDATA_RGDOUT_MASK ) -+ -+/*************************************************************************** -+ * INTC -+ ***************************************************************************/ -+#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -+#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -+#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) /* A dummy ack, as the Pending Register is Read Only. Should we remove __intc_ack_irq() */ -+ -+ -+/*************************************************************************** -+ * I2C -+ ***************************************************************************/ -+ -+#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -+#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -+ -+#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -+#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -+#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -+#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -+ -+#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -+#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -+#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -+ -+#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -+#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -+#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -+ -+#define __i2c_set_clk(dev_clk, i2c_clk) \ -+ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -+ -+#define __i2c_read() ( REG_I2C_DR ) -+#define __i2c_write(val) ( REG_I2C_DR = (val) ) -+ -+ -+/*************************************************************************** -+ * MSC -+ ***************************************************************************/ -+/* n = 0, 1 (MSC0, MSC1) */ -+ -+#define __msc_start_op(n) \ -+ ( REG_MSC_STRPCL(n) = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -+ -+#define __msc_set_resto(n, to) ( REG_MSC_RESTO(n) = to ) -+#define __msc_set_rdto(n, to) ( REG_MSC_RDTO(n) = to ) -+#define __msc_set_cmd(n, cmd) ( REG_MSC_CMD(n) = cmd ) -+#define __msc_set_arg(n, arg) ( REG_MSC_ARG(n) = arg ) -+#define __msc_set_nob(n, nob) ( REG_MSC_NOB(n) = nob ) -+#define __msc_get_nob(n) ( REG_MSC_NOB(n) ) -+#define __msc_set_blklen(n, len) ( REG_MSC_BLKLEN(n) = len ) -+#define __msc_set_cmdat(n, cmdat) ( REG_MSC_CMDAT(n) = cmdat ) -+#define __msc_set_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_IO_ABORT ) -+#define __msc_clear_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_IO_ABORT ) -+ -+#define __msc_set_cmdat_bus_width1(n) \ -+do { \ -+ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_bus_width4(n) \ -+do { \ -+ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_dma_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DMA_EN ) -+#define __msc_set_cmdat_init(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_INIT ) -+#define __msc_set_cmdat_busy(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_BUSY ) -+#define __msc_set_cmdat_stream(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_block(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_read(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_write(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_data_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DATA_EN ) -+ -+/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -+#define __msc_set_cmdat_res_format(n, r) \ -+do { \ -+ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -+ REG_MSC_CMDAT(n) |= (r); \ -+} while(0) -+ -+#define __msc_clear_cmdat(n) \ -+ REG_MSC_CMDAT(n) &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -+ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -+ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -+ -+#define __msc_get_imask(n) ( REG_MSC_IMASK(n) ) -+#define __msc_mask_all_intrs(n) ( REG_MSC_IMASK(n) = 0xff ) -+#define __msc_unmask_all_intrs(n) ( REG_MSC_IMASK(n) = 0x00 ) -+#define __msc_mask_rd(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_unmask_rd(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_mask_wr(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_unmask_wr(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_mask_endcmdres(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_END_CMD_RES ) -+#define __msc_unmask_endcmdres(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_END_CMD_RES ) -+#define __msc_mask_datatrandone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_unmask_datatrandone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_mask_prgdone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_PRG_DONE ) -+#define __msc_unmask_prgdone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_PRG_DONE ) -+ -+/* m=0,1,2,3,4,5,6,7 */ -+#define __msc_set_clkrt(n, m) \ -+do { \ -+ REG_MSC_CLKRT(n) = m; \ -+} while(0) -+ -+#define __msc_get_ireg(n) ( REG_MSC_IREG(n) ) -+#define __msc_ireg_rd(n) ( REG_MSC_IREG(n) & MSC_IREG_RXFIFO_RD_REQ ) -+#define __msc_ireg_wr(n) ( REG_MSC_IREG(n) & MSC_IREG_TXFIFO_WR_REQ ) -+#define __msc_ireg_end_cmd_res(n) ( REG_MSC_IREG(n) & MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_data_tran_done(n) ( REG_MSC_IREG(n) & MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_prg_done(n) ( REG_MSC_IREG(n) & MSC_IREG_PRG_DONE ) -+#define __msc_ireg_clear_end_cmd_res(n) ( REG_MSC_IREG(n) = MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_clear_data_tran_done(n) ( REG_MSC_IREG(n) = MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_clear_prg_done(n) ( REG_MSC_IREG(n) = MSC_IREG_PRG_DONE ) -+ -+#define __msc_get_stat(n) ( REG_MSC_STAT(n) ) -+#define __msc_stat_not_end_cmd_res(n) ( (REG_MSC_STAT(n) & MSC_STAT_END_CMD_RES) == 0) -+#define __msc_stat_crc_err(n) \ -+ ( REG_MSC_STAT(n) & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -+#define __msc_stat_res_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_RES_ERR ) -+#define __msc_stat_rd_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_READ_ERROR ) -+#define __msc_stat_wr_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_WRITE_ERROR_YES ) -+#define __msc_stat_resto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_RES ) -+#define __msc_stat_rdto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_READ ) -+ -+#define __msc_rd_resfifo(n) ( REG_MSC_RES(n) ) -+#define __msc_rd_rxfifo(n) ( REG_MSC_RXFIFO(n) ) -+#define __msc_wr_txfifo(n, v) ( REG_MSC_TXFIFO(n) = v ) -+ -+#define __msc_reset(n) \ -+do { \ -+ REG_MSC_STRPCL(n) = MSC_STRPCL_RESET; \ -+ while (REG_MSC_STAT(n) & MSC_STAT_IS_RESETTING); \ -+} while (0) -+ -+#define __msc_start_clk(n) \ -+do { \ -+ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_START; \ -+} while (0) -+ -+#define __msc_stop_clk(n) \ -+do { \ -+ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -+} while (0) -+ -+#define MMC_CLK 19169200 -+#define SD_CLK 24576000 -+ -+/* msc_clk should little than pclk and little than clk retrieve from card */ -+#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -+do { \ -+ unsigned int rate, pclk, i; \ -+ pclk = dev_clk; \ -+ rate = type?SD_CLK:MMC_CLK; \ -+ if (msc_clk && msc_clk < pclk) \ -+ pclk = msc_clk; \ -+ i = 0; \ -+ while (pclk < rate) \ -+ { \ -+ i ++; \ -+ rate >>= 1; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+/* divide rate to little than or equal to 400kHz */ -+#define __msc_calc_slow_clk_divisor(type, lv) \ -+do { \ -+ unsigned int rate, i; \ -+ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -+ i = 0; \ -+ while (rate > 0) \ -+ { \ -+ rate >>= 1; \ -+ i ++; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+ -+/*************************************************************************** -+ * SSI (Synchronous Serial Interface) -+ ***************************************************************************/ -+/* n = 0, 1 (SSI0, SSI1) */ -+#define __ssi_enable(n) ( REG_SSI_CR0(n) |= SSI_CR0_SSIE ) -+#define __ssi_disable(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_SSIE ) -+#define __ssi_select_ce(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_FSEL ) -+ -+#define __ssi_normal_mode(n) ( REG_SSI_ITR(n) &= ~SSI_ITR_IVLTM_MASK ) -+ -+#define __ssi_select_ce2(n) \ -+do { \ -+ REG_SSI_CR0(n) |= SSI_CR0_FSEL; \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_select_gpc(n) \ -+do { \ -+ REG_SSI_CR0(n) &= ~SSI_CR0_FSEL; \ -+ REG_SSI_CR1(n) |= SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_underrun_auto_clear(n) \ -+do { \ -+ REG_SSI_CR0(n) |= SSI_CR0_EACLRUN; \ -+} while (0) -+ -+#define __ssi_underrun_clear_manually(n) \ -+do { \ -+ REG_SSI_CR0(n) &= ~SSI_CR0_EACLRUN; \ -+} while (0) -+ -+#define __ssi_enable_tx_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TIE | SSI_CR0_TEIE ) -+ -+#define __ssi_disable_tx_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -+ -+#define __ssi_enable_rx_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_RIE | SSI_CR0_REIE ) -+ -+#define __ssi_disable_rx_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -+ -+#define __ssi_enable_txfifo_half_empty_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TIE ) -+#define __ssi_disable_txfifo_half_empty_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_TIE ) -+#define __ssi_enable_tx_error_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TEIE ) -+#define __ssi_disable_tx_error_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_TEIE ) -+#define __ssi_enable_rxfifo_half_full_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_RIE ) -+#define __ssi_disable_rxfifo_half_full_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_RIE ) -+#define __ssi_enable_rx_error_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_REIE ) -+#define __ssi_disable_rx_error_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_REIE ) -+ -+#define __ssi_enable_loopback(n) ( REG_SSI_CR0(n) |= SSI_CR0_LOOP ) -+#define __ssi_disable_loopback(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_LOOP ) -+ -+#define __ssi_enable_receive(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_DISREV ) -+#define __ssi_disable_receive(n) ( REG_SSI_CR0(n) |= SSI_CR0_DISREV ) -+ -+#define __ssi_finish_receive(n) \ -+ ( REG_SSI_CR0(n) |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_disable_recvfinish(n) \ -+ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_flush_txfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH ) -+#define __ssi_flush_rxfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_RFLUSH ) -+ -+#define __ssi_flush_fifo(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -+ -+#define __ssi_finish_transmit(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_UNFIN ) -+#define __ssi_wait_transmit(n) ( REG_SSI_CR1(n) |= SSI_CR1_UNFIN ) -+#define __ssi_use_busy_wait_mode(n) __ssi_wait_transmit(n) -+#define __ssi_unset_busy_wait_mode(n) __ssi_finish_transmit(n) -+ -+#define __ssi_spi_format(n) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SPI; \ -+ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -+ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -+ } while (0) -+ -+/* TI's SSP format, must clear SSI_CR1.UNFIN */ -+#define __ssi_ssp_format(n) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -+ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SSP; \ -+ } while (0) -+ -+/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -+#define __ssi_microwire_format(n) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1(n) |= SSI_CR1_FMAT_MW1; \ -+ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -+ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -+ REG_SSI_CR0(n) &= ~SSI_CR0_RFINE; \ -+ } while (0) -+ -+/* CE# level (FRMHL), CE# in interval time (ITFRM), -+ clock phase and polarity (PHA POL), -+ interval time (SSIITR), interval characters/frame (SSIICR) */ -+ -+/* frmhl,endian,mcom,flen,pha,pol MASK */ -+#define SSICR1_MISC_MASK \ -+ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -+ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) -+ -+#define __ssi_spi_set_misc(n,frmhl,endian,flen,mcom,pha,pol) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSICR1_MISC_MASK; \ -+ REG_SSI_CR1(n) |= ((frmhl) << 30) | ((endian) << 25) | \ -+ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -+ ((pha) << 1) | (pol); \ -+ } while(0) -+ -+/* Transfer with MSB or LSB first */ -+#define __ssi_set_msb(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_LFST ) -+#define __ssi_set_lsb(n) ( REG_SSI_CR1(n) |= SSI_CR1_LFST ) -+ -+#define __ssi_set_frame_length(n, m) \ -+ REG_SSI_CR1(n) = (REG_SSI_CR1(n) & ~SSI_CR1_FLEN_MASK) | (((m) - 2) << 4) -+ -+/* m = 1 - 16 */ -+#define __ssi_set_microwire_command_length(n,m) \ -+ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##m##BIT) ) -+ -+/* Set the clock phase for SPI */ -+#define __ssi_set_spi_clock_phase(n, m) \ -+ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_PHA) | (((m)&0x1)<< 1))) -+ -+/* Set the clock polarity for SPI */ -+#define __ssi_set_spi_clock_polarity(n, p) \ -+ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_POL) | ((p)&0x1)) ) -+ -+/* SSI tx trigger, m = i x 8 */ -+#define __ssi_set_tx_trigger(n, m) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_TTRG_MASK; \ -+ REG_SSI_CR1(n) |= ((m)/8)<> SSI_SR_TFIFONUM_BIT ) -+ -+#define __ssi_get_rxfifo_count(n) \ -+ ( (REG_SSI_SR(n) & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -+ -+#define __ssi_transfer_end(n) ( REG_SSI_SR(n) & SSI_SR_END ) -+#define __ssi_is_busy(n) ( REG_SSI_SR(n) & SSI_SR_BUSY ) -+ -+#define __ssi_txfifo_full(n) ( REG_SSI_SR(n) & SSI_SR_TFF ) -+#define __ssi_rxfifo_empty(n) ( REG_SSI_SR(n) & SSI_SR_RFE ) -+#define __ssi_rxfifo_half_full(n) ( REG_SSI_SR(n) & SSI_SR_RFHF ) -+#define __ssi_txfifo_half_empty(n) ( REG_SSI_SR(n) & SSI_SR_TFHE ) -+#define __ssi_underrun(n) ( REG_SSI_SR(n) & SSI_SR_UNDR ) -+#define __ssi_overrun(n) ( REG_SSI_SR(n) & SSI_SR_OVER ) -+#define __ssi_clear_underrun(n) ( REG_SSI_SR(n) = ~SSI_SR_UNDR ) -+#define __ssi_clear_overrun(n) ( REG_SSI_SR(n) = ~SSI_SR_OVER ) -+#define __ssi_clear_errors(n) ( REG_SSI_SR(n) &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -+ -+#define __ssi_set_clk(n, dev_clk, ssi_clk) \ -+ ( REG_SSI_GR(n) = (dev_clk) / (2*(ssi_clk)) - 1 ) -+ -+#define __ssi_receive_data(n) REG_SSI_DR(n) -+#define __ssi_transmit_data(n, v) (REG_SSI_DR(n) = (v)) -+ -+ -+/*************************************************************************** -+ * CIM -+ ***************************************************************************/ -+ -+#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -+#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -+ -+/* n = 0, 1, 2, 3 */ -+#define __cim_set_input_data_stream_order(n) \ -+ do { \ -+ REG_CIM_CFG &= CIM_CFG_ORDER_MASK; \ -+ REG_CIM_CFG |= ((n)<>CIM_SIZE_LPF_BIT) -+#define __cim_get_pixel() ((REG_CIM_SIZE&CIM_SIZE_PPL_MASK)>>CIM_SIZE_PPL_BIT) -+ -+#define __cim_set_v_offset(a) ( REG_CIM_OFFSET = (REG_CIM_OFFSET&(~CIM_OFFSET_V_MASK)) | ((a)<>CIM_OFFSET_V_BIT) -+#define __cim_get_h_offset() ((REG_CIM_OFFSET&CIM_OFFSET_H_MASK)>>CIM_OFFSET_H_BIT) -+ -+/************************************************************************* -+ * SLCD (Smart LCD Controller) -+ *************************************************************************/ -+#define __slcd_set_data_18bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_18BIT ) -+#define __slcd_set_data_16bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_16BIT ) -+#define __slcd_set_data_8bit_x3() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x3 ) -+#define __slcd_set_data_8bit_x2() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x2 ) -+#define __slcd_set_data_8bit_x1() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x1 ) -+#define __slcd_set_data_24bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_24BIT ) -+#define __slcd_set_data_9bit_x2() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_9BIT_x2 ) -+ -+#define __slcd_set_cmd_16bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_16BIT ) -+#define __slcd_set_cmd_8bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_8BIT ) -+#define __slcd_set_cmd_18bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_18BIT ) -+#define __slcd_set_cmd_24bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_24BIT ) -+ -+#define __slcd_set_cs_high() ( REG_SLCD_CFG |= SLCD_CFG_CS_ACTIVE_HIGH ) -+#define __slcd_set_cs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_CS_ACTIVE_HIGH ) -+ -+#define __slcd_set_rs_high() ( REG_SLCD_CFG |= SLCD_CFG_RS_CMD_HIGH ) -+#define __slcd_set_rs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_RS_CMD_HIGH ) -+ -+#define __slcd_set_clk_falling() ( REG_SLCD_CFG &= ~SLCD_CFG_CLK_ACTIVE_RISING ) -+#define __slcd_set_clk_rising() ( REG_SLCD_CFG |= SLCD_CFG_CLK_ACTIVE_RISING ) -+ -+#define __slcd_set_parallel_type() ( REG_SLCD_CFG &= ~SLCD_CFG_TYPE_SERIAL ) -+#define __slcd_set_serial_type() ( REG_SLCD_CFG |= SLCD_CFG_TYPE_SERIAL ) -+ -+/* SLCD Control Register */ -+#define __slcd_enable_dma() ( REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN ) -+#define __slcd_disable_dma() ( REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN ) -+ -+/* SLCD Status Register */ -+#define __slcd_is_busy() ( REG_SLCD_STATE & SLCD_STATE_BUSY ) -+ -+/* SLCD Data Register */ -+#define __slcd_set_cmd_rs() ( REG_SLCD_DATA |= SLCD_DATA_RS_COMMAND) -+#define __slcd_set_data_rs() ( REG_SLCD_DATA &= ~SLCD_DATA_RS_COMMAND) -+ -+ -+/*************************************************************************** -+ * LCD -+ ***************************************************************************/ -+ -+/*************************************************************************** -+ * LCD -+ ***************************************************************************/ -+#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= ( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -+#define __lcd_as_general_lcd() ( REG_LCD_CFG &= ~( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -+ -+#define __lcd_enable_tvepeh() ( REG_LCD_CFG |= LCD_CFG_TVEPEH ) -+#define __lcd_disable_tvepeh() ( REG_LCD_CFG &= ~LCD_CFG_TVEPEH ) -+ -+#define __lcd_enable_fuhold() ( REG_LCD_CFG |= LCD_CFG_FUHOLD ) -+#define __lcd_disable_fuhold() ( REG_LCD_CFG &= ~LCD_CFG_FUHOLD ) -+ -+#define __lcd_des_8word() ( REG_LCD_CFG |= LCD_CFG_NEWDES ) -+#define __lcd_des_4word() ( REG_LCD_CFG &= ~LCD_CFG_NEWDES ) -+ -+#define __lcd_enable_bypass_pal() ( REG_LCD_CFG |= LCD_CFG_PALBP ) -+#define __lcd_disable_bypass_pal() ( REG_LCD_CFG &= ~LCD_CFG_PALBP ) -+ -+#define __lcd_set_lcdpnl_term() ( REG_LCD_CTRL |= LCD_CFG_TVEN ) -+#define __lcd_set_tv_term() ( REG_LCD_CTRL &= ~LCD_CFG_TVEN ) -+ -+#define __lcd_enable_auto_recover() ( REG_LCD_CFG |= LCD_CFG_RECOVER ) -+#define __lcd_disable_auto_recover() ( REG_LCD_CFG &= ~LCD_CFG_RECOVER ) -+ -+#define __lcd_enable_dither() ( REG_LCD_CFG |= LCD_CFG_DITHER ) -+#define __lcd_disable_dither() ( REG_LCD_CFG &= ~LCD_CFG_DITHER ) -+ -+#define __lcd_disable_ps_mode() ( REG_LCD_CFG |= LCD_CFG_PSM ) -+#define __lcd_enable_ps_mode() ( REG_LCD_CFG &= ~LCD_CFG_PSM ) -+ -+#define __lcd_disable_cls_mode() ( REG_LCD_CFG |= LCD_CFG_CLSM ) -+#define __lcd_enable_cls_mode() ( REG_LCD_CFG &= ~LCD_CFG_CLSM ) -+ -+#define __lcd_disable_spl_mode() ( REG_LCD_CFG |= LCD_CFG_SPLM ) -+#define __lcd_enable_spl_mode() ( REG_LCD_CFG &= ~LCD_CFG_SPLM ) -+ -+#define __lcd_disable_rev_mode() ( REG_LCD_CFG |= LCD_CFG_REVM ) -+#define __lcd_enable_rev_mode() ( REG_LCD_CFG &= ~LCD_CFG_REVM ) -+ -+#define __lcd_disable_hsync_mode() ( REG_LCD_CFG |= LCD_CFG_HSYNM ) -+#define __lcd_enable_hsync_mode() ( REG_LCD_CFG &= ~LCD_CFG_HSYNM ) -+ -+#define __lcd_disable_pclk_mode() ( REG_LCD_CFG |= LCD_CFG_PCLKM ) -+#define __lcd_enable_pclk_mode() ( REG_LCD_CFG &= ~LCD_CFG_PCLKM ) -+ -+#define __lcd_normal_outdata() ( REG_LCD_CFG &= ~LCD_CFG_INVDAT ) -+#define __lcd_inverse_outdata() ( REG_LCD_CFG |= LCD_CFG_INVDAT ) -+ -+#define __lcd_sync_input() ( REG_LCD_CFG |= LCD_CFG_SYNDIR_IN ) -+#define __lcd_sync_output() ( REG_LCD_CFG &= ~LCD_CFG_SYNDIR_IN ) -+ -+#define __lcd_hsync_active_high() ( REG_LCD_CFG &= ~LCD_CFG_HSP ) -+#define __lcd_hsync_active_low() ( REG_LCD_CFG |= LCD_CFG_HSP ) -+ -+#define __lcd_pclk_rising() ( REG_LCD_CFG &= ~LCD_CFG_PCP ) -+#define __lcd_pclk_falling() ( REG_LCD_CFG |= LCD_CFG_PCP ) -+ -+#define __lcd_de_active_high() ( REG_LCD_CFG &= ~LCD_CFG_DEP ) -+#define __lcd_de_active_low() ( REG_LCD_CFG |= LCD_CFG_DEP ) -+ -+#define __lcd_vsync_rising() ( REG_LCD_CFG &= ~LCD_CFG_VSP ) -+#define __lcd_vsync_falling() ( REG_LCD_CFG |= LCD_CFG_VSP ) -+ -+#define __lcd_set_16_tftpnl() \ -+ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_16BIT ) -+ -+#define __lcd_set_18_tftpnl() \ -+ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_18BIT ) -+ -+#define __lcd_set_24_tftpnl() ( REG_LCD_CFG |= LCD_CFG_MODE_TFT_24BIT ) -+ -+/* -+ * n=1,2,4,8 for single mono-STN -+ * n=4,8 for dual mono-STN -+ */ -+#define __lcd_set_panel_datawidth(n) \ -+do { \ -+ REG_LCD_CFG &= ~LCD_CFG_PDW_MASK; \ -+ REG_LCD_CFG |= LCD_CFG_PDW_n##; \ -+} while (0) -+ -+/* m = LCD_CFG_MODE_GENERUIC_TFT_xxx */ -+#define __lcd_set_panel_mode(m) \ -+do { \ -+ REG_LCD_CFG &= ~LCD_CFG_MODE_MASK; \ -+ REG_LCD_CFG |= (m); \ -+} while(0) -+ -+/* n=4,8,16 */ -+#define __lcd_set_burst_length(n) \ -+do { \ -+ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \ -+ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \ -+} while (0) -+ -+#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 ) -+#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 ) -+ -+#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP ) -+#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP ) -+ -+/* n=2,4,16 */ -+#define __lcd_set_stn_frc(n) \ -+do { \ -+ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \ -+ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \ -+} while (0) -+ -+#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM ) -+#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM ) -+ -+#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM ) -+#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM ) -+ -+#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM ) -+#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM ) -+ -+#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 ) -+#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 ) -+ -+#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 ) -+#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 ) -+ -+#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM ) -+#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM ) -+ -+#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM ) -+#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM ) -+ -+#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN ) -+#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN ) -+ -+#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN ) -+#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN ) -+ -+#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS ) -+#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS ) -+ -+#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA ) -+#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA ) -+ -+/* n=1,2,4,8,16 */ -+#define __lcd_set_bpp(n) \ -+ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n ) -+ -+/* LCD status register indication */ -+ -+#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD ) -+#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD ) -+#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 ) -+#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 ) -+#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU ) -+#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF ) -+#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF ) -+ -+#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU ) -+#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF ) -+#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF ) -+ -+/* OSD functions */ -+#define __lcd_enable_osd() (REG_LCD_OSDC |= LCD_OSDC_OSDEN) -+#define __lcd_enable_f0() (REG_LCD_OSDC |= LCD_OSDC_F0EN) -+#define __lcd_enable_f1() (REG_LCD_OSDC |= LCD_OSDC_F1EN) -+#define __lcd_enable_alpha() (REG_LCD_OSDC |= LCD_OSDC_ALPHAEN) -+#define __lcd_enable_alphamd() (REG_LCD_OSDC |= LCD_OSDC_ALPHAMD) -+ -+#define __lcd_disable_osd() (REG_LCD_OSDC &= ~LCD_OSDC_OSDEN) -+#define __lcd_disable_f0() (REG_LCD_OSDC &= ~LCD_OSDC_F0EN) -+#define __lcd_disable_f1() (REG_LCD_OSDC &= ~LCD_OSDC_F1EN) -+#define __lcd_disable_alpha() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAEN) -+#define __lcd_disable_alphamd() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAMD) -+ -+/* OSD Controll Register */ -+#define __lcd_fg1_use_ipu() (REG_LCD_OSDCTRL |= LCD_OSDCTRL_IPU) -+#define __lcd_fg1_use_dma_chan1() (REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_IPU) -+#define __lcd_fg1_unuse_ipu() __lcd_fg1_use_dma_chan1() -+#define __lcd_osd_rgb555_mode() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_RGB555 ) -+#define __lcd_osd_rgb565_mode() ( REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_RGB555 ) -+#define __lcd_osd_change_size() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_CHANGES ) -+#define __lcd_osd_bpp_15_16() \ -+ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_15_16 ) -+#define __lcd_osd_bpp_18_24() \ -+ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_18_24 ) -+ -+/* OSD State Register */ -+#define __lcd_start_of_fg1() ( REG_LCD_STATE & LCD_OSDS_SOF1 ) -+#define __lcd_end_of_fg1() ( REG_LCD_STATE & LCD_OSDS_EOF1 ) -+#define __lcd_start_of_fg0() ( REG_LCD_STATE & LCD_OSDS_SOF0 ) -+#define __lcd_end_of_fg0() ( REG_LCD_STATE & LCD_OSDS_EOF0 ) -+#define __lcd_change_is_rdy() ( REG_LCD_STATE & LCD_OSDS_READY ) -+ -+/* Foreground Color Key Register 0,1(foreground 0, foreground 1) */ -+#define __lcd_enable_colorkey0() (REG_LCD_KEY0 |= LCD_KEY_KEYEN) -+#define __lcd_enable_colorkey1() (REG_LCD_KEY1 |= LCD_KEY_KEYEN) -+#define __lcd_enable_colorkey0_md() (REG_LCD_KEY0 |= LCD_KEY_KEYMD) -+#define __lcd_enable_colorkey1_md() (REG_LCD_KEY1 |= LCD_KEY_KEYMD) -+#define __lcd_set_colorkey0(key) (REG_LCD_KEY0 = (REG_LCD_KEY0&~0xFFFFFF)|(key)) -+#define __lcd_set_colorkey1(key) (REG_LCD_KEY1 = (REG_LCD_KEY1&~0xFFFFFF)|(key)) -+ -+#define __lcd_disable_colorkey0() (REG_LCD_KEY0 &= ~LCD_KEY_KEYEN) -+#define __lcd_disable_colorkey1() (REG_LCD_KEY1 &= ~LCD_KEY_KEYEN) -+#define __lcd_disable_colorkey0_md() (REG_LCD_KEY0 &= ~LCD_KEY_KEYMD) -+#define __lcd_disable_colorkey1_md() (REG_LCD_KEY1 &= ~LCD_KEY_KEYMD) -+ -+/* IPU Restart Register */ -+#define __lcd_enable_ipu_restart() (REG_LCD_IPUR |= LCD_IPUR_IPUREN) -+#define __lcd_disable_ipu_restart() (REG_LCD_IPUR &= ~LCD_IPUR_IPUREN) -+#define __lcd_set_ipu_restart_triger(n) (REG_LCD_IPUR = (REG_LCD_IPUR&(~0xFFFFFF))|(n)) -+ -+/* RGB Control Register */ -+#define __lcd_enable_rgb_dummy() (REG_LCD_RGBC |= LCD_RGBC_RGBDM) -+#define __lcd_disable_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_RGBDM) -+ -+#define __lcd_dummy_rgb() (REG_LCD_RGBC |= LCD_RGBC_DMM) -+#define __lcd_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_DMM) -+ -+#define __lcd_rgb2ycc() (REG_LCD_RGBC |= LCD_RGBC_YCC) -+#define __lcd_notrgb2ycc() (REG_LCD_RGBC &= ~LCD_RGBC_YCC) -+ -+#define __lcd_odd_mode_rgb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RGB ) -+#define __lcd_odd_mode_rbg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RBG ) -+#define __lcd_odd_mode_grb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GRB) -+ -+#define __lcd_odd_mode_gbr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GBR) -+#define __lcd_odd_mode_brg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BRG) -+#define __lcd_odd_mode_bgr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BGR) -+ -+#define __lcd_even_mode_rgb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RGB ) -+#define __lcd_even_mode_rbg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RBG ) -+#define __lcd_even_mode_grb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GRB) -+ -+#define __lcd_even_mode_gbr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GBR) -+#define __lcd_even_mode_brg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BRG) -+#define __lcd_even_mode_bgr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BGR) -+ -+/* Vertical Synchronize Register */ -+#define __lcd_vsync_get_vps() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT ) -+ -+#define __lcd_vsync_get_vpe() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -+#define __lcd_vsync_set_vpe(n) \ -+do { \ -+ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -+ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hps() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -+#define __lcd_hsync_set_hps(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hpe() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -+#define __lcd_hsync_set_hpe(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_ht() \ -+ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -+#define __lcd_vat_set_ht(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_vt() \ -+ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -+#define __lcd_vat_set_vt(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hds() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -+#define __lcd_dah_set_hds(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hde() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -+#define __lcd_dah_set_hde(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vds() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -+#define __lcd_dav_set_vds(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vde() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -+#define __lcd_dav_set_vde(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -+} while (0) -+ -+/* DMA Command Register */ -+#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -+#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -+ -+#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -+#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -+ -+#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -+#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -+ -+#define __lcd_cmd0_get_len() \ -+ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+#define __lcd_cmd1_get_len() \ -+ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+ -+/************************************************************************* -+ * TVE (TV Encoder Controller) ops -+ *************************************************************************/ -+/* TV Encoder Control register ops */ -+#define __tve_soft_reset() (REG_TVE_CTRL |= TVE_CTRL_SWRST) -+ -+#define __tve_output_colorbar() (REG_TVE_CTRL |= TVE_CTRL_CLBAR) -+#define __tve_output_video() (REG_TVE_CTRL &= ~TVE_CTRL_CLBAR) -+ -+#define __tve_input_cr_first() (REG_TVE_CTRL |= TVE_CTRL_CR1ST) -+#define __tve_input_cb_first() (REG_TVE_CTRL &= ~TVE_CTRL_CR1ST) -+ -+#define __tve_set_0_as_black() (REG_TVE_CTRL |= TVE_CTRL_ZBLACK) -+#define __tve_set_16_as_black() (REG_TVE_CTRL &= ~TVE_CTRL_ZBLACK) -+ -+#define __tve_ena_invert_top_bottom() (REG_TVE_CTRL |= TVE_CTRL_FINV) -+#define __tve_dis_invert_top_bottom() (REG_TVE_CTRL &= ~TVE_CTRL_FINV) -+ -+#define __tve_set_pal_mode() (REG_TVE_CTRL |= TVE_CTRL_PAL) -+#define __tve_set_ntsc_mode() (REG_TVE_CTRL &= ~TVE_CTRL_PAL) -+ -+#define __tve_set_pal_dura() (REG_TVE_CTRL |= TVE_CTRL_SYNCT) -+#define __tve_set_ntsc_dura() (REG_TVE_CTRL &= ~TVE_CTRL_SYNCT) -+ -+/* n = 0 ~ 3 */ -+#define __tve_set_c_bandwidth(n) \ -+do {\ -+ REG_TVE_CTRL &= ~TVE_CTRL_CBW_MASK;\ -+ REG_TVE_CTRL |= (n) << TVE_CTRL_CBW_BIT; \ -+}while(0) -+ -+/* n = 0 ~ 3 */ -+#define __tve_set_c_gain(n) \ -+do {\ -+ REG_TVE_CTRL &= ~TVE_CTRL_CGAIN_MASK;\ -+ (REG_TVE_CTRL |= (n) << TVE_CTRL_CGAIN_BIT; \ -+}while(0) -+ -+/* n = 0 ~ 7 */ -+#define __tve_set_yc_delay(n) \ -+do { \ -+ REG_TVE_CTRL &= ~TVE_CTRL_YCDLY_MASK \ -+ REG_TVE_CTRL |= ((n) << TVE_CTRL_YCDLY_BIT); \ -+} while(0) -+ -+#define __tve_disable_all_dacs() (REG_TVE_CTRL |= TVE_CTRL_DAPD) -+#define __tve_disable_dac1() (REG_TVE_CTRL |= TVE_CTRL_DAPD1) -+#define __tve_enable_dac1() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD1) -+#define __tve_disable_dac2() (REG_TVE_CTRL |= TVE_CTRL_DAPD2) -+#define __tve_enable_dac2() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD2) -+#define __tve_disable_dac3() (REG_TVE_CTRL |= TVE_CTRL_DAPD3) -+#define __tve_enable_dac3() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD3) -+ -+#define __tve_enable_svideo_fmt() (REG_TVE_CTRL |= TVE_CTRL_ECVBS) -+#define __tve_enable_cvbs_fmt() (REG_TVE_CTRL &= ~TVE_CTRL_ECVBS) -+ -+/* TV Encoder Frame Configure register ops */ -+/* n = 0 ~ 255 */ -+#define __tve_set_first_video_line(n) \ -+do {\ -+ REG_TVE_FRCFG &= ~TVE_FRCFG_L1ST_MASK;\ -+ REG_TVE_FRCFG |= (n) << TVE_FRCFG_L1ST_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_line_num_per_frm(n) \ -+do {\ -+ REG_TVE_FRCFG &= ~TVE_FRCFG_NLINE_MASK;\ -+ REG_TVE_CFG |= (n) << TVE_FRCFG_NLINE_BIT;\ -+} while(0) -+#define __tve_get_video_line_num()\ -+ (((REG_TVE_FRCFG & TVE_FRCFG_NLINE_MASK) >> TVE_FRCFG_NLINE_BIT) - 1 - 2 * ((REG_TVE_FRCFG & TVE_FRCFG_L1ST_MASK) >> TVE_FRCFG_L1ST_BIT)) -+ -+/* TV Encoder Signal Level Configure register ops */ -+/* n = 0 ~ 1023 */ -+#define __tve_set_white_level(n) \ -+do {\ -+ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_WHITEL_MASK;\ -+ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_WHITEL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_black_level(n) \ -+do {\ -+ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_BLACKL_MASK;\ -+ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_BLACKL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_blank_level(n) \ -+do {\ -+ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_BLANKL_MASK;\ -+ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_BLANKL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_vbi_blank_level(n) \ -+do {\ -+ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_VBLANKL_MASK;\ -+ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_VBLANKL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_sync_level(n) \ -+do {\ -+ REG_TVE_SLCFG3 &= ~TVE_SLCFG3_SYNCL_MASK;\ -+ REG_TVE_SLCFG3 |= (n) << TVE_SLCFG3_SYNCL_BIT;\ -+} while(0) -+ -+/* TV Encoder Signal Level Configure register ops */ -+/* n = 0 ~ 31 */ -+#define __tve_set_front_porch(n) \ -+do {\ -+ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_FRONTP_MASK;\ -+ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_FRONTP_BIT; \ -+} while(0) -+/* n = 0 ~ 127 */ -+#define __tve_set_hsync_width(n) \ -+do {\ -+ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_HSYNCW_MASK;\ -+ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_HSYNCW_BIT; \ -+} while(0) -+/* n = 0 ~ 127 */ -+#define __tve_set_back_porch(n) \ -+do {\ -+ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_BACKP_MASK;\ -+ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_BACKP_BIT; \ -+} while(0) -+/* n = 0 ~ 2047 */ -+#define __tve_set_active_linec(n) \ -+do {\ -+ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_ACTLIN_MASK;\ -+ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_ACTLIN_BIT; \ -+} while(0) -+/* n = 0 ~ 31 */ -+#define __tve_set_breezy_way(n) \ -+do {\ -+ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_PREBW_MASK;\ -+ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_PREBW_BIT; \ -+} while(0) -+ -+/* n = 0 ~ 127 */ -+#define __tve_set_burst_width(n) \ -+do {\ -+ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_BURSTW_MASK;\ -+ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_BURSTW_BIT; \ -+} while(0) -+ -+/* TV Encoder Chrominance filter and Modulation register ops */ -+/* n = 0 ~ (2^32-1) */ -+#define __tve_set_c_sub_carrier_freq(n) REG_TVE_CFREQ = (n) -+/* n = 0 ~ 255 */ -+#define __tve_set_c_sub_carrier_init_phase(n) \ -+do { \ -+ REG_TVE_CPHASE &= ~TVE_CPHASE_INITPH_MASK; \ -+ REG_TVE_CPHASE |= (n) << TVE_CPHASE_INITPH_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_c_sub_carrier_act_phase(n) \ -+do { \ -+ REG_TVE_CPHASE &= ~TVE_CPHASE_ACTPH_MASK; \ -+ REG_TVE_CPHASE |= (n) << TVE_CPHASE_ACTPH_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_c_phase_rst_period(n) \ -+do { \ -+ REG_TVE_CPHASE &= ~TVE_CPHASE_CCRSTP_MASK; \ -+ REG_TVE_CPHASE |= (n) << TVE_CPHASE_CCRSTP_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cb_burst_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBBA_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBBA_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cr_burst_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRBA_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRBA_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cb_gain_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBGAIN_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBGAIN_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cr_gain_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRGAIN_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRGAIN_BIT; \ -+} while(0) -+ -+/* TV Encoder Wide Screen Signal Control register ops */ -+/* n = 0 ~ 7 */ -+#define __tve_set_notch_freq(n) \ -+do { \ -+ REG_TVE_WSSCR &= ~TVE_WSSCR_NCHFREQ_MASK; \ -+ REG_TVE_WSSCR |= (n) << TVE_WSSCR_NCHFREQ_BIT; \ -+} while(0) -+/* n = 0 ~ 7 */ -+#define __tve_set_notch_width() (REG_TVE_WSSCR |= TVE_WSSCR_NCHW_BIT) -+#define __tve_clear_notch_width() (REG_TVE_WSSCR &= ~TVE_WSSCR_NCHW_BIT) -+#define __tve_enable_notch() (REG_TVE_WSSCR |= TVE_WSSCR_ENCH_BIT) -+#define __tve_disable_notch() (REG_TVE_WSSCR &= ~TVE_WSSCR_ENCH_BIT) -+/* n = 0 ~ 7 */ -+#define __tve_set_wss_edge(n) \ -+do { \ -+ REG_TVE_WSSCR &= ~TVE_WSSCR_WSSEDGE_MASK; \ -+ REG_TVE_WSSCR |= (n) << TVE_WSSCR_WSSEDGE_BIT; \ -+} while(0) -+#define __tve_set_wss_clkbyp() (REG_TVE_WSSCR |= TVE_WSSCR_WSSCKBP_BIT) -+#define __tve_set_wss_type() (REG_TVE_WSSCR |= TVE_WSSCR_WSSTP_BIT) -+#define __tve_enable_wssf1() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS1_BIT) -+#define __tve_enable_wssf0() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS0_BIT) -+ -+/* TV Encoder Wide Screen Signal Configure register 1, 2 and 3 ops */ -+/* n = 0 ~ 1023 */ -+#define __tve_set_wss_level(n) \ -+do { \ -+ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSL_MASK; \ -+ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSL_BIT; \ -+} while(0) -+/* n = 0 ~ 4095 */ -+#define __tve_set_wss_freq(n) \ -+do { \ -+ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSFREQ_MASK; \ -+ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSFREQ_BIT; \ -+} while(0) -+/* n = 0, 1; l = 0 ~ 255 */ -+#define __tve_set_wss_line(n,v) \ -+do { \ -+ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -+ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -+} while(0) -+/* n = 0, 1; d = 0 ~ (2^20-1) */ -+#define __tve_set_wss_data(n, v) \ -+do { \ -+ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -+ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -+} while(0) -+ -+/*************************************************************************** -+ * RTC ops -+ ***************************************************************************/ -+ -+#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) -+#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) -+#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) -+#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -+#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -+#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -+#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -+#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) -+#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) -+ -+#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) -+#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) -+#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) -+#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -+ -+#define __rtc_get_second() ( REG_RTC_RSR ) -+#define __rtc_set_second(v) ( REG_RTC_RSR = v ) -+ -+#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) -+#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) -+ -+#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) -+#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -+#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) -+#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) -+#define __rtc_set_adjc_val(v) \ -+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) -+#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) -+#define __rtc_set_nc1Hz_val(v) \ -+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) -+ -+#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) -+ -+#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) -+#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) -+#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) -+#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) -+ -+#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) -+#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) -+ -+#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) -+#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) -+#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) -+#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) -+#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) -+ -+#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) -+#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) -+ -+/************************************************************************* -+ * BCH -+ *************************************************************************/ -+#define __ecc_encoding_4bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BCHE; \ -+ REG_BCH_CRC = BCH_CR_BSEL8; \ -+} while(0) -+#define __ecc_decoding_4bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BCHE; \ -+ REG_BCH_CRC = BCH_CR_ENCE | BCH_CR_BSEL8; \ -+} while(0) -+#define __ecc_encoding_8bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -+} while(0) -+#define __ecc_decoding_8bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -+ REG_BCH_CRC = BCH_CR_ENCE; \ -+} while(0) -+#define __ecc_dma_enable() ( REG_BCH_CRS = BCH_CR_DMAE ) -+#define __ecc_dma_disable() ( REG_BCH_CRC = BCH_CR_DMAE ) -+#define __ecc_disable() ( REG_BCH_CRC = BCH_CR_BCHE ) -+#define __ecc_encode_sync() while (!(REG_BCH_INTS & BCH_INTS_ENCF)) -+#define __ecc_decode_sync() while (!(REG_BCH_INTS & BCH_INTS_DECF)) -+#define __ecc_cnt_dec(n) \ -+do { \ -+ REG_BCH_CNT &= ~(BCH_CNT_DEC_MASK << BCH_CNT_DEC_BIT); \ -+ REG_BCH_CNT = (n) << BCH_CNT_DEC_BIT; \ -+} while(0) -+#define __ecc_cnt_enc(n) \ -+do { \ -+ REG_BCH_CNT &= ~(BCH_CNT_ENC_MASK << BCH_CNT_ENC_BIT); \ -+ REG_BCH_CNT = (n) << BCH_CNT_ENC_BIT; \ -+} while(0) -+ -+/*************************************************************************** -+ * OWI (one-wire bus) ops -+ ***************************************************************************/ -+ -+/* OW control register ops */ -+#define __owi_enable_all_interrupts() ( REG_OWI_CTL = (OWI_CTL_EBYTE | OWI_CTL_EBIT | OWI_CTL_ERST) ) -+#define __owi_disable_all_interrupts() ( REG_OWI_CTL = 0 ) -+ -+#define __owi_enable_byte_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBYTE ) -+#define __owi_disable_byte_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBYTE ) -+#define __owi_enable_bit_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBIT ) -+#define __owi_disable_bit_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBIT ) -+#define __owi_enable_rst_interrupt() ( REG_OWI_CTL |= OWI_CTL_ERST ) -+#define __owi_disable_rst_interrupt() ( REG_OWI_CTL &=~OWI_CTL_ERST ) -+ -+/* OW configure register ops */ -+#define __owi_select_regular_mode() ( REG_OWI_CFG &= ~OWI_CFG_MODE ) -+#define __owi_select_overdrive_mode() ( REG_OWI_CFG |= OWI_CFG_MODE ) -+ -+#define __owi_set_rddata() ( REG_OWI_CFG |= OWI_CFG_RDDATA ) -+#define __owi_clr_rddata() ( REG_OWI_CFG &= ~OWI_CFG_RDDATA ) -+#define __owi_get_rddata() ( REG_OWI_CFG & OWI_CFG_RDDATA ) -+ -+#define __owi_set_wrdata() ( REG_OWI_CFG |= OWI_CFG_WRDATA ) -+#define __owi_clr_wrdata() ( REG_OWI_CFG &= ~OWI_CFG_WRDATA ) -+#define __owi_get_wrdata() ( REG_OWI_CFG & OWI_CFG_WRDATA ) -+ -+#define __owi_get_rdst() ( REG_OWI_CFG & OWI_CFG_RDST ) -+ -+#define __owi_set_wr1rd() ( REG_OWI_CFG |= OWI_CFG_WR1RD ) -+#define __owi_clr_wr1rd() ( REG_OWI_CFG &= ~OWI_CFG_WR1RD ) -+#define __owi_get_wr1rd() ( REG_OWI_CFG & OWI_CFG_WR1RD ) -+ -+#define __owi_set_wr0() ( REG_OWI_CFG |= OWI_CFG_WR0 ) -+#define __owi_clr_wr0() ( REG_OWI_CFG &= ~OWI_CFG_WR0 ) -+#define __owi_get_wr0() ( REG_OWI_CFG & OWI_CFG_WR0 ) -+ -+#define __owi_set_rst() ( REG_OWI_CFG |= OWI_CFG_RST ) -+#define __owi_clr_rst() ( REG_OWI_CFG &= ~OWI_CFG_RST ) -+#define __owi_get_rst() ( REG_OWI_CFG & OWI_CFG_RST ) -+ -+#define __owi_enable_ow_ops() ( REG_OWI_CFG |= OWI_CFG_ENA ) -+#define __owi_disable_ow_ops() ( REG_OWI_CFG &= ~OWI_CFG_ENA ) -+#define __owi_get_enable() ( REG_OWI_CFG & OWI_CFG_ENA ) -+ -+#define __owi_wait_ops_rdy() \ -+ do { \ -+ while(__owi_get_enable()); \ -+ udelay(1); \ -+ } while(0); -+ -+/* OW status register ops */ -+#define __owi_clr_sts() ( REG_OWI_STS = 0 ) -+#define __owi_get_sts_pst() ( REG_OWI_STS & OWI_STS_PST ) -+#define __owi_get_sts_byte_rdy() ( REG_OWI_STS & OWI_STS_BYTE_RDY ) -+#define __owi_get_sts_bit_rdy() ( REG_OWI_STS & OWI_STS_BIT_RDY ) -+#define __owi_get_sts_pst_rdy() ( REG_OWI_STS & OWI_STS_PST_RDY ) -+ -+/************************************************************************* -+ * TSSI MPEG 2-TS slave interface operation -+ *************************************************************************/ -+#define __tssi_enable() ( REG_TSSI_ENA |= TSSI_ENA_ENA ) -+#define __tssi_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_ENA ) -+#define __tssi_soft_reset() ( REG_TSSI_ENA |= TSSI_ENA_SFT_RST ) -+#define __tssi_dma_enable() ( REG_TSSI_ENA |= TSSI_ENA_DMA_EN ) -+#define __tssi_dma_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_DMA_EN ) -+#define __tssi_filter_enable() ( REG_TSSI_ENA |= TSSI_ENA_PID_EN ) -+#define __tssi_filter_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_PID_EN ) -+ -+/* n = 4, 8, 16 */ -+#define __tssi_set_tigger_num(n) \ -+ do { \ -+ REG_TSSI_CFG &= ~TSSI_CFG_TRIG_MASK; \ -+ REG_TSSI_CFG |= TSSI_CFG_TRIG_##n; \ -+ } while (0) -+ -+#define __tssi_set_wd_1() ( REG_TSSI_CFG |= TSSI_CFG_END_WD ) -+#define __tssi_set_wd_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_WD ) -+ -+#define __tssi_set_bt_1() ( REG_TSSI_CFG |= TSSI_CFG_END_BD ) -+#define __tssi_set_bt_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_BD ) -+ -+#define __tssi_set_data_pola_high() ( REG_TSSI_CFG |= TSSI_CFG_TSDI_H ) -+#define __tssi_set_data_pola_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSDI_H ) -+ -+#define __tssi_set_data_use_data0() ( REG_TSSI_CFG |= TSSI_CFG_USE_0 ) -+#define __tssi_set_data_use_data7() ( REG_TSSI_CFG &= ~TSSI_CFG_USE_0 ) -+ -+#define __tssi_select_clk_fast() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_CH ) -+#define __tssi_select_clk_slow() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_CH ) -+ -+#define __tssi_select_serail_mode() ( REG_TSSI_CFG &= ~TSSI_CFG_PARAL ) -+#define __tssi_select_paral_mode() ( REG_TSSI_CFG |= TSSI_CFG_PARAL ) -+ -+#define __tssi_select_clk_nega_edge() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_P ) -+#define __tssi_select_clk_posi_edge() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_P ) -+ -+#define __tssi_select_frm_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFRM_H ) -+#define __tssi_select_frm_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFRM_H ) -+ -+#define __tssi_select_str_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSSTR_H ) -+#define __tssi_select_str_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSSTR_H ) -+ -+#define __tssi_select_fail_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFAIL_H ) -+#define __tssi_select_fail_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFAIL_H ) -+ -+#define __tssi_enable_ovrn_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_OVRNM ) -+#define __tssi_disable_ovrn_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_OVRNM ) -+ -+#define __tssi_enable_trig_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_TRIGM ) -+#define __tssi_disable_trig_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_TRIGM ) -+ -+#define __tssi_state_is_overrun() ( REG_TSSI_STAT & TSSI_STAT_OVRN ) -+#define __tssi_state_trigger_meet() ( REG_TSSI_STAT & TSSI_STAT_TRIG ) -+#define __tssi_clear_state() ( REG_TSSI_STAT = 0 ) /* write 0??? */ -+#define __tssi_state_clear_overrun() ( REG_TSSI_STAT = TSSI_STAT_OVRN ) -+ -+#define __tssi_enable_filte_pid0() ( REG_TSSI_PEN |= TSSI_PEN_PID0 ) -+#define __tssi_disable_filte_pid0() ( REG_TSSI_PEN &= ~TSSI_PEN_PID0 ) -+ -+/* m = 0, ..., 15 */ -+#define __tssi_enable_pid_filter(m) \ -+ do { \ -+ int n = (m); \ -+ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -+ if ( n >= TSSI_PID_MAX ) n += 8; \ -+ REG_TSSI_PEN |= ( 1 << n ); \ -+ } \ -+ } while (0) -+ -+/* m = 0, ..., 15 */ -+#define __tssi_disable_pid_filter(m) \ -+ do { \ -+ int n = (m); \ -+ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -+ if ( n >= TSSI_PID_MAX ) n += 8; \ -+ REG_TSSI_PEN &= ~( 1 << n ); \ -+ } \ -+ } while (0) -+ -+/* n = 0, ..., 7 */ -+#define __tssi_set_pid0(n, pid0) \ -+ do { \ -+ REG_TSSI_PID(n) &= ~TSSI_PID_PID0_MASK; \ -+ REG_TSSI_PID(n) |= ((pid0)<=0 && n < TSSI_PID_MAX*2) { \ -+ if ( n < TSSI_PID_MAX ) \ -+ __tssi_set_pid0(n, pid); \ -+ else \ -+ __tssi_set_pid1(n-TSSI_PID_MAX, pid); \ -+ } \ -+ }while (0) -+ -+ -+#if 0 -+/************************************************************************* -+ * IPU (Image Processing Unit) -+ *************************************************************************/ -+#define u32 volatile unsigned long -+ -+#define write_reg(reg, val) \ -+do { \ -+ *(u32 *)(reg) = (val); \ -+} while(0) -+ -+#define read_reg(reg, off) (*(u32 *)((reg)+(off))) -+ -+ -+#define set_ipu_fmt(rgb_888_out_fmt, rgb_out_oft, out_fmt, yuv_pkg_out, in_oft, in_fmt ) \ -+({ write_reg( (IPU_V_BASE + REG_D_FMT), ((in_fmt) & IN_FMT_MSK)< Unsigned toggle enable */ -+#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ -+#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ -+#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ -+#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ -+#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ -+#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ -+#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ -+#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ -+ -+/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -+ -+#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ -+#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -+ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ -+ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ -+ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ -+ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ -+ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ -+ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ -+#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ -+#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -+ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ -+ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ -+ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ -+ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ -+ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ -+ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ -+ -+/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -+ -+#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ -+#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ -+#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ -+#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ -+#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -+ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ -+#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -+ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ -+#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ -+#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ -+#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ -+ -+/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -+ -+#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ -+#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ -+#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -+ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -+ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -+ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -+ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -+ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -+#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ -+ -+/* AIC Controller FIFO Status Register (AIC_SR) */ -+ -+#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ -+#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) -+#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ -+#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) -+#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ -+#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ -+#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ -+#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ -+ -+/* AIC Controller AC-link Status Register (AIC_ACSR) */ -+ -+#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ -+#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ -+#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ -+#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ -+#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ -+#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ -+ -+/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -+ -+#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ -+ -+/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -+ -+#define AIC_ACCAR_CAR_BIT 0 -+#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -+ -+/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -+ -+#define AIC_ACCDR_CDR_BIT 0 -+#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -+ -+/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -+ -+#define AIC_ACSAR_SAR_BIT 0 -+#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -+ -+/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -+ -+#define AIC_ACSDR_SDR_BIT 0 -+#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -+ -+/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -+ -+#define AIC_I2SDIV_DIV_BIT 0 -+#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -+ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -+ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -+ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -+ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -+ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -+ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -+ -+ -+/************************************************************************* -+ * ICDC (Internal CODEC) -+ *************************************************************************/ -+ -+#define ICDC_CKCFG (ICDC_BASE + 0x00a0) /* Clock Configure Register */ -+#define ICDC_RGADW (ICDC_BASE + 0x00a4) /* internal register access control */ -+#define ICDC_RGDATA (ICDC_BASE + 0x00a8) /* internal register data output */ -+ -+#define REG_ICDC_CKCFG REG32(ICDC_CKCFG) -+#define REG_ICDC_RGADW REG32(ICDC_RGADW) -+#define REG_ICDC_RGDATA REG32(ICDC_RGDATA) -+ -+/* ICDC Clock Configure Register */ -+#define ICDC_CKCFG_CKRDY (1 << 1) -+#define ICDC_CKCFG_SELAD (1 << 0) -+ -+/* ICDC internal register access control Register */ -+#define ICDC_RGADW_RGWR (1 << 16) -+#define ICDC_RGADW_RGADDR_BIT 8 -+#define ICDC_RGADW_RGADDR_MASK (0x7f << ICDC_RGADW_RGADDR_BIT) -+#define ICDC_RGADW_RGDIN_BIT 0 -+#define ICDC_RGADW_RGDIN_MASK (0xff << ICDC_RGADW_RGDIN_BIT) -+ -+/* ICDC internal register data output Register */ -+#define ICDC_RGDATA_IRQ (1 << 8) -+#define ICDC_RGDATA_RGDOUT_BIT 0 -+#define ICDC_RGDATA_RGDOUT_MASK (0xff << ICDC_RGDATA_RGDOUT_BIT) -+ -+/************************************************************************* -+ * PCM Controller -+ *************************************************************************/ -+ -+#define PCM_CTL (PCM_BASE + 0x000) -+#define PCM_CFG (PCM_BASE + 0x004) -+#define PCM_DP (PCM_BASE + 0x008) -+#define PCM_INTC (PCM_BASE + 0x00c) -+#define PCM_INTS (PCM_BASE + 0x010) -+#define PCM_DIV (PCM_BASE + 0x014) -+ -+#define REG_PCM_CTL REG32(PCM_CTL) -+#define REG_PCM_CFG REG32(PCM_CFG) -+#define REG_PCM_DP REG32(PCM_DP) -+#define REG_PCM_INTC REG32(PCM_INTC) -+#define REG_PCM_INTS REG32(PCM_INTS) -+#define REG_PCM_DIV REG32(PCM_DIV) -+ -+/* PCM Controller control Register (PCM_CTL) */ -+ -+#define PCM_CTL_ERDMA (1 << 9) /* Enable Receive DMA */ -+#define PCM_CTL_ETDMA (1 << 8) /* Enable Transmit DMA */ -+#define PCM_CTL_LSMP (1 << 7) /* Play Zero sample or last sample */ -+#define PCM_CTL_ERPL (1 << 6) /* Enable Playing Back Function */ -+#define PCM_CTL_EREC (1 << 5) /* Enable Recording Function */ -+#define PCM_CTL_FLUSH (1 << 4) /* FIFO flush */ -+#define PCM_CTL_RST (1 << 3) /* Reset PCM */ -+#define PCM_CTL_CLKEN (1 << 1) /* Enable the clock division logic */ -+#define PCM_CTL_PCMEN (1 << 0) /* Enable PCM module */ -+ -+/* PCM Controller configure Register (PCM_CFG) */ -+ -+#define PCM_CFG_SLOT_BIT 13 -+#define PCM_CFG_SLOT_MASK (0x3 << PCM_CFG_SLOT_BIT) -+ #define PCM_CFG_SLOT_0 (0 << PCM_CFG_SLOT_BIT) /* Slot is 0 */ -+ #define PCM_CFG_SLOT_1 (1 << PCM_CFG_SLOT_BIT) /* Slot is 1 */ -+ #define PCM_CFG_SLOT_2 (2 << PCM_CFG_SLOT_BIT) /* Slot is 2 */ -+ #define PCM_CFG_SLOT_3 (3 << PCM_CFG_SLOT_BIT) /* Slot is 3 */ -+#define PCM_CFG_ISS_BIT 12 -+#define PCM_CFG_ISS_MASK (0x1 << PCM_CFG_ISS_BIT) -+ #define PCM_CFG_ISS_8 (0 << PCM_CFG_ISS_BIT) -+ #define PCM_CFG_ISS_16 (1 << PCM_CFG_ISS_BIT) -+#define PCM_CFG_OSS_BIT 11 -+#define PCM_CFG_OSS_MASK (0x1 << PCM_CFG_OSS_BIT) -+ #define PCM_CFG_OSS_8 (0 << PCM_CFG_OSS_BIT) -+ #define PCM_CFG_OSS_16 (1 << PCM_CFG_OSS_BIT) -+#define PCM_CFG_IMSBPOS (1 << 10) -+#define PCM_CFG_OMSBPOS (1 << 9) -+#define PCM_CFG_RFTH_BIT 5 /* Receive FIFO Threshold */ -+#define PCM_CFG_RFTH_MASK (0xf << PCM_CFG_RFTH_BIT) -+#define PCM_CFG_TFTH_BIT 1 /* Transmit FIFO Threshold */ -+#define PCM_CFG_TFTH_MASK (0xf << PCM_CFG_TFTH_BIT) -+#define PCM_CFG_MODE (0x0 << 0) -+ -+/* PCM Controller interrupt control Register (PCM_INTC) */ -+ -+#define PCM_INTC_ETFS (1 << 3) -+#define PCM_INTC_ETUR (1 << 2) -+#define PCM_INTC_ERFS (1 << 1) -+#define PCM_INTC_EROR (1 << 0) -+ -+/* PCM Controller interrupt status Register (PCM_INTS) */ -+ -+#define PCM_INTS_RSTS (1 << 14) /* Reset or flush has not complete */ -+#define PCM_INTS_TFL_BIT 9 -+#define PCM_INTS_TFL_MASK (0x1f << PCM_INTS_TFL_BIT) -+#define PCM_INTS_TFS (1 << 8) /* Tranmit FIFO Service Request */ -+#define PCM_INTS_TUR (1 << 7) /* Transmit FIFO Under Run */ -+#define PCM_INTS_RFL_BIT 2 -+#define PCM_INTS_RFL_MASK (0x1f << PCM_INTS_RFL_BIT) -+#define PCM_INTS_RFS (1 << 1) /* Receive FIFO Service Request */ -+#define PCM_INTS_ROR (1 << 0) /* Receive FIFO Over Run */ -+ -+/* PCM Controller clock division Register (PCM_DIV) */ -+#define PCM_DIV_SYNL_BIT 11 -+#define PCM_DIV_SYNL_MASK (0x3f << PCM_DIV_SYNL_BIT) -+#define PCM_DIV_SYNDIV_BIT 6 -+#define PCM_DIV_SYNDIV_MASK (0x1f << PCM_DIV_SYNDIV_BIT) -+#define PCM_DIV_CLKDIV_BIT 0 -+#define PCM_DIV_CLKDIV_MASK (0x3f << PCM_DIV_CLKDIV_BIT) -+ -+ -+/************************************************************************* -+ * I2C -+ *************************************************************************/ -+#define I2C_DR (I2C_BASE + 0x000) -+#define I2C_CR (I2C_BASE + 0x004) -+#define I2C_SR (I2C_BASE + 0x008) -+#define I2C_GR (I2C_BASE + 0x00C) -+ -+#define REG_I2C_DR REG8(I2C_DR) -+#define REG_I2C_CR REG8(I2C_CR) -+#define REG_I2C_SR REG8(I2C_SR) -+#define REG_I2C_GR REG16(I2C_GR) -+ -+/* I2C Control Register (I2C_CR) */ -+ -+#define I2C_CR_IEN (1 << 4) -+#define I2C_CR_STA (1 << 3) -+#define I2C_CR_STO (1 << 2) -+#define I2C_CR_AC (1 << 1) -+#define I2C_CR_I2CE (1 << 0) -+ -+/* I2C Status Register (I2C_SR) */ -+ -+#define I2C_SR_STX (1 << 4) -+#define I2C_SR_BUSY (1 << 3) -+#define I2C_SR_TEND (1 << 2) -+#define I2C_SR_DRF (1 << 1) -+#define I2C_SR_ACKF (1 << 0) -+ -+ -+/************************************************************************* -+ * SSI (Synchronous Serial Interface) -+ *************************************************************************/ -+/* n = 0, 1 (SSI0, SSI1) */ -+#define SSI_DR(n) (SSI_BASE + 0x000 + (n)*0x2000) -+#define SSI_CR0(n) (SSI_BASE + 0x004 + (n)*0x2000) -+#define SSI_CR1(n) (SSI_BASE + 0x008 + (n)*0x2000) -+#define SSI_SR(n) (SSI_BASE + 0x00C + (n)*0x2000) -+#define SSI_ITR(n) (SSI_BASE + 0x010 + (n)*0x2000) -+#define SSI_ICR(n) (SSI_BASE + 0x014 + (n)*0x2000) -+#define SSI_GR(n) (SSI_BASE + 0x018 + (n)*0x2000) -+ -+#define REG_SSI_DR(n) REG32(SSI_DR(n)) -+#define REG_SSI_CR0(n) REG16(SSI_CR0(n)) -+#define REG_SSI_CR1(n) REG32(SSI_CR1(n)) -+#define REG_SSI_SR(n) REG32(SSI_SR(n)) -+#define REG_SSI_ITR(n) REG16(SSI_ITR(n)) -+#define REG_SSI_ICR(n) REG8(SSI_ICR(n)) -+#define REG_SSI_GR(n) REG16(SSI_GR(n)) -+ -+/* SSI Data Register (SSI_DR) */ -+ -+#define SSI_DR_GPC_BIT 0 -+#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -+ -+#define SSI_MAX_FIFO_ENTRIES 128 /* 128 txfifo and 128 rxfifo */ -+ -+/* SSI Control Register 0 (SSI_CR0) */ -+ -+#define SSI_CR0_SSIE (1 << 15) -+#define SSI_CR0_TIE (1 << 14) -+#define SSI_CR0_RIE (1 << 13) -+#define SSI_CR0_TEIE (1 << 12) -+#define SSI_CR0_REIE (1 << 11) -+#define SSI_CR0_LOOP (1 << 10) -+#define SSI_CR0_RFINE (1 << 9) -+#define SSI_CR0_RFINC (1 << 8) -+#define SSI_CR0_EACLRUN (1 << 7) /* hardware auto clear underrun when TxFifo no empty */ -+#define SSI_CR0_FSEL (1 << 6) -+#define SSI_CR0_TFLUSH (1 << 2) -+#define SSI_CR0_RFLUSH (1 << 1) -+#define SSI_CR0_DISREV (1 << 0) -+ -+/* SSI Control Register 1 (SSI_CR1) */ -+ -+#define SSI_CR1_FRMHL_BIT 30 -+#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -+ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -+#define SSI_CR1_TFVCK_BIT 28 -+#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -+#define SSI_CR1_TCKFI_BIT 26 -+#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -+#define SSI_CR1_LFST (1 << 25) -+#define SSI_CR1_ITFRM (1 << 24) -+#define SSI_CR1_UNFIN (1 << 23) -+#define SSI_CR1_MULTS (1 << 22) -+#define SSI_CR1_FMAT_BIT 20 -+#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -+ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -+ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -+ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -+ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -+#define SSI_CR1_TTRG_BIT 16 /* SSI1 TX trigger */ -+#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) -+#define SSI_CR1_MCOM_BIT 12 -+#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -+ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -+ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -+ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -+ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -+ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -+ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -+ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -+ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -+ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -+ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -+ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -+ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -+ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -+ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -+ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -+ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -+#define SSI_CR1_RTRG_BIT 8 /* SSI RX trigger */ -+#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) -+#define SSI_CR1_FLEN_BIT 4 -+#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -+#define SSI_CR1_PHA (1 << 1) -+#define SSI_CR1_POL (1 << 0) -+ -+/* SSI Status Register (SSI_SR) */ -+ -+#define SSI_SR_TFIFONUM_BIT 16 -+#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) -+#define SSI_SR_RFIFONUM_BIT 8 -+#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) -+#define SSI_SR_END (1 << 7) -+#define SSI_SR_BUSY (1 << 6) -+#define SSI_SR_TFF (1 << 5) -+#define SSI_SR_RFE (1 << 4) -+#define SSI_SR_TFHE (1 << 3) -+#define SSI_SR_RFHF (1 << 2) -+#define SSI_SR_UNDR (1 << 1) -+#define SSI_SR_OVER (1 << 0) -+ -+/* SSI Interval Time Control Register (SSI_ITR) */ -+ -+#define SSI_ITR_CNTCLK (1 << 15) -+#define SSI_ITR_IVLTM_BIT 0 -+#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -+ -+ -+/************************************************************************* -+ * MSC -+ ************************************************************************/ -+/* n = 0, 1 (MSC0, MSC1) */ -+#define MSC_STRPCL(n) (MSC_BASE + (n)*0x1000 + 0x000) -+#define MSC_STAT(n) (MSC_BASE + (n)*0x1000 + 0x004) -+#define MSC_CLKRT(n) (MSC_BASE + (n)*0x1000 + 0x008) -+#define MSC_CMDAT(n) (MSC_BASE + (n)*0x1000 + 0x00C) -+#define MSC_RESTO(n) (MSC_BASE + (n)*0x1000 + 0x010) -+#define MSC_RDTO(n) (MSC_BASE + (n)*0x1000 + 0x014) -+#define MSC_BLKLEN(n) (MSC_BASE + (n)*0x1000 + 0x018) -+#define MSC_NOB(n) (MSC_BASE + (n)*0x1000 + 0x01C) -+#define MSC_SNOB(n) (MSC_BASE + (n)*0x1000 + 0x020) -+#define MSC_IMASK(n) (MSC_BASE + (n)*0x1000 + 0x024) -+#define MSC_IREG(n) (MSC_BASE + (n)*0x1000 + 0x028) -+#define MSC_CMD(n) (MSC_BASE + (n)*0x1000 + 0x02C) -+#define MSC_ARG(n) (MSC_BASE + (n)*0x1000 + 0x030) -+#define MSC_RES(n) (MSC_BASE + (n)*0x1000 + 0x034) -+#define MSC_RXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x038) -+#define MSC_TXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x03C) -+#define MSC_LPM(n) (MSC_BASE + (n)*0x1000 + 0x040) -+ -+#define REG_MSC_STRPCL(n) REG16(MSC_STRPCL(n)) -+#define REG_MSC_STAT(n) REG32(MSC_STAT(n)) -+#define REG_MSC_CLKRT(n) REG16(MSC_CLKRT(n)) -+#define REG_MSC_CMDAT(n) REG32(MSC_CMDAT(n)) -+#define REG_MSC_RESTO(n) REG16(MSC_RESTO(n)) -+#define REG_MSC_RDTO(n) REG16(MSC_RDTO(n)) -+#define REG_MSC_BLKLEN(n) REG16(MSC_BLKLEN(n)) -+#define REG_MSC_NOB(n) REG16(MSC_NOB(n)) -+#define REG_MSC_SNOB(n) REG16(MSC_SNOB(n)) -+#define REG_MSC_IMASK(n) REG32(MSC_IMASK(n)) -+#define REG_MSC_IREG(n) REG16(MSC_IREG(n)) -+#define REG_MSC_CMD(n) REG8(MSC_CMD(n)) -+#define REG_MSC_ARG(n) REG32(MSC_ARG(n)) -+#define REG_MSC_RES(n) REG16(MSC_RES(n)) -+#define REG_MSC_RXFIFO(n) REG32(MSC_RXFIFO(n)) -+#define REG_MSC_TXFIFO(n) REG32(MSC_TXFIFO(n)) -+#define REG_MSC_LPM(n) REG32(MSC_LPM(n)) -+ -+/* MSC Clock and Control Register (MSC_STRPCL) */ -+#define MSC_STRPCL_SEND_CCSD (1 << 15) /*send command completion signal disable to ceata */ -+#define MSC_STRPCL_SEND_AS_CCSD (1 << 14) /*send internally generated stop after sending ccsd */ -+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -+#define MSC_STRPCL_START_READWAIT (1 << 5) -+#define MSC_STRPCL_STOP_READWAIT (1 << 4) -+#define MSC_STRPCL_RESET (1 << 3) -+#define MSC_STRPCL_START_OP (1 << 2) -+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -+ -+/* MSC Status Register (MSC_STAT) */ -+#define MSC_STAT_AUTO_CMD_DONE (1 << 31) /*12 is internally generated by controller has finished */ -+#define MSC_STAT_IS_RESETTING (1 << 15) -+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -+#define MSC_STAT_PRG_DONE (1 << 13) -+#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -+#define MSC_STAT_END_CMD_RES (1 << 11) -+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -+#define MSC_STAT_IS_READWAIT (1 << 9) -+#define MSC_STAT_CLK_EN (1 << 8) -+#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -+#define MSC_STAT_CRC_RES_ERR (1 << 5) -+#define MSC_STAT_CRC_READ_ERROR (1 << 4) -+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -+#define MSC_STAT_TIME_OUT_RES (1 << 1) -+#define MSC_STAT_TIME_OUT_READ (1 << 0) -+ -+/* MSC Bus Clock Control Register (MSC_CLKRT) */ -+#define MSC_CLKRT_CLK_RATE_BIT 0 -+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -+ -+/* MSC Command Sequence Control Register (MSC_CMDAT) */ -+#define MSC_CMDAT_CCS_EXPECTED (1 << 31) /* interrupts are enabled in ce-ata */ -+#define MSC_CMDAT_READ_CEATA (1 << 30) -+#define MSC_CMDAT_SDIO_PRDT (1 << 17) /* exact 2 cycle */ -+#define MSC_CMDAT_SEND_AS_STOP (1 << 16) -+#define MSC_CMDAT_RTRG_BIT 14 -+ #define MSC_CMDAT_RTRG_EQUALT_8 (0x0 << MSC_CMDAT_RTRG_BIT) -+ #define MSC_CMDAT_RTRG_EQUALT_16 (0x1 << MSC_CMDAT_RTRG_BIT) /* reset value */ -+ #define MSC_CMDAT_RTRG_EQUALT_24 (0x2 << MSC_CMDAT_RTRG_BIT) -+ -+#define MSC_CMDAT_TTRG_BIT 12 -+ #define MSC_CMDAT_TTRG_LESS_8 (0x0 << MSC_CMDAT_TTRG_BIT) -+ #define MSC_CMDAT_TTRG_LESS_16 (0x1 << MSC_CMDAT_TTRG_BIT) /*reset value */ -+ #define MSC_CMDAT_TTRG_LESS_24 (0x2 << MSC_CMDAT_TTRG_BIT) -+#define MSC_CMDAT_STOP_ABORT (1 << 11) -+#define MSC_CMDAT_BUS_WIDTH_BIT 9 -+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -+ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -+ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -+ #define MSC_CMDAT_BUS_WIDTH_8BIT (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) /* 8-bit data bus */ -+#define MSC_CMDAT_DMA_EN (1 << 8) -+#define MSC_CMDAT_INIT (1 << 7) -+#define MSC_CMDAT_BUSY (1 << 6) -+#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -+#define MSC_CMDAT_WRITE (1 << 4) -+#define MSC_CMDAT_READ (0 << 4) -+#define MSC_CMDAT_DATA_EN (1 << 3) -+#define MSC_CMDAT_RESPONSE_BIT 0 -+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -+ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -+ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -+ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -+ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -+ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -+ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -+ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -+ -+#define CMDAT_DMA_EN (1 << 8) -+#define CMDAT_INIT (1 << 7) -+#define CMDAT_BUSY (1 << 6) -+#define CMDAT_STREAM (1 << 5) -+#define CMDAT_WRITE (1 << 4) -+#define CMDAT_DATA_EN (1 << 3) -+ -+/* MSC Interrupts Mask Register (MSC_IMASK) */ -+#define MSC_IMASK_AUTO_CMD_DONE (1 << 8) -+#define MSC_IMASK_SDIO (1 << 7) -+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IMASK_END_CMD_RES (1 << 2) -+#define MSC_IMASK_PRG_DONE (1 << 1) -+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -+ -+/* MSC Interrupts Status Register (MSC_IREG) */ -+#define MSC_IREG_AUTO_CMD_DONE (1 << 8) -+#define MSC_IREG_SDIO (1 << 7) -+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IREG_END_CMD_RES (1 << 2) -+#define MSC_IREG_PRG_DONE (1 << 1) -+#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -+ -+/* MSC Low Power Mode Register (MSC_LPM) */ -+#define MSC_SET_LPM (1 << 0) -+ -+/************************************************************************* -+ * EMC (External Memory Controller) -+ *************************************************************************/ -+#define EMC_BCR (EMC_BASE + 0x00) /* Bus Control Register */ -+#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ -+#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ -+#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ -+#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ -+#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ -+#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ -+#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ -+#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ -+#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ -+#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ -+ -+#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ -+ -+#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ -+#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ -+#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ -+#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ -+#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ -+#define EMC_DMAR1 (EMC_BASE + 0x94) /* SDRAM Bank 1 Addr Config Register */ -+#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ -+ -+#define REG_EMC_BCR REG32(EMC_BCR) -+#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -+#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -+#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -+#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -+#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -+#define REG_EMC_SACR0 REG32(EMC_SACR0) -+#define REG_EMC_SACR1 REG32(EMC_SACR1) -+#define REG_EMC_SACR2 REG32(EMC_SACR2) -+#define REG_EMC_SACR3 REG32(EMC_SACR3) -+#define REG_EMC_SACR4 REG32(EMC_SACR4) -+ -+#define REG_EMC_NFCSR REG32(EMC_NFCSR) -+ -+#define REG_EMC_DMCR REG32(EMC_DMCR) -+#define REG_EMC_RTCSR REG16(EMC_RTCSR) -+#define REG_EMC_RTCNT REG16(EMC_RTCNT) -+#define REG_EMC_RTCOR REG16(EMC_RTCOR) -+#define REG_EMC_DMAR0 REG32(EMC_DMAR0) -+#define REG_EMC_DMAR1 REG32(EMC_DMAR1) -+ -+/* Bus Control Register */ -+#define EMC_BCR_BT_SEL_BIT 30 -+#define EMC_BCR_BT_SEL_MASK (0x3 << EMC_BCR_BT_SEL_BIT) -+#define EMC_BCR_PK_SEL (1 << 24) -+#define EMC_BCR_BSR_MASK (1 << 2) /* Nand and SDRAM Bus Share Select: 0, share; 1, unshare */ -+ #define EMC_BCR_BSR_SHARE (0 << 2) -+ #define EMC_BCR_BSR_UNSHARE (1 << 2) -+#define EMC_BCR_BRE (1 << 1) -+#define EMC_BCR_ENDIAN (1 << 0) -+ -+/* Static Memory Control Register */ -+#define EMC_SMCR_STRV_BIT 24 -+#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -+#define EMC_SMCR_TAW_BIT 20 -+#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -+#define EMC_SMCR_TBP_BIT 16 -+#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -+#define EMC_SMCR_TAH_BIT 12 -+#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -+#define EMC_SMCR_TAS_BIT 8 -+#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -+#define EMC_SMCR_BW_BIT 6 -+#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -+#define EMC_SMCR_BCM (1 << 3) -+#define EMC_SMCR_BL_BIT 1 -+#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -+#define EMC_SMCR_SMT (1 << 0) -+ -+/* Static Memory Bank Addr Config Reg */ -+#define EMC_SACR_BASE_BIT 8 -+#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -+#define EMC_SACR_MASK_BIT 0 -+#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -+ -+/* NAND Flash Control/Status Register */ -+#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ -+#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ -+#define EMC_NFCSR_NFCE3 (1 << 5) -+#define EMC_NFCSR_NFE3 (1 << 4) -+#define EMC_NFCSR_NFCE2 (1 << 3) -+#define EMC_NFCSR_NFE2 (1 << 2) -+#define EMC_NFCSR_NFCE1 (1 << 1) -+#define EMC_NFCSR_NFE1 (1 << 0) -+ -+/* DRAM Control Register */ -+#define EMC_DMCR_BW_BIT 31 -+#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -+#define EMC_DMCR_CA_BIT 26 -+#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -+#define EMC_DMCR_RMODE (1 << 25) -+#define EMC_DMCR_RFSH (1 << 24) -+#define EMC_DMCR_MRSET (1 << 23) -+#define EMC_DMCR_RA_BIT 20 -+#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -+#define EMC_DMCR_BA_BIT 19 -+#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -+#define EMC_DMCR_PDM (1 << 18) -+#define EMC_DMCR_EPIN (1 << 17) -+#define EMC_DMCR_MBSEL (1 << 16) -+#define EMC_DMCR_TRAS_BIT 13 -+#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -+#define EMC_DMCR_RCD_BIT 11 -+#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -+#define EMC_DMCR_TPC_BIT 8 -+#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -+#define EMC_DMCR_TRWL_BIT 5 -+#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -+#define EMC_DMCR_TRC_BIT 2 -+#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -+#define EMC_DMCR_TCL_BIT 0 -+#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -+ -+/* Refresh Time Control/Status Register */ -+#define EMC_RTCSR_SFR (1 << 8) /* self refresh flag */ -+#define EMC_RTCSR_CMF (1 << 7) -+#define EMC_RTCSR_CKS_BIT 0 -+#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -+ -+/* SDRAM Bank Address Configuration Register */ -+#define EMC_DMAR_BASE_BIT 8 -+#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -+#define EMC_DMAR_MASK_BIT 0 -+#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -+ -+/* Mode Register of SDRAM bank 0 */ -+#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ -+#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ -+#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -+ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -+#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ -+#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -+#define EMC_SDMR_BT_BIT 3 /* Burst Type */ -+#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -+ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ -+ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ -+#define EMC_SDMR_BL_BIT 0 /* Burst Length */ -+#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -+ -+#define EMC_SDMR_CAS2_16BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS2_32BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+#define EMC_SDMR_CAS3_16BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS3_32BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+ -+ -+/************************************************************************* -+ * CIM -+ *************************************************************************/ -+#define CIM_CFG (CIM_BASE + 0x0000) -+#define CIM_CTRL (CIM_BASE + 0x0004) -+#define CIM_STATE (CIM_BASE + 0x0008) -+#define CIM_IID (CIM_BASE + 0x000C) -+#define CIM_RXFIFO (CIM_BASE + 0x0010) -+#define CIM_DA (CIM_BASE + 0x0020) -+#define CIM_FA (CIM_BASE + 0x0024) -+#define CIM_FID (CIM_BASE + 0x0028) -+#define CIM_CMD (CIM_BASE + 0x002C) -+#define CIM_SIZE (CIM_BASE + 0x0030) -+#define CIM_OFFSET (CIM_BASE + 0x0034) -+#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -+ -+#define REG_CIM_CFG REG32(CIM_CFG) -+#define REG_CIM_CTRL REG32(CIM_CTRL) -+#define REG_CIM_STATE REG32(CIM_STATE) -+#define REG_CIM_IID REG32(CIM_IID) -+#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -+#define REG_CIM_DA REG32(CIM_DA) -+#define REG_CIM_FA REG32(CIM_FA) -+#define REG_CIM_FID REG32(CIM_FID) -+#define REG_CIM_CMD REG32(CIM_CMD) -+#define REG_CIM_SIZE REG32(CIM_SIZE) -+#define REG_CIM_OFFSET REG32(CIM_OFFSET) -+ -+/* CIM Configuration Register (CIM_CFG) */ -+ -+#define CIM_CFG_ORDER_BIT 18 -+#define CIM_CFG_ORDER_MASK (0x3 << CIM_CFG_ORDER_BIT) -+ #define CIM_CFG_ORDER_0 (0x0 << CIM_CFG_ORDER_BIT) /* RG-GB; YUYV; YUV */ -+ #define CIM_CFG_ORDER_1 (0x1 << CIM_CFG_ORDER_BIT) /* GR-BG; YVYU; YVU */ -+ #define CIM_CFG_ORDER_2 (0x2 << CIM_CFG_ORDER_BIT) /* BG-GR; UYVY; UVY */ -+ #define CIM_CFG_ORDER_3 (0x3 << CIM_CFG_ORDER_BIT) /* GB-RG; VYUY; VUY */ -+#define CIM_CFG_DF_BIT 16 -+#define CIM_CFG_DF_MASK (0x3 << CIM_CFG_DF_BIT) -+ #define CIM_CFG_DF_RGB (0x0 << CIM_CFG_DF_BIT) -+ #define CIM_CFG_DF_RAWRGB CIM_CFG_DF_RGB -+ #define CIM_CFG_DF_BAYERRGB CIM_CFG_DF_RGB -+ #define CIM_CFG_DF_YUV444 (0x1 << CIM_CFG_DF_BIT) -+ #define CIM_CFG_DF_YUV422 (0x2 << CIM_CFG_DF_BIT) -+ #define CIM_CFG_DF_ITU656 (0x3 << CIM_CFG_DF_BIT) -+#define CIM_CFG_INV_DAT (1 << 15) -+#define CIM_CFG_VSP (1 << 14) /* VSYNC Polarity:0-rising edge active,1-falling edge active */ -+#define CIM_CFG_HSP (1 << 13) /* HSYNC Polarity:0-rising edge active,1-falling edge active */ -+#define CIM_CFG_PCP (1 << 12) /* PCLK working edge: 0-rising, 1-falling */ -+#define CIM_CFG_DMA_BURST_TYPE_BIT 10 -+#define CIM_CFG_DMA_BURST_TYPE_MASK (0x3 << CIM_CFG_DMA_BURST_TYPE_BIT) -+#define CIM_CFG_DMA_BURST_INCR (0 << CIM_CFG_DMA_BURST_TYPE_BIT) -+#define CIM_CFG_DMA_BURST_INCR4 (1 << CIM_CFG_DMA_BURST_TYPE_BIT) -+#define CIM_CFG_DMA_BURST_INCR8 (2 << CIM_CFG_DMA_BURST_TYPE_BIT) -+#define CIM_CFG_DUMMY_ZERO (1 << 9) -+#define CIM_CFG_EXT_VSYNC (1 << 8) -+#define CIM_CFG_PACK_BIT 4 -+#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) /* 11 22 33 44 */ -+ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) /* 22 33 44 11 */ -+ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) /* 33 44 11 22 */ -+ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) /* 44 11 22 33 */ -+ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) /* 44 33 22 11 */ -+ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) /* 33 22 11 44 */ -+ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) /* 22 11 44 33 */ -+ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) /* 11 44 33 22 */ -+#define CIM_CFG_BYPASS_BIT 2 -+#define CIM_CFG_BYPASS_MASK (1 << CIM_CFG_BYPASS_BIT) -+ #define CIM_CFG_BYPASS (1 << CIM_CFG_BYPASS_BIT) -+#define CIM_CFG_DSM_BIT 0 -+#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -+ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -+ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -+ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -+ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ -+ -+/* CIM Control Register (CIM_CTRL) */ -+ -+#define CIM_CTRL_MCLKDIV_BIT 24 -+#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) -+#define CIM_CTRL_FRC_BIT 16 -+#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -+ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -+ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -+ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -+ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -+ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -+ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -+ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -+ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -+ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -+ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -+ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -+ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -+ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -+ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -+ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -+ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -+#define CIM_CTRL_SIZEEN_BIT 14 -+#define CIM_CTRL_SIZEEN_MASK (0x1 << CIM_CTRL_SIZEEN_BIT) -+#define CIM_CTRL_SIZEEN (0x1 << CIM_CTRL_SIZEEN_BIT) -+#define CIM_CTRL_VDDM (1 << 13) /* VDD interrupt enable */ -+#define CIM_CTRL_DMA_SOFM (1 << 12) -+#define CIM_CTRL_DMA_EOFM (1 << 11) -+#define CIM_CTRL_DMA_STOPM (1 << 10) -+#define CIM_CTRL_RXF_TRIGM (1 << 9) -+#define CIM_CTRL_RXF_OFM (1 << 8) -+#define CIM_CTRL_RXF_TRIG_BIT 4 -+#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) -+ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ -+ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ -+ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ -+ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ -+ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ -+ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ -+ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ -+ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ -+#define CIM_CTRL_FAST_MODE_MASK (1 << 3) /* CIM fast mode mask */ -+#define CIM_CTRL_FAST_MODE (1 << 3) /* CIM works in fast mode */ -+#define CIM_CTRL_NORMAL_MODE (0 << 3) /* CIM works in normal mode */ -+#define CIM_CTRL_DMA_EN (1 << 2) /* Enable DMA */ -+#define CIM_CTRL_RXF_RST (1 << 1) /* RxFIFO reset */ -+#define CIM_CTRL_ENA (1 << 0) /* Enable CIM */ -+ -+/* CIM State Register (CIM_STATE) */ -+ -+#define CIM_STATE_DMA_SOF (1 << 6) /* DMA start irq */ -+#define CIM_STATE_DMA_EOF (1 << 5) /* DMA end irq */ -+#define CIM_STATE_DMA_STOP (1 << 4) /* DMA stop irq */ -+#define CIM_STATE_RXF_OF (1 << 3) /* RXFIFO over flow irq */ -+#define CIM_STATE_RXF_TRIG (1 << 2) /* RXFIFO triger meet irq */ -+#define CIM_STATE_RXF_EMPTY (1 << 1) /* RXFIFO empty irq */ -+#define CIM_STATE_VDD (1 << 0) /* CIM disabled irq */ -+ -+/* CIM DMA Command Register (CIM_CMD) */ -+ -+#define CIM_CMD_SOFINT (1 << 31) /* enable DMA start irq */ -+#define CIM_CMD_EOFINT (1 << 30) /* enable DMA end irq */ -+#define CIM_CMD_STOP (1 << 28) /* enable DMA stop irq */ -+#define CIM_CMD_LEN_BIT 0 -+#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -+ -+/* CIM Image Size Register (CIM_SIZE) */ -+#define CIM_SIZE_LPF_BIT 16 /* Lines per freame for csc output image */ -+#define CIM_SIZE_LPF_MASK (0x1fff << CIM_SIZE_LPF_BIT) -+#define CIM_SIZE_PPL_BIT 0 /* Pixels per line for csc output image, should be an even number */ -+#define CIM_SIZE_PPL_MASK (0x1fff << CIM_SIZE_PPL_BIT) -+ -+/* CIM Image Offset Register (CIM_OFFSET) */ -+#define CIM_OFFSET_V_BIT 16 /* Vertical offset */ -+#define CIM_OFFSET_V_MASK (0xfff << CIM_OFFSET_V_BIT) -+#define CIM_OFFSET_H_BIT 0 /* Horizontal offset, should be an enen number */ -+#define CIM_OFFSET_H_MASK (0xfff << CIM_OFFSET_H_BIT) /*OFFSET_H should be even number*/ -+ -+/************************************************************************* -+ * SADC (Smart A/D Controller) -+ *************************************************************************/ -+ -+#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ -+#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ -+#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ -+#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ -+#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ -+#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ -+#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ -+#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ -+#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ -+#define SADC_ADCLK (SADC_BASE + 0x28) /* ADC Clock Divide Register */ -+ -+#define REG_SADC_ENA REG8(SADC_ENA) -+#define REG_SADC_CFG REG32(SADC_CFG) -+#define REG_SADC_CTRL REG8(SADC_CTRL) -+#define REG_SADC_STATE REG8(SADC_STATE) -+#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) -+#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) -+#define REG_SADC_TSDAT REG32(SADC_TSDAT) -+#define REG_SADC_BATDAT REG16(SADC_BATDAT) -+#define REG_SADC_SADDAT REG16(SADC_SADDAT) -+#define REG_SADC_ADCLK REG32(SADC_ADCLK) -+ -+/* ADC Enable Register */ -+#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ -+#define SADC_ENA_ENTR_SLP (1 << 6) /* Touch Screen Enable */ -+#define SADC_ENA_EXIT_SLP (1 << 5) /* Touch Screen Enable */ -+#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ -+#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ -+#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ -+ -+/* ADC Configure Register */ -+#define SADC_CFG_EXIN (1 << 30) -+#define SADC_CFG_CLKOUT_NUM_BIT 16 -+#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) -+#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ -+#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ -+#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) -+#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ -+#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) -+#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ -+#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) -+#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ -+#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ -+#define SADC_CFG_CMD_BIT 0 /* ADC Command */ -+#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) -+ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ -+ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ -+ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ -+ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ -+ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ -+ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ -+ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ -+ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ -+ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ -+ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ -+ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ -+ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ -+ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ -+ -+/* ADC Control Register */ -+#define SADC_CTRL_SLPENDM (1 << 5) /* sleep Interrupt Mask */ -+#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ -+#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ -+#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ -+#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ -+#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ -+ -+/* ADC Status Register */ -+#define SADC_STATE_SLEEPND (1 << 5) /* Pen Down Interrupt Flag */ -+#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ -+#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ -+#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ -+#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ -+#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ -+ -+/* ADC Touch Screen Data Register */ -+#define SADC_TSDAT_DATA0_BIT 0 -+#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) -+#define SADC_TSDAT_TYPE0 (1 << 15) -+#define SADC_TSDAT_DATA1_BIT 16 -+#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) -+#define SADC_TSDAT_TYPE1 (1 << 31) -+ -+/* ADC Clock Divide Register */ -+#define SADC_ADCLK_CLKDIV_10_BIT 16 -+#define SADC_ADCLK_CLKDIV_10_MASK (0x7f << SADC_ADCLK_CLKDIV_10_BIT) -+#define SADC_ADCLK_CLKDIV_BIT 0 -+#define SADC_ADCLK_CLKDIV_MASK (0x3f << SADC_ADCLK_CLKDIV_BIT) -+ -+/************************************************************************* -+ * SLCD (Smart LCD Controller) -+ *************************************************************************/ -+ -+#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ -+#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ -+#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ -+#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ -+ -+#define REG_SLCD_CFG REG32(SLCD_CFG) -+#define REG_SLCD_CTRL REG8(SLCD_CTRL) -+#define REG_SLCD_STATE REG8(SLCD_STATE) -+#define REG_SLCD_DATA REG32(SLCD_DATA) -+ -+/* SLCD Configure Register */ -+#define SLCD_CFG_DWIDTH_BIT 10 -+#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_18BIT (0 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_16BIT (1 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8BIT_x3 (2 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8BIT_x2 (3 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8BIT_x1 (4 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_24BIT (5 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_9BIT_x2 (7 << SLCD_CFG_DWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_BIT (8) -+#define SLCD_CFG_CWIDTH_MASK (0x7 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_24BIT (3 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) -+#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) -+#define SLCD_CFG_RS_CMD_LOW (0 << 3) -+#define SLCD_CFG_RS_CMD_HIGH (1 << 3) -+#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) -+#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) -+#define SLCD_CFG_TYPE_PARALLEL (0 << 0) -+#define SLCD_CFG_TYPE_SERIAL (1 << 0) -+ -+/* SLCD Control Register */ -+#define SLCD_CTRL_DMA_EN (1 << 0) -+ -+/* SLCD Status Register */ -+#define SLCD_STATE_BUSY (1 << 0) -+ -+/* SLCD Data Register */ -+#define SLCD_DATA_RS_DATA (0 << 31) -+#define SLCD_DATA_RS_COMMAND (1 << 31) -+ -+/************************************************************************* -+ * LCD (LCD Controller) -+ *************************************************************************/ -+#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ -+#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ -+#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ -+ -+#define LCD_OSDC (LCD_BASE + 0x100) /* LCD OSD Configure Register */ -+#define LCD_OSDCTRL (LCD_BASE + 0x104) /* LCD OSD Control Register */ -+#define LCD_OSDS (LCD_BASE + 0x108) /* LCD OSD Status Register */ -+#define LCD_BGC (LCD_BASE + 0x10C) /* LCD Background Color Register */ -+#define LCD_KEY0 (LCD_BASE + 0x110) /* LCD Foreground Color Key Register 0 */ -+#define LCD_KEY1 (LCD_BASE + 0x114) /* LCD Foreground Color Key Register 1 */ -+#define LCD_ALPHA (LCD_BASE + 0x118) /* LCD ALPHA Register */ -+#define LCD_IPUR (LCD_BASE + 0x11C) /* LCD IPU Restart Register */ -+ -+#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ -+#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ -+#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ -+ -+#define LCD_XYP0 (LCD_BASE + 0x120) /* Foreground 0 XY Position Register */ -+#define LCD_XYP1 (LCD_BASE + 0x124) /* Foreground 1 XY Position Register */ -+#define LCD_SIZE0 (LCD_BASE + 0x128) /* Foreground 0 Size Register */ -+#define LCD_SIZE1 (LCD_BASE + 0x12C) /* Foreground 1 Size Register */ -+#define LCD_RGBC (LCD_BASE + 0x90) /* RGB Controll Register */ -+ -+#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ -+#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ -+#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ -+#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ -+#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ -+#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ -+#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ -+#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ -+#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ -+#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ -+#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ -+#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ -+#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ -+#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ -+#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ -+ -+#define LCD_OFFS0 (LCD_BASE + 0x60) /* DMA Offsize Register 0 */ -+#define LCD_PW0 (LCD_BASE + 0x64) /* DMA Page Width Register 0 */ -+#define LCD_CNUM0 (LCD_BASE + 0x68) /* DMA Command Counter Register 0 */ -+#define LCD_DESSIZE0 (LCD_BASE + 0x6C) /* Foreground Size in Descriptor 0 Register*/ -+#define LCD_OFFS1 (LCD_BASE + 0x70) /* DMA Offsize Register 1 */ -+#define LCD_PW1 (LCD_BASE + 0x74) /* DMA Page Width Register 1 */ -+#define LCD_CNUM1 (LCD_BASE + 0x78) /* DMA Command Counter Register 1 */ -+#define LCD_DESSIZE1 (LCD_BASE + 0x7C) /* Foreground Size in Descriptor 1 Register*/ -+ -+#define REG_LCD_CFG REG32(LCD_CFG) -+#define REG_LCD_CTRL REG32(LCD_CTRL) -+#define REG_LCD_STATE REG32(LCD_STATE) -+ -+#define REG_LCD_OSDC REG16(LCD_OSDC) -+#define REG_LCD_OSDCTRL REG16(LCD_OSDCTRL) -+#define REG_LCD_OSDS REG16(LCD_OSDS) -+#define REG_LCD_BGC REG32(LCD_BGC) -+#define REG_LCD_KEY0 REG32(LCD_KEY0) -+#define REG_LCD_KEY1 REG32(LCD_KEY1) -+#define REG_LCD_ALPHA REG8(LCD_ALPHA) -+#define REG_LCD_IPUR REG32(LCD_IPUR) -+ -+#define REG_LCD_VAT REG32(LCD_VAT) -+#define REG_LCD_DAH REG32(LCD_DAH) -+#define REG_LCD_DAV REG32(LCD_DAV) -+ -+#define REG_LCD_XYP0 REG32(LCD_XYP0) -+#define REG_LCD_XYP1 REG32(LCD_XYP1) -+#define REG_LCD_SIZE0 REG32(LCD_SIZE0) -+#define REG_LCD_SIZE1 REG32(LCD_SIZE1) -+#define REG_LCD_RGBC REG16(LCD_RGBC) -+ -+#define REG_LCD_VSYNC REG32(LCD_VSYNC) -+#define REG_LCD_HSYNC REG32(LCD_HSYNC) -+#define REG_LCD_PS REG32(LCD_PS) -+#define REG_LCD_CLS REG32(LCD_CLS) -+#define REG_LCD_SPL REG32(LCD_SPL) -+#define REG_LCD_REV REG32(LCD_REV) -+#define REG_LCD_IID REG32(LCD_IID) -+#define REG_LCD_DA0 REG32(LCD_DA0) -+#define REG_LCD_SA0 REG32(LCD_SA0) -+#define REG_LCD_FID0 REG32(LCD_FID0) -+#define REG_LCD_CMD0 REG32(LCD_CMD0) -+#define REG_LCD_DA1 REG32(LCD_DA1) -+#define REG_LCD_SA1 REG32(LCD_SA1) -+#define REG_LCD_FID1 REG32(LCD_FID1) -+#define REG_LCD_CMD1 REG32(LCD_CMD1) -+ -+#define REG_LCD_OFFS0 REG32(LCD_OFFS0) -+#define REG_LCD_PW0 REG32(LCD_PW0) -+#define REG_LCD_CNUM0 REG32(LCD_CNUM0) -+#define REG_LCD_DESSIZE0 REG32(LCD_DESSIZE0) -+#define REG_LCD_OFFS1 REG32(LCD_OFFS1) -+#define REG_LCD_PW1 REG32(LCD_PW1) -+#define REG_LCD_CNUM1 REG32(LCD_CNUM1) -+#define REG_LCD_DESSIZE1 REG32(LCD_DESSIZE1) -+ -+/* LCD Configure Register */ -+#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ -+#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) -+ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) -+ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) -+#define LCD_CFG_TVEPEH (1 << 30) /* TVE PAL enable extra halfline signal */ -+#define LCD_CFG_FUHOLD (1 << 29) /* hold pixel clock when outFIFO underrun */ -+#define LCD_CFG_NEWDES (1 << 28) /* use new descripter. old: 4words, new:8words */ -+#define LCD_CFG_PALBP (1 << 27) /* bypass data format and alpha blending */ -+#define LCD_CFG_TVEN (1 << 26) /* indicate the terminal is lcd or tv */ -+#define LCD_CFG_RECOVER (1 << 25) /* Auto recover when output fifo underrun */ -+#define LCD_CFG_DITHER (1 << 24) /* Dither function */ -+#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ -+#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ -+#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ -+#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ -+#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ -+#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ -+#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ -+#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ -+#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ -+#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ -+#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ -+#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ -+#define LCD_CFG_HSP (1 << 11) /* HSYNC polarity:0-active high,1-active low */ -+#define LCD_CFG_PCP (1 << 10) /* PCLK polarity:0-rising,1-falling */ -+#define LCD_CFG_DEP (1 << 9) /* DE polarity:0-active high,1-active low */ -+#define LCD_CFG_VSP (1 << 8) /* VSYNC polarity:0-rising,1-falling */ -+#define LCD_CFG_MODE_TFT_18BIT (1 << 7) /* 18bit TFT */ -+#define LCD_CFG_MODE_TFT_16BIT (0 << 7) /* 16bit TFT */ -+#define LCD_CFG_MODE_TFT_24BIT (1 << 6) /* 24bit TFT */ -+#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ -+#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) -+#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ -+ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ -+ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ -+ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ -+#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ -+#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ -+ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_LCM (13 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SLCD LCD_CFG_MODE_LCM -+ -+/* LCD Control Register */ -+#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ -+#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -+ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ -+ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ -+ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ -+ #define LCD_CTRL_BST_32 (3 << LCD_CTRL_BST_BIT) /* 32-word */ -+#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode(foreground 0 in OSD mode) */ -+#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode(foreground 0 in OSD mode) */ -+#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ -+#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ -+#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -+ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ -+ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ -+ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ -+#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ -+#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -+#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ -+#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ -+#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ -+#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ -+#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ -+#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ -+#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ -+#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ -+#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ -+#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ -+#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ -+#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ -+#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ -+ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ -+ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ -+ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ -+ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ -+ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ -+ -+/* LCD Status Register */ -+#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ -+#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ -+#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ -+#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ -+#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ -+#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ -+#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ -+ -+/* OSD Configure Register */ -+#define LCD_OSDC_SOFM1 (1 << 15) /* Start of frame interrupt mask for foreground 1 */ -+#define LCD_OSDC_EOFM1 (1 << 14) /* End of frame interrupt mask for foreground 1 */ -+#define LCD_OSDC_REM1 (1 << 13) /* Real end of frame mask for foreground 1 */ -+#define LCD_OSDC_SOFM0 (1 << 11) /* Start of frame interrupt mask for foreground 0 */ -+#define LCD_OSDC_EOFM0 (1 << 10) /* End of frame interrupt mask for foreground 0 */ -+#define LCD_OSDC_REM0 (1 << 9) /* Real end of frame mask for foreground 0 */ -+#define LCD_OSDC_REMB (1 << 7) /* Real end of frame mask for background */ -+#define LCD_OSDC_F1EN (1 << 4) /* enable foreground 1 */ -+#define LCD_OSDC_F0EN (1 << 3) /* enable foreground 0 */ -+#define LCD_OSDC_ALPHAEN (1 << 2) /* enable alpha blending */ -+#define LCD_OSDC_ALPHAMD (1 << 1) /* alpha blending mode */ -+#define LCD_OSDC_OSDEN (1 << 0) /* OSD mode enable */ -+ -+/* OSD Controll Register */ -+#define LCD_OSDCTRL_IPU (1 << 15) /* input data from IPU */ -+#define LCD_OSDCTRL_RGB565 (0 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -+#define LCD_OSDCTRL_RGB555 (1 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -+#define LCD_OSDCTRL_CHANGES (1 << 3) /* Change size flag */ -+#define LCD_OSDCTRL_OSDBPP_BIT 0 /* Bits Per Pixel of OSD Channel 1 */ -+#define LCD_OSDCTRL_OSDBPP_MASK (0x7< -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_BOARD_SERIAL_H__ -+#define __ASM_BOARD_SERIAL_H__ -+ -+#ifndef CONFIG_SERIAL_MANY_PORTS -+#undef RS_TABLE_SIZE -+#define RS_TABLE_SIZE 1 -+#endif -+ -+#define JZ_BASE_BAUD (12000000/16) -+ -+#define JZ_SERIAL_PORT_DEFNS \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -+ -+#endif /* __ASM_BORAD_SERIAL_H__ */ -diff --git a/include/asm-mips/mach-jz4750/war.h b/include/asm-mips/mach-jz4750/war.h -new file mode 100644 -index 0000000..3a5bc17 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750/war.h -@@ -0,0 +1,25 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -+ */ -+#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -+#define __ASM_MIPS_MACH_JZ4740_WAR_H -+ -+#define R4600_V1_INDEX_ICACHEOP_WAR 0 -+#define R4600_V1_HIT_CACHEOP_WAR 0 -+#define R4600_V2_HIT_CACHEOP_WAR 0 -+#define R5432_CP0_INTERRUPT_WAR 0 -+#define BCM1250_M3_WAR 0 -+#define SIBYTE_1956_WAR 0 -+#define MIPS4K_ICACHE_REFILL_WAR 0 -+#define MIPS_CACHE_SYNC_WAR 0 -+#define TX49XX_ICACHE_INDEX_INV_WAR 0 -+#define RM9000_CDEX_SMP_WAR 0 -+#define ICACHE_REFILLS_WORKAROUND_WAR 0 -+#define R10000_LLSC_WAR 0 -+#define MIPS34K_MISSED_ITLB_WAR 0 -+ -+#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -diff --git a/include/asm-mips/mach-jz4750d/board-cetus.h b/include/asm-mips/mach-jz4750d/board-cetus.h -new file mode 100644 -index 0000000..aea475d ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/board-cetus.h -@@ -0,0 +1,124 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/board-cetus.h -+ * -+ * JZ4750D-based CETUS board ver 1.x definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750D_CETUS_H__ -+#define __ASM_JZ4750D_CETUS_H__ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+#define JZ_EXTAL 24000000 -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+//#define CFG_DIV 1 /* hclk=pclk=mclk=CFG_EXTAL/CFG_DIV, just for FPGA board */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+ -+#define GPIO_SD0_VCC_EN_N (32*4+0) /* CIM_D0 */ -+#define GPIO_SD0_CD_N (32*4+1) /* CIM_D1 */ -+#define GPIO_SD0_WP (32*4+2) /* CIM_D2 */ -+#define GPIO_SD1_VCC_EN_N (32*4+3) /* CIM_D3 */ -+#define GPIO_SD1_CD_N (32*4+4) /* CIM_D4 */ -+ -+#define GPIO_USB_DETE (32*4+6) /* CIM_D6 */ -+#define GPIO_DC_DETE_N (32*4+8) /* CIM_MCLK */ -+#define GPIO_CHARG_STAT_N (32*4+10) /* CIM_VSYNC */ -+#define GPIO_DISP_OFF_N (32*4+18) /* SDATO */ -+#define GPIO_LCD_VCC_EN_N (32*4+19) /* SDATI */ -+//#define GPIO_LED_EN 124 /* GPD28 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+/*====================================================================== -+ * LCD backlight -+ */ -+#define GPIO_LCD_PWM (32*4+22) /* GPE22 PWM2 */ -+#define LCD_PWM_CHN 2 /* pwm channel */ -+#define LCD_PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_set_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_clear_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC0_WP_PIN GPIO_SD0_WP -+#define MSC0_HOTPLUG_PIN GPIO_SD0_CD_N -+#define MSC0_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD0_CD_N) -+ -+#define MSC1_WP_PIN GPIO_SD1_WP -+#define MSC1_HOTPLUG_PIN GPIO_SD1_CD_N -+#define MSC1_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD1_CD_N) -+ -+#define __msc0_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD0_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD0_CD_N); \ -+} while (0) -+ -+#define __msc0_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD0_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#define __msc1_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD1_VCC_EN_N); \ -+ /* __gpio_as_input(GPIO_SD1_CD_N);*/ \ -+} while (0) -+ -+#define __msc1_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_card_detected(s) \ -+({ \ -+ int detected = 0; \ -+ if (__gpio_get_pin(GPIO_SD1_CD_N)) \ -+ detected = 1; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4750d_CETUS_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/board-draco.h b/include/asm-mips/mach-jz4750d/board-draco.h -new file mode 100644 -index 0000000..fe04f79 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/board-draco.h -@@ -0,0 +1,126 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/board-draco.h -+ * -+ * JZ4750D-based DRACO board ver 1.x definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750D_DRACO_H__ -+#define __ASM_JZ4750D_DRACO_H__ -+ -+//#define CONFIG_FPGA /* fuwa is an FPGA board */ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+//#define JZ_EXTAL 48000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL 24000000 -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+//#define CFG_DIV 1 /* hclk=pclk=mclk=CFG_EXTAL/CFG_DIV, just for FPGA board */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_SD0_VCC_EN_N (32*2+10) /* GPC10 */ -+#define GPIO_SD0_CD_N (32*2+11) /* GPC11 */ -+#define GPIO_SD0_WP (32*2+12) /* GPC12 */ -+//#define GPIO_SD1_VCC_EN_N (32*2+13) /* GPC13 */ -+#define GPIO_SD1_VCC_EN_N (32*4+4) /* GPE4 */ -+#define GPIO_SD1_CD_N (32*2+14) /* GPC14 */ -+#define GPIO_USB_DETE (32*5+12) /* GPF12 */ -+#define GPIO_DC_DETE_N 103 /* GPD7 */ -+#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -+#define GPIO_DISP_OFF_N 121 /* GPD25, LCD_REV */ -+//#define GPIO_LED_EN 124 /* GPD28 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+/*====================================================================== -+ * LCD backlight -+ */ -+#define GPIO_LCD_PWM (32*4+20) /* GPE20 */ -+ -+#define LCD_PWM_CHN 0 /* pwm channel */ -+#define LCD_PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_set_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_clear_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC0_WP_PIN GPIO_SD0_WP -+#define MSC0_HOTPLUG_PIN GPIO_SD0_CD_N -+#define MSC0_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD0_CD_N) -+ -+#define MSC1_WP_PIN GPIO_SD1_WP -+#define MSC1_HOTPLUG_PIN GPIO_SD1_CD_N -+#define MSC1_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD1_CD_N) -+ -+#define __msc0_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD0_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD0_CD_N); \ -+} while (0) -+ -+#define __msc0_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD0_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#define __msc1_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD1_VCC_EN_N); \ -+ /* __gpio_as_input(GPIO_SD1_CD_N);*/ \ -+} while (0) -+ -+#define __msc1_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_card_detected(s) \ -+({ \ -+ int detected = 0; \ -+ if (__gpio_get_pin(GPIO_SD1_CD_N)) \ -+ detected = 1; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4750d_DRACO_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/board-fuwa1.h b/include/asm-mips/mach-jz4750d/board-fuwa1.h -new file mode 100644 -index 0000000..7b8c6c2 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/board-fuwa1.h -@@ -0,0 +1,126 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/board-fuwa1.h -+ * -+ * JZ4750D-based FUWA1 board ver 1.x definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750D_FUWA1_H__ -+#define __ASM_JZ4750D_FUWA1_H__ -+ -+//#define CONFIG_FPGA /* fuwa is an FPGA board */ -+ -+/*====================================================================== -+ * Frequencies of on-board oscillators -+ */ -+//#define JZ_EXTAL 48000000 /* Main extal freq: 12 MHz */ -+#define JZ_EXTAL 24000000 -+#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -+//#define CFG_DIV 1 /* hclk=pclk=mclk=CFG_EXTAL/CFG_DIV, just for FPGA board */ -+ -+ -+/*====================================================================== -+ * GPIO -+ */ -+#define GPIO_SD0_VCC_EN_N (32*2+10) /* GPC10 */ -+#define GPIO_SD0_CD_N (32*2+11) /* GPC11 */ -+#define GPIO_SD0_WP (32*2+12) /* GPC12 */ -+//#define GPIO_SD1_VCC_EN_N (32*2+13) /* GPC13 */ -+#define GPIO_SD1_VCC_EN_N (32*4+4) /* GPE4 */ -+#define GPIO_SD1_CD_N (32*2+14) /* GPC14 */ -+#define GPIO_USB_DETE 102 /* GPD6 */ -+#define GPIO_DC_DETE_N 103 /* GPD7 */ -+#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -+#define GPIO_DISP_OFF_N 121 /* GPD25, LCD_REV */ -+//#define GPIO_LED_EN 124 /* GPD28 */ -+ -+#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -+ -+/*====================================================================== -+ * LCD backlight -+ */ -+#define GPIO_LCD_PWM (32*4+20) /* GPE20 */ -+ -+#define LCD_PWM_CHN 0 /* pwm channel */ -+#define LCD_PWM_FULL 101 -+/* 100 level: 0,1,...,100 */ -+#define __lcd_set_backlight_level(n) \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_set_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+#define __lcd_close_backlight() \ -+do { \ -+ __gpio_as_output(GPIO_LCD_PWM); \ -+ __gpio_clear_pin(GPIO_LCD_PWM); \ -+} while (0) -+ -+/*====================================================================== -+ * MMC/SD -+ */ -+ -+#define MSC0_WP_PIN GPIO_SD0_WP -+#define MSC0_HOTPLUG_PIN GPIO_SD0_CD_N -+#define MSC0_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD0_CD_N) -+ -+#define MSC1_WP_PIN GPIO_SD1_WP -+#define MSC1_HOTPLUG_PIN GPIO_SD1_CD_N -+#define MSC1_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD1_CD_N) -+ -+#define __msc0_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD0_VCC_EN_N); \ -+ __gpio_as_input(GPIO_SD0_CD_N); \ -+} while (0) -+ -+#define __msc0_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD0_VCC_EN_N); \ -+} while (0) -+ -+#define __msc0_card_detected(s) \ -+({ \ -+ int detected = 1; \ -+ if (__gpio_get_pin(GPIO_SD0_CD_N)) \ -+ detected = 0; \ -+ detected; \ -+}) -+ -+#define __msc1_init_io() \ -+do { \ -+ __gpio_as_output(GPIO_SD1_VCC_EN_N); \ -+ /* __gpio_as_input(GPIO_SD1_CD_N);*/ \ -+} while (0) -+ -+#define __msc1_enable_power() \ -+do { \ -+ __gpio_clear_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_disable_power() \ -+do { \ -+ __gpio_set_pin(GPIO_SD1_VCC_EN_N); \ -+} while (0) -+ -+#define __msc1_card_detected(s) \ -+({ \ -+ int detected = 0; \ -+ if (__gpio_get_pin(GPIO_SD1_CD_N)) \ -+ detected = 1; \ -+ detected; \ -+}) -+ -+#endif /* __ASM_JZ4750d_FUWA1_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/clock.h b/include/asm-mips/mach-jz4750d/clock.h -new file mode 100644 -index 0000000..a2832d6 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/clock.h -@@ -0,0 +1,230 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/clock.h -+ * -+ * JZ4750D clocks definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750D_CLOCK_H__ -+#define __ASM_JZ4750D_CLOCK_H__ -+ -+#ifndef JZ_EXTAL -+#define JZ_EXTAL 12000000 /* 3.6864 MHz */ -+#endif -+#ifndef JZ_EXTAL2 -+#define JZ_EXTAL2 32768 /* 32.768 KHz */ -+#endif -+ -+/* -+ * JZ4750D clocks structure -+ */ -+typedef struct { -+ unsigned int cclk; /* CPU clock */ -+ unsigned int hclk; /* System bus clock */ -+ unsigned int pclk; /* Peripheral bus clock */ -+ unsigned int mclk; /* Flash/SRAM/SDRAM clock */ -+ unsigned int h1clk; /* AHB1 clock */ -+ unsigned int pixclk; /* LCD pixel clock */ -+ unsigned int i2sclk; /* AIC module clock */ -+ unsigned int usbclk; /* USB module clock */ -+ unsigned int mscclk; /* MSC module clock */ -+ unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -+ unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ -+} jz_clocks_t; -+ -+extern jz_clocks_t jz_clocks; -+ -+ -+/* PLL output frequency */ -+static __inline__ unsigned int __cpm_get_pllout(void) -+{ -+#if defined(CONFIG_FPGA) -+ return JZ_EXTAL/CFG_DIV; -+#else -+ unsigned long m, n, no, pllout; -+ unsigned long cppcr = REG_CPM_CPPCR; -+ unsigned long od[4] = {1, 2, 2, 4}; -+ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { -+ m = __cpm_get_pllm() + 2; -+ n = __cpm_get_plln() + 2; -+ no = od[__cpm_get_pllod()]; -+ pllout = ((JZ_EXTAL) / (n * no)) * m; -+ } else -+ pllout = JZ_EXTAL; -+ return pllout; -+#endif -+} -+ -+/* PLL output frequency for MSC/I2S/LCD/USB */ -+static __inline__ unsigned int __cpm_get_pllout2(void) -+{ -+#if defined(CONFIG_FPGA) -+ return JZ_EXTAL/CFG_DIV; -+#else -+ if (REG_CPM_CPCCR & CPM_CPCCR_PCS) -+ return __cpm_get_pllout(); -+ else -+ return __cpm_get_pllout()/2; -+#endif -+} -+ -+/* CPU core clock */ -+static __inline__ unsigned int __cpm_get_cclk(void) -+{ -+ -+#if defined(CONFIG_FGPA) -+ return JZ_EXTAL; -+#else -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ return __cpm_get_pllout() / div[__cpm_get_cdiv()]; -+#endif -+} -+ -+/* AHB system bus clock */ -+static __inline__ unsigned int __cpm_get_hclk(void) -+{ -+#if defined(CONFIG_FPGA) -+ return JZ_EXTAL/CFG_DIV; -+#else -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_hdiv()]; -+#endif -+ -+} -+ -+/* Memory bus clock */ -+static __inline__ unsigned int __cpm_get_mclk(void) -+{ -+#if defined(CONFIG_FPGA) -+ return JZ_EXTAL/CFG_DIV; -+#else -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_mdiv()]; -+#endif -+} -+ -+/* APB peripheral bus clock */ -+static __inline__ unsigned int __cpm_get_pclk(void) -+{ -+#if defined(CONFIG_FPGA) -+ return JZ_EXTAL/CFG_DIV; -+#else -+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -+ -+ return __cpm_get_pllout() / div[__cpm_get_pdiv()]; -+#endif -+} -+ -+/* LCDC module clock */ -+static __inline__ unsigned int __cpm_get_h1clk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_h1div() + 1); -+} -+ -+/* LCD pixel clock */ -+static __inline__ unsigned int __cpm_get_pixclk(void) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); -+} -+ -+/* I2S clock */ -+static __inline__ unsigned int __cpm_get_i2sclk(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { -+ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); -+ } -+ else { -+ return JZ_EXTAL; -+ } -+} -+ -+/* USB clock */ -+static __inline__ unsigned int __cpm_get_usbclk(void) -+{ -+ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { -+ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); -+ } -+ else { -+ return JZ_EXTAL; -+ } -+} -+ -+/* -+ * MSC clock -+ * @n: the index of MMC/SD controller -+ */ -+static __inline__ unsigned int __cpm_get_mscclk(int n) -+{ -+ return __cpm_get_pllout2() / (__cpm_get_mscdiv(n) + 1); -+} -+ -+/* EXTAL clock */ -+static __inline__ unsigned int __cpm_get_extalclk0(void) -+{ -+ return JZ_EXTAL; -+} -+ -+/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -+static __inline__ unsigned int __cpm_get_extalclk(void) -+{ -+#if defined(CONFIG_FPGA) -+ return __cpm_get_pllout(); -+#else -+ if (REG_CPM_CPCCR & CPM_CPCCR_ECS) -+ return __cpm_get_extalclk0()/2; -+ else -+ return __cpm_get_extalclk0(); -+#endif -+ -+} -+ -+/* RTC clock for CPM,INTC,RTC,TCU,WDT */ -+static __inline__ unsigned int __cpm_get_rtcclk(void) -+{ -+ return JZ_EXTAL2; -+} -+ -+/* -+ * Output 24MHz for SD and 16MHz for MMC. -+ * @n: the index of MMC/SD controller -+ */ -+static inline void __cpm_select_msc_clk(int n, int sd) -+{ -+ unsigned int pllout2 = __cpm_get_pllout2(); -+ unsigned int div = 0; -+ -+ if (sd) { -+ div = pllout2 / 24000000; -+ } -+ else { -+ div = pllout2 / 16000000; -+ } -+ -+ REG_CPM_MSCCDR(n) = div - 1; -+ REG_CPM_CPCCR |= CPM_CPCCR_CE; -+} -+ -+/* -+ * Output 48MHz for high speed card. -+ */ -+static inline void __cpm_select_msc_clk_high(int n, int sd) -+{ -+ unsigned int pllout2 = __cpm_get_pllout2(); -+ unsigned int div = 0; -+ -+ div = pllout2 / 48000000; -+ -+ REG_CPM_MSCCDR(n) = div - 1; -+ REG_CPM_CPCCR |= CPM_CPCCR_CE; -+} -+ -+#endif /* __ASM_JZ4750D_CLOCK_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/dma.h b/include/asm-mips/mach-jz4750d/dma.h -new file mode 100644 -index 0000000..3cca844 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/dma.h -@@ -0,0 +1,307 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/dma.h -+ * -+ * JZ4750D DMA definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750D_DMA_H__ -+#define __ASM_JZ4750D_DMA_H__ -+ -+#include -+#include /* need byte IO */ -+#include /* And spinlocks */ -+#include -+#include -+ -+/* -+ * Descriptor structure for JZ4750D DMA engine -+ * Note: this structure must always be aligned to a 16-bytes boundary. -+ */ -+ -+/* old descriptor 4-word */ -+typedef struct { -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+ volatile u32 dsadr; /* DSAR value for the current transfer */ -+ volatile u32 dtadr; /* DTAR value for the current transfer */ -+ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -+} jz_dma_desc; -+ -+/* new descriptor 8-word */ -+typedef struct { -+ volatile u32 dcmd; /* DCMD value for the current transfer */ -+ volatile u32 dsadr; /* DSAR value for the current transfer */ -+ volatile u32 dtadr; /* DTAR value for the current transfer */ -+ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -+ volatile u32 dstrd; /* DMA source and target stride address */ -+ volatile u32 dreqt; /* DMA request type for current transfer */ -+ volatile u32 reserved0; /* Reserved */ -+ volatile u32 reserved1; /* Reserved */ -+} jz_dma_desc_8word; -+ -+/* DMA Device ID's follow */ -+enum { -+ DMA_ID_EXT = 0, /* External request with DREQn */ -+ DMA_ID_NAND, /* NAND DMA request */ -+ DMA_ID_BCH_ENC, /* BCH Encoding DMA request */ -+ DMA_ID_BCH_DEC, /* BCH Decoding DMA request */ -+ DMA_ID_AUTO, /* Auto-request */ -+// DMA_ID_TSSI_RX, /* TSSI receive fifo full request */ -+ DMA_ID_UART3_TX, /* UART3 transmit-fifo-empty request */ -+ DMA_ID_UART3_RX, /* UART3 receve-fifo-full request */ -+ DMA_ID_UART2_TX, /* UART2 transmit-fifo-empty request */ -+ DMA_ID_UART2_RX, /* UART2 receve-fifo-full request */ -+ DMA_ID_UART1_TX, /* UART1 transmit-fifo-empty request */ -+ DMA_ID_UART1_RX, /* UART1 receve-fifo-full request */ -+ DMA_ID_UART0_TX, /* UART0 transmit-fifo-empty request */ -+ DMA_ID_UART0_RX, /* UART0 receve-fifo-full request */ -+ DMA_ID_SSI0_TX, /* SSI0 transmit-fifo-full request */ -+ DMA_ID_SSI0_RX, /* SSI0 receive-fifo-empty request */ -+ DMA_ID_AIC_TX, /* AIC transmit-fifo-full request */ -+ DMA_ID_AIC_RX, /* AIC receive-fifo-empty request */ -+ DMA_ID_MSC0_TX, /* MSC0 transmit-fifo-full request */ -+ DMA_ID_MSC0_RX, /* MSC0 receive-fifo-empty request */ -+ DMA_ID_TCU_OVERFLOW, /* TCU channel n overflow interrupt */ -+ DMA_ID_SADC, /* SADC transfer request */ -+ DMA_ID_MSC1_TX, /* MSC1 transmit-fifo-full request */ -+ DMA_ID_MSC1_RX, /* MSC1 receive-fifo-empty request */ -+ DMA_ID_SSI1_TX, /* SSI1 transmit-fifo-full request */ -+ DMA_ID_SSI1_RX, /* SSI1 receive-fifo-empty request */ -+ DMA_ID_PCM_TX, /* PM transmit-fifo-full request */ -+ DMA_ID_PCM_RX, /* PM receive-fifo-empty request */ -+ DMA_ID_RAW_SET, -+ DMA_ID_MAX -+}; -+ -+/* DMA modes, simulated by sw */ -+#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ -+#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ -+#define DMA_AUTOINIT 0x2 -+#define DMA_MODE_MASK 0x3 -+ -+struct jz_dma_chan { -+ int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ -+ unsigned int io; /* DMA channel number */ -+ const char *dev_str; /* string describes the DMA channel */ -+ int irq; /* DMA irq number */ -+ void *irq_dev; /* DMA private device structure */ -+ unsigned int fifo_addr; /* physical fifo address of the requested device */ -+ unsigned int cntl; /* DMA controll */ -+ unsigned int mode; /* DMA configuration */ -+ unsigned int source; /* DMA request source */ -+}; -+ -+extern struct jz_dma_chan jz_dma_table[]; -+ -+ -+#define DMA_8BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_8BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_32BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_32_32BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -+#define DMA_AIC_32_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_32_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BIT_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BIT_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_RX_CMD \ -+ DMAC_DCMD_DAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_TX_CMD \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+#define DMA_AIC_16BYTE_TX_CMD_UC \ -+ DMAC_DCMD_SAI | \ -+ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -+ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -+ -+extern int jz_request_dma(int dev_id, -+ const char *dev_str, -+ irqreturn_t (*irqhandler)(int, void *), -+ unsigned long irqflags, -+ void *irq_dev_id); -+extern void jz_free_dma(unsigned int dmanr); -+ -+extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -+ int length, int *eof, void *data); -+extern void dump_jz_dma_channel(unsigned int dmanr); -+ -+extern void enable_dma(unsigned int dmanr); -+extern void disable_dma(unsigned int dmanr); -+extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); -+extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); -+extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -+extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -+extern void jz_set_dma_src_width(int dmanr, int nbit); -+extern void jz_set_dma_dest_width(int dmanr, int nbit); -+extern void jz_set_dma_block_size(int dmanr, int nbyte); -+extern unsigned int get_dma_residue(unsigned int dmanr); -+ -+extern spinlock_t dma_spin_lock; -+ -+static __inline__ unsigned long claim_dma_lock(void) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&dma_spin_lock, flags); -+ return flags; -+} -+ -+static __inline__ void release_dma_lock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&dma_spin_lock, flags); -+} -+ -+/* Clear the 'DMA Pointer Flip Flop'. -+ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -+ */ -+#define clear_dma_ff(channel) -+ -+static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -+{ -+ if (dmanr > MAX_DMA_NUM -+ || jz_dma_table[dmanr].dev_id < 0) -+ return NULL; -+ return &jz_dma_table[dmanr]; -+} -+ -+static __inline__ int dma_halted(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 1; -+ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -+} -+ -+static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ return chan->mode; -+} -+ -+static __inline__ void clear_dma_done(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+} -+ -+static __inline__ void clear_dma_halt(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -+ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT); -+} -+ -+static __inline__ void clear_dma_flag(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return; -+ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); -+} -+ -+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -+{ -+} -+ -+static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -+{ -+ unsigned long dccsr; -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return 0; -+ dccsr = REG_DMAC_DCCSR(chan->io); -+ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -+} -+ -+static __inline__ int get_dma_done_irq(unsigned int dmanr) -+{ -+ struct jz_dma_chan *chan = get_dma_chan(dmanr); -+ if (!chan) -+ return -1; -+ return chan->irq; -+} -+ -+#endif /* __ASM_JZ4750D_DMA_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/jz4750d.h b/include/asm-mips/mach-jz4750d/jz4750d.h -new file mode 100644 -index 0000000..ac59226 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/jz4750d.h -@@ -0,0 +1,43 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/jz4750d.h -+ * -+ * JZ4750 common definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750_H__ -+#define __ASM_JZ4750_H__ -+ -+#include -+#include -+#include -+#include -+ -+/*------------------------------------------------------------------ -+ * Platform definitions -+ */ -+#ifdef CONFIG_JZ4750D_FUWA1 -+#include -+#endif -+ -+#ifdef CONFIG_JZ4750D_CETUS -+#include -+#endif -+/* Add other platform definition here ... */ -+ -+ -+/*------------------------------------------------------------------ -+ * Follows are related to platform definitions -+ */ -+ -+#include -+#include -+ -+#endif /* __ASM_JZ4750_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/misc.h b/include/asm-mips/mach-jz4750d/misc.h -new file mode 100644 -index 0000000..cd0b13c ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/misc.h -@@ -0,0 +1,44 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/misc.h -+ * -+ * Ingenic's JZ4750D common include. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * Author: -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_JZ4750D_MISC_H__ -+#define __ASM_JZ4750D_MISC_H__ -+ -+/*========================================================== -+ * I2C -+ *===========================================================*/ -+ -+#define I2C_EEPROM_DEV 0xA /* b'1010 */ -+#define I2C_RTC_DEV 0xD /* b'1101 */ -+#define DIMM0_SPD_ADDR 0 -+#define DIMM1_SPD_ADDR 1 -+#define DIMM2_SPD_ADDR 2 -+#define DIMM3_SPD_ADDR 3 -+#define JZ_HCI_ADDR 7 -+ -+#define DIMM_SPD_LEN 128 -+#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ -+#define I2C_RTC_LEN 16 -+#define HCI_MAC_OFFSET 64 -+ -+extern void i2c_open(void); -+extern void i2c_close(void); -+extern void i2c_setclk(unsigned int i2cclk); -+ -+extern int i2c_read(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+extern int i2c_write(unsigned char device, unsigned char *buf, -+ unsigned char address, int count); -+ -+#endif /* __ASM_JZ4750D_MISC_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/ops.h b/include/asm-mips/mach-jz4750d/ops.h -new file mode 100644 -index 0000000..f28651f ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/ops.h -@@ -0,0 +1,3430 @@ -+/* -+ * linux/include/asm-mips/mach-jz4750d/ops.h -+ * -+ * JZ4750D register definition. -+ * -+ * Copyright (C) 2008 Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef __JZ4750D_OPS_H__ -+#define __JZ4750D_OPS_H__ -+ -+/* -+ * Definition of Module Operations -+ */ -+ -+/*************************************************************************** -+ * EMC -+ ***************************************************************************/ -+#define is_share_mode() (1) -+ -+/*************************************************************************** -+ * GPIO -+ ***************************************************************************/ -+ -+//------------------------------------------------------ -+// GPIO Pins Description -+// -+// PORT 0: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 D0 - -+// 1 D1 - -+// 2 D2 - -+// 3 D3 - -+// 4 D4 - -+// 5 D5 - -+// 6 D6 - -+// 7 D7 - -+// 8 D8 - -+// 9 D9 - -+// 10 D10 - -+// 11 D11 - -+// 12 D12 - -+// 13 D13 - -+// 14 D14 - -+// 15 D15 - -+// 16 D16 - -+// 17 D17 - -+// 18 D18 - -+// 19 D19 - -+// 20 D20 - -+// 21 D21 - -+// 22 D22 - -+// 23 D23 - -+// 24 D24 - -+// 25 D25 - -+// 26 D26 - -+// 27 D27 - -+// 28 D28 - -+// 29 D29 - -+// 30 D30 - -+// 31 D31 - -+// -+//------------------------------------------------------ -+// PORT 1: -+// -+// PIN/BIT N FUNC0 FUNC1 FUNC2 NOTE -+// 0 A0 - - -+// 1 A1 - - -+// 2 A2 - - -+// 3 A3 - - -+// 4 A4 - - -+// 5 A5 - - -+// 6 A6 - - -+// 7 A7 - - -+// 8 A8 - - -+// 9 A9 - - -+// 10 A10 - - -+// 11 A11 - - -+// 12 A12 - - -+// 13 A13 - - -+// 14 A14 - - -+// 15 A15/CLE CL(unshare) MSC0_CLK -+// 16 DCS0# - - -+// 17 RAS# - - -+// 18 CAS# - - -+// 19 SDWE#/BUFD# - - -+// 20 WE0# - - -+// 21 WE1# - - -+// 22 WE2# - - -+// 23 WE3# - - -+// 24 CKO - - Note1 -+// 25 CKE - - -+// 26 SSI_CLK MSC1_CLK - -+// 27 SSI_DT MSC1_D1 - -+// 28 SSI_DR MSC1_D0 - -+// 29 SSI_CE0# MSC1_CMD - -+// 30 SSI_GPC MSC1_D2 - -+// 31 SSI_CE1# MSC1_D3 - -+// -+// Note1: BIT24: it is CKO when chip is reset -+// -+//------------------------------------------------------ -+// PORT 2: -+// -+// PIN/BIT N FUNC0 FUNC1 FUNC2 NOTE -+// 0 SD0 A20 - -+// 1 SD1 A21 - -+// 2 SD2 A22 - -+// 3 SD3 A23 - -+// 4 SD4 A24 - -+// 5 SD5 A25 - -+// 6 SD6 - - -+// 7 SD7 - - -+// 8 SD8 TSDI0 - -+// 9 SD9 TSDI1 - -+// 10 SD10 TSDI2 - -+// 11 SD11 TSDI3 - -+// 12 SD12 TSDI4 - -+// 13 SD13 TSDI5 - -+// 14 SD14 TSDI6 - -+// 15 SD15 TSDI7 - -+// 16 A16/ALE AL(unshare) MSC0_CMD -+// 17 A17 MSC0_D3 - -+// 18 A18 DREQ - -+// 19 A19 DACK - -+// 20 WAIT# - - Note2 -+// 21 CS1# - - -+// 22 CS2# - - -+// 23 CS3# - - -+// 24 CS4# - - -+// 25 RD# - - -+// 26 WR# - - -+// 27 FRB# - - Note3 -+// 28 FRE# MSC0_D0 - -+// 29 FWE# MSC0_D1 - -+// 30 - - - Note4 -+// 31 - - - Note5 -+// -+// Note2: BIT20: it is WIAT# pin when chip is reset -+// -+// Note3: BIT27: when NAND is used, it should connect to NANF FRB#. -+// -+// Note4: BIT30: it is BOOT_SEL0 which would be set as input without pulling when chip is reset. -+// -+// Note5: BIT31: it is BOOT_SEL1 which would be set as input without pulling when chip is reset. -+// -+//------------------------------------------------------ -+// PORT 3: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 0 LCD_B2 - -+// 1 LCD_B3 - -+// 2 LCD_B4 - -+// 3 LCD_B5 - -+// 4 LCD_B6 - -+// 5 LCD_B7 - -+// 6 LCD_G2 - -+// 7 LCD_G3 - -+// 8 LCD_G4 - -+// 9 LCD_G5 - -+// 10 LCD_G6 - -+// 11 LCD_G7 - -+// 12 LCD_R2 - -+// 13 LCD_R3 - -+// 14 LCD_R4 - -+// 15 LCD_R5 - -+// 16 LCD_R6 - -+// 17 LCD_R7 - -+// 18 LCD_PCLK - -+// 19 LCD_HSYNC - -+// 20 LCD_VSYNC - -+// 21 LCD_DE - -+// 22 LCD_CLS LCD_R1 -+// 23 LCD_SPL LCD_G0 -+// 24 LCD_PS LCD_G1 -+// 25 LCD_REV LCD_B1 -+// 26 LCD_B0 - -+// 27 LCD_R0 - -+// 28 UART0_RXD TSCLK -+// 29 UART0_TXD TSSTR -+// 30 UART0_CTS TSFRM -+// 31 UART0_RTS TSFAIL -+// -+//------------------------------------------------------ -+// PORT 4: -+// -+// PIN/BIT N FUNC0 FUNC1 FUNC2 NOTE -+// 0 CIM_D0 TSDI0 - -+// 1 CIM_D1 TSDI1 - -+// 2 CIM_D2 TSDI2 - -+// 3 CIM_D3 TSDI3 - -+// 4 CIM_D4 TSDI4 - -+// 5 CIM_D5 TSDI5 - -+// 6 CIM_D6 TSDI6 - -+// 7 CIM_D7 TSDI7 - -+// 8 CIM_MCLK TSFAIL - -+// 9 CIM_PCLK TSCLK - -+// 10 CIM_VSYNC TSSTR - -+// 11 CIM_HSYNC TSFRM - -+// 12 I2C_SDA - - -+// 13 I2C_SCK - - -+// 18 SDATO - - -+// 19 SDATI - - -+// 20 PWM0 - - -+// 22 PWM2 SYNC - -+// 23 PWM3 UART1_RxD BCLK -+// 24 PWM4 - - -+// 25 PWM5 UART1_TxD SCLK_RSTN -+// 28 DCS1# - - -+// 29 - - - Note6 -+// 30 WKUP - - Note7 -+// 31 - - - Note8 -+// -+// Note6: BIT29: it is BOOT_SEL2 which would be set as input without pulling when chip is reset. -+// Note7: BIT30: it is only used as input and interrupt, and with no pull-up and pull-down -+// Note8: BIT31: it is used to select the function of UART or JTAG set by PESEL[31] -+// PESEL[31] = 0, select JTAG function -+// PESEL[31] = 1, select UART function -+// -+//------------------------------------------------------ -+// PORT 5: -+// -+// PIN/BIT N FUNC0 FUNC1 NOTE -+// 10 SSI_CLK - -+// 11 SSI_DT PWM1 -+// 12 SSI_DR - -+// 13 SSI_CE0# - -+// 14 SSI_GPC - -+// 15 SSI_CE2# - -+// -+////////////////////////////////////////////////////////// -+ -+/*---------------------------------------------------------------- -+ * p is the port number (0,1,2,3,4,5) -+ * o is the pin offset (0-31) inside the port -+ * n is the absolute number of a pin (0-127), regardless of the port -+ */ -+ -+//------------------------------------------- -+// Function Pins Mode -+ -+#define __gpio_as_func0(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXSELC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_func1(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_func2(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFUNS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXSELC(p) = (1 << o); \ -+} while (0) -+ -+/* -+ * D0 ~ D31, A0 ~ A14, DCS0#, RAS#, CAS#, -+ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -+ */ -+#define __gpio_as_sdram_32bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -+ REG_GPIO_PXSELC(0) = 0xffffffff; \ -+ REG_GPIO_PXPES(0) = 0xffffffff; \ -+ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -+} while (0) -+ -+ -+/* -+ * D0 ~ D31, A0 ~ A14, DCS0#, RAS#, CAS#, -+ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -+ * !!!!DCS1# -+ */ -+#define __gpio_as_sdram_x2_32bit() \ -+do { \ -+ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -+ REG_GPIO_PXSELC(0) = 0xffffffff; \ -+ REG_GPIO_PXPES(0) = 0xffffffff; \ -+ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -+ REG_GPIO_PXFUNS(4) = 0x10000000; \ -+ REG_GPIO_PXSELC(4) = 0x10000000; \ -+ REG_GPIO_PXPES(4) = 0x10000000; \ -+} while (0) -+ -+/* -+ * D0 ~ D15, A0 ~ A14, DCS0#, RAS#, CAS#, -+ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -+ */ -+#define __gpio_as_sdram_16bit() \ -+do { \ -+ /* 32/16-bit data normal order */ \ -+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -+ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -+ REG_GPIO_PXPES(0) = 0x0000ffff; \ -+ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -+ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -+ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -+} while (0) -+ -+/* -+ * D0 ~ D7, CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# -+ * @n: chip select number(1 ~ 4) -+ */ -+#define __gpio_as_nand_8bit(n) \ -+do { \ -+ /* 32/16-bit data bus */ \ -+ REG_GPIO_PXFUNS(0) = 0x000000ff; /* D0~D7 */ \ -+ REG_GPIO_PXSELC(0) = 0x000000ff; \ -+ REG_GPIO_PXPES(0) = 0x000000ff; \ -+ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(A15) */ \ -+ REG_GPIO_PXSELC(1) = 0x00008000; \ -+ REG_GPIO_PXPES(1) = 0x00008000; \ -+ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(A16) */ \ -+ REG_GPIO_PXSELC(2) = 0x00010000; \ -+ REG_GPIO_PXPES(2) = 0x00010000; \ -+ \ -+ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -+ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -+ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -+ \ -+ REG_GPIO_PXFUNS(1) = 0x00080000; /* RDWE#/BUFD# */ \ -+ REG_GPIO_PXSELC(1) = 0x00080000; \ -+ REG_GPIO_PXPES(1) = 0x00080000; \ -+ REG_GPIO_PXFUNS(2) = 0x30000000; /* FRE#, FWE# */ \ -+ REG_GPIO_PXSELC(2) = 0x30000000; \ -+ REG_GPIO_PXPES(2) = 0x30000000; \ -+ REG_GPIO_PXFUNC(2) = 0x08000000; /* FRB#(input) */ \ -+ REG_GPIO_PXSELC(2) = 0x08000000; \ -+ REG_GPIO_PXDIRC(2) = 0x08000000; \ -+ REG_GPIO_PXPES(2) = 0x08000000; \ -+} while (0) -+ -+ -+/* -+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 -+ * @n: chip select number(1 ~ 4) -+ */ -+#define __gpio_as_nor_8bit(n) \ -+do { \ -+ /* 32/16-bit data bus */ \ -+ REG_GPIO_PXFUNS(0) = 0x000000ff; \ -+ REG_GPIO_PXSELC(0) = 0x000000ff; \ -+ REG_GPIO_PXPES(0) = 0x000000ff; \ -+ \ -+ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -+ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -+ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -+ \ -+ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -+ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -+ REG_GPIO_PXPES(1) = 0x0000ffff; \ -+ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -+ REG_GPIO_PXSELC(2) = 0x06110007; \ -+ REG_GPIO_PXPES(2) = 0x06110007; \ -+ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -+ REG_GPIO_PXSELS(2) = 0x000e0000; \ -+ REG_GPIO_PXPES(2) = 0x000e0000; \ -+} while (0) -+ -+/* -+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 -+ * @n: chip select number(1 ~ 4) -+ */ -+#define __gpio_as_nor_16bit(n) \ -+do { \ -+ /* 32/16-bit data normal order */ \ -+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -+ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -+ REG_GPIO_PXPES(0) = 0x0000ffff; \ -+ \ -+ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -+ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -+ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -+ \ -+ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -+ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -+ REG_GPIO_PXPES(1) = 0x0000ffff; \ -+ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -+ REG_GPIO_PXSELC(2) = 0x06110007; \ -+ REG_GPIO_PXPES(2) = 0x06110007; \ -+ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -+ REG_GPIO_PXSELS(2) = 0x000e0000; \ -+ REG_GPIO_PXPES(2) = 0x000e0000; \ -+} while (0) -+ -+/* -+ * UART0_TxD, UART0_RxD -+ */ -+#define __gpio_as_uart0() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x30000000; \ -+ REG_GPIO_PXSELC(3) = 0x30000000; \ -+ REG_GPIO_PXPES(3) = 0x30000000; \ -+} while (0) -+ -+/* -+ * UART0_TxD, UART0_RxD, UART0_CTS, UART0_RTS -+ */ -+#define __gpio_as_uart0_ctsrts() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0xf0000000; \ -+ REG_GPIO_PXSELC(3) = 0xf0000000; \ -+ REG_GPIO_PXPES(3) = 0xf0000000; \ -+} while (0) -+ -+/* -+ * UART1_TxD, UART1_RxD -+ */ -+#define __gpio_as_uart1() \ -+do { \ -+ REG_GPIO_PXTRGC(4) = 0x02800000; \ -+ REG_GPIO_PXFUNS(4) = 0x02800000; \ -+ REG_GPIO_PXSELS(4) = 0x02800000; \ -+ REG_GPIO_PXPES(4) = 0x02800000; \ -+} while (0) -+ -+/* -+ * TSCLK, TSSTR, TSFRM, TSFAIL, TSDI0~7 -+ */ -+#define __gpio_as_tssi() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x0000ff00; \ -+ REG_GPIO_PXSELS(2) = 0x0000ff00; \ -+ REG_GPIO_PXPES(2) = 0x0000ff00; \ -+ REG_GPIO_PXFUNS(3) = 0xf0000000; \ -+ REG_GPIO_PXSELS(3) = 0xf0000000; \ -+ REG_GPIO_PXPES(3) = 0xf0000000; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D7, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_8bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003c00ff; \ -+ REG_GPIO_PXTRGC(3) = 0x003c00ff; \ -+ REG_GPIO_PXSELC(3) = 0x003c00ff; \ -+ REG_GPIO_PXPES(3) = 0x003c00ff; \ -+} while (0) -+ -+/* -+ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_16bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003cffff; \ -+ REG_GPIO_PXTRGC(3) = 0x003cffff; \ -+ REG_GPIO_PXSELC(3) = 0x003cffff; \ -+ REG_GPIO_PXPES(3) = 0x003cffff; \ -+} while (0) -+ -+/* -+ * LCD_R2~LCD_R7, LCD_G2~LCD_G7, LCD_B2~LCD_B7, -+ * LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_18bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x003fffff; \ -+ REG_GPIO_PXTRGC(3) = 0x003fffff; \ -+ REG_GPIO_PXSELC(3) = 0x003fffff; \ -+ REG_GPIO_PXPES(3) = 0x003fffff; \ -+} while (0) -+ -+/* -+ * LCD_R0~LCD_R7, LCD_G0~LCD_G7, LCD_B0~LCD_B7, -+ * LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -+ */ -+#define __gpio_as_lcd_24bit() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x0fffffff; \ -+ REG_GPIO_PXTRGC(3) = 0x0fffffff; \ -+ REG_GPIO_PXSELC(3) = 0x0c3fffff; \ -+ REG_GPIO_PXSELS(3) = 0x03c00000; \ -+ REG_GPIO_PXPES(3) = 0x0fffffff; \ -+} while (0) -+ -+/* -+ * LCD_CLS, LCD_SPL, LCD_PS, LCD_REV -+ */ -+#define __gpio_as_lcd_special() \ -+do { \ -+ REG_GPIO_PXFUNS(3) = 0x03C00000; \ -+ REG_GPIO_PXSELC(3) = 0x03C00000; \ -+ REG_GPIO_PXPES(3) = 0x03C00000; \ -+} while (0) -+ -+/* -+ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC -+ */ -+#define __gpio_as_cim() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00000fff; \ -+ REG_GPIO_PXSELC(4) = 0x00000fff; \ -+ REG_GPIO_PXPES(4) = 0x00000fff; \ -+} while (0) -+ -+/* -+ * SDATO, SDATI, BCLK, SYNC, SCLK_RSTN(gpio sepc) or -+ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET(aic spec) -+ */ -+#define __gpio_as_aic() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x16c00000; \ -+ REG_GPIO_PXTRGC(4) = 0x02c00000; \ -+ REG_GPIO_PXTRGS(4) = 0x14000000; \ -+ REG_GPIO_PXSELC(4) = 0x14c00000; \ -+ REG_GPIO_PXSELS(4) = 0x02000000; \ -+ REG_GPIO_PXPES(4) = 0x16c00000; \ -+} while (0) -+ -+/* -+ * MSC0_CMD, MSC0_CLK, MSC0_D0 ~ MSC0_D3 -+ */ -+#define __gpio_as_msc0_4bit() \ -+do { \ -+ REG_GPIO_PXFUNS(1) = 0x00008000; \ -+ REG_GPIO_PXTRGS(1) = 0x00008000; \ -+ REG_GPIO_PXSELC(1) = 0x00008000; \ -+ REG_GPIO_PXPES(1) = 0x00008000; \ -+ REG_GPIO_PXFUNS(2) = 0x38030000; \ -+ REG_GPIO_PXTRGS(2) = 0x00010000; \ -+ REG_GPIO_PXTRGC(2) = 0x38020000; \ -+ REG_GPIO_PXSELC(2) = 0x08010000; \ -+ REG_GPIO_PXSELS(2) = 0x30020000; \ -+ REG_GPIO_PXPES(2) = 0x38030000; \ -+} while (0) -+ -+ -+/* -+ * MSC1_CMD, MSC1_CLK, MSC1_D0 ~ MSC1_D3 -+ */ -+#define __gpio_as_msc1_4bit() \ -+do { \ -+ REG_GPIO_PXFUNS(1) = 0xfc000000; \ -+ REG_GPIO_PXTRGC(1) = 0xfc000000; \ -+ REG_GPIO_PXSELS(1) = 0xfc000000; \ -+ REG_GPIO_PXPES(1) = 0xfc000000; \ -+} while (0) -+ -+#define __gpio_as_msc __gpio_as_msc0_4bit /* default as msc0 4bit */ -+#define __gpio_as_msc0 __gpio_as_msc0_4bit /* msc0 default as 4bit */ -+#define __gpio_as_msc1 __gpio_as_msc1_4bit /* msc1 only support 4bit */ -+ -+/* -+ * SSI_CE0, SSI_CE1, SSI_GPC, SSI_CLK, SSI_DT, SSI_DR -+ */ -+#define __gpio_as_ssi() \ -+do { \ -+ REG_GPIO_PXFUNS(1) = 0xfc000000; \ -+ REG_GPIO_PXTRGC(1) = 0xfc000000; \ -+ REG_GPIO_PXSELC(1) = 0xfc000000; \ -+ REG_GPIO_PXPES(1) = 0xfc000000; \ -+} while (0) -+ -+/* -+ * SSI_CE0, SSI_CE2, SSI_GPC, SSI_CLK, SSI_DT, SSI1_DR -+ */ -+#define __gpio_as_ssi_1() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x0000fc00; \ -+ REG_GPIO_PXTRGC(5) = 0x0000fc00; \ -+ REG_GPIO_PXSELC(5) = 0x0000fc00; \ -+ REG_GPIO_PXPES(5) = 0x0000fc00; \ -+} while (0) -+ -+/* -+ * I2C_SCK, I2C_SDA -+ */ -+#define __gpio_as_i2c() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00003000; \ -+ REG_GPIO_PXSELC(4) = 0x00003000; \ -+ REG_GPIO_PXPES(4) = 0x00003000; \ -+} while (0) -+ -+/* -+ * PWM0 -+ */ -+#define __gpio_as_pwm0() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00100000; \ -+ REG_GPIO_PXSELC(4) = 0x00100000; \ -+ REG_GPIO_PXPES(4) = 0x00100000; \ -+} while (0) -+ -+/* -+ * PWM1 -+ */ -+#define __gpio_as_pwm1() \ -+do { \ -+ REG_GPIO_PXFUNS(5) = 0x00000800; \ -+ REG_GPIO_PXSELC(5) = 0x00000800; \ -+ REG_GPIO_PXPES(5) = 0x00000800; \ -+} while (0) -+ -+/* -+ * PWM2 -+ */ -+#define __gpio_as_pwm2() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00400000; \ -+ REG_GPIO_PXSELC(4) = 0x00400000; \ -+ REG_GPIO_PXPES(4) = 0x00400000; \ -+} while (0) -+ -+/* -+ * PWM3 -+ */ -+#define __gpio_as_pwm3() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x00800000; \ -+ REG_GPIO_PXSELC(4) = 0x00800000; \ -+ REG_GPIO_PXPES(4) = 0x00800000; \ -+} while (0) -+ -+/* -+ * PWM4 -+ */ -+#define __gpio_as_pwm4() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x01000000; \ -+ REG_GPIO_PXSELC(4) = 0x01000000; \ -+ REG_GPIO_PXPES(4) = 0x01000000; \ -+} while (0) -+ -+/* -+ * PWM5 -+ */ -+#define __gpio_as_pwm5() \ -+do { \ -+ REG_GPIO_PXFUNS(4) = 0x02000000; \ -+ REG_GPIO_PXSELC(4) = 0x02000000; \ -+ REG_GPIO_PXPES(4) = 0x02000000; \ -+} while (0) -+ -+/* -+ * n = 0 ~ 5 -+ */ -+#define __gpio_as_pwm(n) __gpio_as_pwm##n() -+ -+/* -+ * DREQ -+ */ -+#define __gpio_as_dreq() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x00040000; \ -+ REG_GPIO_PXSELS(2) = 0x00040000; \ -+ REG_GPIO_PXPES(2) = 0x00040000; \ -+} while (0) -+ -+/* -+ * DACK -+ */ -+#define __gpio_as_dack() \ -+do { \ -+ REG_GPIO_PXFUNS(2) = 0x00080000; \ -+ REG_GPIO_PXSELS(2) = 0x00080000; \ -+ REG_GPIO_PXPES(2) = 0x00080000; \ -+} while (0) -+ -+/* -+ * GPIO or Interrupt Mode -+ */ -+#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) -+ -+#define __gpio_port_as_output(p, o) \ -+do { \ -+ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -+ REG_GPIO_PXSELC(p) = (1 << (o)); \ -+ REG_GPIO_PXDIRS(p) = (1 << (o)); \ -+} while (0) -+ -+#define __gpio_port_as_input(p, o) \ -+do { \ -+ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -+ REG_GPIO_PXSELC(p) = (1 << (o)); \ -+ REG_GPIO_PXDIRC(p) = (1 << (o)); \ -+} while (0) -+ -+#define __gpio_as_output(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_output(p, o); \ -+} while (0) -+ -+#define __gpio_as_input(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ __gpio_port_as_input(p, o); \ -+} while (0) -+ -+#define __gpio_set_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXDATS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_clear_pin(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXDATC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_get_pin(n) \ -+({ \ -+ unsigned int p, o, v; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ if (__gpio_get_port(p) & (1 << o)) \ -+ v = 1; \ -+ else \ -+ v = 0; \ -+ v; \ -+}) -+ -+#define __gpio_as_irq_high_level(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRS(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_low_level(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGC(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRC(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_rise_edge(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRS(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_as_irq_fall_edge(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+ REG_GPIO_PXTRGS(p) = (1 << o); \ -+ REG_GPIO_PXFUNC(p) = (1 << o); \ -+ REG_GPIO_PXSELS(p) = (1 << o); \ -+ REG_GPIO_PXDIRC(p) = (1 << o); \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_mask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMS(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_unmask_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXIMC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_ack_irq(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXFLGC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_get_irq() \ -+({ \ -+ unsigned int p, i, tmp, v = 0; \ -+ for (p = 3; p >= 0; p--) { \ -+ tmp = REG_GPIO_PXFLG(p); \ -+ for (i = 0; i < 32; i++) \ -+ if (tmp & (1 << i)) \ -+ v = (32*p + i); \ -+ } \ -+ v; \ -+}) -+ -+#define __gpio_group_irq(n) \ -+({ \ -+ register int tmp, i; \ -+ tmp = REG_GPIO_PXFLG((n)); \ -+ for (i=31;i>=0;i--) \ -+ if (tmp & (1 << i)) \ -+ break; \ -+ i; \ -+}) -+ -+#define __gpio_enable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXPEC(p) = (1 << o); \ -+} while (0) -+ -+#define __gpio_disable_pull(n) \ -+do { \ -+ unsigned int p, o; \ -+ p = (n) / 32; \ -+ o = (n) % 32; \ -+ REG_GPIO_PXPES(p) = (1 << o); \ -+} while (0) -+ -+ -+/*************************************************************************** -+ * CPM -+ ***************************************************************************/ -+#define __cpm_get_pllm() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) -+#define __cpm_get_plln() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) -+#define __cpm_get_pllod() \ -+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) -+ -+#define __cpm_get_cdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) -+#define __cpm_get_hdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) -+#define __cpm_get_pdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) -+#define __cpm_get_mdiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) -+#define __cpm_get_h1div() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_H1DIV_MASK) >> CPM_CPCCR_H1DIV_BIT) -+#define __cpm_get_udiv() \ -+ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) -+#define __cpm_get_i2sdiv() \ -+ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) -+#define __cpm_get_pixdiv() \ -+ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) -+#define __cpm_get_mscdiv(n) \ -+ ((REG_CPM_MSCCDR(n) & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) -+#define __cpm_get_uhcdiv() \ -+ ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) -+#define __cpm_get_ssidiv() \ -+ ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) -+#define __cpm_get_pcmdiv(v) \ -+ ((REG_CPM_PCMCDR & CPM_PCMCDR_PCMCD_MASK) >> CPM_PCMCDR_PCMCD_BIT) -+ -+#define __cpm_set_cdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) -+#define __cpm_set_hdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) -+#define __cpm_set_pdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) -+#define __cpm_set_mdiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) -+#define __cpm_set_h1div(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_H1DIV_MASK) | ((v) << (CPM_CPCCR_H1DIV_BIT))) -+#define __cpm_set_udiv(v) \ -+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) -+#define __cpm_set_i2sdiv(v) \ -+ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) -+#define __cpm_set_pixdiv(v) \ -+ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) -+#define __cpm_set_mscdiv(n, v) \ -+ (REG_CPM_MSCCDR(n) = (REG_CPM_MSCCDR(n) & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) -+#define __cpm_set_uhcdiv(v) \ -+ (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) -+#define __cpm_set_ssidiv(v) \ -+ (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) -+#define __cpm_set_pcmdiv(v) \ -+ (REG_CPM_PCMCDR = (REG_CPM_PCMCDR & ~CPM_PCMCDR_PCMCD_MASK) | ((v) << (CPM_PCMCDR_PCMCD_BIT))) -+ -+#define __cpm_select_pcmclk_pll() (REG_CPM_PCMCDR |= CPM_PCMCDR_PCMS) -+#define __cpm_select_pcmclk_exclk() (REG_CPM_PCMCDR &= ~CPM_PCMCDR_PCMS) -+#define __cpm_select_tveclk_exclk() (REG_CPM_LPCDR |= CPM_CPCCR_LSCS) -+#define __cpm_select_tveclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LSCS) -+#define __cpm_select_pixclk_lcd() (REG_CPM_LPCDR &= ~CPM_LPCDR_LTCS) -+#define __cpm_select_pixclk_tve() (REG_CPM_LPCDR |= CPM_LPCDR_LTCS) -+#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) -+#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) -+#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) -+#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) -+ -+#define __cpm_enable_cko() -+#define __cpm_exclk_direct() (REG_CPM_CPCCR &= ~CPM_CPCCR_ECS) -+#define __cpm_exclk_div2() (REG_CPM_CPCCR |= CPM_CPCCR_ECS) -+#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) -+#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) -+#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) -+#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) -+ -+#define __cpm_pll_is_off() (REG_CPM_CPPSR & CPM_CPPSR_PLLOFF) -+#define __cpm_pll_is_on() (REG_CPM_CPPSR & CPM_CPPSR_PLLON) -+#define __cpm_pll_bypass() (REG_CPM_CPPSR |= CPM_CPPSR_PLLBP) -+ -+#define __cpm_get_cclk_doze_duty() \ -+ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) -+#define __cpm_set_cclk_doze_duty(v) \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) -+ -+#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) -+#define __cpm_idle_mode() \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) -+#define __cpm_sleep_mode() \ -+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -+ -+#define __cpm_stop_all() (REG_CPM_CLKGR = 0x1fffffff) -+#define __cpm_stop_cimram() (REG_CPM_CLKGR |= CPM_CLKGR_CIMRAM) -+#define __cpm_stop_idct() (REG_CPM_CLKGR |= CPM_CLKGR_IDCT) -+#define __cpm_stop_db() (REG_CPM_CLKGR |= CPM_CLKGR_DB) -+#define __cpm_stop_me() (REG_CPM_CLKGR |= CPM_CLKGR_ME) -+#define __cpm_stop_mc() (REG_CPM_CLKGR |= CPM_CLKGR_MC) -+#define __cpm_stop_tve() (REG_CPM_CLKGR |= CPM_CLKGR_TVE) -+#define __cpm_stop_tssi() (REG_CPM_CLKGR |= CPM_CLKGR_TSSI) -+#define __cpm_stop_owi() (REG_CPM_CLKGR |= CPM_CLKGR_OWI) -+#define __cpm_stop_pcm() (REG_CPM_CLKGR |= CPM_CLKGR_PCM) -+#define __cpm_stop_uart3() (REG_CPM_CLKGR |= CPM_CLKGR_UART3) -+#define __cpm_stop_uart2() (REG_CPM_CLKGR |= CPM_CLKGR_UART2) -+#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -+#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -+#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) -+#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -+#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -+#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -+#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) -+#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -+#define __cpm_stop_msc(n) (REG_CPM_CLKGR |= CPM_CLKGR_MSC##n) -+#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) -+#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -+#define __cpm_stop_ssi(n) (REG_CPM_CLKGR |= CPM_CLKGR_SSI##n) -+#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -+#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -+#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -+#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) -+ -+#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -+#define __cpm_start_cimram() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIMRAM) -+#define __cpm_start_idct() (REG_CPM_CLKGR &= ~CPM_CLKGR_IDCT) -+#define __cpm_start_db() (REG_CPM_CLKGR &= ~CPM_CLKGR_DB) -+#define __cpm_start_me() (REG_CPM_CLKGR &= ~CPM_CLKGR_ME) -+#define __cpm_start_mc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MC) -+#define __cpm_start_tve() (REG_CPM_CLKGR &= ~CPM_CLKGR_TVE) -+#define __cpm_start_tssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_TSSI) -+#define __cpm_start_owi() (REG_CPM_CLKGR &= ~CPM_CLKGR_OWI) -+#define __cpm_start_pcm() (REG_CPM_CLKGR &= ~CPM_CLKGR_PCM) -+#define __cpm_start_uart3() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART3) -+#define __cpm_start_uart2() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART2) -+#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) -+#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) -+#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -+#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) -+#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) -+#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) -+#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -+#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) -+#define __cpm_start_msc(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC##n) -+#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -+#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) -+#define __cpm_start_ssi(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI##n) -+#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) -+#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) -+#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -+#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) -+ -+#define __cpm_get_o1st() \ -+ ((REG_CPM_OPCR & CPM_OPCR_O1ST_MASK) >> CPM_OPCR_O1ST_BIT) -+#define __cpm_set_o1st(v) \ -+ (REG_CPM_OPCR = (REG_CPM_OPCR & ~CPM_OPCR_O1ST_MASK) | ((v) << (CPM_OPCR_O1ST_BIT))) -+#define __cpm_enable_uhcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UHCPHY_DISABLE) -+#define __cpm_suspend_uhcphy() (REG_CPM_OPCR |= CPM_OPCR_UHCPHY_DISABLE) -+#define __cpm_enable_udcphy() (REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE) -+#define __cpm_suspend_udcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE) -+#define __cpm_enable_osc_in_sleep() (REG_CPM_OPCR |= CPM_OPCR_OSC_ENABLE) -+#define __cpm_disable_osc_in_sleep() (REG_CPM_OPCR &= ~CPM_OPCR_OSC_ENABLE) -+#define __cpm_select_rtcclk_rtc() (REG_CPM_OPCR |= CPM_OPCR_ERCS) -+#define __cpm_select_rtcclk_exclk() (REG_CPM_OPCR &= ~CPM_OPCR_ERCS) -+ -+ -+/*************************************************************************** -+ * TCU -+ ***************************************************************************/ -+// where 'n' is the TCU channel -+#define __tcu_select_extalclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) -+#define __tcu_select_rtcclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) -+#define __tcu_select_pclk(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) -+#define __tcu_disable_pclk(n) \ -+ REG_TCU_TCSR(n) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PCK_EN); -+#define __tcu_select_clk_div1(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) -+#define __tcu_select_clk_div4(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) -+#define __tcu_select_clk_div16(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) -+#define __tcu_select_clk_div64(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) -+#define __tcu_select_clk_div256(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) -+#define __tcu_select_clk_div1024(n) \ -+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) -+ -+#define __tcu_enable_pwm_output(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN) -+#define __tcu_disable_pwm_output(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN) -+ -+#define __tcu_init_pwm_output_high(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH) -+#define __tcu_init_pwm_output_low(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH) -+ -+#define __tcu_set_pwm_output_shutdown_graceful(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD) -+#define __tcu_set_pwm_output_shutdown_abrupt(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD) -+ -+#define __tcu_clear_counter_to_zero(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_CNT_CLRZ) -+ -+#define __tcu_ost_enabled() (REG_TCU_TER & TCU_TER_OSTEN) -+#define __tcu_enable_ost() (REG_TCU_TESR = TCU_TESR_OSTST) -+#define __tcu_disable_ost() (REG_TCU_TECR = TCU_TECR_OSTCL) -+ -+#define __tcu_counter_enabled(n) (REG_TCU_TER & (1 << (n))) -+#define __tcu_start_counter(n) (REG_TCU_TESR |= (1 << (n))) -+#define __tcu_stop_counter(n) (REG_TCU_TECR |= (1 << (n))) -+ -+#define __tcu_half_match_flag(n) (REG_TCU_TFR & (1 << ((n) + 16))) -+#define __tcu_full_match_flag(n) (REG_TCU_TFR & (1 << (n))) -+#define __tcu_set_half_match_flag(n) (REG_TCU_TFSR = (1 << ((n) + 16))) -+#define __tcu_set_full_match_flag(n) (REG_TCU_TFSR = (1 << (n))) -+#define __tcu_clear_half_match_flag(n) (REG_TCU_TFCR = (1 << ((n) + 16))) -+#define __tcu_clear_full_match_flag(n) (REG_TCU_TFCR = (1 << (n))) -+#define __tcu_mask_half_match_irq(n) (REG_TCU_TMSR = (1 << ((n) + 16))) -+#define __tcu_mask_full_match_irq(n) (REG_TCU_TMSR = (1 << (n))) -+#define __tcu_unmask_half_match_irq(n) (REG_TCU_TMCR = (1 << ((n) + 16))) -+#define __tcu_unmask_full_match_irq(n) (REG_TCU_TMCR = (1 << (n))) -+ -+#define __tcu_ost_match_flag() (REG_TCU_TFR & TCU_TFR_OSTFLAG) -+#define __tcu_set_ost_match_flag() (REG_TCU_TFSR = TCU_TFSR_OSTFST) -+#define __tcu_clear_ost_match_flag() (REG_TCU_TFCR = TCU_TFCR_OSTFCL) -+#define __tcu_ost_match_irq_masked() (REG_TCU_TMR & TCU_TMR_OSTMASK) -+#define __tcu_mask_ost_match_irq() (REG_TCU_TMSR = TCU_TMSR_OSTMST) -+#define __tcu_unmask_ost_match_irq() (REG_TCU_TMCR = TCU_TMCR_OSTMCL) -+ -+#define __tcu_wdt_clock_stopped() (REG_TCU_TSR & TCU_TSSR_WDTSC) -+#define __tcu_ost_clock_stopped() (REG_TCU_TSR & TCU_TSR_OST) -+#define __tcu_timer_clock_stopped(n) (REG_TCU_TSR & (1 << (n))) -+ -+#define __tcu_start_wdt_clock() (REG_TCU_TSCR = TCU_TSSR_WDTSC) -+#define __tcu_start_ost_clock() (REG_TCU_TSCR = TCU_TSCR_OSTSC) -+#define __tcu_start_timer_clock(n) (REG_TCU_TSCR = (1 << (n))) -+ -+#define __tcu_stop_wdt_clock() (REG_TCU_TSSR = TCU_TSSR_WDTSC) -+#define __tcu_stop_ost_clock() (REG_TCU_TSSR = TCU_TSSR_OSTSS) -+#define __tcu_stop_timer_clock(n) (REG_TCU_TSSR = (1 << (n))) -+ -+#define __tcu_get_count(n) (REG_TCU_TCNT((n))) -+#define __tcu_set_count(n,v) (REG_TCU_TCNT((n)) = (v)) -+#define __tcu_set_full_data(n,v) (REG_TCU_TDFR((n)) = (v)) -+#define __tcu_set_half_data(n,v) (REG_TCU_TDHR((n)) = (v)) -+ -+/* TCU2, counter 1, 2*/ -+#define __tcu_read_real_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -+#define __tcu_read_false_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -+#define __tcu_counter_busy(n) (REG_TCU_TSTR & (1 << (n))) -+#define __tcu_counter_ready(n) (REG_TCU_TSTR & (1 << (n))) -+ -+#define __tcu_set_read_real_value(n) (REG_TCU_TSTSR = (1 << ((n) + 16))) -+#define __tcu_set_read_false_value(n) (REG_TCU_TSTCR = (1 << ((n) + 16))) -+#define __tcu_set_counter_busy(n) (REG_TCU_TSTSR = (1 << (n))) -+#define __tcu_set_counter_ready(n) (REG_TCU_TSTCR = (1 << (n))) -+ -+/* ost counter */ -+#define __ostcu_set_pwm_output_shutdown_graceful() (REG_TCU_OSTCSR &= ~TCU_TCSR_PWM_SD) -+#define __ostcu_set_ost_output_shutdown_abrupt() (REG_TCU_OSTCSR |= TCU_TCSR_PWM_SD) -+#define __ostcu_select_clk_div1() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1) -+#define __ostcu_select_clk_div4() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE4) -+#define __ostcu_select_clk_div16() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE16) -+#define __ostcu_select_clk_div64() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE64) -+#define __ostcu_select_clk_div256() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE256) -+#define __ostcu_select_clk_div1024() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1024) -+#define __ostcu_select_rtcclk() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_RTC_EN) -+#define __ostcu_select_extalclk() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_EXT_EN) -+#define __ostcu_select_pclk() \ -+ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_PCK_EN) -+ -+ -+/*************************************************************************** -+ * WDT -+ ***************************************************************************/ -+#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) -+#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) -+#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) -+#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) -+ -+#define __wdt_select_extalclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) -+#define __wdt_select_rtcclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) -+#define __wdt_select_pclk() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) -+ -+#define __wdt_select_clk_div1() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) -+#define __wdt_select_clk_div4() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) -+#define __wdt_select_clk_div16() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) -+#define __wdt_select_clk_div64() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) -+#define __wdt_select_clk_div256() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) -+#define __wdt_select_clk_div1024() \ -+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) -+ -+ -+/*************************************************************************** -+ * UART -+ ***************************************************************************/ -+ -+#define __uart_enable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -+#define __uart_disable(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -+ -+#define __uart_enable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -+#define __uart_disable_transmit_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -+ -+#define __uart_enable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -+#define __uart_disable_receive_irq(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -+ -+#define __uart_enable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -+#define __uart_disable_loopback(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -+ -+#define __uart_set_8n1(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -+ -+#define __uart_set_baud(n, devclk, baud) \ -+ do { \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -+ } while (0) -+ -+#define __uart_parity_error(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -+ -+#define __uart_clear_errors(n) \ -+ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -+ -+#define __uart_transmit_fifo_empty(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -+ -+#define __uart_transmit_end(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -+ -+#define __uart_transmit_char(n, ch) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -+ -+#define __uart_receive_fifo_full(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_ready(n) \ -+ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -+ -+#define __uart_receive_char(n) \ -+ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -+ -+#define __uart_disable_irda() \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -+#define __uart_enable_irda() \ -+ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -+ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -+ -+ -+/*************************************************************************** -+ * DMAC -+ ***************************************************************************/ -+ -+/* m is the DMA controller index (0, 1), n is the DMA channel index (0 - 11) */ -+ -+#define __dmac_enable_module(m) \ -+ ( REG_DMAC_DMACR(m) |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_012345 ) -+#define __dmac_disable_module(m) \ -+ ( REG_DMAC_DMACR(m) &= ~DMAC_DMACR_DMAE ) -+ -+/* p=0,1,2,3 */ -+#define __dmac_set_priority(m,p) \ -+do { \ -+ REG_DMAC_DMACR(m) &= ~DMAC_DMACR_PR_MASK; \ -+ REG_DMAC_DMACR(m) |= ((p) << DMAC_DMACR_PR_BIT); \ -+} while (0) -+ -+#define __dmac_test_halt_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_HLT ) -+#define __dmac_test_addr_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_AR ) -+ -+#define __dmac_channel_enable_clk(n) \ -+ REG_DMAC_DMACKE((n)/HALF_DMA_NUM) |= 1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM); -+ -+#define __dmac_enable_descriptor(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) -+#define __dmac_disable_descriptor(n) \ -+ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) -+ -+#define __dmac_enable_channel(n) \ -+do { \ -+ REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN; \ -+} while (0) -+#define __dmac_disable_channel(n) \ -+do { \ -+ REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN; \ -+} while (0) -+#define __dmac_channel_enabled(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) -+ -+#define __dmac_channel_enable_irq(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) -+#define __dmac_channel_disable_irq(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) -+ -+#define __dmac_channel_transmit_halt_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) -+#define __dmac_channel_transmit_end_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) -+#define __dmac_channel_address_error_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) -+#define __dmac_channel_count_terminated_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) -+#define __dmac_channel_descriptor_invalid_detected(n) \ -+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) -+ -+#define __dmac_channel_clear_transmit_halt(n) \ -+ do { \ -+ /* clear both channel halt error and globle halt error */ \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT; \ -+ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_HLT; \ -+ } while (0) -+#define __dmac_channel_clear_transmit_end(n) \ -+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) -+#define __dmac_channel_clear_address_error(n) \ -+ do { \ -+ REG_DMAC_DDA(n) = 0; /* clear descriptor address register */ \ -+ REG_DMAC_DSAR(n) = 0; /* clear source address register */ \ -+ REG_DMAC_DTAR(n) = 0; /* clear target address register */ \ -+ /* clear both channel addr error and globle address error */ \ -+ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR; \ -+ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_AR; \ -+ } while (0) -+#define __dmac_channel_clear_count_terminated(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) -+#define __dmac_channel_clear_descriptor_invalid(n) \ -+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) -+ -+#define __dmac_channel_set_transfer_unit_32bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_8bit(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_16byte(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ -+} while (0) -+ -+#define __dmac_channel_set_transfer_unit_32byte(n) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_dest_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ -+} while (0) -+ -+/* w=8,16,32 */ -+#define __dmac_channel_set_src_port_width(n,w) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ -+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ -+} while (0) -+ -+/* v=0-15 */ -+#define __dmac_channel_set_rdil(n,v) \ -+do { \ -+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ -+ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ -+} while (0) -+ -+#define __dmac_channel_dest_addr_fixed(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) -+#define __dmac_channel_dest_addr_increment(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) -+ -+#define __dmac_channel_src_addr_fixed(n) \ -+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) -+#define __dmac_channel_src_addr_increment(n) \ -+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) -+ -+#define __dmac_channel_set_doorbell(n) \ -+ ( REG_DMAC_DMADBSR((n)/HALF_DMA_NUM) = (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -+ -+#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) & (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -+#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) &= ~(1 <<((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -+ -+static __inline__ int __dmac_get_irq(void) -+{ -+ int i; -+ for (i = 0; i < MAX_DMA_NUM; i++) -+ if (__dmac_channel_irq_detected(i)) -+ return i; -+ return -1; -+} -+ -+ -+/*************************************************************************** -+ * AIC (AC'97 & I2S Controller) -+ ***************************************************************************/ -+ -+#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) -+#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) -+ -+#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) -+#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) -+ -+#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) -+#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) -+ -+#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) -+#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) -+#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) -+ -+#define __aic_reset() \ -+do { \ -+ REG_AIC_FR |= AIC_FR_RST; \ -+} while(0) -+ -+ -+#define __aic_set_transmit_trigger(n) \ -+do { \ -+ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ -+ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ -+} while(0) -+ -+#define __aic_set_receive_trigger(n) \ -+do { \ -+ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ -+ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ -+} while(0) -+ -+#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) -+#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) -+#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) -+#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) -+#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) -+#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) -+ -+#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) -+#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) -+ -+#define __aic_enable_transmit_intr() \ -+ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) -+#define __aic_disable_transmit_intr() \ -+ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) -+#define __aic_enable_receive_intr() \ -+ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) -+#define __aic_disable_receive_intr() \ -+ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) -+ -+#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) -+#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) -+#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) -+#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) -+ -+#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) -+#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) -+#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) -+#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) -+#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) -+#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) -+ -+#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 -+#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 -+#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 -+#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 -+#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 -+#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 -+ -+#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 -+#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 -+#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 -+#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 -+#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 -+#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 -+ -+#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) -+#define __ac97_set_xs_mono() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ -+} while(0) -+#define __ac97_set_xs_stereo() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ -+} while(0) -+ -+/* In fact, only stereo is support now. */ -+#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) -+#define __ac97_set_rs_mono() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ -+} while(0) -+#define __ac97_set_rs_stereo() \ -+do { \ -+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -+ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ -+} while(0) -+ -+#define __ac97_warm_reset_codec() \ -+ do { \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ -+ udelay(2); \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ -+ } while (0) -+ -+#define __ac97_cold_reset_codec() \ -+ do { \ -+ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ -+ udelay(2); \ -+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ -+ } while (0) -+ -+/* n=8,16,18,20 */ -+#define __ac97_set_iass(n) \ -+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) -+#define __ac97_set_oass(n) \ -+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) -+ -+#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) -+#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) -+ -+/* n=8,16,18,20,24 */ -+/*#define __i2s_set_sample_size(n) \ -+ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ -+ -+#define __i2s_set_oss_sample_size(n) \ -+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) -+#define __i2s_set_iss_sample_size(n) \ -+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) -+ -+#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) -+#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) -+ -+#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) -+#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) -+#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) -+#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) -+ -+#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) -+ -+#define __aic_get_transmit_resident() \ -+ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) -+#define __aic_get_receive_count() \ -+ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -+ -+#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -+#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -+#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -+#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -+#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -+#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) -+#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) -+ -+#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -+ -+#define CODEC_READ_CMD (1 << 19) -+#define CODEC_WRITE_CMD (0 << 19) -+#define CODEC_REG_INDEX_BIT 12 -+#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -+#define CODEC_REG_DATA_BIT 4 -+#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -+ -+#define __ac97_out_rcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_wcmd_addr(reg) \ -+do { \ -+ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -+} while (0) -+ -+#define __ac97_out_data(value) \ -+do { \ -+ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -+} while (0) -+ -+#define __ac97_in_data() \ -+ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -+ -+#define __ac97_in_status_addr() \ -+ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -+ -+#define __i2s_set_sample_rate(i2sclk, sync) \ -+ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -+ -+#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -+#define __aic_read_rfifo() ( REG_AIC_DR ) -+ -+#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) -+#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) -+ -+// -+// Define next ops for AC97 compatible -+// -+ -+#define AC97_ACSR AIC_ACSR -+ -+#define __ac97_enable() __aic_enable(); __aic_select_ac97() -+#define __ac97_disable() __aic_disable() -+#define __ac97_reset() __aic_reset() -+ -+#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __ac97_enable_record() __aic_enable_record() -+#define __ac97_disable_record() __aic_disable_record() -+#define __ac97_enable_replay() __aic_enable_replay() -+#define __ac97_disable_replay() __aic_disable_replay() -+#define __ac97_enable_loopback() __aic_enable_loopback() -+#define __ac97_disable_loopback() __aic_disable_loopback() -+ -+#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -+#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __ac97_transmit_request() __aic_transmit_request() -+#define __ac97_receive_request() __aic_receive_request() -+#define __ac97_transmit_underrun() __aic_transmit_underrun() -+#define __ac97_receive_overrun() __aic_receive_overrun() -+ -+#define __ac97_clear_errors() __aic_clear_errors() -+ -+#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -+#define __ac97_get_receive_count() __aic_get_receive_count() -+ -+#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -+#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -+#define __ac97_read_rfifo() __aic_read_rfifo() -+ -+// -+// Define next ops for I2S compatible -+// -+ -+#define I2S_ACSR AIC_I2SSR -+ -+#define __i2s_enable() __aic_enable(); __aic_select_i2s() -+#define __i2s_disable() __aic_disable() -+#define __i2s_reset() __aic_reset() -+ -+#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -+#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -+ -+#define __i2s_enable_record() __aic_enable_record() -+#define __i2s_disable_record() __aic_disable_record() -+#define __i2s_enable_replay() __aic_enable_replay() -+#define __i2s_disable_replay() __aic_disable_replay() -+#define __i2s_enable_loopback() __aic_enable_loopback() -+#define __i2s_disable_loopback() __aic_disable_loopback() -+ -+#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -+#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -+#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -+#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -+ -+#define __i2s_transmit_request() __aic_transmit_request() -+#define __i2s_receive_request() __aic_receive_request() -+#define __i2s_transmit_underrun() __aic_transmit_underrun() -+#define __i2s_receive_overrun() __aic_receive_overrun() -+ -+#define __i2s_clear_errors() __aic_clear_errors() -+ -+#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -+#define __i2s_get_receive_count() __aic_get_receive_count() -+ -+#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -+#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -+#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -+#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -+ -+#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -+#define __i2s_read_rfifo() __aic_read_rfifo() -+ -+#define __i2s_reset_codec() \ -+ do { \ -+ } while (0) -+ -+/************************************************************************* -+ * PCM Controller operation -+ *************************************************************************/ -+ -+#define __pcm_enable() ( REG_PCM_CTL |= PCM_CTL_PCMEN ) -+#define __pcm_disable() ( REG_PCM_CTL &= ~PCM_CTL_PCMEN ) -+ -+#define __pcm_clk_enable() ( REG_PCM_CTL |= PCM_CTL_CLKEN ) -+#define __pcm_clk_disable() ( REG_PCM_CTL &= ~PCM_CTL_CLKEN ) -+ -+#define __pcm_reset() ( REG_PCM_CTL |= PCM_CTL_RST ) -+#define __pcm_flush_fifo() ( REG_PCM_CTL |= PCM_CTL_FLUSH ) -+ -+#define __pcm_enable_record() ( REG_PCM_CTL |= PCM_CTL_EREC ) -+#define __pcm_disable_record() ( REG_PCM_CTL &= ~PCM_CTL_EREC ) -+#define __pcm_enable_playback() ( REG_PCM_CTL |= PCM_CTL_ERPL ) -+#define __pcm_disable_playback() ( REG_PCM_CTL &= ~PCM_CTL_ERPL ) -+ -+#define __pcm_enable_rxfifo() __pcm_enable_record() -+#define __pcm_disable_rxfifo() __pcm_disable_record() -+#define __pcm_enable_txfifo() __pcm_enable_playback() -+#define __pcm_disable_txfifo() __pcm_disable_playback() -+ -+#define __pcm_last_sample() ( REG_PCM_CTL |= PCM_CTL_LSMP ) -+#define __pcm_zero_sample() ( REG_PCM_CTL &= ~PCM_CTL_LSMP ) -+ -+#define __pcm_enable_transmit_dma() ( REG_PCM_CTL |= PCM_CTL_ETDMA ) -+#define __pcm_disable_transmit_dma() ( REG_PCM_CTL &= ~PCM_CTL_ETDMA ) -+#define __pcm_enable_receive_dma() ( REG_PCM_CTL |= PCM_CTL_ERDMA ) -+#define __pcm_disable_receive_dma() ( REG_PCM_CTL &= ~PCM_CTL_ERDMA ) -+ -+#define __pcm_as_master() ( REG_PCM_CFG &= PCM_CFG_MODE ) -+#define __pcm_as_slave() ( REG_PCM_CFG |= ~PCM_CFG_MODE ) -+ -+#define __pcm_set_transmit_trigger(n) \ -+do { \ -+ REG_PCM_CFG &= ~PCM_CFG_TFTH_MASK; \ -+ REG_PCM_CFG |= ((n) << PCM_CFG_TFTH_BIT); \ -+} while(0) -+ -+#define __pcm_set_receive_trigger(n) \ -+do { \ -+ REG_PCM_CFG &= ~PCM_CFG_RFTH_MASK; \ -+ REG_PCM_CFG |= ((n) << PCM_CFG_RFTH_BIT); \ -+} while(0) -+ -+#define __pcm_omsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_OMSBPOS ) -+#define __pcm_omsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_OMSBPOS ) -+ -+#define __pcm_imsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_IMSBPOS ) -+#define __pcm_imsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_IMSBPOS ) -+ -+/* set input sample size 8 or 16*/ -+#define __pcm_set_iss(n) \ -+( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_ISS_MASK) | PCM_CFG_ISS_##n ) -+/* set output sample size 8 or 16*/ -+#define __pcm_set_oss(n) \ -+( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_OSS_MASK) | PCM_CFG_OSS_##n ) -+ -+#define __pcm_set_valid_slot(n) \ -+( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_SLOT_MASK) | PCM_CFG_SLOT_##n ) -+ -+#define __pcm_write_data(v) ( REG_PCM_DP = (v) ) -+#define __pcm_read_data() ( REG_PCM_DP ) -+ -+#define __pcm_enable_tfs_intr() ( REG_PCM_INTC |= PCM_INTC_ETFS ) -+#define __pcm_disable_tfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETFS ) -+ -+#define __pcm_enable_tur_intr() ( REG_PCM_INTC |= PCM_INTC_ETUR ) -+#define __pcm_disable_tur_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETUR ) -+ -+#define __pcm_enable_rfs_intr() ( REG_PCM_INTC |= PCM_INTC_ERFS ) -+#define __pcm_disable_rfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ERFS ) -+ -+#define __pcm_enable_ror_intr() ( REG_PCM_INTC |= PCM_INTC_EROR ) -+#define __pcm_disable_ror_intr() ( REG_PCM_INTC &= ~PCM_INTC_EROR ) -+ -+#define __pcm_ints_valid_tx() \ -+( ((REG_PCM_INTS & PCM_INTS_TFL_MASK) >> PCM_INTS_TFL_BIT) ) -+#define __pcm_ints_valid_rx() \ -+( ((REG_PCM_INTS & PCM_INTS_RFL_MASK) >> PCM_INTS_RFL_BIT) ) -+ -+#define __pcm_set_clk_div(n) \ -+( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_CLKDIV_MASK) | ((n) << PCM_DIV_CLKDIV_BIT) ) -+ -+/* sysclk(cpm_pcm_sysclk) Hz is created by cpm logic, and pcmclk Hz is the pcm in/out clock wanted */ -+#define __pcm_set_clk_rate(sysclk, pcmclk) \ -+__pcm_set_clk_div(((sysclk) / (pcmclk) - 1)) -+ -+#define __pcm_set_sync_div(n) \ -+( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNDIV_MASK) | ((n) << PCM_DIV_SYNDIV_BIT) ) -+ -+/* pcmclk is source clock Hz, and sync is the frame sync clock Hz wanted */ -+#define __pcm_set_sync_rate(pcmclk, sync) \ -+__pcm_set_sync_div(((pcmclk) / (8 * (sync)) - 1)) -+ -+ /* set sync length in pcmclk n = 0 ... 63 */ -+#define __pcm_set_sync_len(n) \ -+( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNL_MASK) | (n << PCM_DIV_SYNL_BIT) ) -+ -+ -+/*************************************************************************** -+ * ICDC -+ ***************************************************************************/ -+#define __i2s_internal_codec() __aic_internal_codec() -+#define __i2s_external_codec() __aic_external_codec() -+ -+#define __icdc_clk_ready() ( REG_ICDC_CKCFG & ICDC_CKCFG_CKRDY ) -+#define __icdc_sel_adc() ( REG_ICDC_CKCFG |= ICDC_CKCFG_SELAD ) -+#define __icdc_sel_dac() ( REG_ICDC_CKCFG &= ~ICDC_CKCFG_SELAD ) -+ -+#define __icdc_set_rgwr() ( REG_ICDC_RGADW |= ICDC_RGADW_RGWR ) -+#define __icdc_clear_rgwr() ( REG_ICDC_RGADW &= ~ICDC_RGADW_RGWR ) -+#define __icdc_rgwr_ready() ( REG_ICDC_RGADW & ICDC_RGADW_RGWR ) -+ -+#define __icdc_set_addr(n) \ -+do { \ -+ REG_ICDC_RGADW &= ~ICDC_RGADW_RGADDR_MASK; \ -+ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGADDR_BIT; \ -+} while(0) -+ -+#define __icdc_set_cmd(n) \ -+do { \ -+ REG_ICDC_RGADW &= ~ICDC_RGADW_RGDIN_MASK; \ -+ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGDIN_BIT; \ -+} while(0) -+ -+#define __icdc_irq_pending() ( REG_ICDC_RGDATA & ICDC_RGDATA_IRQ ) -+#define __icdc_get_value() ( REG_ICDC_RGDATA & ICDC_RGDATA_RGDOUT_MASK ) -+ -+/*************************************************************************** -+ * INTC -+ ***************************************************************************/ -+#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -+#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -+#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) /* A dummy ack, as the Pending Register is Read Only. Should we remove __intc_ack_irq() */ -+ -+ -+/*************************************************************************** -+ * I2C -+ ***************************************************************************/ -+ -+#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -+#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -+ -+#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -+#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -+#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -+#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -+ -+#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -+#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -+#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -+ -+#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -+#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -+#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -+ -+#define __i2c_set_clk(dev_clk, i2c_clk) \ -+ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -+ -+#define __i2c_read() ( REG_I2C_DR ) -+#define __i2c_write(val) ( REG_I2C_DR = (val) ) -+ -+ -+/*************************************************************************** -+ * MSC -+ ***************************************************************************/ -+/* n = 0, 1 (MSC0, MSC1) */ -+ -+#define __msc_start_op(n) \ -+ ( REG_MSC_STRPCL(n) = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -+ -+#define __msc_set_resto(n, to) ( REG_MSC_RESTO(n) = to ) -+#define __msc_set_rdto(n, to) ( REG_MSC_RDTO(n) = to ) -+#define __msc_set_cmd(n, cmd) ( REG_MSC_CMD(n) = cmd ) -+#define __msc_set_arg(n, arg) ( REG_MSC_ARG(n) = arg ) -+#define __msc_set_nob(n, nob) ( REG_MSC_NOB(n) = nob ) -+#define __msc_get_nob(n) ( REG_MSC_NOB(n) ) -+#define __msc_set_blklen(n, len) ( REG_MSC_BLKLEN(n) = len ) -+#define __msc_set_cmdat(n, cmdat) ( REG_MSC_CMDAT(n) = cmdat ) -+#define __msc_set_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_IO_ABORT ) -+#define __msc_clear_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_IO_ABORT ) -+ -+#define __msc_set_cmdat_bus_width1(n) \ -+do { \ -+ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_bus_width4(n) \ -+do { \ -+ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -+ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -+} while(0) -+ -+#define __msc_set_cmdat_dma_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DMA_EN ) -+#define __msc_set_cmdat_init(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_INIT ) -+#define __msc_set_cmdat_busy(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_BUSY ) -+#define __msc_set_cmdat_stream(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_block(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_STREAM_BLOCK ) -+#define __msc_set_cmdat_read(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_write(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_WRITE_READ ) -+#define __msc_set_cmdat_data_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DATA_EN ) -+ -+/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -+#define __msc_set_cmdat_res_format(n, r) \ -+do { \ -+ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -+ REG_MSC_CMDAT(n) |= (r); \ -+} while(0) -+ -+#define __msc_clear_cmdat(n) \ -+ REG_MSC_CMDAT(n) &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -+ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -+ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -+ -+#define __msc_get_imask(n) ( REG_MSC_IMASK(n) ) -+#define __msc_mask_all_intrs(n) ( REG_MSC_IMASK(n) = 0xff ) -+#define __msc_unmask_all_intrs(n) ( REG_MSC_IMASK(n) = 0x00 ) -+#define __msc_mask_rd(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_unmask_rd(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_RXFIFO_RD_REQ ) -+#define __msc_mask_wr(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_unmask_wr(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_TXFIFO_WR_REQ ) -+#define __msc_mask_endcmdres(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_END_CMD_RES ) -+#define __msc_unmask_endcmdres(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_END_CMD_RES ) -+#define __msc_mask_datatrandone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_unmask_datatrandone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_DATA_TRAN_DONE ) -+#define __msc_mask_prgdone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_PRG_DONE ) -+#define __msc_unmask_prgdone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_PRG_DONE ) -+ -+/* m=0,1,2,3,4,5,6,7 */ -+#define __msc_set_clkrt(n, m) \ -+do { \ -+ REG_MSC_CLKRT(n) = m; \ -+} while(0) -+ -+#define __msc_get_ireg(n) ( REG_MSC_IREG(n) ) -+#define __msc_ireg_rd(n) ( REG_MSC_IREG(n) & MSC_IREG_RXFIFO_RD_REQ ) -+#define __msc_ireg_wr(n) ( REG_MSC_IREG(n) & MSC_IREG_TXFIFO_WR_REQ ) -+#define __msc_ireg_end_cmd_res(n) ( REG_MSC_IREG(n) & MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_data_tran_done(n) ( REG_MSC_IREG(n) & MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_prg_done(n) ( REG_MSC_IREG(n) & MSC_IREG_PRG_DONE ) -+#define __msc_ireg_clear_end_cmd_res(n) ( REG_MSC_IREG(n) = MSC_IREG_END_CMD_RES ) -+#define __msc_ireg_clear_data_tran_done(n) ( REG_MSC_IREG(n) = MSC_IREG_DATA_TRAN_DONE ) -+#define __msc_ireg_clear_prg_done(n) ( REG_MSC_IREG(n) = MSC_IREG_PRG_DONE ) -+ -+#define __msc_get_stat(n) ( REG_MSC_STAT(n) ) -+#define __msc_stat_not_end_cmd_res(n) ( (REG_MSC_STAT(n) & MSC_STAT_END_CMD_RES) == 0) -+#define __msc_stat_crc_err(n) \ -+ ( REG_MSC_STAT(n) & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -+#define __msc_stat_res_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_RES_ERR ) -+#define __msc_stat_rd_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_READ_ERROR ) -+#define __msc_stat_wr_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_WRITE_ERROR_YES ) -+#define __msc_stat_resto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_RES ) -+#define __msc_stat_rdto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_READ ) -+ -+#define __msc_rd_resfifo(n) ( REG_MSC_RES(n) ) -+#define __msc_rd_rxfifo(n) ( REG_MSC_RXFIFO(n) ) -+#define __msc_wr_txfifo(n, v) ( REG_MSC_TXFIFO(n) = v ) -+ -+#define __msc_reset(n) \ -+do { \ -+ REG_MSC_STRPCL(n) = MSC_STRPCL_RESET; \ -+ while (REG_MSC_STAT(n) & MSC_STAT_IS_RESETTING); \ -+} while (0) -+ -+#define __msc_start_clk(n) \ -+do { \ -+ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_START; \ -+} while (0) -+ -+#define __msc_stop_clk(n) \ -+do { \ -+ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -+} while (0) -+ -+#define MMC_CLK 19169200 -+#define SD_CLK 24576000 -+ -+/* msc_clk should little than pclk and little than clk retrieve from card */ -+#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -+do { \ -+ unsigned int rate, pclk, i; \ -+ pclk = dev_clk; \ -+ rate = type?SD_CLK:MMC_CLK; \ -+ if (msc_clk && msc_clk < pclk) \ -+ pclk = msc_clk; \ -+ i = 0; \ -+ while (pclk < rate) \ -+ { \ -+ i ++; \ -+ rate >>= 1; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+/* divide rate to little than or equal to 400kHz */ -+#define __msc_calc_slow_clk_divisor(type, lv) \ -+do { \ -+ unsigned int rate, i; \ -+ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -+ i = 0; \ -+ while (rate > 0) \ -+ { \ -+ rate >>= 1; \ -+ i ++; \ -+ } \ -+ lv = i; \ -+} while(0) -+ -+ -+/*************************************************************************** -+ * SSI (Synchronous Serial Interface) -+ ***************************************************************************/ -+/* n = 0, 1 (SSI0, SSI1) */ -+#define __ssi_enable(n) ( REG_SSI_CR0(n) |= SSI_CR0_SSIE ) -+#define __ssi_disable(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_SSIE ) -+#define __ssi_select_ce(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_FSEL ) -+ -+#define __ssi_normal_mode(n) ( REG_SSI_ITR(n) &= ~SSI_ITR_IVLTM_MASK ) -+ -+#define __ssi_select_ce2(n) \ -+do { \ -+ REG_SSI_CR0(n) |= SSI_CR0_FSEL; \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_select_gpc(n) \ -+do { \ -+ REG_SSI_CR0(n) &= ~SSI_CR0_FSEL; \ -+ REG_SSI_CR1(n) |= SSI_CR1_MULTS; \ -+} while (0) -+ -+#define __ssi_underrun_auto_clear(n) \ -+do { \ -+ REG_SSI_CR0(n) |= SSI_CR0_EACLRUN; \ -+} while (0) -+ -+#define __ssi_underrun_clear_manually(n) \ -+do { \ -+ REG_SSI_CR0(n) &= ~SSI_CR0_EACLRUN; \ -+} while (0) -+ -+#define __ssi_enable_tx_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TIE | SSI_CR0_TEIE ) -+ -+#define __ssi_disable_tx_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -+ -+#define __ssi_enable_rx_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_RIE | SSI_CR0_REIE ) -+ -+#define __ssi_disable_rx_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -+ -+#define __ssi_enable_txfifo_half_empty_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TIE ) -+#define __ssi_disable_txfifo_half_empty_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_TIE ) -+#define __ssi_enable_tx_error_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TEIE ) -+#define __ssi_disable_tx_error_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_TEIE ) -+#define __ssi_enable_rxfifo_half_full_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_RIE ) -+#define __ssi_disable_rxfifo_half_full_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_RIE ) -+#define __ssi_enable_rx_error_intr(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_REIE ) -+#define __ssi_disable_rx_error_intr(n) \ -+ ( REG_SSI_CR0(n) &= ~SSI_CR0_REIE ) -+ -+#define __ssi_enable_loopback(n) ( REG_SSI_CR0(n) |= SSI_CR0_LOOP ) -+#define __ssi_disable_loopback(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_LOOP ) -+ -+#define __ssi_enable_receive(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_DISREV ) -+#define __ssi_disable_receive(n) ( REG_SSI_CR0(n) |= SSI_CR0_DISREV ) -+ -+#define __ssi_finish_receive(n) \ -+ ( REG_SSI_CR0(n) |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_disable_recvfinish(n) \ -+ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -+ -+#define __ssi_flush_txfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH ) -+#define __ssi_flush_rxfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_RFLUSH ) -+ -+#define __ssi_flush_fifo(n) \ -+ ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -+ -+#define __ssi_finish_transmit(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_UNFIN ) -+#define __ssi_wait_transmit(n) ( REG_SSI_CR1(n) |= SSI_CR1_UNFIN ) -+#define __ssi_use_busy_wait_mode(n) __ssi_wait_transmit(n) -+#define __ssi_unset_busy_wait_mode(n) __ssi_finish_transmit(n) -+ -+#define __ssi_spi_format(n) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SPI; \ -+ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -+ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -+ } while (0) -+ -+/* TI's SSP format, must clear SSI_CR1.UNFIN */ -+#define __ssi_ssp_format(n) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -+ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SSP; \ -+ } while (0) -+ -+/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -+#define __ssi_microwire_format(n) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -+ REG_SSI_CR1(n) |= SSI_CR1_FMAT_MW1; \ -+ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -+ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -+ REG_SSI_CR0(n) &= ~SSI_CR0_RFINE; \ -+ } while (0) -+ -+/* CE# level (FRMHL), CE# in interval time (ITFRM), -+ clock phase and polarity (PHA POL), -+ interval time (SSIITR), interval characters/frame (SSIICR) */ -+ -+/* frmhl,endian,mcom,flen,pha,pol MASK */ -+#define SSICR1_MISC_MASK \ -+ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -+ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) -+ -+#define __ssi_spi_set_misc(n,frmhl,endian,flen,mcom,pha,pol) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSICR1_MISC_MASK; \ -+ REG_SSI_CR1(n) |= ((frmhl) << 30) | ((endian) << 25) | \ -+ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -+ ((pha) << 1) | (pol); \ -+ } while(0) -+ -+/* Transfer with MSB or LSB first */ -+#define __ssi_set_msb(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_LFST ) -+#define __ssi_set_lsb(n) ( REG_SSI_CR1(n) |= SSI_CR1_LFST ) -+ -+#define __ssi_set_frame_length(n, m) \ -+ REG_SSI_CR1(n) = (REG_SSI_CR1(n) & ~SSI_CR1_FLEN_MASK) | (((m) - 2) << 4) -+ -+/* m = 1 - 16 */ -+#define __ssi_set_microwire_command_length(n,m) \ -+ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##m##BIT) ) -+ -+/* Set the clock phase for SPI */ -+#define __ssi_set_spi_clock_phase(n, m) \ -+ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_PHA) | (((m)&0x1)<< 1))) -+ -+/* Set the clock polarity for SPI */ -+#define __ssi_set_spi_clock_polarity(n, p) \ -+ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_POL) | ((p)&0x1)) ) -+ -+/* SSI tx trigger, m = i x 8 */ -+#define __ssi_set_tx_trigger(n, m) \ -+ do { \ -+ REG_SSI_CR1(n) &= ~SSI_CR1_TTRG_MASK; \ -+ REG_SSI_CR1(n) |= ((m)/8)<> SSI_SR_TFIFONUM_BIT ) -+ -+#define __ssi_get_rxfifo_count(n) \ -+ ( (REG_SSI_SR(n) & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -+ -+#define __ssi_transfer_end(n) ( REG_SSI_SR(n) & SSI_SR_END ) -+#define __ssi_is_busy(n) ( REG_SSI_SR(n) & SSI_SR_BUSY ) -+ -+#define __ssi_txfifo_full(n) ( REG_SSI_SR(n) & SSI_SR_TFF ) -+#define __ssi_rxfifo_empty(n) ( REG_SSI_SR(n) & SSI_SR_RFE ) -+#define __ssi_rxfifo_half_full(n) ( REG_SSI_SR(n) & SSI_SR_RFHF ) -+#define __ssi_txfifo_half_empty(n) ( REG_SSI_SR(n) & SSI_SR_TFHE ) -+#define __ssi_underrun(n) ( REG_SSI_SR(n) & SSI_SR_UNDR ) -+#define __ssi_overrun(n) ( REG_SSI_SR(n) & SSI_SR_OVER ) -+#define __ssi_clear_underrun(n) ( REG_SSI_SR(n) = ~SSI_SR_UNDR ) -+#define __ssi_clear_overrun(n) ( REG_SSI_SR(n) = ~SSI_SR_OVER ) -+#define __ssi_clear_errors(n) ( REG_SSI_SR(n) &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -+ -+#define __ssi_set_clk(n, dev_clk, ssi_clk) \ -+ ( REG_SSI_GR(n) = (dev_clk) / (2*(ssi_clk)) - 1 ) -+ -+#define __ssi_receive_data(n) REG_SSI_DR(n) -+#define __ssi_transmit_data(n, v) (REG_SSI_DR(n) = (v)) -+ -+ -+/*************************************************************************** -+ * CIM -+ ***************************************************************************/ -+ -+#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -+#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -+ -+/* n = 0, 1, 2, 3 */ -+#define __cim_set_input_data_stream_order(n) \ -+ do { \ -+ REG_CIM_CFG &= CIM_CFG_ORDER_MASK; \ -+ REG_CIM_CFG |= ((n)<>CIM_SIZE_LPF_BIT) -+#define __cim_get_pixel() ((REG_CIM_SIZE&CIM_SIZE_PPL_MASK)>>CIM_SIZE_PPL_BIT) -+ -+#define __cim_set_v_offset(a) ( REG_CIM_OFFSET = (REG_CIM_OFFSET&(~CIM_OFFSET_V_MASK)) | ((a)<>CIM_OFFSET_V_BIT) -+#define __cim_get_h_offset() ((REG_CIM_OFFSET&CIM_OFFSET_H_MASK)>>CIM_OFFSET_H_BIT) -+ -+/************************************************************************* -+ * SLCD (Smart LCD Controller) -+ *************************************************************************/ -+#define __slcd_set_data_18bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_18BIT ) -+#define __slcd_set_data_16bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_16BIT ) -+#define __slcd_set_data_8bit_x3() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x3 ) -+#define __slcd_set_data_8bit_x2() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x2 ) -+#define __slcd_set_data_8bit_x1() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x1 ) -+#define __slcd_set_data_24bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_24BIT ) -+#define __slcd_set_data_9bit_x2() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_9BIT_x2 ) -+ -+#define __slcd_set_cmd_16bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_16BIT ) -+#define __slcd_set_cmd_8bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_8BIT ) -+#define __slcd_set_cmd_18bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_18BIT ) -+#define __slcd_set_cmd_24bit() \ -+ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_24BIT ) -+ -+#define __slcd_set_cs_high() ( REG_SLCD_CFG |= SLCD_CFG_CS_ACTIVE_HIGH ) -+#define __slcd_set_cs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_CS_ACTIVE_HIGH ) -+ -+#define __slcd_set_rs_high() ( REG_SLCD_CFG |= SLCD_CFG_RS_CMD_HIGH ) -+#define __slcd_set_rs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_RS_CMD_HIGH ) -+ -+#define __slcd_set_clk_falling() ( REG_SLCD_CFG &= ~SLCD_CFG_CLK_ACTIVE_RISING ) -+#define __slcd_set_clk_rising() ( REG_SLCD_CFG |= SLCD_CFG_CLK_ACTIVE_RISING ) -+ -+#define __slcd_set_parallel_type() ( REG_SLCD_CFG &= ~SLCD_CFG_TYPE_SERIAL ) -+#define __slcd_set_serial_type() ( REG_SLCD_CFG |= SLCD_CFG_TYPE_SERIAL ) -+ -+/* SLCD Control Register */ -+#define __slcd_enable_dma() ( REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN ) -+#define __slcd_disable_dma() ( REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN ) -+ -+/* SLCD Status Register */ -+#define __slcd_is_busy() ( REG_SLCD_STATE & SLCD_STATE_BUSY ) -+ -+/* SLCD Data Register */ -+#define __slcd_set_cmd_rs() ( REG_SLCD_DATA |= SLCD_DATA_RS_COMMAND) -+#define __slcd_set_data_rs() ( REG_SLCD_DATA &= ~SLCD_DATA_RS_COMMAND) -+ -+ -+/*************************************************************************** -+ * LCD -+ ***************************************************************************/ -+ -+/*************************************************************************** -+ * LCD -+ ***************************************************************************/ -+#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= ( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -+#define __lcd_as_general_lcd() ( REG_LCD_CFG &= ~( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -+ -+#define __lcd_enable_tvepeh() ( REG_LCD_CFG |= LCD_CFG_TVEPEH ) -+#define __lcd_disable_tvepeh() ( REG_LCD_CFG &= ~LCD_CFG_TVEPEH ) -+ -+#define __lcd_enable_fuhold() ( REG_LCD_CFG |= LCD_CFG_FUHOLD ) -+#define __lcd_disable_fuhold() ( REG_LCD_CFG &= ~LCD_CFG_FUHOLD ) -+ -+#define __lcd_des_8word() ( REG_LCD_CFG |= LCD_CFG_NEWDES ) -+#define __lcd_des_4word() ( REG_LCD_CFG &= ~LCD_CFG_NEWDES ) -+ -+#define __lcd_enable_bypass_pal() ( REG_LCD_CFG |= LCD_CFG_PALBP ) -+#define __lcd_disable_bypass_pal() ( REG_LCD_CFG &= ~LCD_CFG_PALBP ) -+ -+#define __lcd_set_lcdpnl_term() ( REG_LCD_CFG |= LCD_CFG_TVEN ) -+#define __lcd_set_tv_term() ( REG_LCD_CFG &= ~LCD_CFG_TVEN ) -+ -+#define __lcd_enable_auto_recover() ( REG_LCD_CFG |= LCD_CFG_RECOVER ) -+#define __lcd_disable_auto_recover() ( REG_LCD_CFG &= ~LCD_CFG_RECOVER ) -+ -+#define __lcd_enable_dither() ( REG_LCD_CFG |= LCD_CFG_DITHER ) -+#define __lcd_disable_dither() ( REG_LCD_CFG &= ~LCD_CFG_DITHER ) -+ -+#define __lcd_disable_ps_mode() ( REG_LCD_CFG |= LCD_CFG_PSM ) -+#define __lcd_enable_ps_mode() ( REG_LCD_CFG &= ~LCD_CFG_PSM ) -+ -+#define __lcd_disable_cls_mode() ( REG_LCD_CFG |= LCD_CFG_CLSM ) -+#define __lcd_enable_cls_mode() ( REG_LCD_CFG &= ~LCD_CFG_CLSM ) -+ -+#define __lcd_disable_spl_mode() ( REG_LCD_CFG |= LCD_CFG_SPLM ) -+#define __lcd_enable_spl_mode() ( REG_LCD_CFG &= ~LCD_CFG_SPLM ) -+ -+#define __lcd_disable_rev_mode() ( REG_LCD_CFG |= LCD_CFG_REVM ) -+#define __lcd_enable_rev_mode() ( REG_LCD_CFG &= ~LCD_CFG_REVM ) -+ -+#define __lcd_disable_hsync_mode() ( REG_LCD_CFG |= LCD_CFG_HSYNM ) -+#define __lcd_enable_hsync_mode() ( REG_LCD_CFG &= ~LCD_CFG_HSYNM ) -+ -+#define __lcd_disable_pclk_mode() ( REG_LCD_CFG |= LCD_CFG_PCLKM ) -+#define __lcd_enable_pclk_mode() ( REG_LCD_CFG &= ~LCD_CFG_PCLKM ) -+ -+#define __lcd_normal_outdata() ( REG_LCD_CFG &= ~LCD_CFG_INVDAT ) -+#define __lcd_inverse_outdata() ( REG_LCD_CFG |= LCD_CFG_INVDAT ) -+ -+#define __lcd_sync_input() ( REG_LCD_CFG |= LCD_CFG_SYNDIR_IN ) -+#define __lcd_sync_output() ( REG_LCD_CFG &= ~LCD_CFG_SYNDIR_IN ) -+ -+#define __lcd_hsync_active_high() ( REG_LCD_CFG &= ~LCD_CFG_HSP ) -+#define __lcd_hsync_active_low() ( REG_LCD_CFG |= LCD_CFG_HSP ) -+ -+#define __lcd_pclk_rising() ( REG_LCD_CFG &= ~LCD_CFG_PCP ) -+#define __lcd_pclk_falling() ( REG_LCD_CFG |= LCD_CFG_PCP ) -+ -+#define __lcd_de_active_high() ( REG_LCD_CFG &= ~LCD_CFG_DEP ) -+#define __lcd_de_active_low() ( REG_LCD_CFG |= LCD_CFG_DEP ) -+ -+#define __lcd_vsync_rising() ( REG_LCD_CFG &= ~LCD_CFG_VSP ) -+#define __lcd_vsync_falling() ( REG_LCD_CFG |= LCD_CFG_VSP ) -+ -+#define __lcd_set_16_tftpnl() \ -+ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_16BIT ) -+ -+#define __lcd_set_18_tftpnl() \ -+ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_18BIT ) -+ -+#define __lcd_set_24_tftpnl() ( REG_LCD_CFG |= LCD_CFG_MODE_TFT_24BIT ) -+ -+/* -+ * n=1,2,4,8 for single mono-STN -+ * n=4,8 for dual mono-STN -+ */ -+#define __lcd_set_panel_datawidth(n) \ -+do { \ -+ REG_LCD_CFG &= ~LCD_CFG_PDW_MASK; \ -+ REG_LCD_CFG |= LCD_CFG_PDW_n##; \ -+} while (0) -+ -+/* m = LCD_CFG_MODE_GENERUIC_TFT_xxx */ -+#define __lcd_set_panel_mode(m) \ -+do { \ -+ REG_LCD_CFG &= ~LCD_CFG_MODE_MASK; \ -+ REG_LCD_CFG |= (m); \ -+} while(0) -+ -+/* n=4,8,16 */ -+#define __lcd_set_burst_length(n) \ -+do { \ -+ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \ -+ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \ -+} while (0) -+ -+#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 ) -+#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 ) -+ -+#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP ) -+#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP ) -+ -+/* n=2,4,16 */ -+#define __lcd_set_stn_frc(n) \ -+do { \ -+ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \ -+ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \ -+} while (0) -+ -+#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM ) -+#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM ) -+ -+#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM ) -+#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM ) -+ -+#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM ) -+#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM ) -+ -+#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 ) -+#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 ) -+ -+#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 ) -+#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 ) -+ -+#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM ) -+#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM ) -+ -+#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM ) -+#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM ) -+ -+#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN ) -+#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN ) -+ -+#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN ) -+#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN ) -+ -+#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS ) -+#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS ) -+ -+#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA ) -+#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA ) -+ -+/* n=1,2,4,8,16 */ -+#define __lcd_set_bpp(n) \ -+ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n ) -+ -+/* LCD status register indication */ -+ -+#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD ) -+#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD ) -+#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 ) -+#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 ) -+#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU ) -+#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF ) -+#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF ) -+ -+#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU ) -+#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF ) -+#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF ) -+ -+/* OSD functions */ -+#define __lcd_enable_osd() (REG_LCD_OSDC |= LCD_OSDC_OSDEN) -+#define __lcd_enable_f0() (REG_LCD_OSDC |= LCD_OSDC_F0EN) -+#define __lcd_enable_f1() (REG_LCD_OSDC |= LCD_OSDC_F1EN) -+#define __lcd_enable_alpha() (REG_LCD_OSDC |= LCD_OSDC_ALPHAEN) -+#define __lcd_enable_alphamd() (REG_LCD_OSDC |= LCD_OSDC_ALPHAMD) -+ -+#define __lcd_disable_osd() (REG_LCD_OSDC &= ~LCD_OSDC_OSDEN) -+#define __lcd_disable_f0() (REG_LCD_OSDC &= ~LCD_OSDC_F0EN) -+#define __lcd_disable_f1() (REG_LCD_OSDC &= ~LCD_OSDC_F1EN) -+#define __lcd_disable_alpha() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAEN) -+#define __lcd_disable_alphamd() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAMD) -+ -+/* OSD Controll Register */ -+#define __lcd_fg1_use_ipu() (REG_LCD_OSDCTRL |= LCD_OSDCTRL_IPU) -+#define __lcd_fg1_use_dma_chan1() (REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_IPU) -+#define __lcd_fg1_unuse_ipu() __lcd_fg1_use_dma_chan1() -+#define __lcd_osd_rgb555_mode() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_RGB555 ) -+#define __lcd_osd_rgb565_mode() ( REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_RGB555 ) -+#define __lcd_osd_change_size() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_CHANGES ) -+#define __lcd_osd_bpp_15_16() \ -+ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_15_16 ) -+#define __lcd_osd_bpp_18_24() \ -+ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_18_24 ) -+ -+/* OSD State Register */ -+#define __lcd_start_of_fg1() ( REG_LCD_STATE & LCD_OSDS_SOF1 ) -+#define __lcd_end_of_fg1() ( REG_LCD_STATE & LCD_OSDS_EOF1 ) -+#define __lcd_start_of_fg0() ( REG_LCD_STATE & LCD_OSDS_SOF0 ) -+#define __lcd_end_of_fg0() ( REG_LCD_STATE & LCD_OSDS_EOF0 ) -+#define __lcd_change_is_rdy() ( REG_LCD_STATE & LCD_OSDS_READY ) -+ -+/* Foreground Color Key Register 0,1(foreground 0, foreground 1) */ -+#define __lcd_enable_colorkey0() (REG_LCD_KEY0 |= LCD_KEY_KEYEN) -+#define __lcd_enable_colorkey1() (REG_LCD_KEY1 |= LCD_KEY_KEYEN) -+#define __lcd_enable_colorkey0_md() (REG_LCD_KEY0 |= LCD_KEY_KEYMD) -+#define __lcd_enable_colorkey1_md() (REG_LCD_KEY1 |= LCD_KEY_KEYMD) -+#define __lcd_set_colorkey0(key) (REG_LCD_KEY0 = (REG_LCD_KEY0&~0xFFFFFF)|(key)) -+#define __lcd_set_colorkey1(key) (REG_LCD_KEY1 = (REG_LCD_KEY1&~0xFFFFFF)|(key)) -+ -+#define __lcd_disable_colorkey0() (REG_LCD_KEY0 &= ~LCD_KEY_KEYEN) -+#define __lcd_disable_colorkey1() (REG_LCD_KEY1 &= ~LCD_KEY_KEYEN) -+#define __lcd_disable_colorkey0_md() (REG_LCD_KEY0 &= ~LCD_KEY_KEYMD) -+#define __lcd_disable_colorkey1_md() (REG_LCD_KEY1 &= ~LCD_KEY_KEYMD) -+ -+/* IPU Restart Register */ -+#define __lcd_enable_ipu_restart() (REG_LCD_IPUR |= LCD_IPUR_IPUREN) -+#define __lcd_disable_ipu_restart() (REG_LCD_IPUR &= ~LCD_IPUR_IPUREN) -+#define __lcd_set_ipu_restart_triger(n) (REG_LCD_IPUR = (REG_LCD_IPUR&(~0xFFFFFF))|(n)) -+ -+/* RGB Control Register */ -+#define __lcd_enable_rgb_dummy() (REG_LCD_RGBC |= LCD_RGBC_RGBDM) -+#define __lcd_disable_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_RGBDM) -+ -+#define __lcd_dummy_rgb() (REG_LCD_RGBC |= LCD_RGBC_DMM) -+#define __lcd_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_DMM) -+ -+#define __lcd_rgb2ycc() (REG_LCD_RGBC |= LCD_RGBC_YCC) -+#define __lcd_notrgb2ycc() (REG_LCD_RGBC &= ~LCD_RGBC_YCC) -+ -+#define __lcd_odd_mode_rgb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RGB ) -+#define __lcd_odd_mode_rbg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RBG ) -+#define __lcd_odd_mode_grb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GRB) -+ -+#define __lcd_odd_mode_gbr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GBR) -+#define __lcd_odd_mode_brg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BRG) -+#define __lcd_odd_mode_bgr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BGR) -+ -+#define __lcd_even_mode_rgb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RGB ) -+#define __lcd_even_mode_rbg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RBG ) -+#define __lcd_even_mode_grb() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GRB) -+ -+#define __lcd_even_mode_gbr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GBR) -+#define __lcd_even_mode_brg() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BRG) -+#define __lcd_even_mode_bgr() \ -+ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BGR) -+ -+/* Vertical Synchronize Register */ -+#define __lcd_vsync_get_vps() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT ) -+ -+#define __lcd_vsync_get_vpe() \ -+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -+#define __lcd_vsync_set_vpe(n) \ -+do { \ -+ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -+ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hps() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -+#define __lcd_hsync_set_hps(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -+} while (0) -+ -+#define __lcd_hsync_get_hpe() \ -+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -+#define __lcd_hsync_set_hpe(n) \ -+do { \ -+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_ht() \ -+ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -+#define __lcd_vat_set_ht(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -+} while (0) -+ -+#define __lcd_vat_get_vt() \ -+ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -+#define __lcd_vat_set_vt(n) \ -+do { \ -+ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -+ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hds() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -+#define __lcd_dah_set_hds(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -+} while (0) -+ -+#define __lcd_dah_get_hde() \ -+ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -+#define __lcd_dah_set_hde(n) \ -+do { \ -+ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -+ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vds() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -+#define __lcd_dav_set_vds(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -+} while (0) -+ -+#define __lcd_dav_get_vde() \ -+ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -+#define __lcd_dav_set_vde(n) \ -+do { \ -+ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -+ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -+} while (0) -+ -+/* DMA Command Register */ -+#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -+#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -+#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -+ -+#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -+#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -+#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -+ -+#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -+#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -+ -+#define __lcd_cmd0_get_len() \ -+ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+#define __lcd_cmd1_get_len() \ -+ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -+ -+/************************************************************************* -+ * TVE (TV Encoder Controller) ops -+ *************************************************************************/ -+/* TV Encoder Control register ops */ -+#define __tve_soft_reset() (REG_TVE_CTRL |= TVE_CTRL_SWRST) -+ -+#define __tve_output_colorbar() (REG_TVE_CTRL |= TVE_CTRL_CLBAR) -+#define __tve_output_video() (REG_TVE_CTRL &= ~TVE_CTRL_CLBAR) -+ -+#define __tve_input_cr_first() (REG_TVE_CTRL |= TVE_CTRL_CR1ST) -+#define __tve_input_cb_first() (REG_TVE_CTRL &= ~TVE_CTRL_CR1ST) -+ -+#define __tve_set_0_as_black() (REG_TVE_CTRL |= TVE_CTRL_ZBLACK) -+#define __tve_set_16_as_black() (REG_TVE_CTRL &= ~TVE_CTRL_ZBLACK) -+ -+#define __tve_ena_invert_top_bottom() (REG_TVE_CTRL |= TVE_CTRL_FINV) -+#define __tve_dis_invert_top_bottom() (REG_TVE_CTRL &= ~TVE_CTRL_FINV) -+ -+#define __tve_set_pal_mode() (REG_TVE_CTRL |= TVE_CTRL_PAL) -+#define __tve_set_ntsc_mode() (REG_TVE_CTRL &= ~TVE_CTRL_PAL) -+ -+#define __tve_set_pal_dura() (REG_TVE_CTRL |= TVE_CTRL_SYNCT) -+#define __tve_set_ntsc_dura() (REG_TVE_CTRL &= ~TVE_CTRL_SYNCT) -+ -+/* n = 0 ~ 3 */ -+#define __tve_set_c_bandwidth(n) \ -+do {\ -+ REG_TVE_CTRL &= ~TVE_CTRL_CBW_MASK;\ -+ REG_TVE_CTRL |= (n) << TVE_CTRL_CBW_BIT; \ -+}while(0) -+ -+/* n = 0 ~ 3 */ -+#define __tve_set_c_gain(n) \ -+do {\ -+ REG_TVE_CTRL &= ~TVE_CTRL_CGAIN_MASK;\ -+ (REG_TVE_CTRL |= (n) << TVE_CTRL_CGAIN_BIT; \ -+}while(0) -+ -+/* n = 0 ~ 7 */ -+#define __tve_set_yc_delay(n) \ -+do { \ -+ REG_TVE_CTRL &= ~TVE_CTRL_YCDLY_MASK \ -+ REG_TVE_CTRL |= ((n) << TVE_CTRL_YCDLY_BIT); \ -+} while(0) -+ -+#define __tve_disable_all_dacs() (REG_TVE_CTRL |= TVE_CTRL_DAPD) -+#define __tve_disable_dac1() (REG_TVE_CTRL |= TVE_CTRL_DAPD1) -+#define __tve_enable_dac1() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD1) -+#define __tve_disable_dac2() (REG_TVE_CTRL |= TVE_CTRL_DAPD2) -+#define __tve_enable_dac2() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD2) -+#define __tve_disable_dac3() (REG_TVE_CTRL |= TVE_CTRL_DAPD3) -+#define __tve_enable_dac3() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD3) -+ -+#define __tve_enable_svideo_fmt() (REG_TVE_CTRL |= TVE_CTRL_ECVBS) -+#define __tve_enable_cvbs_fmt() (REG_TVE_CTRL &= ~TVE_CTRL_ECVBS) -+ -+/* TV Encoder Frame Configure register ops */ -+/* n = 0 ~ 255 */ -+#define __tve_set_first_video_line(n) \ -+do {\ -+ REG_TVE_FRCFG &= ~TVE_FRCFG_L1ST_MASK;\ -+ REG_TVE_FRCFG |= (n) << TVE_FRCFG_L1ST_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_line_num_per_frm(n) \ -+do {\ -+ REG_TVE_FRCFG &= ~TVE_FRCFG_NLINE_MASK;\ -+ REG_TVE_CFG |= (n) << TVE_FRCFG_NLINE_BIT;\ -+} while(0) -+#define __tve_get_video_line_num()\ -+ (((REG_TVE_FRCFG & TVE_FRCFG_NLINE_MASK) >> TVE_FRCFG_NLINE_BIT) - 1 - 2 * ((REG_TVE_FRCFG & TVE_FRCFG_L1ST_MASK) >> TVE_FRCFG_L1ST_BIT)) -+ -+/* TV Encoder Signal Level Configure register ops */ -+/* n = 0 ~ 1023 */ -+#define __tve_set_white_level(n) \ -+do {\ -+ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_WHITEL_MASK;\ -+ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_WHITEL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_black_level(n) \ -+do {\ -+ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_BLACKL_MASK;\ -+ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_BLACKL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_blank_level(n) \ -+do {\ -+ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_BLANKL_MASK;\ -+ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_BLANKL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_vbi_blank_level(n) \ -+do {\ -+ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_VBLANKL_MASK;\ -+ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_VBLANKL_BIT;\ -+} while(0) -+/* n = 0 ~ 1023 */ -+#define __tve_set_sync_level(n) \ -+do {\ -+ REG_TVE_SLCFG3 &= ~TVE_SLCFG3_SYNCL_MASK;\ -+ REG_TVE_SLCFG3 |= (n) << TVE_SLCFG3_SYNCL_BIT;\ -+} while(0) -+ -+/* TV Encoder Signal Level Configure register ops */ -+/* n = 0 ~ 31 */ -+#define __tve_set_front_porch(n) \ -+do {\ -+ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_FRONTP_MASK;\ -+ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_FRONTP_BIT; \ -+} while(0) -+/* n = 0 ~ 127 */ -+#define __tve_set_hsync_width(n) \ -+do {\ -+ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_HSYNCW_MASK;\ -+ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_HSYNCW_BIT; \ -+} while(0) -+/* n = 0 ~ 127 */ -+#define __tve_set_back_porch(n) \ -+do {\ -+ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_BACKP_MASK;\ -+ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_BACKP_BIT; \ -+} while(0) -+/* n = 0 ~ 2047 */ -+#define __tve_set_active_linec(n) \ -+do {\ -+ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_ACTLIN_MASK;\ -+ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_ACTLIN_BIT; \ -+} while(0) -+/* n = 0 ~ 31 */ -+#define __tve_set_breezy_way(n) \ -+do {\ -+ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_PREBW_MASK;\ -+ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_PREBW_BIT; \ -+} while(0) -+ -+/* n = 0 ~ 127 */ -+#define __tve_set_burst_width(n) \ -+do {\ -+ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_BURSTW_MASK;\ -+ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_BURSTW_BIT; \ -+} while(0) -+ -+/* TV Encoder Chrominance filter and Modulation register ops */ -+/* n = 0 ~ (2^32-1) */ -+#define __tve_set_c_sub_carrier_freq(n) REG_TVE_CFREQ = (n) -+/* n = 0 ~ 255 */ -+#define __tve_set_c_sub_carrier_init_phase(n) \ -+do { \ -+ REG_TVE_CPHASE &= ~TVE_CPHASE_INITPH_MASK; \ -+ REG_TVE_CPHASE |= (n) << TVE_CPHASE_INITPH_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_c_sub_carrier_act_phase(n) \ -+do { \ -+ REG_TVE_CPHASE &= ~TVE_CPHASE_ACTPH_MASK; \ -+ REG_TVE_CPHASE |= (n) << TVE_CPHASE_ACTPH_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_c_phase_rst_period(n) \ -+do { \ -+ REG_TVE_CPHASE &= ~TVE_CPHASE_CCRSTP_MASK; \ -+ REG_TVE_CPHASE |= (n) << TVE_CPHASE_CCRSTP_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cb_burst_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBBA_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBBA_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cr_burst_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRBA_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRBA_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cb_gain_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBGAIN_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBGAIN_BIT; \ -+} while(0) -+/* n = 0 ~ 255 */ -+#define __tve_set_cr_gain_amp(n) \ -+do { \ -+ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRGAIN_MASK; \ -+ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRGAIN_BIT; \ -+} while(0) -+ -+/* TV Encoder Wide Screen Signal Control register ops */ -+/* n = 0 ~ 7 */ -+#define __tve_set_notch_freq(n) \ -+do { \ -+ REG_TVE_WSSCR &= ~TVE_WSSCR_NCHFREQ_MASK; \ -+ REG_TVE_WSSCR |= (n) << TVE_WSSCR_NCHFREQ_BIT; \ -+} while(0) -+/* n = 0 ~ 7 */ -+#define __tve_set_notch_width() (REG_TVE_WSSCR |= TVE_WSSCR_NCHW_BIT) -+#define __tve_clear_notch_width() (REG_TVE_WSSCR &= ~TVE_WSSCR_NCHW_BIT) -+#define __tve_enable_notch() (REG_TVE_WSSCR |= TVE_WSSCR_ENCH_BIT) -+#define __tve_disable_notch() (REG_TVE_WSSCR &= ~TVE_WSSCR_ENCH_BIT) -+/* n = 0 ~ 7 */ -+#define __tve_set_wss_edge(n) \ -+do { \ -+ REG_TVE_WSSCR &= ~TVE_WSSCR_WSSEDGE_MASK; \ -+ REG_TVE_WSSCR |= (n) << TVE_WSSCR_WSSEDGE_BIT; \ -+} while(0) -+#define __tve_set_wss_clkbyp() (REG_TVE_WSSCR |= TVE_WSSCR_WSSCKBP_BIT) -+#define __tve_set_wss_type() (REG_TVE_WSSCR |= TVE_WSSCR_WSSTP_BIT) -+#define __tve_enable_wssf1() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS1_BIT) -+#define __tve_enable_wssf0() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS0_BIT) -+ -+/* TV Encoder Wide Screen Signal Configure register 1, 2 and 3 ops */ -+/* n = 0 ~ 1023 */ -+#define __tve_set_wss_level(n) \ -+do { \ -+ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSL_MASK; \ -+ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSL_BIT; \ -+} while(0) -+/* n = 0 ~ 4095 */ -+#define __tve_set_wss_freq(n) \ -+do { \ -+ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSFREQ_MASK; \ -+ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSFREQ_BIT; \ -+} while(0) -+/* n = 0, 1; l = 0 ~ 255 */ -+#define __tve_set_wss_line(n,v) \ -+do { \ -+ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -+ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -+} while(0) -+/* n = 0, 1; d = 0 ~ (2^20-1) */ -+#define __tve_set_wss_data(n, v) \ -+do { \ -+ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -+ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -+} while(0) -+ -+/*************************************************************************** -+ * RTC ops -+ ***************************************************************************/ -+ -+#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) -+#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) -+#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) -+#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -+#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -+#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -+#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -+#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) -+#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) -+ -+#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) -+#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) -+#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) -+#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -+ -+#define __rtc_get_second() ( REG_RTC_RSR ) -+#define __rtc_set_second(v) ( REG_RTC_RSR = v ) -+ -+#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) -+#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) -+ -+#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) -+#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -+#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) -+#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) -+#define __rtc_set_adjc_val(v) \ -+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) -+#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) -+#define __rtc_set_nc1Hz_val(v) \ -+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) -+ -+#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) -+ -+#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) -+#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) -+#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) -+#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) -+ -+#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) -+#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) -+ -+#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) -+#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) -+#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) -+#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) -+#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) -+ -+#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) -+#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) -+ -+/************************************************************************* -+ * BCH -+ *************************************************************************/ -+#define __ecc_encoding_4bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BCHE; \ -+ REG_BCH_CRC = BCH_CR_BSEL8; \ -+} while(0) -+#define __ecc_decoding_4bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BCHE; \ -+ REG_BCH_CRC = BCH_CR_ENCE | BCH_CR_BSEL8; \ -+} while(0) -+#define __ecc_encoding_8bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -+} while(0) -+#define __ecc_decoding_8bit() \ -+do { \ -+ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -+ REG_BCH_CRC = BCH_CR_ENCE; \ -+} while(0) -+#define __ecc_dma_enable() ( REG_BCH_CRS = BCH_CR_DMAE ) -+#define __ecc_dma_disable() ( REG_BCH_CRC = BCH_CR_DMAE ) -+#define __ecc_disable() ( REG_BCH_CRC = BCH_CR_BCHE ) -+#define __ecc_encode_sync() while (!(REG_BCH_INTS & BCH_INTS_ENCF)) -+#define __ecc_decode_sync() while (!(REG_BCH_INTS & BCH_INTS_DECF)) -+#define __ecc_cnt_dec(n) \ -+do { \ -+ REG_BCH_CNT &= ~(BCH_CNT_DEC_MASK << BCH_CNT_DEC_BIT); \ -+ REG_BCH_CNT = (n) << BCH_CNT_DEC_BIT; \ -+} while(0) -+#define __ecc_cnt_enc(n) \ -+do { \ -+ REG_BCH_CNT &= ~(BCH_CNT_ENC_MASK << BCH_CNT_ENC_BIT); \ -+ REG_BCH_CNT = (n) << BCH_CNT_ENC_BIT; \ -+} while(0) -+ -+/*************************************************************************** -+ * OWI (one-wire bus) ops -+ ***************************************************************************/ -+ -+/* OW control register ops */ -+#define __owi_enable_all_interrupts() ( REG_OWI_CTL = (OWI_CTL_EBYTE | OWI_CTL_EBIT | OWI_CTL_ERST) ) -+#define __owi_disable_all_interrupts() ( REG_OWI_CTL = 0 ) -+ -+#define __owi_enable_byte_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBYTE ) -+#define __owi_disable_byte_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBYTE ) -+#define __owi_enable_bit_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBIT ) -+#define __owi_disable_bit_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBIT ) -+#define __owi_enable_rst_interrupt() ( REG_OWI_CTL |= OWI_CTL_ERST ) -+#define __owi_disable_rst_interrupt() ( REG_OWI_CTL &=~OWI_CTL_ERST ) -+ -+/* OW configure register ops */ -+#define __owi_select_regular_mode() ( REG_OWI_CFG &= ~OWI_CFG_MODE ) -+#define __owi_select_overdrive_mode() ( REG_OWI_CFG |= OWI_CFG_MODE ) -+ -+#define __owi_set_rddata() ( REG_OWI_CFG |= OWI_CFG_RDDATA ) -+#define __owi_clr_rddata() ( REG_OWI_CFG &= ~OWI_CFG_RDDATA ) -+#define __owi_get_rddata() ( REG_OWI_CFG & OWI_CFG_RDDATA ) -+ -+#define __owi_set_wrdata() ( REG_OWI_CFG |= OWI_CFG_WRDATA ) -+#define __owi_clr_wrdata() ( REG_OWI_CFG &= ~OWI_CFG_WRDATA ) -+#define __owi_get_wrdata() ( REG_OWI_CFG & OWI_CFG_WRDATA ) -+ -+#define __owi_get_rdst() ( REG_OWI_CFG & OWI_CFG_RDST ) -+ -+#define __owi_set_wr1rd() ( REG_OWI_CFG |= OWI_CFG_WR1RD ) -+#define __owi_clr_wr1rd() ( REG_OWI_CFG &= ~OWI_CFG_WR1RD ) -+#define __owi_get_wr1rd() ( REG_OWI_CFG & OWI_CFG_WR1RD ) -+ -+#define __owi_set_wr0() ( REG_OWI_CFG |= OWI_CFG_WR0 ) -+#define __owi_clr_wr0() ( REG_OWI_CFG &= ~OWI_CFG_WR0 ) -+#define __owi_get_wr0() ( REG_OWI_CFG & OWI_CFG_WR0 ) -+ -+#define __owi_set_rst() ( REG_OWI_CFG |= OWI_CFG_RST ) -+#define __owi_clr_rst() ( REG_OWI_CFG &= ~OWI_CFG_RST ) -+#define __owi_get_rst() ( REG_OWI_CFG & OWI_CFG_RST ) -+ -+#define __owi_enable_ow_ops() ( REG_OWI_CFG |= OWI_CFG_ENA ) -+#define __owi_disable_ow_ops() ( REG_OWI_CFG &= ~OWI_CFG_ENA ) -+#define __owi_get_enable() ( REG_OWI_CFG & OWI_CFG_ENA ) -+ -+#define __owi_wait_ops_rdy() \ -+ do { \ -+ while(__owi_get_enable()); \ -+ udelay(1); \ -+ } while(0); -+ -+/* OW status register ops */ -+#define __owi_clr_sts() ( REG_OWI_STS = 0 ) -+#define __owi_get_sts_pst() ( REG_OWI_STS & OWI_STS_PST ) -+#define __owi_get_sts_byte_rdy() ( REG_OWI_STS & OWI_STS_BYTE_RDY ) -+#define __owi_get_sts_bit_rdy() ( REG_OWI_STS & OWI_STS_BIT_RDY ) -+#define __owi_get_sts_pst_rdy() ( REG_OWI_STS & OWI_STS_PST_RDY ) -+ -+/************************************************************************* -+ * TSSI MPEG 2-TS slave interface operation -+ *************************************************************************/ -+#define __tssi_enable() ( REG_TSSI_ENA |= TSSI_ENA_ENA ) -+#define __tssi_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_ENA ) -+#define __tssi_soft_reset() ( REG_TSSI_ENA |= TSSI_ENA_SFT_RST ) -+#define __tssi_dma_enable() ( REG_TSSI_ENA |= TSSI_ENA_DMA_EN ) -+#define __tssi_dma_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_DMA_EN ) -+#define __tssi_filter_enable() ( REG_TSSI_ENA |= TSSI_ENA_PID_EN ) -+#define __tssi_filter_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_PID_EN ) -+ -+/* n = 4, 8, 16 */ -+#define __tssi_set_tigger_num(n) \ -+ do { \ -+ REG_TSSI_CFG &= ~TSSI_CFG_TRIG_MASK; \ -+ REG_TSSI_CFG |= TSSI_CFG_TRIG_##n; \ -+ } while (0) -+ -+#define __tssi_set_wd_1() ( REG_TSSI_CFG |= TSSI_CFG_END_WD ) -+#define __tssi_set_wd_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_WD ) -+ -+#define __tssi_set_bt_1() ( REG_TSSI_CFG |= TSSI_CFG_END_BD ) -+#define __tssi_set_bt_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_BD ) -+ -+#define __tssi_set_data_pola_high() ( REG_TSSI_CFG |= TSSI_CFG_TSDI_H ) -+#define __tssi_set_data_pola_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSDI_H ) -+ -+#define __tssi_set_data_use_data0() ( REG_TSSI_CFG |= TSSI_CFG_USE_0 ) -+#define __tssi_set_data_use_data7() ( REG_TSSI_CFG &= ~TSSI_CFG_USE_0 ) -+ -+#define __tssi_select_clk_fast() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_CH ) -+#define __tssi_select_clk_slow() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_CH ) -+ -+#define __tssi_select_serail_mode() ( REG_TSSI_CFG &= ~TSSI_CFG_PARAL ) -+#define __tssi_select_paral_mode() ( REG_TSSI_CFG |= TSSI_CFG_PARAL ) -+ -+#define __tssi_select_clk_nega_edge() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_P ) -+#define __tssi_select_clk_posi_edge() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_P ) -+ -+#define __tssi_select_frm_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFRM_H ) -+#define __tssi_select_frm_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFRM_H ) -+ -+#define __tssi_select_str_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSSTR_H ) -+#define __tssi_select_str_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSSTR_H ) -+ -+#define __tssi_select_fail_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFAIL_H ) -+#define __tssi_select_fail_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFAIL_H ) -+ -+#define __tssi_enable_ovrn_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_OVRNM ) -+#define __tssi_disable_ovrn_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_OVRNM ) -+ -+#define __tssi_enable_trig_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_TRIGM ) -+#define __tssi_disable_trig_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_TRIGM ) -+ -+#define __tssi_state_is_overrun() ( REG_TSSI_STAT & TSSI_STAT_OVRN ) -+#define __tssi_state_trigger_meet() ( REG_TSSI_STAT & TSSI_STAT_TRIG ) -+#define __tssi_clear_state() ( REG_TSSI_STAT = 0 ) /* write 0??? */ -+#define __tssi_state_clear_overrun() ( REG_TSSI_STAT = TSSI_STAT_OVRN ) -+ -+#define __tssi_enable_filte_pid0() ( REG_TSSI_PEN |= TSSI_PEN_PID0 ) -+#define __tssi_disable_filte_pid0() ( REG_TSSI_PEN &= ~TSSI_PEN_PID0 ) -+ -+/* m = 0, ..., 15 */ -+#define __tssi_enable_pid_filter(m) \ -+ do { \ -+ int n = (m); \ -+ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -+ if ( n >= TSSI_PID_MAX ) n += 8; \ -+ REG_TSSI_PEN |= ( 1 << n ); \ -+ } \ -+ } while (0) -+ -+/* m = 0, ..., 15 */ -+#define __tssi_disable_pid_filter(m) \ -+ do { \ -+ int n = (m); \ -+ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -+ if ( n >= TSSI_PID_MAX ) n += 8; \ -+ REG_TSSI_PEN &= ~( 1 << n ); \ -+ } \ -+ } while (0) -+ -+/* n = 0, ..., 7 */ -+#define __tssi_set_pid0(n, pid0) \ -+ do { \ -+ REG_TSSI_PID(n) &= ~TSSI_PID_PID0_MASK; \ -+ REG_TSSI_PID(n) |= ((pid0)<=0 && n < TSSI_PID_MAX*2) { \ -+ if ( n < TSSI_PID_MAX ) \ -+ __tssi_set_pid0(n, pid); \ -+ else \ -+ __tssi_set_pid1(n-TSSI_PID_MAX, pid); \ -+ } \ -+ }while (0) -+ -+ -+#if 0 -+/************************************************************************* -+ * IPU (Image Processing Unit) -+ *************************************************************************/ -+#define u32 volatile unsigned long -+ -+#define write_reg(reg, val) \ -+do { \ -+ *(u32 *)(reg) = (val); \ -+} while(0) -+ -+#define read_reg(reg, off) (*(u32 *)((reg)+(off))) -+ -+ -+#define set_ipu_fmt(rgb_888_out_fmt, rgb_out_oft, out_fmt, yuv_pkg_out, in_oft, in_fmt ) \ -+({ write_reg( (IPU_V_BASE + REG_D_FMT), ((in_fmt) & IN_FMT_MSK)< Unsigned toggle enable */ -+#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ -+#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ -+#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ -+#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ -+#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ -+#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ -+#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ -+#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ -+ -+/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -+ -+#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ -+#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -+ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ -+ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ -+ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ -+ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ -+ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ -+ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ -+#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ -+#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -+ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -+ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -+ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -+ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ -+ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ -+ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ -+ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ -+ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -+ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ -+ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ -+ -+/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -+ -+#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ -+#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ -+#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ -+#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ -+#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -+ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ -+#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -+ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -+ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -+ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -+ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -+#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ -+#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ -+#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ -+#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ -+ -+/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -+ -+#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ -+#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ -+#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -+ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -+ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -+ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -+ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -+ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -+#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ -+ -+/* AIC Controller FIFO Status Register (AIC_SR) */ -+ -+#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ -+#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) -+#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ -+#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) -+#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ -+#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ -+#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ -+#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ -+ -+/* AIC Controller AC-link Status Register (AIC_ACSR) */ -+ -+#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ -+#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ -+#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ -+#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ -+#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ -+#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ -+ -+/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -+ -+#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ -+ -+/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -+ -+#define AIC_ACCAR_CAR_BIT 0 -+#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -+ -+/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -+ -+#define AIC_ACCDR_CDR_BIT 0 -+#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -+ -+/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -+ -+#define AIC_ACSAR_SAR_BIT 0 -+#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -+ -+/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -+ -+#define AIC_ACSDR_SDR_BIT 0 -+#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -+ -+/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -+ -+#define AIC_I2SDIV_DIV_BIT 0 -+#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -+ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -+ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -+ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -+ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -+ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -+ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -+ -+ -+/************************************************************************* -+ * ICDC (Internal CODEC) -+ *************************************************************************/ -+ -+#define ICDC_CKCFG (ICDC_BASE + 0x00a0) /* Clock Configure Register */ -+#define ICDC_RGADW (ICDC_BASE + 0x00a4) /* internal register access control */ -+#define ICDC_RGDATA (ICDC_BASE + 0x00a8) /* internal register data output */ -+ -+#define REG_ICDC_CKCFG REG32(ICDC_CKCFG) -+#define REG_ICDC_RGADW REG32(ICDC_RGADW) -+#define REG_ICDC_RGDATA REG32(ICDC_RGDATA) -+ -+/* ICDC Clock Configure Register */ -+#define ICDC_CKCFG_CKRDY (1 << 1) -+#define ICDC_CKCFG_SELAD (1 << 0) -+ -+/* ICDC internal register access control Register */ -+#define ICDC_RGADW_RGWR (1 << 16) -+#define ICDC_RGADW_RGADDR_BIT 8 -+#define ICDC_RGADW_RGADDR_MASK (0x7f << ICDC_RGADW_RGADDR_BIT) -+#define ICDC_RGADW_RGDIN_BIT 0 -+#define ICDC_RGADW_RGDIN_MASK (0xff << ICDC_RGADW_RGDIN_BIT) -+ -+/* ICDC internal register data output Register */ -+#define ICDC_RGDATA_IRQ (1 << 8) -+#define ICDC_RGDATA_RGDOUT_BIT 0 -+#define ICDC_RGDATA_RGDOUT_MASK (0xff << ICDC_RGDATA_RGDOUT_BIT) -+ -+/************************************************************************* -+ * PCM Controller -+ *************************************************************************/ -+ -+#define PCM_CTL (PCM_BASE + 0x000) -+#define PCM_CFG (PCM_BASE + 0x004) -+#define PCM_DP (PCM_BASE + 0x008) -+#define PCM_INTC (PCM_BASE + 0x00c) -+#define PCM_INTS (PCM_BASE + 0x010) -+#define PCM_DIV (PCM_BASE + 0x014) -+ -+#define REG_PCM_CTL REG32(PCM_CTL) -+#define REG_PCM_CFG REG32(PCM_CFG) -+#define REG_PCM_DP REG32(PCM_DP) -+#define REG_PCM_INTC REG32(PCM_INTC) -+#define REG_PCM_INTS REG32(PCM_INTS) -+#define REG_PCM_DIV REG32(PCM_DIV) -+ -+/* PCM Controller control Register (PCM_CTL) */ -+ -+#define PCM_CTL_ERDMA (1 << 9) /* Enable Receive DMA */ -+#define PCM_CTL_ETDMA (1 << 8) /* Enable Transmit DMA */ -+#define PCM_CTL_LSMP (1 << 7) /* Play Zero sample or last sample */ -+#define PCM_CTL_ERPL (1 << 6) /* Enable Playing Back Function */ -+#define PCM_CTL_EREC (1 << 5) /* Enable Recording Function */ -+#define PCM_CTL_FLUSH (1 << 4) /* FIFO flush */ -+#define PCM_CTL_RST (1 << 3) /* Reset PCM */ -+#define PCM_CTL_CLKEN (1 << 1) /* Enable the clock division logic */ -+#define PCM_CTL_PCMEN (1 << 0) /* Enable PCM module */ -+ -+/* PCM Controller configure Register (PCM_CFG) */ -+ -+#define PCM_CFG_SLOT_BIT 13 -+#define PCM_CFG_SLOT_MASK (0x3 << PCM_CFG_SLOT_BIT) -+ #define PCM_CFG_SLOT_0 (0 << PCM_CFG_SLOT_BIT) /* Slot is 0 */ -+ #define PCM_CFG_SLOT_1 (1 << PCM_CFG_SLOT_BIT) /* Slot is 1 */ -+ #define PCM_CFG_SLOT_2 (2 << PCM_CFG_SLOT_BIT) /* Slot is 2 */ -+ #define PCM_CFG_SLOT_3 (3 << PCM_CFG_SLOT_BIT) /* Slot is 3 */ -+#define PCM_CFG_ISS_BIT 12 -+#define PCM_CFG_ISS_MASK (0x1 << PCM_CFG_ISS_BIT) -+ #define PCM_CFG_ISS_8 (0 << PCM_CFG_ISS_BIT) -+ #define PCM_CFG_ISS_16 (1 << PCM_CFG_ISS_BIT) -+#define PCM_CFG_OSS_BIT 11 -+#define PCM_CFG_OSS_MASK (0x1 << PCM_CFG_OSS_BIT) -+ #define PCM_CFG_OSS_8 (0 << PCM_CFG_OSS_BIT) -+ #define PCM_CFG_OSS_16 (1 << PCM_CFG_OSS_BIT) -+#define PCM_CFG_IMSBPOS (1 << 10) -+#define PCM_CFG_OMSBPOS (1 << 9) -+#define PCM_CFG_RFTH_BIT 5 /* Receive FIFO Threshold */ -+#define PCM_CFG_RFTH_MASK (0xf << PCM_CFG_RFTH_BIT) -+#define PCM_CFG_TFTH_BIT 1 /* Transmit FIFO Threshold */ -+#define PCM_CFG_TFTH_MASK (0xf << PCM_CFG_TFTH_BIT) -+#define PCM_CFG_MODE (0x0 << 0) -+ -+/* PCM Controller interrupt control Register (PCM_INTC) */ -+ -+#define PCM_INTC_ETFS (1 << 3) -+#define PCM_INTC_ETUR (1 << 2) -+#define PCM_INTC_ERFS (1 << 1) -+#define PCM_INTC_EROR (1 << 0) -+ -+/* PCM Controller interrupt status Register (PCM_INTS) */ -+ -+#define PCM_INTS_RSTS (1 << 14) /* Reset or flush has not complete */ -+#define PCM_INTS_TFL_BIT 9 -+#define PCM_INTS_TFL_MASK (0x1f << PCM_INTS_TFL_BIT) -+#define PCM_INTS_TFS (1 << 8) /* Tranmit FIFO Service Request */ -+#define PCM_INTS_TUR (1 << 7) /* Transmit FIFO Under Run */ -+#define PCM_INTS_RFL_BIT 2 -+#define PCM_INTS_RFL_MASK (0x1f << PCM_INTS_RFL_BIT) -+#define PCM_INTS_RFS (1 << 1) /* Receive FIFO Service Request */ -+#define PCM_INTS_ROR (1 << 0) /* Receive FIFO Over Run */ -+ -+/* PCM Controller clock division Register (PCM_DIV) */ -+#define PCM_DIV_SYNL_BIT 11 -+#define PCM_DIV_SYNL_MASK (0x3f << PCM_DIV_SYNL_BIT) -+#define PCM_DIV_SYNDIV_BIT 6 -+#define PCM_DIV_SYNDIV_MASK (0x1f << PCM_DIV_SYNDIV_BIT) -+#define PCM_DIV_CLKDIV_BIT 0 -+#define PCM_DIV_CLKDIV_MASK (0x3f << PCM_DIV_CLKDIV_BIT) -+ -+ -+/************************************************************************* -+ * I2C -+ *************************************************************************/ -+#define I2C_DR (I2C_BASE + 0x000) -+#define I2C_CR (I2C_BASE + 0x004) -+#define I2C_SR (I2C_BASE + 0x008) -+#define I2C_GR (I2C_BASE + 0x00C) -+ -+#define REG_I2C_DR REG8(I2C_DR) -+#define REG_I2C_CR REG8(I2C_CR) -+#define REG_I2C_SR REG8(I2C_SR) -+#define REG_I2C_GR REG16(I2C_GR) -+ -+/* I2C Control Register (I2C_CR) */ -+ -+#define I2C_CR_IEN (1 << 4) -+#define I2C_CR_STA (1 << 3) -+#define I2C_CR_STO (1 << 2) -+#define I2C_CR_AC (1 << 1) -+#define I2C_CR_I2CE (1 << 0) -+ -+/* I2C Status Register (I2C_SR) */ -+ -+#define I2C_SR_STX (1 << 4) -+#define I2C_SR_BUSY (1 << 3) -+#define I2C_SR_TEND (1 << 2) -+#define I2C_SR_DRF (1 << 1) -+#define I2C_SR_ACKF (1 << 0) -+ -+ -+/************************************************************************* -+ * SSI (Synchronous Serial Interface) -+ *************************************************************************/ -+/* n = 0, 1 (SSI0, SSI1) */ -+#define SSI_DR(n) (SSI_BASE + 0x000 + (n)*0x2000) -+#define SSI_CR0(n) (SSI_BASE + 0x004 + (n)*0x2000) -+#define SSI_CR1(n) (SSI_BASE + 0x008 + (n)*0x2000) -+#define SSI_SR(n) (SSI_BASE + 0x00C + (n)*0x2000) -+#define SSI_ITR(n) (SSI_BASE + 0x010 + (n)*0x2000) -+#define SSI_ICR(n) (SSI_BASE + 0x014 + (n)*0x2000) -+#define SSI_GR(n) (SSI_BASE + 0x018 + (n)*0x2000) -+ -+#define REG_SSI_DR(n) REG32(SSI_DR(n)) -+#define REG_SSI_CR0(n) REG16(SSI_CR0(n)) -+#define REG_SSI_CR1(n) REG32(SSI_CR1(n)) -+#define REG_SSI_SR(n) REG32(SSI_SR(n)) -+#define REG_SSI_ITR(n) REG16(SSI_ITR(n)) -+#define REG_SSI_ICR(n) REG8(SSI_ICR(n)) -+#define REG_SSI_GR(n) REG16(SSI_GR(n)) -+ -+/* SSI Data Register (SSI_DR) */ -+ -+#define SSI_DR_GPC_BIT 0 -+#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -+ -+#define SSI_MAX_FIFO_ENTRIES 128 /* 128 txfifo and 128 rxfifo */ -+ -+/* SSI Control Register 0 (SSI_CR0) */ -+ -+#define SSI_CR0_SSIE (1 << 15) -+#define SSI_CR0_TIE (1 << 14) -+#define SSI_CR0_RIE (1 << 13) -+#define SSI_CR0_TEIE (1 << 12) -+#define SSI_CR0_REIE (1 << 11) -+#define SSI_CR0_LOOP (1 << 10) -+#define SSI_CR0_RFINE (1 << 9) -+#define SSI_CR0_RFINC (1 << 8) -+#define SSI_CR0_EACLRUN (1 << 7) /* hardware auto clear underrun when TxFifo no empty */ -+#define SSI_CR0_FSEL (1 << 6) -+#define SSI_CR0_TFLUSH (1 << 2) -+#define SSI_CR0_RFLUSH (1 << 1) -+#define SSI_CR0_DISREV (1 << 0) -+ -+/* SSI Control Register 1 (SSI_CR1) */ -+ -+#define SSI_CR1_FRMHL_BIT 30 -+#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -+ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -+ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -+ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -+#define SSI_CR1_TFVCK_BIT 28 -+#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -+ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -+#define SSI_CR1_TCKFI_BIT 26 -+#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -+ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -+#define SSI_CR1_LFST (1 << 25) -+#define SSI_CR1_ITFRM (1 << 24) -+#define SSI_CR1_UNFIN (1 << 23) -+#define SSI_CR1_MULTS (1 << 22) -+#define SSI_CR1_FMAT_BIT 20 -+#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -+ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -+ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -+ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -+ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -+#define SSI_CR1_TTRG_BIT 16 /* SSI1 TX trigger */ -+#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) -+#define SSI_CR1_MCOM_BIT 12 -+#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -+ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -+ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -+ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -+ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -+ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -+ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -+ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -+ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -+ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -+ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -+ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -+ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -+ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -+ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -+ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -+ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -+#define SSI_CR1_RTRG_BIT 8 /* SSI RX trigger */ -+#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) -+#define SSI_CR1_FLEN_BIT 4 -+#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -+ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -+#define SSI_CR1_PHA (1 << 1) -+#define SSI_CR1_POL (1 << 0) -+ -+/* SSI Status Register (SSI_SR) */ -+ -+#define SSI_SR_TFIFONUM_BIT 16 -+#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) -+#define SSI_SR_RFIFONUM_BIT 8 -+#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) -+#define SSI_SR_END (1 << 7) -+#define SSI_SR_BUSY (1 << 6) -+#define SSI_SR_TFF (1 << 5) -+#define SSI_SR_RFE (1 << 4) -+#define SSI_SR_TFHE (1 << 3) -+#define SSI_SR_RFHF (1 << 2) -+#define SSI_SR_UNDR (1 << 1) -+#define SSI_SR_OVER (1 << 0) -+ -+/* SSI Interval Time Control Register (SSI_ITR) */ -+ -+#define SSI_ITR_CNTCLK (1 << 15) -+#define SSI_ITR_IVLTM_BIT 0 -+#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -+ -+ -+/************************************************************************* -+ * MSC -+ ************************************************************************/ -+/* n = 0, 1 (MSC0, MSC1) */ -+#define MSC_STRPCL(n) (MSC_BASE + (n)*0x1000 + 0x000) -+#define MSC_STAT(n) (MSC_BASE + (n)*0x1000 + 0x004) -+#define MSC_CLKRT(n) (MSC_BASE + (n)*0x1000 + 0x008) -+#define MSC_CMDAT(n) (MSC_BASE + (n)*0x1000 + 0x00C) -+#define MSC_RESTO(n) (MSC_BASE + (n)*0x1000 + 0x010) -+#define MSC_RDTO(n) (MSC_BASE + (n)*0x1000 + 0x014) -+#define MSC_BLKLEN(n) (MSC_BASE + (n)*0x1000 + 0x018) -+#define MSC_NOB(n) (MSC_BASE + (n)*0x1000 + 0x01C) -+#define MSC_SNOB(n) (MSC_BASE + (n)*0x1000 + 0x020) -+#define MSC_IMASK(n) (MSC_BASE + (n)*0x1000 + 0x024) -+#define MSC_IREG(n) (MSC_BASE + (n)*0x1000 + 0x028) -+#define MSC_CMD(n) (MSC_BASE + (n)*0x1000 + 0x02C) -+#define MSC_ARG(n) (MSC_BASE + (n)*0x1000 + 0x030) -+#define MSC_RES(n) (MSC_BASE + (n)*0x1000 + 0x034) -+#define MSC_RXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x038) -+#define MSC_TXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x03C) -+#define MSC_LPM(n) (MSC_BASE + (n)*0x1000 + 0x040) -+ -+#define REG_MSC_STRPCL(n) REG16(MSC_STRPCL(n)) -+#define REG_MSC_STAT(n) REG32(MSC_STAT(n)) -+#define REG_MSC_CLKRT(n) REG16(MSC_CLKRT(n)) -+#define REG_MSC_CMDAT(n) REG32(MSC_CMDAT(n)) -+#define REG_MSC_RESTO(n) REG16(MSC_RESTO(n)) -+#define REG_MSC_RDTO(n) REG16(MSC_RDTO(n)) -+#define REG_MSC_BLKLEN(n) REG16(MSC_BLKLEN(n)) -+#define REG_MSC_NOB(n) REG16(MSC_NOB(n)) -+#define REG_MSC_SNOB(n) REG16(MSC_SNOB(n)) -+#define REG_MSC_IMASK(n) REG32(MSC_IMASK(n)) -+#define REG_MSC_IREG(n) REG16(MSC_IREG(n)) -+#define REG_MSC_CMD(n) REG8(MSC_CMD(n)) -+#define REG_MSC_ARG(n) REG32(MSC_ARG(n)) -+#define REG_MSC_RES(n) REG16(MSC_RES(n)) -+#define REG_MSC_RXFIFO(n) REG32(MSC_RXFIFO(n)) -+#define REG_MSC_TXFIFO(n) REG32(MSC_TXFIFO(n)) -+#define REG_MSC_LPM(n) REG32(MSC_LPM(n)) -+ -+/* MSC Clock and Control Register (MSC_STRPCL) */ -+#define MSC_STRPCL_SEND_CCSD (1 << 15) /*send command completion signal disable to ceata */ -+#define MSC_STRPCL_SEND_AS_CCSD (1 << 14) /*send internally generated stop after sending ccsd */ -+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -+#define MSC_STRPCL_START_READWAIT (1 << 5) -+#define MSC_STRPCL_STOP_READWAIT (1 << 4) -+#define MSC_STRPCL_RESET (1 << 3) -+#define MSC_STRPCL_START_OP (1 << 2) -+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -+ -+/* MSC Status Register (MSC_STAT) */ -+#define MSC_STAT_AUTO_CMD_DONE (1 << 31) /*12 is internally generated by controller has finished */ -+#define MSC_STAT_IS_RESETTING (1 << 15) -+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -+#define MSC_STAT_PRG_DONE (1 << 13) -+#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -+#define MSC_STAT_END_CMD_RES (1 << 11) -+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -+#define MSC_STAT_IS_READWAIT (1 << 9) -+#define MSC_STAT_CLK_EN (1 << 8) -+#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -+#define MSC_STAT_CRC_RES_ERR (1 << 5) -+#define MSC_STAT_CRC_READ_ERROR (1 << 4) -+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -+#define MSC_STAT_TIME_OUT_RES (1 << 1) -+#define MSC_STAT_TIME_OUT_READ (1 << 0) -+ -+/* MSC Bus Clock Control Register (MSC_CLKRT) */ -+#define MSC_CLKRT_CLK_RATE_BIT 0 -+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -+ -+/* MSC Command Sequence Control Register (MSC_CMDAT) */ -+#define MSC_CMDAT_CCS_EXPECTED (1 << 31) /* interrupts are enabled in ce-ata */ -+#define MSC_CMDAT_READ_CEATA (1 << 30) -+#define MSC_CMDAT_SDIO_PRDT (1 << 17) /* exact 2 cycle */ -+#define MSC_CMDAT_SEND_AS_STOP (1 << 16) -+#define MSC_CMDAT_RTRG_BIT 14 -+ #define MSC_CMDAT_RTRG_EQUALT_8 (0x0 << MSC_CMDAT_RTRG_BIT) -+ #define MSC_CMDAT_RTRG_EQUALT_16 (0x1 << MSC_CMDAT_RTRG_BIT) /* reset value */ -+ #define MSC_CMDAT_RTRG_EQUALT_24 (0x2 << MSC_CMDAT_RTRG_BIT) -+ -+#define MSC_CMDAT_TTRG_BIT 12 -+ #define MSC_CMDAT_TTRG_LESS_8 (0x0 << MSC_CMDAT_TTRG_BIT) -+ #define MSC_CMDAT_TTRG_LESS_16 (0x1 << MSC_CMDAT_TTRG_BIT) /*reset value */ -+ #define MSC_CMDAT_TTRG_LESS_24 (0x2 << MSC_CMDAT_TTRG_BIT) -+#define MSC_CMDAT_STOP_ABORT (1 << 11) -+#define MSC_CMDAT_BUS_WIDTH_BIT 9 -+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -+ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -+ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -+ #define MSC_CMDAT_BUS_WIDTH_8BIT (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) /* 8-bit data bus */ -+#define MSC_CMDAT_DMA_EN (1 << 8) -+#define MSC_CMDAT_INIT (1 << 7) -+#define MSC_CMDAT_BUSY (1 << 6) -+#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -+#define MSC_CMDAT_WRITE (1 << 4) -+#define MSC_CMDAT_READ (0 << 4) -+#define MSC_CMDAT_DATA_EN (1 << 3) -+#define MSC_CMDAT_RESPONSE_BIT 0 -+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -+ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -+ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -+ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -+ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -+ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -+ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -+ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -+ -+#define CMDAT_DMA_EN (1 << 8) -+#define CMDAT_INIT (1 << 7) -+#define CMDAT_BUSY (1 << 6) -+#define CMDAT_STREAM (1 << 5) -+#define CMDAT_WRITE (1 << 4) -+#define CMDAT_DATA_EN (1 << 3) -+ -+/* MSC Interrupts Mask Register (MSC_IMASK) */ -+#define MSC_IMASK_AUTO_CMD_DONE (1 << 8) -+#define MSC_IMASK_SDIO (1 << 7) -+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IMASK_END_CMD_RES (1 << 2) -+#define MSC_IMASK_PRG_DONE (1 << 1) -+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -+ -+/* MSC Interrupts Status Register (MSC_IREG) */ -+#define MSC_IREG_AUTO_CMD_DONE (1 << 8) -+#define MSC_IREG_SDIO (1 << 7) -+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -+#define MSC_IREG_END_CMD_RES (1 << 2) -+#define MSC_IREG_PRG_DONE (1 << 1) -+#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -+ -+/* MSC Low Power Mode Register (MSC_LPM) */ -+#define MSC_SET_LPM (1 << 0) -+ -+/************************************************************************* -+ * EMC (External Memory Controller) -+ *************************************************************************/ -+#define EMC_BCR (EMC_BASE + 0x00) /* Bus Control Register */ -+#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ -+#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ -+#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ -+#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ -+#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ -+#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ -+#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ -+#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ -+#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ -+#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ -+ -+#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ -+ -+#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ -+#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ -+#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ -+#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ -+#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ -+#define EMC_DMAR1 (EMC_BASE + 0x94) /* SDRAM Bank 1 Addr Config Register */ -+#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ -+ -+#define REG_EMC_BCR REG32(EMC_BCR) -+#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -+#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -+#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -+#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -+#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -+#define REG_EMC_SACR0 REG32(EMC_SACR0) -+#define REG_EMC_SACR1 REG32(EMC_SACR1) -+#define REG_EMC_SACR2 REG32(EMC_SACR2) -+#define REG_EMC_SACR3 REG32(EMC_SACR3) -+#define REG_EMC_SACR4 REG32(EMC_SACR4) -+ -+#define REG_EMC_NFCSR REG32(EMC_NFCSR) -+ -+#define REG_EMC_DMCR REG32(EMC_DMCR) -+#define REG_EMC_RTCSR REG16(EMC_RTCSR) -+#define REG_EMC_RTCNT REG16(EMC_RTCNT) -+#define REG_EMC_RTCOR REG16(EMC_RTCOR) -+#define REG_EMC_DMAR0 REG32(EMC_DMAR0) -+#define REG_EMC_DMAR1 REG32(EMC_DMAR1) -+ -+/* Bus Control Register */ -+#define EMC_BCR_BT_SEL_BIT 30 -+#define EMC_BCR_BT_SEL_MASK (0x3 << EMC_BCR_BT_SEL_BIT) -+#define EMC_BCR_PK_SEL (1 << 24) -+#define EMC_BCR_BSR_MASK (1 << 2) /* Nand and SDRAM Bus Share Select: 0, share; 1, unshare */ -+ #define EMC_BCR_BSR_SHARE (0 << 2) -+ #define EMC_BCR_BSR_UNSHARE (1 << 2) -+#define EMC_BCR_BRE (1 << 1) -+#define EMC_BCR_ENDIAN (1 << 0) -+ -+/* Static Memory Control Register */ -+#define EMC_SMCR_STRV_BIT 24 -+#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -+#define EMC_SMCR_TAW_BIT 20 -+#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -+#define EMC_SMCR_TBP_BIT 16 -+#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -+#define EMC_SMCR_TAH_BIT 12 -+#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -+#define EMC_SMCR_TAS_BIT 8 -+#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -+#define EMC_SMCR_BW_BIT 6 -+#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -+ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -+#define EMC_SMCR_BCM (1 << 3) -+#define EMC_SMCR_BL_BIT 1 -+#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -+ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -+#define EMC_SMCR_SMT (1 << 0) -+ -+/* Static Memory Bank Addr Config Reg */ -+#define EMC_SACR_BASE_BIT 8 -+#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -+#define EMC_SACR_MASK_BIT 0 -+#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -+ -+/* NAND Flash Control/Status Register */ -+#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ -+#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ -+#define EMC_NFCSR_NFCE3 (1 << 5) -+#define EMC_NFCSR_NFE3 (1 << 4) -+#define EMC_NFCSR_NFCE2 (1 << 3) -+#define EMC_NFCSR_NFE2 (1 << 2) -+#define EMC_NFCSR_NFCE1 (1 << 1) -+#define EMC_NFCSR_NFE1 (1 << 0) -+ -+/* DRAM Control Register */ -+#define EMC_DMCR_BW_BIT 31 -+#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -+#define EMC_DMCR_CA_BIT 26 -+#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -+ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -+#define EMC_DMCR_RMODE (1 << 25) -+#define EMC_DMCR_RFSH (1 << 24) -+#define EMC_DMCR_MRSET (1 << 23) -+#define EMC_DMCR_RA_BIT 20 -+#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -+ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -+#define EMC_DMCR_BA_BIT 19 -+#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -+#define EMC_DMCR_PDM (1 << 18) -+#define EMC_DMCR_EPIN (1 << 17) -+#define EMC_DMCR_MBSEL (1 << 16) -+#define EMC_DMCR_TRAS_BIT 13 -+#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -+#define EMC_DMCR_RCD_BIT 11 -+#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -+#define EMC_DMCR_TPC_BIT 8 -+#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -+#define EMC_DMCR_TRWL_BIT 5 -+#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -+#define EMC_DMCR_TRC_BIT 2 -+#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -+#define EMC_DMCR_TCL_BIT 0 -+#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -+ -+/* Refresh Time Control/Status Register */ -+#define EMC_RTCSR_SFR (1 << 8) /* self refresh flag */ -+#define EMC_RTCSR_CMF (1 << 7) -+#define EMC_RTCSR_CKS_BIT 0 -+#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -+ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -+ -+/* SDRAM Bank Address Configuration Register */ -+#define EMC_DMAR_BASE_BIT 8 -+#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -+#define EMC_DMAR_MASK_BIT 0 -+#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -+ -+/* Mode Register of SDRAM bank 0 */ -+#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ -+#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ -+#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -+ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -+#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ -+#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -+ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -+#define EMC_SDMR_BT_BIT 3 /* Burst Type */ -+#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -+ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ -+ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ -+#define EMC_SDMR_BL_BIT 0 /* Burst Length */ -+#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -+ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -+ -+#define EMC_SDMR_CAS2_16BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS2_32BIT \ -+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+#define EMC_SDMR_CAS3_16BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -+#define EMC_SDMR_CAS3_32BIT \ -+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -+ -+ -+/************************************************************************* -+ * CIM -+ *************************************************************************/ -+#define CIM_CFG (CIM_BASE + 0x0000) -+#define CIM_CTRL (CIM_BASE + 0x0004) -+#define CIM_STATE (CIM_BASE + 0x0008) -+#define CIM_IID (CIM_BASE + 0x000C) -+#define CIM_RXFIFO (CIM_BASE + 0x0010) -+#define CIM_DA (CIM_BASE + 0x0020) -+#define CIM_FA (CIM_BASE + 0x0024) -+#define CIM_FID (CIM_BASE + 0x0028) -+#define CIM_CMD (CIM_BASE + 0x002C) -+#define CIM_SIZE (CIM_BASE + 0x0030) -+#define CIM_OFFSET (CIM_BASE + 0x0034) -+#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -+ -+#define REG_CIM_CFG REG32(CIM_CFG) -+#define REG_CIM_CTRL REG32(CIM_CTRL) -+#define REG_CIM_STATE REG32(CIM_STATE) -+#define REG_CIM_IID REG32(CIM_IID) -+#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -+#define REG_CIM_DA REG32(CIM_DA) -+#define REG_CIM_FA REG32(CIM_FA) -+#define REG_CIM_FID REG32(CIM_FID) -+#define REG_CIM_CMD REG32(CIM_CMD) -+#define REG_CIM_SIZE REG32(CIM_SIZE) -+#define REG_CIM_OFFSET REG32(CIM_OFFSET) -+ -+#define CIM_CFG_ORDER_BIT 18 -+#define CIM_CFG_ORDER_MASK (0x3 << CIM_CFG_ORDER_BIT) -+ #define CIM_CFG_ORDER_0 (0x0 << CIM_CFG_ORDER_BIT) /* Y0CbY1Cr; YCbCr */ -+ #define CIM_CFG_ORDER_1 (0x1 << CIM_CFG_ORDER_BIT) /* Y0CrY1Cb; YCrCb */ -+ #define CIM_CFG_ORDER_2 (0x2 << CIM_CFG_ORDER_BIT) /* CbY0CrY1; CbCrY */ -+ #define CIM_CFG_ORDER_3 (0x3 << CIM_CFG_ORDER_BIT) /* CrY0CbY1; CrCbY */ -+#define CIM_CFG_DF_BIT 16 -+#define CIM_CFG_DF_MASK (0x3 << CIM_CFG_DF_BIT) -+ #define CIM_CFG_DF_YUV444 (0x1 << CIM_CFG_DF_BIT) /* YCbCr444 */ -+ #define CIM_CFG_DF_YUV422 (0x2 << CIM_CFG_DF_BIT) /* YCbCr422 */ -+ #define CIM_CFG_DF_ITU656 (0x3 << CIM_CFG_DF_BIT) /* ITU656 YCbCr422 */ -+#define CIM_CFG_INV_DAT (1 << 15) -+#define CIM_CFG_VSP (1 << 14) /* VSYNC Polarity:0-rising edge active,1-falling edge active */ -+#define CIM_CFG_HSP (1 << 13) /* HSYNC Polarity:0-rising edge active,1-falling edge active */ -+#define CIM_CFG_PCP (1 << 12) /* PCLK working edge: 0-rising, 1-falling */ -+#define CIM_CFG_DMA_BURST_TYPE_BIT 10 -+#define CIM_CFG_DMA_BURST_TYPE_MASK (0x3 << CIM_CFG_DMA_BURST_TYPE_BIT) -+ #define CIM_CFG_DMA_BURST_INCR4 (0 << CIM_CFG_DMA_BURST_TYPE_BIT) -+ #define CIM_CFG_DMA_BURST_INCR8 (1 << CIM_CFG_DMA_BURST_TYPE_BIT) /* Suggested */ -+ #define CIM_CFG_DMA_BURST_INCR16 (2 << CIM_CFG_DMA_BURST_TYPE_BIT) /* Suggested High speed AHB*/ -+#define CIM_CFG_DUMMY_ZERO (1 << 9) -+#define CIM_CFG_EXT_VSYNC (1 << 8) /* Only for ITU656 Progressive mode */ -+#define CIM_CFG_PACK_BIT 4 -+#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -+ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) /* 11 22 33 44 0xY0CbY1Cr */ -+ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) /* 22 33 44 11 0xCbY1CrY0 */ -+ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) /* 33 44 11 22 0xY1CrY0Cb */ -+ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) /* 44 11 22 33 0xCrY0CbY1 */ -+ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) /* 44 33 22 11 0xCrY1CbY0 */ -+ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) /* 33 22 11 44 0xY1CbY0Cr */ -+ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) /* 22 11 44 33 0xCbY0CrY1 */ -+ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) /* 11 44 33 22 0xY0CrY1Cb */ -+#define CIM_CFG_BYPASS_BIT 2 -+#define CIM_CFG_BYPASS_MASK (1 << CIM_CFG_BYPASS_BIT) -+ #define CIM_CFG_BYPASS (1 << CIM_CFG_BYPASS_BIT) -+#define CIM_CFG_DSM_BIT 0 -+#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -+ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -+ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -+ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -+ -+/* CIM Control Register (CIM_CTRL) */ -+#define CIM_CTRL_EEOF_LINE_BIT 20 -+#define CIM_CTRL_EEOF_LINE_MASK (0xfff << CIM_CTRL_EEOF_LINE_BIT) -+#define CIM_CTRL_FRC_BIT 16 -+#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -+ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -+ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -+ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -+ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -+ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -+ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -+ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -+ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -+ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -+ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -+ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -+ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -+ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -+ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -+ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -+ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -+ -+#define CIM_CTRL_DMA_EEOF (1 << 15) /* Enable EEOF interrupt */ -+#define CIM_CTRL_WIN_EN (1 << 14) -+#define CIM_CTRL_VDDM (1 << 13) /* VDD interrupt enable */ -+#define CIM_CTRL_DMA_SOFM (1 << 12) -+#define CIM_CTRL_DMA_EOFM (1 << 11) -+#define CIM_CTRL_DMA_STOPM (1 << 10) -+#define CIM_CTRL_RXF_TRIGM (1 << 9) -+#define CIM_CTRL_RXF_OFM (1 << 8) -+#define CIM_CTRL_DMA_SYNC (1 << 7) /*when change DA, do frame sync */ -+#define CIM_CTRL_RXF_TRIG_BIT 3 -+#define CIM_CTRL_RXF_TRIG_MASK (0xf << CIM_CTRL_RXF_TRIG_BIT) /* trigger value = (n+1)*burst_type */ -+ -+#define CIM_CTRL_DMA_EN (1 << 2) /* Enable DMA */ -+#define CIM_CTRL_RXF_RST (1 << 1) /* RxFIFO reset */ -+#define CIM_CTRL_ENA (1 << 0) /* Enable CIM */ -+ -+/* CIM State Register (CIM_STATE) */ -+#define CIM_STATE_DMA_EEOF (1 << 7) /* DMA Line EEOf irq */ -+#define CIM_STATE_DMA_SOF (1 << 6) /* DMA start irq */ -+#define CIM_STATE_DMA_EOF (1 << 5) /* DMA end irq */ -+#define CIM_STATE_DMA_STOP (1 << 4) /* DMA stop irq */ -+#define CIM_STATE_RXF_OF (1 << 3) /* RXFIFO over flow irq */ -+#define CIM_STATE_RXF_TRIG (1 << 2) /* RXFIFO triger meet irq */ -+#define CIM_STATE_RXF_EMPTY (1 << 1) /* RXFIFO empty irq */ -+#define CIM_STATE_VDD (1 << 0) /* CIM disabled irq */ -+ -+/* CIM DMA Command Register (CIM_CMD) */ -+ -+#define CIM_CMD_SOFINT (1 << 31) /* enable DMA start irq */ -+#define CIM_CMD_EOFINT (1 << 30) /* enable DMA end irq */ -+#define CIM_CMD_EEOFINT (1 << 29) /* enable DMA EEOF irq */ -+#define CIM_CMD_STOP (1 << 28) /* enable DMA stop irq */ -+#define CIM_CMD_OFRCV (1 << 27) /* enable recovery when TXFiFo overflow */ -+#define CIM_CMD_LEN_BIT 0 -+#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -+ -+/* CIM Window-Image Size Register (CIM_SIZE) */ -+#define CIM_SIZE_LPF_BIT 16 /* Lines per freame for csc output image */ -+#define CIM_SIZE_LPF_MASK (0x1fff << CIM_SIZE_LPF_BIT) -+#define CIM_SIZE_PPL_BIT 0 /* Pixels per line for csc output image, should be an even number */ -+#define CIM_SIZE_PPL_MASK (0x1fff << CIM_SIZE_PPL_BIT) -+ -+/* CIM Image Offset Register (CIM_OFFSET) */ -+#define CIM_OFFSET_V_BIT 16 /* Vertical offset */ -+#define CIM_OFFSET_V_MASK (0xfff << CIM_OFFSET_V_BIT) -+#define CIM_OFFSET_H_BIT 0 /* Horizontal offset, should be an enen number */ -+#define CIM_OFFSET_H_MASK (0xfff << CIM_OFFSET_H_BIT) /*OFFSET_H should be even number*/ -+ -+/************************************************************************* -+ * SADC (Smart A/D Controller) -+ *************************************************************************/ -+ -+#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ -+#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ -+#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ -+#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ -+#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ -+#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ -+#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ -+#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ -+#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ -+#define SADC_ADCLK (SADC_BASE + 0x28) /* ADC Clock Divide Register */ -+ -+#define REG_SADC_ENA REG8(SADC_ENA) -+#define REG_SADC_CFG REG32(SADC_CFG) -+#define REG_SADC_CTRL REG8(SADC_CTRL) -+#define REG_SADC_STATE REG8(SADC_STATE) -+#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) -+#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) -+#define REG_SADC_TSDAT REG32(SADC_TSDAT) -+#define REG_SADC_BATDAT REG16(SADC_BATDAT) -+#define REG_SADC_SADDAT REG16(SADC_SADDAT) -+#define REG_SADC_ADCLK REG32(SADC_ADCLK) -+ -+/* ADC Enable Register */ -+#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ -+#define SADC_ENA_ENTR_SLP (1 << 6) /* Touch Screen Enable */ -+#define SADC_ENA_EXIT_SLP (1 << 5) /* Touch Screen Enable */ -+#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ -+#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ -+#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ -+ -+/* ADC Configure Register */ -+#define SADC_CFG_EXIN (1 << 30) -+#define SADC_CFG_CLKOUT_NUM_BIT 16 -+#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) -+#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ -+#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ -+#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) -+ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) -+#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ -+#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) -+ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) -+#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ -+#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) -+#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ -+#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ -+#define SADC_CFG_CMD_BIT 0 /* ADC Command */ -+#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) -+ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ -+ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ -+ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ -+ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ -+ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ -+ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ -+ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ -+ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ -+ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ -+ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ -+ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ -+ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ -+ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ -+ -+/* ADC Control Register */ -+#define SADC_CTRL_SLPENDM (1 << 5) /* sleep Interrupt Mask */ -+#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ -+#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ -+#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ -+#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ -+#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ -+ -+/* ADC Status Register */ -+#define SADC_STATE_SLEEPND (1 << 5) /* Pen Down Interrupt Flag */ -+#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ -+#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ -+#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ -+#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ -+#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ -+ -+/* ADC Touch Screen Data Register */ -+#define SADC_TSDAT_DATA0_BIT 0 -+#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) -+#define SADC_TSDAT_TYPE0 (1 << 15) -+#define SADC_TSDAT_DATA1_BIT 16 -+#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) -+#define SADC_TSDAT_TYPE1 (1 << 31) -+ -+/* ADC Clock Divide Register */ -+#define SADC_ADCLK_CLKDIV_10_BIT 16 -+#define SADC_ADCLK_CLKDIV_10_MASK (0x7f << SADC_ADCLK_CLKDIV_10_BIT) -+#define SADC_ADCLK_CLKDIV_BIT 0 -+#define SADC_ADCLK_CLKDIV_MASK (0x3f << SADC_ADCLK_CLKDIV_BIT) -+ -+/************************************************************************* -+ * SLCD (Smart LCD Controller) -+ *************************************************************************/ -+ -+#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ -+#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ -+#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ -+#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ -+ -+#define REG_SLCD_CFG REG32(SLCD_CFG) -+#define REG_SLCD_CTRL REG8(SLCD_CTRL) -+#define REG_SLCD_STATE REG8(SLCD_STATE) -+#define REG_SLCD_DATA REG32(SLCD_DATA) -+ -+/* SLCD Configure Register */ -+#define SLCD_CFG_DWIDTH_BIT 10 -+#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_18BIT (0 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_16BIT (1 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8BIT_x3 (2 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8BIT_x2 (3 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_8BIT_x1 (4 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_24BIT (5 << SLCD_CFG_DWIDTH_BIT) -+ #define SLCD_CFG_DWIDTH_9BIT_x2 (7 << SLCD_CFG_DWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_BIT (8) -+#define SLCD_CFG_CWIDTH_MASK (0x7 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CWIDTH_24BIT (3 << SLCD_CFG_CWIDTH_BIT) -+#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) -+#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) -+#define SLCD_CFG_RS_CMD_LOW (0 << 3) -+#define SLCD_CFG_RS_CMD_HIGH (1 << 3) -+#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) -+#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) -+#define SLCD_CFG_TYPE_PARALLEL (0 << 0) -+#define SLCD_CFG_TYPE_SERIAL (1 << 0) -+ -+/* SLCD Control Register */ -+#define SLCD_CTRL_DMA_MODE (1 << 2) -+#define SLCD_CTRL_DMA_START (1 << 1) -+#define SLCD_CTRL_DMA_EN (1 << 0) -+ -+/* SLCD Status Register */ -+#define SLCD_STATE_BUSY (1 << 0) -+ -+/* SLCD Data Register */ -+#define SLCD_DATA_RS_DATA (0 << 31) -+#define SLCD_DATA_RS_COMMAND (1 << 31) -+ -+/************************************************************************* -+ * LCD (LCD Controller) -+ *************************************************************************/ -+#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ -+#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ -+#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ -+ -+#define LCD_OSDC (LCD_BASE + 0x100) /* LCD OSD Configure Register */ -+#define LCD_OSDCTRL (LCD_BASE + 0x104) /* LCD OSD Control Register */ -+#define LCD_OSDS (LCD_BASE + 0x108) /* LCD OSD Status Register */ -+#define LCD_BGC (LCD_BASE + 0x10C) /* LCD Background Color Register */ -+#define LCD_KEY0 (LCD_BASE + 0x110) /* LCD Foreground Color Key Register 0 */ -+#define LCD_KEY1 (LCD_BASE + 0x114) /* LCD Foreground Color Key Register 1 */ -+#define LCD_ALPHA (LCD_BASE + 0x118) /* LCD ALPHA Register */ -+#define LCD_IPUR (LCD_BASE + 0x11C) /* LCD IPU Restart Register */ -+ -+#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ -+#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ -+#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ -+ -+#define LCD_XYP0 (LCD_BASE + 0x120) /* Foreground 0 XY Position Register */ -+#define LCD_XYP1 (LCD_BASE + 0x124) /* Foreground 1 XY Position Register */ -+#define LCD_SIZE0 (LCD_BASE + 0x128) /* Foreground 0 Size Register */ -+#define LCD_SIZE1 (LCD_BASE + 0x12C) /* Foreground 1 Size Register */ -+#define LCD_RGBC (LCD_BASE + 0x90) /* RGB Controll Register */ -+ -+#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ -+#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ -+#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ -+#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ -+#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ -+#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ -+#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ -+#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ -+#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ -+#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ -+#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ -+#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ -+#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ -+#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ -+#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ -+ -+#define LCD_OFFS0 (LCD_BASE + 0x60) /* DMA Offsize Register 0 */ -+#define LCD_PW0 (LCD_BASE + 0x64) /* DMA Page Width Register 0 */ -+#define LCD_CNUM0 (LCD_BASE + 0x68) /* DMA Command Counter Register 0 */ -+#define LCD_DESSIZE0 (LCD_BASE + 0x6C) /* Foreground Size in Descriptor 0 Register*/ -+#define LCD_OFFS1 (LCD_BASE + 0x70) /* DMA Offsize Register 1 */ -+#define LCD_PW1 (LCD_BASE + 0x74) /* DMA Page Width Register 1 */ -+#define LCD_CNUM1 (LCD_BASE + 0x78) /* DMA Command Counter Register 1 */ -+#define LCD_DESSIZE1 (LCD_BASE + 0x7C) /* Foreground Size in Descriptor 1 Register*/ -+ -+#define REG_LCD_CFG REG32(LCD_CFG) -+#define REG_LCD_CTRL REG32(LCD_CTRL) -+#define REG_LCD_STATE REG32(LCD_STATE) -+ -+#define REG_LCD_OSDC REG16(LCD_OSDC) -+#define REG_LCD_OSDCTRL REG16(LCD_OSDCTRL) -+#define REG_LCD_OSDS REG16(LCD_OSDS) -+#define REG_LCD_BGC REG32(LCD_BGC) -+#define REG_LCD_KEY0 REG32(LCD_KEY0) -+#define REG_LCD_KEY1 REG32(LCD_KEY1) -+#define REG_LCD_ALPHA REG8(LCD_ALPHA) -+#define REG_LCD_IPUR REG32(LCD_IPUR) -+ -+#define REG_LCD_VAT REG32(LCD_VAT) -+#define REG_LCD_DAH REG32(LCD_DAH) -+#define REG_LCD_DAV REG32(LCD_DAV) -+ -+#define REG_LCD_XYP0 REG32(LCD_XYP0) -+#define REG_LCD_XYP1 REG32(LCD_XYP1) -+#define REG_LCD_SIZE0 REG32(LCD_SIZE0) -+#define REG_LCD_SIZE1 REG32(LCD_SIZE1) -+#define REG_LCD_RGBC REG16(LCD_RGBC) -+ -+#define REG_LCD_VSYNC REG32(LCD_VSYNC) -+#define REG_LCD_HSYNC REG32(LCD_HSYNC) -+#define REG_LCD_PS REG32(LCD_PS) -+#define REG_LCD_CLS REG32(LCD_CLS) -+#define REG_LCD_SPL REG32(LCD_SPL) -+#define REG_LCD_REV REG32(LCD_REV) -+#define REG_LCD_IID REG32(LCD_IID) -+#define REG_LCD_DA0 REG32(LCD_DA0) -+#define REG_LCD_SA0 REG32(LCD_SA0) -+#define REG_LCD_FID0 REG32(LCD_FID0) -+#define REG_LCD_CMD0 REG32(LCD_CMD0) -+#define REG_LCD_DA1 REG32(LCD_DA1) -+#define REG_LCD_SA1 REG32(LCD_SA1) -+#define REG_LCD_FID1 REG32(LCD_FID1) -+#define REG_LCD_CMD1 REG32(LCD_CMD1) -+ -+#define REG_LCD_OFFS0 REG32(LCD_OFFS0) -+#define REG_LCD_PW0 REG32(LCD_PW0) -+#define REG_LCD_CNUM0 REG32(LCD_CNUM0) -+#define REG_LCD_DESSIZE0 REG32(LCD_DESSIZE0) -+#define REG_LCD_OFFS1 REG32(LCD_OFFS1) -+#define REG_LCD_PW1 REG32(LCD_PW1) -+#define REG_LCD_CNUM1 REG32(LCD_CNUM1) -+#define REG_LCD_DESSIZE1 REG32(LCD_DESSIZE1) -+ -+/* LCD Configure Register */ -+#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ -+#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) -+ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) -+ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) -+#define LCD_CFG_TVEPEH (1 << 30) /* TVE PAL enable extra halfline signal */ -+#define LCD_CFG_FUHOLD (1 << 29) /* hold pixel clock when outFIFO underrun */ -+#define LCD_CFG_NEWDES (1 << 28) /* use new descripter. old: 4words, new:8words */ -+#define LCD_CFG_PALBP (1 << 27) /* bypass data format and alpha blending */ -+#define LCD_CFG_TVEN (1 << 26) /* indicate the terminal is lcd or tv */ -+#define LCD_CFG_RECOVER (1 << 25) /* Auto recover when output fifo underrun */ -+#define LCD_CFG_DITHER (1 << 24) /* Dither function */ -+#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ -+#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ -+#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ -+#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ -+#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ -+#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ -+#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ -+#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ -+#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ -+#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ -+#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ -+#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ -+#define LCD_CFG_HSP (1 << 11) /* HSYNC polarity:0-active high,1-active low */ -+#define LCD_CFG_PCP (1 << 10) /* PCLK polarity:0-rising,1-falling */ -+#define LCD_CFG_DEP (1 << 9) /* DE polarity:0-active high,1-active low */ -+#define LCD_CFG_VSP (1 << 8) /* VSYNC polarity:0-rising,1-falling */ -+#define LCD_CFG_MODE_TFT_18BIT (1 << 7) /* 18bit TFT */ -+#define LCD_CFG_MODE_TFT_16BIT (0 << 7) /* 16bit TFT */ -+#define LCD_CFG_MODE_TFT_24BIT (1 << 6) /* 24bit TFT */ -+#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ -+#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) -+#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ -+ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ -+ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ -+ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ -+#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ -+#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ -+ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_LCM (13 << LCD_CFG_MODE_BIT) -+ #define LCD_CFG_MODE_SLCD LCD_CFG_MODE_LCM -+ -+/* LCD Control Register */ -+#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ -+#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -+ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ -+ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ -+ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ -+ #define LCD_CTRL_BST_32 (3 << LCD_CTRL_BST_BIT) /* 32-word */ -+#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode(foreground 0 in OSD mode) */ -+#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode(foreground 0 in OSD mode) */ -+#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ -+#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ -+#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -+ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ -+ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ -+ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ -+#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ -+#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -+#define LCD_CTRL_VGA (1 << 15) /* VGA interface enable */ -+#define LCD_CTRL_DACTE (1 << 14) /* DAC loop back test */ -+#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ -+#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ -+#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ -+#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ -+#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ -+#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ -+#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ -+#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ -+#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ -+#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ -+#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ -+#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ -+#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -+ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ -+ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ -+ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ -+ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ -+ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ -+ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ -+ #define LCD_CTRL_BPP_CMPS_24 (6 << LCD_CTRL_BPP_BIT) /* 24 compress bpp */ -+ -+/* LCD Status Register */ -+#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ -+#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ -+#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ -+#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ -+#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ -+#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ -+#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ -+ -+/* OSD Configure Register */ -+#define LCD_OSDC_SOFM1 (1 << 15) /* Start of frame interrupt mask for foreground 1 */ -+#define LCD_OSDC_EOFM1 (1 << 14) /* End of frame interrupt mask for foreground 1 */ -+#define LCD_OSDC_SOFM0 (1 << 11) /* Start of frame interrupt mask for foreground 0 */ -+#define LCD_OSDC_EOFM0 (1 << 10) /* End of frame interrupt mask for foreground 0 */ -+#define LCD_OSDC_F1EN (1 << 4) /* enable foreground 1 */ -+#define LCD_OSDC_F0EN (1 << 3) /* enable foreground 0 */ -+#define LCD_OSDC_ALPHAEN (1 << 2) /* enable alpha blending */ -+#define LCD_OSDC_ALPHAMD (1 << 1) /* alpha blending mode */ -+#define LCD_OSDC_OSDEN (1 << 0) /* OSD mode enable */ -+ -+/* OSD Controll Register */ -+#define LCD_OSDCTRL_IPU (1 << 15) /* input data from IPU */ -+#define LCD_OSDCTRL_RGB565 (0 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -+#define LCD_OSDCTRL_RGB555 (1 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -+#define LCD_OSDCTRL_CHANGES (1 << 3) /* Change size flag */ -+#define LCD_OSDCTRL_OSDBPP_BIT 0 /* Bits Per Pixel of OSD Channel 1 */ -+#define LCD_OSDCTRL_OSDBPP_MASK (0x7< -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_BOARD_SERIAL_H__ -+#define __ASM_BOARD_SERIAL_H__ -+ -+#ifndef CONFIG_SERIAL_MANY_PORTS -+#undef RS_TABLE_SIZE -+#define RS_TABLE_SIZE 1 -+#endif -+ -+#define JZ_BASE_BAUD (12000000/16) -+ -+#define JZ_SERIAL_PORT_DEFNS \ -+ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -+ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -+ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -+ -+#endif /* __ASM_BORAD_SERIAL_H__ */ -diff --git a/include/asm-mips/mach-jz4750d/war.h b/include/asm-mips/mach-jz4750d/war.h -new file mode 100644 -index 0000000..3a5bc17 ---- /dev/null -+++ b/include/asm-mips/mach-jz4750d/war.h -@@ -0,0 +1,25 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -+ */ -+#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -+#define __ASM_MIPS_MACH_JZ4740_WAR_H -+ -+#define R4600_V1_INDEX_ICACHEOP_WAR 0 -+#define R4600_V1_HIT_CACHEOP_WAR 0 -+#define R4600_V2_HIT_CACHEOP_WAR 0 -+#define R5432_CP0_INTERRUPT_WAR 0 -+#define BCM1250_M3_WAR 0 -+#define SIBYTE_1956_WAR 0 -+#define MIPS4K_ICACHE_REFILL_WAR 0 -+#define MIPS_CACHE_SYNC_WAR 0 -+#define TX49XX_ICACHE_INDEX_INV_WAR 0 -+#define RM9000_CDEX_SMP_WAR 0 -+#define ICACHE_REFILLS_WORKAROUND_WAR 0 -+#define R10000_LLSC_WAR 0 -+#define MIPS34K_MISSED_ITLB_WAR 0 -+ -+#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -diff --git a/include/asm-mips/sizes.h b/include/asm-mips/sizes.h -new file mode 100644 -index 0000000..503843d ---- /dev/null -+++ b/include/asm-mips/sizes.h -@@ -0,0 +1,56 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+/* DO NOT EDIT!! - this file automatically generated -+ * from .s file by awk -f s2h.awk -+ */ -+/* Size definitions -+ * Copyright (C) ARM Limited 1998. All rights reserved. -+ */ -+ -+#ifndef __sizes_h -+#define __sizes_h 1 -+ -+/* handy sizes */ -+#define SZ_16 0x00000010 -+#define SZ_256 0x00000100 -+#define SZ_512 0x00000200 -+ -+#define SZ_1K 0x00000400 -+#define SZ_4K 0x00001000 -+#define SZ_8K 0x00002000 -+#define SZ_16K 0x00004000 -+#define SZ_64K 0x00010000 -+#define SZ_128K 0x00020000 -+#define SZ_256K 0x00040000 -+#define SZ_512K 0x00080000 -+ -+#define SZ_1M 0x00100000 -+#define SZ_2M 0x00200000 -+#define SZ_4M 0x00400000 -+#define SZ_8M 0x00800000 -+#define SZ_16M 0x01000000 -+#define SZ_32M 0x02000000 -+#define SZ_64M 0x04000000 -+#define SZ_128M 0x08000000 -+#define SZ_256M 0x10000000 -+#define SZ_512M 0x20000000 -+ -+#define SZ_1G 0x40000000 -+#define SZ_2G 0x80000000 -+ -+#endif -+ -+/* END */ -diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h -index fd53bfd..b52bba3 100644 ---- a/include/linux/i2c-dev.h -+++ b/include/linux/i2c-dev.h -@@ -49,7 +49,8 @@ - - #define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ - #define I2C_SMBUS 0x0720 /* SMBus transfer */ -- -+#define I2C_SET_SUB_ADDRESS 0x0730 /* SMBus transfer */ -+#define I2C_SET_CLOCK 0x0731 /* SMBus transfer */ - - /* This is the structure as used in the I2C_SMBUS ioctl call */ - struct i2c_smbus_ioctl_data { -@@ -71,4 +72,5 @@ struct i2c_rdwr_ioctl_data { - #define I2C_MAJOR 89 /* Device major number */ - #endif - -+extern void i2c_jz_setclk(unsigned int i2cclk); - #endif /* _LINUX_I2C_DEV_H */ -diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h -index 4030eba..4af8f35 100644 ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -53,6 +53,10 @@ extern void nand_wait_ready(struct mtd_info *mtd); - * bits in one go. - */ - /* Select the chip by setting nCE to low */ -+#define NAND_NCE1 0x08 -+#define NAND_NCE2 0x10 -+#define NAND_NCE3 0x20 -+#define NAND_NCE4 0x40 - #define NAND_NCE 0x01 - /* Select the command latch by setting CLE to high */ - #define NAND_CLE 0x02 -diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h -index b70313d..4dbcf23 100644 ---- a/include/linux/mtd/partitions.h -+++ b/include/linux/mtd/partitions.h -@@ -38,6 +38,17 @@ struct mtd_partition { - char *name; /* identifier string */ - uint64_t size; /* partition size */ - uint64_t offset; /* offset within the master MTD space */ -+ -+ char cpu_mode; -+ /* flag to specify whether the partition works with cpu mode, 0: -+ * dma mode, 1:cpu mode */ -+ char use_planes; -+ /* flag to specify whether multiple planes of NAND is used in -+ * the partition, 0:don't use planes, 1: use planes */ -+ uint32_t mtdblock_jz_invalid; -+ /* flag to specify whether the partition works over mtdblock-jz, -+ * 0: over mtdblock-jz, 1: not over mtdblock-jz */ -+ - uint32_t mask_flags; /* master MTD flags to mask out for this partition */ - struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ - }; -diff --git a/include/linux/vt.h b/include/linux/vt.h -index 02c1c02..edbb787 100644 ---- a/include/linux/vt.h -+++ b/include/linux/vt.h -@@ -18,10 +18,16 @@ extern int unregister_vt_notifier(struct notifier_block *nb); - * resizing). - */ - #define MIN_NR_CONSOLES 1 /* must be at least 1 */ --#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ --#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ -- /* Note: the ioctl VT_GETSTATE does not work for -- consoles 16 and higher (since it returns a short) */ -+ -+#if defined(CONFIG_JZSOC) -+#define MAX_NR_CONSOLES 2 -+#define MAX_NR_USER_CONSOLES 2 -+#else -+#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ -+#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ -+ /* Note: the ioctl VT_GETSTATE does not work for -+ consoles 16 and higher (since it returns a short) */ -+#endif - - /* 0x56 is 'V', to avoid collision with termios and kd */ - -diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h -index be51ae2..0d0b953 100644 ---- a/include/mtd/mtd-abi.h -+++ b/include/mtd/mtd-abi.h -@@ -30,6 +30,14 @@ struct mtd_oob_buf64 { - __u64 usr_ptr; - }; - -+struct mtd_page_buf { -+ uint32_t start; //page start address -+ uint32_t ooblength; -+ uint32_t datlength; -+ unsigned char __user *oobptr; -+ unsigned char __user *datptr; -+}; -+ - #define MTD_ABSENT 0 - #define MTD_RAM 1 - #define MTD_ROM 2 -@@ -42,6 +50,8 @@ struct mtd_oob_buf64 { - #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ - #define MTD_NO_ERASE 0x1000 /* No erase necessary */ - #define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */ -+#define MTD_MTDBLOCK_JZ_INVALID 0x4000 /* Device doesn't works over mtdblock-jz */ -+#define MTD_NAND_CPU_MODE 0x8000 /* Using cpu mode for NAND */ - - // Some common devices / combinations of capabilities - #define MTD_CAP_ROM 0 -diff --git a/include/sound/pcm.h b/include/sound/pcm.h -index 2389352..24dcb18 100644 ---- a/include/sound/pcm.h -+++ b/include/sound/pcm.h -@@ -113,23 +113,23 @@ struct snd_pcm_ops { - #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ - #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ - #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ --#define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ --#define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ --#define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ --#define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ --#define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ --#define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ --#define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ --#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ --#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ --#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ -+#define SNDRV_PCM_RATE_12000 (1<<3) /* 12000Hz */ -+#define SNDRV_PCM_RATE_16000 (1<<4) /* 16000Hz */ -+#define SNDRV_PCM_RATE_22050 (1<<5) /* 22050Hz */ -+#define SNDRV_PCM_RATE_24000 (1<<6) /* 24000Hz */ -+#define SNDRV_PCM_RATE_32000 (1<<7) /* 32000Hz */ -+#define SNDRV_PCM_RATE_44100 (1<<8) /* 44100Hz */ -+#define SNDRV_PCM_RATE_48000 (1<<9) /* 48000Hz */ -+#define SNDRV_PCM_RATE_64000 (1<<10) /* 64000Hz */ -+#define SNDRV_PCM_RATE_88200 (1<<11) /* 88200Hz */ -+#define SNDRV_PCM_RATE_96000 (1<<12) /* 96000Hz */ -+#define SNDRV_PCM_RATE_176400 (1<<13) /* 176400Hz */ -+#define SNDRV_PCM_RATE_192000 (1<<14) /* 192000Hz */ - - #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ - #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ - --#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ -- SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ -- SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) -+#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|SNDRV_PCM_RATE_12000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_24000|SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) - #define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) - #define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ - SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) -diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c -index 72cfd47..5ae0a2d 100644 ---- a/sound/core/pcm_lib.c -+++ b/sound/core/pcm_lib.c -@@ -2076,6 +2076,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, - return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; - } - -+#if 0 - snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) - { - struct snd_pcm_runtime *runtime; -@@ -2091,6 +2092,99 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u - return -EINVAL; - return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); - } -+#else -+snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) -+{ -+ struct snd_pcm_runtime *runtime; -+ int nonblock; -+ -+ snd_pcm_sframes_t tmp_frames; -+ snd_pcm_sframes_t final_frames; -+ int channels; -+ -+ snd_assert(substream != NULL, return -ENXIO); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -ENXIO); -+ snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL); -+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -+ return -EBADFD; -+ -+ nonblock = !!(substream->f_flags & O_NONBLOCK); -+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) -+ return -EINVAL; -+ -+ /* -+ * mono capture process for no mono codec -+ * function codec such as ipcood and dlv -+ */ -+ -+ tmp_frames = snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); -+ -+ channels = runtime->channels; -+ -+ if (channels == 1) { -+ short *tmpbuf = kcalloc(tmp_frames, sizeof(short), GFP_KERNEL); -+ short *src, *dst, *end; -+ -+ memcpy(tmpbuf, buf, frames_to_bytes(runtime, tmp_frames)); -+ -+ src = (short *)buf; -+ dst = (short *)tmpbuf; -+ end = dst + tmp_frames - 1; -+ -+ src++; -+ dst++; -+ dst++; -+ final_frames = 1; -+ while (dst <= end) { -+ *src = *dst; -+ final_frames++; -+ src++; -+ dst++; -+ dst++; -+ } -+ tmp_frames = final_frames; -+ kfree(tmpbuf); -+ -+#if 0 -+ /* when i have time, i will try the code, no kcalloc */ -+ snd_assert(runtime->dma_area, return -EFAULT); -+ if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) -+ return -EFAULT; -+ -+ unsigned int up_bytes = frames_to_bytes(runtime, frames); -+ -+ int while_cnt = 4; -+ int while_all = up_bytes - 2; -+ -+ while (while_cnt <= while_all) { -+ //printk("[%d = %d]\n",(while_cnt/2),while_cnt); -+ buf[(while_cnt/2)] = buf[while_cnt]; -+ //printk("[%d = %d]\n",((while_cnt/2)+1),(while_cnt+1)); -+ buf[((while_cnt/2)+1)] = buf[(while_cnt+1)]; -+ while_cnt += 4; -+#if 0 -+ buf[2] = buf[4]; -+ buf[3] = buf[5]; -+ -+ buf[4] = buf[8]; -+ buf[5] = buf[9]; -+ -+ buf[6] = buf[12]; -+ buf[7] = buf[13]; -+ -+ buf[8] = buf[16]; -+ buf[9] = buf[17]; -+#endif -+ } -+ /* when i have time, i will try the code, no kcalloc */ -+#endif -+ -+ } -+ -+ return tmp_frames; -+} -+#endif - - EXPORT_SYMBOL(snd_pcm_lib_read); - -diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c -index ac2150e..2a57ab7 100644 ---- a/sound/core/pcm_native.c -+++ b/sound/core/pcm_native.c -@@ -1748,12 +1748,13 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, - return snd_interval_refine(hw_param_interval(params, rule->var), &t); - } - --#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -+#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 14 - #error "Change this table" - #endif - --static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, -- 48000, 64000, 88200, 96000, 176400, 192000 }; -+static unsigned int rates[] = { 5512, 8000, 11025, 12000, 16000, 22050, 24000, -+ 32000, 44100, 48000, 64000, 88200, 96000, -+ 176400, 192000 }; - - const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { - .count = ARRAY_SIZE(rates), -@@ -1764,9 +1765,17 @@ static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) - { - struct snd_pcm_hardware *hw = rule->private; -+#if 0 - return snd_interval_list(hw_param_interval(params, rule->var), - snd_pcm_known_rates.count, - snd_pcm_known_rates.list, hw->rates); -+#else -+ //printk("hw->rates=0x%08x\n",hw->rates);//0x3b6 -+ hw->rates = 0x3fe;//12KHz and 24KHz bits are all zero,you need set 1 -+ return snd_interval_list(hw_param_interval(params, rule->var), -+ snd_pcm_known_rates.count, -+ snd_pcm_known_rates.list, hw->rates); -+#endif - } - - static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, -diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig -index bcf2a06..558e4aa 100644 ---- a/sound/oss/Kconfig -+++ b/sound/oss/Kconfig -@@ -5,6 +5,91 @@ - # - # Prompt user for primary drivers. - -+config OSS_OBSOLETE -+ bool "Obsolete OSS drivers" -+ depends on SOUND_PRIME -+ help -+ This option enables support for obsolete OSS drivers that -+ are scheduled for removal in the near future. -+ -+ Please contact Adrian Bunk if you had to -+ say Y here because your hardware is not properly supported -+ by ALSA. -+ -+ If unsure, say N. -+ -+config SOUND_JZ_AC97 -+ bool "Jz On-Chip AC97 driver" -+ depends on OSS_OBSOLETE -+ help -+ Say Y here if you have want to select the on-chip AC97 driver -+ on Jz4730/Jz4740/Jz5730. -+ -+config SOUND_JZ_I2S -+ bool "Jz On-Chip I2S driver" -+ depends on OSS_OBSOLETE -+ help -+ Say Y here if you have want to select the on-chip I2S driver -+ on Jz4730/Jz4740/Jz5730. -+ -+config SOUND_JZ_PCM -+ bool "Jz On-Chip PCM driver" -+ depends on SOC_JZ4750 -+ help -+ Say Y here if you have want to select the on-chip PCM driver -+ on Jz4750. -+ -+choice -+ prompt "I2S codec type" -+ depends on SOUND_JZ_I2S -+ -+config I2S_AK4642EN -+ bool "AK4642EN" -+ depends on SOC_JZ4730 -+ help -+ Answer Y if you have an external AK4642EN codec. -+ -+config I2S_ICODEC -+ bool "Internal On-Chip codec" -+ depends on SOC_JZ4740 -+ help -+ Answer Y if you have an internal I2S codec. -+ -+config I2S_DLV -+ bool "Internal On-Chip codec on Jz4750 or Jz4750d" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ Answer Y if you have an internal I2S codec on Jz4750 or Jz4750d. -+ -+endchoice -+ -+choice -+ prompt "PCM codec type" -+ depends on SOUND_JZ_PCM -+ -+config PCM_TLV320AIC1106 -+ bool "TLV320AIC1106" -+ help -+ Answer Y if you have an TI tlv320aic 1106 codec. -+ -+endchoice -+ -+config SOUND_BT878 -+ tristate "BT878 audio dma" -+ depends on SOUND_PRIME && PCI && OSS_OBSOLETE -+ ---help--- -+ Audio DMA support for bt878 based grabber boards. As you might have -+ already noticed, bt878 is listed with two functions in /proc/pci. -+ Function 0 does the video stuff (bt848 compatible), function 1 does -+ the same for audio data. This is a driver for the audio part of -+ the chip. If you say 'Y' here you get a oss-compatible dsp device -+ where you can record from. If you want just watch TV you probably -+ don't need this driver as most TV cards handle sound with a short -+ cable from the TV card to your sound card's line-in. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called btaudio. -+ - config SOUND_BCM_CS4297A - tristate "Crystal Sound CS4297a (for Swarm)" - depends on SIBYTE_SWARM -@@ -15,6 +100,13 @@ config SOUND_BCM_CS4297A - note that CONFIG_KGDB should not be enabled at the same - time, since it also attempts to use this UART port. - -+config SOUND_ICH -+ tristate "Intel ICH (i8xx) audio support" -+ depends on SOUND_PRIME && PCI && OSS_OBSOLETE -+ help -+ Support for integral audio in Intel's I/O Controller Hub (ICH) -+ chipset, as used on the 810/820/840 motherboards. -+ - config SOUND_VWSND - tristate "SGI Visual Workstation Sound" - depends on X86_VISWS -@@ -24,6 +116,14 @@ config SOUND_VWSND - for more info on this driver's - capabilities. - -+config SOUND_VRC5477 -+ tristate "NEC Vrc5477 AC97 sound" -+ depends on SOUND_PRIME && DDB5477 -+ help -+ Say Y here to enable sound support for the NEC Vrc5477 chip, an -+ integrated, multi-function controller chip for MIPS CPUs. Works -+ with the AC97 codec. -+ - config SOUND_AU1550_AC97 - tristate "Au1550/Au1200 AC97 Sound" - depends on SOC_AU1550 || SOC_AU1200 -@@ -503,7 +603,7 @@ config SOUND_AEDSP16 - questions. - - Read the file and the head of -- as well as -+ as well as - to get more information - about this driver and its configuration. - -@@ -553,6 +653,13 @@ config SOUND_WAVEARTIST - Say Y here to include support for the Rockwell WaveArtist sound - system. This driver is mainly for the NetWinder. - -+config SOUND_TVMIXER -+ tristate "TV card (bt848) mixer support" -+ depends on SOUND_PRIME && I2C && VIDEO_V4L1 && OSS_OBSOLETE -+ help -+ Support for audio mixer facilities on the BT848 TV frame-grabber -+ card. -+ - config SOUND_KAHLUA - tristate "XpressAudio Sound Blaster emulation" - depends on SOUND_SB -diff --git a/sound/oss/Makefile b/sound/oss/Makefile -index e0ae4d4..37d5233 100644 ---- a/sound/oss/Makefile -+++ b/sound/oss/Makefile -@@ -9,6 +9,12 @@ obj-$(CONFIG_SOUND_OSS) += sound.o - - # Please leave it as is, cause the link order is significant ! - -+obj-$(CONFIG_SOUND_JZ_AC97) += jz_ac97.o ac97_codec.o -+obj-$(CONFIG_I2S_AK4642EN) += ak4642en.o -+obj-$(CONFIG_I2S_ICODEC) += jzcodec.o jz_i2s.o -+obj-$(CONFIG_I2S_DLV) += jzdlv.o jz_i2s.o -+obj-$(CONFIG_SOUND_JZ_PCM) += jz_pcm_tlv320aic1106_dma.o -+ - obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o - obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o - obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o -diff --git a/sound/oss/ak4642en.c b/sound/oss/ak4642en.c -new file mode 100644 -index 0000000..b649a7e ---- /dev/null -+++ b/sound/oss/ak4642en.c -@@ -0,0 +1,712 @@ -+/* -+ * linux/sound/oss/ak4642en.c -+ * -+ * AKM ak4642en codec chip driver to I2S interface -+ * -+ * Copyright (c) 2005-2007 Ingenic Semiconductor Inc. -+ * Author: -+ * -+ * 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. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sound_config.h" -+ -+extern mixer_info info; -+extern _old_mixer_info old_info; -+extern int abnormal_data_count; -+ -+extern void (*clear_codec_mode)(void); -+extern void (*set_codec_gpio_pin)(void); -+extern void (*each_time_init_codec)(void); -+extern void (*set_codec_record)(void); -+extern void (*set_codec_replay)(void); -+extern void (*clear_codec_record)(void); -+extern void (*clear_codec_replay)(void); -+extern void (*set_codec_speed)(int range); -+extern void (*codec_mixer_old_info_id_name)(void); -+extern void (*codec_mixer_info_id_name)(void); -+extern void (*set_codec_volume)(int val); -+extern void (*set_codec_mic)(int val); -+extern void (*i2s_resume_codec)(void); -+extern void (*i2s_suspend_codec)(int wr,int rd); -+extern void (*set_replay_hp_or_speaker)(void); -+ -+#define I2S_PDN 68 -+#define JACK_PLUG_PIN 83 -+#define JACK_PLUG_IRQ (IRQ_GPIO_0 + JACK_PLUG_PIN) -+ -+static int jack_plug_level, old_level; -+static unsigned int i2c_addr = 0x26; //AK4642EN device address at I2C bus -+static unsigned int i2c_clk = 100000;//AK4642EN 400kHz max,but 100kHz here -+static unsigned int spk_hp = 0; -+static int codec_volume; -+ -+void set_ak4642en_gpio_pin(void); -+void each_time_init_ak4642en(void); -+void set_ak4642en_replay(void); -+void set_ak4642en_record(void); -+void turn_on_ak4642en(void); -+void turn_off_ak4642en(void); -+void set_ak4642en_speed(int rate); -+void reset_ak4642en(void); -+void ak4642en_mixer_old_info_id_name(void); -+void ak4642en_mixer_info_id_name(void); -+void set_ak4642en_bass(int val); -+void set_ak4642en_volume(int val); -+void set_ak4642en_mic(int val); -+void resume_ak4642en(void); -+void suspend_ak4642en(int wr,int rd); -+ -+static void write_reg(u8 reg, u8 val) -+{ -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_write((i2c_addr >> 1), &val, reg, 1); -+ i2c_close(); -+} -+ -+#if 0 -+static u8 read_reg(u8 reg) -+{ -+ u8 val; -+ i2c_open(); -+ i2c_setclk(i2c_clk); -+ i2c_read((i2c_addr >> 1), &val, reg, 1); -+ i2c_close(); -+ return val; -+} -+ -+static u16 i2s_codec_read(u8 reg) -+{ -+ u16 value; -+ value = read_reg(reg); -+ return value; -+} -+#endif -+ -+static void i2s_codec_write(u8 reg, u16 data) -+{ -+ u8 val = data & 0xff; -+ write_reg(reg, val); -+} -+ -+void set_ak4642en_gpio_pin(void) -+{ -+ //set AIC pin to I2S slave mode,only GPIO70,71,77,78 -+ __gpio_as_output(68); -+ __gpio_clear_pin(68); -+ __gpio_as_output(69); -+ __gpio_clear_pin(69); -+ __gpio_as_output(70); -+ __gpio_clear_pin(70); -+ __gpio_as_input(71); -+ __gpio_clear_pin(71); -+ __gpio_as_input(77); -+ __gpio_clear_pin(77); -+ __gpio_as_input(78); -+ __gpio_clear_pin(78); -+ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; -+ REG_GPIO_GPALR(2) |= 0x14005000; -+ //set SCC clock initialization -+ REG_SCC1_CR(SCC1_BASE) = 0x00000000; -+ udelay(2); -+ REG_SCC1_CR(SCC1_BASE) |= 1 << 31; -+ udelay(2); -+ -+ __gpio_as_output(I2S_PDN); -+ __gpio_set_pin(I2S_PDN); -+ udelay(5); -+ __gpio_clear_pin(I2S_PDN); -+ ndelay(300);//>150ns -+ __gpio_set_pin(I2S_PDN); -+ mdelay(1); -+ //set PLL Master mode -+ i2s_codec_write(0x01, 0x0008);//master -+ i2s_codec_write(0x04, 0x006b);//ref:12MHz;BITCLK:64fs;I2S compli -+ i2s_codec_write(0x05, 0x000b);//sync:48KHz; -+ i2s_codec_write(0x00, 0x0040);//PMVCM -+ i2s_codec_write(0x01, 0x0009);//master,PLL enable -+ mdelay(40); -+ jack_plug_level = 10; -+ old_level = 100; -+ spk_hp = 0; -+ __gpio_disable_pull(JACK_PLUG_PIN); -+ udelay(10); -+ __gpio_as_input(JACK_PLUG_PIN); -+ jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); -+ //i suppose jack_plug_lvel is 1 indicate with HPO -+ if (jack_plug_level > 1 || jack_plug_level <0) -+ printk("Audio ak4642en codec Jack plug level is wrong!\n"); -+ if (jack_plug_level) -+ __gpio_as_irq_fall_edge(JACK_PLUG_PIN); -+ else -+ __gpio_as_irq_rise_edge(JACK_PLUG_PIN); -+} -+ -+void clear_ak4642en_mode(void) -+{ -+ spk_hp = 0; -+ i2s_codec_write(0x01, 0x0008);//master,PLL disable -+ //free_irq(JACK_PLUG_IRQ, i2s_controller); -+ __gpio_clear_pin(I2S_PDN); -+ udelay(2); -+ REG_SCC1_CR(SCC1_BASE) &= 0 << 31; -+ udelay(2); -+} -+ -+void set_ak4642en_replay(void) -+{ -+ //for poll -+ /*jack_plug_level is H for SPK,is L for HP*/ -+ jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); -+ if(old_level == jack_plug_level) -+ return; -+ old_level = jack_plug_level; -+ if(spk_hp == 1) -+ { -+ if(jack_plug_level == 1) -+ { -+ //now HeadPhone output,so clear SPK -+ i2s_codec_write(0x02, 0x0020); -+ i2s_codec_write(0x02, 0x0000); -+ i2s_codec_write(0x00, 0x0040); -+ } -+ else -+ { -+ //now Speaker output,so clear HP -+ i2s_codec_write(0x01, 0x0039); -+ i2s_codec_write(0x01, 0x0009); -+ i2s_codec_write(0x00, 0x0040); -+ i2s_codec_write(0x0e, 0x0000); -+ i2s_codec_write(0x0f, 0x0008); -+ } -+ } -+ spk_hp = 1; -+ if(jack_plug_level == 1) -+ { -+ //for HeadPhone output -+ i2s_codec_write(0x00, 0x0060); // -+ i2s_codec_write(0x0f, 0x0009); //5-10 -+ -+ i2s_codec_write(0x00, 0x0064); // -+ i2s_codec_write(0x09, 0x0091);// volume control 0dB -+ i2s_codec_write(0x0c, 0x0091);// 0dB(right) -+ //eq off -+ i2s_codec_write(0x11, 0x0000);//5-10 -+ i2s_codec_write(0x01, 0x0039); // -+ -+ i2s_codec_write(0x01, 0x0079); // -+ } -+ else -+ { -+ //for Speaker output -+ i2s_codec_write(0x00, 0x0040); -+ i2s_codec_write(0x02, 0x0020); -+ -+ i2s_codec_write(0x03, 0x0018);//5-10 -+ i2s_codec_write(0x06, 0x003c); -+ -+ i2s_codec_write(0x08, 0x00A1);//5-10 -+ -+ i2s_codec_write(0x0b, 0x0040); //5-10 -+ -+ i2s_codec_write(0x07, 0x002d); //5-10 -+ i2s_codec_write(0x09, 0x0091); -+ i2s_codec_write(0x0c, 0x0091); -+ //HP volume output value -+ -+ i2s_codec_write(0x0a, codec_volume);//5-10 -+ i2s_codec_write(0x0d, codec_volume);//5-10 -+ -+ i2s_codec_write(0x00, 0x0074); -+ i2s_codec_write(0x02, 0x00a0); -+ } -+} -+ -+void set_ak4642en_record(void) -+{ -+ abnormal_data_count = 0; -+ i2s_codec_write(0x02, 0x0004); -+ i2s_codec_write(0x03, 0x0038);// recording volume add -+ i2s_codec_write(0x06, 0x0000);//for ALC short waiting time -+ i2s_codec_write(0x08, 0x00e1); -+ i2s_codec_write(0x0b, 0x0000); -+ i2s_codec_write(0x07, 0x0021); // ALC on -+ -+ i2s_codec_write(0x10, 0x0000);//0x0001 -+ //i2s_codec_write(0x10, 0x0001);//0x0001 -+ i2s_codec_write(0x01, 0x0039); //for open pop noise -+ i2s_codec_write(0x01, 0x0079); -+ i2s_codec_write(0x00, 0x0065); -+ mdelay(300); -+} -+ -+void clear_ak4642en_replay(void) -+{ -+ //for poll -+ old_level = 100; -+ spk_hp = 0; -+ if(jack_plug_level == 1) -+ { -+ //for HeadPhone output -+ i2s_codec_write(0x01, 0x0039); // for close pop noise -+ mdelay(300); -+ i2s_codec_write(0x01, 0x0009); //PLL on I2S -+ i2s_codec_write(0x07, 0x0001); -+ i2s_codec_write(0x11, 0x0000); -+ i2s_codec_write(0x00, 0x0040); -+ i2s_codec_write(0x0f, 0x0008); // for open pop noise -+ } -+ else -+ { -+ //for Speaker output -+ i2s_codec_write(0x02, 0x0020); -+ i2s_codec_write(0x07, 0x0001); -+ i2s_codec_write(0x11, 0x0000); -+ i2s_codec_write(0x02, 0x0000); -+ i2s_codec_write(0x00, 0x0040); // for close pop noise -+ } -+} -+ -+void clear_ak4642en_record(void) -+{ -+ //for Mic input(Stereo) -+ i2s_codec_write(0x02, 0x0001); -+ i2s_codec_write(0x07, 0x0001); -+ i2s_codec_write(0x11, 0x0000); -+} -+ -+void each_time_init_ak4642en(void) -+{ -+ __i2s_disable(); -+ __i2s_as_slave(); -+ __i2s_set_sample_size(16); -+} -+ -+void set_ak4642en_speed(int rate) -+{ -+ //codec work at frequency -+ unsigned short speed = 0; -+ unsigned short val = 0; -+ switch (rate) -+ { -+ case 8000: -+ speed = 0x00; -+ if(jack_plug_level == 1) //speaker -+ { -+ i2s_codec_write(0x16, 0x0000); -+ i2s_codec_write(0x17, 0x0000); -+ i2s_codec_write(0x18, 0x0000); -+ i2s_codec_write(0x19, 0x0000); -+ i2s_codec_write(0x1A, 0x0000); -+ i2s_codec_write(0x1B, 0x0000); -+ i2s_codec_write(0x1C, 0x0027);//800hz -+ i2s_codec_write(0x1D, 0x0018); -+ i2s_codec_write(0x1E, 0x00b2); -+ i2s_codec_write(0x1F, 0x002f); -+ i2s_codec_write(0x11, 0x0010); //eq on -+ } -+ break; -+ case 12000: -+ speed = 0x01; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0000); -+ i2s_codec_write(0x17, 0x0000); -+ i2s_codec_write(0x18, 0x0000); -+ i2s_codec_write(0x19, 0x0000); -+ i2s_codec_write(0x1A, 0x0000); -+ i2s_codec_write(0x1B, 0x0000); -+ i2s_codec_write(0x1C, 0x0064); -+ i2s_codec_write(0x1D, 0x001a); -+ i2s_codec_write(0x1E, 0x0038); -+ i2s_codec_write(0x1F, 0x002b); -+ i2s_codec_write(0x11, 0x0010); //eq on -+ } -+ break; -+ case 16000: -+ speed = 0x02; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x00af); -+ i2s_codec_write(0x17, 0x0020); -+ i2s_codec_write(0x18, 0x0043); -+ i2s_codec_write(0x19, 0x001a); -+ i2s_codec_write(0x1A, 0x00af); -+ i2s_codec_write(0x1B, 0x0020); -+ i2s_codec_write(0x1C, 0x00a0); -+ i2s_codec_write(0x1D, 0x001b); -+ i2s_codec_write(0x1E, 0x00c0); -+ i2s_codec_write(0x1F, 0x0028); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 24000: -+ speed = 0x03; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0086); -+ i2s_codec_write(0x17, 0x0015); -+ i2s_codec_write(0x18, 0x005d); -+ i2s_codec_write(0x19, 0x0006); -+ i2s_codec_write(0x1A, 0x0086); -+ i2s_codec_write(0x1B, 0x0015); -+ i2s_codec_write(0x1C, 0x00f5); -+ i2s_codec_write(0x1D, 0x001c); -+ i2s_codec_write(0x1E, 0x0016); -+ i2s_codec_write(0x1F, 0x0026); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 7350: -+ speed = 0x04; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0000); -+ i2s_codec_write(0x17, 0x0000); -+ i2s_codec_write(0x18, 0x0000); -+ i2s_codec_write(0x19, 0x0000); -+ i2s_codec_write(0x1A, 0x0000); -+ i2s_codec_write(0x1B, 0x0000); -+ i2s_codec_write(0x1C, 0x0027); -+ i2s_codec_write(0x1D, 0x0018); -+ i2s_codec_write(0x1E, 0x00b2); -+ i2s_codec_write(0x1F, 0x002f); -+ i2s_codec_write(0x11, 0x0010); //eq on -+ } -+ break; -+ case 11025: -+ speed = 0x05; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0059); -+ i2s_codec_write(0x17, 0x000d); -+ i2s_codec_write(0x18, 0x00cb); -+ i2s_codec_write(0x19, 0x0037); -+ i2s_codec_write(0x1A, 0x0059); -+ i2s_codec_write(0x1B, 0x000d); -+ i2s_codec_write(0x1C, 0x0046); -+ i2s_codec_write(0x1D, 0x001e); -+ i2s_codec_write(0x1E, 0x0074); -+ i2s_codec_write(0x1F, 0x0023); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 14700: -+ speed = 0x06; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0000); -+ i2s_codec_write(0x17, 0x0000); -+ i2s_codec_write(0x18, 0x0000); -+ i2s_codec_write(0x19, 0x0000); -+ i2s_codec_write(0x1A, 0x0000); -+ i2s_codec_write(0x1B, 0x0000); -+ i2s_codec_write(0x1C, 0x004a); -+ i2s_codec_write(0x1D, 0x001b); -+ i2s_codec_write(0x1E, 0x006c); -+ i2s_codec_write(0x1F, 0x0029); -+ i2s_codec_write(0x11, 0x0010); //eq on -+ } -+ break; -+ case 22050: -+ speed = 0x07; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x002d); -+ i2s_codec_write(0x17, 0x0017); -+ i2s_codec_write(0x18, 0x0050); -+ i2s_codec_write(0x19, 0x0009); -+ i2s_codec_write(0x1A, 0x002d); -+ i2s_codec_write(0x1B, 0x0017); -+ i2s_codec_write(0x1C, 0x00d7); -+ i2s_codec_write(0x1D, 0x001c); -+ i2s_codec_write(0x1E, 0x0093); -+ i2s_codec_write(0x1F, 0x0026); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 32000: -+ speed = 0x0a; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0012); -+ i2s_codec_write(0x17, 0x0011); -+ i2s_codec_write(0x18, 0x006e); -+ i2s_codec_write(0x19, 0x003e); -+ i2s_codec_write(0x1A, 0x0012); -+ i2s_codec_write(0x1B, 0x0011); -+ i2s_codec_write(0x1C, 0x00aa); -+ i2s_codec_write(0x1D, 0x001d); -+ i2s_codec_write(0x1E, 0x00ab); -+ i2s_codec_write(0x1F, 0x0024); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 48000: -+ speed = 0x0b; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0082); -+ i2s_codec_write(0x17, 0x000c); -+ i2s_codec_write(0x18, 0x004b); -+ i2s_codec_write(0x19, 0x0036); -+ i2s_codec_write(0x1A, 0x0082); -+ i2s_codec_write(0x1B, 0x000c); -+ i2s_codec_write(0x1C, 0x0068); -+ i2s_codec_write(0x1D, 0x001e); -+ i2s_codec_write(0x1E, 0x0030); -+ i2s_codec_write(0x1F, 0x0023); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 29400: -+ speed = 0x0e; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x003d); -+ i2s_codec_write(0x17, 0x0012); -+ i2s_codec_write(0x18, 0x0083); -+ i2s_codec_write(0x19, 0x0000); -+ i2s_codec_write(0x1A, 0x003d); -+ i2s_codec_write(0x1B, 0x0012); -+ i2s_codec_write(0x1C, 0x0079); -+ i2s_codec_write(0x1D, 0x001d); -+ i2s_codec_write(0x1E, 0x000d); -+ i2s_codec_write(0x1F, 0x0025); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ case 44100: -+ speed = 0x0f; -+ if(jack_plug_level == 1) -+ { -+ i2s_codec_write(0x16, 0x0059); -+ i2s_codec_write(0x17, 0x000d); -+ i2s_codec_write(0x18, 0x00cb); -+ i2s_codec_write(0x19, 0x0037); -+ i2s_codec_write(0x1A, 0x0059); -+ i2s_codec_write(0x1B, 0x000d); -+ i2s_codec_write(0x1C, 0x0046); -+ i2s_codec_write(0x1D, 0x001e); -+ i2s_codec_write(0x1E, 0x0074); -+ i2s_codec_write(0x1F, 0x0023); -+ i2s_codec_write(0x11, 0x0018); //eq on -+ } -+ break; -+ default: -+ break; -+ } -+ val = speed & 0x08; -+ val = val << 2; -+ speed = speed & 0x07; -+ val = val | speed; -+ i2s_codec_write(0x05, val); -+} -+ -+void ak4642en_mixer_old_info_id_name(void) -+{ -+ strncpy(info.id, "AK4642EN", sizeof(info.id)); -+ strncpy(info.name,"AKM AK4642en codec", sizeof(info.name)); -+} -+ -+void ak4642en_mixer_info_id_name(void) -+{ -+ strncpy(old_info.id, "AK4642EN", sizeof(old_info.id)); -+ strncpy(old_info.name,"AKM AK4642en codec", sizeof(old_info.name)); -+} -+ -+void set_ak4642en_volume(int val) -+{ -+ if ( val == 0 ) -+ codec_volume = 255; -+ else if ( val > 1 && val <= 10) -+ codec_volume = 92; -+ else if ( val > 10 && val <= 20 ) -+ codec_volume = 67; -+ else if ( val > 20 && val <= 30 ) -+ codec_volume = 50; -+ else if ( val > 30 && val <= 40 ) -+ codec_volume = 40; -+ else if ( val > 40 && val <= 50 ) -+ codec_volume = 30; -+ else if ( val > 50 && val <= 60 ) -+ codec_volume = 22; -+ else if ( val > 60&& val <= 70 ) -+ codec_volume = 15; -+ else if ( val > 70 && val <= 80 ) -+ codec_volume = 8; -+ else if ( val > 80 && val <= 90 ) -+ codec_volume = 4; -+ else if ( val > 90 && val <= 100 ) -+ codec_volume = 2; -+ -+ i2s_codec_write(0x0a, codec_volume); -+ i2s_codec_write(0x0d, codec_volume); -+} -+ -+void set_ak4642en_mic(int val) -+{ -+ int mic_gain; -+ mic_gain = 241 * val /100; -+ i2s_codec_write(0x09, mic_gain); -+ i2s_codec_write(0x0c, mic_gain); -+} -+ -+void resume_ak4642en(void) -+{ -+ __gpio_as_output(17); -+ __gpio_set_pin(17); //enable ak4642 -+ __gpio_as_output(68); -+ __gpio_clear_pin(68); -+ __gpio_as_output(69); -+ __gpio_clear_pin(69); -+ __gpio_as_output(70); -+ __gpio_clear_pin(70); -+ __gpio_as_input(71); -+ __gpio_clear_pin(71); -+ __gpio_as_input(77); -+ __gpio_clear_pin(77); -+ __gpio_as_input(78); -+ __gpio_clear_pin(78); -+ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; -+ REG_GPIO_GPALR(2) |= 0x14005000; -+ //set SCC clock initialization -+ REG_SCC1_CR(SCC1_BASE) = 0x00000000; -+ udelay(2); -+ REG_SCC1_CR(SCC1_BASE) |= 1 << 31; -+ udelay(2); -+ __gpio_as_output(I2S_PDN); -+ __gpio_set_pin(I2S_PDN); -+ udelay(5); -+ __gpio_clear_pin(I2S_PDN); -+ ndelay(300);//>150ns -+ __gpio_set_pin(I2S_PDN); -+ mdelay(1); -+ //set PLL Master mode -+ i2s_codec_write(0x01, 0x0008);//master -+ i2s_codec_write(0x04, 0x006b);//ref:12MHz;BITCLK:64fs;I2S compli -+ i2s_codec_write(0x05, 0x000b);//sync:48KHz; -+ i2s_codec_write(0x00, 0x0040);//PMVCM -+ i2s_codec_write(0x01, 0x0009);//master,PLL enable -+ jack_plug_level = 10; -+ old_level = 100; -+ spk_hp = 0; -+ __gpio_as_input(JACK_PLUG_PIN); -+ jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); -+ //i suppose jack_plug_lvel is 1 indicate with HPO -+ if(jack_plug_level > 1 || jack_plug_level <0) -+ printk("Audio ak4642en codec Jack plug level is wrong!\n"); -+ if(jack_plug_level) -+ __gpio_as_irq_fall_edge(JACK_PLUG_PIN); -+ else -+ __gpio_as_irq_rise_edge(JACK_PLUG_PIN); -+ -+ i2s_codec_write(0x00, 0x0065); //for resume power -+ i2s_codec_write(0x01, 0x0039); //for open pop noise -+ i2s_codec_write(0x01, 0x0079); -+ i2s_codec_write(0x0a, codec_volume); -+ i2s_codec_write(0x0d, codec_volume); -+} -+ -+void suspend_ak4642en(int wr,int rd) -+{ -+ if(wr) //playing -+ { -+ if(jack_plug_level == 0) -+ { -+ i2s_codec_write(0x01, 0x0039); // for close pop noise -+ mdelay(500); -+ i2s_codec_write(0x01, 0x0009); //PLL on I2S -+ i2s_codec_write(0x07, 0x0001); -+ i2s_codec_write(0x11, 0x0000); -+ i2s_codec_write(0x00, 0x0040); -+ i2s_codec_write(0x0f, 0x0008); // for open pop noise -+ -+ } -+ else -+ { -+ //for Speaker output -+ i2s_codec_write(0x02, 0x0020); -+ i2s_codec_write(0x07, 0x0001); -+ i2s_codec_write(0x11, 0x0000); -+ i2s_codec_write(0x02, 0x0000); -+ i2s_codec_write(0x00, 0x0040); // for close pop noise -+ } -+ } -+ -+ if(rd) // recording -+ { -+ i2s_codec_write(0x02, 0x0001); // 5-11 a1 -+ i2s_codec_write(0x07, 0x0001); -+ i2s_codec_write(0x11, 0x0000); -+ mdelay(300); -+ } -+ __gpio_as_output(17); -+ __gpio_clear_pin(17);//disable ak4642 -+ __i2s_disable(); -+} -+ -+static int __init init_ak4642en(void) -+{ -+ set_codec_gpio_pin = set_ak4642en_gpio_pin; -+ each_time_init_codec = each_time_init_ak4642en; -+ clear_codec_mode = clear_ak4642en_mode; -+ -+ set_codec_record = set_ak4642en_record; -+ set_codec_replay = set_ak4642en_replay; -+ set_replay_hp_or_speaker = set_ak4642en_replay; -+ -+ set_codec_speed = set_ak4642en_speed; -+ clear_codec_record = clear_ak4642en_record; -+ clear_codec_replay = clear_ak4642en_replay; -+ -+ codec_mixer_old_info_id_name = ak4642en_mixer_old_info_id_name; -+ codec_mixer_info_id_name = ak4642en_mixer_info_id_name; -+ -+ set_codec_volume = set_ak4642en_volume; -+ -+ set_codec_mic = set_ak4642en_mic; -+ -+ i2s_resume_codec = resume_ak4642en; -+ i2s_suspend_codec = suspend_ak4642en; -+ printk("---> ak4642en initialization!\n"); -+ return 0; -+} -+ -+static void __exit cleanup_ak4642en(void) -+{ -+ spk_hp = 0; -+ i2s_codec_write(0x01, 0x0008);//master,PLL disable -+ //free_irq(JACK_PLUG_IRQ, i2s_controller); -+ __gpio_clear_pin(I2S_PDN); -+ udelay(2); -+ REG_SCC1_CR(SCC1_BASE) &= 0 << 31; -+ udelay(2); -+} -+ -+module_init(init_ak4642en); -+module_exit(cleanup_ak4642en); -diff --git a/sound/oss/jz_ac97.c b/sound/oss/jz_ac97.c -new file mode 100644 -index 0000000..698a003 ---- /dev/null -+++ b/sound/oss/jz_ac97.c -@@ -0,0 +1,2252 @@ -+/* -+ * linux/drivers/sound/jz_ac97.c -+ * -+ * Jz On-Chip AC97 audio driver. -+ * -+ * Copyright (C) 2005 - 2007, Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ * -+ */ -+ -+#define __NO_VERSION__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+//#include -+#include "sound_config.h" -+ -+#define DMA_ID_AC97_TX DMA_ID_AIC_TX -+#define DMA_ID_AC97_RX DMA_ID_AIC_RX -+ -+/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ -+#define NR_AC97 2 -+ -+#define STANDARD_SPEED 48000 -+#define MAX_RETRY 100 -+ -+static unsigned int k_8000[] = { -+ 0, 42, 85, 128, 170, 213, -+}; -+ -+static unsigned int reload_8000[] = { -+ 1, 0, 0, 0, 0, 0, -+}; -+ -+static unsigned int k_11025[] = { -+ 0, 58, 117, 176, 234, 37, 96, 154, -+ 213, 16, 74, 133, 192, 250, 53, 112, -+ 170, 229, 32, 90, 149, 208, 10, 69, -+ 128, 186, 245, 48, 106, 165, 224, 26, -+ 85, 144, 202, 5, 64, 122, 181, 240, -+ 42, 101, 160, 218, 21, 80, 138, 197, -+}; -+ -+static unsigned int reload_11025[] = { -+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, -+ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -+}; -+ -+static unsigned int k_16000[] = { -+ 0, 85, 170, -+}; -+ -+static unsigned int reload_16000[] = { -+ 1, 0, 0, -+}; -+ -+static unsigned int k_22050[] = { -+ 0, 117, 234, 96, 213, 74, 192, 53, -+ 170, 32, 149, 10, 128, 245, 106, 224, -+ 85, 202, 64, 181, 42, 160, 21, 138, -+}; -+ -+static unsigned int reload_22050[] = { -+ 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, -+ 1, 0, 1, 0, 1, 0, 1, 0, -+}; -+ -+static unsigned int k_24000[] = { -+ 0, 128, -+}; -+ -+static unsigned int reload_24000[] = { -+ 1, 0, -+}; -+ -+static unsigned int k_32000[] = { -+ 0, 170, 85, -+}; -+ -+static unsigned int reload_32000[] = { -+ 1, 0, 1, -+}; -+ -+static unsigned int k_44100[] = { -+ 0, 234, 213, 192, 170, 149, 128, 106, -+ 85, 64, 42, 21, -+}; -+ -+static unsigned int reload_44100[] = { -+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+}; -+ -+static unsigned int k_48000[] = { -+ 0, -+}; -+ -+static unsigned int reload_48000[] = { -+ 1, -+}; -+ -+ -+static unsigned int f_scale_counts[8] = { -+ 6, 48, 3, 24, 2, 3, 12, 1, -+}; -+ -+static int jz_audio_rate; -+static char jz_audio_format; -+static char jz_audio_channels; -+static int jz_audio_k; /* rate expand multiple */ -+static int jz_audio_q; /* rate expand compensate */ -+static int jz_audio_count; /* total count of voice data */ -+static int last_jz_audio_count; -+ -+static int jz_audio_fragments;//unused fragment amount -+static int jz_audio_fragstotal; -+static int jz_audio_fragsize; -+static int jz_audio_dma_tran_count;//bytes count of one DMA transfer -+ -+static unsigned int f_scale_count; -+static unsigned int *f_scale_array; -+static unsigned int *f_scale_reload; -+static unsigned int f_scale_idx; -+ -+static void (*old_mksound)(unsigned int hz, unsigned int ticks); -+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -+extern void jz_set_dma_block_size(int dmanr, int nbyte); -+extern void jz_set_dma_dest_width(int dmanr, int nbit); -+extern void jz_set_dma_src_width(int dmanr, int nbit); -+ -+static void jz_update_filler(int bits, int channels); -+ -+static void Init_In_Out_queue(int fragstotal,int fragsize); -+static void Free_In_Out_queue(int fragstotal,int fragsize); -+ -+static irqreturn_t -+jz_ac97_replay_dma_irq(int irqnr, void *dev_id); -+static irqreturn_t -+jz_ac97_record_dma_irq(int irqnr, void *dev_id); -+ -+static void -+(*replay_filler)(unsigned long src_start, int count, int id); -+static int -+(*record_filler)(unsigned long dst_start, int count, int id); -+ -+static struct file_operations jz_ac97_audio_fops; -+ -+DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -+DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -+ -+struct jz_ac97_controller_info -+{ -+ int io_base; -+ int dma1; /* play */ -+ int dma2; /* record */ -+ -+ char *name; -+ -+ int dev_audio; -+ struct ac97_codec *ac97_codec[NR_AC97]; -+ -+ unsigned short ac97_features; -+ -+ int opened1; -+ int opened2; -+ -+ unsigned char *tmp1; /* tmp buffer for sample conversions */ -+ unsigned char *tmp2; -+ -+ spinlock_t lock; -+ spinlock_t ioctllock; -+ wait_queue_head_t dac_wait; -+ wait_queue_head_t adc_wait; -+ -+ int nextIn; // byte index to next-in to DMA buffer -+ int nextOut; // byte index to next-out from DMA buffer -+ int count; // current byte count in DMA buffer -+ int finish; // current transfered byte count in DMA buffer -+ unsigned total_bytes; // total bytes written or read -+ unsigned blocks; -+ unsigned error; // over/underrun -+ -+ /* We use two devices, because we can do simultaneous play and record. -+ This keeps track of which device is being used for what purpose; -+ these are the actual device numbers. */ -+ int dev_for_play; -+ int dev_for_record; -+ -+ int playing; -+ int recording; -+ int patched; -+ unsigned long rec_buf_size; -+ unsigned long playback_buf_size; -+ -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+static struct jz_ac97_controller_info *ac97_controller = NULL; -+ -+static int jz_readAC97Reg(struct ac97_codec *dev, u8 reg); -+static int jz_writeAC97Reg(struct ac97_codec *dev, u8 reg, u16 data); -+static u16 ac97_codec_read(struct ac97_codec *codec, u8 reg); -+static void ac97_codec_write(struct ac97_codec *codec, u8 reg, u16 data); -+ -+#define QUEUE_MAX 2 -+ -+typedef struct buffer_queue_s { -+ int count; -+ int *id; -+ spinlock_t lock; -+} buffer_queue_t; -+ -+static unsigned long *out_dma_buf = NULL; -+static unsigned long *out_dma_pbuf = NULL; -+static unsigned long *out_dma_buf_data_count = NULL; -+static unsigned long *in_dma_buf = NULL; -+static unsigned long *in_dma_pbuf = NULL; -+static unsigned long *in_dma_buf_data_count = NULL; -+ -+static buffer_queue_t out_empty_queue; -+static buffer_queue_t out_full_queue; -+static buffer_queue_t out_busy_queue; -+ -+static buffer_queue_t in_empty_queue; -+static buffer_queue_t in_full_queue; -+static buffer_queue_t in_busy_queue; -+ -+static int first_record_call = 0; -+ -+static inline int get_buffer_id(struct buffer_queue_s *q) -+{ -+ int r, i; -+ unsigned long flags; -+ spin_lock_irqsave(&q->lock, flags); -+ if (q->count == 0) { -+ spin_unlock_irqrestore(&q->lock, flags); -+ return -1; -+ } -+ r = *(q->id + 0); -+ for (i=0;i < q->count-1;i++) -+ *(q->id + i) = *(q->id + (i+1)); -+ q->count --; -+ spin_unlock_irqrestore(&q->lock, flags); -+ return r; -+} -+ -+static inline void put_buffer_id(struct buffer_queue_s *q, int id) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&q->lock, flags); -+ *(q->id + q->count) = id; -+ q->count ++; -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+ -+static inline int elements_in_queue(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ spin_lock_irqsave(&q->lock, flags); -+ r = q->count; -+ spin_unlock_irqrestore(&q->lock, flags); -+ return r; -+} -+ -+/**************************************************************************** -+ * Architecture related routines -+ ****************************************************************************/ -+static inline -+void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -+{ -+ unsigned long flags; -+ struct jz_ac97_controller_info * controller = -+ (struct jz_ac97_controller_info *) dev_id; -+ //for DSP_GETOPTR -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_dma_tran_count = count; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ set_dma_mode(chan, mode); -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) { -+ count++; -+ printk(KERN_DEBUG "%s: JzSOC DMA controller can't set dma count zero!\n", -+ __FUNCTION__); -+ } -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ release_dma_lock(flags); -+} -+ -+static irqreturn_t -+jz_ac97_record_dma_irq (int irq, void *dev_id) -+{ -+ struct jz_ac97_controller_info * controller = -+ (struct jz_ac97_controller_info *) dev_id; -+ int dma = controller->dma2; -+ int id1, id2; -+ unsigned long flags; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ //for DSP_GETIPTR -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id2); -+ -+ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -+ audio_start_dma(dma,dev_id, -+ *(in_dma_pbuf + id2), -+ *(in_dma_buf_data_count + id2), -+ DMA_MODE_READ); -+ } else { -+ in_busy_queue.count = 0; -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t -+jz_ac97_replay_dma_irq (int irq, void *dev_id) -+{ -+ struct jz_ac97_controller_info * controller = -+ (struct jz_ac97_controller_info *) dev_id; -+ int dma = controller->dma1, id; -+ unsigned long flags; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ //for DSP_GETOPTR -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if ((id = get_buffer_id(&out_busy_queue)) < 0) { -+ printk(KERN_DEBUG "Strange DMA finish interrupt for AC97 module\n"); -+ } -+ -+ put_buffer_id(&out_empty_queue, id); -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ } -+ } else { -+ out_busy_queue.count = 0; -+ } -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+/* -+ * Initialize the onchip AC97 controller -+ */ -+static void jz_ac97_initHw(struct jz_ac97_controller_info *controller) -+{ -+ __ac97_disable(); -+ __ac97_reset(); -+ __ac97_enable(); -+ -+ __ac97_cold_reset_codec(); -+ /* wait for a long time to let ac97 controller reset completely, -+ * otherwise, registers except ACFR will be clear by reset, can't be -+ * set correctly. -+ */ -+ udelay(160); -+ -+ __ac97_disable_record(); -+ __ac97_disable_replay(); -+ __ac97_disable_loopback(); -+ -+ /* Check the trigger threshold reset value to detect version */ -+ if (((REG_AIC_FR & AIC_FR_TFTH_MASK) >> AIC_FR_TFTH_BIT) == 8) { -+ printk("JzAC97: patched controller detected.\n"); -+ controller->patched = 1; -+ } else { -+ printk("JzAC97: standard controller detected.\n"); -+ controller->patched = 0; -+ } -+ -+ /* Set FIFO data size. Which shows valid data bits. -+ * -+ */ -+ __ac97_set_oass(8); -+ __ac97_set_iass(8); -+ -+ __ac97_set_xs_stereo(); -+ __ac97_set_rs_stereo(); -+} -+ -+/* -+ * Initialize all of in(out)_empty_queue value -+ */ -+static void Init_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ if(out_dma_buf || in_dma_buf) -+ return; -+ in_empty_queue.count = fragstotal; -+ out_empty_queue.count = fragstotal; -+ -+ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf) -+ goto all_mem_err; -+ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_pbuf) -+ goto all_mem_err; -+ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf_data_count) -+ goto all_mem_err; -+ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf) -+ goto all_mem_err; -+ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_pbuf) -+ goto all_mem_err; -+ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf_data_count) -+ goto all_mem_err; -+ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_empty_queue.id) -+ goto all_mem_err; -+ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_full_queue.id) -+ goto all_mem_err; -+ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_busy_queue.id) -+ goto all_mem_err; -+ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_empty_queue.id) -+ goto all_mem_err; -+ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_full_queue.id) -+ goto all_mem_err; -+ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_busy_queue.id) -+ goto all_mem_err; -+ -+ for (i=0;i < fragstotal;i++) { -+ *(in_empty_queue.id + i) = i; -+ *(out_empty_queue.id + i) = i; -+ } -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /*alloc DMA buffer*/ -+ for (i = 0; i < jz_audio_fragstotal; i++) { -+ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(out_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(OUT) buffers.\n"); -+ goto mem_failed_out; -+ } -+ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -+ } -+ -+ for (i = 0; i < jz_audio_fragstotal; i++) { -+ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(in_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(IN) buffers.\n"); -+ goto mem_failed_in; -+ } -+ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -+ dma_cache_wback_inv(*(in_dma_buf + i), 4096*8);//fragsize -+ *(in_dma_buf + i) = KSEG1ADDR(*(in_dma_buf + i)); -+ } -+ return ; -+ -+ all_mem_err: -+ printk("error:allocate memory occur error!\n"); -+ return ; -+ -+mem_failed_out: -+ -+ for (i = 0; i < jz_audio_fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ } -+ return ; -+ -+mem_failed_in: -+ -+ for (i = 0; i < jz_audio_fragstotal; i++) { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ return ; -+ -+} -+static void Free_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ if(out_dma_buf != NULL) -+ { -+ for (i = 0; i < jz_audio_fragstotal; i++) -+ { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ *(out_dma_buf + i) = 0; -+ } -+ kfree(out_dma_buf); -+ out_dma_buf = NULL; -+ } -+ if(out_dma_pbuf) -+ { -+ kfree(out_dma_pbuf); -+ out_dma_pbuf = NULL; -+ } -+ if(out_dma_buf_data_count) -+ { -+ kfree(out_dma_buf_data_count); -+ out_dma_buf_data_count = NULL; -+ } -+ if(in_dma_buf) -+ { -+ for (i = 0; i < jz_audio_fragstotal; i++) -+ { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ *(in_dma_buf + i) = 0; -+ } -+ kfree(in_dma_buf); -+ in_dma_buf = NULL; -+ } -+ if(in_dma_pbuf) -+ { -+ kfree(in_dma_pbuf); -+ in_dma_pbuf = NULL; -+ } -+ if(in_dma_buf_data_count) -+ { -+ kfree(in_dma_buf_data_count); -+ in_dma_buf_data_count = NULL; -+ } -+ if(in_empty_queue.id) -+ { -+ kfree(in_empty_queue.id); -+ in_empty_queue.id = NULL; -+ } -+ if(in_full_queue.id) -+ { -+ kfree(in_full_queue.id); -+ in_full_queue.id = NULL; -+ } -+ if(in_busy_queue.id) -+ { -+ kfree(in_busy_queue.id); -+ in_busy_queue.id = NULL; -+ } -+ if(out_empty_queue.id) -+ { -+ kfree(out_empty_queue.id); -+ out_empty_queue.id = NULL; -+ } -+ if(out_full_queue.id) -+ { -+ kfree(out_full_queue.id); -+ out_full_queue.id = NULL; -+ } -+ if(out_busy_queue.id) -+ { -+ kfree(out_busy_queue.id); -+ out_busy_queue.id = NULL; -+ } -+ -+ in_empty_queue.count = fragstotal; -+ out_empty_queue.count = fragstotal; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ return ; -+} -+ -+/* -+ * Reset everything -+ */ -+static void -+jz_ac97_full_reset(struct jz_ac97_controller_info *controller) -+{ -+ jz_ac97_initHw(controller); -+} -+ -+ -+static void -+jz_ac97_mksound(unsigned int hz, unsigned int ticks) -+{ -+// printk("BEEP - %d %d!\n", hz, ticks); -+} -+ -+static int jz_audio_set_speed(int dev, int rate) -+{ -+ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -+ u32 dacp; -+ struct ac97_codec *codec=ac97_controller->ac97_codec[0]; -+ -+ if (rate > 48000) -+ rate = 48000; -+ if (rate < 8000) -+ rate = 8000; -+ -+ -+ /* Power down the DAC */ -+ dacp=ac97_codec_read(codec, AC97_POWER_CONTROL); -+ ac97_codec_write(codec, AC97_POWER_CONTROL, dacp|0x0200); -+ /* Load the rate; only 48Khz playback available, read always zero */ -+ if ((ac97_controller->patched) && (ac97_controller->ac97_features & 1)) -+ ac97_codec_write(codec, AC97_PCM_FRONT_DAC_RATE, rate); -+ else -+ ac97_codec_write(codec, AC97_PCM_FRONT_DAC_RATE, 48000); -+ -+ /* Power it back up */ -+ ac97_codec_write(codec, AC97_POWER_CONTROL, dacp); -+ -+ jz_audio_rate = rate; -+ jz_audio_k = STANDARD_SPEED / rate; -+ if (rate * jz_audio_k != STANDARD_SPEED) -+ jz_audio_q = rate / ((STANDARD_SPEED / jz_audio_k) - rate ); -+ else -+ jz_audio_q = 0x1fffffff; /* a very big value, don't compensate */ -+ -+ switch (rate) { -+ case 8000: -+ f_scale_count = f_scale_counts[0]; -+ f_scale_array = k_8000; -+ f_scale_reload = reload_8000; -+ break; -+ case 11025: -+ f_scale_count = f_scale_counts[1]; -+ f_scale_array = k_11025; -+ f_scale_reload = reload_11025; -+ break; -+ case 16000: -+ f_scale_count = f_scale_counts[2]; -+ f_scale_array = k_16000; -+ f_scale_reload = reload_16000; -+ break; -+ case 22050: -+ f_scale_count = f_scale_counts[3]; -+ f_scale_array = k_22050; -+ f_scale_reload = reload_22050; -+ break; -+ case 24000: -+ f_scale_count = f_scale_counts[4]; -+ f_scale_array = k_24000; -+ f_scale_reload = reload_24000; -+ break; -+ case 32000: -+ f_scale_count = f_scale_counts[5]; -+ f_scale_array = k_32000; -+ f_scale_reload = reload_32000; -+ break; -+ case 44100: -+ f_scale_count = f_scale_counts[6]; -+ f_scale_array = k_44100; -+ f_scale_reload = reload_44100; -+ break; -+ case 48000: -+ f_scale_count = f_scale_counts[7]; -+ f_scale_array = k_48000; -+ f_scale_reload = reload_48000; -+ break; -+ } -+ f_scale_idx = 0; -+ -+ return jz_audio_rate; -+} -+ -+static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char data; -+ volatile unsigned char *s = (unsigned char *)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ if ((jz_audio_count++ % jz_audio_k) == 0) { -+ cnt++; -+ data = *(s++); -+ *(dp ++) = data + 0x80; -+ s++; /* skip the other channel */ -+ } else { -+ s += 2; /* skip the redundancy */ -+ } -+ if (jz_audio_count - last_jz_audio_count >= jz_audio_q) { -+ jz_audio_count++; -+ last_jz_audio_count = jz_audio_count; -+ count -= 2; -+ s += 2; -+ } -+ } -+ return cnt; -+} -+ -+static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char d1, d2; -+ volatile unsigned char *s = (unsigned char *)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; -+ if ((jz_audio_count++ % jz_audio_k) == 0) { -+ cnt += 2; -+ d1 = *(s++); -+ *(dp ++) = d1 + 0x80; -+ d2 = *(s++); -+ *(dp ++) = d2 + 0x80; -+ } else { -+ s += 2; /* skip the redundancy */ -+ } -+ if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 2) { -+ jz_audio_count += 2; -+ last_jz_audio_count = jz_audio_count; -+ count -= 2; -+ s += 2; -+ } -+ } -+ return cnt; -+} -+ -+static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned short d1; -+ unsigned short *s = (unsigned short *)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ if ((jz_audio_count++ % jz_audio_k) == 0) { -+ cnt += 2; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = d1; -+ s++; /* skip the other channel */ -+ } else { -+ s += 2; /* skip the redundancy */ -+ } -+ if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 2) { -+ jz_audio_count += 2; -+ last_jz_audio_count = jz_audio_count; -+ count -= 2; -+ s += 2; -+ } -+ } -+ return cnt; -+} -+ -+static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned short d1, d2; -+ unsigned short *s = (unsigned short *)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ if ((jz_audio_count++ % jz_audio_k) == 0) { -+ cnt += 4; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = d1; -+ d2 = *(s++); -+ *(dp ++) = d2; -+ } else -+ s += 2; /* skip the redundancy */ -+ -+ if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 4) { -+ jz_audio_count += 4; -+ last_jz_audio_count = jz_audio_count; -+ count -= 2; -+ s += 2; -+ } -+ } -+ return cnt; -+} -+ -+ -+static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -+{ -+ int i, cnt = 0; -+ unsigned char data; -+ unsigned char *s = (unsigned char *)src_start; -+ unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count--; -+ jz_audio_count++; -+ cnt += jz_audio_k; -+ data = *(s++) - 0x80; -+ for (i=0;i 0) { -+ count -= 2; -+ jz_audio_count += 2; -+ cnt += 2 * jz_audio_k; -+ d1 = *(s++) - 0x80; -+ d2 = *(s++) - 0x80; -+ for (i=0;i= jz_audio_q * 2) { -+ cnt += 2 * jz_audio_k; -+ last_jz_audio_count = jz_audio_count; -+ for (i=0;i= 0) { -+ if (f_scale_reload[f_scale_idx]) { -+ d1 = d2; -+ d2 = *s++; -+ if (!count) -+ break; -+ count -= 2; -+ } -+ d = d1 + (((d2 - d1) * f_scale_array[f_scale_idx]) >> 8); -+ *dp++ = d; -+ *dp++ = d; -+ cnt += 4; -+ f_scale_idx ++; -+ if (f_scale_idx >= f_scale_count) -+ f_scale_idx = 0; -+ } -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x16_s(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ static short d11, d12, d21, d22, d1, d2; -+ short *s = (short *)src_start; -+ short *dp = (short *)(*(out_dma_buf + id)); -+ -+ d12 = *s++; -+ d22 = *s++; -+ count -= 4; -+ while (count >= 0) { -+ register unsigned int kvalue; -+ kvalue = f_scale_array[f_scale_idx]; -+ if (f_scale_reload[f_scale_idx]) { -+ d11 = d12; -+ d12 = *s++; -+ d21 = d22; -+ d22 = *s++; -+ if (!count) -+ break; -+ count -= 4; -+ } -+ d1 = d11 + (((d12 - d11)*kvalue) >> 8); -+ d2 = d21 + (((d22 - d21)*kvalue) >> 8); -+ *dp++ = d1; -+ *dp++ = d2; -+ cnt += 4; -+ f_scale_idx ++; -+ if (f_scale_idx >= f_scale_count) -+ f_scale_idx = 0; -+ } -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -+{ -+ switch (fmt) { -+ case AFMT_U8: -+ case AFMT_S16_LE: -+ jz_audio_format = fmt; -+ jz_update_filler(fmt, jz_audio_channels); -+ case AFMT_QUERY: -+ break; -+ } -+ return jz_audio_format; -+} -+ -+static short jz_audio_set_channels(int dev, short channels) -+{ -+ switch (channels) { -+ case 1: -+ __ac97_set_xs_stereo(); // always stereo when recording -+ __ac97_set_rs_stereo(); // always stereo when recording -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ break; -+ case 2: -+ __ac97_set_xs_stereo(); -+ __ac97_set_rs_stereo(); -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ break; -+ case 0: -+ break; -+ } -+ return jz_audio_channels; -+} -+ -+ -+static void jz_audio_reset(void) -+{ -+ __ac97_disable_replay(); -+ __ac97_disable_receive_dma(); -+ __ac97_disable_record(); -+ __ac97_disable_transmit_dma(); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file); -+static int jz_audio_open(struct inode *inode, struct file *file); -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg); -+static unsigned int jz_audio_poll(struct file *file, -+ struct poll_table_struct *wait); -+static ssize_t jz_audio_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos); -+static ssize_t jz_audio_read(struct file *file, char *buffer, -+ size_t count, loff_t *ppos); -+ -+/* static struct file_operations jz_ac97_audio_fops */ -+static struct file_operations jz_ac97_audio_fops = -+{ -+ owner: THIS_MODULE, -+ open: jz_audio_open, -+ release: jz_audio_release, -+ write: jz_audio_write, -+ read: jz_audio_read, -+ poll: jz_audio_poll, -+ ioctl: jz_audio_ioctl -+}; -+ -+/* Read / Write AC97 codec registers */ -+static inline int jz_out_command_ready(void) -+{ -+ int t2 = 1000; -+ int done = 0; -+ -+ while (! done && t2-- > 0) { -+ if (REG32(AC97_ACSR) & AIC_ACSR_CADT) { -+ REG32(AC97_ACSR) &= ~AIC_ACSR_CADT; -+ done = 1; -+ } -+ else -+ udelay (1); -+ } -+ return done; -+} -+ -+static inline int jz_in_status_ready(void) -+{ -+ int t2 = 1000; -+ int done = 0; -+ -+ while (! done && t2-- > 0) { -+ if (REG32(AC97_ACSR) & AIC_ACSR_SADR) { -+ REG32(AC97_ACSR) &= ~AIC_ACSR_SADR; -+ done = 1; -+ } -+ else { -+ if (REG32(AC97_ACSR) & AIC_ACSR_RSTO) { -+ REG32(AC97_ACSR) &= ~AIC_ACSR_RSTO; -+ printk(KERN_DEBUG "%s: RSTO receive status timeout.\n", -+ __FUNCTION__); -+ done = 0; -+ break; -+ } -+ udelay (1); -+ } -+ } -+ return done; -+} -+ -+static int jz_readAC97Reg (struct ac97_codec *dev, u8 reg) -+{ -+ u16 value; -+ -+ if (reg < 128) { -+ u8 ret_reg; -+ __ac97_out_rcmd_addr(reg);//output read addr -+ if (jz_out_command_ready())//judge if send completely? -+ while (jz_in_status_ready()) {//judge if receive completely? -+ ret_reg = __ac97_in_status_addr();//slot1:send addr -+ value = __ac97_in_data(); -+ if (ret_reg == reg) -+ return value; -+ else { -+// printk(KERN_DEBUG "%s: index (0x%02x)->(0x%02x) 0x%x\n", __FUNCTION__, reg, ret_reg, value); -+ return -EINVAL; -+ } -+ } -+ } -+ value = __ac97_in_data(); -+ printk (KERN_DEBUG "timeout while reading AC97 codec (0x%x)\n", reg); -+ return -EINVAL; -+} -+ -+static u16 ac97_codec_read(struct ac97_codec *codec, u8 reg) -+{ -+ int res = jz_readAC97Reg(codec, reg); -+ int count = 0; -+ while (res == -EINVAL) { -+ udelay(1000); -+ __ac97_warm_reset_codec(); -+ udelay(1000); -+ res = jz_readAC97Reg(codec, reg); -+ count ++; -+ if (count > MAX_RETRY){ -+ printk(KERN_WARNING"After try %d when read AC97 codec 0x%x, can't success, give up operate!!\n", -+ MAX_RETRY, reg); -+ break; -+ } -+ } -+ return (u16)res; -+} -+ -+static int jz_writeAC97Reg (struct ac97_codec *dev, u8 reg, u16 value) -+{ -+ //unsigned long flags; -+ int done = 0; -+ -+ //save_and_cli(flags); -+ -+ __ac97_out_wcmd_addr(reg); -+ __ac97_out_data(value); -+ if (jz_out_command_ready()) -+ done = 1; -+ else -+ printk (KERN_DEBUG "Tiemout AC97 codec write (0x%X<==0x%X)\n", reg, value); -+ //restore_flags(flags); -+ return done; -+} -+static void ac97_codec_write(struct ac97_codec *codec, u8 reg, u16 data) -+{ -+ int done = jz_writeAC97Reg(codec, reg, data); -+ int count = 0; -+ while (done == 0) { -+ count ++; -+ udelay (2000); -+ __ac97_warm_reset_codec(); -+ udelay(2000); -+ done = jz_writeAC97Reg(codec, reg, data); -+ if ( count > MAX_RETRY ){ -+ printk (KERN_DEBUG " After try %d when write AC97 codec (0x%x), can't sucess, give up!! \n", -+ MAX_RETRY, reg); -+ break; -+ } -+ } -+} -+ -+/* OSS /dev/mixer file operation methods */ -+ -+static int jz_ac97_open_mixdev(struct inode *inode, struct file *file) -+{ -+ int i; -+ int minor = MINOR(inode->i_rdev); -+ struct jz_ac97_controller_info *controller = ac97_controller; -+ -+ for (i = 0; i < NR_AC97; i++) -+ if (controller->ac97_codec[i] != NULL && -+ controller->ac97_codec[i]->dev_mixer == minor) -+ goto match; -+ -+ if (!controller) -+ return -ENODEV; -+ -+ match: -+ file->private_data = controller->ac97_codec[i]; -+ -+ return 0; -+} -+ -+static int jz_ac97_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ struct ac97_codec *codec = (struct ac97_codec *)file->private_data; -+ -+ return codec->mixer_ioctl(codec, cmd, arg); -+} -+ -+static loff_t jz_ac97_llseek(struct file *file, loff_t offset, int origin) -+{ -+ return -ESPIPE; -+} -+ -+static /*const*/ struct file_operations jz_ac97_mixer_fops = { -+ owner: THIS_MODULE, -+ llseek: jz_ac97_llseek, -+ ioctl: jz_ac97_ioctl_mixdev, -+ open: jz_ac97_open_mixdev, -+}; -+ -+/* AC97 codec initialisation. */ -+static int __init jz_ac97_codec_init(struct jz_ac97_controller_info *controller) -+{ -+ int num_ac97 = 0; -+ int ready_2nd = 0; -+ struct ac97_codec *codec; -+ unsigned short eid; -+ int i = 0; -+ -+ if (__ac97_codec_is_low_power_mode()) { -+ printk(KERN_DEBUG "AC97 codec is low power mode, warm reset ...\n"); -+ __ac97_warm_reset_codec(); -+ udelay(10); -+ } -+ i = 0; -+ while (!__ac97_codec_is_ready()) { -+ i++; -+ if ( i > 100 ) { -+ printk(KERN_WARNING "AC97 codec not ready, failed init ..\n"); -+ return -ENODEV; -+ } -+ udelay(10); -+ } -+ i = 0; -+ -+ /* Reset the mixer. */ -+ for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { -+ if ((codec = kmalloc(sizeof(struct ac97_codec), -+ GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ memset(codec, 0, sizeof(struct ac97_codec)); -+ -+ /* initialize some basic codec information, -+ other fields will be filled -+ in ac97_probe_codec */ -+ codec->private_data = controller; -+ codec->id = num_ac97; -+ -+ codec->codec_read = ac97_codec_read; -+ codec->codec_write = ac97_codec_write; -+ -+ if (ac97_probe_codec(codec) == 0) -+ break; -+ -+ eid = ac97_codec_read(codec, AC97_EXTENDED_ID); -+ if (eid == 0xFFFF) { -+ printk(KERN_WARNING "Jz AC97: no codec attached?\n"); -+ kfree(codec); -+ break; -+ } -+ -+ controller->ac97_features = eid; -+ -+ if (!(eid & 0x0001)) -+ printk(KERN_WARNING "AC97 codec: only 48Khz playback available.\n"); -+ else { -+ printk(KERN_WARNING "AC97 codec: supports variable sample rate.\n"); -+ /* Enable HPEN: UCB1400 only */ -+ ac97_codec_write(codec, 0x6a, -+ ac97_codec_read(codec, 0x6a) | 0x40); -+ -+ /* Enable variable rate mode */ -+ ac97_codec_write(codec, AC97_EXTENDED_STATUS, 9); -+ ac97_codec_write(codec, -+ AC97_EXTENDED_STATUS, -+ ac97_codec_read(codec, AC97_EXTENDED_STATUS) | 0xE800); -+ /* power up everything, modify this -+ when implementing power saving */ -+ ac97_codec_write(codec, -+ AC97_POWER_CONTROL, -+ ac97_codec_read(codec, AC97_POWER_CONTROL) & ~0x7f00); -+ /* wait for analog ready */ -+ for (i=10; i && ((ac97_codec_read(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) { -+// current->state = TASK_UNINTERRUPTIBLE; -+// schedule_timeout(HZ/20); -+ } -+ -+ if (!(ac97_codec_read(codec, AC97_EXTENDED_STATUS) & 1)) { -+ printk(KERN_WARNING "Jz AC97: Codec refused to allow VRA, using 48Khz only.\n"); -+ controller->ac97_features &= ~1; -+ } -+ } -+ -+ if ((codec->dev_mixer = -+ register_sound_mixer(&jz_ac97_mixer_fops, -1)) < 0) { -+ printk(KERN_ERR "Jz AC97: couldn't register mixer!\n"); -+ kfree(codec); -+ break; -+ } -+ -+ controller->ac97_codec[num_ac97] = codec; -+ -+ /* if there is no secondary codec at all, don't probe any more */ -+ if (!ready_2nd) -+ return num_ac97+1; -+ } -+ return num_ac97; -+} -+ -+static void jz_update_filler(int format, int channels) -+{ -+#define TYPE(fmt,ch) (((fmt)<<3) | ((ch)&7)) /* up to 8 chans supported. */ -+ -+ -+ switch (TYPE(format, channels)) { -+ default: -+ -+ case TYPE(AFMT_U8, 1): -+ if ((ac97_controller->patched) && -+ (ac97_controller->ac97_features & 1)) { -+ __aic_enable_mono2stereo(); -+ __aic_enable_unsignadj(); -+ jz_set_dma_block_size(ac97_controller->dma1, 16); -+ jz_set_dma_block_size(ac97_controller->dma2, 16); -+ } else { -+ __aic_disable_mono2stereo(); -+ __aic_disable_unsignadj(); -+ jz_set_dma_block_size(ac97_controller->dma1, 4); -+ jz_set_dma_block_size(ac97_controller->dma2, 4); -+ } -+ replay_filler = replay_fill_1x8_u; -+ record_filler = record_fill_1x8_u; -+ __ac97_set_oass(8); -+ __ac97_set_iass(8); -+ jz_set_dma_dest_width(ac97_controller->dma1, 8); -+ jz_set_dma_src_width(ac97_controller->dma2, 8); -+ break; -+ case TYPE(AFMT_U8, 2): -+ if ((ac97_controller->patched) && -+ (ac97_controller->ac97_features & 1)) { -+ __aic_enable_mono2stereo(); -+ __aic_enable_unsignadj(); -+ jz_set_dma_block_size(ac97_controller->dma1, 16); -+ jz_set_dma_block_size(ac97_controller->dma2, 16); -+ } else { -+ __aic_disable_mono2stereo(); -+ __aic_disable_unsignadj(); -+ jz_set_dma_block_size(ac97_controller->dma1, 4); -+ jz_set_dma_block_size(ac97_controller->dma2, 4); -+ } -+ replay_filler = replay_fill_2x8_u; -+ record_filler = record_fill_2x8_u; -+ __ac97_set_oass(8); -+ __ac97_set_iass(8); -+ jz_set_dma_dest_width(ac97_controller->dma1, 8); -+ jz_set_dma_src_width(ac97_controller->dma2, 8); -+ break; -+ case TYPE(AFMT_S16_LE, 1): -+ if ((ac97_controller->patched) && -+ (ac97_controller->ac97_features & 1)) { -+ __aic_enable_mono2stereo(); -+ jz_set_dma_block_size(ac97_controller->dma1, 16); -+ jz_set_dma_block_size(ac97_controller->dma2, 16); -+ } else { -+ __aic_disable_mono2stereo(); -+ jz_set_dma_block_size(ac97_controller->dma1, 4); -+ jz_set_dma_block_size(ac97_controller->dma2, 4); -+ } -+ __aic_disable_unsignadj(); -+ replay_filler = replay_fill_1x16_s; -+ record_filler = record_fill_1x16_s; -+ __ac97_set_oass(16); -+ __ac97_set_iass(16); -+ -+ jz_set_dma_dest_width(ac97_controller->dma1, 16); -+ jz_set_dma_src_width(ac97_controller->dma2, 16); -+ -+ break; -+ -+ case TYPE(AFMT_S16_LE, 2): -+ if ((ac97_controller->patched) && -+ (ac97_controller->ac97_features & 1)) { -+ jz_set_dma_block_size(ac97_controller->dma1, 16); -+ jz_set_dma_block_size(ac97_controller->dma2, 16); -+ } else { -+ jz_set_dma_block_size(ac97_controller->dma1, 4); -+ jz_set_dma_block_size(ac97_controller->dma2, 4); -+ } -+ __aic_disable_mono2stereo(); -+ __aic_disable_unsignadj(); -+ replay_filler = replay_fill_2x16_s; -+ record_filler = record_fill_2x16_s; -+ __ac97_set_oass(16); -+ __ac97_set_iass(16); -+ jz_set_dma_dest_width(ac97_controller->dma1, 16); -+ jz_set_dma_src_width(ac97_controller->dma2, 16); -+ break; -+ } -+} -+ -+#ifdef CONFIG_PROC_FS -+ -+extern struct proc_dir_entry *proc_jz_root; -+ -+static int jz_ac97_init_proc(struct jz_ac97_controller_info *controller) -+{ -+ if (!create_proc_read_entry ("ac97", 0, proc_jz_root, -+ ac97_read_proc, controller->ac97_codec[0])) -+ return -EIO; -+ -+ return 0; -+} -+ -+static void jz_ac97_cleanup_proc(struct jz_ac97_controller_info *controller) -+{ -+} -+ -+#endif -+ -+static void __init attach_jz_ac97(struct jz_ac97_controller_info *controller) -+{ -+ char *name; -+ int adev; -+ -+ name = controller->name; -+ jz_ac97_initHw(controller); -+ -+ /* register /dev/audio ? */ -+ adev = register_sound_dsp(&jz_ac97_audio_fops, -1); -+ if (adev < 0) -+ goto audio_failed; -+ -+ /* initialize AC97 codec and register /dev/mixer */ -+ if (jz_ac97_codec_init(controller) <= 0) -+ goto mixer_failed; -+ -+#ifdef CONFIG_PROC_FS -+ if (jz_ac97_init_proc(controller) < 0) { -+ printk(KERN_ERR "%s: can't create AC97 proc filesystem.\n", name); -+ goto proc_failed; -+ } -+#endif -+ -+ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8);//4 -+ if (!controller->tmp1) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp1_failed; -+ } -+ -+ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8);//4 -+ if (!controller->tmp2) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp2_failed; -+ } -+ -+ if ((controller->dma1 = jz_request_dma(DMA_ID_AC97_TX, "audio dac", -+ jz_ac97_replay_dma_irq, -+ IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -+ goto dma1_failed; -+ } -+ if ((controller->dma2 = jz_request_dma(DMA_ID_AC97_RX, "audio adc", -+ jz_ac97_record_dma_irq, -+ IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -+ goto dma2_failed; -+ } -+ -+ printk("Jz On-Chip AC97 controller registered (DAC: DMA%d/IRQ%d, ADC: DMA%d/IRQ%d)\n", -+ controller->dma1, get_dma_done_irq(controller->dma1), -+ controller->dma2, get_dma_done_irq(controller->dma2)); -+ -+ old_mksound = kd_mksound; /* see vt.c */ -+ kd_mksound = jz_ac97_mksound; -+ controller->dev_audio = adev; -+ return; -+ -+ dma2_failed: -+ jz_free_dma(controller->dma1); -+ dma1_failed: -+ free_pages((unsigned long)controller->tmp2, 8);//4 -+ tmp2_failed: -+ free_pages((unsigned long)controller->tmp1, 8);//4 -+ tmp1_failed: -+#ifdef CONFIG_PROC_FS -+ jz_ac97_cleanup_proc(controller); -+#endif -+ proc_failed: -+ /* unregister mixer dev */ -+ mixer_failed: -+ unregister_sound_dsp(adev); -+ audio_failed: -+ return; -+} -+ -+static int __init probe_jz_ac97(struct jz_ac97_controller_info **controller) -+{ -+ if ((*controller = kmalloc(sizeof(struct jz_ac97_controller_info), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "Jz AC97 Controller: out of memory.\n"); -+ return -ENOMEM; -+ } -+ memset( *controller, 0, sizeof(struct jz_ac97_controller_info) ); -+ (*controller)->name = "Jz AC97 controller"; -+ (*controller)->opened1 = 0; -+ (*controller)->opened2 = 0; -+ -+ init_waitqueue_head(&(*controller)->adc_wait); -+ init_waitqueue_head(&(*controller)->dac_wait); -+ spin_lock_init(&(*controller)->lock); -+ init_waitqueue_head(&rx_wait_queue); -+ init_waitqueue_head(&tx_wait_queue); -+ -+ return 0; -+} -+ -+static void __exit unload_jz_ac97(struct jz_ac97_controller_info *controller) -+{ -+ int adev = controller->dev_audio; -+ -+ jz_ac97_full_reset (controller); -+ -+ controller->dev_audio = -1; -+ -+ if (old_mksound) -+ kd_mksound = old_mksound; /* Our driver support bell for kb, see vt.c */ -+ -+#ifdef CONFIG_PROC_FS -+ jz_ac97_cleanup_proc(controller); -+#endif -+ -+ jz_free_dma(controller->dma1); -+ jz_free_dma(controller->dma2); -+ -+ free_pages((unsigned long)controller->tmp1, 8);//4 -+ free_pages((unsigned long)controller->tmp2, 8);//4 -+ -+ if (adev >= 0) { -+ //unregister_sound_mixer(audio_devs[adev]->mixer_dev); -+ unregister_sound_dsp(controller->dev_audio); -+ } -+} -+ -+#ifdef CONFIG_PM -+ -+static int reserve_mastervol, reserve_micvol; -+static int reserve_power1, reserve_power2; -+static int reserve_power3, reserve_power4; -+static int reserve_power5, reserve_power6; -+ -+static int jz_ac97_suspend(struct jz_ac97_controller_info *controller, int state) -+{ -+ struct ac97_codec *codec = controller->ac97_codec[0]; -+ -+ /* save codec states */ -+ reserve_mastervol = ac97_codec_read(codec, 0x0002); -+ reserve_micvol = ac97_codec_read(codec, 0x000e); -+ -+ reserve_power1 = ac97_codec_read(codec, 0x0026); -+ reserve_power2 = ac97_codec_read(codec, 0x006c); -+ reserve_power3 = ac97_codec_read(codec, 0x005c); -+ reserve_power4 = ac97_codec_read(codec, 0x0064); -+ reserve_power5 = ac97_codec_read(codec, 0x0066); -+ reserve_power6 = ac97_codec_read(codec, 0x006a); -+ -+ /* put codec into power-saving mode */ -+ ac97_codec_write(codec, 0x5c, 0xffff); -+ ac97_codec_write(codec, 0x64, 0x0000); -+ ac97_codec_write(codec, 0x66, 0x0000); -+ ac97_codec_write(codec, 0x6a, 0x0000); -+ -+ ac97_codec_write(codec, 0x6c, 0x0030); -+ ac97_codec_write(codec, 0x26, 0x3b00); -+ -+ ac97_save_state(codec); -+ __ac97_disable(); -+ -+ return 0; -+} -+ -+static int jz_ac97_resume(struct jz_ac97_controller_info *controller) -+{ -+ struct ac97_codec *codec = controller->ac97_codec[0]; -+ -+ jz_ac97_full_reset(controller); -+ ac97_probe_codec(codec); -+ ac97_restore_state(codec); -+ -+ ac97_codec_write(codec, 0x0026, reserve_power1); -+ ac97_codec_write(codec, 0x006c, reserve_power2); -+ ac97_codec_write(codec, 0x005c, reserve_power3); -+ ac97_codec_write(codec, 0x0064, reserve_power4); -+ ac97_codec_write(codec, 0x0066, reserve_power5); -+ ac97_codec_write(codec, 0x006a, reserve_power6); -+ -+ ac97_codec_write(codec, 0x0002, reserve_mastervol); -+ ac97_codec_write(codec, 0x000e, reserve_micvol); -+ -+ /* Enable variable rate mode */ -+ ac97_codec_write(codec, AC97_EXTENDED_STATUS, 9); -+ ac97_codec_write(codec, -+ AC97_EXTENDED_STATUS, -+ ac97_codec_read(codec, AC97_EXTENDED_STATUS) | 0xE800); -+ -+ return 0; -+} -+ -+static int jz_ac97_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct jz_ac97_controller_info *controller = pm_dev->data; -+ -+ if (!controller) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jz_ac97_suspend(controller, (int)data); -+ break; -+ -+ case PM_RESUME: -+ ret = jz_ac97_resume(controller); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#endif /* CONFIG_PM */ -+ -+static int __init init_jz_ac97(void) -+{ -+ int errno; -+ -+ if ((errno = probe_jz_ac97(&ac97_controller)) < 0) -+ return errno; -+ attach_jz_ac97(ac97_controller); -+ -+ out_empty_queue.id = NULL; -+ out_full_queue.id = NULL; -+ out_busy_queue.id = NULL; -+ -+ in_empty_queue.id = NULL; -+ in_full_queue.id = NULL; -+ in_busy_queue.id = NULL; -+ -+#ifdef CONFIG_PM -+ ac97_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -+ jz_ac97_pm_callback); -+ if (ac97_controller->pm) -+ ac97_controller->pm->data = ac97_controller; -+#endif -+ -+ return 0; -+} -+ -+static void __exit cleanup_jz_ac97(void) -+{ -+ unload_jz_ac97(ac97_controller); -+} -+ -+module_init(init_jz_ac97); -+module_exit(cleanup_jz_ac97); -+ -+ -+static int drain_adc(struct jz_ac97_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count; -+ unsigned tmo; -+ -+ add_wait_queue(&ctrl->adc_wait, &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ -+ if (signal_pending(current)) -+ break; -+ if (nonblock) { -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ tmo = (PAGE_SIZE * HZ) / STANDARD_SPEED; -+ tmo *= jz_audio_k * (jz_audio_format == AFMT_S16_LE) ? 2 : 4; -+ tmo /= jz_audio_channels; -+ } -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ if (signal_pending(current)) -+ return -ERESTARTSYS; -+ return 0; -+} -+ -+static int drain_dac(struct jz_ac97_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count; -+ unsigned tmo; -+ -+ add_wait_queue(&(ctrl->dac_wait), &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0 && elements_in_queue(&out_full_queue) <= 0) -+ break; -+ if (signal_pending(current)) -+ break; -+ if (nonblock) { -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ tmo = (PAGE_SIZE * HZ) / STANDARD_SPEED; -+ tmo *= jz_audio_k * (jz_audio_format == AFMT_S16_LE) ? 2 : 4; -+ tmo /= jz_audio_channels; -+ } -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ if (signal_pending(current)) -+ return -ERESTARTSYS; -+ return 0; -+} -+ -+/* -+ * Audio operation routines implementation -+ */ -+static int jz_audio_release(struct inode *inode, struct file *file) -+{ -+ struct jz_ac97_controller_info *controller = -+ (struct jz_ac97_controller_info *) file->private_data; -+ unsigned long flags; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ controller->opened1 = 0; -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ __ac97_disable_transmit_dma(); -+ __ac97_disable_replay(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ } -+ if (file->f_mode & FMODE_READ) { -+ controller->opened2 = 0; -+ first_record_call = 1; -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __ac97_disable_receive_dma(); -+ __ac97_disable_record(); -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ } -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ return 0; -+} -+ -+static int jz_audio_open(struct inode *inode, struct file *file) -+{ -+ struct jz_ac97_controller_info *controller= ac97_controller; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ controller->opened1 = 1; -+ //for ioctl -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ jz_audio_set_channels(controller->dev_audio, 1); -+ jz_audio_set_format(controller->dev_audio, AFMT_U8); -+ jz_audio_set_speed(controller->dev_audio, 8000); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ controller->opened2 = 1; -+ first_record_call = 1; -+ printk(KERN_DEBUG "You'd better apply 48000Hz 16-bit Stereo for record.\n"); -+ //for ioctl -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ jz_audio_set_channels(controller->dev_audio, 2); -+ jz_audio_set_format(controller->dev_audio, AFMT_S16_LE); -+ jz_audio_set_speed(controller->dev_audio, 48000); -+ } -+ -+ last_jz_audio_count = jz_audio_count = 0; -+ file->private_data = controller; -+ -+ jz_audio_fragsize = 8 * PAGE_SIZE; -+ jz_audio_fragstotal = 4; -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ return 0; -+} -+ -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct jz_ac97_controller_info *controller = -+ (struct jz_ac97_controller_info *) file->private_data; -+ int val=0,fullc,busyc,unfinish; -+ unsigned int flags; -+ count_info cinfo; -+ -+ switch (cmd) -+ { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, (int *)arg); -+ -+ case SNDCTL_DSP_RESET: -+ jz_audio_reset(); -+ return 0; -+ -+ case SNDCTL_DSP_SYNC: -+ if (file->f_mode & FMODE_WRITE) -+ return drain_dac(controller, file->f_flags & O_NONBLOCK); -+ return 0; -+ -+ case SNDCTL_DSP_SPEED: /* set smaple rate */ -+ { -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val >= 0) -+ jz_audio_set_speed(controller->dev_audio, val); -+ return put_user(val, (int *)arg); -+ } -+ -+ case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -+ return 0; -+ -+ case SNDCTL_DSP_GETBLKSIZE: -+ //return put_user(4*PAGE_SIZE, (int *)arg); -+ return put_user(jz_audio_fragsize , (int *)arg); -+ -+ case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ -+ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -+ -+ case SNDCTL_DSP_SETFMT: /* Select sample format */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ -+ if (val != AFMT_QUERY) { -+ jz_audio_set_format(controller->dev_audio,val); -+ } else { -+ if (file->f_mode & FMODE_READ) -+ val = (jz_audio_format == 16) ? -+ AFMT_S16_LE : AFMT_U8; -+ else -+ val = (jz_audio_format == 16) ? -+ AFMT_S16_LE : AFMT_U8; -+ } -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val); -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_POST: -+ /* FIXME: the same as RESET ?? */ -+ return 0; -+ -+ case SNDCTL_DSP_SUBDIVIDE: -+ return 0; -+ -+ case SNDCTL_DSP_SETFRAGMENT: -+ if(out_dma_buf || in_dma_buf) -+ return -EBUSY; -+ get_user(val, (long *) arg); -+ jz_audio_fragsize = 1 << (val & 0xFFFF);//16 least bits -+ -+ if (jz_audio_fragsize < 4 * PAGE_SIZE) -+ jz_audio_fragsize = 4 * PAGE_SIZE; -+ if (jz_audio_fragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE -+ jz_audio_fragsize = 16 * PAGE_SIZE; -+ jz_audio_fragstotal = (val >> 16) & 0x7FFF; -+ if (jz_audio_fragstotal < 2) -+ jz_audio_fragstotal = 2; -+ if (jz_audio_fragstotal > 32) -+ jz_audio_fragstotal = 32; -+ -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ return 0; -+ -+ case SNDCTL_DSP_GETCAPS: -+ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -+ -+ case SNDCTL_DSP_NONBLOCK: -+ file->f_flags |= O_NONBLOCK; -+ return 0; -+ -+ case SNDCTL_DSP_SETDUPLEX: -+ return -EINVAL; -+ -+ case SNDCTL_DSP_GETOSPACE: -+ { -+ audio_buf_info abinfo; -+ int i, bytes = 0; -+ -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ //unused fragment amount -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_fragments = elements_in_queue(&out_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ bytes /= jz_audio_k; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ //bytes /= jz_audio_b; -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ abinfo.fragsize = jz_audio_fragsize; -+ abinfo.bytes = bytes; -+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ -+ case SNDCTL_DSP_GETISPACE: -+ { -+ audio_buf_info abinfo; -+ int i, bytes = 0; -+ -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ //unused fragment amount -+ jz_audio_fragments = elements_in_queue(&in_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ abinfo.fragsize = jz_audio_fragsize; -+ abinfo.bytes = bytes; -+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETTRIGGER: -+ val = 0; -+ if (file->f_mode & FMODE_READ && in_dma_buf) //record is at working -+ val |= PCM_ENABLE_INPUT; -+ if (file->f_mode & FMODE_WRITE && out_dma_buf) //playback is at working -+ val |= PCM_ENABLE_OUTPUT; -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_SETTRIGGER: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ /*if (file->f_mode & FMODE_READ) { -+ if (val & PCM_ENABLE_INPUT) { -+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) -+ return ret; -+ start_adc(state); -+ } else -+ stop_adc(state); -+ } -+ if (file->f_mode & FMODE_WRITE) { -+ if (val & PCM_ENABLE_OUTPUT) { -+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) -+ return ret; -+ start_dac(state); -+ } else -+ stop_dac(state); -+ }*/ -+ return 0; -+ -+ case SNDCTL_DSP_GETIPTR: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ //controller->total_bytes += get_dma_residue(controller->dma2); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextIn; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ -+ case SNDCTL_DSP_GETOPTR: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ //controller->total_bytes += get_dma_residue(controller->dma1); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextOut; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ -+ case SNDCTL_DSP_GETODELAY: -+ { -+ int id, i; -+ -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ unfinish = 0; -+ fullc = elements_in_queue(&out_full_queue); -+ busyc = elements_in_queue(&out_busy_queue); -+ -+ for(i = 0;i < fullc ;i ++) -+ { -+ id = *(out_full_queue.id + i); -+ unfinish += *(out_dma_buf_data_count + id); -+ } -+ for(i = 0;i < busyc ;i ++) -+ { -+ id = *(out_busy_queue.id + i); -+ unfinish += get_dma_residue(controller->dma1); -+ } -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ unfinish /= jz_audio_k;//jz_audio_k is jz_audio_b -+ return put_user(val, (int *)arg); -+ } -+ case SOUND_PCM_READ_RATE: -+ return put_user(jz_audio_rate, (int *)arg); -+ case SOUND_PCM_READ_CHANNELS: -+ return put_user(jz_audio_channels, (int *)arg); -+ case SOUND_PCM_READ_BITS: -+ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -+ case SNDCTL_DSP_MAPINBUF: -+ case SNDCTL_DSP_MAPOUTBUF: -+ case SNDCTL_DSP_SETSYNCRO: -+ case SOUND_PCM_WRITE_FILTER: -+ case SOUND_PCM_READ_FILTER: -+ return -EINVAL; -+ } -+ return -EINVAL; -+} -+ -+static unsigned int jz_audio_poll(struct file *file, -+ struct poll_table_struct *wait) -+{ -+ struct jz_ac97_controller_info *controller = -+ (struct jz_ac97_controller_info *) file->private_data; -+ unsigned long flags; -+ unsigned int mask = 0; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ return POLLOUT | POLLWRNORM; -+ poll_wait(file, &controller->dac_wait, wait); -+ } -+ if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ return POLLIN | POLLRDNORM; -+ poll_wait(file, &controller->adc_wait, wait); -+ } -+ spin_lock_irqsave(&controller->lock, flags); -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ mask |= POLLOUT | POLLWRNORM; -+ } -+ else if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ mask |= POLLIN | POLLRDNORM; -+ } -+ spin_unlock_irqrestore(&controller->lock, flags); -+ return mask; -+} -+ -+static ssize_t jz_audio_read(struct file *file, char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct jz_ac97_controller_info *controller = -+ (struct jz_ac97_controller_info *) file->private_data; -+ int id, ret = 0, left_count, copy_count, cnt = 0; -+ unsigned long flags; -+ -+ if (count < 0) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+ if (count < 2*PAGE_SIZE / jz_audio_k) { -+ copy_count = count * 16 / (jz_audio_channels * jz_audio_format); -+ } else -+ copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4; -+ left_count = count; -+ -+ if (first_record_call) { -+ first_record_call = 0; -+ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ *(in_dma_buf_data_count + id) = copy_count * (jz_audio_format/8); -+ __ac97_enable_receive_dma(); -+ __ac97_enable_record(); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ interruptible_sleep_on(&rx_wait_queue); -+ } else -+ BUG(); -+ } -+ -+ while (left_count > 0) { -+ if (elements_in_queue(&in_full_queue) <= 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret ? ret : -EAGAIN; -+ else -+ interruptible_sleep_on(&rx_wait_queue); -+ } -+ if (signal_pending(current)) -+ return ret ? ret: -ERESTARTSYS; -+ -+ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -+ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -+ put_buffer_id(&in_empty_queue, id); -+ } else -+ BUG(); -+ -+ if (elements_in_queue(&in_busy_queue) == 0) { -+ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ *(in_dma_buf_data_count + id) = copy_count * (jz_audio_format/8); -+ __ac97_enable_receive_dma(); -+ __ac97_enable_record(); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ } -+ } -+ -+ if (ret + cnt > count) -+ cnt = count - ret; -+ -+ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -+ return ret ? ret : -EFAULT; -+ -+ ret += cnt; -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ left_count -= cnt; -+ } -+ if (ret != count) -+ printk(KERN_DEBUG "%s: count=%d ret=%d jz_audio_count=%d\n", -+ __FUNCTION__, count, ret, jz_audio_count); -+ return ret; -+} -+ -+static ssize_t jz_audio_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct jz_ac97_controller_info *controller = -+ (struct jz_ac97_controller_info *) file->private_data; -+ int id, ret = 0, left_count, copy_count; -+ unsigned int flags; -+ -+ if (count <= 0) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+ /* The data buffer size of the user space is always a PAGE_SIZE -+ * scale, so the process can be simplified. -+ */ -+ -+ if ((ac97_controller->patched) && (ac97_controller->ac97_features & 1)) -+ copy_count = count; -+ else { -+ if (count < 2*PAGE_SIZE / jz_audio_k) -+ copy_count = count; -+ else -+ copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4; -+ } -+ left_count = count; -+ -+ if (!(ac97_controller->patched) || !(ac97_controller->ac97_features & 1)) { -+ if (copy_from_user(controller->tmp1, buffer, count)) { -+ printk(KERN_DEBUG "%s: copy_from_user failed.\n", __FUNCTION__); -+ return ret ? ret : -EFAULT; -+ } -+ } -+ -+ while (left_count > 0) { -+ if (elements_in_queue(&out_empty_queue) == 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret; -+ else -+ interruptible_sleep_on(&tx_wait_queue); -+ } -+ -+ if (signal_pending(current)) -+ return ret ? ret : -ERESTARTSYS; -+ -+ /* the end fragment size in this write */ -+ if (ret + copy_count > count) -+ copy_count = count - ret; -+ -+ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -+ if ((ac97_controller->patched) && -+ (ac97_controller->ac97_features & 1)) { -+ if (copy_from_user((char *)(*(out_dma_buf + id)), buffer+ret, copy_count)) { -+ printk(KERN_DEBUG "%s: copy_from_user failed.\n", __FUNCTION__); -+ return ret ? ret : -EFAULT; -+ } -+ *(out_dma_buf_data_count + id) = copy_count; -+ } else -+ replay_filler( -+ (unsigned long)controller->tmp1 + ret, -+ copy_count, id); -+ //when 0,kernel will panic -+ if(*(out_dma_buf_data_count + id) > 0) { -+ put_buffer_id(&out_full_queue, id); -+ dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); -+ } else {//when 0,i need refill in empty queue -+ put_buffer_id(&out_empty_queue, id); -+ } -+ } else -+ BUG(); -+ left_count = left_count - copy_count; -+ ret += copy_count; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (elements_in_queue(&out_busy_queue) == 0) { -+ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ -+ __ac97_enable_transmit_dma(); -+ __ac97_enable_replay(); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(controller->dma1,file->private_data, -+ *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ } -+ } -+ } -+ } -+ -+ if (ret != count) -+ printk(KERN_DEBUG "%s: count=%d ret=%d jz_audio_count=%d\n", -+ __FUNCTION__, count, ret, jz_audio_count); -+ return ret; -+} -+ -+/* this function for the other codec function */ -+struct ac97_codec * find_ac97_codec(void) -+{ -+ if ( ac97_controller ) -+ return ac97_controller->ac97_codec[0]; -+ return 0; -+ -+} -+ -diff --git a/sound/oss/jz_i2s.c b/sound/oss/jz_i2s.c -new file mode 100644 -index 0000000..ab67cae ---- /dev/null -+++ b/sound/oss/jz_i2s.c -@@ -0,0 +1,2894 @@ -+/* -+ * linux/drivers/sound/Jz_i2s.c -+ * -+ * JzSOC On-Chip I2S audio driver. -+ * -+ * Copyright (C) 2005 by Junzheng Corp. -+ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -+ * dma channel 4&3,noah is tested. -+ * -+ * 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. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sound_config.h" -+ -+#if defined(CONFIG_I2S_DLV) -+#include "jzdlv.h" -+#endif -+ -+#define DPRINTK(args...) printk(args) -+#define DMA_ID_I2S_TX DMA_ID_AIC_TX -+#define DMA_ID_I2S_RX DMA_ID_AIC_RX -+#define NR_I2S 2 -+#define JZCODEC_RW_BUFFER_SIZE 5 -+#define JZCODEC_RW_BUFFER_TOTAL 4 -+ -+#define USE_NONE 1 -+#define USE_MIC 2 -+#define USE_LINEIN 3 -+ -+typedef struct hpvol_shift_s -+{ -+ int hpvol; -+ int shift; -+} hpvol_shift_t; -+ -+mixer_info info; -+_old_mixer_info old_info; -+int codec_volue_shift; -+hpvol_shift_t hpvol_shift_table[72]; -+int abnormal_data_count; -+unsigned long i2s_clk; -+ -+void (*set_codec_mode)(void) = NULL; -+void (*clear_codec_mode)(void) = NULL; -+void (*set_codec_gpio_pin)(void) = NULL; -+void (*each_time_init_codec)(void) = NULL; -+int (*set_codec_startup_param)(void) = NULL; -+void (*set_codec_volume_table)(void) = NULL; -+void (*set_codec_record)(int mode) = NULL; -+void (*set_codec_replay)(void) = NULL; -+void (*set_codec_replay_record)(int mode) = NULL; -+void (*turn_on_codec)(void) = NULL; -+void (*turn_off_codec)(void) = NULL; -+void (*set_codec_speed)(int rate) = NULL; -+void (*reset_codec)(void) = NULL; -+void (*codec_mixer_old_info_id_name)(void) = NULL; -+void (*codec_mixer_info_id_name)(void) = NULL; -+void (*set_codec_bass)(int val) = NULL; -+void (*set_codec_volume)(int val) = NULL; -+void (*set_codec_mic)(int val) = NULL; -+void (*set_codec_line)(int val) = NULL; -+void (*i2s_resume_codec)(void) = NULL; -+void (*i2s_suspend_codec)(int wr,int rd) = NULL; -+void (*init_codec_pin)(void) = NULL; -+void (*set_codec_some_func)(void) = NULL; -+void (*clear_codec_record)(void) = NULL; -+void (*clear_codec_replay)(void) = NULL; -+void (*set_replay_hp_or_speaker)(void) = NULL; -+void (*set_codec_direct_mode)(void) = NULL; -+void (*clear_codec_direct_mode)(void) = NULL; -+void (*set_codec_linein2hp)(void) = NULL; -+void (*clear_codec_linein2hp)(void) = NULL; -+ -+static int jz_audio_rate; -+static int jz_audio_format; -+static int jz_audio_volume; -+static int jz_audio_channels; -+static int jz_audio_b; /* bits expand multiple */ -+static int jz_audio_fragments; /* unused fragment amount */ -+static int jz_audio_fragstotal; -+static int jz_audio_fragsize; -+static int jz_audio_speed; -+ -+static int codec_bass_gain; -+static int audio_mix_modcnt; -+static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -+#if defined(CONFIG_I2S_DLV) -+int jz_mic_only = 1; -+static int jz_codec_config = 0; -+static unsigned long ramp_up_start; -+static unsigned long ramp_up_end; -+static unsigned long gain_up_start; -+static unsigned long gain_up_end; -+static unsigned long ramp_down_start; -+static unsigned long ramp_down_end; -+static unsigned long gain_down_start; -+static unsigned long gain_down_end; -+#endif -+ -+static int codec_mic_gain; -+static int pop_dma_flag; -+static int last_dma_buffer_id; -+static int drain_flag; -+static int use_mic_line_flag; -+ -+static void (*old_mksound)(unsigned int hz, unsigned int ticks); -+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -+static void jz_update_filler(int bits, int channels); -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize); -+static int Free_In_Out_queue(int fragstotal,int fragsize); -+static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -+static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -+static void (*replay_filler)(signed long src_start, int count, int id); -+static int (*record_filler)(unsigned long dst_start, int count, int id); -+#if defined(CONFIG_I2S_ICODEC) -+static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -+#endif -+static void jz_audio_reset(void); -+static struct file_operations jz_i2s_audio_fops; -+ -+static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -+ -+struct jz_i2s_controller_info -+{ -+ int io_base; -+ int dma1; /* for play */ -+ int dma2; /* for record */ -+ char *name; -+ int dev_audio; -+ struct i2s_codec *i2s_codec[NR_I2S]; -+ int opened1; -+ int opened2; -+ unsigned char *tmp1; /* tmp buffer for sample conversions */ -+ unsigned char *tmp2; -+ spinlock_t lock; -+ spinlock_t ioctllock; -+ -+ wait_queue_head_t dac_wait; -+ wait_queue_head_t adc_wait; -+ int nextIn; /* byte index to next-in to DMA buffer */ -+ int nextOut; /* byte index to next-out from DMA buffer */ -+ int count; /* current byte count in DMA buffer */ -+ int finish; /* current transfered byte count in DMA buffer */ -+ unsigned total_bytes; /* total bytes written or read */ -+ unsigned blocks; -+ unsigned error; /* over/underrun */ -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+ -+static struct jz_i2s_controller_info *i2s_controller = NULL; -+struct i2s_codec -+{ -+ /* I2S controller connected with */ -+ void *private_data; -+ char *name; -+ int id; -+ int dev_mixer; -+ /* controller specific lower leverl i2s accessing routines */ -+ u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ -+ void (*codec_write) (u8 reg, u16 val); -+ /* Wait for codec-ready */ -+ void (*codec_wait) (struct i2s_codec *codec); -+ /* OSS mixer masks */ -+ int modcnt; -+ int supported_mixers; -+ int stereo_mixers; -+ int record_sources; -+ int bit_resolution; -+ /* OSS mixer interface */ -+ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -+ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -+ unsigned int left, unsigned int right); -+ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -+ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -+ /* saved OSS mixer states */ -+ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -+}; -+ -+ -+typedef struct buffer_queue_s -+{ -+ int count; -+ int *id; -+ int lock; -+} buffer_queue_t; -+ -+typedef struct left_right_sample_s -+{ -+ signed long left; -+ signed long right; -+} left_right_sample_t; -+ -+static unsigned long pop_turn_onoff_buf; -+static unsigned long pop_turn_onoff_pbuf; -+ -+static unsigned long *out_dma_buf = NULL; -+static unsigned long *out_dma_pbuf = NULL; -+static unsigned long *out_dma_buf_data_count = NULL; -+static unsigned long *in_dma_buf = NULL; -+static unsigned long *in_dma_pbuf = NULL; -+static unsigned long *in_dma_buf_data_count = NULL; -+ -+static buffer_queue_t out_empty_queue; -+static buffer_queue_t out_full_queue; -+static buffer_queue_t out_busy_queue; -+static buffer_queue_t in_empty_queue; -+static buffer_queue_t in_full_queue; -+static buffer_queue_t in_busy_queue; -+static int first_record_call = 0; -+ -+static left_right_sample_t save_last_samples[64]; -+ -+static inline int get_buffer_id(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ if (q->count == 0) { -+ spin_unlock_irqrestore(&q->lock, flags); -+ return -1; -+ } -+ r = *(q->id + 0); -+ for (i=0;i < q->count-1;i++) -+ *(q->id + i) = *(q->id + (i+1)); -+ q->count --; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void put_buffer_id(struct buffer_queue_s *q, int id) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ *(q->id + q->count) = id; -+ q->count ++; -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+ -+static inline int elements_in_queue(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ r = q->count; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -+{ -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_dma_tran_count = count / jz_audio_b; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+#if 1 -+ jz_set_oss_dma(chan, mode, jz_audio_format); -+#else -+ set_dma_mode(chan, mode); -+#endif -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) { -+ count++; -+ printk("JzSOC DMA controller can't set dma 0 count!\n"); -+ } -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ release_dma_lock(flags); -+} -+ -+static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -+{ -+ int id1, id2; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma2; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ if(drain_flag == 1) -+ wake_up(&drain_wait_queue); -+ /* for DSP_GETIPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id2); -+ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -+ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -+ audio_start_dma(dma,dev_id, -+ *(in_dma_pbuf + id2), -+ *(in_dma_buf_data_count + id2), -+ DMA_MODE_READ); -+ } else -+ in_busy_queue.count = 0; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -+{ -+ int id; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma1; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ if(pop_dma_flag == 1) { -+ pop_dma_flag = 0; -+ wake_up(&pop_wait_queue); -+ } else { -+ if(drain_flag == 1) { -+ /* Is replay dma buffer over ? */ -+ if(elements_in_queue(&out_full_queue) <= 0) { -+ drain_flag = 0; -+ wake_up(&drain_wait_queue); -+ } -+ } -+ -+ /* for DSP_GETOPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if ((id = get_buffer_id(&out_busy_queue)) < 0) -+ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -+ put_buffer_id(&out_empty_queue, id); -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ last_dma_buffer_id = id; -+ } -+ } else -+ out_busy_queue.count = 0; -+ -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void jz_i2s_initHw(int set) -+{ -+#if defined(CONFIG_MIPS_JZ_URANUS) -+ i2s_clk = 48000000; -+#else -+ i2s_clk = __cpm_get_i2sclk(); -+#endif -+ __i2s_disable(); -+ if(set) -+ __i2s_reset(); -+ schedule_timeout(5); -+ if(each_time_init_codec) -+ each_time_init_codec(); -+ __i2s_disable_record(); -+ __i2s_disable_replay(); -+ __i2s_disable_loopback(); -+ __i2s_set_transmit_trigger(4); -+ __i2s_set_receive_trigger(3); -+} -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ -+ /* recording */ -+ in_empty_queue.count = fragstotal; -+ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf) -+ goto all_mem_err; -+ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_pbuf) -+ goto all_mem_err; -+ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf_data_count) -+ goto all_mem_err; -+ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_empty_queue.id) -+ goto all_mem_err; -+ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_full_queue.id) -+ goto all_mem_err; -+ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_busy_queue.id) -+ goto all_mem_err; -+ -+ for (i=0;i < fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ for (i = 0; i < fragstotal; i++) { -+ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(in_dma_buf + i) == 0) -+ goto mem_failed_in; -+ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ } -+ -+ /* playing */ -+ out_empty_queue.count = fragstotal; -+ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf) -+ goto all_mem_err; -+ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_pbuf) -+ goto all_mem_err; -+ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ -+ if (!out_dma_buf_data_count) -+ goto all_mem_err; -+ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_empty_queue.id) -+ goto all_mem_err; -+ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_full_queue.id) -+ goto all_mem_err; -+ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_busy_queue.id) -+ goto all_mem_err; -+ for (i=0;i < fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /* alloc DMA buffer */ -+ for (i = 0; i < fragstotal; i++) { -+ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(out_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(OUT) buffers.\n"); -+ goto mem_failed_out; -+ } -+ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -+ } -+ -+ return 1; -+all_mem_err: -+ printk("error:allocate memory occur error 1!\n"); -+ return 0; -+mem_failed_out: -+ printk("error:allocate memory occur error 2!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ } -+ -+ return 0; -+mem_failed_in: -+ printk("error:allocate memory occur error 3!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ return 0; -+} -+ -+static int Free_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ /* playing */ -+ if(out_dma_buf != NULL) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ *(out_dma_buf + i) = 0; -+ } -+ kfree(out_dma_buf); -+ out_dma_buf = NULL; -+ } -+ if(out_dma_pbuf) { -+ kfree(out_dma_pbuf); -+ out_dma_pbuf = NULL; -+ } -+ if(out_dma_buf_data_count) { -+ kfree(out_dma_buf_data_count); -+ out_dma_buf_data_count = NULL; -+ } -+ if(out_empty_queue.id) { -+ kfree(out_empty_queue.id); -+ out_empty_queue.id = NULL; -+ } -+ if(out_full_queue.id) { -+ kfree(out_full_queue.id); -+ out_full_queue.id = NULL; -+ } -+ if(out_busy_queue.id) { -+ kfree(out_busy_queue.id); -+ out_busy_queue.id = NULL; -+ } -+ out_empty_queue.count = fragstotal; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ -+ /* recording */ -+ if(in_dma_buf) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) { -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ *(in_dma_buf + i) = 0; -+ } -+ kfree(in_dma_buf); -+ in_dma_buf = NULL; -+ } -+ if(in_dma_pbuf) { -+ kfree(in_dma_pbuf); -+ in_dma_pbuf = NULL; -+ } -+ if(in_dma_buf_data_count) { -+ kfree(in_dma_buf_data_count); -+ in_dma_buf_data_count = NULL; -+ } -+ if(in_empty_queue.id) { -+ kfree(in_empty_queue.id); -+ in_empty_queue.id = NULL; -+ } -+ if(in_full_queue.id) { -+ kfree(in_full_queue.id); -+ in_full_queue.id = NULL; -+ } -+ if(in_busy_queue.id) { -+ kfree(in_busy_queue.id); -+ in_busy_queue.id = NULL; -+ } -+ -+ in_empty_queue.count = fragstotal; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ return 1; -+} -+ -+static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -+{ -+ jz_i2s_initHw(0); -+} -+ -+static int jz_audio_set_speed(int dev, int rate) -+{ -+ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -+ jz_audio_speed = rate; -+#if defined(CONFIG_I2S_DLV) -+ if (rate > 96000) -+ rate = 96000; -+#else -+ if (rate > 48000) -+ rate = 48000; -+#endif -+ if (rate < 8000) -+ rate = 8000; -+ jz_audio_rate = rate; -+ -+ if(set_codec_speed) -+ set_codec_speed(rate); -+ -+ return jz_audio_rate; -+} -+ -+ -+static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long data; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt++; -+ data = *(s++); -+ *(dp ++) = ((data << 16) >> 24) + 0x80; -+ s++; /* skip the other channel */ -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -+ d2 = *(s++); -+ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 2; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = (d1 << 16) >> 16; -+ s++; /* skip the other channel */ -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 4; /* count in byte */ -+ d1 = *(s++); -+ d2 = *(s++); -+ if(abnormal_data_count > 0) { -+ d1 = d2 = 0; -+ abnormal_data_count --; -+ } -+ *(dp ++) = (d1 << 16) >> 16; -+ *(dp ++) = (d2 << 16) >> 16; -+ } -+ -+ return cnt; -+} -+ -+static void replay_fill_1x8_u(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char data; -+ unsigned long ddata; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count--; -+ cnt += 1; -+ data = *(s++) - 0x80; -+ ddata = (unsigned long) data << 8; -+ *(dp ++) = ddata; -+ *(dp ++) = ddata; -+ -+ /* save last left and right */ -+ if(count == 1) { -+ save_last_samples[id].left = ddata; -+ save_last_samples[id].right = ddata; -+ } -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+ -+static void replay_fill_2x8_u(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char d1; -+ unsigned long dd1; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 1; -+ cnt += 1 ; -+ d1 = *(s++) - 0x80; -+ dd1 = (unsigned long) d1 << 8; -+ *(dp ++) = dd1; -+ /* save last left */ -+ if(count == 2) -+ save_last_samples[id].left = dd1; -+ /* save last right */ -+ if(count == 1) -+ save_last_samples[id].right = dd1; -+ } -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+ -+static void replay_fill_1x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2 ; -+ d1 = *(s++); -+ l1 = (signed long)d1; -+#if defined(CONFIG_I2S_ICODEC) -+ l1 >>= codec_volue_shift; -+#endif -+ *(dp ++) = l1; -+ *(dp ++) = l1; -+ -+ /* save last left and right */ -+ if(count == 1) { -+ save_last_samples[id].left = l1; -+ save_last_samples[id].right = l1; -+ } -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+#if defined(CONFIG_I2S_ICODEC) -+ int mute_cnt = 0; -+ signed long tmp1,tmp2; -+ volatile signed long *before_dp; -+ int sam_rate = jz_audio_rate / 20; -+ -+ tmp1 = tmp2 = 0; -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ l1 >>= codec_volue_shift; -+ -+ if(l1 == 0) { -+ mute_cnt ++; -+ if(mute_cnt >= sam_rate) { -+ before_dp = dp - 10; -+ *(before_dp) = (signed long)1; -+ before_dp = dp - 11; -+ *(before_dp) = (signed long)1; -+ mute_cnt = 0; -+ } -+ } else -+ mute_cnt = 0; -+ -+ *(dp ++) = l1; -+ -+ tmp1 = tmp2; -+ tmp2 = l1; -+ } -+ -+ /* save last left */ -+ save_last_samples[id].left = tmp1; -+ /* save last right */ -+ save_last_samples[id].right = tmp2; -+#endif -+#if defined(CONFIG_I2S_DLV) -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ -+ *(dp ++) = l1; -+ } -+#endif -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x18_s(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed long d1; -+ signed long l1; -+ volatile signed long *s = (signed long *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count -= 4; -+ cnt += 4; -+ d1 = *(s++); -+ l1 = (signed long)d1; -+ *(dp ++) = l1; -+ } -+ -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -+{ -+ switch (fmt) { -+ case AFMT_U8: -+ __i2s_set_oss_sample_size(8); -+ __i2s_set_iss_sample_size(8); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ break; -+ case AFMT_S16_LE: -+#if defined(CONFIG_I2S_DLV) -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x00); -+ //write_codec_file(2, 0x60); -+#endif -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ break; -+ case 18: -+ __i2s_set_oss_sample_size(18); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ break; -+ case AFMT_QUERY: -+ break; -+ } -+ -+ return jz_audio_format; -+} -+ -+ -+static short jz_audio_set_channels(int dev, short channels) -+{ -+ switch (channels) { -+ case 1: -+ if(set_codec_some_func) -+ set_codec_some_func(); -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -+#endif -+ break; -+ case 2: -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -+#endif -+ break; -+ case 0: -+ break; -+ } -+ -+ return jz_audio_channels; -+} -+ -+static void init_codec(void) -+{ -+ /* inititalize internal I2S codec */ -+ if(init_codec_pin) -+ init_codec_pin(); -+ -+#if defined(CONFIG_I2S_ICDC) -+ /* initialize AIC but not reset it */ -+ jz_i2s_initHw(0); -+#endif -+ if(reset_codec) -+ reset_codec(); -+} -+ -+static void jz_audio_reset(void) -+{ -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+#if defined(CONFIG_I2S_DLV) -+ REG_AIC_I2SCR = 0x10; -+#endif -+ init_codec(); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file); -+static int jz_audio_open(struct inode *inode, struct file *file); -+static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -+static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -+static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -+ -+/* static struct file_operations jz_i2s_audio_fops */ -+static struct file_operations jz_i2s_audio_fops = -+{ -+ owner: THIS_MODULE, -+ open: jz_audio_open, -+ release: jz_audio_release, -+ write: jz_audio_write, -+ read: jz_audio_read, -+ poll: jz_audio_poll, -+ ioctl: jz_audio_ioctl -+}; -+ -+static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -+{ -+ int i; -+ int minor = MINOR(inode->i_rdev); -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ -+ for (i = 0; i < NR_I2S; i++) -+ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -+ goto match; -+ -+ if (!controller) -+ return -ENODEV; -+match: -+ file->private_data = controller->i2s_codec[i]; -+ -+ return 0; -+} -+ -+static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -+ return codec->mixer_ioctl(codec, cmd, arg); -+} -+ -+static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -+{ -+ return -ESPIPE; -+} -+ -+static struct file_operations jz_i2s_mixer_fops = -+{ -+ owner: THIS_MODULE, -+ llseek: jz_i2s_llseek, -+ ioctl: jz_i2s_ioctl_mixdev, -+ open: jz_i2s_open_mixdev, -+}; -+ -+static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ long val = 0; -+ switch (cmd) { -+ case SOUND_MIXER_INFO: -+ -+ if(codec_mixer_info_id_name) -+ codec_mixer_info_id_name(); -+ info.modify_counter = audio_mix_modcnt; -+ -+ return copy_to_user((void *)arg, &info, sizeof(info)); -+ case SOUND_OLD_MIXER_INFO: -+ -+ if(codec_mixer_old_info_id_name) -+ codec_mixer_old_info_id_name(); -+ -+ return copy_to_user((void *)arg, &old_info, sizeof(info)); -+ case SOUND_MIXER_READ_STEREODEVS: -+ -+ return put_user(0, (long *) arg); -+ case SOUND_MIXER_READ_CAPS: -+ -+ val = SOUND_CAP_EXCL_INPUT; -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_READ_DEVMASK: -+ break; -+ case SOUND_MIXER_READ_RECMASK: -+ break; -+ case SOUND_MIXER_READ_RECSRC: -+ break; -+ case SOUND_MIXER_WRITE_SPEAKER: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ switch(val) { -+ case 100: -+ if(set_codec_direct_mode) -+ set_codec_direct_mode(); -+ break; -+ case 0: -+ if(clear_codec_direct_mode) -+ clear_codec_direct_mode(); -+ break; -+ } -+ break; -+ case SOUND_MIXER_WRITE_BASS: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ codec_bass_gain = val; -+ if(set_codec_bass) -+ set_codec_bass(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_BASS: -+ -+ val = codec_bass_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_VOLUME: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ -+ jz_audio_volume = val; -+ if(set_codec_volume) -+ set_codec_volume(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_VOLUME: -+ -+ val = jz_audio_volume; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ -+ case SOUND_MIXER_WRITE_MIC: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ codec_mic_gain = val; -+ use_mic_line_flag = USE_MIC; -+ if(set_codec_mic) -+ set_codec_mic(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_MIC: -+ -+ val = codec_mic_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ -+ case SOUND_MIXER_WRITE_LINE: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ use_mic_line_flag = USE_LINEIN; -+ codec_mic_gain = val; -+ if(set_codec_line) -+ set_codec_line(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_LINE: -+ -+ val = codec_mic_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ default: -+ return -ENOSYS; -+ } -+ audio_mix_modcnt ++; -+ return 0; -+} -+ -+ -+int i2s_probe_codec(struct i2s_codec *codec) -+{ -+ /* generic OSS to I2S wrapper */ -+ codec->mixer_ioctl = i2s_mixer_ioctl; -+ return 1; -+} -+ -+ -+/* I2S codec initialisation. */ -+static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -+{ -+ int num_i2s = 0; -+ struct i2s_codec *codec; -+ -+ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -+ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ memset(codec, 0, sizeof(struct i2s_codec)); -+ codec->private_data = controller; -+ codec->id = num_i2s; -+ -+ if (i2s_probe_codec(codec) == 0) -+ break; -+ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -+ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -+ kfree(codec); -+ break; -+ } -+ controller->i2s_codec[num_i2s] = codec; -+ } -+ return num_i2s; -+} -+ -+ -+static void jz_update_filler(int format, int channels) -+{ -+#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -+ -+ switch (TYPE(format, channels)) -+ { -+ -+ case TYPE(AFMT_U8, 1): -+ jz_audio_b = 4; /* 4bytes * 8bits =32bits */ -+ replay_filler = replay_fill_1x8_u; -+ record_filler = record_fill_1x8_u; -+ break; -+ case TYPE(AFMT_U8, 2): -+ jz_audio_b = 4; -+ replay_filler = replay_fill_2x8_u; -+ record_filler = record_fill_2x8_u; -+ break; -+ case TYPE(AFMT_S16_LE, 1): -+ jz_audio_b = 2; /* 2bytes * 16bits =32bits */ -+ replay_filler = replay_fill_1x16_s; -+ record_filler = record_fill_1x16_s; -+ break; -+ case TYPE(AFMT_S16_LE, 2): -+ jz_audio_b = 2; -+ replay_filler = replay_fill_2x16_s; -+ record_filler = record_fill_2x16_s; -+ break; -+ case TYPE(18, 2): -+ jz_audio_b = 1; -+ replay_filler = replay_fill_2x18_s; -+ record_filler = record_fill_2x16_s; -+ break; -+ default: -+ ; -+ } -+} -+ -+ -+#ifdef CONFIG_PROC_FS -+extern struct proc_dir_entry *proc_jz_root; -+int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ return 0; -+} -+ -+static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -+{ -+ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -+ return -EIO; -+ return 0; -+} -+ -+static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -+{ -+} -+#endif -+ -+static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ char *name; -+ int adev; /* No of Audio device. */ -+ -+ name = controller->name; -+ /* initialize AIC controller and reset it */ -+ jz_i2s_initHw(1); -+ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -+ if (adev < 0) -+ goto audio_failed; -+ /* initialize I2S codec and register /dev/mixer */ -+ if (jz_i2s_codec_init(controller) <= 0) -+ goto mixer_failed; -+ -+#ifdef CONFIG_PROC_FS -+ if (jz_i2s_init_proc(controller) < 0) { -+ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -+ goto proc_failed; -+ } -+#endif -+ -+ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); -+ if (!controller->tmp1) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp1_failed; -+ } -+ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); -+ if (!controller->tmp2) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp2_failed; -+ } -+ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -+ goto dma2_failed; -+ } -+ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -+ goto dma1_failed; -+ } -+ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -+ -+ controller->dev_audio = adev; -+ pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); -+ if(!pop_turn_onoff_buf) -+ printk("pop_turn_onoff_buf alloc is wrong!\n"); -+ pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); -+ -+ return; -+dma2_failed: -+ jz_free_dma(controller->dma1); -+dma1_failed: -+ free_pages((unsigned long)controller->tmp2, 8); -+tmp2_failed: -+ free_pages((unsigned long)controller->tmp1, 8); -+tmp1_failed: -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+proc_failed: -+ /* unregister mixer dev */ -+mixer_failed: -+ unregister_sound_dsp(adev); -+audio_failed: -+ return; -+} -+ -+static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -+{ -+ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -+ return -ENOMEM; -+ } -+ (*controller)->name = "Jz I2S controller"; -+ (*controller)->opened1 = 0; -+ (*controller)->opened2 = 0; -+ init_waitqueue_head(&(*controller)->adc_wait); -+ init_waitqueue_head(&(*controller)->dac_wait); -+ spin_lock_init(&(*controller)->lock); -+ init_waitqueue_head(&rx_wait_queue); -+ init_waitqueue_head(&tx_wait_queue); -+ init_waitqueue_head(&pop_wait_queue); -+ init_waitqueue_head(&drain_wait_queue); -+ -+ return 0; -+} -+ -+static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ int adev = controller->dev_audio; -+ -+ jz_i2s_full_reset(controller); -+ controller->dev_audio = -1; -+ if (old_mksound) -+ kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+ -+ jz_free_dma(controller->dma1); -+ jz_free_dma(controller->dma2); -+ free_pages((unsigned long)controller->tmp1, 8); -+ free_pages((unsigned long)controller->tmp2, 8); -+ free_pages((unsigned long)pop_turn_onoff_buf, 8); -+ -+ if (adev >= 0) { -+ /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ -+ unregister_sound_dsp(controller->dev_audio); -+ } -+} -+ -+#ifdef CONFIG_PM -+static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -+{ -+ if(i2s_suspend_codec) -+ i2s_suspend_codec(controller->opened1,controller->opened2); -+ printk("Aic and codec are suspended!\n"); -+ return 0; -+} -+ -+static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -+{ -+ if(i2s_resume_codec) -+ i2s_resume_codec(); -+ -+#if defined(CONFIG_I2S_AK4642EN) -+ jz_i2s_initHw(0); -+ jz_audio_reset(); -+ __i2s_enable(); -+ jz_audio_set_speed(controller->dev_audio,jz_audio_speed); -+ /* playing */ -+ if(controller->opened1) { -+ if(set_codec_replay) -+ set_codec_replay(); -+ int dma = controller->dma1; -+ int id; -+ unsigned long flags; -+ disable_dma(dma); -+ if(__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if(__dmac_channel_transmit_end_detected(dma)) -+ __dmac_channel_clear_transmit_end(dma); -+ -+ /* for DSP_GETOPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ while((id = get_buffer_id(&out_busy_queue)) >= 0) -+ put_buffer_id(&out_empty_queue, id); -+ -+ out_busy_queue.count=0; -+ if((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_empty_queue, id); -+ } -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } else -+ printk("pm out_empty_queue empty"); -+ } -+ -+ /* recording */ -+ if(controller->opened2) { -+ if(set_codec_record) -+ set_codec_record(use_mic_line_flag); -+ int dma = controller->dma2; -+ int id1, id2; -+ unsigned long flags; -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ } -+ /* for DSP_GETIPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_full_queue, id2); -+ } -+ in_busy_queue.count = 0; -+ } -+#endif -+ -+ return 0; -+} -+ -+static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct jz_i2s_controller_info *controller = pm_dev->data; -+ -+ if (!controller) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jz_i2s_suspend(controller, (int)data); -+ break; -+ case PM_RESUME: -+ ret = jz_i2s_resume(controller); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#endif /* CONFIG_PM */ -+ -+#if defined(CONFIG_I2S_DLV) -+static irqreturn_t aic_codec_irq(int irq, void *dev_id) -+{ -+ u8 file_9 = read_codec_file(9); -+ u8 file_8 = read_codec_file(8); -+ -+ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -+ if ((file_9 & 0x1f) == 0x10) { -+ -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x4) != 0x4); -+ while ((read_codec_file(9) & 0x10) == 0x10) { -+ write_codec_file(9, 0x10); -+ } -+ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x8) != 0x8); -+ write_codec_file(9, file_9); -+ write_codec_file(8, file_8); -+ -+ return IRQ_HANDLED; -+ } -+ -+ if (file_9 & 0x8) -+ ramp_up_end = jiffies; -+ else if (file_9 & 0x4) -+ ramp_down_end = jiffies; -+ else if (file_9 & 0x2) -+ gain_up_end = jiffies; -+ else if (file_9 & 0x1) -+ gain_down_end = jiffies; -+ -+ write_codec_file(9, file_9); -+ if (file_9 & 0xf) -+ wake_up(&pop_wait_queue); -+ while (REG_ICDC_RGDATA & 0x100); -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+static int __init init_jz_i2s(void) -+{ -+ int errno; -+#if defined(CONFIG_I2S_DLV) -+ int retval; -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+#endif -+ use_mic_line_flag = USE_NONE; -+ abnormal_data_count = 0; -+ if(set_codec_mode) -+ set_codec_mode(); -+ -+ drain_flag = 0; -+ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -+ return errno; -+ if(set_codec_gpio_pin) -+ set_codec_gpio_pin(); -+ -+ attach_jz_i2s(i2s_controller); -+ if(set_codec_startup_param) -+ set_codec_startup_param(); -+ if(set_codec_volume_table) -+ set_codec_volume_table(); -+ -+#if defined(CONFIG_I2S_DLV) -+ jz_codec_config = 0; -+ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -+ if (retval) { -+ printk("Could not get aic codec irq %d\n", IRQ_AIC); -+ return retval; -+ } -+#endif -+ -+ out_empty_queue.id = NULL; -+ out_full_queue.id = NULL; -+ out_busy_queue.id = NULL; -+ in_empty_queue.id = NULL; -+ in_full_queue.id = NULL; -+ in_busy_queue.id = NULL; -+ -+ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -+ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+#ifdef CONFIG_PM -+ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -+ jz_i2s_pm_callback); -+ if (i2s_controller->pm) -+ i2s_controller->pm->data = i2s_controller; -+#endif -+#if defined(CONFIG_I2S_DLV) -+ __cpm_start_idct(); -+ __cpm_start_db(); -+ __cpm_start_me(); -+ __cpm_start_mc(); -+ __cpm_start_ipu(); -+#endif -+ printk("JZ I2S OSS audio driver initialized\n"); -+ -+ return 0; -+} -+ -+static void __exit cleanup_jz_i2s(void) -+{ -+#ifdef CONFIG_PM -+ /* pm_unregister(i2s_controller->pm); */ -+#endif -+#if defined(CONFIG_I2S_DLV) -+ free_irq(IRQ_AIC, NULL); -+#endif -+ unload_jz_i2s(i2s_controller); -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ if(clear_codec_mode) -+ clear_codec_mode(); -+} -+ -+module_init(init_jz_i2s); -+module_exit(cleanup_jz_i2s); -+ -+#if defined(CONFIG_SOC_JZ4730) -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,con; -+ -+ if(elements_in_queue(&in_busy_queue) > 0) { -+ if (nonblock) -+ return -EBUSY; -+ drain_flag = 1; -+ sleep_on(&drain_wait_queue); -+ drain_flag = 0; -+ } else { -+ add_wait_queue(&ctrl->adc_wait, &wait); -+ for (con = 0; con < 1000; con ++) { -+ udelay(1); -+ set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ if (nonblock) { -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ } -+ return 0; -+} -+ -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count; -+ -+ if(elements_in_queue(&out_full_queue) > 0) { -+ if (nonblock) -+ return -EBUSY; -+ -+ drain_flag = 1; -+ sleep_on(&drain_wait_queue); -+ drain_flag = 0; -+ } else { -+ add_wait_queue(&(ctrl->dac_wait), &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if(elements_in_queue(&out_full_queue) <= 0) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if(count <= 0) -+ break; -+ } -+ if (nonblock) { -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ } -+ -+ return 0; -+} -+#endif -+ -+#if defined(CONFIG_SOC_JZ4740) -+#define MAXDELAY 50000 -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ int count,ele,i=0; -+ int tfl; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if ( i < MAXDELAY ) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(10); -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ } -+ } else {//non-blocked -+ mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ mdelay(100); -+ -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ -+ /* wait for TX fifo */ -+ while (1) { -+ tfl = __aic_get_transmit_resident(); -+ if (tfl == 0) -+ break; -+ udelay(2); -+ } -+ -+ return 0; -+} -+ -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ int count,i=0; -+ -+ for (;;) { -+ if ( i < MAXDELAY ) -+ { -+ udelay(10); -+ i++; -+ } -+ else -+ break; -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ if (nonblock) { -+ return -EBUSY; -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+#define MAXDELAY 50000 -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ //DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,i=0; -+ -+ //add_wait_queue(&ctrl->adc_wait, &wait); -+ for (;;) { -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ //set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ //spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ //spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ /*if (signal_pending(current)) -+ break;*/ -+ if (nonblock) { -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ /*if (signal_pending(current)) -+ return -ERESTARTSYS;*/ -+ return 0; -+} -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ unsigned long flags; -+ int count,ele,busyele,emptyele,i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(200); -+ -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } else {//non-blocked -+ //mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ //mdelay(100); -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+static int jz_audio_release(struct inode *inode, struct file *file) -+{ -+ unsigned long flags; -+#if defined(CONFIG_I2S_DLV) -+ unsigned long tfl; -+#endif -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+#if defined(CONFIG_I2S_DLV) -+ jz_codec_config = 0; -+#endif -+ if (controller == NULL) -+ return -ENODEV; -+ -+ pop_dma_flag = 0; -+ -+ if (controller->opened1 == 1 && controller->opened2 == 1) { -+ controller->opened1 = 0; -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+#if defined(CONFIG_I2S_DLV) -+ /* wait for fifo empty */ -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ gain_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_down_end = jiffies; -+ /*while (1) { -+ tfl = REG_AIC_SR & 0x00003f00; -+ if (tfl == 0) { -+ udelay(500); -+ break; -+ } -+ mdelay(2); -+ }*/ -+ mdelay(100); -+#endif -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable_replay(); -+ -+#if defined(CONFIG_I2S_ICODEC) -+ if(clear_codec_replay) -+ clear_codec_replay(); -+#endif -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ controller->opened2 = 0; -+ first_record_call = 1; -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+#if defined(CONFIG_I2S_ICODEC) -+ if(clear_codec_record) -+ clear_codec_record(); -+#endif -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ ramp_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_down_end = jiffies; -+ if (use_mic_line_flag == USE_LINEIN) { -+ unset_record_line_input_audio_with_audio_data_replay(); -+ //printk("3 use_mic_line_flag=%d\n",use_mic_line_flag); -+ } -+ if (use_mic_line_flag == USE_MIC) { -+ unset_record_mic_input_audio_with_audio_data_replay(); -+ //printk("4 use_mic_line_flag=%d\n",use_mic_line_flag); -+ } -+ -+#if 0 -+ unset_record_playing_audio_mixed_with_mic_input_audio(); -+#endif -+#endif -+ __i2s_disable(); -+ if(turn_off_codec) -+ turn_off_codec(); -+ abnormal_data_count = 0; -+ } else if (controller->opened1 == 1) { -+ //controller->opened1 = 0; -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ /* add some mute to anti-pop */ -+#if defined(CONFIG_I2S_ICODEC) -+ //write_mute_to_dma_buffer(save_last_samples[last_dma_buffer_id].left,save_last_samples[last_dma_buffer_id].right); -+#endif -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ gain_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_down_end = jiffies; -+ while (1) { -+ tfl = REG_AIC_SR & 0x00003f00; -+ if (tfl == 0) { -+ udelay(500); -+ break; -+ } -+ mdelay(2); -+ } -+#endif -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable_replay(); -+#if defined(CONFIG_I2S_ICODEC) -+ if(clear_codec_replay) -+ clear_codec_replay(); -+#endif -+ __aic_flush_fifo(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ ramp_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_down_end = jiffies; -+ unset_audio_data_replay(); -+#endif -+ __i2s_disable(); -+#if defined(CONFIG_I2S_ICODEC) -+ if(turn_off_codec) -+ turn_off_codec(); -+#endif -+ } else if (controller->opened2 == 1) { -+ controller->opened2 = 0; -+ first_record_call = 1; -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+#if defined(CONFIG_I2S_ICODEC) -+ if(clear_codec_record) -+ clear_codec_record(); -+#endif -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+#if defined(CONFIG_I2S_DLV) -+#if 0 -+ /* unset Record MIC input audio with direct playback */ -+ unset_record_mic_input_audio_with_direct_playback(); -+#endif -+#if 1 -+ /* unset Record MIC input audio without playback */ -+ unset_record_mic_input_audio_without_playback(); -+#endif -+#if 0 -+ /* tested */ -+ /* unset Record LINE input audio without playback */ -+ unset_record_line_input_audio_without_playback(); -+#endif -+#endif -+ __i2s_disable(); -+#if defined(CONFIG_I2S_ICODEC) -+ if(turn_off_codec) -+ turn_off_codec(); -+#endif -+ abnormal_data_count = 0; -+ } -+ -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+/* __cpm_stop_idct(); -+ __cpm_stop_db(); -+ __cpm_stop_me(); -+ __cpm_stop_mc(); -+ __cpm_stop_ipu();*/ -+#endif -+ -+ if (controller->opened1 == 1 && controller->opened2 == 1) { -+ controller->opened1 = 0; -+ controller->opened2 = 0; -+ //print_pop_duration(); -+ //__dmac_disable_module(0); -+ } else if ( controller->opened1 == 1 ) { -+ controller->opened1 = 0; -+ //print_pop_duration(); -+ } else if ( controller->opened2 == 1 ) { -+ controller->opened2 = 0; -+ } -+ -+ return 0; -+} -+ -+static int jz_audio_open(struct inode *inode, struct file *file) -+{ -+ int i; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+#if defined(CONFIG_I2S_DLV) -+ jz_codec_config = 0; -+#endif -+ if (controller == NULL) -+ return -ENODEV; -+ -+ mdelay(2); -+#if defined(CONFIG_I2S_DLV) -+ REG_DMAC_DMACKE(0) = 0x3f; -+#endif -+ pop_dma_flag = 0; -+ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -+ printk("\naudio is busy!\n"); -+ return -EBUSY; -+ } -+ -+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ controller->opened1 = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ for(i=0;i < 64;i++) { -+ save_last_samples[i].left = 0; -+ save_last_samples[i].right = 0; -+ } -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ last_dma_buffer_id = 0; -+ -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ -+ controller->opened2 = 1; -+ first_record_call = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ } else if (file->f_mode & FMODE_WRITE) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ -+ controller->opened1 = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ for(i=0;i < 64;i++) { -+ save_last_samples[i].left = 0; -+ save_last_samples[i].right = 0; -+ } -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ last_dma_buffer_id = 0; -+ } else if (file->f_mode & FMODE_READ) { -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ -+ controller->opened2 = 1; -+ first_record_call = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ } -+ -+ file->private_data = controller; -+ jz_audio_reset(); -+ REG_AIC_FR |= (1 << 6); -+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -+#if defined(CONFIG_I2S_ICODEC) -+ if (set_codec_replay_record) -+ set_codec_replay_record(use_mic_line_flag); -+#endif -+#if defined(CONFIG_I2S_DLV) -+ if (use_mic_line_flag == USE_NONE) { -+ printk("you select mic or line recording please.or use mic recording!\n"); -+ use_mic_line_flag = USE_MIC; -+ } -+ if (use_mic_line_flag == USE_LINEIN) { -+ /* Record LINE input audio with Audio data replay (full duplex for linein) */ -+ /* codec_test_line */ -+ set_record_line_input_audio_with_audio_data_replay(); -+ -+ } -+ if (use_mic_line_flag == USE_MIC) { -+ /* Record MIC input audio with Audio data replay (full duplex) */ -+ /* codec_test_mic */ -+ set_record_mic_input_audio_with_audio_data_replay(); -+ } -+#if 0 -+ /* Record playing audio mixed with MIC input audio */ -+ set_record_playing_audio_mixed_with_mic_input_audio(); -+#endif -+ -+#endif -+ } else if (file->f_mode & FMODE_WRITE) { -+#if defined(CONFIG_I2S_ICODEC) -+ if(set_codec_replay) -+ set_codec_replay(); -+#endif -+#if defined(CONFIG_I2S_DLV) -+ //mdelay(10); -+ /* Audio data replay */ -+ set_audio_data_replay(); -+#endif -+ } else if (file->f_mode & FMODE_READ) { -+#if defined(CONFIG_I2S_ICODEC) -+ abnormal_data_count = 0; -+ if(set_codec_record) -+ set_codec_record(use_mic_line_flag); -+#endif -+#if defined(CONFIG_I2S_DLV) -+#if 0 -+ /* Record MIC input audio with direct playback */ -+ set_record_mic_input_audio_with_direct_playback(); -+#endif -+ -+#if 1 -+ /* set Record MIC input audio without playback */ -+ set_record_mic_input_audio_without_playback(); -+#endif -+#if 0 -+ /* tested */ -+ /* set Record LINE input audio without playback */ -+ set_record_line_input_audio_without_playback(); -+#endif -+ mdelay(1); -+#endif -+ } -+ -+#if defined(CONFIG_I2S_DLV) -+ __aic_reset(); -+ -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ __aic_flush_fifo(); -+#endif -+ -+ __i2s_enable(); -+ -+#if defined(CONFIG_I2S_DLV) -+ ndelay(100); -+ -+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -+#if defined(CONFIG_I2S_DLV) -+ //set SB_ADC or SB_DAC -+ __dmac_enable_module(0); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ ramp_up_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_up_end = jiffies; -+#endif -+ } else if (file->f_mode & FMODE_WRITE) { -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ ramp_up_start = jiffies; -+ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RCR = 0x1; -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RGR = 1;*/ -+ sleep_on(&pop_wait_queue); -+ //ramp_up_end = jiffies; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+#endif -+ } else if (file->f_mode & FMODE_READ) { -+#if defined(CONFIG_I2S_DLV) -+ if (jz_mic_only) -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ else -+ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -+ mdelay(500); -+#endif -+ } -+#endif -+ return 0; -+} -+ -+ -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+unsigned int cmd, unsigned long arg) -+{ -+ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ count_info cinfo; -+ audio_buf_info abinfo; -+ int id, i; -+ -+ val = 0; -+ switch (cmd) { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, (int *)arg); -+ case SNDCTL_DSP_RESET: -+#if 0 -+ jz_audio_reset(); -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+#endif -+ return 0; -+ case SNDCTL_DSP_SYNC: -+ if (file->f_mode & FMODE_WRITE) -+ return drain_dac(controller, file->f_flags & O_NONBLOCK); -+ return 0; -+ case SNDCTL_DSP_SPEED: -+ /* set smaple rate */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val >= 0) -+ jz_audio_set_speed(controller->dev_audio, val); -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_STEREO: -+ /* set stereo or mono channel */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -+ -+ return 0; -+ case SNDCTL_DSP_GETBLKSIZE: -+ //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); -+ return put_user(jz_audio_fragsize, (int *)arg); -+ case SNDCTL_DSP_GETFMTS: -+ /* Returns a mask of supported sample format*/ -+ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -+ case SNDCTL_DSP_SETFMT: -+ /* Select sample format */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val != AFMT_QUERY) -+ jz_audio_set_format(controller->dev_audio,val); -+ else { -+ if (file->f_mode & FMODE_READ) -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ else -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ } -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val); -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_POST: -+ /* FIXME: the same as RESET ?? */ -+ return 0; -+ case SNDCTL_DSP_SUBDIVIDE: -+ return 0; -+ case SNDCTL_DSP_SETFRAGMENT: -+ get_user(val, (long *) arg); -+ newfragsize = 1 << (val & 0xFFFF); -+ if (newfragsize < 4 * PAGE_SIZE) -+ newfragsize = 4 * PAGE_SIZE; -+ if (newfragsize > (16 * PAGE_SIZE)) -+ newfragsize = 16 * PAGE_SIZE; -+ -+ newfragstotal = (val >> 16) & 0x7FFF; -+ if (newfragstotal < 2) -+ newfragstotal = 2; -+ if (newfragstotal > 32) -+ newfragstotal = 32; -+ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -+ return 0; -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(500); -+ jz_audio_fragstotal = newfragstotal; -+ jz_audio_fragsize = newfragsize; -+ -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(10); -+ -+ return 0; -+ case SNDCTL_DSP_GETCAPS: -+ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -+ case SNDCTL_DSP_NONBLOCK: -+ file->f_flags |= O_NONBLOCK; -+ return 0; -+ case SNDCTL_DSP_SETDUPLEX: -+ return -EINVAL; -+ case SNDCTL_DSP_GETOSPACE: -+ { -+ int i; -+ unsigned long bytes = 0; -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_fragments = elements_in_queue(&out_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ if (jz_audio_channels == 2) -+ bytes /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ bytes /= 4; -+ else -+ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); -+ -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ /* unused fragment amount */ -+ abinfo.fragments = jz_audio_fragments; -+ /* amount of fragments */ -+ abinfo.fragstotal = jz_audio_fragstotal; -+ /* fragment size in bytes */ -+ if (jz_audio_channels == 2) -+ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -+ else if (jz_audio_channels == 1) -+ abinfo.fragsize = jz_audio_fragsize / 4; -+ else -+ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); -+ -+ /* write size count without blocking in bytes */ -+ abinfo.bytes = (int)bytes; -+ -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETISPACE: -+ { -+ int i; -+ unsigned long bytes = 0; -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ jz_audio_fragments = elements_in_queue(&in_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ if (jz_audio_channels == 2) -+ bytes /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ bytes /= 4; -+ else -+ printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); -+ -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ -+ if (jz_audio_channels == 2) -+ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -+ else if (jz_audio_channels == 1) -+ abinfo.fragsize = jz_audio_fragsize / 4; -+ else -+ printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); -+ -+ abinfo.bytes = (int)bytes; -+ -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETTRIGGER: -+ val = 0; -+ if (file->f_mode & FMODE_READ && in_dma_buf) -+ val |= PCM_ENABLE_INPUT; -+ if (file->f_mode & FMODE_WRITE && out_dma_buf) -+ val |= PCM_ENABLE_OUTPUT; -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_SETTRIGGER: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ return 0; -+ case SNDCTL_DSP_GETIPTR: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextIn; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETOPTR: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextOut; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETODELAY: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ unfinish = 0; -+ fullc = elements_in_queue(&out_full_queue); -+ busyc = elements_in_queue(&out_busy_queue); -+ for(i = 0;i < fullc ;i ++) { -+ id = *(out_full_queue.id + i); -+ unfinish += *(out_dma_buf_data_count + id); -+ } -+ for(i = 0;i < busyc ;i ++) { -+ id = *(out_busy_queue.id + i); -+ unfinish += get_dma_residue(controller->dma1); -+ } -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (jz_audio_channels == 2) -+ unfinish /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ unfinish /= 4; -+ else -+ printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); -+ -+ return put_user(unfinish, (int *) arg); -+ case SOUND_PCM_READ_RATE: -+ return put_user(jz_audio_rate, (int *)arg); -+ case SOUND_PCM_READ_CHANNELS: -+ return put_user(jz_audio_channels, (int *)arg); -+ case SOUND_PCM_READ_BITS: -+ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -+ case SNDCTL_DSP_MAPINBUF: -+ case SNDCTL_DSP_MAPOUTBUF: -+ case SNDCTL_DSP_SETSYNCRO: -+ case SOUND_PCM_WRITE_FILTER: -+ case SOUND_PCM_READ_FILTER: -+ return -EINVAL; -+ } -+ return -EINVAL; -+} -+ -+ -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long flags; -+ unsigned int mask = 0; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ return POLLOUT | POLLWRNORM; -+ -+ poll_wait(file, &controller->dac_wait, wait); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ return POLLIN | POLLRDNORM; -+ -+ poll_wait(file, &controller->adc_wait, wait); -+ } -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ mask |= POLLOUT | POLLWRNORM; -+ } else if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ mask |= POLLIN | POLLRDNORM; -+ } -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ return mask; -+} -+ -+static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ int id, ret = 0, left_count, copy_count, cnt = 0; -+ unsigned long flags; -+ -+ if (count < 0) -+ return -EINVAL; -+ -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ copy_count = jz_audio_fragsize / 4; -+ -+ left_count = count; -+ if (first_record_call) { -+ first_record_call = 0; -+ audio_read_back_first: -+ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ -+ spin_unlock(&controller->lock); -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ sleep_on(&rx_wait_queue); -+ } else -+ goto audio_read_back_first; -+ } -+ -+ while (left_count > 0) { -+ audio_read_back_second: -+ if (elements_in_queue(&in_full_queue) <= 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret ? ret : -EAGAIN; -+ else -+ sleep_on(&rx_wait_queue); -+ } -+ -+ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -+ spin_lock(&controller->lock); -+ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -+ spin_unlock(&controller->lock); -+ put_buffer_id(&in_empty_queue, id); -+ } else -+ goto audio_read_back_second; -+ -+ if (elements_in_queue(&in_busy_queue) == 0) { -+ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ spin_unlock(&controller->lock); -+ -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ } -+ } -+ if (ret + cnt > count) { -+ spin_lock(&controller->lock); -+ cnt = count - ret; -+ spin_unlock(&controller->lock); -+ } -+ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -+ return ret ? ret : -EFAULT; -+ -+ spin_lock(&controller->lock); -+ ret += cnt; -+ spin_unlock(&controller->lock); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ spin_lock(&controller->lock); -+ left_count -= cnt; -+ spin_unlock(&controller->lock); -+ } -+ return ret; -+} -+ -+static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -+{ -+ int id, ret = 0, left_count, copy_count = 0; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ -+ if (count <= 0) -+ return -EINVAL; -+ -+ if(set_replay_hp_or_speaker) -+ set_replay_hp_or_speaker(); -+ -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if (jz_audio_channels == 2) -+ copy_count = jz_audio_fragsize / jz_audio_b; -+ else if(jz_audio_channels == 1) -+ copy_count = jz_audio_fragsize / 4; -+ left_count = count; -+ if (copy_from_user(controller->tmp1, buffer, count)) { -+ printk("copy_from_user failed:%d",ret); -+ return ret ? ret : -EFAULT; -+ } -+ -+ while (left_count > 0) { -+ audio_write_back: -+ if (file->f_flags & O_NONBLOCK) -+ udelay(2); -+ if (elements_in_queue(&out_empty_queue) == 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret; -+ else -+ sleep_on(&tx_wait_queue); -+ } -+ /* the end fragment size in this write */ -+ if (ret + copy_count > count) -+ copy_count = count - ret; -+ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -+ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ put_buffer_id(&out_full_queue, id); -+ dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); -+ } else -+ put_buffer_id(&out_empty_queue, id); -+ } else -+ goto audio_write_back; -+ -+ left_count = left_count - copy_count; -+ ret += copy_count; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (elements_in_queue(&out_busy_queue) == 0) { -+ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(controller->dma1, -+ file->private_data, -+ *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ last_dma_buffer_id = id; -+#if defined(CONFIG_I2S_DLV) -+ if (jz_codec_config == 0) { -+ write_codec_file_bit(1, 0, 5); -+ gain_up_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_up_end = jiffies; -+ jz_codec_config = 1; -+ //SB_ADC->1 -+ //write_codec_file_bit(5, 1, 4); -+ //while(1); -+ } -+#endif -+ } -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+#if defined(CONFIG_I2S_ICODEC) -+static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -+{ -+ int i,step_len; -+ unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; -+ unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -+ unsigned long l_sample_count,r_sample_count,sample_count; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ signed int left_sam=0,right_sam=0,l_val,r_val; -+ -+ switch (sample_oss) { -+ case 0x0: -+ break; -+ case 0x1: -+ left_sam = (signed int)l_sample; -+ right_sam = (signed int)r_sample; -+ break; -+ case 0x2: -+ break; -+ case 0x3: -+ break; -+ case 0x4: -+ break; -+ } -+ -+ if(left_sam == 0 && right_sam == 0) -+ return; -+ -+ switch (sample_oss) { -+ case 0x0: -+ break; -+ case 0x1: -+ step_len = jz_audio_speed / 10 * 3; -+ step_len = step_len / 2; -+ step_len = 0x7fff / step_len + 1; -+ -+ l_sample_count = 0; -+ l_val = left_sam; -+ -+ while(1) { -+ if(l_val > 0) { -+ if(l_val >= step_len) { -+ l_val -= step_len; -+ l_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(l_val < 0) { -+ if(l_val <= -step_len) { -+ l_val += step_len; -+ l_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(l_val == 0) -+ break; -+ } -+ -+ r_sample_count = 0; -+ r_val = right_sam; -+ while(1) { -+ if(r_val > 0) { -+ if(r_val >= step_len) { -+ r_val -= step_len; -+ r_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(r_val < 0) { -+ if(r_val <= -step_len) { -+ r_val += step_len; -+ r_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(r_val == 0) -+ break; -+ } -+ /* fill up */ -+ if(l_sample_count > r_sample_count) -+ sample_count = l_sample_count; -+ else -+ sample_count = r_sample_count; -+ -+ l_val = left_sam; -+ r_val = right_sam; -+ for(i=0;i <= sample_count;i++) { -+ -+ *pop_buf = (unsigned long)l_val; -+ pop_buf ++; -+ -+ if(l_val > step_len) -+ l_val -= step_len; -+ else if(l_val < -step_len) -+ l_val += step_len; -+ else if(l_val >= -step_len && l_val <= step_len) -+ l_val = 0; -+ -+ *pop_buf = (unsigned long)r_val; -+ pop_buf ++; -+ if(r_val > step_len) -+ r_val -= step_len; -+ else if(r_val < -step_len) -+ r_val += step_len; -+ else if(r_val >= -step_len && r_val <= step_len) -+ r_val = 0; -+ } -+ -+ *pop_buf = 0; -+ pop_buf ++; -+ *pop_buf = 0; -+ -+ pop_buf ++; -+ sample_count += 2; -+ dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); -+ -+ pop_dma_flag = 1; -+ audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); -+ sleep_on(&pop_wait_queue); -+ pop_dma_flag = 0; -+ break; -+ case 0x2: -+ break; -+ case 0x3: -+ break; -+ case 0x4: -+ break; -+ } -+} -+#endif -diff --git a/sound/oss/jz_i2s_4750.c b/sound/oss/jz_i2s_4750.c -new file mode 100644 -index 0000000..d99fa8d ---- /dev/null -+++ b/sound/oss/jz_i2s_4750.c -@@ -0,0 +1,3010 @@ -+/* -+ * linux/drivers/sound/Jz_i2s.c -+ * -+ * JzSOC On-Chip I2S audio driver. -+ * -+ * Copyright (C) 2005 by Junzheng Corp. -+ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -+ * dma channel 4&3,noah is tested. -+ * -+ * 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. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sound_config.h" -+ -+#define DPRINTK(args...) printk(args) -+#define DMA_ID_I2S_TX DMA_ID_AIC_TX -+#define DMA_ID_I2S_RX DMA_ID_AIC_RX -+#define NR_I2S 2 -+#define MAXDELAY 50000 -+#define JZCODEC_RW_BUFFER_SIZE 2 -+#define JZCODEC_RW_BUFFER_TOTAL 6 -+ -+typedef struct hpvol_shift_s -+{ -+ int hpvol; -+ int shift; -+} hpvol_shift_t; -+ -+mixer_info info; -+_old_mixer_info old_info; -+int codec_volue_shift; -+hpvol_shift_t hpvol_shift_table[72]; -+int abnormal_data_count; -+unsigned long i2s_clk; -+ -+void (*set_codec_mode)(void) = NULL; -+void (*clear_codec_mode)(void) = NULL; -+void (*set_codec_gpio_pin)(void) = NULL; -+void (*each_time_init_codec)(void) = NULL; -+int (*set_codec_startup_param)(void) = NULL; -+void (*set_codec_volume_table)(void) = NULL; -+void (*set_codec_record)(void) = NULL; -+void (*set_codec_replay)(void) = NULL; -+void (*set_codec_replay_record)(void); -+void (*turn_on_codec)(void) = NULL; -+void (*turn_off_codec)(void) = NULL; -+void (*set_codec_speed)(int rate) = NULL; -+void (*reset_codec)(void) = NULL; -+void (*codec_mixer_old_info_id_name)(void) = NULL; -+void (*codec_mixer_info_id_name)(void) = NULL; -+void (*set_codec_bass)(int val) = NULL; -+void (*set_codec_volume)(int val) = NULL; -+void (*set_codec_mic)(int val) = NULL; -+void (*i2s_resume_codec)(void) = NULL; -+void (*i2s_suspend_codec)(int wr,int rd) = NULL; -+void (*init_codec_pin)(void) = NULL; -+void (*set_codec_some_func)(void) = NULL; -+void (*clear_codec_record)(void) = NULL; -+void (*clear_codec_replay)(void) = NULL; -+void (*set_replay_hp_or_speaker)(void) = NULL; -+void (*set_codec_direct_mode)(void) = NULL; -+void (*clear_codec_direct_mode)(void) = NULL; -+ -+static int jz_audio_rate; -+static int jz_audio_format; -+static int jz_audio_volume; -+static int jz_audio_channels; -+static int jz_audio_b; /* bits expand multiple */ -+static int jz_audio_fragments; /* unused fragment amount */ -+static int jz_audio_fragstotal; -+static int jz_audio_fragsize; -+static int jz_audio_speed; -+ -+static int codec_bass_gain; -+static int audio_mix_modcnt; -+static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -+static int jz_mic_only = 1; -+static int jz_codec_config = 0; -+static unsigned long ramp_up_start; -+static unsigned long ramp_up_end; -+static unsigned long gain_up_start; -+static unsigned long gain_up_end; -+static unsigned long ramp_down_start; -+static unsigned long ramp_down_end; -+static unsigned long gain_down_start; -+static unsigned long gain_down_end; -+ -+static int codec_mic_gain; -+static int pop_dma_flag; -+static int last_dma_buffer_id; -+static int drain_flag; -+ -+static void (*old_mksound)(unsigned int hz, unsigned int ticks); -+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -+static void jz_update_filler(int bits, int channels); -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize); -+static int Free_In_Out_queue(int fragstotal,int fragsize); -+static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -+static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -+static void (*replay_filler)(signed long src_start, int count, int id); -+static int (*record_filler)(unsigned long dst_start, int count, int id); -+#if defined(CONFIG_I2S_ICODEC) -+static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -+#endif -+static void jz_audio_reset(void); -+static struct file_operations jz_i2s_audio_fops; -+ -+static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -+ -+struct jz_i2s_controller_info -+{ -+ int io_base; -+ int dma1; /* for play */ -+ int dma2; /* for record */ -+ char *name; -+ int dev_audio; -+ struct i2s_codec *i2s_codec[NR_I2S]; -+ int opened1; -+ int opened2; -+ unsigned char *tmp1; /* tmp buffer for sample conversions */ -+ unsigned char *tmp2; -+ spinlock_t lock; -+ spinlock_t ioctllock; -+ -+ wait_queue_head_t dac_wait; -+ wait_queue_head_t adc_wait; -+ int nextIn; /* byte index to next-in to DMA buffer */ -+ int nextOut; /* byte index to next-out from DMA buffer */ -+ int count; /* current byte count in DMA buffer */ -+ int finish; /* current transfered byte count in DMA buffer */ -+ unsigned total_bytes; /* total bytes written or read */ -+ unsigned blocks; -+ unsigned error; /* over/underrun */ -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+ -+static struct jz_i2s_controller_info *i2s_controller = NULL; -+struct i2s_codec -+{ -+ /* I2S controller connected with */ -+ void *private_data; -+ char *name; -+ int id; -+ int dev_mixer; -+ /* controller specific lower leverl i2s accessing routines */ -+ u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ -+ void (*codec_write) (u8 reg, u16 val); -+ /* Wait for codec-ready */ -+ void (*codec_wait) (struct i2s_codec *codec); -+ /* OSS mixer masks */ -+ int modcnt; -+ int supported_mixers; -+ int stereo_mixers; -+ int record_sources; -+ int bit_resolution; -+ /* OSS mixer interface */ -+ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -+ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -+ unsigned int left, unsigned int right); -+ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -+ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -+ /* saved OSS mixer states */ -+ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -+}; -+ -+ -+typedef struct buffer_queue_s -+{ -+ int count; -+ int *id; -+ int lock; -+} buffer_queue_t; -+ -+typedef struct left_right_sample_s -+{ -+ signed long left; -+ signed long right; -+} left_right_sample_t; -+ -+static unsigned long pop_turn_onoff_buf; -+static unsigned long pop_turn_onoff_pbuf; -+ -+static unsigned long *out_dma_buf = NULL; -+static unsigned long *out_dma_pbuf = NULL; -+static unsigned long *out_dma_buf_data_count = NULL; -+static unsigned long *in_dma_buf = NULL; -+static unsigned long *in_dma_pbuf = NULL; -+static unsigned long *in_dma_buf_data_count = NULL; -+ -+static buffer_queue_t out_empty_queue; -+static buffer_queue_t out_full_queue; -+static buffer_queue_t out_busy_queue; -+static buffer_queue_t in_empty_queue; -+static buffer_queue_t in_full_queue; -+static buffer_queue_t in_busy_queue; -+static int first_record_call = 0; -+ -+static left_right_sample_t save_last_samples[64]; -+static int read_codec_file(int addr) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ return(__icdc_get_value()); -+} -+ -+#if 0 /* mask warning */ -+static void printk_codec_files(void) -+{ -+ int cnt; -+ -+ printk("\n"); -+ -+ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -+ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -+ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -+ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -+ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -+ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -+ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -+ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -+ -+ for (cnt = 0; cnt <= 27 ; cnt++) { -+ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -+ } -+ printk("\n"); -+} -+#endif -+ -+static void write_codec_file(int addr, int val) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+} -+ -+static int write_codec_file_bit(int addr, int bitval, int mask_bit) -+{ -+ int val; -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ val = __icdc_get_value(); /* read */ -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val &= ~(1 << mask_bit); -+ if (bitval == 1) -+ val |= 1 << mask_bit; -+ -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val = __icdc_get_value(); /* read */ -+ -+ if (((val >> mask_bit) & bitval) == bitval) -+ return 1; -+ else -+ return 0; -+} -+ -+#if 0 /* mask warning */ -+/* set Audio data replay */ -+static void set_audio_data_replay(void) -+{ -+ /* DAC path */ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ //mdelay(100); -+ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //mdelay(300); -+} -+#endif -+ -+/* unset Audio data replay */ -+static void unset_audio_data_replay(void) -+{ -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //mdelay(800); -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ //mdelay(800); -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+#if 0 /* mask warning */ -+/* set Record MIC input audio without playback */ -+static void set_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2); -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ -+ write_codec_file(22, 0x40);//mic 1 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ //write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record MIC input audio without playback */ -+static void unset_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record LINE input audio without playback */ -+static void set_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ mdelay(10); -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record LINE input audio without playback */ -+static void unset_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -+ -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Playback LINE input audio direct only */ -+static void set_playback_line_input_audio_direct_only(void) -+{ -+ jz_audio_reset();//or init_codec() -+ REG_AIC_I2SCR = 0x10; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -+ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Playback LINE input audio direct only */ -+static void unset_playback_line_input_audio_direct_only(void) -+{ -+ write_codec_file_bit(6, 0, 3);//GIM->0 -+ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ mdelay(100); -+ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record MIC input audio with direct playback */ -+static void set_record_mic_input_audio_with_direct_playback(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ jz_mic_only = 0; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ -+ write_codec_file(22, 0x60);//mic 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file(1, 0x4); -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record MIC input audio with direct playback */ -+static void unset_record_mic_input_audio_with_direct_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record playing audio mixed with MIC input audio */ -+static void set_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ -+ write_codec_file(22, 0x63);//mic 1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record playing audio mixed with MIC input audio */ -+static void unset_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record MIC input audio with Audio data replay (full duplex) */ -+static void set_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record MIC input audio with Audio data replay (full duplex) */ -+static void unset_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -+static void set_record_line_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ -+ -+ //jz_mic_only = 1; -+ write_codec_file(22, 0xc6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -+static void unset_record_line_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+static inline int get_buffer_id(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ if (q->count == 0) { -+ spin_unlock_irqrestore(&q->lock, flags); -+ return -1; -+ } -+ r = *(q->id + 0); -+ for (i=0;i < q->count-1;i++) -+ *(q->id + i) = *(q->id + (i+1)); -+ q->count --; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void put_buffer_id(struct buffer_queue_s *q, int id) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ *(q->id + q->count) = id; -+ q->count ++; -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+ -+static inline int elements_in_queue(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ r = q->count; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -+{ -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_dma_tran_count = count / jz_audio_b; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ //set_dma_mode(chan, mode); -+ jz_set_oss_dma(chan, mode, jz_audio_format); -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) { -+ count++; -+ printk("JzSOC DMA controller can't set dma 0 count!\n"); -+ } -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ release_dma_lock(flags); -+} -+ -+static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -+{ -+ int id1, id2; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma2; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ if(drain_flag == 1) -+ wake_up(&drain_wait_queue); -+ /* for DSP_GETIPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id2); -+ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -+ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -+ audio_start_dma(dma,dev_id, -+ *(in_dma_pbuf + id2), -+ *(in_dma_buf_data_count + id2), -+ DMA_MODE_READ); -+ } else -+ in_busy_queue.count = 0; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -+{ -+ int id; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma1; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ if(pop_dma_flag == 1) { -+ pop_dma_flag = 0; -+ wake_up(&pop_wait_queue); -+ } else { -+ if(drain_flag == 1) { -+ /* Is replay dma buffer over ? */ -+ if(elements_in_queue(&out_full_queue) <= 0) { -+ drain_flag = 0; -+ wake_up(&drain_wait_queue); -+ } -+ } -+ -+ /* for DSP_GETOPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if ((id = get_buffer_id(&out_busy_queue)) < 0) -+ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -+ put_buffer_id(&out_empty_queue, id); -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ last_dma_buffer_id = id; -+ } -+ } else -+ out_busy_queue.count = 0; -+ -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void jz_i2s_initHw(int set) -+{ -+#if defined(CONFIG_MIPS_JZ_URANUS) -+ i2s_clk = 48000000; -+#else -+ i2s_clk = __cpm_get_i2sclk(); -+#endif -+ __i2s_disable(); -+ if(set) -+ __i2s_reset(); -+ schedule_timeout(5); -+ if(each_time_init_codec) -+ each_time_init_codec(); -+ __i2s_disable_record(); -+ __i2s_disable_replay(); -+ __i2s_disable_loopback(); -+ __i2s_set_transmit_trigger(4); -+ __i2s_set_receive_trigger(3); -+} -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ -+ /* recording */ -+ in_empty_queue.count = fragstotal; -+ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf) -+ goto all_mem_err; -+ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_pbuf) -+ goto all_mem_err; -+ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf_data_count) -+ goto all_mem_err; -+ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_empty_queue.id) -+ goto all_mem_err; -+ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_full_queue.id) -+ goto all_mem_err; -+ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_busy_queue.id) -+ goto all_mem_err; -+ -+ for (i=0;i < fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ for (i = 0; i < fragstotal; i++) { -+ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(in_dma_buf + i) == 0) -+ goto mem_failed_in; -+ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ } -+ -+ /* playing */ -+ out_empty_queue.count = fragstotal; -+ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf) -+ goto all_mem_err; -+ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_pbuf) -+ goto all_mem_err; -+ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ -+ if (!out_dma_buf_data_count) -+ goto all_mem_err; -+ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_empty_queue.id) -+ goto all_mem_err; -+ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_full_queue.id) -+ goto all_mem_err; -+ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_busy_queue.id) -+ goto all_mem_err; -+ for (i=0;i < fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /* alloc DMA buffer */ -+ for (i = 0; i < fragstotal; i++) { -+ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(out_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(OUT) buffers.\n"); -+ goto mem_failed_out; -+ } -+ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -+ } -+ -+ return 1; -+all_mem_err: -+ printk("error:allocate memory occur error 1!\n"); -+ return 0; -+mem_failed_out: -+ printk("error:allocate memory occur error 2!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ } -+ -+ return 0; -+mem_failed_in: -+ printk("error:allocate memory occur error 3!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ return 0; -+} -+ -+static int Free_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ /* playing */ -+ if(out_dma_buf != NULL) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ *(out_dma_buf + i) = 0; -+ } -+ kfree(out_dma_buf); -+ out_dma_buf = NULL; -+ } -+ if(out_dma_pbuf) { -+ kfree(out_dma_pbuf); -+ out_dma_pbuf = NULL; -+ } -+ if(out_dma_buf_data_count) { -+ kfree(out_dma_buf_data_count); -+ out_dma_buf_data_count = NULL; -+ } -+ if(out_empty_queue.id) { -+ kfree(out_empty_queue.id); -+ out_empty_queue.id = NULL; -+ } -+ if(out_full_queue.id) { -+ kfree(out_full_queue.id); -+ out_full_queue.id = NULL; -+ } -+ if(out_busy_queue.id) { -+ kfree(out_busy_queue.id); -+ out_busy_queue.id = NULL; -+ } -+ out_empty_queue.count = fragstotal; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ -+ /* recording */ -+ if(in_dma_buf) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) { -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ *(in_dma_buf + i) = 0; -+ } -+ kfree(in_dma_buf); -+ in_dma_buf = NULL; -+ } -+ if(in_dma_pbuf) { -+ kfree(in_dma_pbuf); -+ in_dma_pbuf = NULL; -+ } -+ if(in_dma_buf_data_count) { -+ kfree(in_dma_buf_data_count); -+ in_dma_buf_data_count = NULL; -+ } -+ if(in_empty_queue.id) { -+ kfree(in_empty_queue.id); -+ in_empty_queue.id = NULL; -+ } -+ if(in_full_queue.id) { -+ kfree(in_full_queue.id); -+ in_full_queue.id = NULL; -+ } -+ if(in_busy_queue.id) { -+ kfree(in_busy_queue.id); -+ in_busy_queue.id = NULL; -+ } -+ -+ in_empty_queue.count = fragstotal; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ return 1; -+} -+ -+static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -+{ -+ jz_i2s_initHw(0); -+} -+ -+static int jz_audio_set_speed(int dev, int rate) -+{ -+ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -+ jz_audio_speed = rate; -+ if (rate > 48000) -+ rate = 48000; -+ if (rate < 8000) -+ rate = 8000; -+ jz_audio_rate = rate; -+ -+ if(set_codec_speed) -+ set_codec_speed(rate); -+ -+ return jz_audio_rate; -+} -+ -+ -+static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long data; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt++; -+ data = *(s++); -+ *(dp ++) = ((data << 16) >> 24) + 0x80; -+ s++; /* skip the other channel */ -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -+ d2 = *(s++); -+ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 2; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = (d1 << 16) >> 16; -+ s++; /* skip the other channel */ -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 4; /* count in byte */ -+ d1 = *(s++); -+ d2 = *(s++); -+ if(abnormal_data_count > 0) { -+ d1 = d2 = 0; -+ abnormal_data_count --; -+ } -+ *(dp ++) = (d1 << 16) >> 16; -+ *(dp ++) = (d2 << 16) >> 16; -+ } -+ -+ return cnt; -+} -+ -+static void replay_fill_1x8_u(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char data; -+ unsigned long ddata; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count--; -+ cnt += 1; -+ data = *(s++) - 0x80; -+ ddata = (unsigned long) data << 8; -+ *(dp ++) = ddata; -+ *(dp ++) = ddata; -+ -+ /* save last left and right */ -+ if(count == 1) { -+ save_last_samples[id].left = ddata; -+ save_last_samples[id].right = ddata; -+ } -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+ -+static void replay_fill_2x8_u(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char d1; -+ unsigned long dd1; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 1; -+ cnt += 1 ; -+ d1 = *(s++) - 0x80; -+ dd1 = (unsigned long) d1 << 8; -+ *(dp ++) = dd1; -+ /* save last left */ -+ if(count == 2) -+ save_last_samples[id].left = dd1; -+ /* save last right */ -+ if(count == 1) -+ save_last_samples[id].right = dd1; -+ } -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+ -+static void replay_fill_1x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2 ; -+ d1 = *(s++); -+ l1 = (signed long)d1; -+ *(dp ++) = l1; -+ *(dp ++) = l1; -+ -+ /* save last left and right */ -+ if(count == 1) { -+ save_last_samples[id].left = l1; -+ save_last_samples[id].right = l1; -+ } -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+#if 0 -+static void replay_fill_2x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ int mute_cnt = 0; -+ signed long tmp1,tmp2; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+#if defined(CONFIG_I2S_ICDC) -+ volatile signed long *before_dp; -+ int sam_rate = jz_audio_rate / 20; -+ -+ tmp1 = tmp2 = 0; -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ l1 >>= codec_volue_shift; -+ -+ if(l1 == 0) { -+ mute_cnt ++; -+ if(mute_cnt >= sam_rate) { -+ before_dp = dp - 10; -+ *(before_dp) = (signed long)1; -+ before_dp = dp - 11; -+ *(before_dp) = (signed long)1; -+ mute_cnt = 0; -+ } -+ } else -+ mute_cnt = 0; -+ -+ *(dp ++) = l1; -+ -+ tmp1 = tmp2; -+ tmp2 = l1; -+ } -+ -+ /* save last left */ -+ save_last_samples[id].left = tmp1; -+ /* save last right */ -+ save_last_samples[id].right = tmp2; -+#endif -+#if defined(CONFIG_I2S_DLV) -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ -+ *(dp ++) = l1; -+ } -+#endif -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+#else -+static void replay_fill_2x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ -+#if 0 -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed short *dp = (signed short*)(*(out_dma_buf + id)); -+ memcpy((char*)dp, (char*)s, count); -+ *(out_dma_buf_data_count + id) = count; -+#else -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ -+ *(dp ++) = l1; -+ } -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+#endif -+} -+#endif -+ -+ -+static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -+{ -+ switch (fmt) { -+ case AFMT_U8: -+ __i2s_set_oss_sample_size(8); -+ __i2s_set_iss_sample_size(8); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ break; -+ case AFMT_S16_LE: -+#if defined(CONFIG_I2S_DLV) -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x00); -+ //write_codec_file(2, 0x60); -+#endif -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ /* print all files */ -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ break; -+ -+ case AFMT_QUERY: -+ break; -+ } -+ -+ return jz_audio_format; -+} -+ -+ -+static short jz_audio_set_channels(int dev, short channels) -+{ -+ switch (channels) { -+ case 1: -+ if(set_codec_some_func) -+ set_codec_some_func(); -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -+#endif -+ break; -+ case 2: -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -+#endif -+ break; -+ case 0: -+ break; -+ } -+ -+ return jz_audio_channels; -+} -+ -+static void init_codec(void) -+{ -+ /* inititalize internal I2S codec */ -+ if(init_codec_pin) -+ init_codec_pin(); -+ -+#if defined(CONFIG_I2S_ICDC) -+ /* initialize AIC but not reset it */ -+ jz_i2s_initHw(0); -+#endif -+ if(reset_codec) -+ reset_codec(); -+} -+ -+static void jz_audio_reset(void) -+{ -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+#if defined(CONFIG_I2S_DLV) -+ REG_AIC_I2SCR = 0x10; -+#endif -+ init_codec(); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file); -+static int jz_audio_open(struct inode *inode, struct file *file); -+static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -+static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -+static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -+ -+/* static struct file_operations jz_i2s_audio_fops */ -+static struct file_operations jz_i2s_audio_fops = -+{ -+ owner: THIS_MODULE, -+ open: jz_audio_open, -+ release: jz_audio_release, -+ write: jz_audio_write, -+ read: jz_audio_read, -+ poll: jz_audio_poll, -+ ioctl: jz_audio_ioctl -+}; -+ -+static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -+{ -+ int i; -+ int minor = MINOR(inode->i_rdev); -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ -+ for (i = 0; i < NR_I2S; i++) -+ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -+ goto match; -+ -+ if (!controller) -+ return -ENODEV; -+match: -+ file->private_data = controller->i2s_codec[i]; -+ -+ return 0; -+} -+ -+static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -+ return codec->mixer_ioctl(codec, cmd, arg); -+} -+ -+static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -+{ -+ return -ESPIPE; -+} -+ -+static struct file_operations jz_i2s_mixer_fops = -+{ -+ owner: THIS_MODULE, -+ llseek: jz_i2s_llseek, -+ ioctl: jz_i2s_ioctl_mixdev, -+ open: jz_i2s_open_mixdev, -+}; -+ -+static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ long val = 0; -+ switch (cmd) { -+ case SOUND_MIXER_INFO: -+ -+ if(codec_mixer_info_id_name) -+ codec_mixer_info_id_name(); -+ info.modify_counter = audio_mix_modcnt; -+ -+ return copy_to_user((void *)arg, &info, sizeof(info)); -+ case SOUND_OLD_MIXER_INFO: -+ -+ if(codec_mixer_old_info_id_name) -+ codec_mixer_old_info_id_name(); -+ -+ return copy_to_user((void *)arg, &old_info, sizeof(info)); -+ case SOUND_MIXER_READ_STEREODEVS: -+ -+ return put_user(0, (long *) arg); -+ case SOUND_MIXER_READ_CAPS: -+ -+ val = SOUND_CAP_EXCL_INPUT; -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_READ_DEVMASK: -+ break; -+ case SOUND_MIXER_READ_RECMASK: -+ break; -+ case SOUND_MIXER_READ_RECSRC: -+ break; -+ case SOUND_MIXER_WRITE_SPEAKER: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ switch(val) { -+ case 100: -+ if(set_codec_direct_mode) -+ set_codec_direct_mode(); -+ break; -+ case 0: -+ if(clear_codec_direct_mode) -+ clear_codec_direct_mode(); -+ break; -+ } -+ break; -+ case SOUND_MIXER_WRITE_BASS: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ codec_bass_gain = val; -+ if(set_codec_bass) -+ set_codec_bass(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_BASS: -+ -+ val = codec_bass_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_VOLUME: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ if (val > 31) -+ val = 31; -+ jz_audio_volume = val; -+ -+ if(set_codec_volume) -+ set_codec_volume(val); -+ return 0; -+ case SOUND_MIXER_READ_VOLUME: -+ -+ val = jz_audio_volume; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_MIC: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ codec_mic_gain = val; -+ if(set_codec_mic) -+ set_codec_mic(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_MIC: -+ -+ val = codec_mic_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ default: -+ return -ENOSYS; -+ } -+ audio_mix_modcnt ++; -+ return 0; -+} -+ -+ -+int i2s_probe_codec(struct i2s_codec *codec) -+{ -+ /* generic OSS to I2S wrapper */ -+ codec->mixer_ioctl = i2s_mixer_ioctl; -+ return 1; -+} -+ -+ -+/* I2S codec initialisation. */ -+static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -+{ -+ int num_i2s = 0; -+ struct i2s_codec *codec; -+ -+ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -+ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ memset(codec, 0, sizeof(struct i2s_codec)); -+ codec->private_data = controller; -+ codec->id = num_i2s; -+ -+ if (i2s_probe_codec(codec) == 0) -+ break; -+ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -+ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -+ kfree(codec); -+ break; -+ } -+ controller->i2s_codec[num_i2s] = codec; -+ } -+ return num_i2s; -+} -+ -+ -+static void jz_update_filler(int format, int channels) -+{ -+#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -+ -+ switch (TYPE(format, channels)) -+ { -+ -+ case TYPE(AFMT_U8, 1): -+ jz_audio_b = 4; /* 4bytes * 8bits =32bits */ -+ replay_filler = replay_fill_1x8_u; -+ record_filler = record_fill_1x8_u; -+ break; -+ case TYPE(AFMT_U8, 2): -+ jz_audio_b = 4; -+ replay_filler = replay_fill_2x8_u; -+ record_filler = record_fill_2x8_u; -+ break; -+ case TYPE(AFMT_S16_LE, 1): -+ jz_audio_b = 2; /* 2bytes * 16bits =32bits */ -+ replay_filler = replay_fill_1x16_s; -+ record_filler = record_fill_1x16_s; -+ break; -+ case TYPE(AFMT_S16_LE, 2): -+ jz_audio_b = 2; -+ replay_filler = replay_fill_2x16_s; -+ record_filler = record_fill_2x16_s; -+ break; -+ default: -+ ; -+ } -+} -+ -+ -+#ifdef CONFIG_PROC_FS -+extern struct proc_dir_entry *proc_jz_root; -+int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ return 0; -+} -+ -+static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -+{ -+ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -+ return -EIO; -+ return 0; -+} -+ -+static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -+{ -+} -+#endif -+ -+static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ char *name; -+ int adev; /* No of Audio device. */ -+ -+ name = controller->name; -+ /* initialize AIC controller and reset it */ -+ jz_i2s_initHw(1); -+ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -+ if (adev < 0) -+ goto audio_failed; -+ /* initialize I2S codec and register /dev/mixer */ -+ if (jz_i2s_codec_init(controller) <= 0) -+ goto mixer_failed; -+ -+#ifdef CONFIG_PROC_FS -+ if (jz_i2s_init_proc(controller) < 0) { -+ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -+ goto proc_failed; -+ } -+#endif -+ -+ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); -+ if (!controller->tmp1) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp1_failed; -+ } -+ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); -+ if (!controller->tmp2) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp2_failed; -+ } -+ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -+ goto dma2_failed; -+ } -+ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -+ goto dma1_failed; -+ } -+ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -+ -+ controller->dev_audio = adev; -+ pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); -+ if(!pop_turn_onoff_buf) -+ printk("pop_turn_onoff_buf alloc is wrong!\n"); -+ pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); -+ -+ return; -+dma2_failed: -+ jz_free_dma(controller->dma1); -+dma1_failed: -+ free_pages((unsigned long)controller->tmp2, 8); -+tmp2_failed: -+ free_pages((unsigned long)controller->tmp1, 8); -+tmp1_failed: -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+proc_failed: -+ /* unregister mixer dev */ -+mixer_failed: -+ unregister_sound_dsp(adev); -+audio_failed: -+ return; -+} -+ -+static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -+{ -+ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -+ return -ENOMEM; -+ } -+ (*controller)->name = "Jz I2S controller"; -+ (*controller)->opened1 = 0; -+ (*controller)->opened2 = 0; -+ init_waitqueue_head(&(*controller)->adc_wait); -+ init_waitqueue_head(&(*controller)->dac_wait); -+ spin_lock_init(&(*controller)->lock); -+ init_waitqueue_head(&rx_wait_queue); -+ init_waitqueue_head(&tx_wait_queue); -+ init_waitqueue_head(&pop_wait_queue); -+ init_waitqueue_head(&drain_wait_queue); -+ -+ return 0; -+} -+ -+static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ int adev = controller->dev_audio; -+ -+ jz_i2s_full_reset(controller); -+ controller->dev_audio = -1; -+ if (old_mksound) -+ kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+ -+ jz_free_dma(controller->dma1); -+ jz_free_dma(controller->dma2); -+ free_pages((unsigned long)controller->tmp1, 8); -+ free_pages((unsigned long)controller->tmp2, 8); -+ free_pages((unsigned long)pop_turn_onoff_buf, 8); -+ -+ if (adev >= 0) { -+ /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ -+ unregister_sound_dsp(controller->dev_audio); -+ } -+} -+ -+#ifdef CONFIG_PM -+static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -+{ -+ if(i2s_suspend_codec) -+ i2s_suspend_codec(controller->opened1,controller->opened2); -+ printk("Aic and codec are suspended!\n"); -+ return 0; -+} -+ -+static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -+{ -+ if(i2s_resume_codec) -+ i2s_resume_codec(); -+ -+#if defined(CONFIG_I2S_AK4642EN) -+ jz_i2s_initHw(0); -+ jz_audio_reset(); -+ __i2s_enable(); -+ jz_audio_set_speed(controller->dev_audio,jz_audio_speed); -+ /* playing */ -+ if(controller->opened1) { -+ if(set_codec_replay) -+ set_codec_replay(); -+ int dma = controller->dma1; -+ int id; -+ unsigned long flags; -+ disable_dma(dma); -+ if(__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if(__dmac_channel_transmit_end_detected(dma)) -+ __dmac_channel_clear_transmit_end(dma); -+ -+ /* for DSP_GETOPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ while((id = get_buffer_id(&out_busy_queue)) >= 0) -+ put_buffer_id(&out_empty_queue, id); -+ -+ out_busy_queue.count=0; -+ if((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_empty_queue, id); -+ } -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } else -+ printk("pm out_empty_queue empty"); -+ } -+ -+ /* recording */ -+ if(controller->opened2) { -+ if(set_codec_record) -+ set_codec_record(); -+ int dma = controller->dma2; -+ int id1, id2; -+ unsigned long flags; -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ } -+ /* for DSP_GETIPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_full_queue, id2); -+ } -+ in_busy_queue.count = 0; -+ } -+#endif -+ -+ return 0; -+} -+ -+static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct jz_i2s_controller_info *controller = pm_dev->data; -+ -+ if (!controller) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jz_i2s_suspend(controller, (int)data); -+ break; -+ case PM_RESUME: -+ ret = jz_i2s_resume(controller); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#endif /* CONFIG_PM */ -+static irqreturn_t aic_codec_irq(int irq, void *dev_id) -+{ -+ u8 file_9 = read_codec_file(9); -+ u8 file_8 = read_codec_file(8); -+ -+ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -+ if ((file_9 & 0x1f) == 0x10) { -+ -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x4) != 0x4); -+ while ((read_codec_file(9) & 0x10) == 0x10) { -+ write_codec_file(9, 0x10); -+ } -+ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x8) != 0x8); -+ write_codec_file(9, file_9); -+ write_codec_file(8, file_8); -+ -+ return IRQ_HANDLED; -+ } -+ -+ if (file_9 & 0x8) -+ ramp_up_end = jiffies; -+ else if (file_9 & 0x4) -+ ramp_down_end = jiffies; -+ else if (file_9 & 0x2) -+ gain_up_end = jiffies; -+ else if (file_9 & 0x1) -+ gain_down_end = jiffies; -+ -+ write_codec_file(9, file_9); -+ if (file_9 & 0xf) -+ wake_up(&pop_wait_queue); -+ while (REG_ICDC_RGDATA & 0x100); -+ -+ return IRQ_HANDLED; -+} -+ -+static int __init init_jz_i2s(void) -+{ -+ int errno, retval; -+#if defined(CONFIG_I2S_DLV) -+ -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+#endif -+ -+ abnormal_data_count = 0; -+ if(set_codec_mode) -+ set_codec_mode(); -+ -+ drain_flag = 0; -+ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -+ return errno; -+ if(set_codec_gpio_pin) -+ set_codec_gpio_pin(); -+ -+ attach_jz_i2s(i2s_controller); -+ if(set_codec_startup_param) -+ set_codec_startup_param(); -+#if defined(CONFIG_I2S_DLV) -+ jz_codec_config = 0; -+ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -+ if (retval) { -+ printk("Could not get aic codec irq %d\n", IRQ_AIC); -+ return retval; -+ } -+#endif -+ if(set_codec_volume_table) -+ set_codec_volume_table(); -+ -+ out_empty_queue.id = NULL; -+ out_full_queue.id = NULL; -+ out_busy_queue.id = NULL; -+ in_empty_queue.id = NULL; -+ in_full_queue.id = NULL; -+ in_busy_queue.id = NULL; -+ -+ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -+ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+#ifdef CONFIG_PM -+ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -+ jz_i2s_pm_callback); -+ if (i2s_controller->pm) -+ i2s_controller->pm->data = i2s_controller; -+#endif -+ -+#if defined(CONFIG_I2S_DLV) -+ __cpm_start_idct(); -+ __cpm_start_db(); -+ __cpm_start_me(); -+ __cpm_start_mc(); -+ __cpm_start_ipu(); -+#endif -+ -+ printk("JZ I2S OSS audio driver initialized\n"); -+ -+ return 0; -+} -+ -+static void __exit cleanup_jz_i2s(void) -+{ -+#ifdef CONFIG_PM -+ /* pm_unregister(i2s_controller->pm); */ -+#endif -+#if defined(CONFIG_I2S_DLV) -+ free_irq(IRQ_AIC, NULL); -+#endif -+ unload_jz_i2s(i2s_controller); -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ if(clear_codec_mode) -+ clear_codec_mode(); -+} -+ -+module_init(init_jz_i2s); -+module_exit(cleanup_jz_i2s); -+ -+#if defined(CONFIG_SOC_JZ4730) -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,con; -+ -+ if(elements_in_queue(&in_busy_queue) > 0) { -+ if (nonblock) -+ return -EBUSY; -+ drain_flag = 1; -+ sleep_on(&drain_wait_queue); -+ drain_flag = 0; -+ } else { -+ add_wait_queue(&ctrl->adc_wait, &wait); -+ for (con = 0; con < 1000; con ++) { -+ udelay(1); -+ set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ if (nonblock) { -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ } -+ return 0; -+} -+ -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count; -+ -+ if(elements_in_queue(&out_full_queue) > 0) { -+ if (nonblock) -+ return -EBUSY; -+ -+ drain_flag = 1; -+ sleep_on(&drain_wait_queue); -+ drain_flag = 0; -+ } else { -+ add_wait_queue(&(ctrl->dac_wait), &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if(elements_in_queue(&out_full_queue) <= 0) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if(count <= 0) -+ break; -+ } -+ if (nonblock) { -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ } -+ -+ return 0; -+} -+#endif -+ -+#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ //DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,i=0; -+ -+ //add_wait_queue(&ctrl->adc_wait, &wait); -+ for (;;) { -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ //set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ //spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ //spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ /*if (signal_pending(current)) -+ break;*/ -+ if (nonblock) { -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ /*if (signal_pending(current)) -+ return -ERESTARTSYS;*/ -+ return 0; -+} -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ unsigned long flags; -+ int count,ele,busyele,emptyele,i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(200); -+ -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } else {//non-blocked -+ //mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ //mdelay(100); -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+#if defined(CONFIG_SOC_JZ4740) -+#define MAXDELAY 50000 -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ int count,ele,i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if ( i < MAXDELAY ) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(10); -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ } -+ } else {//non-blocked -+ mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ mdelay(100); -+ -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ int count,i=0; -+ -+ for (;;) { -+ if ( i < MAXDELAY ) -+ { -+ udelay(10); -+ i++; -+ } -+ else -+ break; -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ if (nonblock) { -+ return -EBUSY; -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+static int jz_audio_release(struct inode *inode, struct file *file) -+{ -+ unsigned long flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long tfl; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ pop_dma_flag = 0; -+ if (controller->opened1 == 1) { -+ controller->opened1 = 0; -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ /* add some mute to anti-pop */ -+#if defined(CONFIG_I2S_DLV) -+ /* wait for fifo empty */ -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ gain_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_down_end = jiffies; -+ while (1) { -+ tfl = REG_AIC_SR & 0x00003f00; -+ if (tfl == 0) { -+ udelay(500); -+ break; -+ } -+ mdelay(2); -+ } -+#endif -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable_replay(); -+ __aic_flush_fifo(); -+ if(clear_codec_replay) -+ clear_codec_replay(); -+ __aic_flush_fifo(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ ramp_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_down_end = jiffies; -+ unset_audio_data_replay(); -+#endif -+ __i2s_disable(); -+ if(turn_off_codec) -+ turn_off_codec(); -+ } -+ -+ if (controller->opened2 == 1) { -+ controller->opened2 = 0; -+ first_record_call = 1; -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ -+ if(clear_codec_record) -+ clear_codec_record(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ __i2s_disable(); -+ if(turn_off_codec) -+ turn_off_codec(); -+ abnormal_data_count = 0; -+ } -+ -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+#endif -+ return 0; -+} -+ -+static int jz_audio_open(struct inode *inode, struct file *file) -+{ -+ int i; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ mdelay(2); -+ REG_DMAC_DMACKE(0) = 0x3f; -+ pop_dma_flag = 0; -+ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -+ printk("\naudio is busy!\n"); -+ return -EBUSY; -+ } -+ jz_codec_config = 0; -+ -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+ if (file->f_mode & FMODE_WRITE) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ -+ controller->opened1 = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ for(i=0;i < 64;i++) { -+ save_last_samples[i].left = 0; -+ save_last_samples[i].right = 0; -+ } -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ last_dma_buffer_id = 0; -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ -+ controller->opened2 = 1; -+ first_record_call = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ } -+ -+ file->private_data = controller; -+ jz_audio_reset(); -+ REG_AIC_FR |= (1 << 6); -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if(set_codec_replay) -+ set_codec_replay(); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ abnormal_data_count = 0; -+ if(set_codec_record) -+ set_codec_record(); -+ } -+ -+#if defined(CONFIG_I2S_DLV) -+ __aic_reset(); -+ -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ __aic_flush_fifo(); -+#endif -+ -+ __i2s_enable(); -+ -+#if defined(CONFIG_I2S_DLV) -+ if (file->f_mode & FMODE_WRITE) { -+ -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ ramp_up_start = jiffies; -+ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RCR = 0x1; -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RGR = 1;*/ -+ sleep_on(&pop_wait_queue); -+ //ramp_up_end = jiffies; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ } else if (file->f_mode & FMODE_READ) { -+ if (jz_mic_only) -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ else -+ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -+ mdelay(500); -+ } -+ -+#endif -+ -+ return 0; -+} -+ -+ -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+unsigned int cmd, unsigned long arg) -+{ -+ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ count_info cinfo; -+ audio_buf_info abinfo; -+ int id, i; -+ -+ val = 0; -+ switch (cmd) { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, (int *)arg); -+ case SNDCTL_DSP_RESET: -+#if 0 -+ jz_audio_reset(); -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+#endif -+ return 0; -+ case SNDCTL_DSP_SYNC: -+ if (file->f_mode & FMODE_WRITE) -+ return drain_dac(controller, file->f_flags & O_NONBLOCK); -+ return 0; -+ case SNDCTL_DSP_SPEED: -+ /* set smaple rate */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val >= 0) -+ jz_audio_set_speed(controller->dev_audio, val); -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_STEREO: -+ /* set stereo or mono channel */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -+ -+ return 0; -+ case SNDCTL_DSP_GETBLKSIZE: -+ //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); -+ return put_user(jz_audio_fragsize, (int *)arg); -+ case SNDCTL_DSP_GETFMTS: -+ /* Returns a mask of supported sample format*/ -+ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -+ case SNDCTL_DSP_SETFMT: -+ /* Select sample format */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val != AFMT_QUERY) -+ jz_audio_set_format(controller->dev_audio,val); -+ else { -+ if (file->f_mode & FMODE_READ) -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ else -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ } -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val); -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_POST: -+ /* FIXME: the same as RESET ?? */ -+ return 0; -+ case SNDCTL_DSP_SUBDIVIDE: -+ return 0; -+ case SNDCTL_DSP_SETFRAGMENT: -+ get_user(val, (long *) arg); -+ newfragsize = 1 << (val & 0xFFFF); -+ if (newfragsize < 4 * PAGE_SIZE) -+ newfragsize = 4 * PAGE_SIZE; -+ if (newfragsize > (16 * PAGE_SIZE)) -+ newfragsize = 16 * PAGE_SIZE; -+ -+ newfragstotal = (val >> 16) & 0x7FFF; -+ if (newfragstotal < 2) -+ newfragstotal = 2; -+ if (newfragstotal > 32) -+ newfragstotal = 32; -+ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -+ return 0; -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(500); -+ jz_audio_fragstotal = newfragstotal; -+ jz_audio_fragsize = newfragsize; -+ -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(10); -+ -+ return 0; -+ case SNDCTL_DSP_GETCAPS: -+ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -+ case SNDCTL_DSP_NONBLOCK: -+ file->f_flags |= O_NONBLOCK; -+ return 0; -+ case SNDCTL_DSP_SETDUPLEX: -+ return -EINVAL; -+ case SNDCTL_DSP_GETOSPACE: -+ { -+ int i, bytes = 0; -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_fragments = elements_in_queue(&out_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ if (jz_audio_channels == 2) -+ bytes /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ bytes /= 4; -+ else -+ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); -+ -+ -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ /* unused fragment amount */ -+ abinfo.fragments = jz_audio_fragments; -+ /* amount of fragments */ -+ abinfo.fragstotal = jz_audio_fragstotal; -+ /* fragment size in bytes */ -+ if (jz_audio_channels == 2) -+ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -+ else if (jz_audio_channels == 1) -+ abinfo.fragsize = jz_audio_fragsize / 4; -+ else -+ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); -+ -+ /* write size count without blocking in bytes */ -+ abinfo.bytes = bytes; -+ -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETISPACE: -+ { -+ int i, bytes = 0; -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ jz_audio_fragments = elements_in_queue(&in_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ if (jz_audio_channels == 2) -+ bytes /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ bytes /= 4; -+ else -+ printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); -+ -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ -+ if (jz_audio_channels == 2) -+ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -+ else if (jz_audio_channels == 1) -+ abinfo.fragsize = jz_audio_fragsize / 4; -+ else -+ printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); -+ -+ abinfo.bytes = bytes; -+ -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETTRIGGER: -+ val = 0; -+ if (file->f_mode & FMODE_READ && in_dma_buf) -+ val |= PCM_ENABLE_INPUT; -+ if (file->f_mode & FMODE_WRITE && out_dma_buf) -+ val |= PCM_ENABLE_OUTPUT; -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_SETTRIGGER: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ return 0; -+ case SNDCTL_DSP_GETIPTR: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextIn; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETOPTR: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextOut; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETODELAY: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ unfinish = 0; -+ fullc = elements_in_queue(&out_full_queue); -+ busyc = elements_in_queue(&out_busy_queue); -+ for(i = 0;i < fullc ;i ++) { -+ id = *(out_full_queue.id + i); -+ unfinish += *(out_dma_buf_data_count + id); -+ } -+ for(i = 0;i < busyc ;i ++) { -+ id = *(out_busy_queue.id + i); -+ unfinish += get_dma_residue(controller->dma1); -+ } -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (jz_audio_channels == 2) -+ unfinish /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ unfinish /= 4; -+ else -+ printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); -+ -+ return put_user(unfinish, (int *) arg); -+ case SOUND_PCM_READ_RATE: -+ return put_user(jz_audio_rate, (int *)arg); -+ case SOUND_PCM_READ_CHANNELS: -+ return put_user(jz_audio_channels, (int *)arg); -+ case SOUND_PCM_READ_BITS: -+ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -+ case SNDCTL_DSP_MAPINBUF: -+ case SNDCTL_DSP_MAPOUTBUF: -+ case SNDCTL_DSP_SETSYNCRO: -+ case SOUND_PCM_WRITE_FILTER: -+ case SOUND_PCM_READ_FILTER: -+ return -EINVAL; -+ } -+ return -EINVAL; -+} -+ -+ -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long flags; -+ unsigned int mask = 0; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ return POLLOUT | POLLWRNORM; -+ -+ poll_wait(file, &controller->dac_wait, wait); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ return POLLIN | POLLRDNORM; -+ -+ poll_wait(file, &controller->adc_wait, wait); -+ } -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ mask |= POLLOUT | POLLWRNORM; -+ } else if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ mask |= POLLIN | POLLRDNORM; -+ } -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ return mask; -+} -+ -+static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ int id, ret = 0, left_count, copy_count, cnt = 0; -+ unsigned long flags; -+ -+ if (count < 0) -+ return -EINVAL; -+ -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ copy_count = jz_audio_fragsize / 4; -+ -+ left_count = count; -+ if (first_record_call) { -+ first_record_call = 0; -+ audio_read_back_first: -+ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ -+ spin_unlock(&controller->lock); -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ sleep_on(&rx_wait_queue); -+ } else -+ goto audio_read_back_first; -+ } -+ -+ while (left_count > 0) { -+ audio_read_back_second: -+ if (elements_in_queue(&in_full_queue) <= 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret ? ret : -EAGAIN; -+ else -+ sleep_on(&rx_wait_queue); -+ } -+ -+ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -+ spin_lock(&controller->lock); -+ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -+ spin_unlock(&controller->lock); -+ put_buffer_id(&in_empty_queue, id); -+ } else -+ goto audio_read_back_second; -+ -+ if (elements_in_queue(&in_busy_queue) == 0) { -+ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ spin_unlock(&controller->lock); -+ -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ } -+ } -+ if (ret + cnt > count) { -+ spin_lock(&controller->lock); -+ cnt = count - ret; -+ spin_unlock(&controller->lock); -+ } -+ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -+ return ret ? ret : -EFAULT; -+ -+ spin_lock(&controller->lock); -+ ret += cnt; -+ spin_unlock(&controller->lock); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ spin_lock(&controller->lock); -+ left_count -= cnt; -+ spin_unlock(&controller->lock); -+ } -+ return ret; -+} -+ -+static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -+{ -+ int id, ret = 0, left_count, copy_count = 0; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ -+ if (count <= 0) -+ return -EINVAL; -+ -+ if(set_replay_hp_or_speaker) -+ set_replay_hp_or_speaker(); -+ -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if (jz_audio_channels == 2) -+ copy_count = jz_audio_fragsize / jz_audio_b; -+ else if(jz_audio_channels == 1) -+ copy_count = jz_audio_fragsize / 4; -+ left_count = count; -+ if (copy_from_user(controller->tmp1, buffer, count)) { -+ printk("copy_from_user failed:%d",ret); -+ return ret ? ret : -EFAULT; -+ } -+ -+ while (left_count > 0) { -+ audio_write_back: -+ /*if (file->f_flags & O_NONBLOCK) -+ udelay(2);*/ -+ if (elements_in_queue(&out_empty_queue) == 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret; -+ else -+ sleep_on(&tx_wait_queue); -+ } -+ /* the end fragment size in this write */ -+ if (ret + copy_count > count) -+ copy_count = count - ret; -+ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -+ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ put_buffer_id(&out_full_queue, id); -+ dma_cache_wback_inv(*(out_dma_buf + id), -+ *(out_dma_buf_data_count + id)); -+ } else -+ put_buffer_id(&out_empty_queue, id); -+ } else -+ goto audio_write_back; -+ -+ left_count = left_count - copy_count; -+ ret += copy_count; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (elements_in_queue(&out_busy_queue) == 0) { -+ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(controller->dma1, -+ file->private_data, -+ *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ last_dma_buffer_id = id; -+ if (jz_codec_config == 0) { -+ write_codec_file_bit(1, 0, 5); -+ gain_up_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_up_end = jiffies; -+ jz_codec_config = 1; -+ //SB_ADC->1 -+ //write_codec_file_bit(5, 1, 4); -+ //while(1); -+ } -+ } -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+#if defined(CONFIG_I2S_ICODEC) -+static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -+{ -+ int i,step_len; -+ unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; -+ unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -+ unsigned long l_sample_count,r_sample_count,sample_count; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ signed int left_sam=0,right_sam=0,l_val,r_val; -+ -+ switch (sample_oss) { -+ case 0x0: -+ break; -+ case 0x1: -+ left_sam = (signed int)l_sample; -+ right_sam = (signed int)r_sample; -+ break; -+ case 0x2: -+ break; -+ case 0x3: -+ break; -+ case 0x4: -+ break; -+ } -+ -+ if(left_sam == 0 && right_sam == 0) -+ return; -+ -+ switch (sample_oss) { -+ case 0x0: -+ break; -+ case 0x1: -+ step_len = jz_audio_speed / 10 * 3; -+ step_len = step_len / 2; -+ step_len = 0x7fff / step_len + 1; -+ -+ l_sample_count = 0; -+ l_val = left_sam; -+ -+ while(1) { -+ if(l_val > 0) { -+ if(l_val >= step_len) { -+ l_val -= step_len; -+ l_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(l_val < 0) { -+ if(l_val <= -step_len) { -+ l_val += step_len; -+ l_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(l_val == 0) -+ break; -+ } -+ -+ r_sample_count = 0; -+ r_val = right_sam; -+ while(1) { -+ if(r_val > 0) { -+ if(r_val >= step_len) { -+ r_val -= step_len; -+ r_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(r_val < 0) { -+ if(r_val <= -step_len) { -+ r_val += step_len; -+ r_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(r_val == 0) -+ break; -+ } -+ /* fill up */ -+ if(l_sample_count > r_sample_count) -+ sample_count = l_sample_count; -+ else -+ sample_count = r_sample_count; -+ -+ l_val = left_sam; -+ r_val = right_sam; -+ for(i=0;i <= sample_count;i++) { -+ -+ *pop_buf = (unsigned long)l_val; -+ pop_buf ++; -+ -+ if(l_val > step_len) -+ l_val -= step_len; -+ else if(l_val < -step_len) -+ l_val += step_len; -+ else if(l_val >= -step_len && l_val <= step_len) -+ l_val = 0; -+ -+ *pop_buf = (unsigned long)r_val; -+ pop_buf ++; -+ if(r_val > step_len) -+ r_val -= step_len; -+ else if(r_val < -step_len) -+ r_val += step_len; -+ else if(r_val >= -step_len && r_val <= step_len) -+ r_val = 0; -+ } -+ -+ *pop_buf = 0; -+ pop_buf ++; -+ *pop_buf = 0; -+ -+ pop_buf ++; -+ sample_count += 2; -+ dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); -+ -+ pop_dma_flag = 1; -+ audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); -+ sleep_on(&pop_wait_queue); -+ pop_dma_flag = 0; -+ break; -+ case 0x2: -+ break; -+ case 0x3: -+ break; -+ case 0x4: -+ break; -+ } -+} -+#endif -diff --git a/sound/oss/jz_i2s_dlv_dma_test.c b/sound/oss/jz_i2s_dlv_dma_test.c -new file mode 100644 -index 0000000..49a64a2 ---- /dev/null -+++ b/sound/oss/jz_i2s_dlv_dma_test.c -@@ -0,0 +1,2808 @@ -+/* -+ * linux/drivers/sound/jz_i2s_dlv.c -+ * -+ * JzSOC On-Chip I2S audio driver. -+ * -+ * Copyright (C) 2005 by Junzheng Corp. -+ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -+ * dma channel 4&3,noah is tested. -+ * -+ * 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. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sound_config.h" -+ -+#define DPRINTK(args...) printk(args) -+#define DMA_ID_I2S_TX DMA_ID_AIC_TX -+#define DMA_ID_I2S_RX DMA_ID_AIC_RX -+ -+#define NR_I2S 2 -+#define MAXDELAY 50000 -+#define JZCODEC_RW_BUFFER_SIZE 3 -+#define JZCODEC_RW_BUFFER_TOTAL 3 -+#define JZCODEC_USER_BUFFER 6 -+ -+#define USE_NONE 1 -+#define USE_MIC 2 -+#define USE_LINEIN 3 -+ -+static int jz_audio_rate; -+static char jz_audio_format; -+static char jz_audio_volume; -+static char jz_audio_channels; -+static int jz_audio_b; /* bits expand multiple */ -+static int jz_audio_fragments;//unused fragment amount -+static int jz_audio_fragstotal; -+static int jz_audio_fragsize; -+static int jz_audio_speed; -+static int audio_mix_modcnt; -+static int codec_volue_shift; -+static int jz_audio_dma_tran_count;//bytes count of one DMA transfer -+static int jz_mic_only = 1; -+static int jz_codec_config = 0; -+static int use_mic_line_flag; -+static unsigned long ramp_up_start; -+static unsigned long ramp_up_end; -+static unsigned long gain_up_start; -+static unsigned long gain_up_end; -+static unsigned long ramp_down_start; -+static unsigned long ramp_down_end; -+static unsigned long gain_down_start; -+static unsigned long gain_down_end; -+ -+ -+static void jz_update_filler(int bits, int channels); -+static int Init_In_Out_queue(int fragstotal,int fragsize); -+static int Free_In_Out_queue(int fragstotal,int fragsize); -+static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -+static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -+static void (*replay_filler)(signed long src_start, int count, int id); -+static int (*record_filler)(unsigned long dst_start, int count, int id); -+static void jz_audio_reset(void); -+ -+static struct file_operations jz_i2s_audio_fops; -+ -+static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -+ -+struct jz_i2s_controller_info -+{ -+ int io_base; -+ int dma1; /* play */ -+ int dma2; /* record */ -+ char *name; -+ int dev_audio; -+ struct i2s_codec *i2s_codec[NR_I2S]; -+ int opened1; -+ int opened2; -+ unsigned char *tmp1; /* tmp buffer for sample conversions */ -+ unsigned char *tmp2; -+ spinlock_t lock; -+ spinlock_t ioctllock; -+ -+ wait_queue_head_t dac_wait; -+ wait_queue_head_t adc_wait; -+ int nextIn; // byte index to next-in to DMA buffer -+ int nextOut; // byte index to next-out from DMA buffer -+ int count; // current byte count in DMA buffer -+ int finish; // current transfered byte count in DMA buffer -+ unsigned total_bytes; // total bytes written or read -+ unsigned blocks; -+ unsigned error; // over/underrun -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+ -+static struct jz_i2s_controller_info *i2s_controller = NULL; -+struct i2s_codec -+{ -+ /* I2S controller connected with */ -+ void *private_data; -+ char *name; -+ int id; -+ int dev_mixer; -+ /* controller specific lower leverl i2s accessing routines */ -+ u16 (*codec_read) (u8 reg);//the function accessing Codec REGs fcj add -+ void (*codec_write) (u8 reg, u16 val);//to AK4642EN,val is 8bit -+ /* Wait for codec-ready. Ok to sleep here. */ -+ void (*codec_wait) (struct i2s_codec *codec); -+ /* OSS mixer masks */ -+ int modcnt; -+ int supported_mixers; -+ int stereo_mixers; -+ int record_sources; -+ int bit_resolution; -+ /* OSS mixer interface */ -+ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -+ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -+ unsigned int left, unsigned int right); -+ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -+ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -+ /* saved OSS mixer states */ -+ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -+}; -+ -+ -+typedef struct buffer_queue_s -+{ -+ int count; -+ int *id; -+ int lock; -+} buffer_queue_t; -+ -+typedef struct left_right_sample_s -+{ -+ signed long left; -+ signed long right; -+} left_right_sample_t; -+ -+typedef struct hpvol_shift_s -+{ -+ int hpvol; -+ int shift; -+} hpvol_shift_t; -+ -+static unsigned long *out_dma_buf = NULL; -+static unsigned long *out_dma_pbuf = NULL; -+static unsigned long *out_dma_buf_data_count = NULL; -+static unsigned long *in_dma_buf = NULL; -+static unsigned long *in_dma_pbuf = NULL; -+static unsigned long *in_dma_buf_data_count = NULL; -+ -+static buffer_queue_t out_empty_queue; -+static buffer_queue_t out_full_queue; -+static buffer_queue_t out_busy_queue; -+static buffer_queue_t in_empty_queue; -+static buffer_queue_t in_full_queue; -+static buffer_queue_t in_busy_queue; -+static int first_record_call = 0; -+ -+static int read_codec_file(int addr) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ return(__icdc_get_value()); -+} -+ -+static void printk_codec_files(void) -+{ -+ int cnt; -+ -+ printk("\n"); -+ -+ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -+ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -+ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -+ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -+ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -+ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -+ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -+ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -+ -+ for (cnt = 0; cnt <= 27 ; cnt++) { -+ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -+ } -+ printk("\n"); -+} -+ -+static void write_codec_file(int addr, int val) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+} -+ -+static int write_codec_file_bit(int addr, int bitval, int mask_bit) -+{ -+ int val; -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ val = __icdc_get_value(); /* read */ -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val &= ~(1 << mask_bit); -+ if (bitval == 1) -+ val |= 1 << mask_bit; -+ -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val = __icdc_get_value(); /* read */ -+ -+ if (((val >> mask_bit) & bitval) == bitval) -+ return 1; -+ else -+ return 0; -+} -+ -+/* set Audio data replay */ -+static void set_audio_data_replay() -+{ -+ /* DAC path */ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ //mdelay(100); -+ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //mdelay(300); -+} -+ -+/* unset Audio data replay */ -+static void unset_audio_data_replay(void) -+{ -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //mdelay(800); -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ //mdelay(800); -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record MIC input audio without playback */ -+static void set_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2); -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ -+ write_codec_file(22, 0x40);//mic 1 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ //write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+ -+/* unset Record MIC input audio without playback */ -+static void unset_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record LINE input audio without playback */ -+static void set_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ mdelay(10); -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+ -+/* unset Record LINE input audio without playback */ -+static void unset_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -+ -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Playback LINE input audio direct only */ -+static void set_playback_line_input_audio_direct_only() -+{ -+ jz_audio_reset();//or init_codec() -+ REG_AIC_I2SCR = 0x10; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -+ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -+} -+ -+/* unset Playback LINE input audio direct only */ -+static void unset_playback_line_input_audio_direct_only() -+{ -+ write_codec_file_bit(6, 0, 3);//GIM->0 -+ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ mdelay(100); -+ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record MIC input audio with direct playback */ -+static void set_record_mic_input_audio_with_direct_playback(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ jz_mic_only = 0; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ -+ write_codec_file(22, 0x60);//mic 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file(1, 0x4); -+} -+ -+/* unset Record MIC input audio with direct playback */ -+static void unset_record_mic_input_audio_with_direct_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record playing audio mixed with MIC input audio */ -+static void set_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ -+ write_codec_file(22, 0x63);//mic 1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -+} -+ -+/* unset Record playing audio mixed with MIC input audio */ -+static void unset_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record MIC input audio with Audio data replay (full duplex) */ -+static void set_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+ -+/* unset Record MIC input audio with Audio data replay (full duplex) */ -+static void unset_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+///////// -+/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -+static void set_record_line_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ -+ -+ //jz_mic_only = 1; -+ write_codec_file(22, 0xc6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+ -+/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -+static void unset_record_line_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+///////// -+ -+static inline int get_buffer_id(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ int i; -+ spin_lock_irqsave(&q->lock, flags); -+ //spin_lock(&q->lock); -+ if (q->count == 0) { -+ spin_unlock_irqrestore(&q->lock, flags); -+ //spin_unlock(&q->lock); -+ return -1; -+ } -+ r = *(q->id + 0); -+ for (i=0;i < q->count-1;i++) -+ *(q->id + i) = *(q->id + (i+1)); -+ q->count --; -+ spin_unlock_irqrestore(&q->lock, flags); -+ //spin_unlock(&q->lock); -+ return r; -+} -+ -+static inline void put_buffer_id(struct buffer_queue_s *q, int id) -+{ -+ unsigned long flags; -+ spin_lock_irqsave(&q->lock, flags); -+ //spin_lock(&q->lock); -+ *(q->id + q->count) = id; -+ q->count ++; -+ spin_unlock_irqrestore(&q->lock, flags); -+ //spin_unlock(&q->lock); -+} -+ -+static inline int elements_in_queue(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ spin_lock_irqsave(&q->lock, flags); -+ //spin_lock(&q->lock); -+ r = q->count; -+ spin_unlock_irqrestore(&q->lock, flags); -+ //spin_unlock(&q->lock); -+ return r; -+} -+ -+static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -+{ -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ //for DSP_GETOPTR -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ jz_audio_dma_tran_count = count; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ flags = claim_dma_lock(); -+ //__dmac_disable_module(0); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ -+ set_dma_mode(chan, mode); -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) -+ { -+ count++; -+ printk("JzSOC DMA controller can't set dma 0 count!\n"); -+ } -+ -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ //__dmac_enable_module(0); -+ release_dma_lock(flags); -+ //dump_jz_dma_channel(chan); -+ -+ //printk_codec_files(); -+} -+ -+static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -+{ -+ int id1, id2; -+ -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma2; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ //for DSP_GETIPTR -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id2); -+ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -+ //write back -+ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -+ audio_start_dma(dma,dev_id, -+ *(in_dma_pbuf + id2), -+ *(in_dma_buf_data_count + id2), -+ DMA_MODE_READ); -+ } -+ else -+ in_busy_queue.count = 0; -+ } -+ return IRQ_HANDLED; -+ -+} -+ -+static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -+{ -+ int id; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma1; -+ disable_dma(dma); -+ -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ -+ //for DSP_GETOPTR -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ //spin_lock(&controller->ioctllock); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ //spin_unlock(&controller->ioctllock); -+ if ((id = get_buffer_id(&out_busy_queue)) < 0) -+ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -+ put_buffer_id(&out_empty_queue, id); -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); //very busy -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ } -+ } else -+ out_busy_queue.count = 0; -+ -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+static void jz_i2s_initHw(int set) -+{ -+ __i2s_disable(); -+ //schedule_timeout(5); -+ -+#if defined(CONFIG_I2S_DLV) -+ __i2s_disable(); -+ __i2s_as_slave(); -+ __aic_internal_codec(); -+ //__i2s_set_oss_sample_size(16); -+ //__i2s_set_iss_sample_size(16); -+ -+#endif -+ __i2s_disable_record(); -+ __i2s_disable_replay(); -+ __i2s_disable_loopback(); -+ __i2s_set_transmit_trigger(7); -+ __i2s_set_receive_trigger(8); -+} -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ // recording -+ in_empty_queue.count = fragstotal; -+ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf) -+ goto all_mem_err; -+ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_pbuf) -+ goto all_mem_err; -+ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf_data_count) -+ goto all_mem_err; -+ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_empty_queue.id) -+ goto all_mem_err; -+ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_full_queue.id) -+ goto all_mem_err; -+ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_busy_queue.id) -+ goto all_mem_err; -+ -+ for (i=0;i < fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ for (i = 0; i < fragstotal; i++) { -+ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(in_dma_buf + i) == 0) -+ goto mem_failed_in; -+ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ } -+ -+ //playing -+ out_empty_queue.count = fragstotal; -+ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf) -+ goto all_mem_err; -+ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_pbuf) -+ goto all_mem_err; -+ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ -+ if (!out_dma_buf_data_count) -+ goto all_mem_err; -+ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_empty_queue.id) -+ goto all_mem_err; -+ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_full_queue.id) -+ goto all_mem_err; -+ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_busy_queue.id) -+ goto all_mem_err; -+ for (i=0;i < fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /*alloc DMA buffer*/ -+ for (i = 0; i < fragstotal; i++) { -+ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(out_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(OUT) buffers.\n"); -+ goto mem_failed_out; -+ } -+ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -+ } -+ -+ return 1; -+all_mem_err: -+ printk("error:allocate memory occur error 1!\n"); -+ return 0; -+mem_failed_out: -+ printk("error:allocate memory occur error 2!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ } -+ -+ return 0; -+mem_failed_in: -+ printk("error:allocate memory occur error 3!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ return 0; -+} -+ -+static int Free_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ //playing -+ if(out_dma_buf != NULL) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ *(out_dma_buf + i) = 0; //release page error -+ } -+ kfree(out_dma_buf); -+ out_dma_buf = NULL; -+ } -+ if(out_dma_pbuf) { -+ kfree(out_dma_pbuf); -+ out_dma_pbuf = NULL; -+ } -+ if(out_dma_buf_data_count) { -+ kfree(out_dma_buf_data_count); -+ out_dma_buf_data_count = NULL; -+ } -+ if(out_empty_queue.id) { -+ kfree(out_empty_queue.id); -+ out_empty_queue.id = NULL; -+ } -+ if(out_full_queue.id) { -+ kfree(out_full_queue.id); -+ out_full_queue.id = NULL; -+ } -+ if(out_busy_queue.id) { -+ kfree(out_busy_queue.id); -+ out_busy_queue.id = NULL; -+ } -+ out_empty_queue.count = fragstotal; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ -+ // recording -+ if(in_dma_buf) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) { -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ *(in_dma_buf + i) = 0; //release page error -+ } -+ kfree(in_dma_buf); -+ in_dma_buf = NULL; -+ } -+ if(in_dma_pbuf) { -+ kfree(in_dma_pbuf); -+ in_dma_pbuf = NULL; -+ } -+ if(in_dma_buf_data_count) { -+ kfree(in_dma_buf_data_count); -+ in_dma_buf_data_count = NULL; -+ } -+ if(in_empty_queue.id) { -+ kfree(in_empty_queue.id); -+ in_empty_queue.id = NULL; -+ } -+ if(in_full_queue.id) { -+ kfree(in_full_queue.id); -+ in_full_queue.id = NULL; -+ } -+ if(in_busy_queue.id) { -+ kfree(in_busy_queue.id); -+ in_busy_queue.id = NULL; -+ } -+ -+ in_empty_queue.count = fragstotal; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ return 1; -+} -+ -+static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -+{ -+ jz_i2s_initHw(0); -+} -+ -+static int jz_audio_set_speed(int dev, int rate) -+{ -+ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -+ int speed = 0, val; -+ -+ jz_audio_speed = rate; -+ if (rate > 96000) -+ rate = 96000; -+ if (rate < 8000) -+ rate = 8000; -+ jz_audio_rate = rate; -+ -+#if defined(CONFIG_I2S_DLV) -+ speed = 0; -+ switch (rate) { -+ case 8000: -+ speed = 10; -+ break; -+ case 9600: -+ speed = 9; -+ break; -+ case 11025: -+ speed = 8; -+ break; -+ case 12000: -+ speed = 7; -+ break; -+ case 16000: -+ speed = 6; -+ break; -+ case 22050: -+ speed = 5; -+ break; -+ case 24000: -+ speed = 4; -+ break; -+ case 32000: -+ speed = 3; -+ break; -+ case 44100: -+ speed = 2; -+ break; -+ case 48000: -+ speed = 1; -+ break; -+ case 96000: -+ speed = 0; -+ break; -+ default: -+ break; -+ } -+ -+ val = read_codec_file(4); -+ val = (speed << 4) | speed; -+ write_codec_file(4, val); -+ -+#if 0 -+ for (i = 0; i <= 27 ; i++) { -+ printk(" ( CCC %d : 0x%x ) ",i ,read_codec_file(i)); -+ } -+#endif -+ -+#endif -+ return jz_audio_rate; -+} -+ -+static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long data; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt++; -+ data = *(s++); -+ *(dp ++) = ((data << 16) >> 24) + 0x80; -+ s++; /* skip the other channel */ -+ } -+ return cnt; -+} -+ -+static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -+ d2 = *(s++); -+ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -+ } -+ return cnt; -+} -+ -+static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 2; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = (d1 << 16) >> 16; -+ s++; /* skip the other channel */ -+ } -+ return cnt; -+} -+ -+ -+static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 4; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = (d1 << 16) >> 16; -+ d2 = *(s++); -+ *(dp ++) = (d2 << 16) >> 16; -+ } -+ return cnt; -+} -+ -+static int record_fill_2x24_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 4; /* count in dword */ -+ cnt += 4; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = (d1 << 24) >> 24; -+ d2 = *(s++); -+ *(dp ++) = (d2 << 24) >> 24; -+ } -+ //printk("--- rec 24 ---\n"); -+ return cnt; -+} -+ -+static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char data; -+ unsigned long ddata; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count--; -+ cnt += 1; -+ data = *(s++) - 0x80; -+ ddata = (unsigned long) data << 8; -+ *(dp ++) = ddata; -+ *(dp ++) = ddata; -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x8_u(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char d1; -+ unsigned long dd1; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count -= 1; -+ cnt += 1 ; -+ d1 = *(s++) - 0x80; -+ dd1 = (unsigned long) d1 << 8; -+ *(dp ++) = dd1; -+ } -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_1x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2 ; -+ d1 = *(s++); -+ l1 = (unsigned long)d1; -+ *(dp ++) = l1; -+ *(dp ++) = l1; -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ -+ *(dp ++) = l1; -+ } -+ -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -+{ -+ switch (fmt) { -+ case AFMT_U8: -+ __i2s_set_oss_sample_size(8); -+ __i2s_set_iss_sample_size(8); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ break; -+ case AFMT_S16_LE: -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x00); -+ //write_codec_file(2, 0x60); -+ -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ -+ /* print all files */ -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ break; -+ case 18: -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x28); -+ //write_codec_file(2, 0x60); -+ __i2s_set_oss_sample_size(18); -+ __i2s_set_iss_sample_size(16); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ break; -+ case 24: -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x78); -+ //write_codec_file(2, 0x60); -+ __i2s_set_oss_sample_size(24); -+ __i2s_set_iss_sample_size(24); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ break; -+ case AFMT_QUERY: -+ break; -+ } -+ return jz_audio_format; -+} -+ -+static short jz_audio_set_channels(int dev, short channels) -+{ -+ switch (channels) { -+ case 1: -+ /* print all files */ -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -+ break; -+ case 2: -+ /* print all files */ -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -+ break; -+ case 0: -+ break; -+ } -+ return jz_audio_channels; -+} -+ -+static void init_codec(void) -+{ -+#if defined(CONFIG_I2S_DLV) -+ /* reset DLV codec. from hibernate mode to sleep mode */ -+ write_codec_file(0, 0xf); -+ write_codec_file_bit(6, 0, 0); -+ write_codec_file_bit(6, 0, 1); -+ mdelay(200); -+ //write_codec_file(0, 0xf); -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 -+ mdelay(10);//wait for stability -+#endif -+} -+ -+static void jz_audio_reset(void) -+{ -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+ REG_AIC_I2SCR = 0x10; -+ init_codec(); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file); -+static int jz_audio_open(struct inode *inode, struct file *file); -+static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -+static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -+static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -+/* static struct file_operations jz_i2s_audio_fops */ -+static struct file_operations jz_i2s_audio_fops = -+{ -+ owner: THIS_MODULE, -+ open: jz_audio_open, -+ release: jz_audio_release, -+ write: jz_audio_write, -+ read: jz_audio_read, -+ poll: jz_audio_poll, -+ ioctl: jz_audio_ioctl -+}; -+ -+static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -+{ -+ int i; -+ int minor = MINOR(inode->i_rdev); -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ -+ for (i = 0; i < NR_I2S; i++) -+ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -+ goto match; -+ -+ if (!controller) -+ return -ENODEV; -+match: -+ file->private_data = controller->i2s_codec[i]; -+ return 0; -+} -+ -+static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -+ return codec->mixer_ioctl(codec, cmd, arg); -+} -+ -+static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -+{ -+ return -ESPIPE; -+} -+ -+static struct file_operations jz_i2s_mixer_fops = -+{ -+ owner: THIS_MODULE, -+ llseek: jz_i2s_llseek, -+ ioctl: jz_i2s_ioctl_mixdev, -+ open: jz_i2s_open_mixdev, -+}; -+ -+static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ u8 cur_vol; -+ long val = 0; -+ -+ switch (cmd) { -+ case SOUND_MIXER_INFO: -+ { -+ mixer_info info; -+#if defined(CONFIG_I2S_DLV) -+ strncpy(info.id, "DLV", sizeof(info.id)); -+ strncpy(info.name,"Jz4750 internal codec", sizeof(info.name)); -+#endif -+ -+ info.modify_counter = audio_mix_modcnt; -+ return copy_to_user((void *)arg, &info, sizeof(info)); -+ } -+ case SOUND_OLD_MIXER_INFO: -+ { -+ _old_mixer_info info; -+#if defined(CONFIG_I2S_DLV) -+ strncpy(info.id, "DLV", sizeof(info.id)); -+ strncpy(info.name,"Jz4750 internal codec", sizeof(info.name)); -+#endif -+ -+ return copy_to_user((void *)arg, &info, sizeof(info)); -+ } -+ case SOUND_MIXER_READ_STEREODEVS: -+ return put_user(0, (long *) arg); -+ case SOUND_MIXER_READ_CAPS: -+ val = SOUND_CAP_EXCL_INPUT; -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_READ_DEVMASK: -+ break; -+ case SOUND_MIXER_READ_RECMASK: -+ break; -+ case SOUND_MIXER_READ_RECSRC: -+ break; -+ case SOUND_MIXER_WRITE_SPEAKER: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ -+ REG_CPM_I2SCDR = val; -+ printk_codec_files(); -+ break; -+ case SOUND_MIXER_WRITE_BASS: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+#if defined(CONFIG_I2S_DLV) -+#endif -+ return 0; -+ -+ case SOUND_MIXER_READ_BASS: -+#if defined(CONFIG_I2S_DLV) -+#endif -+ return put_user(val, (long *) arg); -+ -+ case SOUND_MIXER_WRITE_VOLUME: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val == 100) { -+ //REG_CPM_CLKGR |= 0x60; -+ printk("gate clock : 0x%08x\n", REG_CPM_CLKGR); -+ return 100; -+ } -+ if(val == 99) { -+ REG_CPM_CLKGR &= ~0x60; -+ return 99; -+ } -+ if(val == 98) { -+ REG_CPM_CPCCR |= 0x80400000; -+ return 98; -+ } -+ if(val == 97) { -+ REG_CPM_CPCCR &= ~0x8000000; -+ REG_CPM_CPCCR |= 0x0040000; -+ return 97; -+ } -+ if(val > 31) -+ val = 31; -+ -+ jz_audio_volume = val; -+ //printk("\njz_audio_volume=%d\n",jz_audio_volume); -+#if defined(CONFIG_I2S_DLV) -+ cur_vol = val; -+ write_codec_file(17, cur_vol | 0xc0); -+ write_codec_file(18, cur_vol); -+#endif -+ return 0; -+ case SOUND_MIXER_READ_VOLUME: -+#if defined(CONFIG_I2S_DLV) -+ val = jz_audio_volume | jz_audio_volume << 8; -+#endif -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_LINE: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if (val == 100) { -+ printk("Playback LINE input audio direct only is starting...\n"); -+ printk_codec_files(); -+ set_playback_line_input_audio_direct_only(); -+ printk_codec_files(); -+ return 100; -+ } -+ if (val == 99) { -+ printk("Playback LINE input audio direct only is end\n"); -+ unset_playback_line_input_audio_direct_only(); -+ printk_codec_files(); -+ return 99; -+ } -+ -+ if(val > 31) -+ val = 31; -+#if defined(CONFIG_I2S_DLV) -+ use_mic_line_flag = USE_LINEIN; -+ /* set gain */ -+ cur_vol = val; -+ cur_vol &= 0x1f; -+ write_codec_file(11, cur_vol);//GO1L -+ write_codec_file(12, cur_vol);//GO1R -+#endif -+ return 0; -+ break; -+ case SOUND_MIXER_WRITE_MIC: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ -+ if(val > 0xf) -+ val = 0xf; -+#if defined(CONFIG_I2S_DLV) -+ use_mic_line_flag = USE_MIC; -+ /* set gain */ -+ //write_codec_file_bit(6, 1, 3);//GIM -+ cur_vol = val; -+ cur_vol |= cur_vol << 4; -+ write_codec_file(19, cur_vol);//GIL,GIR -+#endif -+ return 0; -+ -+ case SOUND_MIXER_READ_MIC: -+#if defined(CONFIG_I2S_DLV) -+#endif -+ -+ return put_user(val, (long *) arg); -+ default: -+ return -ENOSYS; -+ } -+ audio_mix_modcnt ++; -+ -+ return 0; -+} -+ -+int i2s_probe_codec(struct i2s_codec *codec) -+{ -+ /* generic OSS to I2S wrapper */ -+ codec->mixer_ioctl = i2s_mixer_ioctl; -+ return 1; -+} -+ -+ -+/* I2S codec initialisation. */ -+static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -+{ -+ int num_i2s = 0; -+ struct i2s_codec *codec; -+ -+ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -+ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ memset(codec, 0, sizeof(struct i2s_codec)); -+ codec->private_data = controller; -+ codec->id = num_i2s; -+ -+ if (i2s_probe_codec(codec) == 0) -+ break; -+ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -+ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -+ kfree(codec); -+ break; -+ } -+ controller->i2s_codec[num_i2s] = codec; -+ } -+ return num_i2s; -+} -+ -+static void replay_fill_2x18_s(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed long d1; -+ signed long l1; -+ volatile signed long *s = (signed long *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count -= 4; -+ cnt += 4; -+ d1 = *(s++); -+ l1 = (signed long)d1; -+ *(dp ++) = l1; -+ } -+ -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x24_s(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed long d1; -+ signed long l1; -+ volatile signed long *s = (signed long *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count -= 4; -+ cnt += 4; -+ d1 = *(s++); -+ l1 = (signed long)d1; -+ *(dp ++) = l1; -+ } -+ -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+ //printk("--- play 24 ---\n"); -+} -+ -+static void jz_update_filler(int format, int channels) -+{ -+ #define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -+ -+ switch (TYPE(format, channels)) -+ { -+ default: -+ case TYPE(AFMT_U8, 1): -+ jz_audio_b = 4;//4bytes * 8bits =32bits -+ replay_filler = replay_fill_1x8_u; -+ record_filler = record_fill_1x8_u; -+ break; -+ case TYPE(AFMT_U8, 2): -+ jz_audio_b = 4; -+ replay_filler = replay_fill_2x8_u; -+ record_filler = record_fill_2x8_u; -+ break; -+ case TYPE(AFMT_S16_LE, 1): -+ //2bytes * 16bits =32bits -+ jz_audio_b = 2; -+ replay_filler = replay_fill_1x16_s; -+ record_filler = record_fill_1x16_s; -+ break; -+ case TYPE(AFMT_S16_LE, 2): -+ jz_audio_b = 2; -+ replay_filler = replay_fill_2x16_s; -+ record_filler = record_fill_2x16_s; -+ break; -+ case TYPE(18, 2): -+ jz_audio_b = 1; -+ replay_filler = replay_fill_2x18_s; -+ record_filler = record_fill_2x16_s; -+ break; -+ case TYPE(24, 2): -+ jz_audio_b = 1; -+ replay_filler = replay_fill_2x24_s; -+ record_filler = record_fill_2x24_s; -+ //printk("--- 24 ---\n"); -+ break; -+ } -+} -+ -+ -+#ifdef CONFIG_PROC_FS -+extern struct proc_dir_entry *proc_jz_root; -+ -+int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ return 0; -+} -+ -+static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -+{ -+ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -+ return -EIO; -+ return 0; -+} -+ -+static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -+{ -+ ; -+} -+#endif -+ -+static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ char *name; -+ int adev;//No of Audio device. -+ name = controller->name; -+ jz_i2s_initHw(1);//initialize AIC controller and reset it -+ /* register /dev/audio */ -+ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -+ if (adev < 0) -+ goto audio_failed; -+ /* initialize I2S codec and register /dev/mixer */ -+ if (jz_i2s_codec_init(controller) <= 0) -+ goto mixer_failed; -+ -+#ifdef CONFIG_PROC_FS -+ if (jz_i2s_init_proc(controller) < 0) { -+ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -+ goto proc_failed; -+ } -+#endif -+ -+ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); -+ if (!controller->tmp1) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp1_failed; -+ } -+ -+ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); -+ if (!controller->tmp2) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp2_failed; -+ } -+ -+ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -+ goto dma1_failed; -+ } -+ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -+ goto dma2_failed; -+ } -+ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -+ -+ controller->dev_audio = adev; -+ -+ return; -+dma2_failed: -+ jz_free_dma(controller->dma2); -+dma1_failed: -+ jz_free_dma(controller->dma1); -+ free_pages((unsigned long)controller->tmp2, JZCODEC_USER_BUFFER); -+tmp2_failed: -+tmp1_failed: -+ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+proc_failed: -+ /* unregister mixer dev */ -+mixer_failed: -+ unregister_sound_dsp(adev); -+audio_failed: -+ return; -+} -+ -+ -+static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -+{ -+ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -+ return -ENOMEM; -+ } -+ (*controller)->name = "Jz I2S controller"; -+ (*controller)->opened1 = 0; -+ (*controller)->opened2 = 0; -+ init_waitqueue_head(&(*controller)->adc_wait); -+ init_waitqueue_head(&(*controller)->dac_wait); -+ spin_lock_init(&(*controller)->lock); -+ init_waitqueue_head(&rx_wait_queue); -+ init_waitqueue_head(&tx_wait_queue); -+ init_waitqueue_head(&pop_wait_queue); -+ -+ return 0; -+} -+ -+static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ int adev = controller->dev_audio; -+ jz_i2s_full_reset (controller); -+ controller->dev_audio = -1; -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+ -+ jz_free_dma(controller->dma1); -+ jz_free_dma(controller->dma2); -+ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -+ free_pages((unsigned long)controller->tmp2, JZCODEC_USER_BUFFER); -+ if (adev >= 0) { -+ //unregister_sound_mixer(audio_devs[adev]->mixer_dev); -+ unregister_sound_dsp(controller->dev_audio); -+ } -+} -+ -+ -+#ifdef CONFIG_PM -+static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -+{ -+ return 0; -+} -+ -+static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -+{ -+ return 0; -+} -+ -+static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct jz_i2s_controller_info *controller = pm_dev->data; -+ -+ if (!controller) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jz_i2s_suspend(controller, (int)data); -+ break; -+ -+ case PM_RESUME: -+ ret = jz_i2s_resume(controller); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#endif /* CONFIG_PM */ -+ -+ -+static irqreturn_t aic_codec_irq(int irq, void *dev_id) -+{ -+ u8 file_9 = read_codec_file(9); -+ u8 file_8 = read_codec_file(8); -+ -+ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -+ if ((file_9 & 0x1f) == 0x10) { -+ -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x4) != 0x4); -+ while ((read_codec_file(9) & 0x10) == 0x10) { -+ write_codec_file(9, 0x10); -+ } -+ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x8) != 0x8); -+ write_codec_file(9, file_9); -+ write_codec_file(8, file_8); -+ -+ return IRQ_HANDLED; -+ } -+ -+ if (file_9 & 0x8) -+ ramp_up_end = jiffies; -+ else if (file_9 & 0x4) -+ ramp_down_end = jiffies; -+ else if (file_9 & 0x2) -+ gain_up_end = jiffies; -+ else if (file_9 & 0x1) -+ gain_down_end = jiffies; -+ -+ write_codec_file(9, file_9); -+ if (file_9 & 0xf) -+ wake_up(&pop_wait_queue); -+ while (REG_ICDC_RGDATA & 0x100); -+ -+ return IRQ_HANDLED; -+} -+ -+static int __init init_jz_i2s(void) -+{ -+ int errno, retval; -+ -+#if defined(CONFIG_I2S_DLV) -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+ -+ //REG_CPM_CPCCR &= ~(1 << 31); -+ //REG_CPM_CPCCR &= ~(1 << 30); -+ use_mic_line_flag = USE_NONE; -+ write_codec_file(0, 0xf); -+ -+ REG_AIC_I2SCR = 0x10; -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ __aic_reset(); -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ -+ /* power on DLV */ -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+#endif -+ -+ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -+ return errno; -+ attach_jz_i2s(i2s_controller); -+#if defined(CONFIG_I2S_DLV) -+ __i2s_disable_transmit_intr(); -+ __i2s_disable_receive_intr(); -+ jz_codec_config = 0; -+ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -+ if (retval) { -+ printk("Could not get aic codec irq %d\n", IRQ_AIC); -+ return retval; -+ } -+#endif -+ -+ out_empty_queue.id = NULL; -+ out_full_queue.id = NULL; -+ out_busy_queue.id = NULL; -+ in_empty_queue.id = NULL; -+ in_full_queue.id = NULL; -+ in_busy_queue.id = NULL; -+ -+ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -+ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+#ifdef CONFIG_PM -+ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -+ jz_i2s_pm_callback); -+ if (i2s_controller->pm) -+ i2s_controller->pm->data = i2s_controller; -+#endif -+ -+ __cpm_start_idct(); -+ __cpm_start_db(); -+ __cpm_start_me(); -+ __cpm_start_mc(); -+ __cpm_start_ipu(); -+ -+ return 0; -+} -+ -+ -+static void __exit cleanup_jz_i2s(void) -+{ -+ unload_jz_i2s(i2s_controller); -+#if defined(CONFIG_I2S_DLV) -+ free_irq(IRQ_AIC, NULL); -+#endif -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+} -+ -+module_init(init_jz_i2s); -+module_exit(cleanup_jz_i2s); -+ -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ //DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,i=0; -+ -+ //add_wait_queue(&ctrl->adc_wait, &wait); -+ for (;;) { -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ //set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ //spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ //spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ /*if (signal_pending(current)) -+ break;*/ -+ if (nonblock) { -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ /*if (signal_pending(current)) -+ return -ERESTARTSYS;*/ -+ return 0; -+} -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ unsigned long flags; -+ int count,ele,busyele,emptyele,i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(200); -+ -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } else {//non-blocked -+ mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ mdelay(100); -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static void print_pop_duration(void) -+{ -+ long diff; -+#if 0 -+ printk(" ramp_up_start=0x%x\n",ramp_up_start); -+ printk(" ramp_up_end =0x%x\n",ramp_up_end); -+ printk(" gain_up_start=0x%x\n",gain_up_start); -+ printk(" gain_up_end =0x%x\n",gain_up_end); -+ -+ printk("ramp_down_start=0x%x\n",ramp_down_start); -+ printk("ramp_down_end =0x%x\n",ramp_down_end); -+ printk("gain_down_start=0x%x\n",gain_down_start); -+ printk("gain_down_end =0x%x\n",gain_down_end); -+#endif -+ -+ diff = (long)ramp_up_end - (long)ramp_up_start; -+ printk("ramp up duration: %d ms\n",diff * 1000 / HZ); -+ diff = (long)gain_up_end - (long)gain_up_start; -+ printk("gain up duration: %d ms\n",diff * 1000 / HZ); -+ diff = (long)gain_down_end - (long)gain_down_start; -+ printk("gain down duration: %d ms\n",diff); -+ diff = (long)ramp_down_end - (long)ramp_down_start; -+ printk("ramp down duration: %d ms\n",diff * 1000 / HZ); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long tfl; -+ -+ jz_codec_config = 0; -+ if (controller == NULL) -+ return -ENODEV; -+ -+ if (controller->opened1 == 1 && controller->opened2 == 1) { -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ /* wait for fifo empty */ -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ gain_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_down_end = jiffies; -+ /*while (1) { -+ tfl = REG_AIC_SR & 0x00003f00; -+ if (tfl == 0) { -+ udelay(500); -+ break; -+ } -+ mdelay(2); -+ }*/ -+ mdelay(100); -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ -+ __i2s_disable_transmit_dma(); -+ __i2s_disable_replay(); -+ -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ -+ ///////////////////////// -+ first_record_call = 1; -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ //__aic_flush_fifo(); -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ ramp_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_down_end = jiffies; -+ if (use_mic_line_flag == USE_LINEIN) { -+ unset_record_line_input_audio_with_audio_data_replay(); -+ //printk("3 use_mic_line_flag=%d\n",use_mic_line_flag); -+ } -+ if (use_mic_line_flag == USE_MIC) { -+ unset_record_mic_input_audio_with_audio_data_replay(); -+ //printk("4 use_mic_line_flag=%d\n",use_mic_line_flag); -+ } -+ -+#if 0 -+ unset_record_playing_audio_mixed_with_mic_input_audio(); -+#endif -+ __i2s_disable(); -+#endif -+ } else if ( controller->opened1 == 1 ) { -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ /* wait for fifo empty */ -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ gain_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_down_end = jiffies; -+ while (1) { -+ tfl = REG_AIC_SR & 0x00003f00; -+ if (tfl == 0) { -+ udelay(500); -+ break; -+ } -+ mdelay(2); -+ } -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ -+ __i2s_disable_transmit_dma(); -+ __i2s_disable_replay(); -+ -+ __aic_flush_fifo(); -+ -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ ramp_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_down_end = jiffies; -+ unset_audio_data_replay(); -+#endif -+ __i2s_disable(); -+ } else if ( controller->opened2 == 1 ) { -+ //controller->opened2 = 0; -+ first_record_call = 1; -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+#if defined(CONFIG_I2S_DLV) -+#if 0 -+ /* unset Record MIC input audio with direct playback */ -+ unset_record_mic_input_audio_with_direct_playback(); -+#endif -+#if 1 -+ /* unset Record MIC input audio without playback */ -+ unset_record_mic_input_audio_without_playback(); -+#endif -+#if 0 -+ /* tested */ -+ /* unset Record LINE input audio without playback */ -+ unset_record_line_input_audio_without_playback(); -+#endif -+#endif -+ __i2s_disable(); -+ } -+ -+ if (controller->opened1 == 1 && controller->opened2 == 1) { -+ controller->opened1 = 0; -+ controller->opened2 = 0; -+ print_pop_duration(); -+ //__dmac_disable_module(0); -+ } else if ( controller->opened1 == 1 ) { -+ controller->opened1 = 0; -+ print_pop_duration(); -+ } else if ( controller->opened2 == 1 ) { -+ controller->opened2 = 0; -+ } -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ -+/* __cpm_stop_idct(); -+ __cpm_stop_db(); -+ __cpm_stop_me(); -+ __cpm_stop_mc(); -+ __cpm_stop_ipu();*/ -+ printk("close audio and clear ipu gate : 0x%08x\n", REG_CPM_CLKGR); -+ return 0; -+} -+ -+static int jz_audio_open(struct inode *inode, struct file *file) -+{ -+ int i; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ if (controller == NULL) -+ return -ENODEV; -+ mdelay(2); -+ REG_DMAC_DMACKE(0) = 0x3f; -+ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -+ printk("\naudio is busy!\n"); -+ return -EBUSY; -+ } -+ jz_codec_config = 0; -+ -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+ -+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ controller->opened1 = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ -+ controller->opened2 = 1; -+ first_record_call = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ } else if (file->f_mode & FMODE_WRITE) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ controller->opened1 = 1; -+ //for ioctl -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ } else if (file->f_mode & FMODE_READ) { -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ -+ controller->opened2 = 1; -+ first_record_call = 1; -+ //for ioctl -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ } -+ -+ file->private_data = controller; -+ jz_audio_reset();//11.2 -+ -+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -+#if defined(CONFIG_I2S_DLV) -+ -+ if (use_mic_line_flag == USE_LINEIN) { -+ /* Record LINE input audio with Audio data replay (full duplex for linein) */ -+ /* codec_test_line */ -+ set_record_line_input_audio_with_audio_data_replay(); -+ -+ } -+ if (use_mic_line_flag == USE_MIC) { -+ /* Record MIC input audio with Audio data replay (full duplex) */ -+ /* codec_test_mic */ -+ set_record_mic_input_audio_with_audio_data_replay(); -+ } -+#if 0 -+ /* Record playing audio mixed with MIC input audio */ -+ set_record_playing_audio_mixed_with_mic_input_audio(); -+#endif -+ -+#endif -+ } else if (file->f_mode & FMODE_WRITE) { -+#if defined(CONFIG_I2S_DLV) -+ //mdelay(10); -+ /* Audio data replay */ -+ set_audio_data_replay(); -+#endif -+ } else if (file->f_mode & FMODE_READ) { -+#if defined(CONFIG_I2S_DLV) -+#if 0 -+ /* Record MIC input audio with direct playback */ -+ set_record_mic_input_audio_with_direct_playback(); -+#endif -+ -+#if 1 -+ /* set Record MIC input audio without playback */ -+ set_record_mic_input_audio_without_playback(); -+#endif -+#if 0 -+ /* tested */ -+ /* set Record LINE input audio without playback */ -+ set_record_line_input_audio_without_playback(); -+#endif -+ mdelay(1); -+#endif -+ } -+ -+ __aic_reset(); -+ -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ __aic_flush_fifo(); -+ __i2s_enable(); -+ ndelay(100); -+ -+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -+#if defined(CONFIG_I2S_DLV) -+ //set SB_ADC or SB_DAC -+ __dmac_enable_module(0); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ ramp_up_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_up_end = jiffies; -+#endif -+ } else if (file->f_mode & FMODE_WRITE) { -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ ramp_up_start = jiffies; -+ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RCR = 0x1; -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RGR = 1;*/ -+ sleep_on(&pop_wait_queue); -+ //ramp_up_end = jiffies; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+#endif -+ } else if (file->f_mode & FMODE_READ) { -+#if defined(CONFIG_I2S_DLV) -+ if (jz_mic_only) -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ else -+ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -+ mdelay(500); -+#endif -+ } -+ -+ -+ printk("open audio and set ipu gate : 0x%08x\n", REG_CPM_CLKGR); -+ return 0; -+} -+ -+ -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+unsigned int cmd, unsigned long arg) -+{ -+ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ -+ audio_buf_info abinfo; -+ int i, bytes, id; -+ count_info cinfo; -+ val = 0; -+ bytes = 0; -+ switch (cmd) { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, (int *)arg); -+ case SNDCTL_DSP_RESET: -+ return 0; -+ case SNDCTL_DSP_SYNC: -+ if (file->f_mode & FMODE_WRITE) -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ return 0; -+ case SNDCTL_DSP_SPEED: -+ /* set smaple rate */ -+ { -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val >= 0) -+ jz_audio_set_speed(controller->dev_audio, val); -+ return put_user(val, (int *)arg); -+ } -+ case SNDCTL_DSP_STEREO: -+ /* set stereo or mono channel */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -+ return 0; -+ -+ case SNDCTL_DSP_GETBLKSIZE: -+ //return put_user(4*PAGE_SIZE, (int *)arg); -+ return put_user(jz_audio_fragsize , (int *)arg); -+ case SNDCTL_DSP_GETFMTS: -+ /* Returns a mask of supported sample format*/ -+ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -+ -+ case SNDCTL_DSP_SETFMT: -+ /* Select sample format */ -+ { -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val != AFMT_QUERY) { -+ jz_audio_set_format(controller->dev_audio,val); -+ } else { -+ if (file->f_mode & FMODE_READ) -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ else -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ -+ } -+ return put_user(val, (int *)arg); -+ } -+ -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val); -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_POST: -+ /* FIXME: the same as RESET ?? */ -+ return 0; -+ -+ case SNDCTL_DSP_SUBDIVIDE: -+ return 0; -+ -+ case SNDCTL_DSP_SETFRAGMENT: -+ get_user(val, (long *) arg); -+ newfragsize = 1 << (val & 0xFFFF);//16 least bits -+ -+ if (newfragsize < 4 * PAGE_SIZE) -+ newfragsize = 4 * PAGE_SIZE; -+ if (newfragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE -+ newfragsize = 16 * PAGE_SIZE; -+ -+ newfragstotal = (val >> 16) & 0x7FFF; -+ if (newfragstotal < 2) -+ newfragstotal = 2; -+ if (newfragstotal > 32) -+ newfragstotal = 32; -+ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -+ return 0; -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(500); -+ jz_audio_fragstotal = newfragstotal; -+ jz_audio_fragsize = newfragsize; -+ -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(10); -+ -+ return 0; -+ case SNDCTL_DSP_GETCAPS: -+ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -+ case SNDCTL_DSP_NONBLOCK: -+ file->f_flags |= O_NONBLOCK; -+ return 0; -+ case SNDCTL_DSP_SETDUPLEX: -+ return -EINVAL; -+ case SNDCTL_DSP_GETOSPACE: -+ { -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ //unused fragment amount -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_fragments = elements_in_queue(&out_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ bytes /= jz_audio_b; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ abinfo.fragsize = jz_audio_fragsize; -+ abinfo.bytes = bytes; -+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETISPACE: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ -+ bytes = 0; -+ //unused fragment amount -+ jz_audio_fragments = elements_in_queue(&in_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ bytes /= jz_audio_b; -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ abinfo.fragsize = jz_audio_fragsize; -+ abinfo.bytes = bytes; -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ case SNDCTL_DSP_GETTRIGGER: -+ val = 0; -+ if (file->f_mode & FMODE_READ && in_dma_buf) -+ val |= PCM_ENABLE_INPUT; -+ if (file->f_mode & FMODE_WRITE && out_dma_buf) -+ val |= PCM_ENABLE_OUTPUT; -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_SETTRIGGER: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ return 0; -+ case SNDCTL_DSP_GETIPTR: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ //controller->total_bytes += get_dma_residue(controller->dma2); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextIn; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETOPTR: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ //controller->total_bytes += get_dma_residue(controller->dma1); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextOut; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETODELAY: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ unfinish = 0; -+ fullc = elements_in_queue(&out_full_queue); -+ busyc = elements_in_queue(&out_busy_queue); -+ for(i = 0;i < fullc ;i ++) { -+ id = *(out_full_queue.id + i); -+ unfinish += *(out_dma_buf_data_count + id); -+ } -+ for(i = 0;i < busyc ;i ++) { -+ id = *(out_busy_queue.id + i); -+ unfinish += get_dma_residue(controller->dma1); -+ } -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ unfinish /= jz_audio_b; -+ return put_user(unfinish, (int *) arg); -+ case SOUND_PCM_READ_RATE: -+ return put_user(jz_audio_rate, (int *)arg); -+ case SOUND_PCM_READ_CHANNELS: -+ return put_user(jz_audio_channels, (int *)arg); -+ case SOUND_PCM_READ_BITS: -+ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, -+ (int *)arg); -+ case SNDCTL_DSP_MAPINBUF: -+ case SNDCTL_DSP_MAPOUTBUF: -+ case SNDCTL_DSP_SETSYNCRO: -+ case SOUND_PCM_WRITE_FILTER: -+ case SOUND_PCM_READ_FILTER: -+ return -EINVAL; -+ } -+ return -EINVAL; -+} -+ -+ -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long flags; -+ unsigned int mask = 0; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ return POLLOUT | POLLWRNORM; -+ poll_wait(file, &controller->dac_wait, wait); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ return POLLIN | POLLRDNORM; -+ poll_wait(file, &controller->adc_wait, wait); -+ } -+ spin_lock_irqsave(&controller->lock, flags); -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ mask |= POLLOUT | POLLWRNORM; -+ } else if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ mask |= POLLIN | POLLRDNORM; -+ } -+ spin_unlock_irqrestore(&controller->lock, flags); -+ return mask; -+} -+ -+static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ int id, ret = 0, left_count, copy_count, cnt = 0; -+ -+ if (count < 0) -+ return -EINVAL; -+ -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->nextIn = 0; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ -+ spin_lock(&controller->lock); -+ -+ copy_count = jz_audio_fragsize / 4; -+ -+ left_count = count; -+ spin_unlock(&controller->lock); -+ -+ if (first_record_call) { -+ first_record_call = 0; -+ audio_read_back_first: -+ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ spin_unlock(&controller->lock); -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ -+ //write back -+ dma_cache_wback_inv(*(in_dma_buf + id), -+ *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ //interruptible_sleep_on(&rx_wait_queue); -+ sleep_on(&rx_wait_queue); -+ } else -+ goto audio_read_back_first; -+ } -+ -+ while (left_count > 0) { -+ audio_read_back_second: -+ if (elements_in_queue(&in_full_queue) <= 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret ? ret : -EAGAIN; -+ else -+ sleep_on(&rx_wait_queue); -+ } -+ /*if (signal_pending(current)) -+ return ret ? ret: -ERESTARTSYS; */ -+ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -+ spin_lock(&controller->lock); -+ cnt = record_filler((unsigned long)controller->tmp2+ret, -+ copy_count, id); -+ spin_unlock(&controller->lock); -+ put_buffer_id(&in_empty_queue, id); -+ } else -+ goto audio_read_back_second; -+ -+ if (elements_in_queue(&in_busy_queue) == 0) { -+ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ spin_unlock(&controller->lock); -+ //write back -+ dma_cache_wback_inv(*(in_dma_buf + id), -+ *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ } -+ } -+ if (ret + cnt > count) { -+ spin_lock(&controller->lock); -+ cnt = count - ret; -+ spin_unlock(&controller->lock); -+ } -+ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -+ return ret ? ret : -EFAULT; -+ spin_lock(&controller->lock); -+ ret += cnt; -+ spin_unlock(&controller->lock); -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->nextIn += ret; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ spin_lock(&controller->lock); -+ left_count -= cnt; -+ spin_unlock(&controller->lock); -+ }//while (left_count > 0) -+ return ret; -+} -+ -+static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -+{ -+ int id, ret = 0, left_count, copy_count = 0, val; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ -+ if (count <= 0) -+ return -EINVAL; -+ -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ //spin_lock(&controller->ioctllock); -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ //spin_unlock(&controller->ioctllock); -+ if (jz_audio_channels == 2) -+ copy_count = jz_audio_fragsize / jz_audio_b; -+ else if(jz_audio_channels == 1) -+ copy_count = jz_audio_fragsize / 4; -+ -+ left_count = count; -+ if (copy_from_user(controller->tmp1, buffer, count)) { -+ printk("copy_from_user failed:%d",ret); -+ return ret ? ret : -EFAULT; -+ } -+ -+ while (left_count > 0) { -+ audio_write_back: -+ if (file->f_flags & O_NONBLOCK) -+ udelay(2); -+ if (elements_in_queue(&out_empty_queue) == 0) { -+ // all are full -+ if (file->f_flags & O_NONBLOCK) -+ return ret;//no waiting,no block -+ else { -+ sleep_on(&tx_wait_queue);//blocked -+ } -+ } -+ /*if (signal_pending(current)) -+ return ret ? ret : -ERESTARTSYS;*/ -+ /* the end fragment size in this write */ -+ if (ret + copy_count > count) -+ copy_count = count - ret; -+ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -+ //replay_filler((unsigned long)controller->tmp1 + ret, copy_count, id); -+ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ put_buffer_id(&out_full_queue, id); //busy in -+ dma_cache_wback_inv(*(out_dma_buf + id), -+ *(out_dma_buf_data_count + id)); -+ } else -+ put_buffer_id(&out_empty_queue, id); //spare -+ } else -+ goto audio_write_back; -+ -+ left_count = left_count - copy_count; -+ ret += copy_count; -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ controller->nextOut += ret; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ if (elements_in_queue(&out_busy_queue) == 0) { -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); //first once,next spare -+ -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(controller->dma1, -+ file->private_data, -+ *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ if (jz_codec_config == 0) { -+ write_codec_file_bit(1, 0, 5); -+ gain_up_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_up_end = jiffies; -+ jz_codec_config = 1; -+ //SB_ADC->1 -+ //write_codec_file_bit(5, 1, 4); -+ //while(1); -+ } -+ } -+ } -+ } -+ } -+ return ret; -+} -diff --git a/sound/oss/jz_i2s_for_4750.c b/sound/oss/jz_i2s_for_4750.c -new file mode 100644 -index 0000000..2ca3342 ---- /dev/null -+++ b/sound/oss/jz_i2s_for_4750.c -@@ -0,0 +1,2981 @@ -+/* -+ * linux/drivers/sound/Jz_i2s.c -+ * -+ * JzSOC On-Chip I2S audio driver. -+ * -+ * Copyright (C) 2005 by Junzheng Corp. -+ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -+ * dma channel 4&3,noah is tested. -+ * -+ * 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. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sound_config.h" -+ -+#define DPRINTK(args...) printk(args) -+#define DMA_ID_I2S_TX DMA_ID_AIC_TX -+#define DMA_ID_I2S_RX DMA_ID_AIC_RX -+#define NR_I2S 2 -+#define MAXDELAY 50000 -+#define JZCODEC_RW_BUFFER_SIZE 2 -+#define JZCODEC_RW_BUFFER_TOTAL 6 -+ -+typedef struct hpvol_shift_s -+{ -+ int hpvol; -+ int shift; -+} hpvol_shift_t; -+ -+mixer_info info; -+_old_mixer_info old_info; -+int codec_volue_shift; -+hpvol_shift_t hpvol_shift_table[72]; -+int abnormal_data_count; -+unsigned long i2s_clk; -+ -+void (*set_codec_mode)(void) = NULL; -+void (*clear_codec_mode)(void) = NULL; -+void (*set_codec_gpio_pin)(void) = NULL; -+void (*each_time_init_codec)(void) = NULL; -+int (*set_codec_startup_param)(void) = NULL; -+void (*set_codec_volume_table)(void) = NULL; -+void (*set_codec_record)(void) = NULL; -+void (*set_codec_replay)(void) = NULL; -+void (*set_codec_replay_record)(void); -+void (*turn_on_codec)(void) = NULL; -+void (*turn_off_codec)(void) = NULL; -+void (*set_codec_speed)(int rate) = NULL; -+void (*reset_codec)(void) = NULL; -+void (*codec_mixer_old_info_id_name)(void) = NULL; -+void (*codec_mixer_info_id_name)(void) = NULL; -+void (*set_codec_bass)(int val) = NULL; -+void (*set_codec_volume)(int val) = NULL; -+void (*set_codec_mic)(int val) = NULL; -+void (*i2s_resume_codec)(void) = NULL; -+void (*i2s_suspend_codec)(int wr,int rd) = NULL; -+void (*init_codec_pin)(void) = NULL; -+void (*set_codec_some_func)(void) = NULL; -+void (*clear_codec_record)(void) = NULL; -+void (*clear_codec_replay)(void) = NULL; -+void (*set_replay_hp_or_speaker)(void) = NULL; -+void (*set_codec_direct_mode)(void) = NULL; -+void (*clear_codec_direct_mode)(void) = NULL; -+ -+static int jz_audio_rate; -+static int jz_audio_format; -+static int jz_audio_volume; -+static int jz_audio_channels; -+static int jz_audio_b; /* bits expand multiple */ -+static int jz_audio_fragments; /* unused fragment amount */ -+static int jz_audio_fragstotal; -+static int jz_audio_fragsize; -+static int jz_audio_speed; -+ -+static int codec_bass_gain; -+static int audio_mix_modcnt; -+static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -+static int jz_mic_only = 1; -+static int jz_codec_config = 0; -+static unsigned long ramp_up_start; -+static unsigned long ramp_up_end; -+static unsigned long gain_up_start; -+static unsigned long gain_up_end; -+static unsigned long ramp_down_start; -+static unsigned long ramp_down_end; -+static unsigned long gain_down_start; -+static unsigned long gain_down_end; -+ -+static int codec_mic_gain; -+static int pop_dma_flag; -+static int last_dma_buffer_id; -+static int drain_flag; -+ -+static void (*old_mksound)(unsigned int hz, unsigned int ticks); -+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -+static void jz_update_filler(int bits, int channels); -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize); -+static int Free_In_Out_queue(int fragstotal,int fragsize); -+static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -+static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -+static void (*replay_filler)(signed long src_start, int count, int id); -+static int (*record_filler)(unsigned long dst_start, int count, int id); -+#if defined(CONFIG_I2S_ICODEC) -+static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -+#endif -+static void jz_audio_reset(void); -+static struct file_operations jz_i2s_audio_fops; -+ -+static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -+ -+struct jz_i2s_controller_info -+{ -+ int io_base; -+ int dma1; /* for play */ -+ int dma2; /* for record */ -+ char *name; -+ int dev_audio; -+ struct i2s_codec *i2s_codec[NR_I2S]; -+ int opened1; -+ int opened2; -+ unsigned char *tmp1; /* tmp buffer for sample conversions */ -+ unsigned char *tmp2; -+ spinlock_t lock; -+ spinlock_t ioctllock; -+ -+ wait_queue_head_t dac_wait; -+ wait_queue_head_t adc_wait; -+ int nextIn; /* byte index to next-in to DMA buffer */ -+ int nextOut; /* byte index to next-out from DMA buffer */ -+ int count; /* current byte count in DMA buffer */ -+ int finish; /* current transfered byte count in DMA buffer */ -+ unsigned total_bytes; /* total bytes written or read */ -+ unsigned blocks; -+ unsigned error; /* over/underrun */ -+#ifdef CONFIG_PM -+ struct pm_dev *pm; -+#endif -+}; -+ -+ -+static struct jz_i2s_controller_info *i2s_controller = NULL; -+struct i2s_codec -+{ -+ /* I2S controller connected with */ -+ void *private_data; -+ char *name; -+ int id; -+ int dev_mixer; -+ /* controller specific lower leverl i2s accessing routines */ -+ u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ -+ void (*codec_write) (u8 reg, u16 val); -+ /* Wait for codec-ready */ -+ void (*codec_wait) (struct i2s_codec *codec); -+ /* OSS mixer masks */ -+ int modcnt; -+ int supported_mixers; -+ int stereo_mixers; -+ int record_sources; -+ int bit_resolution; -+ /* OSS mixer interface */ -+ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -+ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -+ unsigned int left, unsigned int right); -+ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -+ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -+ /* saved OSS mixer states */ -+ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -+}; -+ -+ -+typedef struct buffer_queue_s -+{ -+ int count; -+ int *id; -+ int lock; -+} buffer_queue_t; -+ -+typedef struct left_right_sample_s -+{ -+ signed long left; -+ signed long right; -+} left_right_sample_t; -+ -+static unsigned long pop_turn_onoff_buf; -+static unsigned long pop_turn_onoff_pbuf; -+ -+static unsigned long *out_dma_buf = NULL; -+static unsigned long *out_dma_pbuf = NULL; -+static unsigned long *out_dma_buf_data_count = NULL; -+static unsigned long *in_dma_buf = NULL; -+static unsigned long *in_dma_pbuf = NULL; -+static unsigned long *in_dma_buf_data_count = NULL; -+ -+static buffer_queue_t out_empty_queue; -+static buffer_queue_t out_full_queue; -+static buffer_queue_t out_busy_queue; -+static buffer_queue_t in_empty_queue; -+static buffer_queue_t in_full_queue; -+static buffer_queue_t in_busy_queue; -+static int first_record_call = 0; -+ -+static left_right_sample_t save_last_samples[64]; -+static int read_codec_file(int addr) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ return(__icdc_get_value()); -+} -+ -+static void printk_codec_files(void) -+{ -+ int cnt; -+ -+ printk("\n"); -+ -+ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -+ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -+ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -+ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -+ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -+ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -+ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -+ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -+ -+ for (cnt = 0; cnt <= 27 ; cnt++) { -+ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -+ } -+ printk("\n"); -+} -+ -+static void write_codec_file(int addr, int val) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+} -+ -+static int write_codec_file_bit(int addr, int bitval, int mask_bit) -+{ -+ int val; -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ val = __icdc_get_value(); /* read */ -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val &= ~(1 << mask_bit); -+ if (bitval == 1) -+ val |= 1 << mask_bit; -+ -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val = __icdc_get_value(); /* read */ -+ -+ if (((val >> mask_bit) & bitval) == bitval) -+ return 1; -+ else -+ return 0; -+} -+ -+/* set Audio data replay */ -+static void set_audio_data_replay() -+{ -+ /* DAC path */ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ //mdelay(100); -+ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //mdelay(300); -+} -+ -+/* unset Audio data replay */ -+static void unset_audio_data_replay(void) -+{ -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //mdelay(800); -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ //mdelay(800); -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record MIC input audio without playback */ -+static void set_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2); -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ -+ write_codec_file(22, 0x40);//mic 1 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ //write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+ -+/* unset Record MIC input audio without playback */ -+static void unset_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record LINE input audio without playback */ -+static void set_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ mdelay(10); -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+ -+/* unset Record LINE input audio without playback */ -+static void unset_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -+ -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Playback LINE input audio direct only */ -+static void set_playback_line_input_audio_direct_only() -+{ -+ jz_audio_reset();//or init_codec() -+ REG_AIC_I2SCR = 0x10; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -+ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -+} -+ -+/* unset Playback LINE input audio direct only */ -+static void unset_playback_line_input_audio_direct_only() -+{ -+ write_codec_file_bit(6, 0, 3);//GIM->0 -+ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ mdelay(100); -+ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record MIC input audio with direct playback */ -+static void set_record_mic_input_audio_with_direct_playback(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ jz_mic_only = 0; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ -+ write_codec_file(22, 0x60);//mic 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file(1, 0x4); -+} -+ -+/* unset Record MIC input audio with direct playback */ -+static void unset_record_mic_input_audio_with_direct_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record playing audio mixed with MIC input audio */ -+static void set_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ -+ write_codec_file(22, 0x63);//mic 1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -+} -+ -+/* unset Record playing audio mixed with MIC input audio */ -+static void unset_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+/* set Record MIC input audio with Audio data replay (full duplex) */ -+static void set_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+ -+/* unset Record MIC input audio with Audio data replay (full duplex) */ -+static void unset_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+ -+///////// -+/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -+static void set_record_line_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ -+ -+ //jz_mic_only = 1; -+ write_codec_file(22, 0xc6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+ -+/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -+static void unset_record_line_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+///////// -+static inline int get_buffer_id(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ if (q->count == 0) { -+ spin_unlock_irqrestore(&q->lock, flags); -+ return -1; -+ } -+ r = *(q->id + 0); -+ for (i=0;i < q->count-1;i++) -+ *(q->id + i) = *(q->id + (i+1)); -+ q->count --; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void put_buffer_id(struct buffer_queue_s *q, int id) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ *(q->id + q->count) = id; -+ q->count ++; -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+ -+static inline int elements_in_queue(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ r = q->count; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -+{ -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_dma_tran_count = count / jz_audio_b; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ //set_dma_mode(chan, mode); -+ jz_set_oss_dma(chan, mode, jz_audio_format); -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) { -+ count++; -+ printk("JzSOC DMA controller can't set dma 0 count!\n"); -+ } -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ release_dma_lock(flags); -+} -+ -+static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -+{ -+ int id1, id2; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma2; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ if(drain_flag == 1) -+ wake_up(&drain_wait_queue); -+ /* for DSP_GETIPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id2); -+ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -+ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -+ audio_start_dma(dma,dev_id, -+ *(in_dma_pbuf + id2), -+ *(in_dma_buf_data_count + id2), -+ DMA_MODE_READ); -+ } else -+ in_busy_queue.count = 0; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -+{ -+ int id; -+ unsigned long flags; -+ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -+ int dma = controller->dma1; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ -+ if(pop_dma_flag == 1) { -+ pop_dma_flag = 0; -+ wake_up(&pop_wait_queue); -+ } else { -+ if(drain_flag == 1) { -+ /* Is replay dma buffer over ? */ -+ if(elements_in_queue(&out_full_queue) <= 0) { -+ drain_flag = 0; -+ wake_up(&drain_wait_queue); -+ } -+ } -+ -+ /* for DSP_GETOPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if ((id = get_buffer_id(&out_busy_queue)) < 0) -+ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -+ put_buffer_id(&out_empty_queue, id); -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ last_dma_buffer_id = id; -+ } -+ } else -+ out_busy_queue.count = 0; -+ -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void jz_i2s_initHw(int set) -+{ -+#if defined(CONFIG_MIPS_JZ_URANUS) -+ i2s_clk = 48000000; -+#else -+ i2s_clk = __cpm_get_i2sclk(); -+#endif -+ __i2s_disable(); -+ if(set) -+ __i2s_reset(); -+ schedule_timeout(5); -+ if(each_time_init_codec) -+ each_time_init_codec(); -+ __i2s_disable_record(); -+ __i2s_disable_replay(); -+ __i2s_disable_loopback(); -+ __i2s_set_transmit_trigger(4); -+ __i2s_set_receive_trigger(3); -+} -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ -+ /* recording */ -+ in_empty_queue.count = fragstotal; -+ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf) -+ goto all_mem_err; -+ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_pbuf) -+ goto all_mem_err; -+ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf_data_count) -+ goto all_mem_err; -+ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_empty_queue.id) -+ goto all_mem_err; -+ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_full_queue.id) -+ goto all_mem_err; -+ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_busy_queue.id) -+ goto all_mem_err; -+ -+ for (i=0;i < fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ for (i = 0; i < fragstotal; i++) { -+ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(in_dma_buf + i) == 0) -+ goto mem_failed_in; -+ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ } -+ -+ /* playing */ -+ out_empty_queue.count = fragstotal; -+ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf) -+ goto all_mem_err; -+ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_pbuf) -+ goto all_mem_err; -+ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ -+ if (!out_dma_buf_data_count) -+ goto all_mem_err; -+ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_empty_queue.id) -+ goto all_mem_err; -+ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_full_queue.id) -+ goto all_mem_err; -+ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_busy_queue.id) -+ goto all_mem_err; -+ for (i=0;i < fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /* alloc DMA buffer */ -+ for (i = 0; i < fragstotal; i++) { -+ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(out_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(OUT) buffers.\n"); -+ goto mem_failed_out; -+ } -+ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -+ } -+ -+ return 1; -+all_mem_err: -+ printk("error:allocate memory occur error 1!\n"); -+ return 0; -+mem_failed_out: -+ printk("error:allocate memory occur error 2!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ } -+ -+ return 0; -+mem_failed_in: -+ printk("error:allocate memory occur error 3!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ return 0; -+} -+ -+static int Free_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ /* playing */ -+ if(out_dma_buf != NULL) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ *(out_dma_buf + i) = 0; -+ } -+ kfree(out_dma_buf); -+ out_dma_buf = NULL; -+ } -+ if(out_dma_pbuf) { -+ kfree(out_dma_pbuf); -+ out_dma_pbuf = NULL; -+ } -+ if(out_dma_buf_data_count) { -+ kfree(out_dma_buf_data_count); -+ out_dma_buf_data_count = NULL; -+ } -+ if(out_empty_queue.id) { -+ kfree(out_empty_queue.id); -+ out_empty_queue.id = NULL; -+ } -+ if(out_full_queue.id) { -+ kfree(out_full_queue.id); -+ out_full_queue.id = NULL; -+ } -+ if(out_busy_queue.id) { -+ kfree(out_busy_queue.id); -+ out_busy_queue.id = NULL; -+ } -+ out_empty_queue.count = fragstotal; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ -+ /* recording */ -+ if(in_dma_buf) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) { -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ *(in_dma_buf + i) = 0; -+ } -+ kfree(in_dma_buf); -+ in_dma_buf = NULL; -+ } -+ if(in_dma_pbuf) { -+ kfree(in_dma_pbuf); -+ in_dma_pbuf = NULL; -+ } -+ if(in_dma_buf_data_count) { -+ kfree(in_dma_buf_data_count); -+ in_dma_buf_data_count = NULL; -+ } -+ if(in_empty_queue.id) { -+ kfree(in_empty_queue.id); -+ in_empty_queue.id = NULL; -+ } -+ if(in_full_queue.id) { -+ kfree(in_full_queue.id); -+ in_full_queue.id = NULL; -+ } -+ if(in_busy_queue.id) { -+ kfree(in_busy_queue.id); -+ in_busy_queue.id = NULL; -+ } -+ -+ in_empty_queue.count = fragstotal; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ return 1; -+} -+ -+static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -+{ -+ jz_i2s_initHw(0); -+} -+ -+static int jz_audio_set_speed(int dev, int rate) -+{ -+ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -+ jz_audio_speed = rate; -+ if (rate > 48000) -+ rate = 48000; -+ if (rate < 8000) -+ rate = 8000; -+ jz_audio_rate = rate; -+ -+ if(set_codec_speed) -+ set_codec_speed(rate); -+ -+ return jz_audio_rate; -+} -+ -+ -+static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long data; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt++; -+ data = *(s++); -+ *(dp ++) = ((data << 16) >> 24) + 0x80; -+ s++; /* skip the other channel */ -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -+ d2 = *(s++); -+ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 2; /* count in byte */ -+ d1 = *(s++); -+ *(dp ++) = (d1 << 16) >> 16; -+ s++; /* skip the other channel */ -+ } -+ -+ return cnt; -+} -+ -+ -+static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned long d1, d2; -+ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ while (count > 0) { -+ count -= 2; /* count in dword */ -+ cnt += 4; /* count in byte */ -+ d1 = *(s++); -+ d2 = *(s++); -+ if(abnormal_data_count > 0) { -+ d1 = d2 = 0; -+ abnormal_data_count --; -+ } -+ *(dp ++) = (d1 << 16) >> 16; -+ *(dp ++) = (d2 << 16) >> 16; -+ } -+ -+ return cnt; -+} -+ -+static void replay_fill_1x8_u(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char data; -+ unsigned long ddata; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count--; -+ cnt += 1; -+ data = *(s++) - 0x80; -+ ddata = (unsigned long) data << 8; -+ *(dp ++) = ddata; -+ *(dp ++) = ddata; -+ -+ /* save last left and right */ -+ if(count == 1) { -+ save_last_samples[id].left = ddata; -+ save_last_samples[id].right = ddata; -+ } -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+ -+static void replay_fill_2x8_u(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned char d1; -+ unsigned long dd1; -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 1; -+ cnt += 1 ; -+ d1 = *(s++) - 0x80; -+ dd1 = (unsigned long) d1 << 8; -+ *(dp ++) = dd1; -+ /* save last left */ -+ if(count == 2) -+ save_last_samples[id].left = dd1; -+ /* save last right */ -+ if(count == 1) -+ save_last_samples[id].right = dd1; -+ } -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+ -+static void replay_fill_1x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ count -= 2; -+ cnt += 2 ; -+ d1 = *(s++); -+ l1 = (signed long)d1; -+ *(dp ++) = l1; -+ *(dp ++) = l1; -+ -+ /* save last left and right */ -+ if(count == 1) { -+ save_last_samples[id].left = l1; -+ save_last_samples[id].right = l1; -+ } -+ } -+ cnt = cnt * 2 * jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+#if 0 -+static void replay_fill_2x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ int mute_cnt = 0; -+ signed long tmp1,tmp2; -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+#if defined(CONFIG_I2S_ICDC) -+ volatile signed long *before_dp; -+ int sam_rate = jz_audio_rate / 20; -+ -+ tmp1 = tmp2 = 0; -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ l1 >>= codec_volue_shift; -+ -+ if(l1 == 0) { -+ mute_cnt ++; -+ if(mute_cnt >= sam_rate) { -+ before_dp = dp - 10; -+ *(before_dp) = (signed long)1; -+ before_dp = dp - 11; -+ *(before_dp) = (signed long)1; -+ mute_cnt = 0; -+ } -+ } else -+ mute_cnt = 0; -+ -+ *(dp ++) = l1; -+ -+ tmp1 = tmp2; -+ tmp2 = l1; -+ } -+ -+ /* save last left */ -+ save_last_samples[id].left = tmp1; -+ /* save last right */ -+ save_last_samples[id].right = tmp2; -+#endif -+#if defined(CONFIG_I2S_DLV) -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ -+ *(dp ++) = l1; -+ } -+#endif -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+} -+#else -+static void replay_fill_2x16_s(signed long src_start, int count, int id) -+{ -+ int cnt = 0; -+ signed short d1; -+ signed long l1; -+ int mute_cnt = 0; -+ signed long tmp1,tmp2; -+ -+#if 0 -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed short *dp = (signed short*)(*(out_dma_buf + id)); -+ memcpy((char*)dp, (char*)s, count); -+ *(out_dma_buf_data_count + id) = count; -+#else -+ volatile signed short *s = (signed short *)src_start; -+ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -+ while (count > 0) { -+ count -= 2; -+ cnt += 2; -+ d1 = *(s++); -+ -+ l1 = (signed long)d1; -+ -+ *(dp ++) = l1; -+ } -+ cnt *= jz_audio_b; -+ *(out_dma_buf_data_count + id) = cnt; -+#endif -+} -+#endif -+ -+ -+static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -+{ -+ switch (fmt) { -+ case AFMT_U8: -+ __i2s_set_oss_sample_size(8); -+ __i2s_set_iss_sample_size(8); -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ break; -+ case AFMT_S16_LE: -+#if defined(CONFIG_I2S_DLV) -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x00); -+ //write_codec_file(2, 0x60); -+#endif -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format,jz_audio_channels); -+ /* print all files */ -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ break; -+ -+ case AFMT_QUERY: -+ break; -+ } -+ -+ return jz_audio_format; -+} -+ -+ -+static short jz_audio_set_channels(int dev, short channels) -+{ -+ switch (channels) { -+ case 1: -+ if(set_codec_some_func) -+ set_codec_some_func(); -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -+#endif -+ break; -+ case 2: -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -+#endif -+ break; -+ case 0: -+ break; -+ } -+ -+ return jz_audio_channels; -+} -+ -+static void init_codec(void) -+{ -+ /* inititalize internal I2S codec */ -+ if(init_codec_pin) -+ init_codec_pin(); -+ -+#if defined(CONFIG_I2S_ICDC) -+ /* initialize AIC but not reset it */ -+ jz_i2s_initHw(0); -+#endif -+ if(reset_codec) -+ reset_codec(); -+} -+ -+static void jz_audio_reset(void) -+{ -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+#if defined(CONFIG_I2S_DLV) -+ REG_AIC_I2SCR = 0x10; -+#endif -+ init_codec(); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file); -+static int jz_audio_open(struct inode *inode, struct file *file); -+static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -+static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -+static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -+ -+/* static struct file_operations jz_i2s_audio_fops */ -+static struct file_operations jz_i2s_audio_fops = -+{ -+ owner: THIS_MODULE, -+ open: jz_audio_open, -+ release: jz_audio_release, -+ write: jz_audio_write, -+ read: jz_audio_read, -+ poll: jz_audio_poll, -+ ioctl: jz_audio_ioctl -+}; -+ -+static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -+{ -+ int i; -+ int minor = MINOR(inode->i_rdev); -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ -+ for (i = 0; i < NR_I2S; i++) -+ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -+ goto match; -+ -+ if (!controller) -+ return -ENODEV; -+match: -+ file->private_data = controller->i2s_codec[i]; -+ -+ return 0; -+} -+ -+static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -+ return codec->mixer_ioctl(codec, cmd, arg); -+} -+ -+static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -+{ -+ return -ESPIPE; -+} -+ -+static struct file_operations jz_i2s_mixer_fops = -+{ -+ owner: THIS_MODULE, -+ llseek: jz_i2s_llseek, -+ ioctl: jz_i2s_ioctl_mixdev, -+ open: jz_i2s_open_mixdev, -+}; -+ -+static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ long val = 0; -+ switch (cmd) { -+ case SOUND_MIXER_INFO: -+ -+ if(codec_mixer_info_id_name) -+ codec_mixer_info_id_name(); -+ info.modify_counter = audio_mix_modcnt; -+ -+ return copy_to_user((void *)arg, &info, sizeof(info)); -+ case SOUND_OLD_MIXER_INFO: -+ -+ if(codec_mixer_old_info_id_name) -+ codec_mixer_old_info_id_name(); -+ -+ return copy_to_user((void *)arg, &old_info, sizeof(info)); -+ case SOUND_MIXER_READ_STEREODEVS: -+ -+ return put_user(0, (long *) arg); -+ case SOUND_MIXER_READ_CAPS: -+ -+ val = SOUND_CAP_EXCL_INPUT; -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_READ_DEVMASK: -+ break; -+ case SOUND_MIXER_READ_RECMASK: -+ break; -+ case SOUND_MIXER_READ_RECSRC: -+ break; -+ case SOUND_MIXER_WRITE_SPEAKER: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ switch(val) { -+ case 100: -+ if(set_codec_direct_mode) -+ set_codec_direct_mode(); -+ break; -+ case 0: -+ if(clear_codec_direct_mode) -+ clear_codec_direct_mode(); -+ break; -+ } -+ break; -+ case SOUND_MIXER_WRITE_BASS: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ codec_bass_gain = val; -+ if(set_codec_bass) -+ set_codec_bass(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_BASS: -+ -+ val = codec_bass_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_VOLUME: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ if (val > 31) -+ val = 31; -+ jz_audio_volume = val; -+ -+ if(set_codec_volume) -+ set_codec_volume(val); -+ return 0; -+ case SOUND_MIXER_READ_VOLUME: -+ -+ val = jz_audio_volume; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_MIC: -+ -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ codec_mic_gain = val; -+ if(set_codec_mic) -+ set_codec_mic(val); -+ -+ return 0; -+ case SOUND_MIXER_READ_MIC: -+ -+ val = codec_mic_gain; -+ ret = val << 8; -+ val = val | ret; -+ -+ return put_user(val, (long *) arg); -+ default: -+ return -ENOSYS; -+ } -+ audio_mix_modcnt ++; -+ return 0; -+} -+ -+ -+int i2s_probe_codec(struct i2s_codec *codec) -+{ -+ /* generic OSS to I2S wrapper */ -+ codec->mixer_ioctl = i2s_mixer_ioctl; -+ return 1; -+} -+ -+ -+/* I2S codec initialisation. */ -+static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -+{ -+ int num_i2s = 0; -+ struct i2s_codec *codec; -+ -+ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -+ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ memset(codec, 0, sizeof(struct i2s_codec)); -+ codec->private_data = controller; -+ codec->id = num_i2s; -+ -+ if (i2s_probe_codec(codec) == 0) -+ break; -+ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -+ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -+ kfree(codec); -+ break; -+ } -+ controller->i2s_codec[num_i2s] = codec; -+ } -+ return num_i2s; -+} -+ -+ -+static void jz_update_filler(int format, int channels) -+{ -+#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -+ -+ switch (TYPE(format, channels)) -+ { -+ -+ case TYPE(AFMT_U8, 1): -+ jz_audio_b = 4; /* 4bytes * 8bits =32bits */ -+ replay_filler = replay_fill_1x8_u; -+ record_filler = record_fill_1x8_u; -+ break; -+ case TYPE(AFMT_U8, 2): -+ jz_audio_b = 4; -+ replay_filler = replay_fill_2x8_u; -+ record_filler = record_fill_2x8_u; -+ break; -+ case TYPE(AFMT_S16_LE, 1): -+ jz_audio_b = 2; /* 2bytes * 16bits =32bits */ -+ replay_filler = replay_fill_1x16_s; -+ record_filler = record_fill_1x16_s; -+ break; -+ case TYPE(AFMT_S16_LE, 2): -+ jz_audio_b = 2; -+ replay_filler = replay_fill_2x16_s; -+ record_filler = record_fill_2x16_s; -+ break; -+ default: -+ ; -+ } -+} -+ -+ -+#ifdef CONFIG_PROC_FS -+extern struct proc_dir_entry *proc_jz_root; -+int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ return 0; -+} -+ -+static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -+{ -+ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -+ return -EIO; -+ return 0; -+} -+ -+static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -+{ -+} -+#endif -+ -+static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ char *name; -+ int adev; /* No of Audio device. */ -+ -+ name = controller->name; -+ /* initialize AIC controller and reset it */ -+ jz_i2s_initHw(1); -+ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -+ if (adev < 0) -+ goto audio_failed; -+ /* initialize I2S codec and register /dev/mixer */ -+ if (jz_i2s_codec_init(controller) <= 0) -+ goto mixer_failed; -+ -+#ifdef CONFIG_PROC_FS -+ if (jz_i2s_init_proc(controller) < 0) { -+ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -+ goto proc_failed; -+ } -+#endif -+ -+ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); -+ if (!controller->tmp1) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp1_failed; -+ } -+ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); -+ if (!controller->tmp2) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp2_failed; -+ } -+ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -+ goto dma2_failed; -+ } -+ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -+ goto dma1_failed; -+ } -+ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -+ -+ controller->dev_audio = adev; -+ pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); -+ if(!pop_turn_onoff_buf) -+ printk("pop_turn_onoff_buf alloc is wrong!\n"); -+ pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); -+ -+ return; -+dma2_failed: -+ jz_free_dma(controller->dma1); -+dma1_failed: -+ free_pages((unsigned long)controller->tmp2, 8); -+tmp2_failed: -+ free_pages((unsigned long)controller->tmp1, 8); -+tmp1_failed: -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+proc_failed: -+ /* unregister mixer dev */ -+mixer_failed: -+ unregister_sound_dsp(adev); -+audio_failed: -+ return; -+} -+ -+static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -+{ -+ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -+ return -ENOMEM; -+ } -+ (*controller)->name = "Jz I2S controller"; -+ (*controller)->opened1 = 0; -+ (*controller)->opened2 = 0; -+ init_waitqueue_head(&(*controller)->adc_wait); -+ init_waitqueue_head(&(*controller)->dac_wait); -+ spin_lock_init(&(*controller)->lock); -+ init_waitqueue_head(&rx_wait_queue); -+ init_waitqueue_head(&tx_wait_queue); -+ init_waitqueue_head(&pop_wait_queue); -+ init_waitqueue_head(&drain_wait_queue); -+ -+ return 0; -+} -+ -+static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -+{ -+ int adev = controller->dev_audio; -+ -+ jz_i2s_full_reset(controller); -+ controller->dev_audio = -1; -+ if (old_mksound) -+ kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ -+ -+#ifdef CONFIG_PROC_FS -+ jz_i2s_cleanup_proc(controller); -+#endif -+ -+ jz_free_dma(controller->dma1); -+ jz_free_dma(controller->dma2); -+ free_pages((unsigned long)controller->tmp1, 8); -+ free_pages((unsigned long)controller->tmp2, 8); -+ free_pages((unsigned long)pop_turn_onoff_buf, 8); -+ -+ if (adev >= 0) { -+ /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ -+ unregister_sound_dsp(controller->dev_audio); -+ } -+} -+ -+#ifdef CONFIG_PM -+static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -+{ -+ if(i2s_suspend_codec) -+ i2s_suspend_codec(controller->opened1,controller->opened2); -+ printk("Aic and codec are suspended!\n"); -+ return 0; -+} -+ -+static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -+{ -+ if(i2s_resume_codec) -+ i2s_resume_codec(); -+ -+#if defined(CONFIG_I2S_AK4642EN) -+ jz_i2s_initHw(0); -+ jz_audio_reset(); -+ __i2s_enable(); -+ jz_audio_set_speed(controller->dev_audio,jz_audio_speed); -+ /* playing */ -+ if(controller->opened1) { -+ if(set_codec_replay) -+ set_codec_replay(); -+ int dma = controller->dma1; -+ int id; -+ unsigned long flags; -+ disable_dma(dma); -+ if(__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if(__dmac_channel_transmit_end_detected(dma)) -+ __dmac_channel_clear_transmit_end(dma); -+ -+ /* for DSP_GETOPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ while((id = get_buffer_id(&out_busy_queue)) >= 0) -+ put_buffer_id(&out_empty_queue, id); -+ -+ out_busy_queue.count=0; -+ if((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_empty_queue, id); -+ } -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } else -+ printk("pm out_empty_queue empty"); -+ } -+ -+ /* recording */ -+ if(controller->opened2) { -+ if(set_codec_record) -+ set_codec_record(); -+ int dma = controller->dma2; -+ int id1, id2; -+ unsigned long flags; -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ } -+ /* for DSP_GETIPTR */ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_full_queue, id2); -+ } -+ in_busy_queue.count = 0; -+ } -+#endif -+ -+ return 0; -+} -+ -+static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -+{ -+ int ret; -+ struct jz_i2s_controller_info *controller = pm_dev->data; -+ -+ if (!controller) return -EINVAL; -+ -+ switch (req) { -+ case PM_SUSPEND: -+ ret = jz_i2s_suspend(controller, (int)data); -+ break; -+ case PM_RESUME: -+ ret = jz_i2s_resume(controller); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+#endif /* CONFIG_PM */ -+static irqreturn_t aic_codec_irq(int irq, void *dev_id) -+{ -+ u8 file_9 = read_codec_file(9); -+ u8 file_8 = read_codec_file(8); -+ -+ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -+ if ((file_9 & 0x1f) == 0x10) { -+ -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x4) != 0x4); -+ while ((read_codec_file(9) & 0x10) == 0x10) { -+ write_codec_file(9, 0x10); -+ } -+ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x8) != 0x8); -+ write_codec_file(9, file_9); -+ write_codec_file(8, file_8); -+ -+ return IRQ_HANDLED; -+ } -+ -+ if (file_9 & 0x8) -+ ramp_up_end = jiffies; -+ else if (file_9 & 0x4) -+ ramp_down_end = jiffies; -+ else if (file_9 & 0x2) -+ gain_up_end = jiffies; -+ else if (file_9 & 0x1) -+ gain_down_end = jiffies; -+ -+ write_codec_file(9, file_9); -+ if (file_9 & 0xf) -+ wake_up(&pop_wait_queue); -+ while (REG_ICDC_RGDATA & 0x100); -+ -+ return IRQ_HANDLED; -+} -+ -+static int __init init_jz_i2s(void) -+{ -+ int errno, retval; -+#if defined(CONFIG_I2S_DLV) -+ -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+#endif -+ -+ abnormal_data_count = 0; -+ if(set_codec_mode) -+ set_codec_mode(); -+ -+ drain_flag = 0; -+ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -+ return errno; -+ if(set_codec_gpio_pin) -+ set_codec_gpio_pin(); -+ -+ attach_jz_i2s(i2s_controller); -+ if(set_codec_startup_param) -+ set_codec_startup_param(); -+#if defined(CONFIG_I2S_DLV) -+ jz_codec_config = 0; -+ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -+ if (retval) { -+ printk("Could not get aic codec irq %d\n", IRQ_AIC); -+ return retval; -+ } -+#endif -+ if(set_codec_volume_table) -+ set_codec_volume_table(); -+ -+ out_empty_queue.id = NULL; -+ out_full_queue.id = NULL; -+ out_busy_queue.id = NULL; -+ in_empty_queue.id = NULL; -+ in_full_queue.id = NULL; -+ in_busy_queue.id = NULL; -+ -+ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -+ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+#ifdef CONFIG_PM -+ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -+ jz_i2s_pm_callback); -+ if (i2s_controller->pm) -+ i2s_controller->pm->data = i2s_controller; -+#endif -+ -+#if defined(CONFIG_I2S_DLV) -+ __cpm_start_idct(); -+ __cpm_start_db(); -+ __cpm_start_me(); -+ __cpm_start_mc(); -+ __cpm_start_ipu(); -+#endif -+ -+ printk("JZ I2S OSS audio driver initialized\n"); -+ -+ return 0; -+} -+ -+static void __exit cleanup_jz_i2s(void) -+{ -+#ifdef CONFIG_PM -+ /* pm_unregister(i2s_controller->pm); */ -+#endif -+#if defined(CONFIG_I2S_DLV) -+ free_irq(IRQ_AIC, NULL); -+#endif -+ unload_jz_i2s(i2s_controller); -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ if(clear_codec_mode) -+ clear_codec_mode(); -+} -+ -+module_init(init_jz_i2s); -+module_exit(cleanup_jz_i2s); -+ -+#if defined(CONFIG_SOC_JZ4730) -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,con; -+ -+ if(elements_in_queue(&in_busy_queue) > 0) { -+ if (nonblock) -+ return -EBUSY; -+ drain_flag = 1; -+ sleep_on(&drain_wait_queue); -+ drain_flag = 0; -+ } else { -+ add_wait_queue(&ctrl->adc_wait, &wait); -+ for (con = 0; con < 1000; con ++) { -+ udelay(1); -+ set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ if (nonblock) { -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ remove_wait_queue(&ctrl->adc_wait, &wait); -+ current->state = TASK_RUNNING; -+ } -+ return 0; -+} -+ -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count; -+ -+ if(elements_in_queue(&out_full_queue) > 0) { -+ if (nonblock) -+ return -EBUSY; -+ -+ drain_flag = 1; -+ sleep_on(&drain_wait_queue); -+ drain_flag = 0; -+ } else { -+ add_wait_queue(&(ctrl->dac_wait), &wait); -+ for (;;) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ if(elements_in_queue(&out_full_queue) <= 0) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if(count <= 0) -+ break; -+ } -+ if (nonblock) { -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ remove_wait_queue(&ctrl->dac_wait, &wait); -+ current->state = TASK_RUNNING; -+ } -+ -+ return 0; -+} -+#endif -+ -+#if defined(CONFIG_SOC_JZ4750) -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ //DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int count,i=0; -+ -+ //add_wait_queue(&ctrl->adc_wait, &wait); -+ for (;;) { -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ //set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ //spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ //spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ /*if (signal_pending(current)) -+ break;*/ -+ if (nonblock) { -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ return -EBUSY; -+ } -+ } -+ //remove_wait_queue(&ctrl->adc_wait, &wait); -+ //current->state = TASK_RUNNING; -+ /*if (signal_pending(current)) -+ return -ERESTARTSYS;*/ -+ return 0; -+} -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ unsigned long flags; -+ int count,ele,busyele,emptyele,i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if (i < MAXDELAY) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(200); -+ -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } else {//non-blocked -+ //mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ //mdelay(100); -+ busyele = elements_in_queue(&out_busy_queue); -+ emptyele = elements_in_queue(&out_empty_queue); -+ -+ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+#if defined(CONFIG_SOC_JZ4740) -+#define MAXDELAY 50000 -+static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ int count,ele,i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if ( i < MAXDELAY ) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(10); -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ } -+ } else {//non-blocked -+ mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ mdelay(100); -+ -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -+{ -+ int count,i=0; -+ -+ for (;;) { -+ if ( i < MAXDELAY ) -+ { -+ udelay(10); -+ i++; -+ } -+ else -+ break; -+ spin_lock(&ctrl->lock); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock(&ctrl->lock); -+ if (count <= 0) -+ break; -+ -+ if (nonblock) { -+ return -EBUSY; -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+static int jz_audio_release(struct inode *inode, struct file *file) -+{ -+ unsigned long flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long tfl; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ pop_dma_flag = 0; -+ if (controller->opened1 == 1) { -+ controller->opened1 = 0; -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ /* add some mute to anti-pop */ -+#if defined(CONFIG_I2S_DLV) -+ /* wait for fifo empty */ -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ gain_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_down_end = jiffies; -+ while (1) { -+ tfl = REG_AIC_SR & 0x00003f00; -+ if (tfl == 0) { -+ udelay(500); -+ break; -+ } -+ mdelay(2); -+ } -+#endif -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable_replay(); -+ __aic_flush_fifo(); -+ if(clear_codec_replay) -+ clear_codec_replay(); -+ __aic_flush_fifo(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ ramp_down_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //ramp_down_end = jiffies; -+ unset_audio_data_replay(); -+#endif -+ __i2s_disable(); -+ if(turn_off_codec) -+ turn_off_codec(); -+ } -+ -+ if (controller->opened2 == 1) { -+ controller->opened2 = 0; -+ first_record_call = 1; -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ -+ if(clear_codec_record) -+ clear_codec_record(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ __i2s_disable(); -+ if(turn_off_codec) -+ turn_off_codec(); -+ abnormal_data_count = 0; -+ } -+ -+#if defined(CONFIG_I2S_DLV) -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+#endif -+ return 0; -+} -+ -+static int jz_audio_open(struct inode *inode, struct file *file) -+{ -+ int i; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ mdelay(2); -+ REG_DMAC_DMACKE(0) = 0x3f; -+ pop_dma_flag = 0; -+ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -+ printk("\naudio is busy!\n"); -+ return -EBUSY; -+ } -+ jz_codec_config = 0; -+ -+ ramp_up_start = 0; -+ ramp_up_end = 0; -+ gain_up_start = 0; -+ gain_up_end = 0; -+ ramp_down_start = 0; -+ ramp_down_end = 0; -+ gain_down_start = 0; -+ gain_down_end = 0; -+ if (file->f_mode & FMODE_WRITE) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ -+ controller->opened1 = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ for(i=0;i < 64;i++) { -+ save_last_samples[i].left = 0; -+ save_last_samples[i].right = 0; -+ } -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ last_dma_buffer_id = 0; -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ -+ controller->opened2 = 1; -+ first_record_call = 1; -+ /* for ioctl */ -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ } -+ -+ file->private_data = controller; -+ jz_audio_reset(); -+ REG_AIC_FR |= (1 << 6); -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if(set_codec_replay) -+ set_codec_replay(); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ abnormal_data_count = 0; -+ if(set_codec_record) -+ set_codec_record(); -+ } -+ -+#if defined(CONFIG_I2S_DLV) -+ __aic_reset(); -+ -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ __aic_flush_fifo(); -+#endif -+ -+ __i2s_enable(); -+ -+#if defined(CONFIG_I2S_DLV) -+ if (file->f_mode & FMODE_WRITE) { -+ -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ ramp_up_start = jiffies; -+ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RCR = 0x1; -+ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -+ REG_RTC_RGR = 1;*/ -+ sleep_on(&pop_wait_queue); -+ //ramp_up_end = jiffies; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ } else if (file->f_mode & FMODE_READ) { -+ if (jz_mic_only) -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ else -+ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -+ mdelay(500); -+ } -+ -+#endif -+ -+ return 0; -+} -+ -+ -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+unsigned int cmd, unsigned long arg) -+{ -+ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ count_info cinfo; -+ audio_buf_info abinfo; -+ int id, i; -+ -+ val = 0; -+ switch (cmd) { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, (int *)arg); -+ case SNDCTL_DSP_RESET: -+#if 0 -+ jz_audio_reset(); -+ __i2s_disable_replay(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_record(); -+ __i2s_disable_transmit_dma(); -+#endif -+ return 0; -+ case SNDCTL_DSP_SYNC: -+ if (file->f_mode & FMODE_WRITE) -+ return drain_dac(controller, file->f_flags & O_NONBLOCK); -+ return 0; -+ case SNDCTL_DSP_SPEED: -+ /* set smaple rate */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val >= 0) -+ jz_audio_set_speed(controller->dev_audio, val); -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_STEREO: -+ /* set stereo or mono channel */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -+ -+ return 0; -+ case SNDCTL_DSP_GETBLKSIZE: -+ //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); -+ return put_user(jz_audio_fragsize, (int *)arg); -+ case SNDCTL_DSP_GETFMTS: -+ /* Returns a mask of supported sample format*/ -+ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -+ case SNDCTL_DSP_SETFMT: -+ /* Select sample format */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ if (val != AFMT_QUERY) -+ jz_audio_set_format(controller->dev_audio,val); -+ else { -+ if (file->f_mode & FMODE_READ) -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ else -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ } -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ jz_audio_set_channels(controller->dev_audio, val); -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_POST: -+ /* FIXME: the same as RESET ?? */ -+ return 0; -+ case SNDCTL_DSP_SUBDIVIDE: -+ return 0; -+ case SNDCTL_DSP_SETFRAGMENT: -+ get_user(val, (long *) arg); -+ newfragsize = 1 << (val & 0xFFFF); -+ if (newfragsize < 4 * PAGE_SIZE) -+ newfragsize = 4 * PAGE_SIZE; -+ if (newfragsize > (16 * PAGE_SIZE)) -+ newfragsize = 16 * PAGE_SIZE; -+ -+ newfragstotal = (val >> 16) & 0x7FFF; -+ if (newfragstotal < 2) -+ newfragstotal = 2; -+ if (newfragstotal > 32) -+ newfragstotal = 32; -+ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -+ return 0; -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(500); -+ jz_audio_fragstotal = newfragstotal; -+ jz_audio_fragsize = newfragsize; -+ -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(10); -+ -+ return 0; -+ case SNDCTL_DSP_GETCAPS: -+ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -+ case SNDCTL_DSP_NONBLOCK: -+ file->f_flags |= O_NONBLOCK; -+ return 0; -+ case SNDCTL_DSP_SETDUPLEX: -+ return -EINVAL; -+ case SNDCTL_DSP_GETOSPACE: -+ { -+ int i, bytes = 0; -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_fragments = elements_in_queue(&out_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ if (jz_audio_channels == 2) -+ bytes /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ bytes /= 4; -+ else -+ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); -+ -+ -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ /* unused fragment amount */ -+ abinfo.fragments = jz_audio_fragments; -+ /* amount of fragments */ -+ abinfo.fragstotal = jz_audio_fragstotal; -+ /* fragment size in bytes */ -+ if (jz_audio_channels == 2) -+ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -+ else if (jz_audio_channels == 1) -+ abinfo.fragsize = jz_audio_fragsize / 4; -+ else -+ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); -+ -+ /* write size count without blocking in bytes */ -+ abinfo.bytes = bytes; -+ -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETISPACE: -+ { -+ int i, bytes = 0; -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ jz_audio_fragments = elements_in_queue(&in_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ if (jz_audio_channels == 2) -+ bytes /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ bytes /= 4; -+ else -+ printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); -+ -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ -+ if (jz_audio_channels == 2) -+ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -+ else if (jz_audio_channels == 1) -+ abinfo.fragsize = jz_audio_fragsize / 4; -+ else -+ printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); -+ -+ abinfo.bytes = bytes; -+ -+ return copy_to_user((void *)arg, &abinfo, -+ sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETTRIGGER: -+ val = 0; -+ if (file->f_mode & FMODE_READ && in_dma_buf) -+ val |= PCM_ENABLE_INPUT; -+ if (file->f_mode & FMODE_WRITE && out_dma_buf) -+ val |= PCM_ENABLE_OUTPUT; -+ -+ return put_user(val, (int *)arg); -+ case SNDCTL_DSP_SETTRIGGER: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ return 0; -+ case SNDCTL_DSP_GETIPTR: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextIn; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETOPTR: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextOut; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETODELAY: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ unfinish = 0; -+ fullc = elements_in_queue(&out_full_queue); -+ busyc = elements_in_queue(&out_busy_queue); -+ for(i = 0;i < fullc ;i ++) { -+ id = *(out_full_queue.id + i); -+ unfinish += *(out_dma_buf_data_count + id); -+ } -+ for(i = 0;i < busyc ;i ++) { -+ id = *(out_busy_queue.id + i); -+ unfinish += get_dma_residue(controller->dma1); -+ } -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (jz_audio_channels == 2) -+ unfinish /= jz_audio_b; -+ else if (jz_audio_channels == 1) -+ unfinish /= 4; -+ else -+ printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); -+ -+ return put_user(unfinish, (int *) arg); -+ case SOUND_PCM_READ_RATE: -+ return put_user(jz_audio_rate, (int *)arg); -+ case SOUND_PCM_READ_CHANNELS: -+ return put_user(jz_audio_channels, (int *)arg); -+ case SOUND_PCM_READ_BITS: -+ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -+ case SNDCTL_DSP_MAPINBUF: -+ case SNDCTL_DSP_MAPOUTBUF: -+ case SNDCTL_DSP_SETSYNCRO: -+ case SOUND_PCM_WRITE_FILTER: -+ case SOUND_PCM_READ_FILTER: -+ return -EINVAL; -+ } -+ return -EINVAL; -+} -+ -+ -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ unsigned long flags; -+ unsigned int mask = 0; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ return POLLOUT | POLLWRNORM; -+ -+ poll_wait(file, &controller->dac_wait, wait); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ return POLLIN | POLLRDNORM; -+ -+ poll_wait(file, &controller->adc_wait, wait); -+ } -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ mask |= POLLOUT | POLLWRNORM; -+ } else if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ mask |= POLLIN | POLLRDNORM; -+ } -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ return mask; -+} -+ -+static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -+{ -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ int id, ret = 0, left_count, copy_count, cnt = 0; -+ unsigned long flags; -+ -+ if (count < 0) -+ return -EINVAL; -+ -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ copy_count = jz_audio_fragsize / 4; -+ -+ left_count = count; -+ if (first_record_call) { -+ first_record_call = 0; -+ audio_read_back_first: -+ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ -+ spin_unlock(&controller->lock); -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ sleep_on(&rx_wait_queue); -+ } else -+ goto audio_read_back_first; -+ } -+ -+ while (left_count > 0) { -+ audio_read_back_second: -+ if (elements_in_queue(&in_full_queue) <= 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret ? ret : -EAGAIN; -+ else -+ sleep_on(&rx_wait_queue); -+ } -+ -+ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -+ spin_lock(&controller->lock); -+ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -+ spin_unlock(&controller->lock); -+ put_buffer_id(&in_empty_queue, id); -+ } else -+ goto audio_read_back_second; -+ -+ if (elements_in_queue(&in_busy_queue) == 0) { -+ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count * 4; -+ spin_unlock(&controller->lock); -+ -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ } -+ } -+ if (ret + cnt > count) { -+ spin_lock(&controller->lock); -+ cnt = count - ret; -+ spin_unlock(&controller->lock); -+ } -+ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -+ return ret ? ret : -EFAULT; -+ -+ spin_lock(&controller->lock); -+ ret += cnt; -+ spin_unlock(&controller->lock); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextIn += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ spin_lock(&controller->lock); -+ left_count -= cnt; -+ spin_unlock(&controller->lock); -+ } -+ return ret; -+} -+ -+static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -+{ -+ int id, ret = 0, left_count, copy_count = 0; -+ unsigned int flags; -+ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -+ -+ if (count <= 0) -+ return -EINVAL; -+ -+ if(set_replay_hp_or_speaker) -+ set_replay_hp_or_speaker(); -+ -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if (jz_audio_channels == 2) -+ copy_count = jz_audio_fragsize / jz_audio_b; -+ else if(jz_audio_channels == 1) -+ copy_count = jz_audio_fragsize / 4; -+ left_count = count; -+ if (copy_from_user(controller->tmp1, buffer, count)) { -+ printk("copy_from_user failed:%d",ret); -+ return ret ? ret : -EFAULT; -+ } -+ -+ while (left_count > 0) { -+ audio_write_back: -+ /*if (file->f_flags & O_NONBLOCK) -+ udelay(2);*/ -+ if (elements_in_queue(&out_empty_queue) == 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret; -+ else -+ sleep_on(&tx_wait_queue); -+ } -+ /* the end fragment size in this write */ -+ if (ret + copy_count > count) -+ copy_count = count - ret; -+ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -+ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ put_buffer_id(&out_full_queue, id); -+ dma_cache_wback_inv(*(out_dma_buf + id), -+ *(out_dma_buf_data_count + id)); -+ } else -+ put_buffer_id(&out_empty_queue, id); -+ } else -+ goto audio_write_back; -+ -+ left_count = left_count - copy_count; -+ ret += copy_count; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut += ret; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+ if (elements_in_queue(&out_busy_queue) == 0) { -+ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(controller->dma1, -+ file->private_data, -+ *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ last_dma_buffer_id = id; -+ if (jz_codec_config == 0) { -+ write_codec_file_bit(1, 0, 5); -+ gain_up_start = jiffies; -+ sleep_on(&pop_wait_queue); -+ //gain_up_end = jiffies; -+ jz_codec_config = 1; -+ //SB_ADC->1 -+ //write_codec_file_bit(5, 1, 4); -+ //while(1); -+ } -+ } -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+#if defined(CONFIG_I2S_ICODEC) -+static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -+{ -+ int i,step_len; -+ unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; -+ unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -+ unsigned long l_sample_count,r_sample_count,sample_count; -+ struct jz_i2s_controller_info *controller = i2s_controller; -+ signed int left_sam=0,right_sam=0,l_val,r_val; -+ -+ switch (sample_oss) { -+ case 0x0: -+ break; -+ case 0x1: -+ left_sam = (signed int)l_sample; -+ right_sam = (signed int)r_sample; -+ break; -+ case 0x2: -+ break; -+ case 0x3: -+ break; -+ case 0x4: -+ break; -+ } -+ -+ if(left_sam == 0 && right_sam == 0) -+ return; -+ -+ switch (sample_oss) { -+ case 0x0: -+ break; -+ case 0x1: -+ step_len = jz_audio_speed / 10 * 3; -+ step_len = step_len / 2; -+ step_len = 0x7fff / step_len + 1; -+ -+ l_sample_count = 0; -+ l_val = left_sam; -+ -+ while(1) { -+ if(l_val > 0) { -+ if(l_val >= step_len) { -+ l_val -= step_len; -+ l_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(l_val < 0) { -+ if(l_val <= -step_len) { -+ l_val += step_len; -+ l_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(l_val == 0) -+ break; -+ } -+ -+ r_sample_count = 0; -+ r_val = right_sam; -+ while(1) { -+ if(r_val > 0) { -+ if(r_val >= step_len) { -+ r_val -= step_len; -+ r_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(r_val < 0) { -+ if(r_val <= -step_len) { -+ r_val += step_len; -+ r_sample_count ++; -+ } else -+ break; -+ } -+ -+ if(r_val == 0) -+ break; -+ } -+ /* fill up */ -+ if(l_sample_count > r_sample_count) -+ sample_count = l_sample_count; -+ else -+ sample_count = r_sample_count; -+ -+ l_val = left_sam; -+ r_val = right_sam; -+ for(i=0;i <= sample_count;i++) { -+ -+ *pop_buf = (unsigned long)l_val; -+ pop_buf ++; -+ -+ if(l_val > step_len) -+ l_val -= step_len; -+ else if(l_val < -step_len) -+ l_val += step_len; -+ else if(l_val >= -step_len && l_val <= step_len) -+ l_val = 0; -+ -+ *pop_buf = (unsigned long)r_val; -+ pop_buf ++; -+ if(r_val > step_len) -+ r_val -= step_len; -+ else if(r_val < -step_len) -+ r_val += step_len; -+ else if(r_val >= -step_len && r_val <= step_len) -+ r_val = 0; -+ } -+ -+ *pop_buf = 0; -+ pop_buf ++; -+ *pop_buf = 0; -+ -+ pop_buf ++; -+ sample_count += 2; -+ dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); -+ -+ pop_dma_flag = 1; -+ audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); -+ sleep_on(&pop_wait_queue); -+ pop_dma_flag = 0; -+ break; -+ case 0x2: -+ break; -+ case 0x3: -+ break; -+ case 0x4: -+ break; -+ } -+} -+#endif -diff --git a/sound/oss/jz_pcm_tlv320aic1106_dma.c b/sound/oss/jz_pcm_tlv320aic1106_dma.c -new file mode 100644 -index 0000000..1a1f4cf ---- /dev/null -+++ b/sound/oss/jz_pcm_tlv320aic1106_dma.c -@@ -0,0 +1,1839 @@ -+/* -+ * linux/drivers/sound/jz_pcm_tlv320aic1106.c -+ * -+ * JzSOC On-Chip PCM audio driver. -+ * -+ * Copyright (C) 2005 by Ingenic Corp. -+ * -+ * 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. -+ * -+ * Because the normal application of AUDIO devices are focused on Little_endian, -+ * then we only perform the little endian data format in driver. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sound_config.h" -+ -+#define NR_PCM 2 -+#define MAXDELAY 50000 -+#define JZCODEC_RW_BUFFER_SIZE 4 -+#define JZCODEC_RW_BUFFER_TOTAL 3 -+#define JZCODEC_USER_BUFFER 6 -+ -+#define MODE_is_8 0 // 1 is 8 bits, and 0 is 16 bits -+ -+static int jz_audio_rate; -+static char jz_audio_format; -+static char jz_audio_volume; -+static char jz_audio_channels; -+static int jz_audio_fragments;//unused fragment amount -+static int jz_audio_fragstotal; -+static int jz_audio_fragsize; -+static int jz_audio_speed; -+static int jz_audio_dma_tran_count;//bytes count of one DMA transfer -+ -+static void jz_update_filler(int bits, int channels); -+static int Init_In_Out_queue(int fragstotal,int fragsize); -+static int Free_In_Out_queue(int fragstotal,int fragsize); -+static irqreturn_t jz_pcm_irq(int irqnr, void *ref); -+static irqreturn_t jz_pcm_replay_dma_irq(int irqnr, void *ref); -+static irqreturn_t jz_pcm_record_dma_irq(int irqnr, void *ref); -+static void (*replay_filler)(unsigned long src_start, int count, int id); -+static int (*record_filler)(unsigned long dst_start, int count, int id); -+static void dump_pcmc_reg(void); -+ -+static struct file_operations jz_pcm_audio_fops; -+static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -+static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -+ -+struct jz_pcm_controller_info { -+ int io_base; -+ int dma1; /* play */ -+ int dma2; /* record */ -+ char *name; -+ int dev_audio; -+ struct pcm_codec *pcm_codec[NR_PCM]; -+ int opened1; -+ int opened2; -+ unsigned char *tmp1; /* tmp buffer for sample conversions */ -+ unsigned char *tmp2; -+ spinlock_t lock; -+ spinlock_t ioctllock; -+ -+ wait_queue_head_t dac_wait; -+ wait_queue_head_t adc_wait; -+ int nextIn; // byte index to next-in to DMA buffer -+ int nextOut; // byte index to next-out from DMA buffer -+ int count; // current byte count in DMA buffer -+ int finish; // current transfered byte count in DMA buffer -+ unsigned long total_bytes; // total bytes written or read -+ unsigned long blocks; -+ unsigned long error; // over/underrun -+}; -+static struct jz_pcm_controller_info *pcm_controller = NULL; -+ -+struct pcm_codec { -+ /* PCM controller connected with */ -+ void *private_data; -+ char *name; -+ int id; -+ int dev_mixer; -+ /* controller specific lower leverl pcm accessing routines */ -+ u16 (*codec_read) (u8 reg);//the function accessing Codec REGs -+ void (*codec_write) (u8 reg, u16 val); -+ /* Wait for codec-ready. Ok to sleep here. */ -+ void (*codec_wait) (struct pcm_codec *codec); -+ /* OSS mixer masks */ -+ int modcnt; -+ int supported_mixers; -+ int stereo_mixers; -+ int record_sources; -+ int bit_resolution; -+ /* OSS mixer interface */ -+ int (*read_mixer) (struct pcm_codec *codec, int oss_channel); -+ void (*write_mixer)(struct pcm_codec *codec, int oss_channel, -+ unsigned int left, unsigned int right); -+ int (*recmask_io) (struct pcm_codec *codec, int rw, int mask); -+ int (*mixer_ioctl)(struct pcm_codec *codec, unsigned int cmd, unsigned long arg); -+ /* saved OSS mixer states */ -+ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -+}; -+ -+typedef struct buffer_queue_s { -+ int count; -+ int *id; -+ int lock; -+} buffer_queue_t; -+ -+static unsigned long *out_dma_buf = NULL; -+static unsigned long *out_dma_pbuf = NULL; -+static unsigned long *out_dma_buf_data_count = NULL; -+static unsigned long *in_dma_buf = NULL; -+static unsigned long *in_dma_pbuf = NULL; -+static unsigned long *in_dma_buf_data_count = NULL; -+ -+static buffer_queue_t out_empty_queue; -+static buffer_queue_t out_full_queue; -+static buffer_queue_t out_busy_queue; -+static buffer_queue_t in_empty_queue; -+static buffer_queue_t in_full_queue; -+static buffer_queue_t in_busy_queue; -+static int first_record_call = 0; -+ -+static inline int get_buffer_id(struct buffer_queue_s *q) -+{ -+ int r, i; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ if (q->count == 0) { -+ spin_unlock_irqrestore(&q->lock, flags); -+ return -1; -+ } -+ r = *(q->id + 0); -+ for (i=0;i < q->count-1;i++) -+ *(q->id + i) = *(q->id + (i+1)); -+ q->count --; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void put_buffer_id(struct buffer_queue_s *q, int id) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ *(q->id + q->count) = id; -+ q->count ++; -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+ -+static inline int elements_in_queue(struct buffer_queue_s *q) -+{ -+ int r; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ r = q->count; -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return r; -+} -+ -+static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -+{ -+ unsigned long flags; -+ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -+ -+ //for DSP_GETOPTR -+ //spin_lock_irqsave(&controller->ioctllock, flags); -+ spin_lock(&controller->ioctllock); -+ jz_audio_dma_tran_count = count; -+ //spin_unlock_irqrestore(&controller->ioctllock, flags); -+ spin_unlock(&controller->ioctllock); -+ flags = claim_dma_lock(); -+ __dmac_disable_module(0);//!!!!!!!!! -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ set_dma_mode(chan, mode); -+#if MODE_is_8 -+ __dmac_channel_set_src_port_width(chan, 8); -+ __dmac_channel_set_dest_port_width(chan, 8); -+ __dmac_channel_set_transfer_unit_8bit(chan); -+#else -+ __dmac_channel_set_src_port_width(chan, 16); -+ __dmac_channel_set_dest_port_width(chan, 16); -+ __dmac_channel_set_transfer_unit_16bit(chan); -+#endif -+ -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) { -+ count++; -+ printk("JzSOC DMA controller can't set dma 0 count!\n"); -+ } -+ -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ __dmac_enable_module(0); -+ release_dma_lock(flags); -+#if 0 -+ //for DSP_GETOPTR on FPGA -+ struct jz_dma_chan *tmpchan = &jz_dma_table[1]; -+ -+ spin_lock(&controller->ioctllock); -+ jz_audio_dma_tran_count = count; -+ spin_unlock(&controller->ioctllock); -+ flags = claim_dma_lock(); -+ disable_dma(chan); -+ clear_dma_ff(chan); -+ set_dma_mode(chan, mode); -+#if MODE_is_8 -+ __dmac_channel_set_src_port_width(chan, 8); -+ __dmac_channel_set_dest_port_width(chan, 8); -+ __dmac_channel_set_transfer_unit_8bit(chan); -+#else -+ __dmac_channel_set_src_port_width(chan, 16); -+ __dmac_channel_set_dest_port_width(chan, 16); -+ __dmac_channel_set_transfer_unit_16bit(chan); -+#endif -+ set_dma_addr(chan, phyaddr); -+ if (count == 0) { -+ count++; -+ printk("JzSOC DMA controller can't set dma 0 count!\n"); -+ } -+ set_dma_count(chan, count); -+ enable_dma(chan); -+ release_dma_lock(flags); -+#if 0 -+ __pcm_enable_tfs_intr(); -+ __pcm_enable_tur_intr(); -+ __pcm_enable_rfs_intr(); -+ __pcm_enable_ror_intr(); -+#endif -+#endif -+} -+ -+static irqreturn_t jz_pcm_record_dma_irq(int irq, void *dev_id) -+{ -+ int id1, id2; -+ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -+ int dma = controller->dma2; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ //for DSP_GETIPTR -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock(&controller->ioctllock); -+ id1 = get_buffer_id(&in_busy_queue); -+ put_buffer_id(&in_full_queue, id1); -+ -+ wake_up(&rx_wait_queue); -+ wake_up(&controller->adc_wait); -+ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id2); -+ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -+ -+ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -+ audio_start_dma(dma,dev_id, -+ *(in_dma_pbuf + id2), -+ *(in_dma_buf_data_count + id2), -+ DMA_MODE_READ); -+ } else -+ in_busy_queue.count = 0; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t jz_pcm_irq(int irq, void *dev_id) -+{ -+ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -+ printk("pcm interrupt REG_PCM_INTS : 0x%08x\n",REG_PCM_INTS); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t jz_pcm_replay_dma_irq(int irq, void *dev_id) -+{ -+ int id; -+ unsigned long flags; -+ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -+ int dma = controller->dma1; -+ -+ disable_dma(dma); -+ if (__dmac_channel_address_error_detected(dma)) { -+ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -+ __dmac_channel_clear_address_error(dma); -+ } -+ if (__dmac_channel_transmit_end_detected(dma)) { -+ __dmac_channel_clear_transmit_end(dma); -+ //for DSP_GETOPTR -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->total_bytes += jz_audio_dma_tran_count; -+ controller->blocks ++; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ if ((id = get_buffer_id(&out_busy_queue)) < 0) -+ printk(KERN_DEBUG "Strange DMA finish interrupt for PCM module\n"); -+ put_buffer_id(&out_empty_queue, id); -+ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); //very busy -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ } -+ } else -+ out_busy_queue.count = 0; -+ -+ if (elements_in_queue(&out_empty_queue) > 0) { -+ wake_up(&tx_wait_queue); -+ wake_up(&controller->dac_wait); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int Init_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ // recording -+ in_empty_queue.count = fragstotal; -+ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf) -+ goto all_mem_err; -+ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_pbuf) -+ goto all_mem_err; -+ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!in_dma_buf_data_count) -+ goto all_mem_err; -+ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_empty_queue.id) -+ goto all_mem_err; -+ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_full_queue.id) -+ goto all_mem_err; -+ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!in_busy_queue.id) -+ goto all_mem_err; -+ -+ for (i=0;i < fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ for (i = 0; i < fragstotal; i++) { -+ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(in_dma_buf + i) == 0) -+ goto mem_failed_in; -+ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ } -+ -+ //playing -+ out_empty_queue.count = fragstotal; -+ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_buf) -+ goto all_mem_err; -+ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ if (!out_dma_pbuf) -+ goto all_mem_err; -+ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -+ -+ if (!out_dma_buf_data_count) -+ goto all_mem_err; -+ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_empty_queue.id) -+ goto all_mem_err; -+ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_full_queue.id) -+ goto all_mem_err; -+ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -+ if (!out_busy_queue.id) -+ goto all_mem_err; -+ for (i=0;i < fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /*alloc DMA buffer*/ -+ for (i = 0; i < fragstotal; i++) { -+ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -+ if (*(out_dma_buf + i) == 0) { -+ printk(" can't allocate required DMA(OUT) buffers.\n"); -+ goto mem_failed_out; -+ } -+ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -+ } -+ -+ return 1; -+all_mem_err: -+ printk("error:allocate memory occur error 1!\n"); -+ return 0; -+mem_failed_out: -+ printk("error:allocate memory occur error 2!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ } -+ -+ return 0; -+mem_failed_in: -+ printk("error:allocate memory occur error 3!\n"); -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ return 0; -+} -+ -+static int Free_In_Out_queue(int fragstotal,int fragsize) -+{ -+ int i; -+ //playing -+ if(out_dma_buf != NULL) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(out_dma_buf + i)) -+ free_pages(*(out_dma_buf + i), get_order(fragsize)); -+ *(out_dma_buf + i) = 0; //release page error -+ } -+ kfree(out_dma_buf); -+ out_dma_buf = NULL; -+ } -+ if(out_dma_pbuf) { -+ kfree(out_dma_pbuf); -+ out_dma_pbuf = NULL; -+ } -+ if(out_dma_buf_data_count) { -+ kfree(out_dma_buf_data_count); -+ out_dma_buf_data_count = NULL; -+ } -+ if(out_empty_queue.id) { -+ kfree(out_empty_queue.id); -+ out_empty_queue.id = NULL; -+ } -+ if(out_full_queue.id) { -+ kfree(out_full_queue.id); -+ out_full_queue.id = NULL; -+ } -+ if(out_busy_queue.id) { -+ kfree(out_busy_queue.id); -+ out_busy_queue.id = NULL; -+ } -+ out_empty_queue.count = fragstotal; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ -+ // recording -+ if(in_dma_buf) { -+ for (i = 0; i < fragstotal; i++) { -+ if(*(in_dma_buf + i)) { -+ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -+ free_pages(*(in_dma_buf + i), get_order(fragsize)); -+ } -+ *(in_dma_buf + i) = 0; //release page error -+ } -+ kfree(in_dma_buf); -+ in_dma_buf = NULL; -+ } -+ if(in_dma_pbuf) { -+ kfree(in_dma_pbuf); -+ in_dma_pbuf = NULL; -+ } -+ if(in_dma_buf_data_count) { -+ kfree(in_dma_buf_data_count); -+ in_dma_buf_data_count = NULL; -+ } -+ if(in_empty_queue.id) { -+ kfree(in_empty_queue.id); -+ in_empty_queue.id = NULL; -+ } -+ if(in_full_queue.id) { -+ kfree(in_full_queue.id); -+ in_full_queue.id = NULL; -+ } -+ if(in_busy_queue.id) { -+ kfree(in_busy_queue.id); -+ in_busy_queue.id = NULL; -+ } -+ -+ in_empty_queue.count = fragstotal; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ -+ return 1; -+} -+ -+static int jz_audio_set_speed(int dev, int rate) -+{ -+ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 */ -+ long codec_speed; -+ long speed = 0; -+ -+ jz_audio_speed = rate; -+ if (rate > 48000) -+ rate = 48000; -+ if (rate < 8000) -+ rate = 8000; -+ jz_audio_rate = rate; -+ -+ /*switch (rate) { -+ case 8000: -+ speed = 0; -+ break; -+ case 11025: -+ speed = 1; -+ break; -+ case 12000: -+ speed = 2; -+ break; -+ case 16000: -+ speed = 3; -+ break; -+ case 22050: -+ speed = 4; -+ break; -+ case 24000: -+ speed = 5; -+ break; -+ case 32000: -+ speed = 6; -+ break; -+ case 44100: -+ speed = 7; -+ break; -+ case 48000: -+ speed = 8; -+ break; -+ default: -+ break; -+ } -+ printk("set PCMIN or PCMOUT speed.\n"); -+ __pcm_set_clk_rate(speed); -+ __pcm_set_sync_rate(256);*/ -+ -+ return jz_audio_rate; -+} -+ -+ -+static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ volatile unsigned char *s = (unsigned char*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+ while (count > 0) { -+ *dp = *s; -+ dp ++; -+ s++; -+ count --; -+ cnt ++; -+ } -+ -+ return cnt; -+} -+ -+static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ volatile unsigned char *s = (unsigned char*)(*(in_dma_buf + id)); -+ volatile unsigned char *dp = (unsigned char*)dst_start; -+ -+#if 1 -+ while (count > 0) { -+ *dp = *s; -+ s ++; -+ dp ++; -+ count --; -+ cnt ++; -+ } -+#else -+ while (count > 0) { -+ *dp = *s; -+ s += 2; //skip right sample -+ dp ++; -+ count -= 2; -+ cnt ++; -+ } -+#endif -+ return cnt; -+} -+ -+static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned short d1; -+ unsigned short *s = (unsigned short*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+ while (count > 0) { -+ *dp = *s; -+ s ++; -+ dp ++; -+ count -= 2; -+ cnt += 2; -+ } -+ -+ return cnt; -+} -+ -+static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned short *s = (unsigned short*)(*(in_dma_buf + id)); -+ unsigned short *dp = (unsigned short *)dst_start; -+ -+#if 1 -+ while (count > 0) { -+ *dp = *s; -+ s ++; -+ dp ++; -+ count -= 2; -+ cnt += 2; -+ } -+#else -+ while (count > 0) { -+ *dp = *s; -+ s += 2; //skip right sample -+ dp ++; -+ count -= 4; -+ cnt += 2;/* count in byte */ -+ } -+#endif -+ -+ return cnt; -+} -+ -+static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -+{ -+#if 0 -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); -+ -+ *(out_dma_buf_data_count + id) = count; -+ while (count > 0) { -+ *dp = *s; -+ dp ++; -+ s ++; -+ count --; -+ } -+#else -+ volatile u8 *s = (u8 *)src_start; -+ volatile u8 *dp = (u8 *)(*(out_dma_buf + id)); -+ -+ *(out_dma_buf_data_count + id) = count; -+ while (count > 0) { -+ *dp = *s; -+ dp ++; -+ s ++; -+ count --; -+ } -+#endif -+} -+ -+static void replay_fill_2x8_u(unsigned long src_start, int count, int id) -+{ -+ volatile unsigned char *s = (unsigned char *)src_start; -+ volatile unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); -+ -+#if 1 -+ *(out_dma_buf_data_count + id) = count; -+ while (count > 0) { -+ *dp = *s; -+ dp ++; -+ s ++; -+ count --; -+ } -+#else -+ while (count > 0) { -+ *dp = *s; -+ s += 2; //skip right sample -+ dp ++; -+ count -= 2; -+ cnt ++; -+ } -+ *(out_dma_buf_data_count + id) = cnt; -+#endif -+} -+ -+ -+static void replay_fill_1x16_s(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned short d1, l1; -+ signed short sam_to; -+ volatile unsigned short *s = (unsigned short *)src_start; -+ volatile unsigned short *dp = (unsigned short*)(*(out_dma_buf + id)); -+ -+ while (count > 0) { -+ d1 = *s; -+ -+ sam_to = (signed short)d1; -+ if (sam_to >= 0) { -+ sam_to = 0xfff * sam_to / 0x7fff; -+ } else { -+ sam_to = 0 - sam_to; -+ sam_to = 0xfff * sam_to / 0x7fff; -+ sam_to = 0 - sam_to; -+ } -+ d1 = (unsigned short)sam_to; -+ d1 = d1 << 3; -+ l1 = d1 | jz_audio_volume; -+ -+ *dp = l1; -+ s ++; -+ dp ++; -+ count -= 2; -+ cnt += 2 ; -+ } -+ *(out_dma_buf_data_count + id) = cnt; -+} -+ -+static void replay_fill_2x16_s(unsigned long src_start, int count, int id) -+{ -+ int cnt = 0; -+ unsigned short d1, l1; -+ volatile unsigned short *s = (unsigned short *)src_start; -+ volatile unsigned short *dp = (unsigned short*)(*(out_dma_buf + id)); -+ -+#if 1 -+ while (count > 0) { -+ d1 = *s; -+ l1 = (d1 & 0xfff8) | jz_audio_volume; -+ *dp = l1; -+ s ++; -+ dp ++; -+ count -= 2; -+ cnt += 2 ; -+ } -+ *(out_dma_buf_data_count + id) = cnt; -+#else -+ while (count > 0) { -+ d1 = *s; -+ l1 = (d1 & 0xfff8) | jz_audio_volume; -+ *dp = l1; -+ s += 2; //skip right sample -+ dp ++; -+ count -= 4; -+ cnt += 2; -+ } -+ *(out_dma_buf_data_count + id) = cnt; -+#endif -+} -+ -+static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -+{ -+ switch (fmt) { -+ case AFMT_U8: -+ case AFMT_S16_LE: -+ jz_audio_format = fmt; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ case AFMT_QUERY: -+ break; -+ } -+ -+ return jz_audio_format; -+} -+ -+static short jz_audio_set_channels(int dev, short channels) -+{ -+ switch (channels) { -+ case 1: -+ case 2: -+ jz_audio_channels = channels; -+ jz_update_filler(jz_audio_format, jz_audio_channels); -+ break; -+ default: -+ printk("channel number is wrong. %d\n",__LINE__); -+ } -+ -+ return jz_audio_channels; -+} -+ -+static void init_codec(void) -+{ -+ printk("set PCM codec RESET pin on LOW, while MCLK occur.\n"); -+ printk("set LINSEL on LOW(8bits) or HIGH(13bits+3bits for PCMOUT gain).\n"); -+} -+ -+static void jz_audio_reset(void) -+{ -+ __pcm_flush_fifo(); -+ __pcm_disable_txfifo(); -+ __pcm_disable_rxfifo(); -+ __pcm_set_transmit_trigger(7); -+ __pcm_set_receive_trigger(7); -+ __pcm_omsb_next_sync(); -+ __pcm_imsb_next_sync(); -+#if MODE_is_8 -+ __pcm_set_iss(8);//8bits decided by LINSEL -+ __pcm_set_oss(8);//8bits decided by LINSEL -+#else -+ __pcm_set_iss(16);//16bits decided by LINSEL -+ __pcm_set_oss(16); -+#endif -+ __pcm_disable_tfs_intr(); -+ __pcm_disable_tur_intr(); -+ __pcm_disable_rfs_intr(); -+ __pcm_disable_ror_intr(); -+ -+ __pcm_disable_receive_dma(); -+ __pcm_disable_transmit_dma(); -+ -+ //init_codec(); -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file); -+static int jz_audio_open(struct inode *inode, struct file *file); -+static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -+static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -+static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -+ -+/* static struct file_operations jz_pcm_audio_fops */ -+static struct file_operations jz_pcm_audio_fops = -+{ -+ owner: THIS_MODULE, -+ open: jz_audio_open, -+ release: jz_audio_release, -+ write: jz_audio_write, -+ read: jz_audio_read, -+ poll: jz_audio_poll, -+ ioctl: jz_audio_ioctl -+}; -+ -+static int jz_pcm_open_mixdev(struct inode *inode, struct file *file) -+{ -+ int i; -+ int minor = MINOR(inode->i_rdev); -+ struct jz_pcm_controller_info *controller = pcm_controller; -+ -+ for (i = 0; i < NR_PCM; i++) -+ if (controller->pcm_codec[i] != NULL && controller->pcm_codec[i]->dev_mixer == minor) -+ goto match; -+ -+ if (!controller) -+ return -ENODEV; -+match: -+ file->private_data = controller->pcm_codec[i]; -+ -+ return 0; -+} -+ -+static int jz_pcm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct pcm_codec *codec = (struct pcm_codec *)file->private_data; -+ return codec->mixer_ioctl(codec, cmd, arg); -+} -+ -+static loff_t jz_pcm_llseek(struct file *file, loff_t offset, int origin) -+{ -+ return -ESPIPE; -+} -+ -+static struct file_operations jz_pcm_mixer_fops = -+{ -+ owner: THIS_MODULE, -+ llseek: jz_pcm_llseek, -+ ioctl: jz_pcm_ioctl_mixdev, -+ open: jz_pcm_open_mixdev, -+}; -+ -+static int pcm_mixer_ioctl(struct pcm_codec *codec, unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ long val = 0; -+ -+ switch (cmd) { -+ case SOUND_MIXER_READ_STEREODEVS: -+ return put_user(0, (long *) arg); -+ case SOUND_MIXER_READ_CAPS: -+ val = SOUND_CAP_EXCL_INPUT; -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_READ_DEVMASK: -+ break; -+ case SOUND_MIXER_READ_RECMASK: -+ break; -+ case SOUND_MIXER_READ_RECSRC: -+ break; -+ case SOUND_MIXER_WRITE_VOLUME: -+ ret = get_user(val, (long *) arg); -+ if (ret) -+ return ret; -+ val = val & 0xff; -+ if(val < 0) -+ val = 0; -+ if(val > 100) -+ val = 100; -+ if (val == 100) { -+ dump_pcmc_reg(); -+ return 100; -+ } -+ val = val / 10; -+ switch (val) { -+ case 0: -+ case 1: -+ jz_audio_volume = 7; -+ break; -+ case 2: -+ jz_audio_volume = 6; -+ break; -+ case 3: -+ jz_audio_volume = 5; -+ break; -+ case 4: -+ jz_audio_volume = 4; -+ break; -+ case 5: -+ jz_audio_volume = 3; -+ break; -+ case 6: -+ jz_audio_volume = 2; -+ break; -+ case 7: -+ case 8: -+ jz_audio_volume = 1; -+ break; -+ case 9: -+ case 10: -+ jz_audio_volume = 0; -+ break; -+ } -+ return 0; -+ case SOUND_MIXER_READ_VOLUME: -+ val = jz_audio_volume; -+ ret = val << 8; -+ val = val | ret; -+ return put_user(val, (long *) arg); -+ case SOUND_MIXER_WRITE_MIC: -+ printk("Can not justify Mic gain to the PCM codec.!\n"); -+ return -ENOSYS; -+ -+ case SOUND_MIXER_READ_MIC: -+ printk("Can not justify Mic gain to the PCM codec.!\n"); -+ return -ENOSYS; -+ default: -+ return -ENOSYS; -+ } -+ -+ return 0; -+} -+ -+ -+int pcm_probe_codec(struct pcm_codec *codec) -+{ -+ /* generic OSS to PCM wrapper */ -+ codec->mixer_ioctl = pcm_mixer_ioctl; -+ return 1; -+} -+ -+/* PCM codec initialisation. */ -+static int __init jz_pcm_codec_init(struct jz_pcm_controller_info *controller) -+{ -+ int num_pcm = 0; -+ struct pcm_codec *codec; -+ -+ for (num_pcm = 0; num_pcm < NR_PCM; num_pcm++) { -+ if ((codec = kmalloc(sizeof(struct pcm_codec),GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ memset(codec, 0, sizeof(struct pcm_codec)); -+ codec->private_data = controller; -+ codec->id = num_pcm; -+ -+ if (pcm_probe_codec(codec) == 0) -+ break; -+ if ((codec->dev_mixer = register_sound_mixer(&jz_pcm_mixer_fops, -1)) < 0) { -+ printk(KERN_ERR "Jz PCM: couldn't register mixer!\n"); -+ kfree(codec); -+ break; -+ } -+ controller->pcm_codec[num_pcm] = codec; -+ } -+ -+ return num_pcm; -+} -+ -+static void jz_update_filler(int format, int channels) -+{ -+#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -+ -+ switch (TYPE(format, channels)) { -+ default: -+ case TYPE(AFMT_U8, 1): -+ replay_filler = replay_fill_1x8_u; -+ record_filler = record_fill_1x8_u; -+ break; -+ case TYPE(AFMT_U8, 2): -+ /*replay_filler = replay_fill_2x8_u; -+ record_filler = record_fill_2x8_u;*/ -+ printk("channel is 2. Line:%d\n",__LINE__); -+ break; -+ case TYPE(AFMT_S16_LE, 1): -+ replay_filler = replay_fill_1x16_s; -+ record_filler = record_fill_1x16_s; -+ break; -+ case TYPE(AFMT_S16_LE, 2): -+ /*replay_filler = replay_fill_2x16_s; -+ record_filler = record_fill_2x16_s;*/ -+ printk("channel is 2. Line:%d\n",__LINE__); -+ break; -+ } -+} -+ -+static void __init attach_jz_pcm(struct jz_pcm_controller_info *controller) -+{ -+ char *name; -+ int adev;//No of Audio device. -+ int err; -+ -+ name = controller->name; -+ /* register /dev/audio */ -+ adev = register_sound_dsp(&jz_pcm_audio_fops, -1); -+ if (adev < 0) -+ goto audio_failed; -+ /* initialize PCM codec and register /dev/mixer */ -+ if (jz_pcm_codec_init(controller) <= 0) -+ goto mixer_failed; -+ -+ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); -+ if (!controller->tmp1) { -+ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -+ goto tmp1_failed; -+ } -+ printk("DMA_ID_PCM_TX=0x%08x DMA_ID_PCM_RX=0x%08x\n",DMA_ID_PCM_TX ,DMA_ID_PCM_RX); -+ if ((controller->dma1 = jz_request_dma(DMA_ID_PCM_TX, "audio dac", jz_pcm_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -+ goto dma1_failed; -+ } -+ if ((controller->dma2 = jz_request_dma(DMA_ID_PCM_RX, "audio adc", jz_pcm_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -+ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -+ goto dma2_failed; -+ } -+ printk("JzSOC On-Chip PCM controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -+ -+ err = request_irq(IRQ_PCM, jz_pcm_irq, IRQF_DISABLED, "pcm irq", controller); -+ if (err < 0) -+ printk("can't allocate pcm irq.\n"); -+ controller->dev_audio = adev; -+ -+ return; -+dma2_failed: -+ jz_free_dma(controller->dma2); -+dma1_failed: -+ jz_free_dma(controller->dma1); -+tmp1_failed: -+ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -+ -+mixer_failed: -+ unregister_sound_dsp(adev); -+audio_failed: -+ return; -+} -+ -+ -+static int __init probe_jz_pcm(struct jz_pcm_controller_info **controller) -+{ -+ if ((*controller = kmalloc(sizeof(struct jz_pcm_controller_info), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "Jz PCM Controller: out of memory.\n"); -+ return -ENOMEM; -+ } -+ -+ (*controller)->name = "Jz PCM controller"; -+ (*controller)->opened1 = 0; -+ (*controller)->opened2 = 0; -+ init_waitqueue_head(&(*controller)->adc_wait); -+ init_waitqueue_head(&(*controller)->dac_wait); -+ spin_lock_init(&(*controller)->lock); -+ init_waitqueue_head(&rx_wait_queue); -+ init_waitqueue_head(&tx_wait_queue); -+ -+ return 0; -+} -+ -+static void __exit unload_jz_pcm(struct jz_pcm_controller_info *controller) -+{ -+ int adev = controller->dev_audio; -+ -+ __pcm_reset(); -+ schedule_timeout(5); -+ __pcm_disable(); -+ __pcm_clk_disable(); -+ __pcm_flush_fifo(); -+ -+ controller->dev_audio = -1; -+ jz_free_dma(controller->dma1); -+ jz_free_dma(controller->dma2); -+ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -+ -+ if (adev >= 0) -+ unregister_sound_dsp(controller->dev_audio); -+} -+ -+static int __init init_jz_pcm(void) -+{ -+ int errno; -+ /* 24M OSC ---> CPCCR.ECS ---> PCMCDR.PCMS ---> cpm_pcm_sysclk(X) */ -+ long X = 12000000; //in Hz /* 6.144 MHz <= X <= 264.192 MHz */ -+ -+#if 0 -+ /* pcm_sys_clk is from PLL divsion */ -+ REG_CPM_PCMCDR = 0x8000001b; -+ REG_CPM_CPCCR |= 0x00400000; -+#endif -+ /* pcm_sys_clk is from external clock */ -+ /* reset codec GPF4 */ -+ __gpio_as_output(32 * 5 + 4); -+ __gpio_set_pin(32 * 5 + 4); -+ mdelay(1); -+ -+ __pcm_reset(); -+ schedule_timeout(5); -+ __pcm_clk_disable(); -+ -+ /* set CPM to output cpm-pcm-sysclk ,assume cpm-pcm-sysclk is X Hz */ -+ /* PCMCLK must be 2048000 Hz, it is 256 mutil of PCMSYNC */ -+ //__pcm_set_clk_rate(X, 2048000); -+ __pcm_set_clk_rate(X, 2000000); -+ /* PCMSYNC must be 8000 Hz. 2048000 / 256 = 8000 */ -+ __pcm_set_sync_rate(2048000, 8000); -+ //__pcm_set_sync_rate(2000000, 8000); -+ __pcm_set_sync_len(0); -+ -+ __pcm_flush_fifo(); -+ __pcm_disable_txfifo(); -+ __pcm_disable_rxfifo(); -+ __pcm_set_transmit_trigger(7); -+ __pcm_set_receive_trigger(7); -+ __pcm_omsb_next_sync(); -+ __pcm_imsb_next_sync(); -+ -+#if MODE_is_8 -+ __pcm_set_iss(8);//8bits decided by LINSEL -+ __pcm_set_oss(8); -+#else -+ __pcm_set_iss(16);//16bits decided by LINSEL -+ __pcm_set_oss(16); -+#endif -+ __pcm_set_valid_slot(1); -+ -+ __pcm_disable_tfs_intr(); -+ __pcm_disable_tur_intr(); -+ __pcm_disable_rfs_intr(); -+ __pcm_disable_ror_intr(); -+ -+ __pcm_disable_receive_dma(); -+ __pcm_disable_transmit_dma(); -+ -+ __pcm_last_sample(); -+ __pcm_as_master(); -+ -+ __pcm_enable(); -+ __pcm_clk_enable(); -+ -+ if ((errno = probe_jz_pcm(&pcm_controller)) < 0) -+ return errno; -+ attach_jz_pcm(pcm_controller); -+ -+ out_empty_queue.id = NULL; -+ out_full_queue.id = NULL; -+ out_busy_queue.id = NULL; -+ in_empty_queue.id = NULL; -+ in_full_queue.id = NULL; -+ in_busy_queue.id = NULL; -+ -+ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -+ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ -+ __gpio_clear_pin(32 * 5 + 4); -+ udelay(100); -+ -+ __gpio_set_pin(32 * 5 + 4); -+ dump_pcmc_reg(); -+ -+ return 0; -+} -+ -+ -+static void __exit cleanup_jz_pcm(void) -+{ -+ unload_jz_pcm(pcm_controller); -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+} -+ -+module_init(init_jz_pcm); -+module_exit(cleanup_jz_pcm); -+ -+static int drain_adc(struct jz_pcm_controller_info *ctrl, int nonblock) -+{ -+ unsigned long flags; -+ int count, i=0; -+ -+ for (;;) { -+ if ( i < MAXDELAY ) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma2); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ -+ if (nonblock) -+ return -EBUSY; -+ } -+ -+ return 0; -+} -+static int drain_dac(struct jz_pcm_controller_info *ctrl, int nonblock) -+{ -+ unsigned long flags; -+ int count, ele, i=0; -+ -+ for (;;) { -+ if(!nonblock) {//blocked -+ if ( i < MAXDELAY ) { -+ udelay(10); -+ i++; -+ } else -+ break; -+ -+ ele = elements_in_queue(&out_full_queue); -+ if(ele <= 0) { -+ udelay(10); -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } else {//non-blocked -+ mdelay(100); -+ ele = elements_in_queue(&out_full_queue); -+ -+ if(ele <= 0) { -+ mdelay(100); -+ -+ spin_lock_irqsave(&ctrl->lock, flags); -+ count = get_dma_residue(ctrl->dma1); -+ spin_unlock_irqrestore(&ctrl->lock, flags); -+ if (count <= 0) -+ break; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int jz_audio_release(struct inode *inode, struct file *file) -+{ -+ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ if ( controller->opened1 == 1 ) { -+ __pcm_enable_transmit_dma(); -+ __pcm_enable_txfifo(); -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma1); -+ set_dma_count(controller->dma1, 0); -+ -+ __pcm_disable_transmit_dma(); -+ __pcm_disable_txfifo(); -+ -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ spin_unlock(&controller->ioctllock); -+ //__pcm_disable(); -+ controller->opened1 = 0; -+ } -+ -+ if ( controller->opened2 == 1 ) { -+ first_record_call = 1; -+ __pcm_enable_receive_dma(); -+ __pcm_enable_rxfifo(); -+ drain_adc(controller, file->f_flags & O_NONBLOCK); -+ disable_dma(controller->dma2); -+ set_dma_count(controller->dma2, 0); -+ __pcm_disable_receive_dma(); -+ __pcm_disable_rxfifo(); -+ -+ spin_lock(&controller->ioctllock); -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ spin_unlock(&controller->ioctllock); -+ //__pcm_disable(); -+ controller->opened2 = 0; -+ } -+ __pcm_disable_tfs_intr(); -+ __pcm_disable_tur_intr(); -+ __pcm_disable_rfs_intr(); -+ __pcm_disable_ror_intr(); -+ -+ return 0; -+} -+ -+static int jz_audio_open(struct inode *inode, struct file *file) -+{ -+ int i; -+ struct jz_pcm_controller_info *controller = pcm_controller; -+ -+ if (controller == NULL) -+ return -ENODEV; -+ -+ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -+ printk("\naudio is busy!\n"); -+ return -EBUSY; -+ } -+ REG_DMAC_DMACKE(0) = 0x3f; -+ REG_DMAC_DMACKE(1) = 0x3f; -+ if (file->f_mode & FMODE_WRITE) { -+ if (controller->opened1 == 1) -+ return -EBUSY; -+ controller->opened1 = 1; -+ //for ioctl -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextOut = 0; -+ -+ out_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(out_empty_queue.id + i) = i; -+ out_busy_queue.count = 0; -+ out_full_queue.count = 0; -+ /* set PCMOUT params */ -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (controller->opened2 == 1) -+ return -EBUSY; -+ controller->opened2 = 1; -+ first_record_call = 1; -+ //for ioctl -+ controller->total_bytes = 0; -+ jz_audio_dma_tran_count = 0; -+ controller->count = 0; -+ controller->finish = 0; -+ controller->blocks = 0; -+ controller->nextIn = 0; -+ in_empty_queue.count = jz_audio_fragstotal; -+ for (i=0;i < jz_audio_fragstotal;i++) -+ *(in_empty_queue.id + i) = i; -+ in_full_queue.count = 0; -+ in_busy_queue.count = 0; -+ /* set PCMIN params */ -+ } -+ -+ file->private_data = controller; -+ jz_audio_reset(); -+ __pcm_enable(); -+ -+ return 0; -+} -+ -+static int jz_audio_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -+ unsigned int flags; -+ audio_buf_info abinfo; -+ int i, bytes, id; -+ count_info cinfo; -+ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -+ -+ val = 0; -+ bytes = 0; -+ switch (cmd) { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, (int *)arg); -+ case SNDCTL_DSP_RESET: -+ return 0; -+ case SNDCTL_DSP_SYNC: -+ if (file->f_mode & FMODE_WRITE) -+ drain_dac(controller, file->f_flags & O_NONBLOCK); -+ return 0; -+ case SNDCTL_DSP_SPEED: -+ { -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ /* set smaple rate */ -+ if (val >= 0) -+ jz_audio_set_speed(controller->dev_audio, val); -+ return put_user(val, (int *)arg); -+ } -+ case SNDCTL_DSP_STEREO: -+ /* set stereo or mono channel */ -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ -+ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -+ return 0; -+ -+ case SNDCTL_DSP_GETBLKSIZE: -+ //return put_user(4*PAGE_SIZE, (int *)arg); -+ return put_user(jz_audio_fragsize , (int *)arg); -+ case SNDCTL_DSP_GETFMTS: -+ /* Returns a mask of supported sample format*/ -+ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -+ -+ case SNDCTL_DSP_SETFMT: -+ { -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ /* Select sample format */ -+ if (val != AFMT_QUERY) -+ jz_audio_set_format(controller->dev_audio,val); -+ else -+ if (file->f_mode & FMODE_READ) -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ else -+ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -+ return put_user(val, (int *)arg); -+ } -+ -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__); -+ jz_audio_set_channels(controller->dev_audio, val); -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_POST: -+ /* FIXME: the same as RESET ?? */ -+ return 0; -+ -+ case SNDCTL_DSP_SUBDIVIDE: -+ return 0; -+ -+ case SNDCTL_DSP_SETFRAGMENT: -+ get_user(val, (long *) arg); -+ newfragsize = 1 << (val & 0xFFFF);//16 least bits -+ -+ if (newfragsize < 4 * PAGE_SIZE) -+ newfragsize = 4 * PAGE_SIZE; -+ if (newfragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE -+ newfragsize = 16 * PAGE_SIZE; -+ -+ newfragstotal = (val >> 16) & 0x7FFF; -+ if (newfragstotal < 2) -+ newfragstotal = 2; -+ if (newfragstotal > 32) -+ newfragstotal = 32; -+ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -+ return 0; -+ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(500); -+ jz_audio_fragstotal = newfragstotal; -+ jz_audio_fragsize = newfragsize; -+ -+ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -+ mdelay(10); -+ -+ return 0; -+ case SNDCTL_DSP_GETCAPS: -+ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -+ case SNDCTL_DSP_NONBLOCK: -+ file->f_flags |= O_NONBLOCK; -+ return 0; -+ case SNDCTL_DSP_SETDUPLEX: -+ return -EINVAL; -+ case SNDCTL_DSP_GETOSPACE: -+ { -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ //unused fragment amount -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ jz_audio_fragments = elements_in_queue(&out_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ abinfo.fragsize = jz_audio_fragsize; -+ abinfo.bytes = bytes; -+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -+ } -+ case SNDCTL_DSP_GETISPACE: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ bytes = 0; -+ //unused fragment amount -+ jz_audio_fragments = elements_in_queue(&in_empty_queue); -+ for (i = 0; i < jz_audio_fragments; i++) -+ bytes += jz_audio_fragsize; -+ -+ abinfo.fragments = jz_audio_fragments; -+ abinfo.fragstotal = jz_audio_fragstotal; -+ abinfo.fragsize = jz_audio_fragsize; -+ abinfo.bytes = bytes; -+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -+ case SNDCTL_DSP_GETTRIGGER: -+ val = 0; -+ if (file->f_mode & FMODE_READ && in_dma_buf) -+ val |= PCM_ENABLE_INPUT; -+ if (file->f_mode & FMODE_WRITE && out_dma_buf) -+ val |= PCM_ENABLE_OUTPUT; -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_SETTRIGGER: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ return 0; -+ case SNDCTL_DSP_GETIPTR: -+ if (!(file->f_mode & FMODE_READ)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextIn; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETOPTR: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ cinfo.bytes = controller->total_bytes; -+ cinfo.blocks = controller->blocks; -+ cinfo.ptr = controller->nextOut; -+ controller->blocks = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -+ case SNDCTL_DSP_GETODELAY: -+ if (!(file->f_mode & FMODE_WRITE)) -+ return -EINVAL; -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ unfinish = 0; -+ fullc = elements_in_queue(&out_full_queue); -+ busyc = elements_in_queue(&out_busy_queue); -+ for(i = 0;i < fullc ;i ++) { -+ id = *(out_full_queue.id + i); -+ unfinish += *(out_dma_buf_data_count + id); -+ } -+ for(i = 0;i < busyc ;i ++) { -+ id = *(out_busy_queue.id + i); -+ unfinish += get_dma_residue(controller->dma1); -+ } -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ return put_user(unfinish, (int *) arg); -+ case SOUND_PCM_READ_RATE: -+ return put_user(jz_audio_rate, (int *)arg); -+ case SOUND_PCM_READ_CHANNELS: -+ return put_user(jz_audio_channels, (int *)arg); -+ case SOUND_PCM_READ_BITS: -+ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -+ case SNDCTL_DSP_MAPINBUF: -+ case SNDCTL_DSP_MAPOUTBUF: -+ case SNDCTL_DSP_SETSYNCRO: -+ case SOUND_PCM_WRITE_FILTER: -+ case SOUND_PCM_READ_FILTER: -+ return -EINVAL; -+ } -+ return -EINVAL; -+} -+ -+static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -+{ -+ unsigned long flags; -+ unsigned int mask = 0; -+ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ return POLLOUT | POLLWRNORM; -+ poll_wait(file, &controller->dac_wait, wait); -+ } -+ -+ if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ return POLLIN | POLLRDNORM; -+ poll_wait(file, &controller->adc_wait, wait); -+ } -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ if (file->f_mode & FMODE_WRITE) { -+ if (elements_in_queue(&out_empty_queue) > 0) -+ mask |= POLLOUT | POLLWRNORM; -+ } else if (file->f_mode & FMODE_READ) { -+ if (elements_in_queue(&in_full_queue) > 0) -+ mask |= POLLIN | POLLRDNORM; -+ } -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ return mask; -+} -+ -+static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -+{ -+ int id, ret = 0, left_count, copy_count, cnt = 0; -+ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -+ -+ if (count < 0) -+ return -EINVAL; -+ -+ __pcm_enable_receive_dma(); -+ __pcm_enable_rxfifo(); -+ -+ spin_lock(&controller->ioctllock); -+ controller->nextIn = 0; -+ spin_unlock(&controller->ioctllock); -+ -+ spin_lock(&controller->lock); -+ -+#if 0 -+ if (count < 2 * PAGE_SIZE ) -+ copy_count = count * 16 / (jz_audio_channels * jz_audio_format); -+ else -+ copy_count = 2 * PAGE_SIZE ; -+#else -+ if (count <= jz_audio_fragsize) -+ copy_count = count; -+ else -+ copy_count = jz_audio_fragsize; -+#endif -+ -+ left_count = count; -+ spin_unlock(&controller->lock); -+ -+ if (first_record_call) { -+ first_record_call = 0; -+audio_read_back_first: -+ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count; -+ spin_unlock(&controller->lock); -+ -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ -+ sleep_on(&rx_wait_queue); -+ } else -+ goto audio_read_back_first; -+ } -+ -+ while (left_count > 0) { -+audio_read_back_second: -+ if (elements_in_queue(&in_full_queue) <= 0) { -+ if (file->f_flags & O_NONBLOCK) -+ return ret ? ret : -EAGAIN; -+ else -+ sleep_on(&rx_wait_queue); -+ } -+ -+ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -+ spin_lock(&controller->lock); -+ cnt = record_filler((unsigned long)controller->tmp1+ret, copy_count, id); -+ spin_unlock(&controller->lock); -+ put_buffer_id(&in_empty_queue, id); -+ } else -+ goto audio_read_back_second; -+ -+ if (elements_in_queue(&in_busy_queue) == 0) { -+ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -+ put_buffer_id(&in_busy_queue, id); -+ spin_lock(&controller->lock); -+ *(in_dma_buf_data_count + id) = copy_count; -+ spin_unlock(&controller->lock); -+ -+ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -+ audio_start_dma(controller->dma2,file->private_data, -+ *(in_dma_pbuf + id), -+ *(in_dma_buf_data_count + id), -+ DMA_MODE_READ); -+ } -+ } -+ if (ret + cnt > count) { -+ spin_lock(&controller->lock); -+ cnt = count - ret; -+ spin_unlock(&controller->lock); -+ } -+ if (copy_to_user(buffer+ret, controller->tmp1+ret, cnt)) -+ return ret ? ret : -EFAULT; -+ spin_lock(&controller->lock); -+ ret += cnt; -+ spin_unlock(&controller->lock); -+ -+ spin_lock(&controller->ioctllock); -+ controller->nextIn += ret; -+ spin_unlock(&controller->ioctllock); -+ -+ spin_lock(&controller->lock); -+ left_count -= cnt; -+ spin_unlock(&controller->lock); -+ } -+ -+ return ret; -+} -+ -+static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -+{ -+ int id, ret, left_count, copy_count; -+ unsigned int flags; -+ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -+ -+ if (count <= 0) -+ return -EINVAL; -+ -+ __pcm_enable_transmit_dma(); -+ __pcm_enable_txfifo(); -+ -+ spin_lock_irqsave(&controller->ioctllock, flags); -+ controller->nextOut = 0; -+ spin_unlock_irqrestore(&controller->ioctllock, flags); -+ -+#if 0 -+ if (count < 2 * PAGE_SIZE ) -+ copy_count = count; -+ else -+ copy_count = 2 * PAGE_SIZE; -+#else -+ if (count <= jz_audio_fragsize) -+ copy_count = count; -+ else -+ copy_count = jz_audio_fragsize; -+#endif -+ -+ left_count = count; -+ ret = 0; -+ -+ if (copy_from_user(controller->tmp1, buffer, count)) { -+ printk("copy_from_user failed:%d",ret); -+ return ret ? ret : -EFAULT; -+ } -+ -+ while (left_count > 0) { -+audio_write_back: -+ if (elements_in_queue(&out_empty_queue) == 0) { -+ // all are full -+ if (file->f_flags & O_NONBLOCK) -+ return ret; -+ else -+ sleep_on(&tx_wait_queue); -+ } -+ /* the end fragment size in this write */ -+ if (ret + copy_count > count) -+ copy_count = count - ret; -+ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -+ replay_filler((unsigned long)controller->tmp1 + ret, copy_count, id); -+ if(*(out_dma_buf_data_count + id) > 0) { -+ put_buffer_id(&out_full_queue, id); //busy in -+ dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); -+ } else -+ put_buffer_id(&out_empty_queue, id); //spare -+ } else -+ goto audio_write_back; -+ -+ left_count = left_count - copy_count; -+ ret += copy_count;//all is in byte -+ -+ spin_lock(&controller->ioctllock); -+ controller->nextOut += ret; -+ spin_unlock(&controller->ioctllock); -+ -+ if (elements_in_queue(&out_busy_queue) == 0) { -+ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -+ put_buffer_id(&out_busy_queue, id); -+ -+ if(*(out_dma_buf_data_count + id) > 0) { -+ audio_start_dma(controller->dma1, -+ file->private_data, -+ *(out_dma_pbuf + id), -+ *(out_dma_buf_data_count + id), -+ DMA_MODE_WRITE); -+ -+ } -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+static void dump_pcmc_reg(void) -+{ -+ printk("REG_DMAC_DMACKE(0) : 0x%08x\n",REG_DMAC_DMACKE(0)); -+ printk("REG_DMAC_DMACKE(1) : 0x%08x\n",REG_DMAC_DMACKE(1)); -+ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -+ printk("REG_CPM_CPCCR : 0x%08x\n",REG_CPM_CPCCR); -+ printk("REG_CPM_PCMCDR : 0x%08x\n",REG_CPM_PCMCDR); -+ printk("REG_PCM_CLT : 0x%08x\n",REG_PCM_CTL); -+ printk("REG_PCM_CFG : 0x%08x\n",REG_PCM_CFG); -+ printk("REG_PCM_INTC : 0x%08x\n",REG_PCM_INTC); -+ printk("REG_PCM_INTS : 0x%08x\n",REG_PCM_INTS); -+ printk("REG_PCM_DIV : 0x%08x\n",REG_PCM_DIV); -+} -diff --git a/sound/oss/jzcodec.c b/sound/oss/jzcodec.c -new file mode 100644 -index 0000000..680b1d2 ---- /dev/null -+++ b/sound/oss/jzcodec.c -@@ -0,0 +1,443 @@ -+/* -+ * linux/drivers/sound/jzcodec.c -+ * -+ * JzSOC internal audio driver. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sound_config.h" -+ -+#define USE_NONE 1 -+#define USE_MIC 2 -+#define USE_LINEIN 3 -+ -+typedef struct hpvol_shift_s -+{ -+ int hpvol; -+ int shift; -+} hpvol_shift_t; -+ -+extern mixer_info info; -+extern _old_mixer_info old_info; -+extern int codec_volue_shift; -+extern hpvol_shift_t hpvol_shift_table[72]; -+extern int abnormal_data_count; -+ -+extern void (*set_codec_mode)(void); -+extern void (*each_time_init_codec)(void); -+extern int (*set_codec_startup_param)(void); -+extern void (*set_codec_volume_table)(void); -+extern void (*set_codec_record)(int mode); -+extern void (*set_codec_replay)(void); -+extern void (*set_codec_replay_record)(int mode); -+extern void (*turn_on_codec)(void); -+extern void (*turn_off_codec)(void); -+extern void (*set_codec_speed)(int rate); -+extern void (*reset_codec)(void); -+extern void (*codec_mixer_old_info_id_name)(void); -+extern void (*codec_mixer_info_id_name)(void); -+extern void (*set_codec_bass)(int val); -+extern void (*set_codec_volume)(int val); -+extern void (*set_codec_mic)(int val); -+extern void (*set_codec_line)(int val); -+extern void (*i2s_resume_codec)(void); -+extern void (*i2s_suspend_codec)(void); -+extern void (*set_codec_direct_mode)(void); -+extern void (*clear_codec_direct_mode)(void); -+ -+static int jzcodec_reg[2]; -+ -+void set_jzcodec_mode(void); -+void each_time_init_jzcodec(void); -+int set_jzcodec_startup_param(void); -+void set_jzcodec_volume_table(void); -+void set_jzcodec_replay(void); -+void set_jzcodec_record(int mode); -+void turn_on_jzcodec(void); -+void turn_off_jzcodec(void); -+void set_jzcodec_speed(int rate); -+void reset_jzcodec(void); -+void jzcodec_mixer_old_info_id_name(void); -+void jzcodec_mixer_info_id_name(void); -+void set_jzcodec_bass(int val); -+void set_jzcodec_volume(int val); -+void set_jzcodec_mic(int val); -+void set_jzcodec_line(int val); -+void in_codec_app1(void); -+void in_codec_app12(void); -+void HP_turn_on(void); -+void HP_turn_off(void); -+void resume_jzcodec(void); -+void suspend_jzcodec(void); -+void set_jzcodec_replay_record(int mode); -+ -+void set_jzcodec_mode(void) -+{ -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ -+ REG_ICDC_CDCCR1 = 0x001b2303; -+ schedule_timeout(1); -+ REG_ICDC_CDCCR1 = 0x001b2302; -+} -+ -+void each_time_init_jzcodec(void) -+{ -+ __i2s_disable(); -+ __i2s_as_slave(); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+} -+ -+int set_jzcodec_startup_param(void) -+{ -+ REG_ICDC_CDCCR1 = 0x001b2300; -+ schedule_timeout(50); -+ REG_ICDC_CDCCR1 = 0x00033300; -+ schedule_timeout(5); -+ REG_ICDC_CDCCR1 = 0x17026300; -+ -+ return 1; -+} -+void set_jzcodec_volume_table(void) -+{ -+ int errno,hpvol_step,sample_shift; -+ -+ codec_volue_shift = 0; -+ hpvol_step = 3; -+ sample_shift = 0; -+ for(errno = 0;errno < 72;errno++) { -+ hpvol_shift_table[errno].hpvol = hpvol_step; -+ hpvol_shift_table[errno].shift = sample_shift; -+ hpvol_step --; -+ if(hpvol_step <= 0) { -+ hpvol_step = 3; -+ sample_shift ++; -+ } -+ } -+} -+ -+void set_jzcodec_replay(void) -+{ -+ in_codec_app1(); -+} -+ -+void set_jzcodec_record(int mode) -+{ -+ switch (mode) { -+ case USE_NONE: -+ case USE_MIC: -+ in_codec_app12(); -+ abnormal_data_count = 0; -+ break; -+ case USE_LINEIN: -+ REG_ICDC_CDCCR1 = 0x27022000;//for linein -+ mdelay(300); -+ break; -+ } -+} -+ -+void set_jzcodec_replay_record(int mode) -+{ -+ long val = 0; -+ REG_ICDC_CDCCR1 = 0x00037302; -+ mdelay(2); -+ REG_ICDC_CDCCR1 = 0x03006000; -+ mdelay(2); -+ -+ switch (mode) { -+ case USE_NONE: -+ case USE_MIC: -+ REG_ICDC_CDCCR1 = 0x17022000;//for mic -+ break; -+ case USE_LINEIN: -+ REG_ICDC_CDCCR1 = 0x27022000;//for linein -+ break; -+ } -+ -+ val = REG_ICDC_CDCCR2; -+ val &= 0x0000ff00; -+ val |= 0x00170030; -+ REG_ICDC_CDCCR2 = val; -+} -+ -+void turn_on_jzcodec(void) -+{ -+ HP_turn_on(); -+} -+ -+void set_jzcodec_direct_mode(void) -+{ -+ long val = 0; -+ REG_ICDC_CDCCR1 = 0x14000000; -+ val &= 0x0000ff00; -+ val |= 0x001f0033; -+ REG_ICDC_CDCCR2 = val; -+ mdelay(300); -+} -+ -+void clear_jzcodec_direct_mode(void) -+{ -+ HP_turn_off(); -+} -+ -+void turn_off_jzcodec(void) -+{ -+ HP_turn_off(); -+} -+ -+void set_jzcodec_speed(int rate) -+{ -+ long codec_speed,speed = 0; -+ switch (rate) { -+ case 8000: -+ speed = 0; -+ break; -+ case 11025: -+ speed = 1; -+ break; -+ case 12000: -+ speed = 2; -+ break; -+ case 16000: -+ speed = 3; -+ break; -+ case 22050: -+ speed = 4; -+ break; -+ case 24000: -+ speed = 5; -+ break; -+ case 32000: -+ speed = 6; -+ break; -+ case 44100: -+ speed = 7; -+ break; -+ case 48000: -+ speed = 8; -+ break; -+ default: -+ break; -+ } -+ -+ codec_speed = REG_ICDC_CDCCR2; -+ codec_speed |= 0x00000f00; -+ -+ speed = speed << 8; -+ speed |= 0xfffff0ff; -+ codec_speed &= speed; -+ REG_ICDC_CDCCR2 = codec_speed; -+} -+ -+void reset_jzcodec(void) -+{ -+ REG_ICDC_CDCCR1 |= 1; -+ mdelay(1); -+ REG_ICDC_CDCCR1 &= 0xfffffffe; -+} -+ -+void jzcodec_mixer_old_info_id_name(void) -+{ -+ strncpy(info.id, "JZCODEC", sizeof(info.id)); -+ strncpy(info.name,"Jz internal codec", sizeof(info.name)); -+} -+ -+void jzcodec_mixer_info_id_name(void) -+{ -+ strncpy(old_info.id, "JZCODEC", sizeof(old_info.id)); -+ strncpy(old_info.name,"Jz internal codec", sizeof(old_info.name)); -+} -+ -+void set_jzcodec_bass(int val) -+{ -+ int bass_gain = 0; -+ if(val < 25) -+ bass_gain = 0; -+ if(val >= 25 && val < 50) -+ bass_gain = 1; -+ if(val >= 50 && val < 75) -+ bass_gain = 2; -+ if(val >= 75 && val <= 100 ) -+ bass_gain = 3; -+ -+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3 << 4)) | (bass_gain << 4)); -+} -+ -+void set_jzcodec_volume(int val) -+{ -+ unsigned int sample_oss; -+ int index,shift_max,vol_scale,vol_step,codec_volume; -+ shift_max = 0; -+ sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -+ -+ switch(sample_oss) -+ { -+ case 0x0: -+ shift_max = 4; /* 8 bits */ -+ break; -+ case 0x1: -+ shift_max = 10; /* 16 bits */ -+ break; -+ case 0x2: -+ shift_max = 12; /* 18 bits */ -+ break; -+ case 0x3: -+ shift_max = 15; /* 20 bits */ -+ break; -+ case 0x4: -+ shift_max = 19; /* 24 bits */ -+ break; -+ } -+ -+ vol_scale = 3 * (shift_max + 1); -+ vol_step = 100 / vol_scale; -+ -+ for(index = 0;index <= 100;index += vol_step) -+ if( val <= index ) -+ break; -+ -+ if(index == 0) -+ index = vol_step; -+ index = index / vol_step; -+ if(index > vol_scale) -+ index = vol_scale; -+ -+ index = vol_scale - index; -+ codec_volume = hpvol_shift_table[index].hpvol; -+ codec_volue_shift = hpvol_shift_table[index].shift; -+ codec_volume = 3; -+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | codec_volume); -+} -+ -+void set_jzcodec_mic(int val) -+{ -+ long mic_gain; -+ -+ mic_gain = 31 * val /100; -+ REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 | (0x3 << 4)); -+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (mic_gain << 16)); -+} -+ -+void set_jzcodec_line(int val) -+{ -+ long line_gain; -+ -+ line_gain = 31 * val /100; -+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (line_gain << 16)); -+} -+ -+void HP_turn_on(void) -+{ -+ long val = 0; -+ /* simple and slow anti-pop */ -+ REG_ICDC_CDCCR1 = 0x00037302; -+ mdelay(2); -+ REG_ICDC_CDCCR1 = 0x03006000; -+ mdelay(2); -+ REG_ICDC_CDCCR1 = 0x03002000; -+ -+ val = REG_ICDC_CDCCR2; -+ val &= 0x0000ff00; -+ val |= 0x001f0033; -+ REG_ICDC_CDCCR2 = val; -+} -+ -+void HP_turn_off(void) -+{ -+ mdelay(20); -+ REG_ICDC_CDCCR1 = 0x00033300; -+} -+ -+void in_codec_app1(void) -+{ -+ /* test is OK */ -+ HP_turn_on(); -+} -+ -+void in_codec_app12(void) -+{ -+ REG_ICDC_CDCCR1 = 0x14024300; -+ mdelay(300); -+} -+ -+void resume_jzcodec(void) -+{ -+ REG_ICDC_CDCCR2 = 0x00170800; -+ mdelay(2); -+ REG_ICDC_CDCCR1 = 0x001f2102; -+ mdelay(5); -+ REG_ICDC_CDCCR1 = 0x00033302; -+ mdelay(550); -+ REG_ICDC_CDCCR1 = 0x00033300; -+ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -+ REG_ICDC_CDCCR2 = jzcodec_reg[1]; -+} -+ -+void suspend_jzcodec(void) -+{ -+ -+ jzcodec_reg[0] = REG_ICDC_CDCCR1; -+ jzcodec_reg[1] = REG_ICDC_CDCCR2; -+ -+ REG_ICDC_CDCCR1 = 0x001b2302; -+ mdelay(1); -+ REG_ICDC_CDCCR1 = 0x001b2102; -+} -+ -+static int __init init_jzcodec(void) -+{ -+ set_codec_mode = set_jzcodec_mode; -+ each_time_init_codec = each_time_init_jzcodec; -+ -+ set_codec_startup_param = set_jzcodec_startup_param; -+ set_codec_volume_table = set_jzcodec_volume_table; -+ set_codec_record = set_jzcodec_record; -+ set_codec_replay = set_jzcodec_replay; -+ set_codec_replay_record = set_jzcodec_replay_record; -+ turn_on_codec = turn_on_jzcodec; -+ turn_off_codec = turn_off_jzcodec; -+ set_codec_speed = set_jzcodec_speed; -+ reset_codec = reset_jzcodec; -+ codec_mixer_old_info_id_name = jzcodec_mixer_old_info_id_name; -+ codec_mixer_info_id_name = jzcodec_mixer_info_id_name; -+ set_codec_bass = set_jzcodec_bass; -+ set_codec_volume = set_jzcodec_volume; -+ set_codec_mic = set_jzcodec_mic; -+ set_codec_line = set_jzcodec_line; -+ i2s_resume_codec = resume_jzcodec; -+ i2s_suspend_codec = suspend_jzcodec; -+ set_codec_direct_mode = set_jzcodec_direct_mode; -+ clear_codec_direct_mode = clear_jzcodec_direct_mode; -+ -+ return 0; -+} -+ -+ -+static void __exit cleanup_jzcodec(void) -+{ -+ REG_ICDC_CDCCR1 = 0x001b2302; -+ -+} -+ -+module_init(init_jzcodec); -+module_exit(cleanup_jzcodec); -diff --git a/sound/oss/jzdlv.c b/sound/oss/jzdlv.c -new file mode 100644 -index 0000000..772b12f ---- /dev/null -+++ b/sound/oss/jzdlv.c -@@ -0,0 +1,644 @@ -+/* -+ * linux/drivers/sound/jzcodec.c -+ * -+ * JzSOC internal audio driver. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sound_config.h" -+#include "jzdlv.h" -+ -+#define USE_NONE 1 -+#define USE_MIC 2 -+#define USE_LINEIN 3 -+ -+extern mixer_info info; -+extern _old_mixer_info old_info; -+extern int codec_volue_shift; -+ -+extern void (*set_codec_mode)(void); -+extern void (*each_time_init_codec)(void); -+extern int (*set_codec_startup_param)(void); -+extern void (*set_codec_record)(void); -+extern void (*set_codec_replay)(void); -+extern void (*set_codec_replay_record)(void); -+extern void (*turn_on_codec)(void); -+extern void (*turn_off_codec)(void); -+extern void (*set_codec_speed)(int rate); -+extern void (*reset_codec)(void); -+extern void (*codec_mixer_old_info_id_name)(void); -+extern void (*codec_mixer_info_id_name)(void); -+extern void (*set_codec_bass)(int val); -+extern void (*set_codec_volume)(int val); -+extern void (*set_codec_mic)(int val); -+extern void (*set_codec_line)(int val); -+extern void (*i2s_resume_codec)(void); -+extern void (*i2s_suspend_codec)(void); -+extern void (*set_codec_direct_mode)(void); -+extern void (*clear_codec_direct_mode)(void); -+ -+ -+void set_dlv_mode(void); -+void each_time_init_jzcodec(void); -+int set_dlv_startup_param(void); -+void set_dlvjzcodec_volume_table(void); -+void set_dlv_replay(void); -+void set_dlv_record(void); -+void set_dlv_speed(int rate); -+void reset_dlv(void); -+void jzcodec_mixer_old_info_id_name(void); -+void jzcodec_mixer_info_id_name(void); -+void set_dlv_volume(int val); -+void set_dlv_mic(int val); -+ -+extern int jz_mic_only; -+int read_codec_file(int addr) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ return(__icdc_get_value()); -+} -+ -+#if 0 -+void printk_codec_files(void) -+{ -+ int cnt; -+ -+ printk("\n"); -+ -+ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -+ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -+ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -+ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -+ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -+ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -+ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -+ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -+ -+ for (cnt = 0; cnt <= 27 ; cnt++) { -+ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -+ } -+ printk("\n"); -+} -+#endif -+ -+void write_codec_file(int addr, int val) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+} -+ -+int write_codec_file_bit(int addr, int bitval, int mask_bit) -+{ -+ int val; -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ val = __icdc_get_value(); /* read */ -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val &= ~(1 << mask_bit); -+ if (bitval == 1) -+ val |= 1 << mask_bit; -+ -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val = __icdc_get_value(); /* read */ -+ -+ if (((val >> mask_bit) & bitval) == bitval) -+ return 1; -+ else -+ return 0; -+} -+void set_dlv_mode(void) -+{ -+ /*REG_CPM_CPCCR &= ~(1 << 31); -+ REG_CPM_CPCCR &= ~(1 << 30);*/ -+ write_codec_file(0, 0xf); -+ -+ REG_AIC_I2SCR = 0x10; -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ __aic_reset(); -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ -+ /* power on DLV */ -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+} -+void reset_dlv_codec(void) -+{ -+ /* reset DLV codec. from hibernate mode to sleep mode */ -+ write_codec_file(0, 0xf); -+ write_codec_file_bit(6, 0, 0); -+ write_codec_file_bit(6, 0, 1); -+ mdelay(200); -+ //write_codec_file(0, 0xf); -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 -+ mdelay(10);//wait for stability -+} -+ -+void each_time_init_dlv(void) -+{ -+ __i2s_disable(); -+ __i2s_as_slave(); -+ __aic_internal_codec(); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+} -+ -+int set_dlv_startup_param(void) -+{ -+ __i2s_disable_transmit_intr(); -+ __i2s_disable_receive_intr(); -+ -+ return 1; -+} -+/* set Audio data replay */ -+void set_audio_data_replay(void) -+{ -+ /* DAC path */ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ //mdelay(100); -+ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //mdelay(300); -+} -+ -+#if 1 /* mask warning */ -+/* set Record MIC input audio without playback */ -+void set_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2); -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ -+ write_codec_file(22, 0x40);//mic 1 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ //write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+#endif -+ -+#if 1 /* mask warning */ -+/* unset Record MIC input audio without playback */ -+void unset_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record LINE input audio without playback */ -+void set_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ jz_mic_only = 1; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ mdelay(10); -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record LINE input audio without playback */ -+void unset_record_line_input_audio_without_playback(void) -+{ -+ /* ADC path for LINE IN */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -+ -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Playback LINE input audio direct only */ -+void set_playback_line_input_audio_direct_only(void) -+{ -+ jz_audio_reset();//or init_codec() -+ REG_AIC_I2SCR = 0x10; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ write_codec_file(22, 0xf6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ mdelay(10); -+ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -+ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Playback LINE input audio direct only */ -+void unset_playback_line_input_audio_direct_only(void) -+{ -+ write_codec_file_bit(6, 0, 3);//GIM->0 -+ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ mdelay(100); -+ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record MIC input audio with direct playback */ -+void set_record_mic_input_audio_with_direct_playback(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ jz_mic_only = 0; -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ mdelay(10); -+ -+ write_codec_file(22, 0x60);//mic 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ //write_codec_file(1, 0x4); -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record MIC input audio with direct playback */ -+void unset_record_mic_input_audio_with_direct_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ jz_mic_only = 0; -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* set Record playing audio mixed with MIC input audio */ -+void set_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ mdelay(10); -+ -+ write_codec_file(22, 0x63);//mic 1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -+} -+#endif -+ -+#if 0 /* mask warning */ -+/* unset Record playing audio mixed with MIC input audio */ -+void unset_record_playing_audio_mixed_with_mic_input_audio(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 1 /* mask warning */ -+/* set Record MIC input audio with Audio data replay (full duplex) */ -+void set_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+#endif -+ -+#if 1 /* mask warning */ -+/* unset Record MIC input audio with Audio data replay (full duplex) */ -+void unset_record_mic_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 1 /* mask warning */ -+/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -+void set_record_line_input_audio_with_audio_data_replay(void) -+{ -+ write_codec_file(9, 0xff); -+ //write_codec_file(8, 0x30); -+ write_codec_file(8, 0x20); -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ -+ -+ //jz_mic_only = 1; -+ write_codec_file(22, 0xc6);//line in 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+} -+#endif -+ -+#if 1 /* mask warning */ -+/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -+void unset_record_line_input_audio_with_audio_data_replay(void) -+{ -+ /* ADC path */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+#if 1 -+/* unset Audio data replay */ -+void unset_audio_data_replay(void) -+{ -+ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ //mdelay(800); -+ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ //mdelay(800); -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+} -+#endif -+ -+void set_dlv_replay(void) -+{ -+ set_audio_data_replay(); -+} -+ -+void set_dlv_speed(int rate) -+{ -+ int speed = 0, val; -+ speed = 0; -+ switch (rate) { -+ case 8000: -+ speed = 10; -+ break; -+ case 9600: -+ speed = 9; -+ break; -+ case 11025: -+ speed = 8; -+ break; -+ case 12000: -+ speed = 7; -+ break; -+ case 16000: -+ speed = 6; -+ break; -+ case 22050: -+ speed = 5; -+ break; -+ case 24000: -+ speed = 4; -+ break; -+ case 32000: -+ speed = 3; -+ break; -+ case 44100: -+ speed = 2; -+ break; -+ case 48000: -+ speed = 1; -+ break; -+ case 96000: -+ speed = 0; -+ break; -+ default: -+ break; -+ } -+ -+ val = read_codec_file(4); -+ val = (speed << 4) | speed; -+ write_codec_file(4, val); -+} -+ -+void reset_jzcodec(void) -+{ -+ -+} -+ -+void dlv_mixer_old_info_id_name(void) -+{ -+ strncpy(info.id, "JZDLV", sizeof(info.id)); -+ strncpy(info.name,"Jz internal codec dlv on jz4750", sizeof(info.name)); -+} -+ -+void dlv_mixer_info_id_name(void) -+{ -+ strncpy(old_info.id, "JZDLV", sizeof(old_info.id)); -+ strncpy(old_info.name,"Jz internal codec dlv on jz4750", sizeof(old_info.name)); -+} -+ -+void set_dlv_mic(int val) -+{ -+ int cur_vol ; -+ /* set gain */ -+ //write_codec_file_bit(6, 1, 3);//GIM -+ cur_vol = 31 * val / 100; -+ cur_vol |= cur_vol << 4; -+ write_codec_file(19, cur_vol);//GIL,GIR -+} -+ -+void set_dlv_line(int val) -+{ -+ int cur_vol; -+ /* set gain */ -+ cur_vol = 31 * val / 100; -+ cur_vol &= 0x1f; -+ write_codec_file(11, cur_vol);//GO1L -+ write_codec_file(12, cur_vol);//GO1R -+} -+ -+void set_dlv_volume(int val) -+{ -+ unsigned long cur_vol; -+ cur_vol = 31 * (100 - val) / 100; -+ write_codec_file(17, cur_vol | 0xc0); -+ write_codec_file(18, cur_vol); -+} -+ -+static int __init init_dlv(void) -+{ -+ set_codec_mode = set_dlv_mode; -+ each_time_init_codec = each_time_init_dlv; -+ reset_codec = reset_dlv_codec; -+ set_codec_startup_param = set_dlv_startup_param; -+ -+ set_codec_replay = set_dlv_replay; -+ -+ set_codec_speed = set_dlv_speed; -+ -+ codec_mixer_old_info_id_name = dlv_mixer_old_info_id_name; -+ codec_mixer_info_id_name = dlv_mixer_info_id_name; -+ -+ set_codec_volume = set_dlv_volume; -+ set_codec_mic = set_dlv_mic; -+ set_codec_line = set_dlv_line; -+ -+ return 0; -+} -+ -+ -+static void __exit cleanup_dlv(void) -+{ -+ -+} -+ -+module_init(init_dlv); -+module_exit(cleanup_dlv); -diff --git a/sound/oss/jzdlv.h b/sound/oss/jzdlv.h -new file mode 100644 -index 0000000..450e7ea ---- /dev/null -+++ b/sound/oss/jzdlv.h -@@ -0,0 +1,21 @@ -+/* header file for dlv */ -+void write_codec_file(int addr, int val); -+int read_codec_file(int addr); -+void printk_codec_files(void); -+int write_codec_file_bit(int addr, int bitval, int mask_bit); -+void set_audio_data_replay(void); -+void unset_audio_data_replay(void); -+void set_record_mic_input_audio_without_playback(void); -+void unset_record_mic_input_audio_without_playback(void); -+void set_record_line_input_audio_without_playback(void); -+void unset_record_line_input_audio_without_playback(void); -+void set_playback_line_input_audio_direct_only(void); -+void unset_playback_line_input_audio_direct_only(void); -+void set_record_mic_input_audio_with_direct_playback(void); -+void unset_record_mic_input_audio_with_direct_playback(void); -+void set_record_playing_audio_mixed_with_mic_input_audio(void); -+void unset_record_playing_audio_mixed_with_mic_input_audio(void); -+void set_record_mic_input_audio_with_audio_data_replay(void); -+void unset_record_mic_input_audio_with_audio_data_replay(void); -+void set_record_line_input_audio_with_audio_data_replay(void); -+void unset_record_line_input_audio_with_audio_data_replay(void); -diff --git a/sound/oss/os.h b/sound/oss/os.h -index a1a962d..2fb00ab 100644 ---- a/sound/oss/os.h -+++ b/sound/oss/os.h -@@ -9,7 +9,6 @@ - #ifdef __KERNEL__ - #include - #include --#include - #include - #include - #include -diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig -index d3e786a..e827f85 100644 ---- a/sound/soc/Kconfig -+++ b/sound/soc/Kconfig -@@ -35,6 +35,8 @@ source "sound/soc/s3c24xx/Kconfig" - source "sound/soc/s6000/Kconfig" - source "sound/soc/sh/Kconfig" - source "sound/soc/txx9/Kconfig" -+source "sound/soc/jz4740/Kconfig" -+source "sound/soc/jz4750/Kconfig" - - # Supported codecs - source "sound/soc/codecs/Kconfig" -diff --git a/sound/soc/Makefile b/sound/soc/Makefile -index 6f1e28d..6d72e6d 100644 ---- a/sound/soc/Makefile -+++ b/sound/soc/Makefile -@@ -13,3 +13,5 @@ obj-$(CONFIG_SND_SOC) += s3c24xx/ - obj-$(CONFIG_SND_SOC) += s6000/ - obj-$(CONFIG_SND_SOC) += sh/ - obj-$(CONFIG_SND_SOC) += txx9/ -+obj-$(CONFIG_SND_SOC) += jz4740/ -+obj-$(CONFIG_SND_SOC) += jz4750/ -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index bbc97fd..c5dea8c 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -176,3 +176,14 @@ config SND_SOC_WM9712 - - config SND_SOC_WM9713 - tristate -+config SND_SOC_ICODEC -+ tristate "Jz4740 internal codec" -+ depends on SND_SOC && SND_JZ4740_SOC_PAVO && SND_JZ4740_SOC_I2S -+ help -+ Say Y if you want to use internal codec on Ingenic Jz4740 PAVO board. -+ -+config SND_SOC_DLV -+ tristate "Jz4750 internal codec" -+ depends on SND_SOC && SND_JZ4750_SOC_APUS && SND_JZ4750_SOC_I2S -+ help -+ Say Y if you want to use internal codec on Ingenic Jz4750 APUS board. -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 8b75305..7f53f57 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -4,6 +4,8 @@ snd-soc-ad73311-objs := ad73311.o - snd-soc-ak4104-objs := ak4104.o - snd-soc-ak4535-objs := ak4535.o - snd-soc-cs4270-objs := cs4270.o -+snd-soc-jzcodec-objs := jzcodec.o -+snd-soc-jzdlv-objs := jzdlv.o - snd-soc-l3-objs := l3.o - snd-soc-pcm3008-objs := pcm3008.o - snd-soc-spdif-objs := spdif_transciever.o -@@ -41,6 +43,8 @@ obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o - obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o - obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o - obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o -+obj-$(CONFIG_SND_SOC_ICODEC) += snd-soc-jzcodec.o -+obj-$(CONFIG_SND_SOC_DLV) += snd-soc-jzdlv.o - obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o - obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o - obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o -diff --git a/sound/soc/codecs/jzcodec.c b/sound/soc/codecs/jzcodec.c -new file mode 100644 -index 0000000..f922845 ---- /dev/null -+++ b/sound/soc/codecs/jzcodec.c -@@ -0,0 +1,729 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../jz4740/jz4740-pcm.h" -+#include "jzcodec.h" -+ -+#define AUDIO_NAME "jzcodec" -+#define JZCODEC_VERSION "1.0" -+ -+/* -+ * Debug -+ */ -+ -+#define JZCODEC_DEBUG 0 -+ -+#ifdef JZCODEC_DEBUG -+#define dbg(format, arg...) \ -+ printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) do {} while (0) -+#endif -+#define err(format, arg...) \ -+ printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) -+#define info(format, arg...) \ -+ printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -+#define warn(format, arg...) \ -+ printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) -+ -+struct snd_soc_codec_device soc_codec_dev_jzcodec; -+ -+/* codec private data */ -+struct jzcodec_priv { -+ unsigned int sysclk; -+}; -+ -+/* -+ * jzcodec register cache -+ */ -+static u32 jzcodec_reg[JZCODEC_CACHEREGNUM / 2]; -+ -+/* -+ * codec register is 16 bits width in ALSA, so we define array to store 16 bits configure paras -+ */ -+static u16 jzcodec_reg_LH[JZCODEC_CACHEREGNUM]; -+ -+/* -+ * read jzcodec register cache -+ */ -+static inline unsigned int jzcodec_read_reg_cache(struct snd_soc_codec *codec, -+ unsigned int reg) -+{ -+ u16 *cache = codec->reg_cache; -+ -+ if (reg >= JZCODEC_CACHEREGNUM) -+ return -1; -+ return cache[reg]; -+} -+ -+/* -+ * write jzcodec register cache -+ */ -+static inline void jzcodec_write_reg_cache(struct snd_soc_codec *codec, -+ unsigned int reg, u16 value) -+{ -+ u16 *cache = codec->reg_cache; -+ u32 reg_val; -+ -+ if (reg >= JZCODEC_CACHEREGNUM) { -+ return; -+ } -+ -+ cache[reg] = value; -+ /* update internal codec register value */ -+ switch (reg) { -+ case 0: -+ case 1: -+ reg_val = cache[0] & 0xffff; -+ reg_val = reg_val | (cache[1] << 16); -+ jzcodec_reg[0] = reg_val; -+ break; -+ case 2: -+ case 3: -+ reg_val = cache[2] & 0xffff; -+ reg_val = reg_val | (cache[3] << 16); -+ jzcodec_reg[1] = reg_val; -+ break; -+ } -+} -+ -+/* -+ * write to the jzcodec register space -+ */ -+static int jzcodec_write(struct snd_soc_codec *codec, unsigned int reg, -+ unsigned int value) -+{ -+ jzcodec_write_reg_cache(codec, reg, value); -+ if(codec->hw_write) -+ codec->hw_write(&value, NULL, reg); -+ return 0; -+} -+ -+static int jzcodec_reset(struct snd_soc_codec *codec) -+{ -+ u16 val; -+ -+ val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -+ val = val | 0x1; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ mdelay(1); -+ -+ val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -+ val = val & ~0x1; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ mdelay(1); -+ -+ return 0; -+} -+ -+static const struct snd_kcontrol_new jzcodec_snd_controls[] = { -+ -+ //SOC_DOUBLE_R("Master Playback Volume", 1, 1, 0, 3, 0), -+ SOC_DOUBLE_R("Master Playback Volume", ICODEC_2_LOW, ICODEC_2_LOW, 0, 3, 0), -+ //SOC_DOUBLE_R("MICBG", ICODEC_2_LOW, ICODEC_2_LOW, 4, 3, 0), -+ //SOC_DOUBLE_R("Line", 2, 2, 0, 31, 0), -+ SOC_DOUBLE_R("Line", ICODEC_2_HIGH, ICODEC_2_HIGH, 0, 31, 0), -+}; -+ -+/* add non dapm controls */ -+static int jzcodec_add_controls(struct snd_soc_codec *codec) -+{ -+ int err, i; -+ -+ for (i = 0; i < ARRAY_SIZE(jzcodec_snd_controls); i++) { -+ if ((err = snd_ctl_add(codec->card, -+ snd_soc_cnew(&jzcodec_snd_controls[i], codec, NULL))) < 0) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = { -+ SND_SOC_DAPM_OUTPUT("LOUT"), -+ SND_SOC_DAPM_OUTPUT("LHPOUT"), -+ SND_SOC_DAPM_OUTPUT("ROUT"), -+ SND_SOC_DAPM_OUTPUT("RHPOUT"), -+ SND_SOC_DAPM_INPUT("MICIN"), -+ SND_SOC_DAPM_INPUT("RLINEIN"), -+ SND_SOC_DAPM_INPUT("LLINEIN"), -+}; -+ -+static const char *intercon[][3] = { -+ /* output mixer */ -+ {"Output Mixer", "Line Bypass Switch", "Line Input"}, -+ {"Output Mixer", "HiFi Playback Switch", "DAC"}, -+ {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, -+ -+ /* outputs */ -+ {"RHPOUT", NULL, "Output Mixer"}, -+ {"ROUT", NULL, "Output Mixer"}, -+ {"LHPOUT", NULL, "Output Mixer"}, -+ {"LOUT", NULL, "Output Mixer"}, -+ -+ /* input mux */ -+ {"Input Mux", "Line In", "Line Input"}, -+ {"Input Mux", "Mic", "Mic Bias"}, -+ {"ADC", NULL, "Input Mux"}, -+ -+ /* inputs */ -+ {"Line Input", NULL, "LLINEIN"}, -+ {"Line Input", NULL, "RLINEIN"}, -+ {"Mic Bias", NULL, "MICIN"}, -+ -+ /* terminator */ -+ {NULL, NULL, NULL}, -+}; -+ -+static int jzcodec_add_widgets(struct snd_soc_codec *codec) -+{ -+ int i,cnt; -+ -+ cnt = ARRAY_SIZE(jzcodec_dapm_widgets); -+ for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) { -+ snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]); -+ } -+ -+ /* set up audio path interconnects */ -+ for(i = 0; intercon[i][0] != NULL; i++) { -+ snd_soc_dapm_connect_input(codec, intercon[i][0], -+ intercon[i][1], intercon[i][2]); -+ } -+ -+ snd_soc_dapm_new_widgets(codec); -+ return 0; -+} -+ -+static int jzcodec_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; -+ u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -+ -+ /* bit size. codec side */ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ break; -+ } -+ /* sample rate */ -+ reg_val = reg_val & ~(0xf << 8); -+ -+ switch (params_rate(params)) { -+ case 8000: -+ reg_val |= (0x0 << 8); -+ break; -+ case 11025: -+ reg_val |= (0x1 << 8); -+ break; -+ case 12000: -+ reg_val |= (0x2 << 8); -+ break; -+ case 16000: -+ reg_val |= (0x3 << 8); -+ break; -+ case 22050: -+ reg_val |= (0x4 << 8); -+ break; -+ case 24000: -+ reg_val |= (0x5 << 8); -+ break; -+ case 32000: -+ reg_val |= (0x6 << 8); -+ break; -+ case 44100: -+ reg_val |= (0x7 << 8); -+ break; -+ case 48000: -+ reg_val |= (0x8 << 8); -+ break; -+ default: -+ printk(" invalid rate :0x%08x\n",params_rate(params)); -+ } -+ -+ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -+ return 0; -+} -+ -+static int jzcodec_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ int ret = 0; -+ u16 val; -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ break; -+ -+ case SNDRV_PCM_TRIGGER_START: -+ //case SNDRV_PCM_TRIGGER_RESUME: -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ val = 0x7302; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ val = 0x0003; -+ jzcodec_write(codec, ICODEC_1_HIGH, val); -+ mdelay(2); -+ val = 0x6000; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ val = 0x0300; -+ jzcodec_write(codec, ICODEC_1_HIGH, val); -+ mdelay(2); -+ val = 0x2000; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ val = 0x0300; -+ jzcodec_write(codec, ICODEC_1_HIGH, val); -+ } else { -+ val = 0x4300; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ val = 0x1402; -+ jzcodec_write(codec, ICODEC_1_HIGH, val); -+ } -+ break; -+ -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ //case SNDRV_PCM_TRIGGER_SUSPEND: -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { -+ val = 0x3300; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ val = 0x0003; -+ jzcodec_write(codec, ICODEC_1_HIGH, val); -+ } else { -+ val = 0x3300; -+ jzcodec_write(codec, ICODEC_1_LOW, val); -+ val = 0x0003; -+ jzcodec_write(codec, ICODEC_1_HIGH, val); -+ } -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int jzcodec_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; */ -+ -+ return 0; -+} -+ -+static void jzcodec_shutdown(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; -+ -+ /* deactivate */ -+ if (!codec->active) { -+ udelay(50); -+ } -+} -+ -+static int jzcodec_mute(struct snd_soc_codec_dai *dai, int mute) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -+ -+ if (mute != 0) -+ mute = 1; -+ if (mute) -+ reg_val = reg_val | (0x1 << 14); -+ else -+ reg_val = reg_val & ~(0x1 << 14); -+ -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ return 0; -+} -+ -+static int jzcodec_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, -+ int clk_id, unsigned int freq, int dir) -+{ -+ struct snd_soc_codec *codec = codec_dai->codec; -+ struct jzcodec_priv *jzcodec = codec->private_data; -+ -+ jzcodec->sysclk = freq; -+ return 0; -+} -+/* -+ * Set's ADC and Voice DAC format. called by pavo_hw_params() in pavo.c -+ */ -+static int jzcodec_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, -+ unsigned int fmt) -+{ -+ /* struct snd_soc_codec *codec = codec_dai->codec; */ -+ -+ /* set master/slave audio interface. codec side */ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBM_CFM: -+ /* set master mode for codec */ -+ break; -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* set slave mode for codec */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* interface format . set some parameter for codec side */ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ /* set I2S mode for codec */ -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ /* set right J mode */ -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ /* set left J mode */ -+ break; -+ case SND_SOC_DAIFMT_DSP_A: -+ /* set dsp A mode */ -+ break; -+ case SND_SOC_DAIFMT_DSP_B: -+ /* set dsp B mode */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* clock inversion. codec side */ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* jzcodec_write(codec, 0, val); */ -+ return 0; -+} -+ -+static int jzcodec_dapm_event(struct snd_soc_codec *codec, int event) -+{ -+/* u16 reg_val; */ -+ -+ switch (event) { -+ case SNDRV_CTL_POWER_D0: /* full On */ -+ /* vref/mid, osc on, dac unmute */ -+ /* u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); */ -+ /* jzcodec_write(codec, 0, val); */ -+ break; -+ case SNDRV_CTL_POWER_D1: /* partial On */ -+ case SNDRV_CTL_POWER_D2: /* partial On */ -+ break; -+ case SNDRV_CTL_POWER_D3hot: /* Off, with power */ -+ /* everything off except vref/vmid, */ -+ /*reg_val = 0x0800; -+ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x0017; -+ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -+ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -+ mdelay(2); -+ reg_val = 0x2102; -+ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x001f; -+ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -+ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -+ mdelay(2); -+ reg_val = 0x3302; -+ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x0003; -+ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -+ REG_ICDC_CDCCR1 = jzcodec_reg[0];*/ -+ break; -+ case SNDRV_CTL_POWER_D3cold: /* Off, without power */ -+ /* everything off, dac mute, inactive */ -+ /*reg_val = 0x2302; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x001b; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -+ mdelay(1); -+ reg_val = 0x2102; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x001b; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val);*/ -+ break; -+ } -+ codec->dapm_state = event; -+ return 0; -+} -+ -+#define JZCODEC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ -+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ -+ SNDRV_PCM_RATE_48000) -+ -+#define JZCODEC_FORMATS (SNDRV_PCM_FORMAT_S8 | SNDRV_PCM_FMTBIT_S16_LE) -+ -+struct snd_soc_codec_dai jzcodec_dai = { -+ .name = "JZCODEC", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZCODEC_RATES, -+ .formats = JZCODEC_FORMATS,}, -+ .capture = { -+ .stream_name = "Capture", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZCODEC_RATES, -+ .formats = JZCODEC_FORMATS,}, -+ .ops = { -+ .trigger = jzcodec_pcm_trigger, -+ .prepare = jzcodec_pcm_prepare, -+ .hw_params = jzcodec_hw_params, -+ .shutdown = jzcodec_shutdown, -+ }, -+ .dai_ops = { -+ .digital_mute = jzcodec_mute, -+ .set_sysclk = jzcodec_set_dai_sysclk, -+ .set_fmt = jzcodec_set_dai_fmt, -+ } -+}; -+EXPORT_SYMBOL_GPL(jzcodec_dai); -+ -+#ifdef CONFIG_PM -+static u16 jzcodec_reg_pm[JZCODEC_CACHEREGNUM]; -+static int jzcodec_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ struct snd_soc_codec *codec = socdev->codec; -+ -+ jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -+ jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH); -+ jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -+ jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); -+ -+ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); -+ return 0; -+} -+ -+static int jzcodec_resume(struct platform_device *pdev) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ struct snd_soc_codec *codec = socdev->codec; -+ u16 reg_val; -+ -+ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); -+ reg_val = jzcodec_reg_pm[ICODEC_1_LOW]; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = jzcodec_reg_pm[ICODEC_1_HIGH]; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -+ reg_val = jzcodec_reg_pm[ICODEC_2_LOW]; -+ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -+ reg_val = jzcodec_reg_pm[ICODEC_2_HIGH]; -+ jzcodec_write(codec, ICODEC_2_HIGH, reg_val); -+ -+ jzcodec_dapm_event(codec, codec->suspend_dapm_state); -+ return 0; -+} -+#else -+#define jzcodec_suspend NULL -+#define jzcodec_resume NULL -+#endif -+/* -+ * initialise the JZCODEC driver -+ * register the mixer and dsp interfaces with the kernel -+ */ -+static int jzcodec_init(struct snd_soc_device *socdev) -+{ -+ struct snd_soc_codec *codec = socdev->codec; -+ int reg, ret = 0; -+ u16 reg_val; -+ -+ for (reg = 0; reg < JZCODEC_CACHEREGNUM / 2; reg++) { -+ switch (reg) { -+ case 0: -+ jzcodec_reg[reg] = REG_ICDC_CDCCR1; -+ jzcodec_reg_LH[ICODEC_1_LOW] = jzcodec_reg[reg] & 0xffff; -+ jzcodec_reg_LH[ICODEC_1_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; -+ break; -+ case 1: -+ jzcodec_reg[reg] = REG_ICDC_CDCCR2; -+ jzcodec_reg_LH[ICODEC_2_LOW] = jzcodec_reg[reg] & 0xffff; -+ jzcodec_reg_LH[ICODEC_2_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; -+ break; -+ } -+ } -+ -+ codec->name = "JZCODEC"; -+ codec->owner = THIS_MODULE; -+ codec->read = jzcodec_read_reg_cache; -+ codec->write = jzcodec_write; -+ codec->dapm_event = jzcodec_dapm_event; -+ codec->dai = &jzcodec_dai; -+ codec->num_dai = 1; -+ codec->reg_cache_size = sizeof(jzcodec_reg_LH); -+ codec->reg_cache = kmemdup(jzcodec_reg_LH, sizeof(jzcodec_reg_LH), GFP_KERNEL); -+ if (codec->reg_cache == NULL) -+ return -ENOMEM; -+ -+ jzcodec_reset(codec); -+ /* register pcms */ -+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -+ if (ret < 0) { -+ printk(KERN_ERR "jzcodec: failed to create pcms\n"); -+ goto pcm_err; -+ } -+ -+ /* power on device */ -+ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); -+ -+ /* clear suspend bit of jz4740 internal codec */ -+ reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -+ reg_val = reg_val & ~(0x2); -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ /* set vol bits */ -+ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -+ reg_val = reg_val | 0x3; -+ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -+ /* set line in capture gain bits */ -+ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); -+ reg_val = reg_val | 0x1f; -+ jzcodec_write(codec, ICODEC_2_HIGH, reg_val); -+ /* set mic boost gain bits */ -+ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -+ reg_val = reg_val | (0x3 << 4); -+ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -+ mdelay(5); -+ reg_val = 0x3300; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x0003; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -+ jzcodec_add_controls(codec); -+ jzcodec_add_widgets(codec); -+ -+ ret = snd_soc_register_card(socdev); -+ if (ret < 0) { -+ printk(KERN_ERR "jzcodec: failed to register card\n"); -+ goto card_err; -+ } -+ return ret; -+ -+card_err: -+ snd_soc_free_pcms(socdev); -+ snd_soc_dapm_free(socdev); -+pcm_err: -+ kfree(codec->reg_cache); -+ return ret; -+} -+ -+static struct snd_soc_device *jzcodec_socdev; -+ -+static int write_codec_reg(u16 * add, char * name, int reg) -+{ -+ switch (reg) { -+ case 0: -+ case 1: -+ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -+ break; -+ case 2: -+ case 3: -+ REG_ICDC_CDCCR2 = jzcodec_reg[1]; -+ break; -+ } -+ return 0; -+} -+ -+static int jzcodec_probe(struct platform_device *pdev) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ struct snd_soc_codec *codec; -+ struct jzcodec_priv *jzcodec; -+ int ret = 0; -+ -+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -+ if (codec == NULL) -+ return -ENOMEM; -+ -+ jzcodec = kzalloc(sizeof(struct jzcodec_priv), GFP_KERNEL); -+ if (jzcodec == NULL) { -+ kfree(codec); -+ return -ENOMEM; -+ } -+ -+ codec->private_data = jzcodec; -+ socdev->codec = codec; -+ mutex_init(&codec->mutex); -+ INIT_LIST_HEAD(&codec->dapm_widgets); -+ INIT_LIST_HEAD(&codec->dapm_paths); -+ -+ jzcodec_socdev = socdev; -+ -+ /* Add other interfaces here ,no I2C connection */ -+ codec->hw_write = (hw_write_t)write_codec_reg; -+ ret = jzcodec_init(jzcodec_socdev); -+ -+ if (ret < 0) { -+ codec = jzcodec_socdev->codec; -+ err("failed to initialise jzcodec\n"); -+ kfree(codec); -+ } -+ -+ return ret; -+} -+ -+/* power down chip */ -+static int jzcodec_remove(struct platform_device *pdev) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ struct snd_soc_codec *codec = socdev->codec; -+ -+ if (codec->control_data) -+ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); -+ -+ snd_soc_free_pcms(socdev); -+ snd_soc_dapm_free(socdev); -+ kfree(codec->private_data); -+ kfree(codec); -+ -+ return 0; -+} -+ -+struct snd_soc_codec_device soc_codec_dev_jzcodec = { -+ .probe = jzcodec_probe, -+ .remove = jzcodec_remove, -+ .suspend = jzcodec_suspend, -+ .resume = jzcodec_resume, -+}; -+ -+EXPORT_SYMBOL_GPL(soc_codec_dev_jzcodec); -+ -+MODULE_DESCRIPTION("ASoC JZCODEC driver"); -+MODULE_AUTHOR("Richard"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/codecs/jzcodec.h b/sound/soc/codecs/jzcodec.h -new file mode 100644 -index 0000000..7e4dedf ---- /dev/null -+++ b/sound/soc/codecs/jzcodec.h -@@ -0,0 +1,22 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _ICODEC_H -+#define _ICODEC_H -+ -+/* jzcodec register space */ -+#define ICODEC_1_LOW 0x00 /* bit0 -- bit15 in CDCCR1 */ -+#define ICODEC_1_HIGH 0x01 /* bit16 -- bit31 in CDCCR1 */ -+#define ICODEC_2_LOW 0x02 /* bit0 -- bit16 in CDCCR2 */ -+#define ICODEC_2_HIGH 0x03 /* bit16 -- bit31 in CDCCR2 */ -+ -+#define JZCODEC_CACHEREGNUM 4 -+#define JZCODEC_SYSCLK 0 -+ -+extern struct snd_soc_codec_dai jzcodec_dai; -+extern struct snd_soc_codec_device soc_codec_dev_jzcodec; -+ -+#endif -diff --git a/sound/soc/codecs/jzdlv.c b/sound/soc/codecs/jzdlv.c -new file mode 100644 -index 0000000..2ed2b28 ---- /dev/null -+++ b/sound/soc/codecs/jzdlv.c -@@ -0,0 +1,970 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../jz4750/jz4750-pcm.h" -+#include "jzdlv.h" -+ -+#define AUDIO_NAME "jzdlv" -+#define JZDLV_VERSION "1.0" -+ -+/* -+ * Debug -+ */ -+ -+#define JZDLV_DEBUG 0 -+ -+#ifdef JZDLV_DEBUG -+#define dbg(format, arg...) \ -+ printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) do {} while (0) -+#endif -+#define err(format, arg...) \ -+ printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) -+#define info(format, arg...) \ -+ printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -+#define warn(format, arg...) \ -+ printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) -+ -+struct snd_soc_codec_device soc_codec_dev_jzdlv; -+ -+/* codec private data */ -+struct jzdlv_priv { -+ unsigned int sysclk; -+}; -+ -+/* -+ * jzdlv register cache -+ */ -+static u16 jzdlv_reg[JZDLV_CACHEREGNUM]; -+ -+int read_codec_file(int addr) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ return(__icdc_get_value()); -+} -+ -+static void printk_codec_files(void) -+{ -+ int cnt, val; -+ -+ //printk("\n"); -+#if 0 -+ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -+ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -+ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -+ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -+ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -+ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -+ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -+ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -+#endif -+ for (cnt = 0; cnt < JZDLV_CACHEREGNUM ; cnt++) { -+ val = read_codec_file(cnt); -+ jzdlv_reg[cnt] = val; -+ //printk(" ( %d : 0x%x ) ",cnt ,jzdlv_reg[cnt]); -+ } -+ //printk("\n"); -+} -+ -+void write_codec_file(int addr, int val) -+{ -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+ //jzdlv_reg[addr] = val; -+} -+ -+int write_codec_file_bit(int addr, int bitval, int mask_bit) -+{ -+ int val; -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ mdelay(1); -+ val = __icdc_get_value(); /* read */ -+ -+ val &= ~(1 << mask_bit); -+ if (bitval == 1) -+ val |= 1 << mask_bit; -+#if 0 -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ __icdc_set_cmd(val); /* write */ -+ mdelay(1); -+ __icdc_set_rgwr(); -+ mdelay(1); -+#else -+ write_codec_file(addr, val); -+#endif -+ while (__icdc_rgwr_ready()); -+ __icdc_set_addr(addr); -+ val = __icdc_get_value(); /* read */ -+ -+ if (((val >> mask_bit) & bitval) == bitval) -+ return 1; -+ else -+ return 0; -+} -+ -+/* -+ * read jzdlv register cache -+ */ -+static inline unsigned int jzdlv_read_reg_cache(struct snd_soc_codec *codec, -+ unsigned int reg) -+{ -+ u16 *cache = codec->reg_cache; -+ -+ if (reg >= JZDLV_CACHEREGNUM) -+ return -1; -+ return cache[reg]; -+} -+ -+static inline unsigned int jzdlv_read(struct snd_soc_codec *codec, -+ unsigned int reg) -+{ -+ u8 data; -+ data = reg; -+ if (codec->hw_write(codec->control_data, &data, 1) != 1) -+ return -EIO; -+ -+ if (codec->hw_read(codec->control_data, &data, 1) != 1) -+ return -EIO; -+ -+ return data; -+} -+ -+/* -+ * write jzdlv register cache -+ */ -+static inline void jzdlv_write_reg_cache(struct snd_soc_codec *codec, -+ unsigned int reg, u16 value) -+{ -+ u16 *cache = codec->reg_cache; -+ -+ if (reg >= JZDLV_CACHEREGNUM) { -+ return; -+ } -+ -+ cache[reg] = value; -+ -+} -+ -+/* -+ * write to the jzdlv register space -+ */ -+static int jzdlv_write(struct snd_soc_codec *codec, unsigned int reg, -+ unsigned int value) -+{ -+ jzdlv_write_reg_cache(codec, reg, value); -+ if(codec->hw_write) -+ codec->hw_write(&value, NULL, reg); -+ return 0; -+} -+ -+/* set Audio data replay */ -+void set_audio_data_replay(void) -+{ -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x20);// only CCMC -+ mdelay(10); -+ -+ /* DAC path */ -+ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ mdelay(100); -+ write_codec_file_bit(1, 0, 5);//DAC_MUTE->0 -+} -+ -+/* unset Audio data replay */ -+void unset_audio_data_replay(void) -+{ -+ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -+ mdelay(200); -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -+ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -+ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -+ write_codec_file_bit(6, 1, 1);//SB->1 -+ -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+} -+ -+/* set Record MIC input audio without playback */ -+static void set_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ write_codec_file_bit(1, 1, 2); -+ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -+ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -+ -+ write_codec_file(22, 0x40);//mic 1 -+ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -+ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -+ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -+ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -+ -+ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -+ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -+ write_codec_file_bit(6, 1, 3);// gain set -+ -+ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -+ mdelay(100); -+ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -+ write_codec_file(1, 0x4); -+} -+ -+/* unset Record MIC input audio without playback */ -+static void unset_record_mic_input_audio_without_playback(void) -+{ -+ /* ADC path for MIC IN */ -+ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -+ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -+ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -+} -+ -+#if 0 -+static irqreturn_t aic_codec_irq(int irq, void *dev_id) -+{ -+ u8 file_9 = read_codec_file(9); -+ u8 file_8 = read_codec_file(8); -+ -+ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -+ if ((file_9 & 0x1f) == 0x10) { -+ // have hp short circuit -+ write_codec_file(8, 0x3f);//mask all interrupt -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x4) != 0x4); -+ while ((read_codec_file(9) & 0x10) == 0x10) { -+ write_codec_file(9, 0x10); -+ } -+ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x8) != 0x8); -+ write_codec_file(9, file_9); -+ write_codec_file(8, file_8); -+ -+ return IRQ_HANDLED; -+ } -+ -+ if (file_9 & 0x8) -+ ramp_up_end = jiffies; -+ else if (file_9 & 0x4) -+ ramp_down_end = jiffies; -+ else if (file_9 & 0x2) -+ gain_up_end = jiffies; -+ else if (file_9 & 0x1) -+ gain_down_end = jiffies; -+ -+ write_codec_file(9, file_9); -+ if (file_9 & 0xf) -+ wake_up(&pop_wait_queue); -+ while (REG_ICDC_RGDATA & 0x100); -+ -+ return IRQ_HANDLED; -+} -+#else -+static irqreturn_t aic_codec_irq(int irq, void *dev_id) -+{ -+ u8 file_9 = read_codec_file(9); -+ u8 file_8 = read_codec_file(8); -+ -+ //printk("--- 1 8:0x%x 9:0x%x ---\n",file_8,file_9); -+ if ((file_9 & 0x1f) == 0x10) { -+ write_codec_file(8, 0x3f); -+ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x4) != 0x4); -+ while ((read_codec_file(9) & 0x10) == 0x10) { -+ write_codec_file(9, 0x10); -+ } -+ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -+ mdelay(300); -+ while ((read_codec_file(9) & 0x8) != 0x8); -+ write_codec_file(9, file_9); -+ write_codec_file(8, file_8); -+ -+ return IRQ_HANDLED; -+ } -+ /*if (file_9 & 0x8) -+ ramp_up_end = jiffies; -+ else if (file_9 & 0x4) -+ ramp_down_end = jiffies; -+ else if (file_9 & 0x2) -+ gain_up_end = jiffies; -+ else if (file_9 & 0x1) -+ gain_down_end = jiffies;*/ -+ -+ write_codec_file(9, file_9); -+ /*if (file_9 & 0xf) -+ wake_up(&pop_wait_queue);*/ -+ while (REG_ICDC_RGDATA & 0x100); -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+static int jzdlv_reset(struct snd_soc_codec *codec) -+{ -+ /* reset DLV codec. from hibernate mode to sleep mode */ -+ write_codec_file(0, 0xf); -+ write_codec_file_bit(6, 0, 0); -+ write_codec_file_bit(6, 0, 1); -+ mdelay(200); -+ //write_codec_file(0, 0xf); -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 -+ mdelay(10);//wait for stability -+ -+ return 0; -+} -+ -+ -+#if 0 -+static int jzdlv_sync(struct snd_soc_codec *codec) -+{ -+ u16 *cache = codec->reg_cache; -+ int i, r = 0; -+ -+ for (i = 0; i < JZDLV_CACHEREGNUM; i++) -+ r |= jzdlv_write(codec, i, cache[i]); -+ -+ return r; -+}; -+#endif -+ -+static const struct snd_kcontrol_new jzdlv_snd_controls[] = { -+ -+ //SOC_DOUBLE_R("Master Playback Volume", 1, 1, 0, 3, 0), -+ SOC_DOUBLE_R("Master Playback Volume", DLV_CGR8, DLV_CGR9, 0, 31, 0), -+ //SOC_DOUBLE_R("MICBG", ICODEC_2_LOW, ICODEC_2_LOW, 4, 3, 0), -+ //SOC_DOUBLE_R("Line", 2, 2, 0, 31, 0), -+ SOC_DOUBLE_R("Line", DLV_CGR10, DLV_CGR10, 0, 31, 0), -+}; -+ -+/* add non dapm controls */ -+static int jzdlv_add_controls(struct snd_soc_codec *codec) -+{ -+ int err, i; -+ -+ for (i = 0; i < ARRAY_SIZE(jzdlv_snd_controls); i++) { -+ if ((err = snd_ctl_add(codec->card, -+ snd_soc_cnew(&jzdlv_snd_controls[i], codec, NULL))) < 0) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static const struct snd_soc_dapm_widget jzdlv_dapm_widgets[] = { -+ SND_SOC_DAPM_OUTPUT("LOUT"), -+ SND_SOC_DAPM_OUTPUT("LHPOUT"), -+ SND_SOC_DAPM_OUTPUT("ROUT"), -+ SND_SOC_DAPM_OUTPUT("RHPOUT"), -+ SND_SOC_DAPM_INPUT("MICIN"), -+ SND_SOC_DAPM_INPUT("RLINEIN"), -+ SND_SOC_DAPM_INPUT("LLINEIN"), -+}; -+ -+static const char *intercon[][3] = { -+ /* output mixer */ -+ {"Output Mixer", "Line Bypass Switch", "Line Input"}, -+ {"Output Mixer", "HiFi Playback Switch", "DAC"}, -+ {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, -+ -+ /* outputs */ -+ {"RHPOUT", NULL, "Output Mixer"}, -+ {"ROUT", NULL, "Output Mixer"}, -+ {"LHPOUT", NULL, "Output Mixer"}, -+ {"LOUT", NULL, "Output Mixer"}, -+ -+ /* input mux */ -+ {"Input Mux", "Line In", "Line Input"}, -+ {"Input Mux", "Mic", "Mic Bias"}, -+ {"ADC", NULL, "Input Mux"}, -+ -+ /* inputs */ -+ {"Line Input", NULL, "LLINEIN"}, -+ {"Line Input", NULL, "RLINEIN"}, -+ {"Mic Bias", NULL, "MICIN"}, -+ -+ /* terminator */ -+ {NULL, NULL, NULL}, -+}; -+ -+static void init_codec(void) -+{ -+ /* reset DLV codec. from hibernate mode to sleep mode */ -+ write_codec_file(0, 0xf); -+ write_codec_file_bit(6, 0, 0); -+ write_codec_file_bit(6, 0, 1); -+ mdelay(200); -+ //write_codec_file(0, 0xf); -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 -+ mdelay(10);//wait for stability -+} -+ -+static int jzdlv_add_widgets(struct snd_soc_codec *codec) -+{ -+ int i,cnt; -+ -+ cnt = ARRAY_SIZE(jzdlv_dapm_widgets); -+ for(i = 0; i < ARRAY_SIZE(jzdlv_dapm_widgets); i++) { -+ snd_soc_dapm_new_control(codec, &jzdlv_dapm_widgets[i]); -+ } -+ -+ /* set up audio path interconnects */ -+ for(i = 0; intercon[i][0] != NULL; i++) { -+ snd_soc_dapm_connect_input(codec, intercon[i][0], -+ intercon[i][1], intercon[i][2]); -+ } -+ -+ snd_soc_dapm_new_widgets(codec); -+ return 0; -+} -+ -+static int jzdlv_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; -+ int speed = 0; -+ int val = 0; -+ -+ /* sample channel */ -+ switch (params_channels(params)) { -+ case 1: -+ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -+ break; -+ case 2: -+ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -+ break; -+ } -+ /* sample rate */ -+ switch (params_rate(params)) { -+ case 8000: -+ speed = 10; -+ break; -+ case 9600: -+ speed = 9; -+ break; -+ case 11025: -+ speed = 8; -+ break; -+ case 12000: -+ speed = 7; -+ break; -+ case 16000: -+ speed = 6; -+ break; -+ case 22050: -+ speed = 5; -+ break; -+ case 24000: -+ speed = 4; -+ break; -+ case 32000: -+ speed = 3; -+ break; -+ case 44100: -+ speed = 2; -+ break; -+ case 48000: -+ speed = 1; -+ break; -+ case 96000: -+ speed = 0; -+ break; -+ default: -+ printk(" invalid rate :0x%08x\n",params_rate(params)); -+ } -+ -+ val = (speed << 4) | speed; -+ jzdlv_write(codec, DLV_CCR2, val); -+ -+ return 0; -+} -+ -+static int jzdlv_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ int ret = 0; -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ //struct snd_soc_device *socdev = rtd->socdev; -+ //struct snd_soc_codec *codec = socdev->codec; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ break; -+ case SNDRV_PCM_TRIGGER_START: -+ //case SNDRV_PCM_TRIGGER_RESUME: -+ -+ init_codec(); -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ set_audio_data_replay(); -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ __aic_flush_fifo(); -+ } else { -+ set_record_mic_input_audio_without_playback(); -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ __aic_flush_fifo(); -+ write_codec_file_bit(5, 1, 7); -+ } -+ -+ break; -+ -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ //case SNDRV_PCM_TRIGGER_SUSPEND: -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ unset_audio_data_replay(); -+ } else { -+ unset_record_mic_input_audio_without_playback(); -+ } -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int jzdlv_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; */ -+ -+ return 0; -+} -+ -+static void jzdlv_shutdown(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_device *socdev = rtd->socdev; -+ struct snd_soc_codec *codec = socdev->codec; -+ -+ /* deactivate */ -+ if (!codec->active) { -+ udelay(50); -+ } -+} -+ -+static int jzdlv_mute(struct snd_soc_codec_dai *dai, int mute) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ u16 reg_val = jzdlv_read_reg_cache(codec, 2/*DLV_1_LOW*/); -+ -+ if (mute != 0) -+ mute = 1; -+ if (mute) -+ reg_val = reg_val | (0x1 << 14); -+ else -+ reg_val = reg_val & ~(0x1 << 14); -+ -+ //jzdlv_write(codec, DLV_1_LOW, reg_val); -+ return 0; -+} -+ -+static int jzdlv_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, -+ int clk_id, unsigned int freq, int dir) -+{ -+ struct snd_soc_codec *codec = codec_dai->codec; -+ struct jzdlv_priv *jzdlv = codec->private_data; -+ -+ jzdlv->sysclk = freq; -+ return 0; -+} -+/* -+ * Set's ADC and Voice DAC format. called by apus_hw_params() in apus.c -+ */ -+static int jzdlv_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, -+ unsigned int fmt) -+{ -+ /* struct snd_soc_codec *codec = codec_dai->codec; */ -+ -+ /* set master/slave audio interface. codec side */ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBM_CFM: -+ /* set master mode for codec */ -+ break; -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* set slave mode for codec */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* interface format . set some parameter for codec side */ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ /* set I2S mode for codec */ -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ /* set right J mode */ -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ /* set left J mode */ -+ break; -+ case SND_SOC_DAIFMT_DSP_A: -+ /* set dsp A mode */ -+ break; -+ case SND_SOC_DAIFMT_DSP_B: -+ /* set dsp B mode */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* clock inversion. codec side */ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* jzcodec_write(codec, 0, val); */ -+ return 0; -+} -+ -+static int jzdlv_dapm_event(struct snd_soc_codec *codec, int event) -+{ -+/* u16 reg_val; */ -+ -+ switch (event) { -+ case SNDRV_CTL_POWER_D0: /* full On */ -+ /* vref/mid, osc on, dac unmute */ -+ /* u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); */ -+ /* jzcodec_write(codec, 0, val); */ -+ break; -+ case SNDRV_CTL_POWER_D1: /* partial On */ -+ case SNDRV_CTL_POWER_D2: /* partial On */ -+ break; -+ case SNDRV_CTL_POWER_D3hot: /* Off, with power */ -+ /* everything off except vref/vmid, */ -+ /*reg_val = 0x0800; -+ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x0017; -+ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -+ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -+ mdelay(2); -+ reg_val = 0x2102; -+ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x001f; -+ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -+ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -+ mdelay(2); -+ reg_val = 0x3302; -+ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x0003; -+ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -+ REG_ICDC_CDCCR1 = jzcodec_reg[0];*/ -+ break; -+ case SNDRV_CTL_POWER_D3cold: /* Off, without power */ -+ /* everything off, dac mute, inactive */ -+ /*reg_val = 0x2302; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x001b; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -+ mdelay(1); -+ reg_val = 0x2102; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = 0x001b; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val);*/ -+ break; -+ } -+ //codec->dapm_state = event; -+ return 0; -+} -+ -+#define JZDLV_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ -+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ -+ SNDRV_PCM_RATE_48000) -+ -+#define JZDLV_FORMATS (SNDRV_PCM_FORMAT_S8 | SNDRV_PCM_FMTBIT_S16_LE) -+ -+struct snd_soc_codec_dai jzdlv_dai = { -+ .name = "JZDLV", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZDLV_RATES, -+ .formats = JZDLV_FORMATS,}, -+ .capture = { -+ .stream_name = "Capture", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZDLV_RATES, -+ .formats = JZDLV_FORMATS,}, -+ .ops = { -+ .trigger = jzdlv_pcm_trigger, -+ .prepare = jzdlv_pcm_prepare, -+ .hw_params = jzdlv_hw_params, -+ .shutdown = jzdlv_shutdown, -+ }, -+ .dai_ops = { -+ .digital_mute = jzdlv_mute, -+ .set_sysclk = jzdlv_set_dai_sysclk, -+ .set_fmt = jzdlv_set_dai_fmt, -+ } -+}; -+EXPORT_SYMBOL_GPL(jzdlv_dai); -+ -+#ifdef CONFIG_PM -+//static u16 jzdlv_reg_pm[JZDLV_CACHEREGNUM]; -+static int jzdlv_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ //struct snd_soc_codec *codec = socdev->codec; -+#if 0 -+ jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -+ jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH); -+ jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -+ jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); -+ -+ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); -+#endif -+ return 0; -+} -+ -+static int jzdlv_resume(struct platform_device *pdev) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ //struct snd_soc_codec *codec = socdev->codec; -+ //u16 reg_val; -+#if 0 -+ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); -+ reg_val = jzcodec_reg_pm[ICODEC_1_LOW]; -+ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -+ reg_val = jzcodec_reg_pm[ICODEC_1_HIGH]; -+ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -+ reg_val = jzcodec_reg_pm[ICODEC_2_LOW]; -+ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -+ reg_val = jzcodec_reg_pm[ICODEC_2_HIGH]; -+ jzcodec_write(codec, ICODEC_2_HIGH, reg_val); -+ -+ jzcodec_dapm_event(codec, codec->suspend_dapm_state); -+#endif -+ return 0; -+} -+#else -+#define jzdlv_suspend NULL -+#define jzdlv_resume NULL -+#endif -+/* -+ * initialise the JZDLV driver -+ * register the mixer and dsp interfaces with the kernel -+ */ -+static int jzdlv_init(struct snd_soc_device *socdev) -+{ -+ struct snd_soc_codec *codec = socdev->codec; -+ int ret = 0, retval; -+ -+ /*REG_CPM_CPCCR &= ~(1 << 31); -+ REG_CPM_CPCCR &= ~(1 << 30);*/ -+ write_codec_file(0, 0xf); -+ -+ REG_AIC_I2SCR = 0x10; -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ __aic_reset(); -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ -+ /* power on DLV */ -+ write_codec_file(8, 0x3f); -+ write_codec_file(9, 0xff); -+ mdelay(10); -+ -+ __cpm_start_idct(); -+ __cpm_start_db(); -+ __cpm_start_me(); -+ __cpm_start_mc(); -+ __cpm_start_ipu(); -+ -+ codec->name = "JZDLV"; -+ codec->owner = THIS_MODULE; -+ codec->read = jzdlv_read_reg_cache; -+ codec->write = jzdlv_write; -+ //codec->dapm_event = jzdlv_dapm_event; -+ codec->dai = &jzdlv_dai; -+ codec->num_dai = 1; -+ codec->reg_cache_size = sizeof(jzdlv_reg); -+ codec->reg_cache = kmemdup(jzdlv_reg, sizeof(jzdlv_reg), GFP_KERNEL); -+ if (codec->reg_cache == NULL) -+ return -ENOMEM; -+ -+ jzdlv_reset(codec); -+ /* register pcms */ -+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -+ if (ret < 0) { -+ printk(KERN_ERR "jzdlv: failed to create pcms\n"); -+ goto pcm_err; -+ } -+ -+ /* power on device */ -+ jzdlv_dapm_event(codec, SNDRV_CTL_POWER_D3hot); -+ -+ jzdlv_add_controls(codec); -+ jzdlv_add_widgets(codec); -+ -+ ret = snd_soc_register_card(socdev); -+ if (ret < 0) { -+ printk(KERN_ERR "jzcodec: failed to register card\n"); -+ goto card_err; -+ } -+ -+ mdelay(10); -+ REG_AIC_I2SCR = 0x10; -+ mdelay(20); -+ /* power on DLV */ -+ write_codec_file(9, 0xff); -+ write_codec_file(8, 0x3f); -+ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -+ if (retval) { -+ printk("Could not get aic codec irq %d\n", IRQ_AIC); -+ return retval; -+ } -+ -+ printk_codec_files(); -+ return ret; -+ -+card_err: -+ snd_soc_free_pcms(socdev); -+ snd_soc_dapm_free(socdev); -+pcm_err: -+ kfree(codec->reg_cache); -+ return ret; -+} -+ -+static struct snd_soc_device *jzdlv_socdev; -+ -+static int write_codec_reg(u16 * add, char * name, int reg) -+{ -+ write_codec_file(reg, *add); -+ -+ return 0; -+} -+ -+static int jzdlv_probe(struct platform_device *pdev) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ struct snd_soc_codec *codec; -+ struct jzdlv_priv *jzdlv; -+ int ret = 0; -+ -+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -+ if (codec == NULL) -+ return -ENOMEM; -+ -+ jzdlv = kzalloc(sizeof(struct jzdlv_priv), GFP_KERNEL); -+ if (jzdlv == NULL) { -+ kfree(codec); -+ return -ENOMEM; -+ } -+ -+ codec->private_data = jzdlv; -+ socdev->codec = codec; -+ mutex_init(&codec->mutex); -+ INIT_LIST_HEAD(&codec->dapm_widgets); -+ INIT_LIST_HEAD(&codec->dapm_paths); -+ -+ jzdlv_socdev = socdev; -+ -+ /* Add other interfaces here ,no I2C connection */ -+ codec->hw_write = (hw_write_t)write_codec_reg; -+ //codec->hw_read = (hw_read_t)read_codec_reg; -+ ret = jzdlv_init(jzdlv_socdev); -+ -+ if (ret < 0) { -+ codec = jzdlv_socdev->codec; -+ err("failed to initialise jzdlv\n"); -+ kfree(codec); -+ } -+ -+ return ret; -+} -+ -+/* power down chip */ -+static int jzdlv_remove(struct platform_device *pdev) -+{ -+ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -+ struct snd_soc_codec *codec = socdev->codec; -+ -+ if (codec->control_data) -+ jzdlv_dapm_event(codec, SNDRV_CTL_POWER_D3cold); -+ -+ snd_soc_free_pcms(socdev); -+ snd_soc_dapm_free(socdev); -+ kfree(codec->private_data); -+ kfree(codec); -+ -+ return 0; -+} -+ -+struct snd_soc_codec_device soc_codec_dev_jzdlv = { -+ .probe = jzdlv_probe, -+ .remove = jzdlv_remove, -+ .suspend = jzdlv_suspend, -+ .resume = jzdlv_resume, -+}; -+ -+EXPORT_SYMBOL_GPL(soc_codec_dev_jzdlv); -+ -+MODULE_DESCRIPTION("ASoC JZDLV driver"); -+MODULE_AUTHOR("Richard"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/codecs/jzdlv.h b/sound/soc/codecs/jzdlv.h -new file mode 100644 -index 0000000..a901a69 ---- /dev/null -+++ b/sound/soc/codecs/jzdlv.h -@@ -0,0 +1,50 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _DLV_H -+#define _DLV_H -+ -+/* jzdlv register space */ -+ -+#define DLV_AICR 0x00 -+#define DLV_CR1 0x01 -+#define DLV_CR2 0x02 -+#define DLV_CCR1 0x03 -+#define DLV_CCR2 0x04 -+#define DLV_PMR1 0x05 -+#define DLV_PMR2 0x06 -+#define DLV_CRR 0x07 -+#define DLV_ICR 0x08 -+#define DLV_IFR 0x09 -+#define DLV_CGR1 0x0a -+#define DLV_CGR2 0x0b -+#define DLV_CGR3 0x0c -+#define DLV_CGR4 0x0d -+#define DLV_CGR5 0x0e -+#define DLV_CGR6 0x0f -+#define DLV_CGR7 0x10 -+#define DLV_CGR8 0x11 -+#define DLV_CGR9 0x12 -+#define DLV_CGR10 0x13 -+#define DLV_TR1 0x14 -+#define DLV_TR2 0x15 -+#define DLV_CR3 0x16 -+#define DLV_AGC1 0x17 -+#define DLV_AGC2 0x18 -+#define DLV_AGC3 0x19 -+#define DLV_AGC4 0x1a -+#define DLV_AGC5 0x1b -+ -+#define JZDLV_CACHEREGNUM (DLV_AGC5+1) -+#define JZDLV_SYSCLK 0 -+ -+int read_codec_file(int addr); -+int write_codec_file_bit(int addr, int bitval, int mask_bit); -+void write_codec_file(int addr, int val); -+extern struct snd_soc_codec_dai jzdlv_dai; -+extern struct snd_soc_codec_device soc_codec_dev_jzdlv; -+ -+#endif -diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig -new file mode 100644 -index 0000000..0bfbffe ---- /dev/null -+++ b/sound/soc/jz4740/Kconfig -@@ -0,0 +1,34 @@ -+config SND_JZ4740_SOC -+ tristate "SoC Audio for Ingenic jz4740 chip" -+ depends on (JZ4740_PAVO || JZ4725_DIPPER || JZ4720_VIRGO) && SND_SOC -+ help -+ Say Y or M if you want to add support for codecs attached to -+ the Jz4740 AC97, I2S or SSP interface. You will also need -+ to select the audio interfaces to support below. -+ -+config SND_JZ4740_SOC_PAVO -+ tristate "SoC Audio support for Ingenic Jz4740 PAVO board" -+ depends on SND_JZ4740_SOC -+ help -+ Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 PAVO board. -+ -+config SND_JZ4740_AC97 -+ tristate "select AC97 protocol and AC97 codec pcm core support" -+ depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO -+ select SND_AC97_CODEC -+ help -+ Say Y if you want to add AC97 protocol support for pcm core. -+ -+config SND_JZ4740_SOC_AC97 -+ tristate "SoC Audio (AC97 protocol) for Ingenic jz4740 chip" -+ depends on SND_JZ4740_SOC && SND_JZ4740_AC97 && SND_JZ4740_SOC_PAVO -+ select AC97_BUS -+ select SND_SOC_AC97_BUS -+ help -+ Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4740 PAVO board. -+ -+config SND_JZ4740_SOC_I2S -+ depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO -+ tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip" -+ help -+ Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 PAVO board. -diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile -new file mode 100644 -index 0000000..4c79b13 ---- /dev/null -+++ b/sound/soc/jz4740/Makefile -@@ -0,0 +1,15 @@ -+# -+# Jz4740 Platform Support -+# -+snd-soc-jz4740-objs := jz4740-pcm.o -+snd-soc-jz4740-ac97-objs := jz4740-ac97.o -+snd-soc-jz4740-i2s-objs := jz4740-i2s.o -+ -+obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o -+obj-$(CONFIG_SND_JZ4740_SOC_AC97) += snd-soc-jz4740-ac97.o -+obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o -+ -+# Jz4740 Machine Support -+snd-soc-pavo-objs := pavo.o -+ -+obj-$(CONFIG_SND_JZ4740_SOC_PAVO) += snd-soc-pavo.o -diff --git a/sound/soc/jz4740/jz4740-ac97.c b/sound/soc/jz4740/jz4740-ac97.c -new file mode 100644 -index 0000000..84da470 ---- /dev/null -+++ b/sound/soc/jz4740/jz4740-ac97.c -@@ -0,0 +1,261 @@ -+/* -+ * linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip. -+ * -+ * Author: Richard -+ * Created: Dec 02, 2007 -+ * Copyright: Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jz4740-pcm.h" -+#include "jz4740-ac97.h" -+ -+static DEFINE_MUTEX(car_mutex); -+static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); -+static volatile long gsr_bits; -+ -+static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97, -+ unsigned short reg) -+{ -+ unsigned short val = -1; -+ volatile u32 *reg_addr; -+ -+ mutex_lock(&car_mutex); -+ -+out: mutex_unlock(&car_mutex); -+ return val; -+} -+ -+static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg, -+ unsigned short val) -+{ -+ volatile u32 *reg_addr; -+ -+ mutex_lock(&car_mutex); -+ -+ mutex_unlock(&car_mutex); -+} -+ -+static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97) -+{ -+ gsr_bits = 0; -+} -+ -+static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97) -+{ -+} -+ -+static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id) -+{ -+ long status; -+ return IRQ_NONE; -+} -+ -+struct snd_ac97_bus_ops soc_ac97_ops = { -+ .read = jz4740_ac97_read, -+ .write = jz4740_ac97_write, -+ .warm_reset = jz4740_ac97_warm_reset, -+ .reset = jz4740_ac97_cold_reset, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = { -+ .name = "AC97 PCM Stereo out", -+ .dev_addr = __PREG(PCDR), -+ .drcmr = &DRCMRTXPCDR, -+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | -+ DCMD_BURST32 | DCMD_WIDTH4, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = { -+ .name = "AC97 PCM Stereo in", -+ .dev_addr = __PREG(PCDR), -+ .drcmr = &DRCMRRXPCDR, -+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -+ DCMD_BURST32 | DCMD_WIDTH4, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = { -+ .name = "AC97 Aux PCM (Slot 5) Mono out", -+ .dev_addr = __PREG(MODR), -+ .drcmr = &DRCMRTXMODR, -+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | -+ DCMD_BURST16 | DCMD_WIDTH2, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = { -+ .name = "AC97 Aux PCM (Slot 5) Mono in", -+ .dev_addr = __PREG(MODR), -+ .drcmr = &DRCMRRXMODR, -+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -+ DCMD_BURST16 | DCMD_WIDTH2, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = { -+ .name = "AC97 Mic PCM (Slot 6) Mono in", -+ .dev_addr = __PREG(MCDR), -+ .drcmr = &DRCMRRXMCDR, -+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -+ DCMD_BURST16 | DCMD_WIDTH2, -+}; -+ -+#ifdef CONFIG_PM -+static int jz4740_ac97_suspend(struct platform_device *pdev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ return 0; -+} -+ -+static int jz4740_ac97_resume(struct platform_device *pdev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ return 0; -+} -+ -+#else -+#define jz4740_ac97_suspend NULL -+#define jz4740_ac97_resume NULL -+#endif -+ -+static int jz4740_ac97_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ return 0; -+} -+ -+static void jz4740_ac97_remove(struct platform_device *pdev) -+{ -+} -+ -+static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out; -+ else -+ cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in; -+ -+ return 0; -+} -+ -+static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out; -+ else -+ cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in; -+ -+ return 0; -+} -+ -+static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ return -ENODEV; -+ else -+ cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in; -+ -+ return 0; -+} -+ -+#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ -+ SNDRV_PCM_RATE_48000) -+ -+struct snd_soc_cpu_dai jz4740_ac97_dai[] = { -+{ -+ .name = "jz4740-ac97", -+ .id = 0, -+ .type = SND_SOC_DAI_AC97, -+ .probe = jz4740_ac97_probe, -+ .remove = jz4740_ac97_remove, -+ .suspend = jz4740_ac97_suspend, -+ .resume = jz4740_ac97_resume, -+ .playback = { -+ .stream_name = "AC97 Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .capture = { -+ .stream_name = "AC97 Capture", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .hw_params = jz4740_ac97_hw_params,}, -+}, -+{ -+ .name = "jz4740-ac97-aux", -+ .id = 1, -+ .type = SND_SOC_DAI_AC97, -+ .playback = { -+ .stream_name = "AC97 Aux Playback", -+ .channels_min = 1, -+ .channels_max = 1, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .capture = { -+ .stream_name = "AC97 Aux Capture", -+ .channels_min = 1, -+ .channels_max = 1, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .hw_params = jz4740_ac97_hw_aux_params,}, -+}, -+{ -+ .name = "jz4740-ac97-mic", -+ .id = 2, -+ .type = SND_SOC_DAI_AC97, -+ .capture = { -+ .stream_name = "AC97 Mic Capture", -+ .channels_min = 1, -+ .channels_max = 1, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .hw_params = jz4740_ac97_hw_mic_params,}, -+}, -+}; -+ -+EXPORT_SYMBOL_GPL(jz4740_ac97_dai); -+EXPORT_SYMBOL_GPL(soc_ac97_ops); -+ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4740/jz4740-ac97.h b/sound/soc/jz4740/jz4740-ac97.h -new file mode 100644 -index 0000000..e80e2a0 ---- /dev/null -+++ b/sound/soc/jz4740/jz4740-ac97.h -@@ -0,0 +1,21 @@ -+/* -+ * linux/sound/soc/jz4740/jz4740-ac97.h -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _JZ4740_AC97_H -+#define _JZ4740_AC97_H -+ -+#define JZ4740_DAI_AC97_HIFI 0 -+#define JZ4740_DAI_AC97_AUX 1 -+#define JZ4740_DAI_AC97_MIC 2 -+ -+extern struct snd_soc_cpu_dai jz4740_ac97_dai[3]; -+ -+/* platform data */ -+extern struct snd_ac97_bus_ops jz4740_ac97_ops; -+ -+#endif -diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c -new file mode 100644 -index 0000000..de40d4d ---- /dev/null -+++ b/sound/soc/jz4740/jz4740-i2s.c -@@ -0,0 +1,296 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz4740-pcm.h" -+#include "jz4740-i2s.h" -+ -+static struct jz4740_dma_client jz4740_dma_client_out = { -+ .name = "I2S PCM Stereo out" -+}; -+ -+static struct jz4740_dma_client jz4740_dma_client_in = { -+ .name = "I2S PCM Stereo in" -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_out = { -+ .client = &jz4740_dma_client_out, -+ .channel = DMA_ID_AIC_TX, -+ .dma_addr = AIC_DR, -+ .dma_size = 2, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_in = { -+ .client = &jz4740_dma_client_in, -+ .channel = DMA_ID_AIC_RX, -+ .dma_addr = AIC_DR, -+ .dma_size = 2, -+}; -+ -+static int jz4740_i2s_startup(struct snd_pcm_substream *substream) -+{ -+ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/ -+ -+ return 0; -+} -+ -+static int jz4740_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, -+ unsigned int fmt) -+{ -+ /* interface format */ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ /* 1 : ac97 , 0 : i2s */ -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* 0 : slave */ -+ break; -+ case SND_SOC_DAIFMT_CBM_CFS: -+ /* 1 : master */ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+* Set Jz4740 Clock source -+*/ -+static int jz4740_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, -+ int clk_id, unsigned int freq, int dir) -+{ -+ return 0; -+} -+ -+static void jz4740_snd_tx_ctrl(int on) -+{ -+ if (on) { -+ /* enable replay */ -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ __i2s_enable(); -+ -+ } else { -+ /* disable replay & capture */ -+ __i2s_disable_replay(); -+ __i2s_disable_record(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable(); -+ } -+} -+ -+static void jz4740_snd_rx_ctrl(int on) -+{ -+ if (on) { -+ /* enable capture */ -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ __i2s_enable(); -+ -+ } else { -+ /* disable replay & capture */ -+ __i2s_disable_replay(); -+ __i2s_disable_record(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable(); -+ } -+} -+ -+static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ int channels = params_channels(params); -+ -+ jz4740_snd_rx_ctrl(0); -+ jz4740_snd_rx_ctrl(0); -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out; -+ if (channels == 1) -+ __aic_enable_mono2stereo(); -+ else -+ __aic_disable_mono2stereo(); -+ } else -+ cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_in; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S8: -+ __i2s_set_transmit_trigger(4); -+ __i2s_set_receive_trigger(3); -+ __i2s_set_oss_sample_size(8); -+ __i2s_set_iss_sample_size(8); -+ break; -+ case SNDRV_PCM_FORMAT_S16_LE: -+ /* playback sample:16 bits, burst:16 bytes */ -+ __i2s_set_transmit_trigger(4); -+ /* capture sample:16 bits, burst:16 bytes */ -+ __i2s_set_receive_trigger(3); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ break; -+ } -+ -+ return 0; -+} -+ -+static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ int ret = 0; -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ jz4740_snd_rx_ctrl(1); -+ else -+ jz4740_snd_tx_ctrl(1); -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ jz4740_snd_rx_ctrl(0); -+ else -+ jz4740_snd_tx_ctrl(0); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream) -+{ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ } else { -+ } -+ -+ return; -+} -+ -+static int jz4740_i2s_probe(struct platform_device *pdev) -+{ -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ mdelay(2); -+ -+ __i2s_disable(); -+ __i2s_reset(); -+ mdelay(2); -+ -+ __i2s_disable(); -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ __aic_play_lastsample(); -+ -+ __i2s_disable_record(); -+ __i2s_disable_replay(); -+ __i2s_disable_loopback(); -+ __i2s_set_transmit_trigger(7); -+ __i2s_set_receive_trigger(7); -+ -+ jz4740_snd_tx_ctrl(0); -+ jz4740_snd_rx_ctrl(0); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int jz4740_i2s_suspend(struct platform_device *dev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ if (!dai->active) -+ return 0; -+ -+ return 0; -+} -+ -+static int jz4740_i2s_resume(struct platform_device *pdev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ if (!dai->active) -+ return 0; -+ -+ return 0; -+} -+ -+#else -+#define jz4740_i2s_suspend NULL -+#define jz4740_i2s_resume NULL -+#endif -+ -+#define JZ4740_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -+ SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\ -+ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\ -+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ -+ SNDRV_PCM_RATE_48000) -+ -+struct snd_soc_cpu_dai jz4740_i2s_dai = { -+ .name = "jz4740-i2s", -+ .id = 0, -+ .type = SND_SOC_DAI_I2S, -+ .probe = jz4740_i2s_probe, -+ .suspend = jz4740_i2s_suspend, -+ .resume = jz4740_i2s_resume, -+ .playback = { -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZ4740_I2S_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, -+ .capture = { -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZ4740_I2S_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .startup = jz4740_i2s_startup, -+ .shutdown = jz4740_i2s_shutdown, -+ .trigger = jz4740_i2s_trigger, -+ .hw_params = jz4740_i2s_hw_params,}, -+ .dai_ops = { -+ .set_fmt = jz4740_i2s_set_dai_fmt, -+ .set_sysclk = jz4740_i2s_set_dai_sysclk, -+ }, -+}; -+ -+EXPORT_SYMBOL_GPL(jz4740_i2s_dai); -+ -+/* Module information */ -+MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn"); -+MODULE_DESCRIPTION("jz4740 I2S SoC Interface"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h -new file mode 100644 -index 0000000..f4cbcec ---- /dev/null -+++ b/sound/soc/jz4740/jz4740-i2s.h -@@ -0,0 +1,18 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _JZ4740_I2S_H -+#define _JZ4740_I2S_H -+ -+/* jz4740 DAI ID's */ -+#define JZ4740_DAI_I2S 0 -+ -+/* I2S clock */ -+#define JZ4740_I2S_SYSCLK 0 -+ -+extern struct snd_soc_cpu_dai jz4740_i2s_dai; -+ -+#endif -diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c -new file mode 100644 -index 0000000..516dd1f ---- /dev/null -+++ b/sound/soc/jz4740/jz4740-pcm.c -@@ -0,0 +1,689 @@ -+/* -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include "jz4740-pcm.h" -+ -+static long sum_bytes = 0; -+static int first_transfer = 0; -+static int printk_flag = 0; -+static int tran_bit = 0; -+#ifdef CONFIG_SND_OSSEMUL -+static int hw_params_cnt = 0; -+#endif -+ -+struct jz4740_dma_buf_aic { -+ struct jz4740_dma_buf_aic *next; -+ int size; /* buffer size in bytes */ -+ dma_addr_t data; /* start of DMA data */ -+ dma_addr_t ptr; /* where the DMA got to [1] */ -+ void *id; /* client's id */ -+}; -+ -+struct jz4740_runtime_data { -+ spinlock_t lock; -+ int state; -+ int aic_dma_flag; /* start dma transfer or not */ -+ unsigned int dma_loaded; -+ unsigned int dma_limit; -+ unsigned int dma_period; -+ dma_addr_t dma_start; -+ dma_addr_t dma_pos; -+ dma_addr_t dma_end; -+ struct jz4740_pcm_dma_params *params; -+ -+ dma_addr_t user_cur_addr; /* user current write buffer start address */ -+ unsigned int user_cur_len; /* user current write buffer length */ -+ -+ /* buffer list and information */ -+ struct jz4740_dma_buf_aic *curr; /* current dma buffer */ -+ struct jz4740_dma_buf_aic *next; /* next buffer to load */ -+ struct jz4740_dma_buf_aic *end; /* end of queue */ -+ -+}; -+ -+/* identify hardware playback capabilities */ -+static const struct snd_pcm_hardware jz4740_pcm_hardware = { -+ .info = SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_MMAP_VALID | -+ SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_BLOCK_TRANSFER, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_U16_LE | -+ SNDRV_PCM_FMTBIT_U8 | -+ SNDRV_PCM_FMTBIT_S8, -+ .rates = SNDRV_PCM_RATE_8000_48000/*0x3fe*/, -+ .rate_min = 8000, -+ .rate_min = 48000, -+ .channels_min = 1,//2 -+ .channels_max = 2, -+ .buffer_bytes_max = 128 * 1024,//16 * 1024 -+ .period_bytes_min = PAGE_SIZE, -+ .period_bytes_max = PAGE_SIZE * 2, -+ .periods_min = 2, -+ .periods_max = 128,//16, -+ .fifo_size = 32, -+}; -+ -+/* jz4740__dma_buf_enqueue -+ * -+ * queue an given buffer for dma transfer. -+ * -+ * data the physical address of the buffer data -+ * size the size of the buffer in bytes -+ * -+*/ -+static int jz4740_dma_buf_enqueue(struct jz4740_runtime_data *prtd, dma_addr_t data, int size) -+{ -+ struct jz4740_dma_buf_aic *aic_buf; -+ -+ aic_buf = kzalloc(sizeof(struct jz4740_dma_buf_aic), GFP_KERNEL); -+ if (aic_buf == NULL) { -+ printk("aic buffer allocate failed,no memory!\n"); -+ return -ENOMEM; -+ } -+ aic_buf->next = NULL; -+ aic_buf->data = aic_buf->ptr = data; -+ aic_buf->size = size; -+ if( prtd->curr == NULL) { -+ prtd->curr = aic_buf; -+ prtd->end = aic_buf; -+ prtd->next = NULL; -+ } else { -+ if (prtd->end == NULL) -+ printk("prtd->end is NULL\n"); -+ prtd->end->next = aic_buf; -+ prtd->end = aic_buf; -+ } -+ -+ /* if necessary, update the next buffer field */ -+ if (prtd->next == NULL) -+ prtd->next = aic_buf; -+ -+ return 0; -+} -+ -+ -+void audio_start_dma(struct jz4740_runtime_data *prtd, int mode) -+{ -+ unsigned long flags; -+ struct jz4740_dma_buf_aic *aic_buf; -+ int channel; -+ -+ switch (mode) { -+ case DMA_MODE_WRITE: -+ /* free cur aic_buf */ -+ if (first_transfer == 1) { -+ first_transfer = 0; -+ } else { -+ aic_buf = prtd->curr; -+ if (aic_buf != NULL) { -+ prtd->curr = aic_buf->next; -+ prtd->next = aic_buf->next; -+ aic_buf->next = NULL; -+ kfree(aic_buf); -+ aic_buf = NULL; -+ } -+ } -+ -+ aic_buf = prtd->next; -+ channel = prtd->params->channel; -+ if (aic_buf) { -+ flags = claim_dma_lock(); -+ disable_dma(channel); -+ jz_set_alsa_dma(channel, mode, tran_bit); -+ set_dma_addr(channel, aic_buf->data); -+ set_dma_count(channel, aic_buf->size); -+ enable_dma(channel); -+ release_dma_lock(flags); -+ prtd->aic_dma_flag |= AIC_START_DMA; -+ } else { -+ printk("next buffer is NULL for playback\n"); -+ prtd->aic_dma_flag &= ~AIC_START_DMA; -+ return; -+ } -+ break; -+ case DMA_MODE_READ: -+ /* free cur aic_buf */ -+ if (first_transfer == 1) { -+ first_transfer = 0; -+ } else { -+ aic_buf = prtd->curr; -+ if (aic_buf != NULL) { -+ prtd->curr = aic_buf->next; -+ prtd->next = aic_buf->next; -+ aic_buf->next = NULL; -+ kfree(aic_buf); -+ aic_buf = NULL; -+ } -+ } -+ -+ aic_buf = prtd->next; -+ channel = prtd->params->channel; -+ -+ if (aic_buf) { -+ flags = claim_dma_lock(); -+ disable_dma(channel); -+ jz_set_alsa_dma(channel, mode, tran_bit); -+ set_dma_addr(channel, aic_buf->data); -+ set_dma_count(channel, aic_buf->size); -+ enable_dma(channel); -+ release_dma_lock(flags); -+ prtd->aic_dma_flag |= AIC_START_DMA; -+ } else { -+ printk("next buffer is NULL for capture\n"); -+ prtd->aic_dma_flag &= ~AIC_START_DMA; -+ return; -+ } -+ break; -+ } -+ /* dump_jz_dma_channel(channel); */ -+} -+ -+/* -+ * place a dma buffer onto the queue for the dma system to handle. -+*/ -+static void jz4740_pcm_enqueue(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd = runtime->private_data; -+ /*struct snd_dma_buffer *buf = &substream->dma_buffer;*/ -+ dma_addr_t pos = prtd->dma_pos; -+ int ret; -+ -+ while (prtd->dma_loaded < prtd->dma_limit) { -+ unsigned long len = prtd->dma_period; -+ -+ if ((pos + len) > prtd->dma_end) { -+ len = prtd->dma_end - pos; -+ } -+ ret = jz4740_dma_buf_enqueue(prtd, pos, len); -+ if (ret == 0) { -+ prtd->dma_loaded++; -+ pos += prtd->dma_period; -+ if (pos >= prtd->dma_end) -+ pos = prtd->dma_start; -+ } else -+ break; -+ } -+ -+ prtd->dma_pos = pos; -+} -+ -+/* -+ * call the function:jz4740_pcm_dma_irq() after DMA has transfered the current buffer -+ */ -+static irqreturn_t jz4740_pcm_dma_irq(int dma_ch, void *dev_id) -+{ -+ struct snd_pcm_substream *substream = dev_id; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd = runtime->private_data; -+ /*struct jz4740_dma_buf_aic *aic_buf = prtd->curr;*/ -+ int channel = prtd->params->channel; -+ unsigned long flags; -+ -+ disable_dma(channel); -+ prtd->aic_dma_flag &= ~AIC_START_DMA; -+ /* must clear TT bit in DCCSR to avoid interrupt again */ -+ if (__dmac_channel_transmit_end_detected(channel)) { -+ __dmac_channel_clear_transmit_end(channel); -+ } -+ if (__dmac_channel_transmit_halt_detected(channel)) { -+ __dmac_channel_clear_transmit_halt(channel); -+ } -+ -+ if (__dmac_channel_address_error_detected(channel)) { -+ __dmac_channel_clear_address_error(channel); -+ } -+ -+ if (substream) -+ snd_pcm_period_elapsed(substream); -+ -+ spin_lock(&prtd->lock); -+ prtd->dma_loaded--; -+ if (prtd->state & ST_RUNNING) { -+ jz4740_pcm_enqueue(substream); -+ } -+ spin_unlock(&prtd->lock); -+ -+ local_irq_save(flags); -+ if (prtd->state & ST_RUNNING) { -+ if (prtd->dma_loaded) { -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ audio_start_dma(prtd, DMA_MODE_WRITE); -+ else -+ audio_start_dma(prtd, DMA_MODE_READ); -+ } -+ } -+ local_irq_restore(flags); -+ return IRQ_HANDLED; -+} -+ -+/* some parameter about DMA operation */ -+static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd = runtime->private_data; -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct jz4740_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; -+ size_t totbytes = params_buffer_bytes(params); -+ int ret; -+ -+#ifdef CONFIG_SND_OSSEMUL -+ if (hw_params_cnt) -+ return 0; -+ else -+ hw_params_cnt++ ; -+#endif -+ -+ if (!dma) -+ return 0; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S8: -+ tran_bit = 8; -+ break; -+ case SNDRV_PCM_FORMAT_S16_LE: -+ tran_bit = 16; -+ break; -+ } -+ -+ /* prepare DMA */ -+ prtd->params = dma; -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ ret = jz_request_dma(DMA_ID_AIC_TX, prtd->params->client->name, -+ jz4740_pcm_dma_irq, IRQF_DISABLED, substream); -+ if (ret < 0) -+ return ret; -+ prtd->params->channel = ret; -+ } else { -+ ret = jz_request_dma(DMA_ID_AIC_RX, prtd->params->client->name, -+ jz4740_pcm_dma_irq, IRQF_DISABLED, substream); -+ if (ret < 0) -+ return ret; -+ prtd->params->channel = ret; -+ } -+ -+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); -+ runtime->dma_bytes = totbytes; -+ -+ spin_lock_irq(&prtd->lock); -+ prtd->dma_loaded = 0; -+ prtd->aic_dma_flag = 0; -+ prtd->dma_limit = runtime->hw.periods_min; -+ prtd->dma_period = params_period_bytes(params); -+ prtd->dma_start = runtime->dma_addr; -+ prtd->dma_pos = prtd->dma_start; -+ prtd->dma_end = prtd->dma_start + totbytes; -+ prtd->curr = NULL; -+ prtd->next = NULL; -+ prtd->end = NULL; -+ sum_bytes = 0; -+ first_transfer = 1; -+ printk_flag = 0; -+ -+ __dmac_disable_descriptor(prtd->params->channel); -+ __dmac_channel_disable_irq(prtd->params->channel); -+ spin_unlock_irq(&prtd->lock); -+ -+ return ret; -+} -+ -+static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+ struct jz4740_runtime_data *prtd = substream->runtime->private_data; -+ -+ snd_pcm_set_runtime_buffer(substream, NULL); -+ if (prtd->params) { -+ jz_free_dma(prtd->params->channel); -+ prtd->params = NULL; -+ } -+ -+ return 0; -+} -+ -+/* set some dma para for playback/capture */ -+static int jz4740_dma_ctrl(int channel) -+{ -+ -+ disable_dma(channel); -+ -+ /* must clear TT bit in DCCSR to avoid interrupt again */ -+ if (__dmac_channel_transmit_end_detected(channel)) { -+ __dmac_channel_clear_transmit_end(channel); -+ } -+ if (__dmac_channel_transmit_halt_detected(channel)) { -+ __dmac_channel_clear_transmit_halt(channel); -+ } -+ -+ if (__dmac_channel_address_error_detected(channel)) { -+ __dmac_channel_clear_address_error(channel); -+ } -+ -+ return 0; -+ -+} -+ -+static int jz4740_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ struct jz4740_runtime_data *prtd = substream->runtime->private_data; -+ int ret = 0; -+ -+ /* return if this is a bufferless transfer e.g */ -+ if (!prtd->params) -+ return 0; -+ -+ /* flush the DMA channel and DMA channel bit check */ -+ jz4740_dma_ctrl(prtd->params->channel); -+ prtd->dma_loaded = 0; -+ prtd->dma_pos = prtd->dma_start; -+ -+ /* enqueue dma buffers */ -+ jz4740_pcm_enqueue(substream); -+ -+ return ret; -+ -+} -+ -+static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd = runtime->private_data; -+ -+ int ret = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ prtd->state |= ST_RUNNING; -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ audio_start_dma(prtd, DMA_MODE_WRITE); -+ } else { -+ audio_start_dma(prtd, DMA_MODE_READ); -+ } -+ -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ prtd->state &= ~ST_RUNNING; -+ break; -+ -+ case SNDRV_PCM_TRIGGER_RESUME: -+ printk(" RESUME \n"); -+ break; -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ printk(" RESTART \n"); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static snd_pcm_uframes_t -+jz4740_pcm_pointer(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd = runtime->private_data; -+ struct jz4740_dma_buf_aic *aic_buf = prtd->curr; -+ long count,res; -+ -+ dma_addr_t ptr; -+ snd_pcm_uframes_t x; -+ int channel = prtd->params->channel; -+ -+ spin_lock(&prtd->lock); -+#if 1 -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ res = ptr - prtd->dma_start; -+ } else { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ res = ptr - prtd->dma_start; -+ } -+ -+# else -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ REG_DMAC_DSAR(channel) = ptr; -+ res = ptr - prtd->dma_start; -+ } else { -+ ptr = REG_DMAC_DSAR(channel); -+ if (ptr == 0x0) -+ printk("\ndma address is 00000000 in running!\n"); -+ res = ptr - prtd->dma_start; -+ } -+ } else { -+ if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ REG_DMAC_DTAR(channel) = ptr; -+ res = ptr - prtd->dma_start; -+ } else { -+ ptr = REG_DMAC_DTAR(channel); -+ if (ptr == 0x0) -+ printk("\ndma address is 00000000 in running!\n"); -+ res = ptr - prtd->dma_start; -+ } -+ } -+#endif -+ spin_unlock(&prtd->lock); -+ x = bytes_to_frames(runtime, res); -+ if (x == runtime->buffer_size) -+ x = 0; -+ -+ return x; -+} -+ -+static int jz4740_pcm_open(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd; -+ -+#ifdef CONFIG_SND_OSSEMUL -+ hw_params_cnt = 0; -+#endif -+ snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); -+ prtd = kzalloc(sizeof(struct jz4740_runtime_data), GFP_KERNEL); -+ if (prtd == NULL) -+ return -ENOMEM; -+ -+ spin_lock_init(&prtd->lock); -+ -+ runtime->private_data = prtd; -+ -+ return 0; -+} -+ -+static int jz4740_pcm_close(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4740_runtime_data *prtd = runtime->private_data; -+ struct jz4740_dma_buf_aic *aic_buf = NULL; -+ -+#ifdef CONFIG_SND_OSSEMUL -+ hw_params_cnt = 0; -+#endif -+ -+ if (prtd) -+ aic_buf = prtd->curr; -+ -+ while (aic_buf != NULL) { -+ prtd->curr = aic_buf->next; -+ prtd->next = aic_buf->next; -+ aic_buf->next = NULL; -+ kfree(aic_buf); -+ aic_buf = NULL; -+ aic_buf = prtd->curr; -+ } -+ -+ if (prtd) { -+ prtd->curr = NULL; -+ prtd->next = NULL; -+ prtd->end = NULL; -+ kfree(prtd); -+ } -+ -+ return 0; -+} -+ -+static int jz4740_pcm_mmap(struct snd_pcm_substream *substream, -+ struct vm_area_struct *vma)//include/linux/mm.h -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ int ret = -ENXIO; -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ start = runtime->dma_addr; -+ -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) { -+ return -EINVAL; -+ } -+ -+ off += start; -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ -+#if defined(CONFIG_MIPS32) -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; -+ /* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */ -+#endif -+ ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot); -+ -+ return ret; -+} -+ -+struct snd_pcm_ops jz4740_pcm_ops = { -+ .open = jz4740_pcm_open, -+ .close = jz4740_pcm_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = jz4740_pcm_hw_params, -+ .hw_free = jz4740_pcm_hw_free, -+ .prepare = jz4740_pcm_prepare, -+ .trigger = jz4740_pcm_trigger, -+ .pointer = jz4740_pcm_pointer, -+ .mmap = jz4740_pcm_mmap, -+}; -+ -+static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -+{ -+ struct snd_pcm_substream *substream = pcm->streams[stream].substream; -+ struct snd_dma_buffer *buf = &substream->dma_buffer; -+ size_t size = jz4740_pcm_hardware.buffer_bytes_max; -+ buf->dev.type = SNDRV_DMA_TYPE_DEV; -+ buf->dev.dev = pcm->card->dev; -+ buf->private_data = NULL; -+ -+ /*buf->area = dma_alloc_coherent(pcm->card->dev, size, -+ &buf->addr, GFP_KERNEL);*/ -+ buf->area = dma_alloc_noncoherent(pcm->card->dev, size, -+ &buf->addr, GFP_KERNEL); -+ if (!buf->area) -+ return -ENOMEM; -+ buf->bytes = size; -+ return 0; -+} -+ -+static void jz4740_pcm_free_dma_buffers(struct snd_pcm *pcm) -+{ -+ struct snd_pcm_substream *substream; -+ struct snd_dma_buffer *buf; -+ int stream; -+ -+ for (stream = 0; stream < 2; stream++) { -+ substream = pcm->streams[stream].substream; -+ if (!substream) -+ continue; -+ -+ buf = &substream->dma_buffer; -+ if (!buf->area) -+ continue; -+ -+ dma_free_noncoherent(pcm->card->dev, buf->bytes, -+ buf->area, buf->addr); -+ buf->area = NULL; -+ } -+} -+ -+static u64 jz4740_pcm_dmamask = DMA_32BIT_MASK; -+ -+int jz4740_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai, -+ struct snd_pcm *pcm) -+{ -+ int ret = 0; -+ -+ if (!card->dev->dma_mask) -+ card->dev->dma_mask = &jz4740_pcm_dmamask; -+ if (!card->dev->coherent_dma_mask) -+ card->dev->coherent_dma_mask = DMA_32BIT_MASK; -+ -+ if (dai->playback.channels_min) { -+ ret = jz4740_pcm_preallocate_dma_buffer(pcm, -+ SNDRV_PCM_STREAM_PLAYBACK); -+ if (ret) -+ goto out; -+ } -+ -+ if (dai->capture.channels_min) { -+ ret = jz4740_pcm_preallocate_dma_buffer(pcm, -+ SNDRV_PCM_STREAM_CAPTURE); -+ if (ret) -+ goto out; -+ } -+ out: -+ -+ return ret; -+} -+ -+struct snd_soc_platform jz4740_soc_platform = { -+ .name = "jz4740-audio", -+ .pcm_ops = &jz4740_pcm_ops, -+ .pcm_new = jz4740_pcm_new, -+ .pcm_free = jz4740_pcm_free_dma_buffers, -+}; -+ -+EXPORT_SYMBOL_GPL(jz4740_soc_platform); -+ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("Ingenic Jz4740 PCM DMA module"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h -new file mode 100644 -index 0000000..68ea842 ---- /dev/null -+++ b/sound/soc/jz4740/jz4740-pcm.h -@@ -0,0 +1,33 @@ -+/* -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _JZ4740_PCM_H -+#define _JZ4740_PCM_H -+ -+#include -+ -+#define ST_RUNNING (1<<0) -+#define ST_OPENED (1<<1) -+ -+#define AIC_START_DMA (1<<0) -+#define AIC_END_DMA (1<<1) -+ -+struct jz4740_dma_client { -+ char *name; -+}; -+ -+struct jz4740_pcm_dma_params { -+ struct jz4740_dma_client *client; /* stream identifier */ -+ int channel; /* Channel ID */ -+ dma_addr_t dma_addr; -+ int dma_size; /* Size of the DMA transfer */ -+}; -+ -+/* platform data */ -+extern struct snd_soc_platform jz4740_soc_platform; -+ -+#endif -diff --git a/sound/soc/jz4740/pavo.c b/sound/soc/jz4740/pavo.c -new file mode 100644 -index 0000000..9d6056e ---- /dev/null -+++ b/sound/soc/jz4740/pavo.c -@@ -0,0 +1,360 @@ -+/* -+ * pavo.c -- SoC audio for PAVO -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/jzcodec.h" -+#include "jz4740-pcm.h" -+#include "jz4740-i2s.h" -+ -+#define PAVO_HP 0 -+#define PAVO_MIC 1 -+#define PAVO_LINE 2 -+#define PAVO_HEADSET 3 -+#define PAVO_HP_OFF 4 -+#define PAVO_SPK_ON 0 -+#define PAVO_SPK_OFF 1 -+ -+ /* audio clock in Hz - rounded from 12.235MHz */ -+#define PAVO_AUDIO_CLOCK 12288000 -+ -+static int pavo_jack_func; -+static int pavo_spk_func; -+ -+unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) -+{ -+ unsigned short gpio_bit = 0; -+ -+ return gpio_bit; -+} -+ -+unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) -+{ -+ unsigned short gpio_bit = 0; -+ -+ return gpio_bit; -+} -+ -+static void pavo_ext_control(struct snd_soc_codec *codec) -+{ -+ int spk = 0, mic = 0, line = 0, hp = 0, hs = 0; -+ -+ /* set up jack connection */ -+ switch (pavo_jack_func) { -+ case PAVO_HP: -+ hp = 1; -+ /* set = unmute headphone */ -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ case PAVO_MIC: -+ mic = 1; -+ /* reset = mute headphone */ -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ case PAVO_LINE: -+ line = 1; -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ case PAVO_HEADSET: -+ hs = 1; -+ mic = 1; -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ } -+ -+ if (pavo_spk_func == PAVO_SPK_ON) -+ spk = 1; -+ -+ /* set the enpoints to their new connetion states */ -+ snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk); -+ snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic); -+ snd_soc_dapm_set_endpoint(codec, "Line Jack", line); -+ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp); -+ snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs); -+ -+ /* signal a DAPM event */ -+ snd_soc_dapm_sync_endpoints(codec); -+} -+ -+static int pavo_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->socdev->codec; -+ -+ /* check the jack status at stream startup */ -+ pavo_ext_control(codec); -+ return 0; -+} -+ -+/* we need to unmute the HP at shutdown as the mute burns power on pavo */ -+static void pavo_shutdown(struct snd_pcm_substream *substream) -+{ -+ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->socdev->codec;*/ -+ -+ return; -+} -+ -+static int pavo_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ int ret = 0; -+ -+ /* set codec DAI configuration */ -+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -+ if (ret < 0) -+ return ret; -+ -+ /* set cpu DAI configuration */ -+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -+ if (ret < 0) -+ return ret; -+ -+ /* set the codec system clock for DAC and ADC */ -+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZCODEC_SYSCLK, 111, -+ SND_SOC_CLOCK_IN); -+ if (ret < 0) -+ return ret; -+ -+ /* set the I2S system clock as input (unused) */ -+ ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4740_I2S_SYSCLK, 0, -+ SND_SOC_CLOCK_IN); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static struct snd_soc_ops pavo_ops = { -+ .startup = pavo_startup, -+ .hw_params = pavo_hw_params, -+ .shutdown = pavo_shutdown, -+}; -+ -+static int pavo_get_jack(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ ucontrol->value.integer.value[0] = pavo_jack_func; -+ return 0; -+} -+ -+static int pavo_set_jack(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -+ -+ if (pavo_jack_func == ucontrol->value.integer.value[0]) -+ return 0; -+ -+ pavo_jack_func = ucontrol->value.integer.value[0]; -+ pavo_ext_control(codec); -+ return 1; -+} -+ -+static int pavo_get_spk(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ ucontrol->value.integer.value[0] = pavo_spk_func; -+ return 0; -+} -+ -+static int pavo_set_spk(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -+ -+ if (pavo_spk_func == ucontrol->value.integer.value[0]) -+ return 0; -+ -+ pavo_spk_func = ucontrol->value.integer.value[0]; -+ pavo_ext_control(codec); -+ return 1; -+} -+ -+static int pavo_amp_event(struct snd_soc_dapm_widget *w, int event) -+{ -+ if (SND_SOC_DAPM_EVENT_ON(event)) -+ //set_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON); -+ ; -+ else -+ //reset_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON); -+ ; -+ -+ return 0; -+} -+ -+static int pavo_mic_event(struct snd_soc_dapm_widget *w, int event) -+{ -+ if (SND_SOC_DAPM_EVENT_ON(event)) -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); -+ ; -+ else -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); -+ ; -+ -+ return 0; -+} -+ -+/* pavo machine dapm widgets */ -+static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = { -+SND_SOC_DAPM_HP("Headphone Jack", NULL), -+SND_SOC_DAPM_MIC("Mic Jack",pavo_mic_event), -+SND_SOC_DAPM_SPK("Ext Spk", pavo_amp_event), -+SND_SOC_DAPM_LINE("Line Jack", NULL), -+SND_SOC_DAPM_HP("Headset Jack", NULL), -+}; -+ -+/* pavo machine audio map (connections to the codec pins) */ -+static const char *audio_map[][3] = { -+ -+ /* headset Jack - in = micin, out = LHPOUT*/ -+ {"Headset Jack", NULL, "LHPOUT"}, -+ -+ /* headphone connected to LHPOUT1, RHPOUT1 */ -+ {"Headphone Jack", NULL, "LHPOUT"}, -+ {"Headphone Jack", NULL, "RHPOUT"}, -+ -+ /* speaker connected to LOUT, ROUT */ -+ {"Ext Spk", NULL, "ROUT"}, -+ {"Ext Spk", NULL, "LOUT"}, -+ -+ /* mic is connected to MICIN (via right channel of headphone jack) */ -+ {"MICIN", NULL, "Mic Jack"}, -+ -+ /* Same as the above but no mic bias for line signals */ -+ {"MICIN", NULL, "Line Jack"}, -+ -+ {NULL, NULL, NULL}, -+}; -+ -+static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", -+ "Off"}; -+static const char *spk_function[] = {"On", "Off"}; -+static const struct soc_enum pavo_enum[] = { -+ SOC_ENUM_SINGLE_EXT(5, jack_function), -+ SOC_ENUM_SINGLE_EXT(2, spk_function), -+}; -+ -+static const struct snd_kcontrol_new jzcodec_pavo_controls[] = { -+ SOC_ENUM_EXT("Jack Function", pavo_enum[0], pavo_get_jack, -+ pavo_set_jack), -+ SOC_ENUM_EXT("Speaker Function", pavo_enum[1], pavo_get_spk, -+ pavo_set_spk), -+}; -+ -+/* -+ * Pavo for a jzcodec as connected on jz4740 Device -+ */ -+static int pavo_jzcodec_init(struct snd_soc_codec *codec) -+{ -+ int i, err; -+ -+ snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); -+ snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); -+ -+ /* Add pavo specific controls */ -+ for (i = 0; i < ARRAY_SIZE(jzcodec_pavo_controls); i++) { -+ err = snd_ctl_add(codec->card, -+ snd_soc_cnew(&jzcodec_pavo_controls[i],codec, NULL)); -+ if (err < 0) -+ return err; -+ } -+ -+ /* Add pavo specific widgets */ -+ for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) { -+ snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]); -+ } -+ -+ /* Set up pavo specific audio path audio_map */ -+ for(i = 0; audio_map[i][0] != NULL; i++) { -+ snd_soc_dapm_connect_input(codec, audio_map[i][0], -+ audio_map[i][1], audio_map[i][2]); -+ } -+ -+ snd_soc_dapm_sync_endpoints(codec); -+ return 0; -+} -+ -+/* pavo digital audio interface glue - connects codec <--> CPU */ -+static struct snd_soc_dai_link pavo_dai = { -+ .name = "JZCODEC", -+ .stream_name = "JZCODEC", -+ .cpu_dai = &jz4740_i2s_dai, -+ .codec_dai = &jzcodec_dai, -+ .init = pavo_jzcodec_init, -+ .ops = &pavo_ops, -+}; -+ -+/* pavo audio machine driver */ -+static struct snd_soc_machine snd_soc_machine_pavo = { -+ .name = "Pavo", -+ .dai_link = &pavo_dai, -+ .num_links = 1, -+}; -+ -+/* pavo audio subsystem */ -+static struct snd_soc_device pavo_snd_devdata = { -+ .machine = &snd_soc_machine_pavo, -+ .platform = &jz4740_soc_platform, -+ .codec_dev = &soc_codec_dev_jzcodec, -+ //.codec_data -+}; -+ -+static struct platform_device *pavo_snd_device; -+ -+static int __init pavo_init(void) -+{ -+ int ret; -+ -+ pavo_snd_device = platform_device_alloc("soc-audio", -1); -+ -+ if (!pavo_snd_device) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pavo_snd_device, &pavo_snd_devdata); -+ pavo_snd_devdata.dev = &pavo_snd_device->dev; -+ ret = platform_device_add(pavo_snd_device); -+ -+ if (ret) -+ platform_device_put(pavo_snd_device); -+ -+ return ret; -+} -+ -+static void __exit pavo_exit(void) -+{ -+ platform_device_unregister(pavo_snd_device); -+} -+ -+module_init(pavo_init); -+module_exit(pavo_exit); -+ -+/* Module information */ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("ALSA SoC Pavo"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4750/Kconfig b/sound/soc/jz4750/Kconfig -new file mode 100644 -index 0000000..7cf9b16 ---- /dev/null -+++ b/sound/soc/jz4750/Kconfig -@@ -0,0 +1,34 @@ -+config SND_JZ4750_SOC -+ tristate "SoC Audio for Ingenic jz4750 chip" -+ depends on (JZ4750_APUS || JZ4750_FUWA) && SND_SOC -+ help -+ Say Y or M if you want to add support for codecs attached to -+ the Jz4750 AC97, I2S or SSP interface. You will also need -+ to select the audio interfaces to support below. -+ -+config SND_JZ4750_SOC_APUS -+ tristate "SoC Audio support for Ingenic Jz4750 APUS board" -+ depends on SND_JZ4750_SOC -+ help -+ Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4750 APUS board. -+ -+config SND_JZ4750_AC97 -+ tristate "select AC97 protocol and AC97 codec pcm core support" -+ depends on SND_JZ4750_SOC && SND_JZ4750_SOC_APUS -+ select SND_AC97_CODEC -+ help -+ Say Y if you want to add AC97 protocol support for pcm core. -+ -+config SND_JZ4750_SOC_AC97 -+ tristate "SoC Audio (AC97 protocol) for Ingenic jz4750 chip" -+ depends on SND_JZ4750_SOC && SND_JZ4750_AC97 && SND_JZ4750_SOC_APUS -+ select AC97_BUS -+ select SND_SOC_AC97_BUS -+ help -+ Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4750 APUS board. -+ -+config SND_JZ4750_SOC_I2S -+ depends on SND_JZ4750_SOC && SND_JZ4750_SOC_APUS -+ tristate "SoC Audio (I2S protocol) for Ingenic jz4750 chip" -+ help -+ Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4750 APUS board. -diff --git a/sound/soc/jz4750/Makefile b/sound/soc/jz4750/Makefile -new file mode 100644 -index 0000000..ba5cbfa ---- /dev/null -+++ b/sound/soc/jz4750/Makefile -@@ -0,0 +1,15 @@ -+# -+# Jz4750 Platform Support -+# -+snd-soc-jz4750-objs := jz4750-pcm.o -+snd-soc-jz4750-ac97-objs := jz4750-ac97.o -+snd-soc-jz4750-i2s-objs := jz4750-i2s.o -+ -+obj-$(CONFIG_SND_JZ4750_SOC) += snd-soc-jz4750.o -+obj-$(CONFIG_SND_JZ4750_SOC_AC97) += snd-soc-jz4750-ac97.o -+obj-$(CONFIG_SND_JZ4750_SOC_I2S) += snd-soc-jz4750-i2s.o -+ -+# Jz4750 Machine Support -+snd-soc-apus-objs := apus.o -+ -+obj-$(CONFIG_SND_JZ4750_SOC_APUS) += snd-soc-apus.o -diff --git a/sound/soc/jz4750/apus.c b/sound/soc/jz4750/apus.c -new file mode 100644 -index 0000000..def2104 ---- /dev/null -+++ b/sound/soc/jz4750/apus.c -@@ -0,0 +1,357 @@ -+/* -+ * apus.c -- SoC audio for APUS -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/jzdlv.h" -+#include "jz4750-pcm.h" -+#include "jz4750-i2s.h" -+ -+#define APUS_HP 0 -+#define APUS_MIC 1 -+#define APUS_LINE 2 -+#define APUS_HEADSET 3 -+#define APUS_HP_OFF 4 -+#define APUS_SPK_ON 0 -+#define APUS_SPK_OFF 1 -+ -+static int apus_jack_func; -+static int apus_spk_func; -+ -+unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) -+{ -+ unsigned short gpio_bit = 0; -+ -+ return gpio_bit; -+} -+ -+unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) -+{ -+ unsigned short gpio_bit = 0; -+ -+ return gpio_bit; -+} -+ -+static void apus_ext_control(struct snd_soc_codec *codec) -+{ -+ int spk = 0, mic = 0, line = 0, hp = 0, hs = 0; -+ -+ /* set up jack connection */ -+ switch (apus_jack_func) { -+ case APUS_HP: -+ hp = 1; -+ /* set = unmute headphone */ -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ case APUS_MIC: -+ mic = 1; -+ /* reset = mute headphone */ -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ case APUS_LINE: -+ line = 1; -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ case APUS_HEADSET: -+ hs = 1; -+ mic = 1; -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -+ break; -+ } -+ -+ if (apus_spk_func == APUS_SPK_ON) -+ spk = 1; -+ -+ /* set the enpoints to their new connetion states */ -+ snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk); -+ snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic); -+ snd_soc_dapm_set_endpoint(codec, "Line Jack", line); -+ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp); -+ snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs); -+ -+ /* signal a DAPM event */ -+ snd_soc_dapm_sync_endpoints(codec); -+} -+ -+static int apus_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->socdev->codec; -+ -+ /* check the jack status at stream startup */ -+ apus_ext_control(codec); -+ return 0; -+} -+ -+/* we need to unmute the HP at shutdown as the mute burns power on apus */ -+static void apus_shutdown(struct snd_pcm_substream *substream) -+{ -+ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->socdev->codec;*/ -+ -+ return; -+} -+ -+static int apus_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ int ret = 0; -+ -+ /* set codec DAI configuration */ -+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -+ if (ret < 0) -+ return ret; -+ -+ /* set cpu DAI configuration */ -+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -+ if (ret < 0) -+ return ret; -+ -+ /* set the codec system clock for DAC and ADC */ -+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZDLV_SYSCLK, 111, -+ SND_SOC_CLOCK_IN); -+ if (ret < 0) -+ return ret; -+ -+ /* set the I2S system clock as input (unused) */ -+ ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4750_I2S_SYSCLK, 0, -+ SND_SOC_CLOCK_IN); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static struct snd_soc_ops apus_ops = { -+ .startup = apus_startup, -+ .hw_params = apus_hw_params, -+ .shutdown = apus_shutdown, -+}; -+ -+static int apus_get_jack(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ ucontrol->value.integer.value[0] = apus_jack_func; -+ return 0; -+} -+ -+static int apus_set_jack(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -+ -+ if (apus_jack_func == ucontrol->value.integer.value[0]) -+ return 0; -+ -+ apus_jack_func = ucontrol->value.integer.value[0]; -+ apus_ext_control(codec); -+ return 1; -+} -+ -+static int apus_get_spk(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ ucontrol->value.integer.value[0] = apus_spk_func; -+ return 0; -+} -+ -+static int apus_set_spk(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -+ -+ if (apus_spk_func == ucontrol->value.integer.value[0]) -+ return 0; -+ -+ apus_spk_func = ucontrol->value.integer.value[0]; -+ apus_ext_control(codec); -+ return 1; -+} -+ -+static int apus_amp_event(struct snd_soc_dapm_widget *w, int event) -+{ -+ if (SND_SOC_DAPM_EVENT_ON(event)) -+ //set_scoop_gpio(&corgiscoop_device.dev, APUS_SCP_APM_ON); -+ ; -+ else -+ //reset_scoop_gpio(&corgiscoop_device.dev, APUS_SCP_APM_ON); -+ ; -+ -+ return 0; -+} -+ -+static int apus_mic_event(struct snd_soc_dapm_widget *w, int event) -+{ -+ if (SND_SOC_DAPM_EVENT_ON(event)) -+ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); -+ ; -+ else -+ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); -+ ; -+ -+ return 0; -+} -+ -+/* apus machine dapm widgets */ -+static const struct snd_soc_dapm_widget jzdlv_dapm_widgets[] = { -+SND_SOC_DAPM_HP("Headphone Jack", NULL), -+SND_SOC_DAPM_MIC("Mic Jack",apus_mic_event), -+SND_SOC_DAPM_SPK("Ext Spk", apus_amp_event), -+SND_SOC_DAPM_LINE("Line Jack", NULL), -+SND_SOC_DAPM_HP("Headset Jack", NULL), -+}; -+ -+/* apus machine audio map (connections to the codec pins) */ -+static const char *audio_map[][3] = { -+ -+ /* headset Jack - in = micin, out = LHPOUT*/ -+ {"Headset Jack", NULL, "LHPOUT"}, -+ -+ /* headphone connected to LHPOUT1, RHPOUT1 */ -+ {"Headphone Jack", NULL, "LHPOUT"}, -+ {"Headphone Jack", NULL, "RHPOUT"}, -+ -+ /* speaker connected to LOUT, ROUT */ -+ {"Ext Spk", NULL, "ROUT"}, -+ {"Ext Spk", NULL, "LOUT"}, -+ -+ /* mic is connected to MICIN (via right channel of headphone jack) */ -+ {"MICIN", NULL, "Mic Jack"}, -+ -+ /* Same as the above but no mic bias for line signals */ -+ {"MICIN", NULL, "Line Jack"}, -+ -+ {NULL, NULL, NULL}, -+}; -+ -+static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", -+ "Off"}; -+static const char *spk_function[] = {"On", "Off"}; -+static const struct soc_enum apus_enum[] = { -+ SOC_ENUM_SINGLE_EXT(5, jack_function), -+ SOC_ENUM_SINGLE_EXT(2, spk_function), -+}; -+ -+static const struct snd_kcontrol_new jzdlv_apus_controls[] = { -+ SOC_ENUM_EXT("Jack Function", apus_enum[0], apus_get_jack, -+ apus_set_jack), -+ SOC_ENUM_EXT("Speaker Function", apus_enum[1], apus_get_spk, -+ apus_set_spk), -+}; -+ -+/* -+ * Apus for a jzdlv as connected on jz4750 Device -+ */ -+static int apus_jzdlv_init(struct snd_soc_codec *codec) -+{ -+ int i, err; -+ -+ snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); -+ snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); -+ -+ /* Add apus specific controls */ -+ for (i = 0; i < ARRAY_SIZE(jzdlv_apus_controls); i++) { -+ err = snd_ctl_add(codec->card, -+ snd_soc_cnew(&jzdlv_apus_controls[i],codec, NULL)); -+ if (err < 0) -+ return err; -+ } -+ -+ /* Add apus specific widgets */ -+ for(i = 0; i < ARRAY_SIZE(jzdlv_dapm_widgets); i++) { -+ snd_soc_dapm_new_control(codec, &jzdlv_dapm_widgets[i]); -+ } -+ -+ /* Set up apus specific audio path audio_map */ -+ for(i = 0; audio_map[i][0] != NULL; i++) { -+ snd_soc_dapm_connect_input(codec, audio_map[i][0], -+ audio_map[i][1], audio_map[i][2]); -+ } -+ -+ snd_soc_dapm_sync_endpoints(codec); -+ return 0; -+} -+ -+/* apus digital audio interface glue - connects codec <--> CPU */ -+static struct snd_soc_dai_link apus_dai = { -+ .name = "JZDLV", -+ .stream_name = "JZDLV", -+ .cpu_dai = &jz4750_i2s_dai, -+ .codec_dai = &jzdlv_dai, -+ .init = apus_jzdlv_init, -+ .ops = &apus_ops, -+}; -+ -+/* apus audio machine driver */ -+static struct snd_soc_machine snd_soc_machine_apus = { -+ .name = "Apus", -+ .dai_link = &apus_dai, -+ .num_links = 1, -+}; -+ -+/* apus audio subsystem */ -+static struct snd_soc_device apus_snd_devdata = { -+ .machine = &snd_soc_machine_apus, -+ .platform = &jz4750_soc_platform, -+ .codec_dev = &soc_codec_dev_jzdlv, -+ //.codec_data -+}; -+ -+static struct platform_device *apus_snd_device; -+ -+static int __init apus_init(void) -+{ -+ int ret; -+ -+ apus_snd_device = platform_device_alloc("soc-audio", -1); -+ -+ if (!apus_snd_device) -+ return -ENOMEM; -+ -+ platform_set_drvdata(apus_snd_device, &apus_snd_devdata); -+ apus_snd_devdata.dev = &apus_snd_device->dev; -+ ret = platform_device_add(apus_snd_device); -+ -+ if (ret) -+ platform_device_put(apus_snd_device); -+ -+ return ret; -+} -+ -+static void __exit apus_exit(void) -+{ -+ platform_device_unregister(apus_snd_device); -+} -+ -+module_init(apus_init); -+module_exit(apus_exit); -+ -+/* Module information */ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("ALSA SoC Apus"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4750/jz4750-ac97.c b/sound/soc/jz4750/jz4750-ac97.c -new file mode 100644 -index 0000000..84da470 ---- /dev/null -+++ b/sound/soc/jz4750/jz4750-ac97.c -@@ -0,0 +1,261 @@ -+/* -+ * linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip. -+ * -+ * Author: Richard -+ * Created: Dec 02, 2007 -+ * Copyright: Ingenic Semiconductor Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "jz4740-pcm.h" -+#include "jz4740-ac97.h" -+ -+static DEFINE_MUTEX(car_mutex); -+static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); -+static volatile long gsr_bits; -+ -+static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97, -+ unsigned short reg) -+{ -+ unsigned short val = -1; -+ volatile u32 *reg_addr; -+ -+ mutex_lock(&car_mutex); -+ -+out: mutex_unlock(&car_mutex); -+ return val; -+} -+ -+static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg, -+ unsigned short val) -+{ -+ volatile u32 *reg_addr; -+ -+ mutex_lock(&car_mutex); -+ -+ mutex_unlock(&car_mutex); -+} -+ -+static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97) -+{ -+ gsr_bits = 0; -+} -+ -+static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97) -+{ -+} -+ -+static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id) -+{ -+ long status; -+ return IRQ_NONE; -+} -+ -+struct snd_ac97_bus_ops soc_ac97_ops = { -+ .read = jz4740_ac97_read, -+ .write = jz4740_ac97_write, -+ .warm_reset = jz4740_ac97_warm_reset, -+ .reset = jz4740_ac97_cold_reset, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = { -+ .name = "AC97 PCM Stereo out", -+ .dev_addr = __PREG(PCDR), -+ .drcmr = &DRCMRTXPCDR, -+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | -+ DCMD_BURST32 | DCMD_WIDTH4, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = { -+ .name = "AC97 PCM Stereo in", -+ .dev_addr = __PREG(PCDR), -+ .drcmr = &DRCMRRXPCDR, -+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -+ DCMD_BURST32 | DCMD_WIDTH4, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = { -+ .name = "AC97 Aux PCM (Slot 5) Mono out", -+ .dev_addr = __PREG(MODR), -+ .drcmr = &DRCMRTXMODR, -+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | -+ DCMD_BURST16 | DCMD_WIDTH2, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = { -+ .name = "AC97 Aux PCM (Slot 5) Mono in", -+ .dev_addr = __PREG(MODR), -+ .drcmr = &DRCMRRXMODR, -+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -+ DCMD_BURST16 | DCMD_WIDTH2, -+}; -+ -+static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = { -+ .name = "AC97 Mic PCM (Slot 6) Mono in", -+ .dev_addr = __PREG(MCDR), -+ .drcmr = &DRCMRRXMCDR, -+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -+ DCMD_BURST16 | DCMD_WIDTH2, -+}; -+ -+#ifdef CONFIG_PM -+static int jz4740_ac97_suspend(struct platform_device *pdev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ return 0; -+} -+ -+static int jz4740_ac97_resume(struct platform_device *pdev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ return 0; -+} -+ -+#else -+#define jz4740_ac97_suspend NULL -+#define jz4740_ac97_resume NULL -+#endif -+ -+static int jz4740_ac97_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ return 0; -+} -+ -+static void jz4740_ac97_remove(struct platform_device *pdev) -+{ -+} -+ -+static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out; -+ else -+ cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in; -+ -+ return 0; -+} -+ -+static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out; -+ else -+ cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in; -+ -+ return 0; -+} -+ -+static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ return -ENODEV; -+ else -+ cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in; -+ -+ return 0; -+} -+ -+#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ -+ SNDRV_PCM_RATE_48000) -+ -+struct snd_soc_cpu_dai jz4740_ac97_dai[] = { -+{ -+ .name = "jz4740-ac97", -+ .id = 0, -+ .type = SND_SOC_DAI_AC97, -+ .probe = jz4740_ac97_probe, -+ .remove = jz4740_ac97_remove, -+ .suspend = jz4740_ac97_suspend, -+ .resume = jz4740_ac97_resume, -+ .playback = { -+ .stream_name = "AC97 Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .capture = { -+ .stream_name = "AC97 Capture", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .hw_params = jz4740_ac97_hw_params,}, -+}, -+{ -+ .name = "jz4740-ac97-aux", -+ .id = 1, -+ .type = SND_SOC_DAI_AC97, -+ .playback = { -+ .stream_name = "AC97 Aux Playback", -+ .channels_min = 1, -+ .channels_max = 1, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .capture = { -+ .stream_name = "AC97 Aux Capture", -+ .channels_min = 1, -+ .channels_max = 1, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .hw_params = jz4740_ac97_hw_aux_params,}, -+}, -+{ -+ .name = "jz4740-ac97-mic", -+ .id = 2, -+ .type = SND_SOC_DAI_AC97, -+ .capture = { -+ .stream_name = "AC97 Mic Capture", -+ .channels_min = 1, -+ .channels_max = 1, -+ .rates = JZ4740_AC97_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .hw_params = jz4740_ac97_hw_mic_params,}, -+}, -+}; -+ -+EXPORT_SYMBOL_GPL(jz4740_ac97_dai); -+EXPORT_SYMBOL_GPL(soc_ac97_ops); -+ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4750/jz4750-ac97.h b/sound/soc/jz4750/jz4750-ac97.h -new file mode 100644 -index 0000000..cd116e9 ---- /dev/null -+++ b/sound/soc/jz4750/jz4750-ac97.h -@@ -0,0 +1,21 @@ -+/* -+ * linux/sound/soc/jz4750/jz4750-ac97.h -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _JZ4750_AC97_H -+#define _JZ4750_AC97_H -+ -+#define JZ4750_DAI_AC97_HIFI 0 -+#define JZ4750_DAI_AC97_AUX 1 -+#define JZ4750_DAI_AC97_MIC 2 -+ -+extern struct snd_soc_cpu_dai jz4750_ac97_dai[3]; -+ -+/* platform data */ -+extern struct snd_ac97_bus_ops jz4750_ac97_ops; -+ -+#endif -diff --git a/sound/soc/jz4750/jz4750-i2s.c b/sound/soc/jz4750/jz4750-i2s.c -new file mode 100644 -index 0000000..887443e ---- /dev/null -+++ b/sound/soc/jz4750/jz4750-i2s.c -@@ -0,0 +1,311 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "jz4750-pcm.h" -+#include "jz4750-i2s.h" -+#include "../codecs/jzdlv.h" -+ -+static struct jz4750_dma_client jz4750_dma_client_out = { -+ .name = "I2S PCM Stereo out" -+}; -+ -+static struct jz4750_dma_client jz4750_dma_client_in = { -+ .name = "I2S PCM Stereo in" -+}; -+ -+static struct jz4750_pcm_dma_params jz4750_i2s_pcm_stereo_out = { -+ .client = &jz4750_dma_client_out, -+ .channel = DMA_ID_AIC_TX, -+ .dma_addr = AIC_DR, -+ .dma_size = 2, -+}; -+ -+static struct jz4750_pcm_dma_params jz4750_i2s_pcm_stereo_in = { -+ .client = &jz4750_dma_client_in, -+ .channel = DMA_ID_AIC_RX, -+ .dma_addr = AIC_DR, -+ .dma_size = 2, -+}; -+ -+static int jz4750_i2s_startup(struct snd_pcm_substream *substream) -+{ -+ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/ -+ -+ return 0; -+} -+ -+static int jz4750_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, -+ unsigned int fmt) -+{ -+ /* interface format */ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ /* 1 : ac97 , 0 : i2s */ -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* 0 : slave */ -+ break; -+ case SND_SOC_DAIFMT_CBM_CFS: -+ /* 1 : master */ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+* Set Jz4750 Clock source -+*/ -+static int jz4750_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, -+ int clk_id, unsigned int freq, int dir) -+{ -+ return 0; -+} -+ -+static void jz4750_snd_tx_ctrl(int on) -+{ -+ if (on) { -+ /* enable replay */ -+ __i2s_enable_transmit_dma(); -+ __i2s_enable_replay(); -+ __i2s_enable(); -+ -+ } else { -+ /* disable replay & capture */ -+ __i2s_disable_replay(); -+ __i2s_disable_record(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable(); -+ } -+} -+ -+static void jz4750_snd_rx_ctrl(int on) -+{ -+ if (on) { -+ /* enable capture */ -+ __i2s_enable_receive_dma(); -+ __i2s_enable_record(); -+ __i2s_enable(); -+ -+ } else { -+ /* disable replay & capture */ -+ __i2s_disable_replay(); -+ __i2s_disable_record(); -+ __i2s_disable_receive_dma(); -+ __i2s_disable_transmit_dma(); -+ __i2s_disable(); -+ } -+} -+ -+static int jz4750_i2s_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -+ int channels = params_channels(params); -+ -+ jz4750_snd_rx_ctrl(0); -+ jz4750_snd_rx_ctrl(0); -+ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_out; -+ -+ if (channels == 1) -+ __aic_enable_mono2stereo(); -+ else -+ __aic_disable_mono2stereo(); -+ } else -+ rtd->dai->cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_in; -+ -+#if 1 -+ switch (channels) { -+ case 1: -+ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -+ break; -+ case 2: -+ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -+ break; -+ } -+#endif -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S8: -+ __i2s_set_transmit_trigger(4); -+ __i2s_set_receive_trigger(3); -+ __i2s_set_oss_sample_size(8); -+ __i2s_set_iss_sample_size(8); -+ break; -+ case SNDRV_PCM_FORMAT_S16_LE: -+ /* playback sample:16 bits, burst:16 bytes */ -+ __i2s_set_transmit_trigger(4); -+ /* capture sample:16 bits, burst:16 bytes */ -+ __i2s_set_receive_trigger(3); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ /* DAC path and ADC path */ -+ write_codec_file(2, 0x00); -+ break; -+ } -+ -+ return 0; -+} -+ -+static int jz4750_i2s_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ int ret = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ jz4750_snd_rx_ctrl(1); -+ else -+ jz4750_snd_tx_ctrl(1); -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ jz4750_snd_rx_ctrl(0); -+ else -+ jz4750_snd_tx_ctrl(0); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static void jz4750_i2s_shutdown(struct snd_pcm_substream *substream) -+{ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ } else { -+ } -+ -+ return; -+} -+ -+static int jz4750_i2s_probe(struct platform_device *pdev) -+{ -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ mdelay(2); -+ -+ __i2s_disable(); -+ mdelay(2); -+ REG_AIC_I2SCR = 0x10; -+ __i2s_disable(); -+ __i2s_internal_codec(); -+ __i2s_as_slave(); -+ __i2s_select_i2s(); -+ __aic_select_i2s(); -+ __i2s_set_oss_sample_size(16); -+ __i2s_set_iss_sample_size(16); -+ __aic_play_lastsample(); -+ -+ __i2s_disable_record(); -+ __i2s_disable_replay(); -+ __i2s_disable_loopback(); -+ __i2s_set_transmit_trigger(7); -+ __i2s_set_receive_trigger(7); -+ -+ jz4750_snd_tx_ctrl(0); -+ jz4750_snd_rx_ctrl(0); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int jz4750_i2s_suspend(struct platform_device *dev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ if (!dai->active) -+ return 0; -+ -+ return 0; -+} -+ -+static int jz4750_i2s_resume(struct platform_device *pdev, -+ struct snd_soc_cpu_dai *dai) -+{ -+ if (!dai->active) -+ return 0; -+ -+ return 0; -+} -+ -+#else -+#define jz4750_i2s_suspend NULL -+#define jz4750_i2s_resume NULL -+#endif -+ -+#define JZ4750_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -+ SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\ -+ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\ -+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ -+ SNDRV_PCM_RATE_48000) -+ -+struct snd_soc_cpu_dai jz4750_i2s_dai = { -+ .name = "jz4750-i2s", -+ .id = 0, -+ .type = SND_SOC_DAI_I2S, -+ .probe = jz4750_i2s_probe, -+ .suspend = jz4750_i2s_suspend, -+ .resume = jz4750_i2s_resume, -+ .playback = { -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZ4750_I2S_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, -+ .capture = { -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = JZ4750_I2S_RATES, -+ .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, -+ .ops = { -+ .startup = jz4750_i2s_startup, -+ .shutdown = jz4750_i2s_shutdown, -+ .trigger = jz4750_i2s_trigger, -+ .hw_params = jz4750_i2s_hw_params,}, -+ .dai_ops = { -+ .set_fmt = jz4750_i2s_set_dai_fmt, -+ .set_sysclk = jz4750_i2s_set_dai_sysclk, -+ }, -+}; -+ -+EXPORT_SYMBOL_GPL(jz4750_i2s_dai); -+ -+/* Module information */ -+MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn"); -+MODULE_DESCRIPTION("jz4750 I2S SoC Interface"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4750/jz4750-i2s.h b/sound/soc/jz4750/jz4750-i2s.h -new file mode 100644 -index 0000000..c227cae ---- /dev/null -+++ b/sound/soc/jz4750/jz4750-i2s.h -@@ -0,0 +1,18 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _JZ4750_I2S_H -+#define _JZ4750_I2S_H -+ -+/* jz4750 DAI ID's */ -+#define JZ4750_DAI_I2S 0 -+ -+/* I2S clock */ -+#define JZ4750_I2S_SYSCLK 0 -+ -+extern struct snd_soc_cpu_dai jz4750_i2s_dai; -+ -+#endif -diff --git a/sound/soc/jz4750/jz4750-pcm.c b/sound/soc/jz4750/jz4750-pcm.c -new file mode 100644 -index 0000000..e50d1c8 ---- /dev/null -+++ b/sound/soc/jz4750/jz4750-pcm.c -@@ -0,0 +1,689 @@ -+/* -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include "jz4750-pcm.h" -+ -+static long sum_bytes = 0; -+static int first_transfer = 0; -+static int printk_flag = 0; -+static int tran_bit = 0; -+#ifdef CONFIG_SND_OSSEMUL -+static int hw_params_cnt = 0; -+#endif -+ -+struct jz4750_dma_buf_aic { -+ struct jz4750_dma_buf_aic *next; -+ int size; /* buffer size in bytes */ -+ dma_addr_t data; /* start of DMA data */ -+ dma_addr_t ptr; /* where the DMA got to [1] */ -+ void *id; /* client's id */ -+}; -+ -+struct jz4750_runtime_data { -+ spinlock_t lock; -+ int state; -+ int aic_dma_flag; /* start dma transfer or not */ -+ unsigned int dma_loaded; -+ unsigned int dma_limit; -+ unsigned int dma_period; -+ dma_addr_t dma_start; -+ dma_addr_t dma_pos; -+ dma_addr_t dma_end; -+ struct jz4750_pcm_dma_params *params; -+ -+ dma_addr_t user_cur_addr; /* user current write buffer start address */ -+ unsigned int user_cur_len; /* user current write buffer length */ -+ -+ /* buffer list and information */ -+ struct jz4750_dma_buf_aic *curr; /* current dma buffer */ -+ struct jz4750_dma_buf_aic *next; /* next buffer to load */ -+ struct jz4750_dma_buf_aic *end; /* end of queue */ -+ -+}; -+ -+/* identify hardware playback capabilities */ -+static const struct snd_pcm_hardware jz4750_pcm_hardware = { -+ .info = SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_PAUSE | -+ SNDRV_PCM_INFO_RESUME | -+ SNDRV_PCM_INFO_MMAP_VALID | -+ SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_BLOCK_TRANSFER, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_U16_LE | -+ SNDRV_PCM_FMTBIT_U8 | -+ SNDRV_PCM_FMTBIT_S8, -+ .rates = SNDRV_PCM_RATE_8000_96000/*0x3fe*/, -+ .rate_min = 8000, -+ .rate_max = 96000, -+ .channels_min = 1,//2 -+ .channels_max = 2, -+ .buffer_bytes_max = 128 * 1024,//16 * 1024 -+ .period_bytes_min = PAGE_SIZE, -+ .period_bytes_max = PAGE_SIZE * 2, -+ .periods_min = 2, -+ .periods_max = 128,//16, -+ .fifo_size = 32, -+}; -+ -+/* jz4750__dma_buf_enqueue -+ * -+ * queue an given buffer for dma transfer. -+ * -+ * data the physical address of the buffer data -+ * size the size of the buffer in bytes -+ * -+*/ -+static int jz4750_dma_buf_enqueue(struct jz4750_runtime_data *prtd, dma_addr_t data, int size) -+{ -+ struct jz4750_dma_buf_aic *aic_buf; -+ -+ aic_buf = kzalloc(sizeof(struct jz4750_dma_buf_aic), GFP_KERNEL); -+ if (aic_buf == NULL) { -+ printk("aic buffer allocate failed,no memory!\n"); -+ return -ENOMEM; -+ } -+ aic_buf->next = NULL; -+ aic_buf->data = aic_buf->ptr = data; -+ aic_buf->size = size; -+ if( prtd->curr == NULL) { -+ prtd->curr = aic_buf; -+ prtd->end = aic_buf; -+ prtd->next = NULL; -+ } else { -+ if (prtd->end == NULL) -+ printk("prtd->end is NULL\n"); -+ prtd->end->next = aic_buf; -+ prtd->end = aic_buf; -+ } -+ -+ /* if necessary, update the next buffer field */ -+ if (prtd->next == NULL) -+ prtd->next = aic_buf; -+ -+ return 0; -+} -+ -+void audio_start_dma(struct jz4750_runtime_data *prtd, int mode) -+{ -+ unsigned long flags; -+ struct jz4750_dma_buf_aic *aic_buf; -+ int channel; -+ -+ switch (mode) { -+ case DMA_MODE_WRITE: -+ /* free cur aic_buf */ -+ if (first_transfer == 1) { -+ first_transfer = 0; -+ } else { -+ aic_buf = prtd->curr; -+ if (aic_buf != NULL) { -+ prtd->curr = aic_buf->next; -+ prtd->next = aic_buf->next; -+ aic_buf->next = NULL; -+ kfree(aic_buf); -+ aic_buf = NULL; -+ } -+ } -+ -+ aic_buf = prtd->next; -+ channel = prtd->params->channel; -+ if (aic_buf) { -+ flags = claim_dma_lock(); -+ disable_dma(channel); -+ jz_set_alsa_dma(channel, mode, tran_bit); -+ set_dma_addr(channel, aic_buf->data); -+ set_dma_count(channel, aic_buf->size); -+ enable_dma(channel); -+ release_dma_lock(flags); -+ prtd->aic_dma_flag |= AIC_START_DMA; -+ } else { -+ printk("next buffer is NULL for playback\n"); -+ prtd->aic_dma_flag &= ~AIC_START_DMA; -+ return; -+ } -+ break; -+ case DMA_MODE_READ: -+ /* free cur aic_buf */ -+ if (first_transfer == 1) { -+ first_transfer = 0; -+ } else { -+ aic_buf = prtd->curr; -+ if (aic_buf != NULL) { -+ prtd->curr = aic_buf->next; -+ prtd->next = aic_buf->next; -+ aic_buf->next = NULL; -+ kfree(aic_buf); -+ aic_buf = NULL; -+ } -+ } -+ -+ aic_buf = prtd->next; -+ channel = prtd->params->channel; -+ -+ if (aic_buf) { -+ flags = claim_dma_lock(); -+ disable_dma(channel); -+ jz_set_alsa_dma(channel, mode, tran_bit); -+ set_dma_addr(channel, aic_buf->data); -+ set_dma_count(channel, aic_buf->size); -+ enable_dma(channel); -+ release_dma_lock(flags); -+ prtd->aic_dma_flag |= AIC_START_DMA; -+ } else { -+ printk("next buffer is NULL for capture\n"); -+ prtd->aic_dma_flag &= ~AIC_START_DMA; -+ return; -+ } -+ break; -+ } -+} -+ -+/* -+ * place a dma buffer onto the queue for the dma system to handle. -+*/ -+static void jz4750_pcm_enqueue(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd = runtime->private_data; -+ /*struct snd_dma_buffer *buf = &substream->dma_buffer;*/ -+ dma_addr_t pos = prtd->dma_pos; -+ int ret; -+ -+ while (prtd->dma_loaded < prtd->dma_limit) { -+ unsigned long len = prtd->dma_period; -+ -+ if ((pos + len) > prtd->dma_end) { -+ len = prtd->dma_end - pos; -+ } -+ ret = jz4750_dma_buf_enqueue(prtd, pos, len); -+ if (ret == 0) { -+ prtd->dma_loaded++; -+ pos += prtd->dma_period; -+ if (pos >= prtd->dma_end) -+ pos = prtd->dma_start; -+ } else -+ break; -+ } -+ -+ prtd->dma_pos = pos; -+} -+ -+/* -+ * call the function:jz4750_pcm_dma_irq() after DMA has transfered the current buffer -+ */ -+static irqreturn_t jz4750_pcm_dma_irq(int dma_ch, void *dev_id) -+{ -+ struct snd_pcm_substream *substream = dev_id; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd = runtime->private_data; -+ /*struct jz4750_dma_buf_aic *aic_buf = prtd->curr;*/ -+ int channel = prtd->params->channel; -+ unsigned long flags; -+ -+ disable_dma(channel); -+ prtd->aic_dma_flag &= ~AIC_START_DMA; -+ /* must clear TT bit in DCCSR to avoid interrupt again */ -+ if (__dmac_channel_transmit_end_detected(channel)) { -+ __dmac_channel_clear_transmit_end(channel); -+ } -+ if (__dmac_channel_transmit_halt_detected(channel)) { -+ __dmac_channel_clear_transmit_halt(channel); -+ } -+ -+ if (__dmac_channel_address_error_detected(channel)) { -+ __dmac_channel_clear_address_error(channel); -+ } -+ if (substream) -+ snd_pcm_period_elapsed(substream); -+ -+ spin_lock(&prtd->lock); -+ prtd->dma_loaded--; -+ if (prtd->state & ST_RUNNING) { -+ jz4750_pcm_enqueue(substream); -+ } -+ spin_unlock(&prtd->lock); -+ -+ local_irq_save(flags); -+ if (prtd->state & ST_RUNNING) { -+ if (prtd->dma_loaded) { -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ audio_start_dma(prtd, DMA_MODE_WRITE); -+ else -+ audio_start_dma(prtd, DMA_MODE_READ); -+ } -+ } -+ local_irq_restore(flags); -+ return IRQ_HANDLED; -+} -+ -+/* some parameter about DMA operation */ -+static int jz4750_pcm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd = runtime->private_data; -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct jz4750_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; -+ size_t totbytes = params_buffer_bytes(params); -+ int ret; -+ -+#ifdef CONFIG_SND_OSSEMUL -+ if (hw_params_cnt) -+ return 0; -+ else -+ hw_params_cnt++ ; -+#endif -+ -+ if (!dma) -+ return 0; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S8: -+ tran_bit = 8; -+ break; -+ case SNDRV_PCM_FORMAT_S16_LE: -+ tran_bit = 16; -+ break; -+ } -+ -+ /* prepare DMA */ -+ prtd->params = dma; -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ ret = jz_request_dma(DMA_ID_AIC_TX, prtd->params->client->name, -+ jz4750_pcm_dma_irq, IRQF_DISABLED, substream); -+ if (ret < 0) -+ return ret; -+ prtd->params->channel = ret; -+ } else { -+ ret = jz_request_dma(DMA_ID_AIC_RX, prtd->params->client->name, -+ jz4750_pcm_dma_irq, IRQF_DISABLED, substream); -+ if (ret < 0) -+ return ret; -+ prtd->params->channel = ret; -+ } -+ -+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); -+ runtime->dma_bytes = totbytes; -+ -+ spin_lock_irq(&prtd->lock); -+ prtd->dma_loaded = 0; -+ prtd->aic_dma_flag = 0; -+ prtd->dma_limit = runtime->hw.periods_min; -+ prtd->dma_period = params_period_bytes(params); -+ prtd->dma_start = runtime->dma_addr; -+ prtd->dma_pos = prtd->dma_start; -+ prtd->dma_end = prtd->dma_start + totbytes; -+ prtd->curr = NULL; -+ prtd->next = NULL; -+ prtd->end = NULL; -+ sum_bytes = 0; -+ first_transfer = 1; -+ printk_flag = 0; -+ -+ __dmac_disable_descriptor(prtd->params->channel); -+ __dmac_channel_disable_irq(prtd->params->channel); -+ spin_unlock_irq(&prtd->lock); -+ -+ return ret; -+} -+ -+static int jz4750_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+ struct jz4750_runtime_data *prtd = substream->runtime->private_data; -+ -+ snd_pcm_set_runtime_buffer(substream, NULL); -+ if (prtd->params) { -+ jz_free_dma(prtd->params->channel); -+ prtd->params = NULL; -+ } -+ -+ return 0; -+} -+ -+/* set some dma para for playback/capture */ -+static int jz4750_dma_ctrl(int channel) -+{ -+ disable_dma(channel); -+ -+ /* must clear TT bit in DCCSR to avoid interrupt again */ -+ if (__dmac_channel_transmit_end_detected(channel)) { -+ __dmac_channel_clear_transmit_end(channel); -+ } -+ if (__dmac_channel_transmit_halt_detected(channel)) { -+ __dmac_channel_clear_transmit_halt(channel); -+ } -+ -+ if (__dmac_channel_address_error_detected(channel)) { -+ __dmac_channel_clear_address_error(channel); -+ } -+ -+ return 0; -+ -+} -+ -+static int jz4750_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ struct jz4750_runtime_data *prtd = substream->runtime->private_data; -+ int ret = 0; -+ -+ /* return if this is a bufferless transfer e.g */ -+ if (!prtd->params) -+ return 0; -+ -+ /* flush the DMA channel and DMA channel bit check */ -+ jz4750_dma_ctrl(prtd->params->channel); -+ prtd->dma_loaded = 0; -+ prtd->dma_pos = prtd->dma_start; -+ -+ /* enqueue dma buffers */ -+ jz4750_pcm_enqueue(substream); -+ -+ return ret; -+ -+} -+ -+static int jz4750_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd = runtime->private_data; -+ -+ int ret = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ prtd->state |= ST_RUNNING; -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ audio_start_dma(prtd, DMA_MODE_WRITE); -+ } else { -+ audio_start_dma(prtd, DMA_MODE_READ); -+ } -+ -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ prtd->state &= ~ST_RUNNING; -+ break; -+ -+ case SNDRV_PCM_TRIGGER_RESUME: -+ printk(" RESUME \n"); -+ break; -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ printk(" RESTART \n"); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static snd_pcm_uframes_t -+jz4750_pcm_pointer(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd = runtime->private_data; -+ struct jz4750_dma_buf_aic *aic_buf = prtd->curr; -+ long count,res; -+ -+ dma_addr_t ptr; -+ snd_pcm_uframes_t x; -+ int channel = prtd->params->channel; -+ -+ spin_lock(&prtd->lock); -+#if 1 -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ res = ptr - prtd->dma_start; -+ } else { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ res = ptr - prtd->dma_start; -+ } -+ -+# else -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ REG_DMAC_DSAR(channel) = ptr; -+ res = ptr - prtd->dma_start; -+ } else { -+ ptr = REG_DMAC_DSAR(channel); -+ if (ptr == 0x0) -+ printk("\ndma address is 00000000 in running!\n"); -+ res = ptr - prtd->dma_start; -+ } -+ } else { -+ if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { -+ count = get_dma_residue(channel); -+ count = aic_buf->size - count; -+ ptr = aic_buf->data + count; -+ REG_DMAC_DTAR(channel) = ptr; -+ res = ptr - prtd->dma_start; -+ } else { -+ ptr = REG_DMAC_DTAR(channel); -+ if (ptr == 0x0) -+ printk("\ndma address is 00000000 in running!\n"); -+ res = ptr - prtd->dma_start; -+ } -+ } -+#endif -+ spin_unlock(&prtd->lock); -+ x = bytes_to_frames(runtime, res); -+ if (x == runtime->buffer_size) -+ x = 0; -+ -+ return x; -+} -+ -+static int jz4750_pcm_open(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd; -+ -+#ifdef CONFIG_SND_OSSEMUL -+ hw_params_cnt = 0; -+#endif -+ REG_DMAC_DMACKE(0) = 0x3f; -+ REG_DMAC_DMACKE(1) = 0x3f; -+ snd_soc_set_runtime_hwparams(substream, &jz4750_pcm_hardware); -+ prtd = kzalloc(sizeof(struct jz4750_runtime_data), GFP_KERNEL); -+ if (prtd == NULL) -+ return -ENOMEM; -+ -+ spin_lock_init(&prtd->lock); -+ -+ runtime->private_data = prtd; -+ -+ return 0; -+} -+ -+static int jz4750_pcm_close(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct jz4750_runtime_data *prtd = runtime->private_data; -+ struct jz4750_dma_buf_aic *aic_buf = NULL; -+ -+#ifdef CONFIG_SND_OSSEMUL -+ hw_params_cnt = 0; -+#endif -+ -+ if (prtd) -+ aic_buf = prtd->curr; -+ -+ while (aic_buf != NULL) { -+ prtd->curr = aic_buf->next; -+ prtd->next = aic_buf->next; -+ aic_buf->next = NULL; -+ kfree(aic_buf); -+ aic_buf = NULL; -+ aic_buf = prtd->curr; -+ } -+ -+ if (prtd) { -+ prtd->curr = NULL; -+ prtd->next = NULL; -+ prtd->end = NULL; -+ kfree(prtd); -+ } -+ -+ return 0; -+} -+ -+static int jz4750_pcm_mmap(struct snd_pcm_substream *substream, -+ struct vm_area_struct *vma)//include/linux/mm.h -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ unsigned long start; -+ unsigned long off; -+ u32 len; -+ int ret = -ENXIO; -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ start = runtime->dma_addr; -+ -+ len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes); -+ start &= PAGE_MASK; -+ -+ if ((vma->vm_end - vma->vm_start + off) > len) { -+ return -EINVAL; -+ } -+ -+ off += start; -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ vma->vm_flags |= VM_IO; -+ -+#if defined(CONFIG_MIPS32) -+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; -+ /* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */ -+#endif -+ ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot); -+ -+ return ret; -+} -+ -+struct snd_pcm_ops jz4750_pcm_ops = { -+ .open = jz4750_pcm_open, -+ .close = jz4750_pcm_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = jz4750_pcm_hw_params, -+ .hw_free = jz4750_pcm_hw_free, -+ .prepare = jz4750_pcm_prepare, -+ .trigger = jz4750_pcm_trigger, -+ .pointer = jz4750_pcm_pointer, -+ .mmap = jz4750_pcm_mmap, -+}; -+ -+static int jz4750_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -+{ -+ struct snd_pcm_substream *substream = pcm->streams[stream].substream; -+ struct snd_dma_buffer *buf = &substream->dma_buffer; -+ size_t size = jz4750_pcm_hardware.buffer_bytes_max; -+ buf->dev.type = SNDRV_DMA_TYPE_DEV; -+ buf->dev.dev = pcm->card->dev; -+ buf->private_data = NULL; -+ -+ /*buf->area = dma_alloc_coherent(pcm->card->dev, size, -+ &buf->addr, GFP_KERNEL);*/ -+ buf->area = dma_alloc_noncoherent(pcm->card->dev, size, -+ &buf->addr, GFP_KERNEL); -+ if (!buf->area) -+ return -ENOMEM; -+ buf->bytes = size; -+ return 0; -+} -+ -+static void jz4750_pcm_free_dma_buffers(struct snd_pcm *pcm) -+{ -+ struct snd_pcm_substream *substream; -+ struct snd_dma_buffer *buf; -+ int stream; -+ -+ for (stream = 0; stream < 2; stream++) { -+ substream = pcm->streams[stream].substream; -+ if (!substream) -+ continue; -+ -+ buf = &substream->dma_buffer; -+ if (!buf->area) -+ continue; -+ -+ dma_free_noncoherent(pcm->card->dev, buf->bytes, -+ buf->area, buf->addr); -+ buf->area = NULL; -+ } -+} -+ -+static u64 jz4750_pcm_dmamask = DMA_32BIT_MASK; -+ -+int jz4750_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai, -+ struct snd_pcm *pcm) -+{ -+ int ret = 0; -+ -+ if (!card->dev->dma_mask) -+ card->dev->dma_mask = &jz4750_pcm_dmamask; -+ if (!card->dev->coherent_dma_mask) -+ card->dev->coherent_dma_mask = DMA_32BIT_MASK; -+ -+ if (dai->playback.channels_min) { -+ ret = jz4750_pcm_preallocate_dma_buffer(pcm, -+ SNDRV_PCM_STREAM_PLAYBACK); -+ if (ret) -+ goto out; -+ } -+ -+ if (dai->capture.channels_min) { -+ ret = jz4750_pcm_preallocate_dma_buffer(pcm, -+ SNDRV_PCM_STREAM_CAPTURE); -+ if (ret) -+ goto out; -+ } -+ out: -+ -+ return ret; -+} -+ -+struct snd_soc_platform jz4750_soc_platform = { -+ .name = "jz4750-audio", -+ .pcm_ops = &jz4750_pcm_ops, -+ .pcm_new = jz4750_pcm_new, -+ .pcm_free = jz4750_pcm_free_dma_buffers, -+}; -+ -+EXPORT_SYMBOL_GPL(jz4750_soc_platform); -+ -+MODULE_AUTHOR("Richard"); -+MODULE_DESCRIPTION("Ingenic Jz4750 PCM DMA module"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/soc/jz4750/jz4750-pcm.h b/sound/soc/jz4750/jz4750-pcm.h -new file mode 100644 -index 0000000..d7d4f72 ---- /dev/null -+++ b/sound/soc/jz4750/jz4750-pcm.h -@@ -0,0 +1,33 @@ -+/* -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _JZ4750_PCM_H -+#define _JZ4750_PCM_H -+ -+#include -+ -+#define ST_RUNNING (1<<0) -+#define ST_OPENED (1<<1) -+ -+#define AIC_START_DMA (1<<0) -+#define AIC_END_DMA (1<<1) -+ -+struct jz4750_dma_client { -+ char *name; -+}; -+ -+struct jz4750_pcm_dma_params { -+ struct jz4750_dma_client *client; /* stream identifier */ -+ int channel; /* Channel ID */ -+ dma_addr_t dma_addr; -+ int dma_size; /* Size of the DMA transfer */ -+}; -+ -+/* platform data */ -+extern struct snd_soc_platform jz4750_soc_platform; -+ -+#endif diff --git a/target/linux/xburst/patches-2.6.31/001-core.patch b/target/linux/xburst/patches-2.6.31/001-core.patch new file mode 100644 index 000000000..a958aaa98 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/001-core.patch @@ -0,0 +1,726 @@ +From ac50b482e2278cdff65e67c8a31079bf9c5ae289 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:47:08 +0200 +Subject: [PATCH] core + +--- + arch/mips/Kconfig | 48 +++++ + arch/mips/Makefile | 18 ++ + arch/mips/boot/Makefile | 23 ++- + arch/mips/include/asm/bootinfo.h | 6 + + arch/mips/include/asm/cpu.h | 13 ++- + arch/mips/include/asm/mach-generic/irq.h | 2 +- + arch/mips/include/asm/r4kcache.h | 231 ++++++++++++++++++++++ + arch/mips/include/asm/suspend.h | 3 + + arch/mips/kernel/cpu-probe.c | 21 ++ + arch/mips/kernel/signal.c | 6 + + arch/mips/kernel/unaligned.c | 5 + + arch/mips/mm/c-r4k.c | 30 +++ + arch/mips/mm/cache.c | 2 + + arch/mips/mm/tlbex.c | 5 + + include/linux/suspend.h | 315 ------------------------------ + 15 files changed, 409 insertions(+), 319 deletions(-) + delete mode 100644 include/linux/suspend.h + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 3ca0fe1..e8f8027 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -671,6 +671,29 @@ source "arch/mips/cavium-octeon/Kconfig" + + endmenu + ++##################################################### ++# Ingenic SOC series ++##################################################### ++ ++config SOC_JZ4720 ++ bool ++ select JZSOC ++ ++config SOC_JZ4740 ++ bool ++ select JZSOC ++ ++config JZSOC ++ bool ++ select JZRISC ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_SUPPORTS_32BIT_KERNEL ++ ++config JZRISC ++ bool ++ ++#################################################### ++ + config RWSEM_GENERIC_SPINLOCK + bool + default y +@@ -1893,6 +1916,14 @@ config NR_CPUS + + source "kernel/time/Kconfig" + ++# the value of (max order + 1) ++config FORCE_MAX_ZONEORDER ++ prompt "MAX_ZONEORDER" ++ int ++ default "12" ++ help ++ The max memory that can be allocated = 4KB * 2^(CONFIG_FORCE_MAX_ZONEORDER - 1) ++ + # + # Timer Interrupt Frequency Configuration + # +@@ -2164,6 +2195,23 @@ config BINFMT_ELF32 + + endmenu + ++menu "CPU Frequency scaling" ++ ++config CPU_FREQ_JZ ++ tristate "CPUfreq driver for JZ CPUs" ++ depends on JZSOC ++ default n ++ help ++ This enables the CPUfreq driver for JZ CPUs. ++ ++ If in doubt, say N. ++ ++if (CPU_FREQ_JZ) ++source "drivers/cpufreq/Kconfig" ++endif ++ ++endmenu ++ + menu "Power management options" + + config ARCH_HIBERNATION_POSSIBLE +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index 861da51..14a6f9a 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -180,6 +180,14 @@ cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 + load-$(CONFIG_AR7) += 0xffffffff94100000 + + # ++# Commond Ingenic JZ4740 series ++# ++ ++core-$(CONFIG_SOC_JZ4740) += arch/mips/jz4740/ ++cflags-$(CONFIG_SOC_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 ++load-$(CONFIG_SOC_JZ4740) += 0xffffffff80010000 ++ ++# + # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. + # + core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ +@@ -711,6 +719,12 @@ makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1) + + all: $(all-y) + ++uImage: $(vmlinux-32) ++ +@$(call makeboot,$@) ++ ++zImage: $(vmlinux-32) ++ +@$(call makeboot,$@) ++ + vmlinux.bin: $(vmlinux-32) + +@$(call makeboot,$@) + +@@ -740,6 +754,7 @@ install: + + archclean: + @$(MAKE) $(clean)=arch/mips/boot ++ @$(MAKE) $(clean)=arch/mips/boot/compressed + @$(MAKE) $(clean)=arch/mips/lasat + + define archhelp +@@ -747,6 +762,9 @@ define archhelp + echo ' vmlinux.ecoff - ECOFF boot image' + echo ' vmlinux.bin - Raw binary boot image' + echo ' vmlinux.srec - SREC boot image' ++ echo ' uImage - u-boot format image (arch/$(ARCH)/boot/uImage)' ++ echo ' zImage - Compressed binary image (arch/$(ARCH)/boot/compressed/zImage)' ++ echo ' vmlinux.bin - Uncompressed binary image (arch/$(ARCH)/boot/vmlinux.bin)' + echo + echo ' These will be default as apropriate for a configured platform.' + endef +diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile +index 2a209d7..1cfce3e 100644 +--- a/arch/mips/boot/Makefile ++++ b/arch/mips/boot/Makefile +@@ -7,6 +7,9 @@ + # Copyright (C) 2004 Maciej W. Rozycki + # + ++# This one must match the LOADADDR in arch/mips/Makefile! ++LOADADDR=0x80010000 ++ + # + # Some DECstations need all possible sections of an ECOFF executable + # +@@ -25,7 +28,7 @@ strip-flags = $(addprefix --remove-section=,$(drop-sections)) + + VMLINUX = vmlinux + +-all: vmlinux.ecoff vmlinux.srec addinitrd ++all: vmlinux.ecoff vmlinux.srec addinitrd uImage zImage + + vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) + $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS) +@@ -42,8 +45,24 @@ vmlinux.srec: $(VMLINUX) + $(obj)/addinitrd: $(obj)/addinitrd.c + $(HOSTCC) -o $@ $^ + ++uImage: $(VMLINUX) vmlinux.bin ++ rm -f $(obj)/vmlinux.bin.gz ++ gzip -9 $(obj)/vmlinux.bin ++ mkimage -A mips -O linux -T kernel -C gzip \ ++ -a $(LOADADDR) -e $(shell sh ./$(obj)/tools/entry $(NM) $(VMLINUX) ) \ ++ -n 'Linux-$(KERNELRELEASE)' \ ++ -d $(obj)/vmlinux.bin.gz $(obj)/uImage ++ @echo ' Kernel: arch/mips/boot/$@ is ready' ++ ++zImage: ++ $(Q)$(MAKE) $(build)=$(obj)/compressed loadaddr=$(LOADADDR) $@ ++ @echo ' Kernel: arch/mips/boot/compressed/$@ is ready' ++ + clean-files += addinitrd \ + elf2ecoff \ + vmlinux.bin \ + vmlinux.ecoff \ +- vmlinux.srec ++ vmlinux.srec \ ++ vmlinux.bin.gz \ ++ uImage \ ++ zImage +diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h +index 610fe3a..8451d28 100644 +--- a/arch/mips/include/asm/bootinfo.h ++++ b/arch/mips/include/asm/bootinfo.h +@@ -57,6 +57,12 @@ + #define MACH_MIKROTIK_RB532 0 /* Mikrotik RouterBoard 532 */ + #define MACH_MIKROTIK_RB532A 1 /* Mikrotik RouterBoard 532A */ + ++/* ++ * Valid machtype for group INGENIC ++ */ ++#define MACH_INGENIC_JZ4720 0 /* JZ4730 SOC */ ++#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */ ++ + #define CL_SIZE COMMAND_LINE_SIZE + + extern char *system_type; +diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h +index 3bdc0e3..904c574 100644 +--- a/arch/mips/include/asm/cpu.h ++++ b/arch/mips/include/asm/cpu.h +@@ -34,7 +34,7 @@ + #define PRID_COMP_LSI 0x080000 + #define PRID_COMP_LEXRA 0x0b0000 + #define PRID_COMP_CAVIUM 0x0d0000 +- ++#define PRID_COMP_INGENIC 0xd00000 + + /* + * Assigned values for the product ID register. In order to detect a +@@ -127,6 +127,12 @@ + #define PRID_IMP_CAVIUM_CN52XX 0x0700 + + /* ++ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC ++ */ ++ ++#define PRID_IMP_JZRISC 0x0200 ++ ++/* + * Definitions for 7:0 on legacy processors + */ + +@@ -217,6 +223,11 @@ enum cpu_type_enum { + CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2, + CPU_CAVIUM_OCTEON, + ++ /* ++ * Ingenic class processors ++ */ ++ CPU_JZRISC, CPU_XBURST, ++ + CPU_LAST + }; + +diff --git a/arch/mips/include/asm/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h +index 70d9a25..73b7a83 100644 +--- a/arch/mips/include/asm/mach-generic/irq.h ++++ b/arch/mips/include/asm/mach-generic/irq.h +@@ -9,7 +9,7 @@ + #define __ASM_MACH_GENERIC_IRQ_H + + #ifndef NR_IRQS +-#define NR_IRQS 128 ++#define NR_IRQS 256 + #endif + + #ifdef CONFIG_I8259 +diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h +index 387bf59..b500056 100644 +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -17,6 +17,58 @@ + #include + #include + ++#ifdef CONFIG_JZRISC ++ ++#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 */ +diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h +index 294cdb6..94dc597 100644 +--- a/arch/mips/include/asm/suspend.h ++++ b/arch/mips/include/asm/suspend.h +@@ -2,6 +2,9 @@ + #define __ASM_SUSPEND_H + + static inline int arch_prepare_suspend(void) { return 0; } ++#if defined(CONFIG_PM) && defined(CONFIG_JZSOC) ++extern int jz_pm_init(void); ++#endif + + /* References to section boundaries */ + extern const void __nosave_begin, __nosave_end; +diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c +index 1abe990..4535ae7 100644 +--- a/arch/mips/kernel/cpu-probe.c ++++ b/arch/mips/kernel/cpu-probe.c +@@ -160,6 +160,7 @@ void __init check_wait(void) + case CPU_PR4450: + case CPU_BCM3302: + case CPU_CAVIUM_OCTEON: ++ case CPU_JZRISC: + cpu_wait = r4k_wait; + break; + +@@ -888,6 +889,23 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu) + } + } + ++static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) ++{ ++ decode_configs(c); ++ c->options &= ~MIPS_CPU_COUNTER; /* JZRISC does not implement the CP0 counter. */ ++ switch (c->processor_id & 0xff00) { ++ case PRID_IMP_JZRISC: ++ c->cputype = CPU_JZRISC; ++ c->isa_level = MIPS_CPU_ISA_M32R1; ++ c->tlbsize = 32; ++ __cpu_name[cpu] = "Ingenic JZRISC"; ++ break; ++ default: ++ panic("Unknown Ingenic Processor ID!"); ++ break; ++ } ++} ++ + const char *__cpu_name[NR_CPUS]; + + __cpuinit void cpu_probe(void) +@@ -925,6 +943,9 @@ __cpuinit void cpu_probe(void) + case PRID_COMP_CAVIUM: + cpu_probe_cavium(c, cpu); + break; ++ case PRID_COMP_INGENIC: ++ cpu_probe_ingenic(c, cpu); ++ break; + } + + BUG_ON(!__cpu_name[cpu]); +diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c +index 67bd626..e26ebe0 100644 +diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c +index 6721ee2..dd4b70b 100644 +--- a/arch/mips/mm/c-r4k.c ++++ b/arch/mips/mm/c-r4k.c +@@ -928,6 +928,36 @@ static void __cpuinit probe_pcache(void) + c->dcache.waybit = 0; + break; + ++ case CPU_JZRISC: ++ config1 = read_c0_config1(); ++ config1 = (config1 >> 22) & 0x07; ++ if (config1 == 0x07) ++ config1 = 10; ++ else ++ config1 = config1 + 11; ++ config1 += 2; ++ icache_size = (1 << config1); ++ c->icache.linesz = 32; ++ c->icache.ways = 4; ++ c->icache.waybit = __ffs(icache_size / c->icache.ways); ++ ++ config1 = read_c0_config1(); ++ config1 = (config1 >> 13) & 0x07; ++ if (config1 == 0x07) ++ config1 = 10; ++ else ++ config1 = config1 + 11; ++ config1 += 2; ++ dcache_size = (1 << config1); ++ c->dcache.linesz = 32; ++ c->dcache.ways = 4; ++ c->dcache.waybit = __ffs(dcache_size / c->dcache.ways); ++ ++ c->dcache.flags = 0; ++ c->options |= MIPS_CPU_PREFETCH; ++ ++ break; ++ + default: + if (!(config & MIPS_CONF_M)) + panic("Don't know how to probe P-caches on this cpu."); +diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c +index 694d51f..4b2bc95 100644 +--- a/arch/mips/mm/cache.c ++++ b/arch/mips/mm/cache.c +@@ -52,6 +52,8 @@ void (*_dma_cache_wback)(unsigned long start, unsigned long size); + void (*_dma_cache_inv)(unsigned long start, unsigned long size); + + EXPORT_SYMBOL(_dma_cache_wback_inv); ++EXPORT_SYMBOL(_dma_cache_wback); ++EXPORT_SYMBOL(_dma_cache_inv); + + #endif /* CONFIG_DMA_NONCOHERENT */ + +diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c +index 9a17bf8..9b80053 100644 +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -385,6 +385,11 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, + tlbw(p); + break; + ++ case CPU_JZRISC: ++ tlbw(p); ++ uasm_i_nop(p); ++ break; ++ + default: + panic("No TLB refill handler yet (CPU type: %d)", + current_cpu_data.cputype); +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/050-nand.patch b/target/linux/xburst/patches-2.6.31/050-nand.patch new file mode 100644 index 000000000..b1c921aaf --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/050-nand.patch @@ -0,0 +1,156 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -420,4 +420,10 @@ config MTD_NAND_SH_FLCTL + Several Renesas SuperH CPU has FLCTL. This option enables support + for NAND Flash using FLCTL. This driver support SH7723. + ++config MTD_NAND_JZ4740 ++ tristate "Support NAND Flash device on Jz4740 board" ++ depends on SOC_JZ4740 ++ help ++ Support NAND Flash device on Jz4740 board ++ + endif # MTD_NAND +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -40,5 +40,6 @@ obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_ + obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o + obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o + obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o ++obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o + + nand-objs := nand_base.o nand_bbt.o + +diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c +index 4ce8e3a..ee5c90d 100644 +--- a/arch/mips/jz4740/platform.c ++++ b/arch/mips/jz4740/platform.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #include + +@@ -152,12 +153,70 @@ static struct platform_device jz_i2c_device = { + .resource = jz_i2c_resources, + }; + ++static struct resource jz_nand_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(EMC_BASE), ++ .end = CPHYSADDR(EMC_BASE) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct nand_ecclayout qi_lb60_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 = 0, ++ .length = 6}, ++ {.offset = 42, ++ .length = 22}} ++}; ++ ++static struct mtd_partition qi_lb60_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 = 20 * 0x100000, ++ }, ++ { .name = "NAND DATA partition", ++ .offset = 100 * 0x100000, ++ .size = 20 * 0x100000, ++ }, ++}; ++ ++static struct jz_nand_platform_data jz_nand_platform_data = { ++ .num_partitions = ARRAY_SIZE(qi_lb60_partitions), ++ .partitions = qi_lb60_partitions, ++ .ecc_layout = &qi_lb60_ecclayout, ++}; ++ ++static struct platform_device jz_nand_device = { ++ .name = "jz4740-nand", ++ .num_resources = ARRAY_SIZE(jz_nand_resources), ++ .resource = jz_nand_resources, ++ .dev = { ++ .platform_data = &jz_nand_platform_data, ++ } ++}; ++ + /* All */ + static struct platform_device *jz_platform_devices[] __initdata = { + &jz_usb_ohci_device, + &jz_lcd_device, + &jz_usb_gdt_device, + &jz_mmc_device, ++ &jz_nand_device, + &jz_i2c_device, + }; + +diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c +index 92f0afe..08a7b37 100644 +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 0a9c9cd..3870dcc 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -896,29 +896,22 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *ecc_calc = chip->buffers->ecccalc; + uint8_t *ecc_code = chip->buffers->ecccode; + uint32_t *eccpos = chip->ecc.layout->eccpos; +- +- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { +- chip->ecc.hwctl(mtd, NAND_ECC_READ); +- chip->read_buf(mtd, p, eccsize); +- chip->ecc.calculate(mtd, p, &ecc_calc[i]); +- } +- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); ++ int stat; + + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; + +- eccsteps = chip->ecc.steps; +- p = buf; +- +- for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { +- int stat; + ++ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { ++ chip->ecc.hwctl(mtd, NAND_ECC_READ); ++ chip->read_buf(mtd, p, eccsize); + stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } ++ + return 0; + } + +@@ -1068,6 +1061,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, + bufpoi = aligned ? buf : chip->buffers->databuf; + + if (likely(sndcmd)) { ++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x00, page); ++ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; + } diff --git a/target/linux/xburst/patches-2.6.31/100-battery.patch b/target/linux/xburst/patches-2.6.31/100-battery.patch new file mode 100644 index 000000000..739249413 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/100-battery.patch @@ -0,0 +1,36 @@ +From e8e05da0df412b041b9bb7d7d0dc30931a3e1344 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:47:33 +0200 +Subject: [PATCH] battery + +--- + drivers/power/Kconfig | 5 +++++ + drivers/power/Makefile | 1 + + 2 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig +index bdbc4f7..3942136 100644 +--- a/drivers/power/Kconfig ++++ b/drivers/power/Kconfig +@@ -103,4 +103,9 @@ config CHARGER_PCF50633 + help + Say Y to include support for NXP PCF50633 Main Battery Charger. + ++config BATTERY_JZ ++ tristate "JZ battery" ++ help ++ Say Y to enable support for the battery in JZ SOC. ++ + endif # POWER_SUPPLY +diff --git a/drivers/power/Makefile b/drivers/power/Makefile +index 380d17c..4eebbf5 100644 +--- a/drivers/power/Makefile ++++ b/drivers/power/Makefile +@@ -28,3 +28,4 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o + obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o + obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o + obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o ++obj-$(CONFIG_BATTERY_JZ) += jz_battery.o +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/101-mmc.patch b/target/linux/xburst/patches-2.6.31/101-mmc.patch new file mode 100644 index 000000000..9ee072128 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/101-mmc.patch @@ -0,0 +1,45 @@ +From 18cd35fce85884d15b1c600dd6e132ed25d6954b Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:47:20 +0200 +Subject: [PATCH] mmc + +--- + drivers/mmc/host/Kconfig | 9 +++++++++ + drivers/mmc/host/Makefile | 1 + + 2 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 891ef18..11e35bd 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -66,6 +66,15 @@ config MMC_RICOH_MMC + useless. It is safe to select this driver even if you don't + have a Ricoh based card reader. + ++config MMC_JZ ++ tristate "JZ SD/Multimedia Card Interface support" ++ depends on SOC_JZ4720 || SOC_JZ4740 ++ help ++ This selects the Ingenic JZ4720/JZ4740 SD/Multimedia card Interface. ++ If you have abIngenic platform with a Multimedia Card slot, ++ say Y or M here. ++ ++ If unsure, say N. + + To compile this driver as a module, choose M here: + the module will be called ricoh_mmc. +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index cf153f6..5396cd6 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -6,6 +6,7 @@ ifeq ($(CONFIG_MMC_DEBUG),y) + EXTRA_CFLAGS += -DDEBUG + endif + ++obj-$(CONFIG_MMC_JZ) += jz_mmc.o + obj-$(CONFIG_MMC_ARMMMCI) += mmci.o + obj-$(CONFIG_MMC_PXA) += pxamci.o + obj-$(CONFIG_MMC_IMX) += imxmmc.o +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/102-video.patch b/target/linux/xburst/patches-2.6.31/102-video.patch new file mode 100644 index 000000000..eaa3e6f4f --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/102-video.patch @@ -0,0 +1,151 @@ +From 2623194f73c9d272245263c8a54c7b1a63766e8e Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:49:48 +0200 +Subject: [PATCH] video + +--- + drivers/video/Kconfig | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/video/Makefile | 3 + + 2 files changed, 116 insertions(+), 0 deletions(-) + +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index 3b54b39..3d5d623 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -237,6 +237,119 @@ config FB_TILEBLITTING + comment "Frame buffer hardware drivers" + depends on FB + ++/************************************************************/ ++config FB_JZSOC ++ tristate "JZSOC LCD controller support" ++ depends on FB && JZSOC ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT ++ ---help--- ++ JZSOC LCD Controller and Smart LCD Controller driver support. ++ ++config FB_JZ4740_SLCD ++ tristate "JZ4740 Smart LCD controller support" ++ depends on FB_JZSOC && SOC_JZ4740 ++ default n ++ ---help--- ++ This is the frame buffer device driver for the JZ4740 Smart LCD controller. ++ If select this, please set to . ++ ++choice ++ depends on FB_JZ4740_SLCD ++ prompt "SLCD Panel" ++ default JZ_SLCD_LGDP4551_8BUS ++ ++config JZ_SLCD_LGDP4551 ++ bool "LG LGDP4551 Smart LCD panel" ++ ---help--- ++ Driver for Smart LCD LGDP4551, 8-bit sytem interface, 16BPP. ++ ++config JZ_SLCD_SPFD5420A ++ bool "SPFD5420A Smart LCD panel" ++ ---help--- ++ Driver for Smart LCD SPFD5420A 18-bit sytem interface, 18BPP. ++ ++config JZ_SLCD_TRULY ++ bool "TRULY Smart LCD panel (MAX Pixels 400x240)" ++ ---help--- ++ ++endchoice ++ ++config FB_JZLCD_4730_4740 ++ tristate "JZ4730 JZ4740 LCD controller support" ++ depends on FB_JZSOC && (SOC_JZ4730 || SOC_JZ4740) ++ help ++ This is the frame buffer device driver for the JZ4730 and JZ4740 LCD controller. ++choice ++ depends on FB_JZLCD_4730_4740 ++ prompt "LCD Panel" ++ default JZLCD_SAMSUNG_LTP400WQF01 ++ ++config JZLCD_SHARP_LQ035Q7 ++ bool "SHARP LQ035Q7 TFT panel (240x320)" ++ ++config JZLCD_SAMSUNG_LTS350Q1 ++ bool "SAMSUNG LTS350Q1 TFT panel (240x320)" ++ ++config JZLCD_SAMSUNG_LTV350QVF04 ++ bool "SAMSUNG LTV350QV_F04 TFT panel (320x240)" ++ ++config JZLCD_SAMSUNG_LTP400WQF01 ++ bool "SAMSUNG LTP400WQF01 TFT panel (480x272)(16bits)" ++ ++config JZLCD_SAMSUNG_LTP400WQF02 ++ bool "SAMSUNG LTP400WQF02 TFT panel (480x272)(18bits)" ++ ++config JZLCD_AUO_A030FL01_V1 ++ bool "AUO A030FL01_V1 TFT panel (480x272)" ++ ++config JZLCD_TRULY_TFTG320240DTSW ++ bool "TRULY TFTG320240DTSW TFT panel (320x240)" ++ ++config JZLCD_TRULY_TFTG320240DTSW_SERIAL ++ bool "TRULY TFTG320240DTSW TFT panel (320x240)(8bit-serial mode)" ++ ++config JZLCD_TRULY_TFTG240320UTSW_63W_E ++ bool "TRULY TFTG240320UTSW-63W-E TFT panel (240x320,2.5in)" ++ ++config JZLCD_FOXCONN_PT035TN01 ++ bool "FOXCONN PT035TN01 TFT panel (320x240)" ++ ++config JZLCD_INNOLUX_PT035TN01_SERIAL ++ bool "INNOLUX PT035TN01 TFT panel (320x240,3.5in)(8bit-serial mode)" ++ ++config JZLCD_TOSHIBA_LTM084P363 ++ bool "Toshiba LTM084P363 TFT panel (800x600)" ++ ++config JZLCD_HYNIX_HT10X21 ++ bool "Hynix HT10X21_300 TFT panel (1024x768)" ++ ++config JZLCD_INNOLUX_AT080TN42 ++ bool "INNOLUX AT080TN42 TFT panel (800x600)" ++ ++config JZLCD_CSTN_800x600 ++ bool "800x600 colorDSTN panel" ++ ++config JZLCD_CSTN_320x240 ++ bool "320x240 colorSTN panel" ++ ++config JZLCD_MSTN_480x320 ++ bool "480x320 monoSTN panel" ++ ++config JZLCD_MSTN_320x240 ++ bool "320x240 monoSTN panel" ++ ++config JZLCD_MSTN_240x128 ++ bool "240x128 monoSTN panel" ++ ++config JZLCD_MSTN_INVERSE ++ bool "Use an inverse color display." ++ depends on (JZLCD_MSTN_480x320 || JZLCD_MSTN_240x128) ++ ++endchoice ++ ++ + config FB_CIRRUS + tristate "Cirrus Logic support" + depends on FB && (ZORRO || PCI) +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 01a819f..289b6e9 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -28,6 +28,9 @@ obj-$(CONFIG_FB_DDC) += fb_ddc.o + obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o + + # Hardware specific drivers go first ++obj-$(CONFIG_FB_JZLCD_4720_4740) += jzlcd.o ++obj-$(CONFIG_FB_JZ4740_SLCD) += jz4740_slcd.o ++ + obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o + obj-$(CONFIG_FB_ARC) += arcfb.o + obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/103-serial.patch b/target/linux/xburst/patches-2.6.31/103-serial.patch new file mode 100644 index 000000000..982c0fb04 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/103-serial.patch @@ -0,0 +1,178 @@ +From 35d6fcb8cc04d368abef00b00e6af04b8c71ba46 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:54:02 +0200 +Subject: [PATCH] serial + +--- + drivers/serial/8250.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 103 insertions(+), 1 deletions(-) + +diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c +index fb867a9..d8784c3 100644 +--- a/drivers/serial/8250.c ++++ b/drivers/serial/8250.c +@@ -194,7 +194,7 @@ static const struct serial8250_config uart_config[] = { + [PORT_16550A] = { + .name = "16550A", + .fifo_size = 16, +- .tx_loadsz = 16, ++ .tx_loadsz = 8, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, +@@ -401,6 +401,10 @@ static unsigned int mem_serial_in(struct uart_port *p, int offset) + static void mem_serial_out(struct uart_port *p, int offset, int value) + { + offset = map_8250_out_reg(p, offset) << p->regshift; ++#if defined(CONFIG_JZSOC) ++ if (offset == (UART_FCR << p->regshift)) ++ value |= 0x10; /* set FCR.UUE */ ++#endif + writeb(value, p->membase + offset); + } + +@@ -2213,6 +2217,83 @@ static void serial8250_shutdown(struct uart_port *port) + serial_unlink_irq_chain(up); + } + ++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) ++static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */ ++static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud) ++{ ++ int err, sum, i, j; ++ int a[12], b[12]; ++ unsigned short div, umr, uacr; ++ unsigned short umr_best, div_best, uacr_best; ++ long long t0, t1, t2, t3; ++ ++ sum = 0; ++ umr_best = div_best = uacr_best = 0; ++ div = 1; ++ ++ if ((port->uartclk % (16 * baud)) == 0) { ++ quot1[0] = port->uartclk / (16 * baud); ++ quot1[1] = 16; ++ quot1[2] = 0; ++ return quot1; ++ } ++ ++ while (1) { ++ umr = port->uartclk / (baud * div); ++ if (umr > 32) { ++ div++; ++ continue; ++ } ++ if (umr < 4) { ++ break; ++ } ++ for (i = 0; i < 12; i++) { ++ a[i] = umr; ++ b[i] = 0; ++ sum = 0; ++ for (j = 0; j <= i; j++) { ++ sum += a[j]; ++ } ++ ++ /* the precision could be 1/2^(36) due to the value of t0 */ ++ t0 = 0x1000000000LL; ++ t1 = (i + 1) * t0; ++ t2 = (sum * div) * t0; ++ t3 = div * t0; ++ do_div(t1, baud); ++ do_div(t2, port->uartclk); ++ do_div(t3, (2 * port->uartclk)); ++ err = t1 - t2 - t3; ++ ++ if (err > 0) { ++ a[i] += 1; ++ b[i] = 1; ++ } ++ } ++ ++ uacr = 0; ++ for (i = 0; i < 12; i++) { ++ if (b[i] == 1) { ++ uacr |= 1 << i; ++ } ++ } ++ ++ /* the best value of umr should be near 16, and the value of uacr should better be smaller */ ++ if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) { ++ div_best = div; ++ umr_best = umr; ++ uacr_best = uacr; ++ } ++ div++; ++ } ++ ++ quot1[0] = div_best; ++ quot1[1] = umr_best; ++ quot1[2] = uacr_best; ++ ++ return quot1; ++} ++#else + static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) + { + unsigned int quot; +@@ -2232,6 +2313,7 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int + + return quot; + } ++#endif + + static void + serial8250_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -2241,6 +2323,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + unsigned char cval, fcr = 0; + unsigned long flags; + unsigned int baud, quot; ++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) ++ unsigned short *quot1; ++#endif + + switch (termios->c_cflag & CSIZE) { + case CS5: +@@ -2273,7 +2358,12 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); ++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) ++ quot1 = serial8250_get_divisor(port, baud); ++ quot = quot1[0]; /* not usefull, just let gcc happy */ ++#else + quot = serial8250_get_divisor(port, baud); ++#endif + + /* + * Oxford Semi 952 rev B workaround +@@ -2351,6 +2441,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + if (up->capabilities & UART_CAP_UUE) + up->ier |= UART_IER_UUE | UART_IER_RTOIE; + ++#ifdef CONFIG_JZSOC ++ up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */ ++#endif ++ + serial_out(up, UART_IER, up->ier); + + if (up->capabilities & UART_CAP_EFR) { +@@ -2385,7 +2479,15 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + } + ++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) ++#define UART_UMR 9 ++#define UART_UACR 10 ++ serial_dl_write(up, quot1[0]); ++ serial_outp(up, UART_UMR, quot1[1]); ++ serial_outp(up, UART_UACR, quot1[2]); ++#else + serial_dl_write(up, quot); ++#endif + + /* + * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/104-usb.patch b/target/linux/xburst/patches-2.6.31/104-usb.patch new file mode 100644 index 000000000..f64ac1941 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/104-usb.patch @@ -0,0 +1,183 @@ +From d6e1e759473e3b62bb2a7b906bbb27f1f1f2aff2 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:54:18 +0200 +Subject: [PATCH] usb + +--- + drivers/usb/Kconfig | 1 + + drivers/usb/core/hub.c | 43 +++++++++++++++++++++++++++++++++++++ + drivers/usb/gadget/Kconfig | 18 ++++++++++++++- + drivers/usb/gadget/Makefile | 3 ++ + drivers/usb/gadget/gadget_chips.h | 9 +++++++ + 5 files changed, 73 insertions(+), 1 deletions(-) + +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index dcd49f1..a520bed 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -44,6 +44,7 @@ config USB_ARCH_HAS_OHCI + default y if PPC_MPC52xx + # MIPS: + default y if SOC_AU1X00 ++ default y if JZSOC + # SH: + default y if CPU_SUBTYPE_SH7720 + default y if CPU_SUBTYPE_SH7721 +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 71f86c6..d3f9344 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1857,6 +1857,25 @@ static int hub_port_reset(struct usb_hub *hub, int port1, + { + int i, status; + ++#ifdef CONFIG_SOC_JZ4730 ++ /* ++ * On Jz4730, we assume that the first USB port was used as device. ++ * If not, please comment next lines. ++ */ ++ if (port1 == 1) { ++ return 0; ++ } ++#endif ++ ++#if defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) ++ /* ++ * On Jz4740 and Jz4750, the second USB port was used as device. ++ */ ++ if (port1 == 2) { ++ return 0; ++ } ++#endif ++ + /* Block EHCI CF initialization during the port reset. + * Some companion controllers don't like it when they mix. + */ +@@ -2818,11 +2837,35 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, + le16_to_cpu(hub->descriptor->wHubCharacteristics); + struct usb_device *udev; + int status, i; ++#ifdef CONFIG_JZSOC ++ static char jzhub = 1; /* the hub first to be initialized is jzsoc on-chip hub */ ++#endif + + dev_dbg (hub_dev, + "port %d, status %04x, change %04x, %s\n", + port1, portstatus, portchange, portspeed (portstatus)); + ++#ifdef CONFIG_SOC_JZ4730 ++ /* ++ * On Jz4730, we assume that the first USB port was used as device. ++ * If not, please comment next lines. ++ */ ++ if ((port1 == 1) && (jzhub)) { ++ jzhub = 0; ++ return; ++ } ++#endif ++ ++#if defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) ++ /* ++ * On Jz4740 and Jz4750, the second USB port was used as device. ++ */ ++ if ((port1 == 2) && (jzhub)) { ++ jzhub = 0; ++ return; ++ } ++#endif ++ + if (hub->has_indicators) { + set_port_led(hub, port1, HUB_LED_AUTO); + hub->indicator[port1-1] = INDICATOR_AUTO; +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index 7f8e83a..a973ce7 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -121,11 +121,24 @@ choice + # + # Integrated controllers + # ++config USB_GADGET_JZ4740 ++ boolean "JZ4740 UDC" ++ depends on SOC_JZ4740 ++ select USB_GADGET_DUALSPEED ++ help ++ 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" + depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 + select USB_GADGET_SELECTED ++ + help + Many Atmel AT91 processors (such as the AT91RM2000) have a + full speed USB Device Port with support for five configurable +@@ -534,6 +547,10 @@ config USB_DUMMY_HCD + + endchoice + ++config USB_JZ_UDC_HOTPLUG ++ boolean "Ingenic USB Device Controller Hotplug Support" ++ depends on USB_GADGET_JZ4750 ++ + config USB_GADGET_DUALSPEED + bool + depends on USB_GADGET +@@ -541,7 +558,6 @@ config USB_GADGET_DUALSPEED + help + Means that gadget drivers should include extra descriptors + and code to handle dual-speed controllers. +- + # + # USB Gadget Drivers + # +diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile +index e6017e6..b758686 100644 +--- a/drivers/usb/gadget/Makefile ++++ b/drivers/usb/gadget/Makefile +@@ -27,6 +27,9 @@ obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o + obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o + obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o + obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o ++obj-$(CONFIG_USB_JZ4740) += jz4740_udc.o ++ ++obj-$(CONFIG_USB_JZ_UDC_HOTPLUG)+= udc_hotplug_core.o + + # + # USB gadget drivers +diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h +index 8e0e9a0..d9c0990 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 +@@ -239,6 +245,9 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) + return 0x23; + else if (gadget_is_langwell(gadget)) + return 0x24; ++ else if (gadget_is_jz4740(gadget)) ++ return 0x25; ++ + return -ENOENT; + } + +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/105-sound.patch b/target/linux/xburst/patches-2.6.31/105-sound.patch new file mode 100644 index 000000000..77aa8eda2 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/105-sound.patch @@ -0,0 +1,268 @@ +From 1a6fa6adbd597171648c7cb308cc9e3efe488668 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 19 Aug 2009 14:54:29 +0200 +Subject: [PATCH] sound + +--- + include/sound/pcm.h | 26 ++++++------ + sound/core/pcm_lib.c | 94 +++++++++++++++++++++++++++++++++++++++++++++ + sound/core/pcm_native.c | 15 ++++++- + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/codecs/Kconfig | 12 ++++++ + sound/soc/codecs/Makefile | 2 + + 7 files changed, 135 insertions(+), 16 deletions(-) + +diff --git a/include/sound/pcm.h b/include/sound/pcm.h +index 2389352..24dcb18 100644 +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -113,23 +113,23 @@ struct snd_pcm_ops { + #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ + #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ + #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ +-#define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ +-#define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ +-#define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ +-#define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ +-#define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ +-#define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ +-#define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ +-#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ +-#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ +-#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ ++#define SNDRV_PCM_RATE_12000 (1<<3) /* 12000Hz */ ++#define SNDRV_PCM_RATE_16000 (1<<4) /* 16000Hz */ ++#define SNDRV_PCM_RATE_22050 (1<<5) /* 22050Hz */ ++#define SNDRV_PCM_RATE_24000 (1<<6) /* 24000Hz */ ++#define SNDRV_PCM_RATE_32000 (1<<7) /* 32000Hz */ ++#define SNDRV_PCM_RATE_44100 (1<<8) /* 44100Hz */ ++#define SNDRV_PCM_RATE_48000 (1<<9) /* 48000Hz */ ++#define SNDRV_PCM_RATE_64000 (1<<10) /* 64000Hz */ ++#define SNDRV_PCM_RATE_88200 (1<<11) /* 88200Hz */ ++#define SNDRV_PCM_RATE_96000 (1<<12) /* 96000Hz */ ++#define SNDRV_PCM_RATE_176400 (1<<13) /* 176400Hz */ ++#define SNDRV_PCM_RATE_192000 (1<<14) /* 192000Hz */ + + #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ + #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ + +-#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ +- SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ +- SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) ++#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|SNDRV_PCM_RATE_12000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_24000|SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) + #define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) + #define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ + SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) +diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c +index 72cfd47..5ae0a2d 100644 +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -2076,6 +2076,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, + return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + } + ++#if 0 + snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) + { + struct snd_pcm_runtime *runtime; +@@ -2091,6 +2092,99 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u + return -EINVAL; + return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); + } ++#else ++snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) ++{ ++ struct snd_pcm_runtime *runtime; ++ int nonblock; ++ ++ snd_pcm_sframes_t tmp_frames; ++ snd_pcm_sframes_t final_frames; ++ int channels; ++ ++ snd_assert(substream != NULL, return -ENXIO); ++ runtime = substream->runtime; ++ snd_assert(runtime != NULL, return -ENXIO); ++ snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL); ++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ return -EBADFD; ++ ++ nonblock = !!(substream->f_flags & O_NONBLOCK); ++ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) ++ return -EINVAL; ++ ++ /* ++ * mono capture process for no mono codec ++ * function codec such as ipcood and dlv ++ */ ++ ++ tmp_frames = snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); ++ ++ channels = runtime->channels; ++ ++ if (channels == 1) { ++ short *tmpbuf = kcalloc(tmp_frames, sizeof(short), GFP_KERNEL); ++ short *src, *dst, *end; ++ ++ memcpy(tmpbuf, buf, frames_to_bytes(runtime, tmp_frames)); ++ ++ src = (short *)buf; ++ dst = (short *)tmpbuf; ++ end = dst + tmp_frames - 1; ++ ++ src++; ++ dst++; ++ dst++; ++ final_frames = 1; ++ while (dst <= end) { ++ *src = *dst; ++ final_frames++; ++ src++; ++ dst++; ++ dst++; ++ } ++ tmp_frames = final_frames; ++ kfree(tmpbuf); ++ ++#if 0 ++ /* when i have time, i will try the code, no kcalloc */ ++ snd_assert(runtime->dma_area, return -EFAULT); ++ if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) ++ return -EFAULT; ++ ++ unsigned int up_bytes = frames_to_bytes(runtime, frames); ++ ++ int while_cnt = 4; ++ int while_all = up_bytes - 2; ++ ++ while (while_cnt <= while_all) { ++ //printk("[%d = %d]\n",(while_cnt/2),while_cnt); ++ buf[(while_cnt/2)] = buf[while_cnt]; ++ //printk("[%d = %d]\n",((while_cnt/2)+1),(while_cnt+1)); ++ buf[((while_cnt/2)+1)] = buf[(while_cnt+1)]; ++ while_cnt += 4; ++#if 0 ++ buf[2] = buf[4]; ++ buf[3] = buf[5]; ++ ++ buf[4] = buf[8]; ++ buf[5] = buf[9]; ++ ++ buf[6] = buf[12]; ++ buf[7] = buf[13]; ++ ++ buf[8] = buf[16]; ++ buf[9] = buf[17]; ++#endif ++ } ++ /* when i have time, i will try the code, no kcalloc */ ++#endif ++ ++ } ++ ++ return tmp_frames; ++} ++#endif + + EXPORT_SYMBOL(snd_pcm_lib_read); + +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index ac2150e..2a57ab7 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1748,12 +1748,13 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, + return snd_interval_refine(hw_param_interval(params, rule->var), &t); + } + +-#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 ++#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 14 + #error "Change this table" + #endif + +-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, +- 48000, 64000, 88200, 96000, 176400, 192000 }; ++static unsigned int rates[] = { 5512, 8000, 11025, 12000, 16000, 22050, 24000, ++ 32000, 44100, 48000, 64000, 88200, 96000, ++ 176400, 192000 }; + + const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { + .count = ARRAY_SIZE(rates), +@@ -1764,9 +1765,17 @@ static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) + { + struct snd_pcm_hardware *hw = rule->private; ++#if 0 + return snd_interval_list(hw_param_interval(params, rule->var), + snd_pcm_known_rates.count, + snd_pcm_known_rates.list, hw->rates); ++#else ++ //printk("hw->rates=0x%08x\n",hw->rates);//0x3b6 ++ hw->rates = 0x3fe;//12KHz and 24KHz bits are all zero,you need set 1 ++ return snd_interval_list(hw_param_interval(params, rule->var), ++ snd_pcm_known_rates.count, ++ snd_pcm_known_rates.list, hw->rates); ++#endif + } + + static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, +diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig +index d3e786a..a5335f4 100644 +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -35,6 +35,7 @@ source "sound/soc/s3c24xx/Kconfig" + source "sound/soc/s6000/Kconfig" + source "sound/soc/sh/Kconfig" + source "sound/soc/txx9/Kconfig" ++source "sound/soc/jz4740/Kconfig" + + # Supported codecs + source "sound/soc/codecs/Kconfig" +diff --git a/sound/soc/Makefile b/sound/soc/Makefile +index 6f1e28d..132772d 100644 +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -13,3 +13,4 @@ obj-$(CONFIG_SND_SOC) += s3c24xx/ + obj-$(CONFIG_SND_SOC) += s6000/ + obj-$(CONFIG_SND_SOC) += sh/ + obj-$(CONFIG_SND_SOC) += txx9/ ++obj-$(CONFIG_SND_SOC) += jz4740/ +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index bbc97fd..493e216 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -176,3 +176,15 @@ config SND_SOC_WM9712 + + config SND_SOC_WM9713 + tristate ++ ++config SND_SOC_ICODEC ++ tristate "Jz4740 internal codec" ++ depends on SND_SOC && SND_JZ4740_SOC_PAVO && SND_JZ4740_SOC_I2S ++ help ++ Say Y if you want to use internal codec on Ingenic Jz4740 PAVO board. ++ ++config SND_SOC_DLV ++ tristate "Jz4750 internal codec" ++ depends on SND_SOC && SND_JZ4750_SOC_APUS && SND_JZ4750_SOC_I2S ++ help ++ Say Y if you want to use internal codec on Ingenic Jz4750 APUS board. +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 8b75305..f053c15 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -34,6 +34,7 @@ snd-soc-wm9081-objs := wm9081.o + snd-soc-wm9705-objs := wm9705.o + snd-soc-wm9712-objs := wm9712.o + snd-soc-wm9713-objs := wm9713.o ++snd-soc-jzcodec-objs := jzcodec.o + + obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o + obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o +@@ -71,3 +72,4 @@ obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o + obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o + obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o + obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o ++obj-$(CONFIG_SND_SOC_ICODEC) += snd-soc-jzcodec.o +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.31/200-qi_lb60.patch b/target/linux/xburst/patches-2.6.31/200-qi_lb60.patch new file mode 100644 index 000000000..dd2544123 --- /dev/null +++ b/target/linux/xburst/patches-2.6.31/200-qi_lb60.patch @@ -0,0 +1,319 @@ +--- /dev/null ++++ b/arch/mips/jz4740/board-qi_lb60.c +@@ -0,0 +1,110 @@ ++/* ++ * linux/arch/mips/jz4740/board-qi_lb60.c ++ * ++ * QI_LB60 setup routines. ++ * ++ * Copyright (c) 2009 Qi Hardware inc., ++ * Author: Xiangfu Liu ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++extern void (*jz_timer_callback)(void); ++ ++static void dancing(void) ++{ ++ static unsigned int count = 0; ++ ++ count ++; ++ count &= 1; ++ if (count) ++ __gpio_set_pin(GPIO_LED_EN); ++ else ++ __gpio_clear_pin(GPIO_LED_EN); ++} ++ ++static void pi_timer_callback(void) ++{ ++ static unsigned long count = 0; ++ ++ if ((++count) % 50 == 0) { ++ dancing(); ++ count = 0; ++ } ++} ++ ++static void __init board_cpm_setup(void) ++{ ++ /* Stop unused module clocks here. ++ * We have started all module clocks at arch/mips/jz4740/setup.c. ++ */ ++} ++ ++static void __init board_gpio_setup(void) ++{ ++ /* ++ * Most of the GPIO pins should have been initialized by the boot-loader ++ */ ++ ++ /* ++ * Initialize MSC pins ++ */ ++ /* __gpio_as_msc(); */ ++ ++ /* ++ * Initialize LCD pins ++ */ ++ /* __gpio_as_lcd_18bit(); */ ++ ++ /* ++ * Initialize SSI pins ++ */ ++ /* __gpio_as_ssi(); */ ++ ++ /* ++ * Initialize I2C pins ++ */ ++ /* __gpio_as_i2c(); */ ++ ++ /* ++ * Initialize Other pins ++ */ ++ __gpio_as_output(GPIO_SD_VCC_EN_N); ++ __gpio_disable_pull(GPIO_SD_VCC_EN_N); ++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); ++ ++ __gpio_as_input(GPIO_SD_CD_N); ++ __gpio_disable_pull(GPIO_SD_CD_N); ++ ++ __gpio_as_input(GPIO_SD_WP); ++ __gpio_disable_pull(GPIO_SD_WP); ++ ++ __gpio_as_input(GPIO_DC_DETE_N); ++ __gpio_as_input(GPIO_CHARG_STAT_N); ++} ++ ++void __init jz_board_setup(void) ++{ ++ printk("Qi Hardware JZ4740 QI_LB60 setup\n"); ++ ++ board_cpm_setup(); ++ board_gpio_setup(); ++ ++ jz_timer_callback = pi_timer_callback; ++} +--- a/arch/mips/jz4740/Makefile ++++ b/arch/mips/jz4740/Makefile +@@ -16,6 +16,7 @@ obj-$(CONFIG_JZ4740_LEO) += board-leo.o + obj-$(CONFIG_JZ4740_LYRA) += board-lyra.o + obj-$(CONFIG_JZ4725_DIPPER) += board-dipper.o + obj-$(CONFIG_JZ4720_VIRGO) += board-virgo.o ++obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o + + # PM support + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -655,6 +655,14 @@ choice + Kodama + Hikari + Say Y here for most Octeon reference boards. ++ ++config JZ4740_QI_LB60 ++ bool "Ingenic JZ4740 QI_LB60 board" ++ select DMA_NONCOHERENT ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select SOC_JZ4740 + + endchoice + +--- a/drivers/video/jzlcd.c ++++ b/drivers/video/jzlcd.c +@@ -126,15 +126,18 @@ static struct jzfb_info jzfb = { + MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N | DE_N, + 320, 240, 16, 60, 3, 3, 3, 3, 3, 85 /* 320x240 */ + #endif +-#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) && defined(CONFIG_JZ4740_PAVO) +- MODE_TFT_GEN | HSYNC_N | VSYNC_N | MODE_TFT_18BIT | PCLK_N, +-// 320, 240, 18, 110, 1, 1, 10, 50, 10, 13 +- 320, 240, 18, 80, 1, 1, 10, 50, 10, 13 +-#endif +-#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) && !(defined(CONFIG_JZ4740_PAVO)) +- MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, +- 320, 240, 16, 110, 1, 1, 10, 50, 10, 13 +-#endif ++#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) ++ #if defined(CONFIG_JZ4740_PAVO) ++ MODE_TFT_GEN | HSYNC_N | VSYNC_N | MODE_TFT_18BIT | PCLK_N, ++ 320, 240, 18, 80, 1, 1, 10, 50, 10, 13 ++ #elif defined(CONFIG_JZ4740_QI_LB60) ++ MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N, ++ 320, 240, 32, 70, 1, 1, 273, 140, 1, 20 ++ #else ++ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, ++ 320, 240, 16, 110, 1, 1, 10, 50, 10, 13 ++ #endif ++#endif /* CONFIG_JZLCD_FOXCONN_PT035TN01 */ + #if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) + MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N, + 320, 240, 32, 60, 1, 1, 10, 50, 10, 13 +@@ -1523,7 +1526,7 @@ static int __init jzfb_init(void) + cfb->pm->data = cfb; + #endif + +- __lcd_display_on(); ++ __lcd_display_off(); + + return 0; + +--- a/drivers/video/jzlcd.h ++++ b/drivers/video/jzlcd.h +@@ -363,7 +363,11 @@ do { \ + #if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) || defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) + + #if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) /* board pmp */ +-#define MODE 0xcd /* 24bit parellel RGB */ ++ #if defined(CONFIG_JZ4740_QI_LB60) ++ #define MODE 0xc9 ++ #else ++ #define MODE 0xcd /* 24bit parellel RGB */ ++ #endif + #endif + #if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) + #define MODE 0xc9 /* 8bit serial RGB */ +@@ -384,6 +388,11 @@ do { \ + #define SPCK (32*1+17) //LCD_CLS + #define SPDA (32*2+12) //LCD_D12 + #define LCD_RET (32*2+23) //LCD_REV, GPC23 ++#elif defined(CONFIG_JZ4740_QI_LB60) ++ #define SPEN (32*2+21) //LCD_SPL ++ #define SPCK (32*2+23) //LCD_CLS ++ #define SPDA (32*2+22) //LCD_D12 ++ #define LCD_RET (32*3+27) + #if 0 /*old driver*/ + #define SPEN (32*1+18) //LCD_SPL + #define SPCK (32*1+17) //LCD_CLS +@@ -655,7 +664,7 @@ do { \ + + /*#if defined(CONFIG_JZ4740_LEO) || defined(CONFIG_JZ4740_PAVO)*/ + #if defined(CONFIG_SOC_JZ4740) +-#if defined(CONFIG_JZ4740_PAVO) || defined(CONFIG_JZ4740_LYRA) ++#if defined(CONFIG_JZ4740_PAVO) || defined(CONFIG_JZ4740_LYRA) || defined(CONFIG_JZ4740_QI_LB60) + #define GPIO_PWM 123 /* GP_D27 */ + #define PWM_CHN 4 /* pwm channel */ + #define PWM_FULL 101 +@@ -725,7 +734,7 @@ do { \ + do { \ + __gpio_set_pin(GPIO_DISP_OFF_N); \ + __lcd_special_on(); \ +- __lcd_set_backlight_level(80); \ ++ __lcd_set_backlight_level(20); \ + } while (0) + + #define __lcd_display_off() \ +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/board-qi_lb60.h +@@ -0,0 +1,79 @@ ++/* ++ * linux/include/asm-mips/mach-jz4740/board-qi_lb60.h ++ * ++ * Copyright (c) 2009 Qi Hardware inc., ++ * Author: Xiangfu Liu ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 3 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef __ASM_JZ4740_QI_LB60_H__ ++#define __ASM_JZ4740_QI_LB60_H__ ++ ++/* ++ * Frequencies of on-board oscillators ++ */ ++#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ ++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ ++ ++/* ++ * GPIO ++ */ ++#define GPIO_DC_DETE_N (2 * 32 + 26) ++#define GPIO_CHARG_STAT_N (2 * 32 + 27) ++#define GPIO_LED_EN (2 * 32 + 28) ++#define GPIO_LCD_CS (2 * 32 + 21) ++#define GPIO_DISP_OFF_N (3 * 32 + 21) ++#define GPIO_PWM (3 * 32 + 27) ++ ++#define GPIO_AMP_EN (3 * 32 + 4) ++ ++#define GPIO_SD_CD_N (3 * 32 + 0) ++#define GPIO_SD_VCC_EN_N (3 * 32 + 2) ++#define GPIO_SD_WP (3 * 32 + 16) ++ ++#define GPIO_USB_DETE (3 * 32 + 28) ++#define GPIO_BUZZ_PWM (3 * 32 + 27) ++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE ++ ++#define GPIO_AUDIO_POP (1 * 32 + 29) ++#define GPIO_COB_TEST (1 * 32 + 30) ++ ++#define GPIO_KEYOUT_BASE (2 * 32 + 10) ++#define GPIO_KEYIN_BASE (3 * 32 + 18) ++#define GPIO_KEYIN_8 (3 * 32 + 26) ++ ++/* ++ * MMC/SD ++ */ ++#define MSC_WP_PIN GPIO_SD_WP ++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N ++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) ++ ++#define __msc_init_io() \ ++do { \ ++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ ++ __gpio_as_input(GPIO_SD_CD_N); \ ++} while (0) ++ ++#define __msc_enable_power() \ ++do { \ ++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ ++} while (0) ++ ++#define __msc_disable_power() \ ++do { \ ++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ ++} while (0) ++ ++#define __msc_card_detected(s) \ ++({ \ ++ int detected = 1; \ ++ if (!__gpio_get_pin(GPIO_SD_CD_N)) \ ++ detected = 0; \ ++ detected; \ ++}) ++ ++#endif /* __ASM_JZ4740_QI_LB60_H__ */ +--- a/arch/mips/include/asm/mach-jz4740/jz4740.h ++++ b/arch/mips/include/asm/mach-jz4740/jz4740.h +@@ -43,6 +43,10 @@ + #include + #endif + ++#ifdef CONFIG_JZ4740_QI_LB60 ++#include ++#endif ++ + /* Add other platform definition here ... */ + +