diff --git a/target/linux/xburst/Makefile b/target/linux/xburst/Makefile index 138197290..3a68cabe9 100644 --- a/target/linux/xburst/Makefile +++ b/target/linux/xburst/Makefile @@ -12,14 +12,12 @@ BOARDNAME:=Ingenic XBurst FEATURES:=jffs2 targz ubifs audio SUBTARGETS:=qi_lb60 n516 n526 -LINUX_VERSION:=2.6.32.12 +LINUX_VERSION:=2.6.34-rc7 DEVICE_TYPE=other include $(INCLUDE_DIR)/target.mk -KERNELNAME:=uImage - define Target/Description Build firmware images for XBurst JZ47x0 based boards. endef diff --git a/target/linux/xburst/config-2.6.34 b/target/linux/xburst/config-2.6.34 new file mode 100644 index 000000000..5e0e37cc9 --- /dev/null +++ b/target/linux/xburst/config-2.6.34 @@ -0,0 +1,365 @@ +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_PHYS_ADDR_T_64BIT is not set +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_BACKLIGHT_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_BATTERY_JZ4740 is not set +# CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set +CONFIG_BITREVERSE=y +# CONFIG_BLK_DEV_INITRD 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_CHARGER_GPIO=y +CONFIG_CONSOLE_TRANSLATIONS=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_LOONGSON2E is not set +# CONFIG_CPU_LOONGSON2F is not set +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +CONFIG_CPU_MIPS32=y +# 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_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_DEFAULT_AS=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EARLY_PRINTK=y +CONFIG_ELF_CORE=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_FAT_FS=y +# CONFIG_FB_JZ4740 is not set +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_IMAGEBLIT=y +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FONT_10x18 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_SUN12x22 is not set +CONFIG_FONT_SUN8x16=y +CONFIG_FONTS=y +CONFIG_FORCE_MAX_ZONEORDER=12 +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FRAMEBUFFER_CONSOLE is not set +CONFIG_FREEZER=y +CONFIG_INOTIFY_USER=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CLOCKEVENTS=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_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_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PWM=y +# CONFIG_HIBERNATION is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_HW_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_GPIO_BUTTONS is not set +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT=y +CONFIG_IRQ_CPU=y +CONFIG_JBD=y +# CONFIG_JZ4740_ADC is not set +# CONFIG_JZ4740_N516 is not set +# CONFIG_JZ4740_N526 is not set +# CONFIG_JZ4740_QI_LB60 is not set +CONFIG_JZRISC=y +CONFIG_JZSOC=y +CONFIG_KALLSYMS=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_MATRIX is not set +# 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_LCD_CLASS_DEVICE is not set +# CONFIG_LCD_GPM940B0 is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LEDS_PWM is not set +CONFIG_LEGACY_PTY_COUNT=2 +CONFIG_LEGACY_PTYS=y +CONFIG_LOCK_KERNEL=y +# CONFIG_LOGO_LINUX_CLUT224 is not set +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_OPENWRT_CLUT224 is not set +# CONFIG_LOGO is not set +CONFIG_LOONGSON_UART_BASE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +CONFIG_MACH_JZ=y +# CONFIG_MACH_LOONGSON is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_MINI_FO is not set +# CONFIG_MIPS_COBALT 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_MIPS=y +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_JZ=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC=y +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_NAND_JZ4740=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND=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_MTD_UBI=y +# CONFIG_N516_LPC is not set +CONFIG_NEED_DMA_MAP_STATE=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_NEW_LEDS is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y +CONFIG_NLS=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_PCI is not set +# CONFIG_PDA_POWER is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PM_DEBUG is not set +CONFIG_PM_OPS=y +# CONFIG_PM_RUNTIME is not set +CONFIG_PM_SLEEP=y +CONFIG_PM=y +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_POWERTV is not set +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT=y +CONFIG_PRINTK_TIME=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_CMOS is not set +CONFIG_RTC_DRV_JZ4740=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_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_SND_SOC_ALL_CODECS is not set +# CONFIG_SND_SOC_JZCODEC is not set +# CONFIG_SND_SOC_JZ4740 is not set +# CONFIG_SND_JZ4740_SOC_N516 is not set +# CONFIG_SND_JZ4740_SOC_N526 is not set +# CONFIG_SND_JZ4740_SOC_QI_LB60 is not set +CONFIG_SOC_JZ4740=y +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SQUASHFS is not set +# CONFIG_STAGING is not set +CONFIG_SUSPEND_FREEZER=y +CONFIG_SUSPEND=y +# CONFIG_SYN_COOKIES is not set +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_TRAD_SIGNALS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_UBIFS_FS_LZO=y +# CONFIG_UBIFS_FS_XATTR is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_ETH_EEM is not set +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_ETH=y +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_IMX is not set +CONFIG_USB_GADGET_JZ4740=y +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET=y +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_G_SERIAL is not set +CONFIG_USB_JZ4740=y +# CONFIG_USB_MIDI_GADGET is not set +CONFIG_USB_SUPPORT=y +# CONFIG_USB_ZERO is not set +CONFIG_VFAT_FS=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_VLAN_8021Q is not set +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_VT=y +# CONFIG_WATCHDOG is not set +# CONFIG_WLAN_80211 is not set +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/xburst/image/Makefile b/target/linux/xburst/image/Makefile index c445494c7..9c03b3809 100644 --- a/target/linux/xburst/image/Makefile +++ b/target/linux/xburst/image/Makefile @@ -17,8 +17,22 @@ UBIFS_OPTS = -m 2048 -e 126KiB -c 4096 UBINIZE_OPTS = -m 2048 -p 128KiB -s 512 endif +UIMAGE:=$(BIN_DIR)/$(IMG_PREFIX)-uImage.bin + +define kernel_entry +0x$(shell $(TARGET_CROSS)nm $(1) 2>/dev/null | grep " kernel_entry" | cut -f1 -d ' ') +endef + + +define MkImageGzip + gzip -9 -c $(1) > $(1).gz + mkimage -A mips -O linux -T kernel -a 0x80010000 -C gzip \ + -e $(call kernel_entry,$(LINUX_DIR)/vmlinux) -n 'MIPS OpenWrt Linux-$(LINUX_VERSION)' \ + -d $(1).gz $(2) +endef + define Image/BuildKernel - cp $(LINUX_DIR)/arch/mips/boot/uImage $(BIN_DIR)/$(IMG_PREFIX)-uImage.bin + $(call MkImageGzip,$(KDIR)/vmlinux,$(UIMAGE)) endef define Image/Build/squashfs diff --git a/target/linux/xburst/n516/config-2.6.34 b/target/linux/xburst/n516/config-2.6.34 new file mode 100644 index 000000000..1a7251d2e --- /dev/null +++ b/target/linux/xburst/n516/config-2.6.34 @@ -0,0 +1,16 @@ +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_JZ4740=y +CONFIG_FB_METRONOME=m +CONFIG_FB_SYS_FOPS=m +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_GPIO=y +CONFIG_JZ4740_N516=y +CONFIG_LEDS_GPIO=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_N516_LPC=y +CONFIG_NEW_LEDS=y +CONFIG_SENSORS_LM75=y diff --git a/target/linux/xburst/n526/config-2.6.34 b/target/linux/xburst/n526/config-2.6.34 new file mode 100644 index 000000000..916ee8dc8 --- /dev/null +++ b/target/linux/xburst/n526/config-2.6.34 @@ -0,0 +1,4 @@ +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +CONFIG_JZ4740_N516=y diff --git a/target/linux/xburst/patches-2.6.34/001-core.patch b/target/linux/xburst/patches-2.6.34/001-core.patch new file mode 100644 index 000000000..b43bcc252 --- /dev/null +++ b/target/linux/xburst/patches-2.6.34/001-core.patch @@ -0,0 +1,4416 @@ +From 7efb2cae3df49ba749860a0df04933dc522da224 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Sat, 24 Apr 2010 17:35:05 +0200 +Subject: [PATCH] Add JZ4740 SoC core support + +--- + arch/mips/Kconfig | 4 + + arch/mips/Makefile | 6 + + arch/mips/include/asm/bootinfo.h | 6 + + arch/mips/include/asm/cpu.h | 13 +- + arch/mips/include/asm/mach-jz4740/base.h | 28 + + arch/mips/include/asm/mach-jz4740/clock.h | 28 + + arch/mips/include/asm/mach-jz4740/dma.h | 90 +++ + arch/mips/include/asm/mach-jz4740/gpio.h | 398 +++++++++++ + arch/mips/include/asm/mach-jz4740/irq.h | 55 ++ + arch/mips/include/asm/mach-jz4740/platform.h | 34 + + arch/mips/include/asm/mach-jz4740/serial.h | 30 + + arch/mips/include/asm/mach-jz4740/timer.h | 22 + + arch/mips/include/asm/mach-jz4740/war.h | 25 + + arch/mips/jz4740/Kconfig | 29 + + arch/mips/jz4740/Makefile | 17 + + arch/mips/jz4740/clock-debugfs.c | 109 +++ + arch/mips/jz4740/clock.c | 935 ++++++++++++++++++++++++++ + arch/mips/jz4740/clock.h | 75 ++ + arch/mips/jz4740/dma.c | 339 ++++++++++ + arch/mips/jz4740/gpio.c | 598 ++++++++++++++++ + arch/mips/jz4740/irq.c | 174 +++++ + arch/mips/jz4740/irq.h | 21 + + arch/mips/jz4740/platform.c | 246 +++++++ + arch/mips/jz4740/pm.c | 59 ++ + arch/mips/jz4740/prom.c | 69 ++ + arch/mips/jz4740/pwm.c | 167 +++++ + arch/mips/jz4740/reset.c | 81 +++ + arch/mips/jz4740/reset.h | 7 + + arch/mips/jz4740/setup.c | 64 ++ + arch/mips/jz4740/time.c | 145 ++++ + arch/mips/jz4740/timer.c | 45 ++ + arch/mips/jz4740/timer.h | 130 ++++ + arch/mips/kernel/cpu-probe.c | 20 + + arch/mips/mm/tlbex.c | 5 + + 34 files changed, 4073 insertions(+), 1 deletions(-) + create mode 100644 arch/mips/include/asm/mach-jz4740/base.h + create mode 100644 arch/mips/include/asm/mach-jz4740/clock.h + create mode 100644 arch/mips/include/asm/mach-jz4740/dma.h + create mode 100644 arch/mips/include/asm/mach-jz4740/gpio.h + create mode 100644 arch/mips/include/asm/mach-jz4740/irq.h + create mode 100644 arch/mips/include/asm/mach-jz4740/platform.h + create mode 100644 arch/mips/include/asm/mach-jz4740/serial.h + create mode 100644 arch/mips/include/asm/mach-jz4740/timer.h + create mode 100644 arch/mips/include/asm/mach-jz4740/war.h + create mode 100644 arch/mips/jz4740/Kconfig + create mode 100644 arch/mips/jz4740/Makefile + create mode 100644 arch/mips/jz4740/clock-debugfs.c + create mode 100644 arch/mips/jz4740/clock.c + create mode 100644 arch/mips/jz4740/clock.h + create mode 100644 arch/mips/jz4740/dma.c + create mode 100644 arch/mips/jz4740/gpio.c + create mode 100644 arch/mips/jz4740/irq.c + create mode 100644 arch/mips/jz4740/irq.h + create mode 100644 arch/mips/jz4740/platform.c + create mode 100644 arch/mips/jz4740/pm.c + create mode 100644 arch/mips/jz4740/prom.c + create mode 100644 arch/mips/jz4740/pwm.c + create mode 100644 arch/mips/jz4740/reset.c + create mode 100644 arch/mips/jz4740/reset.h + create mode 100644 arch/mips/jz4740/setup.c + create mode 100644 arch/mips/jz4740/time.c + create mode 100644 arch/mips/jz4740/timer.c + create mode 100644 arch/mips/jz4740/timer.h + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 7e6fd1c..e902f02 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -162,6 +162,9 @@ config MACH_JAZZ + Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and + Olivetti M700-10 workstations. + ++config MACH_JZ ++ bool "Ingenic JZ4720/JZ4740 based machines" ++ + config LASAT + bool "LASAT Networks platforms" + select CEVT_R4K +@@ -686,6 +689,7 @@ endchoice + source "arch/mips/alchemy/Kconfig" + source "arch/mips/bcm63xx/Kconfig" + source "arch/mips/jazz/Kconfig" ++source "arch/mips/jz4740/Kconfig" + source "arch/mips/lasat/Kconfig" + source "arch/mips/pmc-sierra/Kconfig" + source "arch/mips/powertv/Kconfig" +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index 0b9c01a..007a82e 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -659,6 +659,12 @@ else + load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 + endif + ++# Ingenic JZ4740 ++# ++core-$(CONFIG_SOC_JZ4740) += arch/mips/jz4740/ ++cflags-$(CONFIG_SOC_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 ++load-$(CONFIG_SOC_JZ4740) += 0xffffffff80010000 ++ + cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic + drivers-$(CONFIG_PCI) += arch/mips/pci/ + +diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h +index 09eee09..15a8ef0 100644 +--- a/arch/mips/include/asm/bootinfo.h ++++ b/arch/mips/include/asm/bootinfo.h +@@ -71,6 +71,12 @@ + #define MACH_LEMOTE_LL2F 7 + #define MACH_LOONGSON_END 8 + ++/* ++ * Valid machtype for group INGENIC ++ */ ++#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */ ++#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */ ++ + extern char *system_type; + const char *get_system_type(void); + +diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h +index a5acda4..e67aebb 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 +@@ -133,6 +133,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 + */ + +@@ -226,6 +232,11 @@ enum cpu_type_enum { + CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2, + CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, + ++ /* ++ * Ingenic class processors ++ */ ++ CPU_JZRISC, CPU_XBURST, ++ + CPU_LAST + }; + +diff --git a/arch/mips/include/asm/mach-jz4740/base.h b/arch/mips/include/asm/mach-jz4740/base.h +new file mode 100644 +index 0000000..a281972 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/base.h +@@ -0,0 +1,28 @@ ++#ifndef __JZ4740_BASE_ADDR_H__ ++#define __JZ4740_BASE_ADDR_H__ ++ ++#define JZ4740_CPM_BASE_ADDR 0xb0000000 ++#define JZ4740_INTC_BASE_ADDR 0xb0001000 ++#define JZ4740_TCU_BASE_ADDR 0xb0002000 ++#define JZ4740_WDT_BASE_ADDR 0xb0002000 ++#define JZ4740_RTC_BASE_ADDR 0xb0003000 ++#define JZ4740_GPIO_BASE_ADDR 0xb0010000 ++#define JZ4740_AIC_BASE_ADDR 0xb0020000 ++#define JZ4740_ICDC_BASE_ADDR 0xb0020000 ++#define JZ4740_MSC_BASE_ADDR 0xb0021000 ++#define JZ4740_UART0_BASE_ADDR 0xb0030000 ++#define JZ4740_UART1_BASE_ADDR 0xb0031000 ++#define JZ4740_I2C_BASE_ADDR 0xb0042000 ++#define JZ4740_SSI_BASE_ADDR 0xb0043000 ++#define JZ4740_SADC_BASE_ADDR 0xb0070000 ++#define JZ4740_EMC_BASE_ADDR 0xb3010000 ++#define JZ4740_DMAC_BASE_ADDR 0xb3020000 ++#define JZ4740_UHC_BASE_ADDR 0xb3030000 ++#define JZ4740_UDC_BASE_ADDR 0xb3040000 ++#define JZ4740_LCD_BASE_ADDR 0xb3050000 ++#define JZ4740_SLCD_BASE_ADDR 0xb3050000 ++#define JZ4740_CIM_BASE_ADDR 0xb3060000 ++#define JZ4740_IPU_BASE_ADDR 0xb3080000 ++#define JZ4740_ETH_BASE_ADDR 0xb3100000 ++ ++#endif +diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h +new file mode 100644 +index 0000000..9069727 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/clock.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * ++ * 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 __ASM_JZ4740_CLOCK_H__ ++#define __ASM_JZ4740_CLOCK_H__ ++ ++enum jz4740_wait_mode { ++ JZ4740_WAIT_MODE_IDLE, ++ JZ4740_WAIT_MODE_SLEEP, ++}; ++ ++void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode); ++ ++void jz4740_clock_udc_enable_auto_suspend(void); ++void jz4740_clock_udc_disable_auto_suspend(void); ++ ++#endif +diff --git a/arch/mips/include/asm/mach-jz4740/dma.h b/arch/mips/include/asm/mach-jz4740/dma.h +new file mode 100644 +index 0000000..d31d4e0 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/dma.h +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ7420/JZ4740 DMA definitions ++ * ++ * 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 __ASM_MACH_JZ4740_DMA_H__ ++#define __ASM_MACH_JZ4740_DMA_H__ ++ ++struct jz4740_dma_chan; ++ ++enum jz4740_dma_request_type { ++ JZ4740_DMA_TYPE_AUTO_REQUEST = 8, ++ JZ4740_DMA_TYPE_UART_TRANSMIT = 20, ++ JZ4740_DMA_TYPE_UART_RECEIVE = 21, ++ JZ4740_DMA_TYPE_SPI_TRANSMIT = 22, ++ JZ4740_DMA_TYPE_SPI_RECEIVE = 23, ++ JZ4740_DMA_TYPE_AIC_TRANSMIT = 24, ++ JZ4740_DMA_TYPE_AIC_RECEIVE = 25, ++ JZ4740_DMA_TYPE_MMC_TRANSMIT = 26, ++ JZ4740_DMA_TYPE_MMC_RECEIVE = 27, ++ JZ4740_DMA_TYPE_TCU = 28, ++ JZ4740_DMA_TYPE_SADC = 29, ++ JZ4740_DMA_TYPE_SLCD = 30, ++}; ++ ++enum jz4740_dma_width { ++ JZ4740_DMA_WIDTH_8BIT, ++ JZ4740_DMA_WIDTH_16BIT, ++ JZ4740_DMA_WIDTH_32BIT, ++}; ++ ++enum jz4740_dma_transfer_size { ++ JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0, ++ JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1, ++ JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2, ++ JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3, ++ JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4, ++}; ++ ++enum jz4740_dma_flags { ++ JZ4740_DMA_SRC_AUTOINC = 0x2, ++ JZ4740_DMA_DST_AUTOINC = 0x1, ++}; ++ ++enum jz4740_dma_mode { ++ JZ4740_DMA_MODE_SINGLE = 0, ++ JZ4740_DMA_MODE_BLOCK = 1, ++}; ++ ++struct jz4740_dma_config { ++ enum jz4740_dma_width src_width; ++ enum jz4740_dma_width dst_width; ++ enum jz4740_dma_transfer_size transfer_size; ++ enum jz4740_dma_request_type request_type; ++ enum jz4740_dma_flags flags; ++ enum jz4740_dma_mode mode; ++}; ++ ++typedef void (*jz4740_dma_complete_callback_t)(struct jz4740_dma_chan *, int, void *); ++ ++struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name); ++void jz4740_dma_free(struct jz4740_dma_chan *dma); ++ ++void jz4740_dma_configure(struct jz4740_dma_chan *dma, ++ const struct jz4740_dma_config *config); ++ ++ ++void jz4740_dma_enable(struct jz4740_dma_chan *dma); ++void jz4740_dma_disable(struct jz4740_dma_chan *dma); ++ ++void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src); ++void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst); ++void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count); ++ ++uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma); ++ ++void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma, ++ jz4740_dma_complete_callback_t cb); ++ ++#endif /* __ASM_JZ4740_DMA_H__ */ +diff --git a/arch/mips/include/asm/mach-jz4740/gpio.h b/arch/mips/include/asm/mach-jz4740/gpio.h +new file mode 100644 +index 0000000..5f175d7 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/gpio.h +@@ -0,0 +1,398 @@ ++/* ++ * Copyright (C) 2009, Lars-Peter Clausen ++ * JZ7420/JZ4740 GPIO pin definitions ++ * ++ * 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_GPIO_H ++#define _JZ_GPIO_H ++ ++#include ++ ++enum jz_gpio_function { ++ JZ_GPIO_FUNC_NONE, ++ JZ_GPIO_FUNC1, ++ JZ_GPIO_FUNC2, ++ JZ_GPIO_FUNC3, ++}; ++ ++ ++/* ++ Usually a driver for a SoC component has to request several gpio pins and ++ configure them as funcion pins. ++ jz_gpio_bulk_request can be used to ease this process. ++ Usually one would do something like: ++ ++ const static struct jz_gpio_bulk_request i2c_pins[] = { ++ JZ_GPIO_BULK_PIN(I2C_SDA), ++ JZ_GPIO_BULK_PIN(I2C_SCK), ++ }; ++ ++ inside the probe function: ++ ++ ret = jz_gpio_bulk_request(i2c_pins, ARRAY_SIZE(i2c_pins)); ++ if (ret) { ++ ... ++ ++ inside the remove function: ++ ++ jz_gpio_bulk_free(i2c_pins, ARRAY_SIZE(i2c_pins)); ++ ++ ++*/ ++struct jz_gpio_bulk_request { ++ int gpio; ++ const char *name; ++ enum jz_gpio_function function; ++}; ++ ++#define JZ_GPIO_BULK_PIN(pin) { \ ++ .gpio = JZ_GPIO_ ## pin, \ ++ .name = #pin, \ ++ .function = JZ_GPIO_FUNC_ ## pin \ ++} ++ ++int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num); ++void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num); ++void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num); ++void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num); ++void jz_gpio_enable_pullup(unsigned gpio); ++void jz_gpio_disable_pullup(unsigned gpio); ++int jz_gpio_set_function(int gpio, enum jz_gpio_function function); ++ ++int jz_gpio_port_direction_input(int port, uint32_t mask); ++int jz_gpio_port_direction_output(int port, uint32_t mask); ++void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask); ++uint32_t jz_gpio_port_get_value(int port, uint32_t mask); ++ ++#include ++ ++#define JZ_GPIO_PORTA(x) ((x) + 32 * 0) ++#define JZ_GPIO_PORTB(x) ((x) + 32 * 1) ++#define JZ_GPIO_PORTC(x) ((x) + 32 * 2) ++#define JZ_GPIO_PORTD(x) ((x) + 32 * 3) ++ ++/* Port A function pins */ ++#define JZ_GPIO_MEM_DATA0 JZ_GPIO_PORTA(0) ++#define JZ_GPIO_MEM_DATA1 JZ_GPIO_PORTA(1) ++#define JZ_GPIO_MEM_DATA2 JZ_GPIO_PORTA(2) ++#define JZ_GPIO_MEM_DATA3 JZ_GPIO_PORTA(3) ++#define JZ_GPIO_MEM_DATA4 JZ_GPIO_PORTA(4) ++#define JZ_GPIO_MEM_DATA5 JZ_GPIO_PORTA(5) ++#define JZ_GPIO_MEM_DATA6 JZ_GPIO_PORTA(6) ++#define JZ_GPIO_MEM_DATA7 JZ_GPIO_PORTA(7) ++#define JZ_GPIO_MEM_DATA8 JZ_GPIO_PORTA(8) ++#define JZ_GPIO_MEM_DATA9 JZ_GPIO_PORTA(9) ++#define JZ_GPIO_MEM_DATA10 JZ_GPIO_PORTA(10) ++#define JZ_GPIO_MEM_DATA11 JZ_GPIO_PORTA(11) ++#define JZ_GPIO_MEM_DATA12 JZ_GPIO_PORTA(12) ++#define JZ_GPIO_MEM_DATA13 JZ_GPIO_PORTA(13) ++#define JZ_GPIO_MEM_DATA14 JZ_GPIO_PORTA(14) ++#define JZ_GPIO_MEM_DATA15 JZ_GPIO_PORTA(15) ++#define JZ_GPIO_MEM_DATA16 JZ_GPIO_PORTA(16) ++#define JZ_GPIO_MEM_DATA17 JZ_GPIO_PORTA(17) ++#define JZ_GPIO_MEM_DATA18 JZ_GPIO_PORTA(18) ++#define JZ_GPIO_MEM_DATA19 JZ_GPIO_PORTA(19) ++#define JZ_GPIO_MEM_DATA20 JZ_GPIO_PORTA(20) ++#define JZ_GPIO_MEM_DATA21 JZ_GPIO_PORTA(21) ++#define JZ_GPIO_MEM_DATA22 JZ_GPIO_PORTA(22) ++#define JZ_GPIO_MEM_DATA23 JZ_GPIO_PORTA(23) ++#define JZ_GPIO_MEM_DATA24 JZ_GPIO_PORTA(24) ++#define JZ_GPIO_MEM_DATA25 JZ_GPIO_PORTA(25) ++#define JZ_GPIO_MEM_DATA26 JZ_GPIO_PORTA(26) ++#define JZ_GPIO_MEM_DATA27 JZ_GPIO_PORTA(27) ++#define JZ_GPIO_MEM_DATA28 JZ_GPIO_PORTA(28) ++#define JZ_GPIO_MEM_DATA29 JZ_GPIO_PORTA(29) ++#define JZ_GPIO_MEM_DATA30 JZ_GPIO_PORTA(30) ++#define JZ_GPIO_MEM_DATA31 JZ_GPIO_PORTA(31) ++ ++#define JZ_GPIO_FUNC_MEM_DATA0 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA1 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA2 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA3 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA4 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA5 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA6 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA7 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA8 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA9 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA10 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA11 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA12 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA13 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA14 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA15 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA16 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA17 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA18 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA19 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA20 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA21 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA22 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA23 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA24 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA25 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA26 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA27 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA28 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA29 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA30 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DATA31 JZ_GPIO_FUNC1 ++ ++/* Port B function pins */ ++#define JZ_GPIO_MEM_ADDR0 JZ_GPIO_PORTB(0) ++#define JZ_GPIO_MEM_ADDR1 JZ_GPIO_PORTB(1) ++#define JZ_GPIO_MEM_ADDR2 JZ_GPIO_PORTB(2) ++#define JZ_GPIO_MEM_ADDR3 JZ_GPIO_PORTB(3) ++#define JZ_GPIO_MEM_ADDR4 JZ_GPIO_PORTB(4) ++#define JZ_GPIO_MEM_ADDR5 JZ_GPIO_PORTB(5) ++#define JZ_GPIO_MEM_ADDR6 JZ_GPIO_PORTB(6) ++#define JZ_GPIO_MEM_ADDR7 JZ_GPIO_PORTB(7) ++#define JZ_GPIO_MEM_ADDR8 JZ_GPIO_PORTB(8) ++#define JZ_GPIO_MEM_ADDR9 JZ_GPIO_PORTB(9) ++#define JZ_GPIO_MEM_ADDR10 JZ_GPIO_PORTB(10) ++#define JZ_GPIO_MEM_ADDR11 JZ_GPIO_PORTB(11) ++#define JZ_GPIO_MEM_ADDR12 JZ_GPIO_PORTB(12) ++#define JZ_GPIO_MEM_ADDR13 JZ_GPIO_PORTB(13) ++#define JZ_GPIO_MEM_ADDR14 JZ_GPIO_PORTB(14) ++#define JZ_GPIO_MEM_ADDR15 JZ_GPIO_PORTB(15) ++#define JZ_GPIO_MEM_ADDR16 JZ_GPIO_PORTB(16) ++#define JZ_GPIO_MEM_CLS JZ_GPIO_PORTB(17) ++#define JZ_GPIO_MEM_SPL JZ_GPIO_PORTB(18) ++#define JZ_GPIO_MEM_DCS JZ_GPIO_PORTB(19) ++#define JZ_GPIO_MEM_RAS JZ_GPIO_PORTB(20) ++#define JZ_GPIO_MEM_CAS JZ_GPIO_PORTB(21) ++#define JZ_GPIO_MEM_SDWE JZ_GPIO_PORTB(22) ++#define JZ_GPIO_MEM_CKE JZ_GPIO_PORTB(23) ++#define JZ_GPIO_MEM_CKO JZ_GPIO_PORTB(24) ++#define JZ_GPIO_MEM_CS0 JZ_GPIO_PORTB(25) ++#define JZ_GPIO_MEM_CS1 JZ_GPIO_PORTB(26) ++#define JZ_GPIO_MEM_CS2 JZ_GPIO_PORTB(27) ++#define JZ_GPIO_MEM_CS3 JZ_GPIO_PORTB(28) ++#define JZ_GPIO_MEM_RD JZ_GPIO_PORTB(29) ++#define JZ_GPIO_MEM_WR JZ_GPIO_PORTB(30) ++#define JZ_GPIO_MEM_WE0 JZ_GPIO_PORTB(31) ++ ++#define JZ_GPIO_FUNC_MEM_ADDR0 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR1 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR2 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR3 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR4 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR5 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR6 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR7 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR8 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR9 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR10 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR11 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR12 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR13 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR14 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR15 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_ADDR16 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CLS JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_SPL JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_DCS JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_RAS JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CAS JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_SDWE JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CKE JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CKO JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CS0 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CS1 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CS2 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_CS3 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_RD JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_WR JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_WE0 JZ_GPIO_FUNC1 ++ ++ ++#define JZ_GPIO_MEM_ADDR21 JZ_GPIO_PORTB(17) ++#define JZ_GPIO_MEM_ADDR22 JZ_GPIO_PORTB(18) ++ ++#define JZ_GPIO_FUNC_MEM_ADDR21 JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_ADDR22 JZ_GPIO_FUNC2 ++ ++/* Port C function pins */ ++#define JZ_GPIO_LCD_DATA0 JZ_GPIO_PORTC(0) ++#define JZ_GPIO_LCD_DATA1 JZ_GPIO_PORTC(1) ++#define JZ_GPIO_LCD_DATA2 JZ_GPIO_PORTC(2) ++#define JZ_GPIO_LCD_DATA3 JZ_GPIO_PORTC(3) ++#define JZ_GPIO_LCD_DATA4 JZ_GPIO_PORTC(4) ++#define JZ_GPIO_LCD_DATA5 JZ_GPIO_PORTC(5) ++#define JZ_GPIO_LCD_DATA6 JZ_GPIO_PORTC(6) ++#define JZ_GPIO_LCD_DATA7 JZ_GPIO_PORTC(7) ++#define JZ_GPIO_LCD_DATA8 JZ_GPIO_PORTC(8) ++#define JZ_GPIO_LCD_DATA9 JZ_GPIO_PORTC(9) ++#define JZ_GPIO_LCD_DATA10 JZ_GPIO_PORTC(10) ++#define JZ_GPIO_LCD_DATA11 JZ_GPIO_PORTC(11) ++#define JZ_GPIO_LCD_DATA12 JZ_GPIO_PORTC(12) ++#define JZ_GPIO_LCD_DATA13 JZ_GPIO_PORTC(13) ++#define JZ_GPIO_LCD_DATA14 JZ_GPIO_PORTC(14) ++#define JZ_GPIO_LCD_DATA15 JZ_GPIO_PORTC(15) ++#define JZ_GPIO_LCD_DATA16 JZ_GPIO_PORTC(16) ++#define JZ_GPIO_LCD_DATA17 JZ_GPIO_PORTC(17) ++#define JZ_GPIO_LCD_PCLK JZ_GPIO_PORTC(18) ++#define JZ_GPIO_LCD_HSYNC JZ_GPIO_PORTC(19) ++#define JZ_GPIO_LCD_VSYNC JZ_GPIO_PORTC(20) ++#define JZ_GPIO_LCD_DE JZ_GPIO_PORTC(21) ++#define JZ_GPIO_LCD_PS JZ_GPIO_PORTC(22) ++#define JZ_GPIO_LCD_REV JZ_GPIO_PORTC(23) ++#define JZ_GPIO_MEM_WE1 JZ_GPIO_PORTC(24) ++#define JZ_GPIO_MEM_WE2 JZ_GPIO_PORTC(25) ++#define JZ_GPIO_MEM_WE3 JZ_GPIO_PORTC(26) ++#define JZ_GPIO_MEM_WAIT JZ_GPIO_PORTC(27) ++#define JZ_GPIO_MEM_FRE JZ_GPIO_PORTC(28) ++#define JZ_GPIO_MEM_FWE JZ_GPIO_PORTC(29) ++ ++#define JZ_GPIO_FUNC_LCD_DATA0 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA1 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA2 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA3 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA4 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA5 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA6 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA7 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA8 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA9 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA10 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA11 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA12 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA13 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA14 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA15 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA16 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DATA17 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_PCLK JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_VSYNC JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_HSYNC JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_DE JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_PS JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_LCD_REV JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_WE1 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_WE2 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_WE3 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_WAIT JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_FRE JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MEM_FWE JZ_GPIO_FUNC1 ++ ++ ++#define JZ_GPIO_MEM_ADDR19 JZ_GPIO_PORTB(22) ++#define JZ_GPIO_MEM_ADDR20 JZ_GPIO_PORTB(23) ++ ++#define JZ_GPIO_FUNC_MEM_ADDR19 JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_ADDR20 JZ_GPIO_FUNC2 ++ ++/* Port D function pins */ ++#define JZ_GPIO_CIM_DATA0 JZ_GPIO_PORTD(0) ++#define JZ_GPIO_CIM_DATA1 JZ_GPIO_PORTD(1) ++#define JZ_GPIO_CIM_DATA2 JZ_GPIO_PORTD(2) ++#define JZ_GPIO_CIM_DATA3 JZ_GPIO_PORTD(3) ++#define JZ_GPIO_CIM_DATA4 JZ_GPIO_PORTD(4) ++#define JZ_GPIO_CIM_DATA5 JZ_GPIO_PORTD(5) ++#define JZ_GPIO_CIM_DATA6 JZ_GPIO_PORTD(6) ++#define JZ_GPIO_CIM_DATA7 JZ_GPIO_PORTD(7) ++#define JZ_GPIO_MSC_CMD JZ_GPIO_PORTD(8) ++#define JZ_GPIO_MSC_CLK JZ_GPIO_PORTD(9) ++#define JZ_GPIO_MSC_DATA0 JZ_GPIO_PORTD(10) ++#define JZ_GPIO_MSC_DATA1 JZ_GPIO_PORTD(11) ++#define JZ_GPIO_MSC_DATA2 JZ_GPIO_PORTD(12) ++#define JZ_GPIO_MSC_DATA3 JZ_GPIO_PORTD(13) ++#define JZ_GPIO_CIM_MCLK JZ_GPIO_PORTD(14) ++#define JZ_GPIO_CIM_PCLK JZ_GPIO_PORTD(15) ++#define JZ_GPIO_CIM_VSYNC JZ_GPIO_PORTD(16) ++#define JZ_GPIO_CIM_HSYNC JZ_GPIO_PORTD(17) ++#define JZ_GPIO_SPI_CLK JZ_GPIO_PORTD(18) ++#define JZ_GPIO_SPI_CE0 JZ_GPIO_PORTD(19) ++#define JZ_GPIO_SPI_DT JZ_GPIO_PORTD(20) ++#define JZ_GPIO_SPI_DR JZ_GPIO_PORTD(21) ++#define JZ_GPIO_SPI_CE1 JZ_GPIO_PORTD(22) ++#define JZ_GPIO_PWM0 JZ_GPIO_PORTD(23) ++#define JZ_GPIO_PWM1 JZ_GPIO_PORTD(24) ++#define JZ_GPIO_PWM2 JZ_GPIO_PORTD(25) ++#define JZ_GPIO_PWM3 JZ_GPIO_PORTD(26) ++#define JZ_GPIO_PWM4 JZ_GPIO_PORTD(27) ++#define JZ_GPIO_PWM5 JZ_GPIO_PORTD(28) ++#define JZ_GPIO_PWM6 JZ_GPIO_PORTD(30) ++#define JZ_GPIO_PWM7 JZ_GPIO_PORTD(31) ++ ++#define JZ_GPIO_FUNC_CIM_DATA JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_CIM_DATA0 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA1 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA2 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA3 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA4 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA5 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA6 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_CIM_DATA7 JZ_GPIO_FUNC_CIM_DATA ++#define JZ_GPIO_FUNC_MSC_CMD JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MSC_CLK JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MSC_DATA JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_MSC_DATA0 JZ_GPIO_FUNC_MSC_DATA ++#define JZ_GPIO_FUNC_MSC_DATA1 JZ_GPIO_FUNC_MSC_DATA ++#define JZ_GPIO_FUNC_MSC_DATA2 JZ_GPIO_FUNC_MSC_DATA ++#define JZ_GPIO_FUNC_MSC_DATA3 JZ_GPIO_FUNC_MSC_DATA ++#define JZ_GPIO_FUNC_CIM_MCLK JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_CIM_PCLK JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_CIM_VSYNC JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_CIM_HSYNC JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_SPI_CLK JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_SPI_CE0 JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_SPI_DT JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_SPI_DR JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_SPI_CE1 JZ_GPIO_FUNC1 ++ ++#define JZ_GPIO_FUNC_PWM JZ_GPIO_FUNC1 ++#define JZ_GPIO_FUNC_PWM0 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM1 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM2 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM3 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM4 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM5 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM6 JZ_GPIO_FUNC_PWM ++#define JZ_GPIO_FUNC_PWM7 JZ_GPIO_FUNC_PWM ++ ++#define JZ_GPIO_MEM_SCLK_RSTN JZ_GPIO_PORTD(18) ++#define JZ_GPIO_MEM_BCLK JZ_GPIO_PORTD(19) ++#define JZ_GPIO_MEM_SDATO JZ_GPIO_PORTD(20) ++#define JZ_GPIO_MEM_SDATI JZ_GPIO_PORTD(21) ++#define JZ_GPIO_MEM_SYNC JZ_GPIO_PORTD(22) ++#define JZ_GPIO_I2C_SDA JZ_GPIO_PORTD(23) ++#define JZ_GPIO_I2C_SCK JZ_GPIO_PORTD(24) ++#define JZ_GPIO_UART0_TXD JZ_GPIO_PORTD(25) ++#define JZ_GPIO_UART0_RXD JZ_GPIO_PORTD(26) ++#define JZ_GPIO_MEM_ADDR17 JZ_GPIO_PORTD(27) ++#define JZ_GPIO_MEM_ADDR18 JZ_GPIO_PORTD(28) ++#define JZ_GPIO_UART0_CTS JZ_GPIO_PORTD(30) ++#define JZ_GPIO_UART0_RTS JZ_GPIO_PORTD(31) ++ ++#define JZ_GPIO_FUNC_MEM_SCLK_RSTN JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_BCLK JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_SDATO JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_SDATI JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_SYNC JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_I2C_SDA JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_I2C_SCK JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_UART0_TXD JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_UART0_RXD JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_ADDR17 JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_MEM_ADDR18 JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_UART0_CTS JZ_GPIO_FUNC2 ++#define JZ_GPIO_FUNC_UART0_RTS JZ_GPIO_FUNC2 ++ ++#define JZ_GPIO_UART1_RXD JZ_GPIO_PORTD(30) ++#define JZ_GPIO_UART1_TXD JZ_GPIO_PORTD(31) ++ ++#define JZ_GPIO_FUNC_UART1_RXD JZ_GPIO_FUNC3 ++#define JZ_GPIO_FUNC_UART1_TXD JZ_GPIO_FUNC3 ++ ++#endif +diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h +new file mode 100644 +index 0000000..5e27b78 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/irq.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2009-2010, Lars-Peter Clausen ++ * JZ7420/JZ4740 IRQ definitions ++ * ++ * 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 __ASM_MACH_JZ4740_IRQ_H__ ++#define __ASM_MACH_JZ4740_IRQ_H__ ++ ++#define MIPS_CPU_IRQ_BASE 0 ++#define JZ4740_IRQ_BASE 8 ++ ++/* 1st-level interrupts */ ++#define JZ4740_IRQ(x) (JZ4740_IRQ_BASE + (x)) ++#define JZ4740_IRQ_I2C JZ4740_IRQ(1) ++#define JZ4740_IRQ_UHC JZ4740_IRQ(3) ++#define JZ4740_IRQ_UART1 JZ4740_IRQ(8) ++#define JZ4740_IRQ_UART0 JZ4740_IRQ(9) ++#define JZ4740_IRQ_SADC JZ4740_IRQ(12) ++#define JZ4740_IRQ_MSC JZ4740_IRQ(14) ++#define JZ4740_IRQ_RTC JZ4740_IRQ(15) ++#define JZ4740_IRQ_SSI JZ4740_IRQ(16) ++#define JZ4740_IRQ_CIM JZ4740_IRQ(17) ++#define JZ4740_IRQ_AIC JZ4740_IRQ(18) ++#define JZ4740_IRQ_ETH JZ4740_IRQ(19) ++#define JZ4740_IRQ_DMAC JZ4740_IRQ(20) ++#define JZ4740_IRQ_TCU2 JZ4740_IRQ(21) ++#define JZ4740_IRQ_TCU1 JZ4740_IRQ(22) ++#define JZ4740_IRQ_TCU0 JZ4740_IRQ(23) ++#define JZ4740_IRQ_UDC JZ4740_IRQ(24) ++#define JZ4740_IRQ_GPIO3 JZ4740_IRQ(25) ++#define JZ4740_IRQ_GPIO2 JZ4740_IRQ(26) ++#define JZ4740_IRQ_GPIO1 JZ4740_IRQ(27) ++#define JZ4740_IRQ_GPIO0 JZ4740_IRQ(28) ++#define JZ4740_IRQ_IPU JZ4740_IRQ(29) ++#define JZ4740_IRQ_LCD JZ4740_IRQ(30) ++ ++/* 2nd-level interrupts */ ++#define JZ4740_IRQ_DMA(x) ((x) + JZ4740_IRQ(32)) ++ ++#define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x)) ++#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x)) ++ ++#define NR_IRQS (JZ4740_IRQ_GPIO(127) + 1) ++ ++#endif +diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h +new file mode 100644 +index 0000000..a2e2871 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/platform.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2009, Lars-Peter Clausen ++ * JZ7420/JZ4740 platform device definitions ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++ ++#ifndef __JZ4740_PLATFORM_H ++#define __JZ4740_PLATFORM_H ++ ++#include ++ ++extern struct platform_device jz4740_usb_ohci_device; ++extern struct platform_device jz4740_usb_gdt_device; ++extern struct platform_device jz4740_mmc_device; ++extern struct platform_device jz4740_rtc_device; ++extern struct platform_device jz4740_i2c_device; ++extern struct platform_device jz4740_nand_device; ++extern struct platform_device jz4740_framebuffer_device; ++extern struct platform_device jz4740_i2s_device; ++extern struct platform_device jz4740_codec_device; ++extern struct platform_device jz4740_adc_device; ++extern struct platform_device jz4740_battery_device; ++ ++#endif +diff --git a/arch/mips/include/asm/mach-jz4740/serial.h b/arch/mips/include/asm/mach-jz4740/serial.h +new file mode 100644 +index 0000000..c4819b9 +--- /dev/null ++++ b/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/arch/mips/include/asm/mach-jz4740/timer.h b/arch/mips/include/asm/mach-jz4740/timer.h +new file mode 100644 +index 0000000..30153ff +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/timer.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 platform timer 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. ++ * ++ */ ++ ++#ifndef __ASM_MACH_JZ4740_TIMER ++#define __ASM_MACH_JZ4740_TIMER ++ ++void jz4740_timer_enable_watchdog(void); ++void jz4740_timer_disable_watchdog(void); ++ ++#endif +diff --git a/arch/mips/include/asm/mach-jz4740/war.h b/arch/mips/include/asm/mach-jz4740/war.h +new file mode 100644 +index 0000000..3a5bc17 +--- /dev/null ++++ b/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/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig +new file mode 100644 +index 0000000..5f6da09 +--- /dev/null ++++ b/arch/mips/jz4740/Kconfig +@@ -0,0 +1,29 @@ ++choice ++ prompt "Machine type" ++ depends on MACH_JZ ++ default JZ4740_QI_LB60 ++ ++endchoice ++ ++config HAVE_PWM ++ bool ++ ++config SOC_JZ4740 ++ bool ++ select JZSOC ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select IRQ_CPU ++ select DMA_NONCOHERENT ++ select HAVE_PWM ++ ++config JZSOC ++ bool ++ select JZRISC ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_SUPPORTS_32BIT_KERNEL ++ ++config JZRISC ++ bool +diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile +new file mode 100644 +index 0000000..e389ddd +--- /dev/null ++++ b/arch/mips/jz4740/Makefile +@@ -0,0 +1,17 @@ ++# ++# Makefile for the Ingenic JZ4740. ++# ++ ++# Object file lists. ++ ++obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ ++ gpio.o clock.o platform.o timer.o pwm.o ++ ++obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o ++ ++# board specific support ++ ++# PM support ++ ++obj-$(CONFIG_PM) += pm.o ++ +diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c +new file mode 100644 +index 0000000..993b91b +--- /dev/null ++++ b/arch/mips/jz4740/clock-debugfs.c +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 SoC clock support debugfs entries ++ * ++ * 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 "clock.h" ++ ++static struct dentry *jz4740_clock_debugfs; ++ ++static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value) ++{ ++ struct clk *clk = data; ++ *value = clk_is_enabled(clk); ++ ++ return 0; ++} ++ ++static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value) ++{ ++ struct clk *clk = data; ++ ++ if (value) ++ return clk_enable(clk); ++ else ++ clk_disable(clk); ++ ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled, ++ jz4740_clock_debugfs_show_enabled, ++ jz4740_clock_debugfs_set_enabled, ++ "%llu\n"); ++ ++static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value) ++{ ++ struct clk *clk = data; ++ *value = clk_get_rate(clk); ++ ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate, ++ jz4740_clock_debugfs_show_rate, ++ NULL, ++ "%llu\n"); ++ ++void jz4740_clock_debugfs_add_clk(struct clk *clk) ++{ ++ if (!jz4740_clock_debugfs) ++ return; ++ ++ clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs); ++ debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk, ++ &jz4740_clock_debugfs_ops_rate); ++ debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk, ++ &jz4740_clock_debugfs_ops_enabled); ++ ++ if (clk->parent) { ++ char parent_path[100]; ++ snprintf(parent_path, 100, "../%s", clk->parent->name); ++ clk->debugfs_parent_entry = debugfs_create_symlink("parent", ++ clk->debugfs_entry, ++ parent_path); ++ } ++} ++ ++/* TODO: Locking */ ++void jz4740_clock_debugfs_update_parent(struct clk *clk) ++{ ++ if (clk->debugfs_parent_entry) ++ debugfs_remove(clk->debugfs_parent_entry); ++ ++ if (clk->parent) { ++ char parent_path[100]; ++ snprintf(parent_path, 100, "../%s", clk->parent->name); ++ clk->debugfs_parent_entry = debugfs_create_symlink("parent", ++ clk->debugfs_entry, ++ parent_path); ++ } else { ++ clk->debugfs_parent_entry = NULL; ++ } ++} ++ ++void jz4740_clock_debugfs_init(void) ++{ ++ jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL); ++ if (IS_ERR(jz4740_clock_debugfs)) ++ jz4740_clock_debugfs = NULL; ++} +diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c +new file mode 100644 +index 0000000..3954a20 +--- /dev/null ++++ b/arch/mips/jz4740/clock.c +@@ -0,0 +1,935 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 SoC clock 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 "clock.h" ++ ++#define JZ_REG_CLOCK_CTRL 0x00 ++#define JZ_REG_CLOCK_LOW_POWER 0x04 ++#define JZ_REG_CLOCK_PLL 0x10 ++#define JZ_REG_CLOCK_GATE 0x20 ++#define JZ_REG_CLOCK_SLEEP_CTRL 0x24 ++#define JZ_REG_CLOCK_I2S 0x60 ++#define JZ_REG_CLOCK_LCD 0x64 ++#define JZ_REG_CLOCK_MMC 0x68 ++#define JZ_REG_CLOCK_UHC 0x6C ++#define JZ_REG_CLOCK_SPI 0x74 ++ ++#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31) ++#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30) ++#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29) ++#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000 ++#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22) ++#define JZ_CLOCK_CTRL_PLL_HALF BIT(21) ++#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000 ++#define JZ_CLOCK_CTRL_UDIV_OFFSET 23 ++#define JZ_CLOCK_CTRL_LDIV_OFFSET 16 ++#define JZ_CLOCK_CTRL_MDIV_OFFSET 12 ++#define JZ_CLOCK_CTRL_PDIV_OFFSET 8 ++#define JZ_CLOCK_CTRL_HDIV_OFFSET 4 ++#define JZ_CLOCK_CTRL_CDIV_OFFSET 0 ++ ++#define JZ_CLOCK_GATE_UART0 BIT(0) ++#define JZ_CLOCK_GATE_TCU BIT(1) ++#define JZ_CLOCK_GATE_RTC BIT(2) ++#define JZ_CLOCK_GATE_I2C BIT(3) ++#define JZ_CLOCK_GATE_SPI BIT(4) ++#define JZ_CLOCK_GATE_AIC BIT(5) ++#define JZ_CLOCK_GATE_I2S BIT(6) ++#define JZ_CLOCK_GATE_MMC BIT(7) ++#define JZ_CLOCK_GATE_ADC BIT(8) ++#define JZ_CLOCK_GATE_CIM BIT(9) ++#define JZ_CLOCK_GATE_LCD BIT(10) ++#define JZ_CLOCK_GATE_UDC BIT(11) ++#define JZ_CLOCK_GATE_DMAC BIT(12) ++#define JZ_CLOCK_GATE_IPU BIT(13) ++#define JZ_CLOCK_GATE_UHC BIT(14) ++#define JZ_CLOCK_GATE_UART1 BIT(15) ++ ++#define JZ_CLOCK_I2S_DIV_MASK 0x01ff ++ ++#define JZ_CLOCK_LCD_DIV_MASK 0x01ff ++ ++#define JZ_CLOCK_MMC_DIV_MASK 0x001f ++ ++#define JZ_CLOCK_UHC_DIV_MASK 0x000f ++ ++#define JZ_CLOCK_SPI_SRC_PLL BIT(31) ++#define JZ_CLOCK_SPI_DIV_MASK 0x000f ++ ++#define JZ_CLOCK_PLL_M_MASK 0x01ff ++#define JZ_CLOCK_PLL_N_MASK 0x001f ++#define JZ_CLOCK_PLL_OD_MASK 0x0003 ++#define JZ_CLOCK_PLL_STABLE BIT(10) ++#define JZ_CLOCK_PLL_BYPASS BIT(9) ++#define JZ_CLOCK_PLL_ENABLED BIT(8) ++#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f ++#define JZ_CLOCK_PLL_M_OFFSET 23 ++#define JZ_CLOCK_PLL_N_OFFSET 18 ++#define JZ_CLOCK_PLL_OD_OFFSET 16 ++ ++#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2) ++#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0) ++ ++#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7) ++#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6) ++ ++static void __iomem *jz_clock_base; ++static spinlock_t jz_clock_lock; ++static LIST_HEAD(jz_clocks); ++ ++struct main_clk { ++ struct clk clk; ++ uint32_t div_offset; ++}; ++ ++struct divided_clk { ++ struct clk clk; ++ uint32_t reg; ++ uint32_t mask; ++}; ++ ++struct static_clk { ++ struct clk clk; ++ unsigned long rate; ++}; ++ ++static uint32_t jz_clk_reg_read(int reg) ++{ ++ return readl(jz_clock_base + reg); ++} ++ ++static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask) ++{ ++ uint32_t val2; ++ ++ spin_lock(&jz_clock_lock); ++ val2 = readl(jz_clock_base + reg); ++ val2 &= ~mask; ++ val2 |= val; ++ writel(val2, jz_clock_base + reg); ++ spin_unlock(&jz_clock_lock); ++} ++ ++static void jz_clk_reg_set_bits(int reg, uint32_t mask) ++{ ++ uint32_t val; ++ ++ spin_lock(&jz_clock_lock); ++ val = readl(jz_clock_base + reg); ++ val |= mask; ++ writel(val, jz_clock_base + reg); ++ spin_unlock(&jz_clock_lock); ++} ++ ++static void jz_clk_reg_clear_bits(int reg, uint32_t mask) ++{ ++ uint32_t val; ++ ++ spin_lock(&jz_clock_lock); ++ val = readl(jz_clock_base + reg); ++ val &= ~mask; ++ writel(val, jz_clock_base + reg); ++ spin_unlock(&jz_clock_lock); ++} ++ ++static int jz_clk_enable_gating(struct clk *clk) ++{ ++ if (clk->gate_bit == JZ4740_CLK_NOT_GATED) ++ return -EINVAL; ++ ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); ++ return 0; ++} ++ ++static int jz_clk_disable_gating(struct clk *clk) ++{ ++ if (clk->gate_bit == JZ4740_CLK_NOT_GATED) ++ return -EINVAL; ++ ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); ++ return 0; ++} ++ ++static int jz_clk_is_enabled_gating(struct clk *clk) ++{ ++ if (clk->gate_bit == JZ4740_CLK_NOT_GATED) ++ return 1; ++ ++ return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit); ++} ++ ++static unsigned long jz_clk_static_get_rate(struct clk *clk) ++{ ++ return ((struct static_clk *)clk)->rate; ++} ++ ++static int jz_clk_ko_enable(struct clk *clk) ++{ ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); ++ return 0; ++} ++ ++static int jz_clk_ko_disable(struct clk *clk) ++{ ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); ++ return 0; ++} ++ ++static int jz_clk_ko_is_enabled(struct clk *clk) ++{ ++ return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE); ++} ++ ++static const int pllno[] = {1, 2, 2, 4}; ++ ++static unsigned long jz_clk_pll_get_rate(struct clk *clk) ++{ ++ uint32_t val; ++ int m; ++ int n; ++ int od; ++ ++ val = jz_clk_reg_read(JZ_REG_CLOCK_PLL); ++ ++ if (val & JZ_CLOCK_PLL_BYPASS) ++ return clk_get_rate(clk->parent); ++ ++ m = ((val >> 23) & 0x1ff) + 2; ++ n = ((val >> 18) & 0x1f) + 2; ++ od = (val >> 16) & 0x3; ++ ++ return clk_get_rate(clk->parent) * (m / n) / pllno[od]; ++} ++ ++static unsigned long jz_clk_pll_half_get_rate(struct clk *clk) ++{ ++ uint32_t reg; ++ ++ reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); ++ if (reg & JZ_CLOCK_CTRL_PLL_HALF) ++ return jz_clk_pll_get_rate(clk->parent); ++ return jz_clk_pll_get_rate(clk->parent) >> 1; ++} ++ ++static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; ++ ++static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate) ++{ ++ unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); ++ int div; ++ ++ div = parent_rate / rate; ++ if (div > 32) ++ return parent_rate / 32; ++ else if (div < 1) ++ return parent_rate; ++ ++ div &= (0x3 << (ffs(div) - 1)); ++ ++ return parent_rate / div; ++} ++ ++static unsigned long jz_clk_main_get_rate(struct clk *clk) ++{ ++ struct main_clk *mclk = (struct main_clk *)clk; ++ uint32_t div; ++ ++ div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); ++ ++ div >>= mclk->div_offset; ++ div &= 0xf; ++ ++ if (div >= ARRAY_SIZE(jz_clk_main_divs)) ++ div = ARRAY_SIZE(jz_clk_main_divs) - 1; ++ ++ return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div]; ++} ++ ++static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate) ++{ ++ struct main_clk *mclk = (struct main_clk *)clk; ++ int i; ++ int div; ++ unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); ++ ++ rate = jz_clk_main_round_rate(clk, rate); ++ ++ div = parent_rate / rate; ++ ++ i = (ffs(div) - 1) << 1; ++ if (i > 0 && !(div & BIT(i-1))) ++ i -= 1; ++ ++ jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset, ++ 0xf << mclk->div_offset); ++ ++ return 0; ++} ++ ++static struct clk_ops jz_clk_static_ops = { ++ .get_rate = jz_clk_static_get_rate, ++ .enable = jz_clk_enable_gating, ++ .disable = jz_clk_disable_gating, ++ .is_enabled = jz_clk_is_enabled_gating, ++}; ++ ++static struct static_clk jz_clk_ext = { ++ .clk = { ++ .name = "ext", ++ .gate_bit = JZ4740_CLK_NOT_GATED, ++ .ops = &jz_clk_static_ops, ++ }, ++}; ++ ++static struct clk_ops jz_clk_pll_ops = { ++ .get_rate = jz_clk_static_get_rate, ++}; ++ ++static struct clk jz_clk_pll = { ++ .name = "pll", ++ .parent = &jz_clk_ext.clk, ++ .ops = &jz_clk_pll_ops, ++}; ++ ++static struct clk_ops jz_clk_pll_half_ops = { ++ .get_rate = jz_clk_pll_half_get_rate, ++}; ++ ++static struct clk jz_clk_pll_half = { ++ .name = "pll half", ++ .parent = &jz_clk_pll, ++ .ops = &jz_clk_pll_half_ops, ++}; ++ ++static const struct clk_ops jz_clk_main_ops = { ++ .get_rate = jz_clk_main_get_rate, ++ .set_rate = jz_clk_main_set_rate, ++ .round_rate = jz_clk_main_round_rate, ++}; ++ ++static struct main_clk jz_clk_cpu = { ++ .clk = { ++ .name = "cclk", ++ .parent = &jz_clk_pll, ++ .ops = &jz_clk_main_ops, ++ }, ++ .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET, ++}; ++ ++static struct main_clk jz_clk_memory = { ++ .clk = { ++ .name = "mclk", ++ .parent = &jz_clk_pll, ++ .ops = &jz_clk_main_ops, ++ }, ++ .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET, ++}; ++ ++static struct main_clk jz_clk_high_speed_peripheral = { ++ .clk = { ++ .name = "hclk", ++ .parent = &jz_clk_pll, ++ .ops = &jz_clk_main_ops, ++ }, ++ .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET, ++}; ++ ++ ++static struct main_clk jz_clk_low_speed_peripheral = { ++ .clk = { ++ .name = "pclk", ++ .parent = &jz_clk_pll, ++ .ops = &jz_clk_main_ops, ++ }, ++ .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET, ++}; ++ ++static const struct clk_ops jz_clk_ko_ops = { ++ .enable = jz_clk_ko_enable, ++ .disable = jz_clk_ko_disable, ++ .is_enabled = jz_clk_ko_is_enabled, ++}; ++ ++static struct clk jz_clk_ko = { ++ .name = "cko", ++ .parent = &jz_clk_memory.clk, ++ .ops = &jz_clk_ko_ops, ++}; ++ ++static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent) ++{ ++ if (parent == &jz_clk_pll) ++ jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); ++ else if (parent == &jz_clk_ext.clk) ++ jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); ++ else ++ return -EINVAL; ++ ++ clk->parent = parent; ++ ++ return 0; ++} ++ ++static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent) ++{ ++ if (parent == &jz_clk_pll_half) ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); ++ else if (parent == &jz_clk_ext.clk) ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); ++ else ++ return -EINVAL; ++ ++ clk->parent = parent; ++ ++ return 0; ++} ++ ++static int jz_clk_udc_enable(struct clk *clk) ++{ ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL, ++ JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); ++ ++ return 0; ++} ++ ++static int jz_clk_udc_disable(struct clk *clk) ++{ ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL, ++ JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); ++ ++ return 0; ++} ++ ++static int jz_clk_udc_is_enabled(struct clk *clk) ++{ ++ return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) & ++ JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); ++} ++static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) ++{ ++ if (parent == &jz_clk_pll_half) ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); ++ else if (parent == &jz_clk_ext.clk) ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); ++ else ++ return -EINVAL; ++ ++ clk->parent = parent; ++ ++ return 0; ++} ++ ++static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate) ++{ ++ int div; ++ ++ if (clk->parent == &jz_clk_ext.clk) ++ return -EINVAL; ++ ++ div = clk_get_rate(clk->parent) / rate - 1; ++ ++ if (div < 0) ++ div = 0; ++ else if (div > 63) ++ div = 63; ++ ++ jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET, ++ JZ_CLOCK_CTRL_UDIV_MASK); ++ return 0; ++} ++ ++static unsigned long jz_clk_udc_get_rate(struct clk *clk) ++{ ++ int div; ++ ++ if (clk->parent == &jz_clk_ext.clk) ++ return clk_get_rate(clk->parent); ++ ++ div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK); ++ div >>= JZ_CLOCK_CTRL_UDIV_OFFSET; ++ div += 1; ++ ++ return clk_get_rate(clk->parent) / div; ++} ++ ++static unsigned long jz_clk_divided_get_rate(struct clk *clk) ++{ ++ struct divided_clk *dclk = (struct divided_clk *)clk; ++ int div; ++ ++ if (clk->parent == &jz_clk_ext.clk) ++ return clk_get_rate(clk->parent); ++ ++ div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1; ++ ++ return clk_get_rate(clk->parent) / div; ++} ++ ++static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate) ++{ ++ struct divided_clk *dclk = (struct divided_clk *)clk; ++ int div; ++ ++ if (clk->parent == &jz_clk_ext.clk) ++ return -EINVAL; ++ ++ div = clk_get_rate(clk->parent) / rate - 1; ++ ++ if (div < 0) ++ div = 0; ++ else if (div > dclk->mask) ++ div = dclk->mask; ++ ++ jz_clk_reg_write_mask(dclk->reg, div, dclk->mask); ++ ++ return 0; ++} ++ ++static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate) ++{ ++ int div; ++ unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent); ++ ++ if (rate > 150000000) ++ return 150000000; ++ ++ div = parent_rate / rate; ++ if (div < 1) ++ div = 1; ++ else if (div > 32) ++ div = 32; ++ ++ return parent_rate / div; ++} ++ ++static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ int div; ++ ++ if (rate > 150000000) ++ return -EINVAL; ++ ++ div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1; ++ if (div < 0) ++ div = 0; ++ else if (div > 31) ++ div = 31; ++ ++ jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET, ++ JZ_CLOCK_CTRL_LDIV_MASK); ++ ++ return 0; ++} ++ ++static unsigned long jz_clk_ldclk_get_rate(struct clk *clk) ++{ ++ int div; ++ ++ div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK; ++ div >>= JZ_CLOCK_CTRL_LDIV_OFFSET; ++ ++ return jz_clk_pll_half_get_rate(clk->parent) / (div + 1); ++} ++ ++static const struct clk_ops jz_clk_ops_ld = { ++ .set_rate = jz_clk_ldclk_set_rate, ++ .get_rate = jz_clk_ldclk_get_rate, ++ .round_rate = jz_clk_ldclk_round_rate, ++ .enable = jz_clk_enable_gating, ++ .disable = jz_clk_disable_gating, ++ .is_enabled = jz_clk_is_enabled_gating, ++}; ++ ++static struct clk jz_clk_ld = { ++ .name = "lcd", ++ .gate_bit = JZ_CLOCK_GATE_LCD, ++ .parent = &jz_clk_pll_half, ++ .ops = &jz_clk_ops_ld, ++}; ++ ++/* TODO: ops!!! */ ++static struct clk jz_clk_cim_mclk = { ++ .name = "cim_mclk", ++ .parent = &jz_clk_high_speed_peripheral.clk, ++}; ++ ++static struct static_clk jz_clk_cim_pclk = { ++ .clk = { ++ .name = "cim_pclk", ++ .gate_bit = JZ_CLOCK_GATE_CIM, ++ .ops = &jz_clk_static_ops, ++ }, ++}; ++ ++static const struct clk_ops jz_clk_i2s_ops = { ++ .set_rate = jz_clk_divided_set_rate, ++ .get_rate = jz_clk_divided_get_rate, ++ .enable = jz_clk_enable_gating, ++ .disable = jz_clk_disable_gating, ++ .is_enabled = jz_clk_is_enabled_gating, ++ .set_parent = jz_clk_i2s_set_parent, ++}; ++ ++static const struct clk_ops jz_clk_spi_ops = { ++ .set_rate = jz_clk_divided_set_rate, ++ .get_rate = jz_clk_divided_get_rate, ++ .enable = jz_clk_enable_gating, ++ .disable = jz_clk_disable_gating, ++ .is_enabled = jz_clk_is_enabled_gating, ++ .set_parent = jz_clk_spi_set_parent, ++}; ++ ++static const struct clk_ops jz_clk_divided_ops = { ++ .set_rate = jz_clk_divided_set_rate, ++ .get_rate = jz_clk_divided_get_rate, ++ .enable = jz_clk_enable_gating, ++ .disable = jz_clk_disable_gating, ++ .is_enabled = jz_clk_is_enabled_gating, ++}; ++ ++static struct divided_clk jz4740_clock_divided_clks[] = { ++ { ++ .clk = { ++ .name = "lcd_pclk", ++ .parent = &jz_clk_pll_half, ++ .gate_bit = JZ4740_CLK_NOT_GATED, ++ .ops = &jz_clk_divided_ops, ++ }, ++ .reg = JZ_REG_CLOCK_LCD, ++ .mask = JZ_CLOCK_LCD_DIV_MASK, ++ }, ++ { ++ .clk = { ++ .name = "i2s", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_I2S, ++ .ops = &jz_clk_i2s_ops, ++ }, ++ .reg = JZ_REG_CLOCK_I2S, ++ .mask = JZ_CLOCK_I2S_DIV_MASK, ++ }, ++ { ++ .clk = { ++ .name = "spi", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_SPI, ++ .ops = &jz_clk_spi_ops, ++ }, ++ .reg = JZ_REG_CLOCK_SPI, ++ .mask = JZ_CLOCK_SPI_DIV_MASK, ++ }, ++ { ++ .clk = { ++ .name = "mmc", ++ .parent = &jz_clk_pll_half, ++ .gate_bit = JZ_CLOCK_GATE_MMC, ++ .ops = &jz_clk_divided_ops, ++ }, ++ .reg = JZ_REG_CLOCK_MMC, ++ .mask = JZ_CLOCK_MMC_DIV_MASK, ++ }, ++ { ++ .clk = { ++ .name = "uhc", ++ .parent = &jz_clk_pll_half, ++ .gate_bit = JZ_CLOCK_GATE_UHC, ++ .ops = &jz_clk_divided_ops, ++ }, ++ .reg = JZ_REG_CLOCK_UHC, ++ .mask = JZ_CLOCK_UHC_DIV_MASK, ++ }, ++}; ++ ++static const struct clk_ops jz_clk_udc_ops = { ++ .set_parent = jz_clk_udc_set_parent, ++ .set_rate = jz_clk_udc_set_rate, ++ .get_rate = jz_clk_udc_get_rate, ++ .enable = jz_clk_udc_enable, ++ .disable = jz_clk_udc_disable, ++ .is_enabled = jz_clk_udc_is_enabled, ++}; ++ ++static const struct clk_ops jz_clk_simple_ops = { ++ .enable = jz_clk_enable_gating, ++ .disable = jz_clk_disable_gating, ++ .is_enabled = jz_clk_is_enabled_gating, ++}; ++ ++static struct clk jz4740_clock_simple_clks[] = { ++ { ++ .name = "udc", ++ .parent = &jz_clk_ext.clk, ++ .ops = &jz_clk_udc_ops, ++ }, ++ { ++ .name = "uart0", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_UART0, ++ .ops = &jz_clk_simple_ops, ++ }, ++ { ++ .name = "uart1", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_UART1, ++ .ops = &jz_clk_simple_ops, ++ }, ++ { ++ .name = "dma", ++ .parent = &jz_clk_high_speed_peripheral.clk, ++ .gate_bit = JZ_CLOCK_GATE_UART0, ++ .ops = &jz_clk_simple_ops, ++ }, ++ { ++ .name = "ipu", ++ .parent = &jz_clk_high_speed_peripheral.clk, ++ .gate_bit = JZ_CLOCK_GATE_IPU, ++ .ops = &jz_clk_simple_ops, ++ }, ++ { ++ .name = "adc", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_ADC, ++ .ops = &jz_clk_simple_ops, ++ }, ++ { ++ .name = "i2c", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_I2C, ++ .ops = &jz_clk_simple_ops, ++ }, ++ { ++ .name = "aic", ++ .parent = &jz_clk_ext.clk, ++ .gate_bit = JZ_CLOCK_GATE_AIC, ++ .ops = &jz_clk_simple_ops, ++ }, ++}; ++ ++static struct static_clk jz_clk_rtc = { ++ .clk = { ++ .name = "rtc", ++ .gate_bit = JZ_CLOCK_GATE_RTC, ++ .ops = &jz_clk_static_ops, ++ }, ++ .rate = 32768, ++}; ++ ++int clk_enable(struct clk *clk) ++{ ++ if (!clk->ops->enable) ++ return -EINVAL; ++ ++ return clk->ops->enable(clk); ++} ++EXPORT_SYMBOL_GPL(clk_enable); ++ ++void clk_disable(struct clk *clk) ++{ ++ if (clk->ops->disable) ++ clk->ops->disable(clk); ++} ++EXPORT_SYMBOL_GPL(clk_disable); ++ ++int clk_is_enabled(struct clk *clk) ++{ ++ if (clk->ops->is_enabled) ++ return clk->ops->is_enabled(clk); ++ ++ return 1; ++} ++ ++unsigned long clk_get_rate(struct clk *clk) ++{ ++ if (clk->ops->get_rate) ++ return clk->ops->get_rate(clk); ++ if (clk->parent) ++ return clk_get_rate(clk->parent); ++ ++ return -EINVAL; ++} ++EXPORT_SYMBOL_GPL(clk_get_rate); ++ ++int clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ if (!clk->ops->set_rate) ++ return -EINVAL; ++ return clk->ops->set_rate(clk, rate); ++} ++EXPORT_SYMBOL_GPL(clk_set_rate); ++ ++long clk_round_rate(struct clk *clk, unsigned long rate) ++{ ++ if (clk->ops->round_rate) ++ return clk->ops->round_rate(clk, rate); ++ ++ return -EINVAL; ++} ++EXPORT_SYMBOL_GPL(clk_round_rate); ++ ++int clk_set_parent(struct clk *clk, struct clk *parent) ++{ ++ int ret; ++ ++ if (!clk->ops->set_parent) ++ return -EINVAL; ++ ++ clk_disable(clk); ++ ret = clk->ops->set_parent(clk, parent); ++ clk_enable(clk); ++ ++ jz4740_clock_debugfs_update_parent(clk); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(clk_set_parent); ++ ++struct clk *clk_get(struct device *dev, const char *name) ++{ ++ struct clk *clk; ++ ++ list_for_each_entry(clk, &jz_clocks, list) { ++ if (strcmp(clk->name, name) == 0) ++ return clk; ++ } ++ return ERR_PTR(-ENOENT); ++} ++EXPORT_SYMBOL_GPL(clk_get); ++ ++void clk_put(struct clk *clk) ++{ ++} ++EXPORT_SYMBOL_GPL(clk_put); ++ ++ ++static inline void clk_add(struct clk *clk) ++{ ++ list_add_tail(&clk->list, &jz_clocks); ++ ++ jz4740_clock_debugfs_add_clk(clk); ++} ++ ++static void clk_register_clks(void) ++{ ++ size_t i; ++ ++ clk_add(&jz_clk_ext.clk); ++ clk_add(&jz_clk_pll); ++ clk_add(&jz_clk_pll_half); ++ clk_add(&jz_clk_cpu.clk); ++ clk_add(&jz_clk_high_speed_peripheral.clk); ++ clk_add(&jz_clk_low_speed_peripheral.clk); ++ clk_add(&jz_clk_ko); ++ clk_add(&jz_clk_ld); ++ clk_add(&jz_clk_cim_mclk); ++ clk_add(&jz_clk_cim_pclk.clk); ++ clk_add(&jz_clk_rtc.clk); ++ ++ for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i) ++ clk_add(&jz4740_clock_divided_clks[i].clk); ++ ++ for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i) ++ clk_add(&jz4740_clock_simple_clks[i]); ++} ++ ++void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) ++{ ++ switch (mode) { ++ case JZ4740_WAIT_MODE_IDLE: ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); ++ break; ++ case JZ4740_WAIT_MODE_SLEEP: ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); ++ break; ++ } ++} ++ ++void jz4740_clock_udc_disable_auto_suspend(void) ++{ ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); ++} ++EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); ++ ++void jz4740_clock_udc_enable_auto_suspend(void) ++{ ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); ++} ++EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); ++ ++void jz4740_clock_suspend(void) ++{ ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, ++ JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); ++ ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); ++} ++ ++void jz4740_clock_resume(void) ++{ ++ uint32_t pll; ++ ++ jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); ++ ++ do { ++ pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL); ++ } while (!(pll & JZ_CLOCK_PLL_STABLE)); ++ ++ jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, ++ JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); ++} ++ ++int jz4740_clock_init(void) ++{ ++ uint32_t val; ++ ++ jz_clock_base = ioremap(CPHYSADDR(JZ4740_CPM_BASE_ADDR), 0x100); ++ if (!jz_clock_base) ++ return -EBUSY; ++ ++ spin_lock_init(&jz_clock_lock); ++ ++ jz_clk_ext.rate = jz4740_clock_bdata.ext_rate; ++ jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate; ++ ++ val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); ++ ++ if (val & JZ_CLOCK_SPI_SRC_PLL) ++ jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; ++ ++ val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); ++ ++ if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) ++ jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; ++ ++ if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) ++ jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half; ++ ++ jz4740_clock_debugfs_init(); ++ ++ clk_register_clks(); ++ ++ return 0; ++} +diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h +new file mode 100644 +index 0000000..96010a4 +--- /dev/null ++++ b/arch/mips/jz4740/clock.h +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 SoC clock 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. ++ * ++ */ ++ ++#ifndef __JZ4740_CLOCK_H__ ++#define __JZ4740_CLOCK_H__ ++ ++struct jz4740_clock_board_data { ++ unsigned long ext_rate; ++ unsigned long rtc_rate; ++}; ++ ++extern struct jz4740_clock_board_data jz4740_clock_bdata; ++ ++int jz4740_clock_init(void); ++void jz4740_clock_suspend(void); ++void jz4740_clock_resume(void); ++ ++struct clk; ++ ++struct clk_ops { ++ unsigned long (*get_rate)(struct clk *clk); ++ unsigned long (*round_rate)(struct clk *clk, unsigned long rate); ++ int (*set_rate)(struct clk *clk, unsigned long rate); ++ int (*enable)(struct clk *clk); ++ int (*disable)(struct clk *clk); ++ int (*is_enabled)(struct clk *clk); ++ ++ int (*set_parent)(struct clk *clk, struct clk *parent); ++ ++}; ++ ++struct clk { ++ const char *name; ++ struct clk *parent; ++ ++ uint32_t gate_bit; ++ ++ const struct clk_ops *ops; ++ ++ struct list_head list; ++ ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs_entry; ++ struct dentry *debugfs_parent_entry; ++#endif ++ ++}; ++ ++#define JZ4740_CLK_NOT_GATED ((uint32_t)-1) ++ ++int clk_is_enabled(struct clk *clk); ++ ++#ifdef CONFIG_DEBUG_FS ++void jz4740_clock_debugfs_init(void); ++void jz4740_clock_debugfs_add_clk(struct clk *clk); ++void jz4740_clock_debugfs_update_parent(struct clk *clk); ++#else ++static inline void jz4740_clock_debugfs_init(void) {}; ++static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {}; ++static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {}; ++#endif ++ ++#endif +diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c +new file mode 100644 +index 0000000..217ddc8 +--- /dev/null ++++ b/arch/mips/jz4740/dma.c +@@ -0,0 +1,339 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 SoC DMA 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 ++ ++#define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20) ++#define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20) ++#define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20) ++#define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20) ++#define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20) ++#define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20) ++#define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20) ++ ++#define JZ_REG_DMA_CTRL 0x300 ++#define JZ_REG_DMA_IRQ 0x304 ++#define JZ_REG_DMA_DOORBELL 0x308 ++#define JZ_REG_DMA_DOORBELL_SET 0x30C ++ ++#define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31) ++#define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6) ++#define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4) ++#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3) ++#define JZ_DMA_STATUS_CTRL_HALT BIT(2) ++#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1) ++#define JZ_DMA_STATUS_CTRL_ENABLE BIT(0) ++ ++#define JZ_DMA_CMD_SRC_INC BIT(23) ++#define JZ_DMA_CMD_DST_INC BIT(22) ++#define JZ_DMA_CMD_RDIL_MASK (0xf << 16) ++#define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14) ++#define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12) ++#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8) ++#define JZ_DMA_CMD_BLOCK_MODE BIT(7) ++#define JZ_DMA_CMD_DESC_VALID BIT(4) ++#define JZ_DMA_CMD_DESC_VALID_MODE BIT(3) ++#define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2) ++#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1) ++#define JZ_DMA_CMD_LINK_ENABLE BIT(0) ++ ++#define JZ_DMA_CMD_FLAGS_OFFSET 22 ++#define JZ_DMA_CMD_RDIL_OFFSET 16 ++#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14 ++#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12 ++#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8 ++#define JZ_DMA_CMD_MODE_OFFSET 7 ++ ++#define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8) ++#define JZ_DMA_CTRL_HALT BIT(3) ++#define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2) ++#define JZ_DMA_CTRL_ENABLE BIT(0) ++ ++ ++static void __iomem *jz4740_dma_base; ++static spinlock_t jz4740_dma_lock; ++ ++static inline uint32_t jz4740_dma_read(size_t reg) ++{ ++ return readl(jz4740_dma_base + reg); ++} ++ ++static inline void jz4740_dma_write(size_t reg, uint32_t val) ++{ ++ writel(val, jz4740_dma_base + reg); ++} ++ ++static inline void jz4740_dma_write_mask(size_t reg, uint32_t val, uint32_t mask) ++{ ++ uint32_t val2; ++ val2 = jz4740_dma_read(reg); ++ val2 &= ~mask; ++ val2 |= val; ++ jz4740_dma_write(reg, val2); ++} ++ ++struct jz4740_dma_chan { ++ unsigned int id; ++ void *dev; ++ const char *name; ++ ++ enum jz4740_dma_flags flags; ++ uint32_t transfer_shift; ++ ++ jz4740_dma_complete_callback_t complete_cb; ++ ++ unsigned used:1; ++}; ++ ++#define JZ4740_DMA_CHANNEL(_id) { .id = _id } ++ ++struct jz4740_dma_chan jz4740_dma_channels[] = { ++ JZ4740_DMA_CHANNEL(0), ++ JZ4740_DMA_CHANNEL(1), ++ JZ4740_DMA_CHANNEL(2), ++ JZ4740_DMA_CHANNEL(3), ++ JZ4740_DMA_CHANNEL(4), ++ JZ4740_DMA_CHANNEL(5), ++}; ++ ++struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name) ++{ ++ unsigned int i; ++ struct jz4740_dma_chan *dma = NULL; ++ ++ spin_lock(&jz4740_dma_lock); ++ ++ for (i = 0; i < ARRAY_SIZE(jz4740_dma_channels); ++i) { ++ if (!jz4740_dma_channels[i].used) { ++ dma = &jz4740_dma_channels[i]; ++ dma->used = 1; ++ break; ++ } ++ } ++ ++ spin_unlock(&jz4740_dma_lock); ++ ++ if (!dma) ++ return NULL; ++ ++ dma->dev = dev; ++ dma->name = name; ++ ++ return dma; ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_request); ++ ++void jz4740_dma_configure(struct jz4740_dma_chan *dma, ++ const struct jz4740_dma_config *config) ++{ ++ uint32_t cmd; ++ uint32_t ctrl; ++ ++ switch (config->transfer_size) { ++ case JZ4740_DMA_TRANSFER_SIZE_2BYTE: ++ dma->transfer_shift = 1; ++ break; ++ case JZ4740_DMA_TRANSFER_SIZE_4BYTE: ++ dma->transfer_shift = 2; ++ break; ++ case JZ4740_DMA_TRANSFER_SIZE_16BYTE: ++ dma->transfer_shift = 4; ++ break; ++ case JZ4740_DMA_TRANSFER_SIZE_32BYTE: ++ dma->transfer_shift = 5; ++ break; ++ default: ++ dma->transfer_shift = 0; ++ break; ++ } ++ ++ cmd = config->flags << JZ_DMA_CMD_FLAGS_OFFSET; ++ cmd |= config->src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET; ++ cmd |= config->dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET; ++ cmd |= config->transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET; ++ cmd |= config->mode << JZ_DMA_CMD_MODE_OFFSET; ++ cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE; ++ ++ ctrl = JZ_DMA_STATUS_CTRL_NO_DESC; ++ ctrl |= JZ_DMA_STATUS_CTRL_HALT; ++ ++ jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd); ++ jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), ctrl); ++ jz4740_dma_write(JZ_REG_DMA_REQ_TYPE(dma->id), config->request_type); ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_configure); ++ ++void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src) ++{ ++ jz4740_dma_write(JZ_REG_DMA_SRC_ADDR(dma->id), src); ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_set_src_addr); ++ ++void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst) ++{ ++ jz4740_dma_write(JZ_REG_DMA_DST_ADDR(dma->id), dst); ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_set_dst_addr); ++ ++void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count) ++{ ++ count >>= dma->transfer_shift; ++ jz4740_dma_write(JZ_REG_DMA_TRANSFER_COUNT(dma->id), count); ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_set_transfer_count); ++ ++void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma, ++ jz4740_dma_complete_callback_t cb) ++{ ++ dma->complete_cb = cb; ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_set_complete_cb); ++ ++void jz4740_dma_free(struct jz4740_dma_chan *dma) ++{ ++ dma->dev = NULL; ++ dma->complete_cb = NULL; ++ dma->used = 0; ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_free); ++ ++void jz4740_dma_enable(struct jz4740_dma_chan *dma) ++{ ++ jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), ++ JZ_DMA_STATUS_CTRL_ENABLE, ++ JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_HALT); ++ ++ jz4740_dma_write_mask(JZ_REG_DMA_CTRL, ++ JZ_DMA_CTRL_ENABLE, ++ JZ_DMA_CTRL_ENABLE | JZ_DMA_CTRL_HALT); ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_enable); ++ ++void jz4740_dma_disable(struct jz4740_dma_chan *dma) ++{ ++ jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0, ++ JZ_DMA_STATUS_CTRL_ENABLE); ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_disable); ++ ++uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma) ++{ ++ uint32_t residue; ++ residue = jz4740_dma_read(JZ_REG_DMA_TRANSFER_COUNT(dma->id)); ++ return residue << dma->transfer_shift; ++} ++EXPORT_SYMBOL_GPL(jz4740_dma_get_residue); ++ ++static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma) ++{ ++ uint32_t status; ++ ++ status = jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id)); ++ ++ jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0, ++ JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE); ++ ++ if (dma->complete_cb) ++ dma->complete_cb(dma, 0, dma->dev); ++} ++ ++static irqreturn_t jz4740_dma_irq(int irq, void *dev_id) ++{ ++ uint32_t irq_status; ++ unsigned int i; ++ ++ irq_status = readl(jz4740_dma_base + JZ_REG_DMA_IRQ); ++ ++ for (i = 0; i < 6; ++i) { ++ if (irq_status & (1 << i)) ++ jz4740_dma_chan_irq(&jz4740_dma_channels[i]); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++#if 0 ++static struct jz4740_dma_config dma_test_config = { ++ .src_width = JZ4740_DMA_WIDTH_32BIT, ++ .dst_width = JZ4740_DMA_WIDTH_32BIT, ++ .transfer_size = JZ4740_DMA_TRANSFER_SIZE_4BYTE, ++ .request_type = JZ4740_DMA_TYPE_AUTO_REQUEST, ++ .flags = JZ4740_DMA_SRC_AUTOINC | JZ4740_DMA_DST_AUTOINC, ++ .mode = JZ4740_DMA_MODE_BLOCK, ++}; ++ ++static void jz4740_dma_test(void) ++{ ++ uint32_t *buf1, *buf2; ++ dma_addr_t addr1, addr2; ++ struct jz4740_dma_chan *dma = jz4740_dma_request(NULL, "dma test"); ++ int i; ++ ++ printk("STARTING DMA TEST\n"); ++ ++ buf1 = dma_alloc_coherent(NULL, ++ 0x1000, ++ &addr1, GFP_KERNEL); ++ buf2 = dma_alloc_coherent(NULL, ++ 0x1000, ++ &addr2, GFP_KERNEL); ++ ++ for (i = 0; i < 0x400; ++i) ++ buf1[i] = i; ++ ++ ++ jz4740_dma_configure(dma, &dma_test_config); ++ jz4740_dma_set_src_addr(dma, addr1); ++ jz4740_dma_set_dst_addr(dma, addr2); ++ jz4740_dma_set_transfer_count(dma, 0x1000); ++ ++ jz4740_dma_enable(dma); ++ mdelay(2000); ++ ++ for (i = 0; i < 0x400; ++i) { ++ if (buf2[i] != i) ++ printk("OH MY GOD: %x %x\n", i, buf2[i]); ++ } ++ ++ printk("DMA TEST DONE\n"); ++} ++#endif ++ ++static int jz4740_dma_init(void) ++{ ++ unsigned int ret; ++ ++ jz4740_dma_base = ioremap(CPHYSADDR(JZ4740_DMAC_BASE_ADDR), 0x400); ++ ++ if (!jz4740_dma_base) ++ return -EBUSY; ++ ++ spin_lock_init(&jz4740_dma_lock); ++ ++ ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL); ++ ++ if (ret) ++ printk(KERN_ERR "JZ4740 DMA: Failed to request irq: %d\n", ret); ++ ++ return ret; ++} ++arch_initcall(jz4740_dma_init); +diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c +new file mode 100644 +index 0000000..14d8288 +--- /dev/null ++++ b/arch/mips/jz4740/gpio.c +@@ -0,0 +1,598 @@ ++/* ++ * Copyright (C) 2009-2010, Lars-Peter Clausen ++ * JZ4740 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 ++#include ++ ++#include ++ ++#define JZ4740_GPIO_BASE_A (32*0) ++#define JZ4740_GPIO_BASE_B (32*1) ++#define JZ4740_GPIO_BASE_C (32*2) ++#define JZ4740_GPIO_BASE_D (32*3) ++ ++#define JZ4740_GPIO_NUM_A 32 ++#define JZ4740_GPIO_NUM_B 32 ++#define JZ4740_GPIO_NUM_C 31 ++#define JZ4740_GPIO_NUM_D 32 ++ ++#define JZ4740_IRQ_GPIO_BASE_A (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_A) ++#define JZ4740_IRQ_GPIO_BASE_B (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_B) ++#define JZ4740_IRQ_GPIO_BASE_C (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_C) ++#define JZ4740_IRQ_GPIO_BASE_D (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_D) ++ ++#define JZ4740_IRQ_GPIO_A(num) (JZ4740_IRQ_GPIO_BASE_A + num) ++#define JZ4740_IRQ_GPIO_B(num) (JZ4740_IRQ_GPIO_BASE_B + num) ++#define JZ4740_IRQ_GPIO_C(num) (JZ4740_IRQ_GPIO_BASE_C + num) ++#define JZ4740_IRQ_GPIO_D(num) (JZ4740_IRQ_GPIO_BASE_D + num) ++ ++#define JZ_REG_GPIO_PIN 0x00 ++#define JZ_REG_GPIO_DATA 0x10 ++#define JZ_REG_GPIO_DATA_SET 0x14 ++#define JZ_REG_GPIO_DATA_CLEAR 0x18 ++#define JZ_REG_GPIO_MASK 0x20 ++#define JZ_REG_GPIO_MASK_SET 0x24 ++#define JZ_REG_GPIO_MASK_CLEAR 0x28 ++#define JZ_REG_GPIO_PULL 0x30 ++#define JZ_REG_GPIO_PULL_SET 0x34 ++#define JZ_REG_GPIO_PULL_CLEAR 0x38 ++#define JZ_REG_GPIO_FUNC 0x40 ++#define JZ_REG_GPIO_FUNC_SET 0x44 ++#define JZ_REG_GPIO_FUNC_CLEAR 0x48 ++#define JZ_REG_GPIO_SELECT 0x50 ++#define JZ_REG_GPIO_SELECT_SET 0x54 ++#define JZ_REG_GPIO_SELECT_CLEAR 0x58 ++#define JZ_REG_GPIO_DIRECTION 0x60 ++#define JZ_REG_GPIO_DIRECTION_SET 0x64 ++#define JZ_REG_GPIO_DIRECTION_CLEAR 0x68 ++#define JZ_REG_GPIO_TRIGGER 0x70 ++#define JZ_REG_GPIO_TRIGGER_SET 0x74 ++#define JZ_REG_GPIO_TRIGGER_CLEAR 0x78 ++#define JZ_REG_GPIO_FLAG 0x80 ++#define JZ_REG_GPIO_FLAG_CLEAR 0x14 ++ ++ ++#define GPIO_TO_BIT(gpio) BIT(gpio & 0x1f) ++#define GPIO_TO_REG(gpio, reg) (gpio_to_jz_gpio_chip(gpio)->base + (reg)) ++#define CHIP_TO_REG(chip, reg) (gpio_chip_to_jz_gpio_chip(chip)->base + (reg)) ++ ++struct jz_gpio_chip { ++ unsigned int irq; ++ unsigned int irq_base; ++ uint32_t wakeup; ++ uint32_t suspend_mask; ++ uint32_t edge_trigger_both; ++ ++ void __iomem *base; ++ ++ spinlock_t lock; ++ ++ struct gpio_chip gpio_chip; ++ struct irq_chip irq_chip; ++ struct sys_device sysdev; ++}; ++ ++ ++static struct jz_gpio_chip jz4740_gpio_chips[]; ++ ++static inline struct jz_gpio_chip *gpio_to_jz_gpio_chip(unsigned int gpio) ++{ ++ return &jz4740_gpio_chips[gpio >> 5]; ++} ++ ++static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *gpio_chip) ++{ ++ return container_of(gpio_chip, struct jz_gpio_chip, gpio_chip); ++} ++ ++static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(unsigned int irq) ++{ ++ return get_irq_chip_data(irq); ++} ++ ++static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) ++{ ++ writel(GPIO_TO_BIT(gpio), GPIO_TO_REG(gpio, reg)); ++} ++ ++int jz_gpio_set_function(int gpio, enum jz_gpio_function function) ++{ ++ if (function == JZ_GPIO_FUNC_NONE) { ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_CLEAR); ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); ++ } else { ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_SET); ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); ++ switch (function) { ++ case JZ_GPIO_FUNC1: ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); ++ break; ++ case JZ_GPIO_FUNC3: ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_SET); ++ case JZ_GPIO_FUNC2: /* Falltrough */ ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_SET); ++ break; ++ default: ++ BUG(); ++ break; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(jz_gpio_set_function); ++ ++int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num) ++{ ++ size_t i; ++ int ret; ++ ++ for (i = 0; i < num; ++i, ++request) { ++ ret = gpio_request(request->gpio, request->name); ++ if (ret) ++ goto err; ++ jz_gpio_set_function(request->gpio, request->function); ++ } ++ ++ return 0; ++ ++err: ++ for (--request; i > 0; --i, --request) { ++ gpio_free(request->gpio); ++ jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(jz_gpio_bulk_request); ++ ++void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num) ++{ ++ size_t i; ++ ++ for (i = 0; i < num; ++i, ++request) { ++ gpio_free(request->gpio); ++ jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); ++ } ++ ++} ++EXPORT_SYMBOL_GPL(jz_gpio_bulk_free); ++ ++void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num) ++{ ++ size_t i; ++ ++ for (i = 0; i < num; ++i, ++request) { ++ jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); ++ jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_CLEAR); ++ jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_PULL_SET); ++ } ++} ++EXPORT_SYMBOL_GPL(jz_gpio_bulk_suspend); ++ ++void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num) ++{ ++ size_t i; ++ ++ for (i = 0; i < num; ++i, ++request) ++ jz_gpio_set_function(request->gpio, request->function); ++} ++EXPORT_SYMBOL_GPL(jz_gpio_bulk_resume); ++ ++void jz_gpio_enable_pullup(unsigned gpio) ++{ ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_CLEAR); ++} ++EXPORT_SYMBOL_GPL(jz_gpio_enable_pullup); ++ ++void jz_gpio_disable_pullup(unsigned gpio) ++{ ++ jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_SET); ++} ++EXPORT_SYMBOL_GPL(jz_gpio_disable_pullup); ++ ++static int jz_gpio_get_value(struct gpio_chip *chip, unsigned gpio) ++{ ++ return !!(readl(CHIP_TO_REG(chip, JZ_REG_GPIO_PIN)) & BIT(gpio)); ++} ++ ++static void jz_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) ++{ ++ uint32_t __iomem *reg = CHIP_TO_REG(chip, JZ_REG_GPIO_DATA_SET); ++ reg += !value; ++ writel(BIT(gpio), reg); ++} ++ ++static int jz_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, ++ int value) ++{ ++ writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_SET)); ++ 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_REG(chip, JZ_REG_GPIO_DIRECTION_CLEAR)); ++ ++ return 0; ++} ++ ++int jz_gpio_port_direction_input(int port, uint32_t mask) ++{ ++ writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(jz_gpio_port_direction_input); ++ ++int jz_gpio_port_direction_output(int port, uint32_t mask) ++{ ++ writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_SET)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(jz_gpio_port_direction_output); ++ ++void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask) ++{ ++ writel(~value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_CLEAR)); ++ writel(value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_SET)); ++} ++EXPORT_SYMBOL(jz_gpio_port_set_value); ++ ++uint32_t jz_gpio_port_get_value(int port, uint32_t mask) ++{ ++ uint32_t value = readl(GPIO_TO_REG(port, JZ_REG_GPIO_PIN)); ++ ++ return value & mask; ++} ++EXPORT_SYMBOL(jz_gpio_port_get_value); ++ ++ ++#define IRQ_TO_GPIO(irq) (irq - JZ4740_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) ++ ++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; ++ struct jz_gpio_chip *chip = get_irq_desc_data(desc); ++ ++ gpio_bank = JZ4740_IRQ_GPIO0 - irq; ++ ++ flag = readl(chip->base + JZ_REG_GPIO_FLAG); ++ ++ gpio_irq = ffs(flag) - 1; ++ ++ if (chip->edge_trigger_both & BIT(gpio_irq)) { ++ uint32_t value = readl(chip->base + JZ_REG_GPIO_PIN); ++ if (value & BIT(gpio_irq)) { ++ writel(BIT(gpio_irq), ++ chip->base + JZ_REG_GPIO_DIRECTION_CLEAR); ++ } else { ++ writel(BIT(gpio_irq), ++ chip->base + JZ_REG_GPIO_DIRECTION_SET); ++ } ++ } ++ ++ gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0); ++ ++ generic_handle_irq(gpio_irq); ++}; ++ ++static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg) ++{ ++ writel(IRQ_TO_BIT(irq), IRQ_TO_REG(irq, reg)); ++} ++ ++static void jz_gpio_irq_mask(unsigned int irq) ++{ ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET); ++}; ++ ++static void jz_gpio_irq_unmask(unsigned int irq) ++{ ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR); ++}; ++ ++ ++/* TODO: Check if function is gpio */ ++static unsigned int jz_gpio_irq_startup(unsigned int irq) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET); ++ ++ desc->status &= ~IRQ_MASKED; ++ jz_gpio_irq_unmask(irq); ++ ++ return 0; ++} ++ ++static void jz_gpio_irq_shutdown(unsigned int irq) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ jz_gpio_irq_mask(irq); ++ desc->status |= IRQ_MASKED; ++ ++ /* Set direction to input */ ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR); ++} ++ ++static void jz_gpio_irq_ack(unsigned int irq) ++{ ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR); ++}; ++ ++static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) ++{ ++ struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ jz_gpio_irq_mask(irq); ++ ++ if (flow_type == IRQ_TYPE_EDGE_BOTH) { ++ uint32_t value = readl(IRQ_TO_REG(irq, JZ_REG_GPIO_PIN)); ++ if (value & IRQ_TO_BIT(irq)) ++ flow_type = IRQ_TYPE_EDGE_FALLING; ++ else ++ flow_type = IRQ_TYPE_EDGE_RISING; ++ chip->edge_trigger_both |= IRQ_TO_BIT(irq); ++ } else { ++ chip->edge_trigger_both &= ~IRQ_TO_BIT(irq); ++ } ++ ++ switch (flow_type) { ++ case IRQ_TYPE_EDGE_RISING: ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); ++ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (!(desc->status & IRQ_MASKED)) ++ jz_gpio_irq_unmask(irq); ++ ++ return 0; ++} ++ ++static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on) ++{ ++ struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); ++ spin_lock(&chip->lock); ++ if (on) ++ chip->wakeup |= IRQ_TO_BIT(irq); ++ else ++ chip->wakeup &= ~IRQ_TO_BIT(irq); ++ spin_unlock(&chip->lock); ++ ++ set_irq_wake(chip->irq, on); ++ return 0; ++} ++ ++int gpio_to_irq(unsigned gpio) ++{ ++ return JZ4740_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); ++ ++/* ++ * This lock class tells lockdep that GPIO irqs are in a different ++ * category than their parents, so it won't report false recursion. ++ */ ++static struct lock_class_key gpio_lock_class; ++ ++#define JZ4740_GPIO_CHIP(_bank) { \ ++ .irq_base = JZ4740_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 = JZ4740_GPIO_BASE_ ## _bank, \ ++ .ngpio = JZ4740_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, \ ++ .set_wake = jz_gpio_irq_set_wake, \ ++ }, \ ++} ++ ++static struct jz_gpio_chip jz4740_gpio_chips[] = { ++ JZ4740_GPIO_CHIP(A), ++ JZ4740_GPIO_CHIP(B), ++ JZ4740_GPIO_CHIP(C), ++ JZ4740_GPIO_CHIP(D), ++}; ++ ++static inline struct jz_gpio_chip *sysdev_to_chip(struct sys_device *dev) ++{ ++ return container_of(dev, struct jz_gpio_chip, sysdev); ++} ++ ++static int jz4740_gpio_suspend(struct sys_device *dev, pm_message_t state) ++{ ++ struct jz_gpio_chip *chip = sysdev_to_chip(dev); ++ ++ chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); ++ writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); ++ writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); ++ ++ return 0; ++} ++ ++static int jz4740_gpio_resume(struct sys_device *dev) ++{ ++ struct jz_gpio_chip *chip = sysdev_to_chip(dev); ++ uint32_t mask = chip->suspend_mask; ++ ++ writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); ++ writel(mask, chip->base + JZ_REG_GPIO_MASK_SET); ++ ++ return 0; ++} ++ ++static struct sysdev_class jz4740_gpio_sysdev_class = { ++ .name = "gpio", ++ .suspend = jz4740_gpio_suspend, ++ .resume = jz4740_gpio_resume, ++}; ++ ++static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) ++{ ++ int ret, irq; ++ ++ chip->sysdev.id = id; ++ chip->sysdev.cls = &jz4740_gpio_sysdev_class; ++ ret = sysdev_register(&chip->sysdev); ++ ++ if (ret) ++ return ret; ++ ++ spin_lock_init(&chip->lock); ++ ++ chip->base = ioremap(CPHYSADDR(JZ4740_GPIO_BASE_ADDR) + (id * 0x100), 0x100); ++ ++ gpiochip_add(&chip->gpio_chip); ++ ++ chip->irq = JZ4740_IRQ_INTC_GPIO(id); ++ set_irq_data(chip->irq, chip); ++ set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler); ++ ++ for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { ++ lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class); ++ set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq); ++ set_irq_chip_data(irq, chip); ++ } ++ ++ return 0; ++} ++ ++int __init jz_gpiolib_init(void) ++{ ++ unsigned int i; ++ int ret; ++ ++ ret = sysdev_class_register(&jz4740_gpio_sysdev_class); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) { ++ jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); ++ } ++ ++ printk(KERN_INFO "JZ4740 GPIO initalized\n"); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_DEBUG_FS ++ ++static inline void gpio_seq_reg(struct seq_file *s, struct jz_gpio_chip *chip, ++ const char *name, unsigned int reg) ++{ ++ seq_printf(s, "\t%s: %08x\n", name, readl(chip->base + reg)); ++} ++ ++ ++static int gpio_regs_show(struct seq_file *s, void *unused) ++{ ++ struct jz_gpio_chip *chip = jz4740_gpio_chips; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i, ++chip) { ++ seq_printf(s, "GPIO %d: \n", i); ++ gpio_seq_reg(s, chip, "Pin", JZ_REG_GPIO_PIN); ++ gpio_seq_reg(s, chip, "Data", JZ_REG_GPIO_DATA); ++ gpio_seq_reg(s, chip, "Mask", JZ_REG_GPIO_MASK); ++ gpio_seq_reg(s, chip, "Pull", JZ_REG_GPIO_PULL); ++ gpio_seq_reg(s, chip, "Func", JZ_REG_GPIO_FUNC); ++ gpio_seq_reg(s, chip, "Select", JZ_REG_GPIO_SELECT); ++ gpio_seq_reg(s, chip, "Direction", JZ_REG_GPIO_DIRECTION); ++ gpio_seq_reg(s, chip, "Trigger", JZ_REG_GPIO_TRIGGER); ++ gpio_seq_reg(s, chip, "Flag", JZ_REG_GPIO_FLAG); ++ } ++ ++ return 0; ++} ++ ++static int gpio_regs_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, gpio_regs_show, NULL); ++} ++ ++static const struct file_operations gpio_regs_operations = { ++ .open = gpio_regs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int __init gpio_debugfs_init(void) ++{ ++ (void) debugfs_create_file("jz_regs_gpio", S_IFREG | S_IRUGO, ++ NULL, NULL, &gpio_regs_operations); ++ return 0; ++} ++subsys_initcall(gpio_debugfs_init); ++ ++#endif +diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c +new file mode 100644 +index 0000000..a8c76af +--- /dev/null ++++ b/arch/mips/jz4740/irq.c +@@ -0,0 +1,174 @@ ++/* ++ * Copyright (C) 2009-2010, Lars-Peter Clausen ++ * JZ4740 platform IRQ 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 ++#include ++#include ++ ++#include ++ ++static void __iomem *jz_intc_base; ++static uint32_t jz_intc_wakeup; ++static uint32_t jz_intc_saved; ++ ++#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 ++ ++#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE) ++ ++static void intc_irq_unmask(unsigned int irq) ++{ ++ writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK); ++} ++ ++static void intc_irq_mask(unsigned int irq) ++{ ++ writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK); ++} ++ ++static void intc_irq_ack(unsigned int irq) ++{ ++ writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_PENDING); ++} ++ ++static int intc_irq_set_wake(unsigned int irq, unsigned int on) ++{ ++ if (on) ++ jz_intc_wakeup |= IRQ_BIT(irq); ++ else ++ jz_intc_wakeup &= ~IRQ_BIT(irq); ++ ++ return 0; ++} ++ ++static struct irq_chip intc_irq_type = { ++ .name = "INTC", ++ .mask = intc_irq_mask, ++ .unmask = intc_irq_unmask, ++ .ack = intc_irq_ack, ++ .set_wake = intc_irq_set_wake, ++}; ++ ++static irqreturn_t jz4740_cascade(int irq, void *data) ++{ ++ uint32_t irq_reg; ++ int intc_irq; ++ ++ irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); ++ intc_irq = ffs(irq_reg); ++ if (intc_irq) ++ generic_handle_irq(intc_irq - 1 + JZ4740_IRQ_BASE); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction jz4740_cascade_action = { ++ .handler = jz4740_cascade, ++ .name = "JZ4740 cascade interrupt", ++ .flags = IRQF_DISABLED, ++}; ++ ++void __init arch_init_irq(void) ++{ ++ int i; ++ mips_cpu_irq_init(); ++ ++ jz_intc_base = ioremap(CPHYSADDR(JZ4740_INTC_BASE_ADDR), 0x14); ++ ++ for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) { ++ intc_irq_mask(i); ++ set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq); ++ } ++ ++ setup_irq(2, &jz4740_cascade_action); ++} ++ ++asmlinkage void plat_irq_dispatch(void) ++{ ++ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; ++ if (pending & STATUSF_IP2) ++ do_IRQ(2); ++ else if (pending & STATUSF_IP3) ++ do_IRQ(3); ++ else ++ spurious_interrupt(); ++} ++ ++void jz4740_intc_suspend(void) ++{ ++ jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK); ++ writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK); ++ writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK); ++} ++ ++void jz4740_intc_resume(void) ++{ ++ writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK); ++ writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++ ++static inline void intc_seq_reg(struct seq_file *s, const char *name, ++ unsigned int reg) ++{ ++ seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg)); ++} ++ ++static int intc_regs_show(struct seq_file *s, void *unused) ++{ ++ intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS); ++ intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK); ++ intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING); ++ ++ return 0; ++} ++ ++static int intc_regs_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, intc_regs_show, NULL); ++} ++ ++static const struct file_operations intc_regs_operations = { ++ .open = intc_regs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int __init intc_debugfs_init(void) ++{ ++ (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO, ++ NULL, NULL, &intc_regs_operations); ++ return 0; ++} ++subsys_initcall(intc_debugfs_init); ++ ++#endif +diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h +new file mode 100644 +index 0000000..dadbd5f +--- /dev/null ++++ b/arch/mips/jz4740/irq.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * ++ * 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 __MIPS_JZ4740_IRQ_H__ ++#define __MIPS_JZ4740_IRQ_H__ ++ ++extern void jz4740_intc_suspend(void); ++extern void jz4740_intc_resume(void); ++ ++#endif +diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c +new file mode 100644 +index 0000000..6bb0778 +--- /dev/null ++++ b/arch/mips/jz4740/platform.c +@@ -0,0 +1,246 @@ ++/* ++ * Copyright (C) 2009-2010, Lars-Peter Clausen ++ * JZ4740 platform devices ++ * ++ * 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 ++ ++/* OHCI (USB full speed host controller) */ ++static struct resource jz4740_usb_ohci_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_UHC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_UHC_BASE_ADDR) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = JZ4740_IRQ_UHC, ++ .end = JZ4740_IRQ_UHC, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++/* The dmamask must be set for OHCI to work */ ++static u64 ohci_dmamask = ~(u32)0; ++ ++struct platform_device jz4740_usb_ohci_device = { ++ .name = "jz4740-ohci", ++ .id = -1, ++ .dev = { ++ .dma_mask = &ohci_dmamask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .num_resources = ARRAY_SIZE(jz4740_usb_ohci_resources), ++ .resource = jz4740_usb_ohci_resources, ++}; ++ ++/* UDC (USB gadget controller) */ ++static struct resource jz4740_usb_gdt_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_UDC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_UDC_BASE_ADDR) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = JZ4740_IRQ_UDC, ++ .end = JZ4740_IRQ_UDC, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 jz4740_udc_dmamask = ~(u32)0; ++ ++struct platform_device jz4740_usb_gdt_device = { ++ .name = "jz-udc", ++ .id = -1, ++ .dev = { ++ .dma_mask = &jz4740_udc_dmamask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .num_resources = ARRAY_SIZE(jz4740_usb_gdt_resources), ++ .resource = jz4740_usb_gdt_resources, ++}; ++ ++/** MMC/SD controller **/ ++static struct resource jz4740_mmc_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_MSC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_MSC_BASE_ADDR) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = JZ4740_IRQ_MSC, ++ .end = JZ4740_IRQ_MSC, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static u64 jz4740_mmc_dmamask = ~(u32)0; ++ ++struct platform_device jz4740_mmc_device = { ++ .name = "jz4740-mmc", ++ .id = 0, ++ .dev = { ++ .dma_mask = &jz4740_mmc_dmamask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .num_resources = ARRAY_SIZE(jz4740_mmc_resources), ++ .resource = jz4740_mmc_resources, ++}; ++ ++static struct resource jz4740_rtc_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_RTC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_RTC_BASE_ADDR) + 0x38 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = JZ4740_IRQ_RTC, ++ .end = JZ4740_IRQ_RTC, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++struct platform_device jz4740_rtc_device = { ++ .name = "jz4740-rtc", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(jz4740_rtc_resources), ++ .resource = jz4740_rtc_resources, ++}; ++ ++/** I2C controller **/ ++static struct resource jz4740_i2c_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_I2C_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_I2C_BASE_ADDR) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = JZ4740_IRQ_I2C, ++ .end = JZ4740_IRQ_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static u64 jz4740_i2c_dmamask = ~(u32)0; ++ ++struct platform_device jz4740_i2c_device = { ++ .name = "jz_i2c", ++ .id = 0, ++ .dev = { ++ .dma_mask = &jz4740_i2c_dmamask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .num_resources = ARRAY_SIZE(jz4740_i2c_resources), ++ .resource = jz4740_i2c_resources, ++}; ++ ++static struct resource jz4740_nand_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_EMC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_EMC_BASE_ADDR) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct platform_device jz4740_nand_device = { ++ .name = "jz4740-nand", ++ .num_resources = ARRAY_SIZE(jz4740_nand_resources), ++ .resource = jz4740_nand_resources, ++}; ++ ++static struct resource jz4740_framebuffer_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_LCD_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_LCD_BASE_ADDR) + 0x10000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static u64 jz4740_fb_dmamask = ~(u32)0; ++ ++struct platform_device jz4740_framebuffer_device = { ++ .name = "jz4740-fb", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(jz4740_framebuffer_resources), ++ .resource = jz4740_framebuffer_resources, ++ .dev = { ++ .dma_mask = &jz4740_fb_dmamask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++}; ++ ++static struct resource jz4740_i2s_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_AIC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_AIC_BASE_ADDR) + 0x38 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct platform_device jz4740_i2s_device = { ++ .name = "jz4740-i2s", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(jz4740_i2s_resources), ++ .resource = jz4740_i2s_resources, ++}; ++ ++static struct resource jz4740_codec_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_AIC_BASE_ADDR) + 0x80, ++ .end = CPHYSADDR(JZ4740_AIC_BASE_ADDR) + 0x88 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct platform_device jz4740_codec_device = { ++ .name = "jz4740-codec", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(jz4740_codec_resources), ++ .resource = jz4740_codec_resources, ++}; ++ ++static struct resource jz4740_adc_resources[] = { ++ [0] = { ++ .start = CPHYSADDR(JZ4740_SADC_BASE_ADDR), ++ .end = CPHYSADDR(JZ4740_SADC_BASE_ADDR) + 0x30, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = JZ4740_IRQ_SADC, ++ .end = JZ4740_IRQ_SADC, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++struct platform_device jz4740_adc_device = { ++ .name = "jz4740-adc", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(jz4740_adc_resources), ++ .resource = jz4740_adc_resources, ++}; ++ ++struct platform_device jz4740_battery_device = { ++ .name = "jz4740-battery", ++ .id = -1, ++ .dev = { ++ .parent = &jz4740_adc_device.dev ++ }, ++}; +diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c +new file mode 100644 +index 0000000..4ca3156 +--- /dev/null ++++ b/arch/mips/jz4740/pm.c +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 SoC power management 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 "clock.h" ++#include "irq.h" ++ ++static int jz_pm_enter(suspend_state_t state) ++{ ++ jz4740_intc_suspend(); ++ jz4740_clock_suspend(); ++ ++ jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP); ++ ++ __asm__(".set\tmips3\n\t" ++ "wait\n\t" ++ ".set\tmips0"); ++ ++ jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE); ++ ++ jz4740_clock_resume(); ++ jz4740_intc_resume(); ++ ++ return 0; ++} ++ ++static struct platform_suspend_ops jz_pm_ops = { ++ .valid = suspend_valid_only_mem, ++ .enter = jz_pm_enter, ++}; ++ ++/* ++ * Initialize power interface ++ */ ++int __init jz_pm_init(void) ++{ ++ suspend_set_ops(&jz_pm_ops); ++ return 0; ++ ++} ++late_initcall(jz_pm_init); +diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c +new file mode 100644 +index 0000000..4f99ea3 +--- /dev/null ++++ b/arch/mips/jz4740/prom.c +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 SoC prom code ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * 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 ++ ++void jz4740_init_cmdline(int argc, char *argv[]) ++{ ++ unsigned int count = COMMAND_LINE_SIZE - 1; ++ int i; ++ char *dst = &(arcs_cmdline[0]); ++ char *src; ++ ++ for (i = 1; i < argc && count; ++i) { ++ src = argv[i]; ++ while (*src && count) { ++ *dst++ = *src++; ++ --count; ++ } ++ *dst++ = ' '; ++ } ++ if (i > 1) ++ --dst; ++ ++ *dst = 0; ++} ++ ++void __init prom_init(void) ++{ ++ jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1); ++ mips_machtype = MACH_INGENIC_JZ4740; ++} ++ ++void __init prom_free_prom_memory(void) ++{ ++} ++ ++#define UART_REG(offset) ((void __iomem*)(JZ4740_UART0_BASE_ADDR + (offset << 2))) ++ ++void prom_putchar(char c) ++{ ++ uint8_t lsr; ++ ++ do { ++ lsr = readb(UART_REG(UART_LSR)); ++ } while ((lsr & UART_LSR_TEMT) == 0); ++ ++ writeb(c, UART_REG(UART_TX)); ++} +diff --git a/arch/mips/jz4740/pwm.c b/arch/mips/jz4740/pwm.c +new file mode 100644 +index 0000000..0ff8c1d +--- /dev/null ++++ b/arch/mips/jz4740/pwm.c +@@ -0,0 +1,167 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 platform PWM 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 "timer.h" ++ ++static struct clk *jz4740_pwm_clk; ++ ++DEFINE_MUTEX(jz4740_pwm_mutex); ++ ++struct pwm_device { ++ unsigned int id; ++ unsigned int gpio; ++ bool used; ++}; ++ ++static struct pwm_device jz4740_pwm_list[] = { ++ { 2, JZ_GPIO_PWM2, false }, ++ { 3, JZ_GPIO_PWM3, false }, ++ { 4, JZ_GPIO_PWM4, false }, ++ { 5, JZ_GPIO_PWM5, false }, ++ { 6, JZ_GPIO_PWM6, false }, ++ { 7, JZ_GPIO_PWM7, false }, ++}; ++ ++struct pwm_device *pwm_request(int id, const char *label) ++{ ++ int ret = 0; ++ struct pwm_device *pwm; ++ ++ if (!jz4740_pwm_clk) { ++ jz4740_pwm_clk = clk_get(NULL, "pclk"); ++ ++ if (IS_ERR(jz4740_pwm_clk)) ++ return ERR_PTR(PTR_ERR(jz4740_pwm_clk)); ++ } ++ ++ if (id < 2 || id > 7) { ++ return ERR_PTR(-ENOENT); ++ } ++ ++ mutex_lock(&jz4740_pwm_mutex); ++ ++ pwm = &jz4740_pwm_list[id - 2]; ++ if (pwm->used) ++ ret = -EBUSY; ++ else ++ pwm->used = true; ++ ++ mutex_unlock(&jz4740_pwm_mutex); ++ ++ if (ret) { ++ return ERR_PTR(ret); ++ } ++ ++ ret = gpio_request(pwm->gpio, label); ++ ++ if (ret) { ++ printk("Failed to request pwm gpio: %d\n", ret); ++ pwm->used = false; ++ return ERR_PTR(ret); ++ } ++ ++ jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_PWM); ++ ++ jz4740_timer_start(id); ++ ++ return pwm; ++} ++ ++void pwm_free(struct pwm_device *pwm) ++{ ++ pwm_disable(pwm); ++ jz4740_timer_set_ctrl(pwm->id, 0); ++ ++ jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_NONE); ++ gpio_free(pwm->gpio); ++ ++ jz4740_timer_stop(pwm->id); ++ ++ pwm->used = false; ++ ++} ++ ++int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) ++{ ++ unsigned long long tmp; ++ unsigned long period, duty; ++ unsigned int prescaler = 0; ++ unsigned int id = pwm->id; ++ uint16_t ctrl; ++ bool is_enabled; ++ ++ if (duty_ns < 0 || duty_ns > period_ns) ++ return -EINVAL; ++ ++ tmp = (unsigned long long)clk_get_rate(jz4740_pwm_clk) * period_ns; ++ ++ do_div(tmp, 1000000000); ++ ++ period = tmp; ++ ++ while (period > 0xffff && prescaler < 6) { ++ period >>= 2; ++ ++prescaler; ++ } ++ ++ if (prescaler == 6) ++ return -EINVAL; ++ ++ ++ tmp = (unsigned long long)period * duty_ns; ++ do_div(tmp, period_ns); ++ duty = tmp; ++ ++ if (duty >= period) ++ duty = period - 1; ++ ++ is_enabled = jz4740_timer_is_enabled(id); ++ jz4740_timer_disable(id); ++ ++ jz4740_timer_set_count(id, 0); ++ jz4740_timer_set_duty(id, duty); ++ jz4740_timer_set_period(id, period); ++ ++ ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_PWM_ENABLE | ++ JZ_TIMER_CTRL_SRC_PCLK; ++ ++ jz4740_timer_set_ctrl(id, ctrl); ++ ++ if (is_enabled) ++ jz4740_timer_enable(id); ++ ++ return 0; ++} ++ ++int pwm_enable(struct pwm_device *pwm) ++{ ++ jz4740_timer_enable(pwm->id); ++ ++ return 0; ++} ++ ++void pwm_disable(struct pwm_device *pwm) ++{ ++ jz4740_timer_disable(pwm->id); ++} +diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c +new file mode 100644 +index 0000000..448a7da +--- /dev/null ++++ b/arch/mips/jz4740/reset.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * ++ * 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 ++ ++static void jz4740_halt(void) ++{ ++ while (1) { ++ __asm__(".set push;\n" ++ ".set mips3;\n" ++ "wait;\n" ++ ".set pop;\n" ++ ); ++ } ++} ++ ++#define JZ_REG_WDT_DATA 0x00 ++#define JZ_REG_WDT_COUNTER_ENABLE 0x04 ++#define JZ_REG_WDT_COUNTER 0x08 ++#define JZ_REG_WDT_CTRL 0x0c ++ ++static void jz4740_restart(char *command) ++{ ++ void __iomem *wdt_base = ioremap(CPHYSADDR(JZ4740_WDT_BASE_ADDR), 0x0f); ++ ++ jz4740_timer_enable_watchdog(); ++ ++ writeb(0, wdt_base + JZ_REG_WDT_COUNTER_ENABLE); ++ ++ writew(0, wdt_base + JZ_REG_WDT_COUNTER); ++ writew(0, wdt_base + JZ_REG_WDT_DATA); ++ writew(BIT(2), wdt_base + JZ_REG_WDT_CTRL); ++ ++ writeb(1, wdt_base + JZ_REG_WDT_COUNTER_ENABLE); ++ jz4740_halt(); ++} ++ ++#define JZ_REG_RTC_CTRL 0x00 ++#define JZ_REG_RTC_HIBERNATE 0x20 ++ ++#define JZ_RTC_CTRL_WRDY BIT(7) ++ ++static void jz4740_power_off(void) ++{ ++ void __iomem *rtc_base = ioremap(CPHYSADDR(JZ4740_RTC_BASE_ADDR), 0x24); ++ uint32_t ctrl; ++ ++ do { ++ ctrl = readl(rtc_base + JZ_REG_RTC_CTRL); ++ } while (!(ctrl & JZ_RTC_CTRL_WRDY)); ++ ++ writel(1, rtc_base + JZ_REG_RTC_HIBERNATE); ++ jz4740_halt(); ++} ++ ++void jz4740_reset_init(void) ++{ ++ _machine_restart = jz4740_restart; ++ _machine_halt = jz4740_halt; ++ pm_power_off = jz4740_power_off; ++} +diff --git a/arch/mips/jz4740/reset.h b/arch/mips/jz4740/reset.h +new file mode 100644 +index 0000000..c57a829 +--- /dev/null ++++ b/arch/mips/jz4740/reset.h +@@ -0,0 +1,7 @@ ++#ifndef __MIPS_JZ4740_RESET_H__ ++#define __MIPS_JZ4740_RESET_H__ ++ ++extern void jz4740_reset_init(void); ++ ++#endif ++ +diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c +new file mode 100644 +index 0000000..a6628f4 +--- /dev/null ++++ b/arch/mips/jz4740/setup.c +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2009-2010, Lars-Peter Clausen ++ * JZ4740 setup code ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * 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 "reset.h" ++#include "clock.h" ++ ++static void __init jz4740_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 = SERIAL_IO_MEM; ++ s.regshift = 2; ++ s.uartclk = jz4740_clock_bdata.ext_rate; ++ ++ s.line = 0; ++ s.membase = (u8 *)JZ4740_UART0_BASE_ADDR; ++ s.irq = JZ4740_IRQ_UART0; ++ if (early_serial_setup(&s) != 0) { ++ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); ++ } ++ ++ s.line = 1; ++ s.membase = (u8 *)JZ4740_UART1_BASE_ADDR; ++ s.irq = JZ4740_IRQ_UART1; ++ if (early_serial_setup(&s) != 0) { ++ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); ++ } ++#endif ++} ++void __init plat_mem_setup(void) ++{ ++ jz4740_reset_init(); ++ jz4740_serial_setup(); ++} ++ ++const char *get_system_type(void) ++{ ++ return "JZ4740"; ++} +diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c +new file mode 100644 +index 0000000..7721ba7 +--- /dev/null ++++ b/arch/mips/jz4740/time.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 platform time 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 "clock.h" ++#include "timer.h" ++ ++#define TIMER_CLOCKEVENT 0 ++#define TIMER_CLOCKSOURCE 1 ++ ++static uint16_t jz4740_jiffies_per_tick; ++ ++static cycle_t jz4740_clocksource_read(struct clocksource *cs) ++{ ++ return jz4740_timer_get_count(TIMER_CLOCKSOURCE); ++} ++ ++static struct clocksource jz4740_clocksource = { ++ .name = "jz4740-timer", ++ .rating = 200, ++ .read = jz4740_clocksource_read, ++ .mask = CLOCKSOURCE_MASK(16), ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++ ++static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) ++{ ++ struct clock_event_device *cd = devid; ++ ++ jz4740_timer_ack_full(TIMER_CLOCKEVENT); ++ ++ if (cd->mode != CLOCK_EVT_MODE_PERIODIC) ++ jz4740_timer_disable(TIMER_CLOCKEVENT); ++ ++ cd->event_handler(cd); ++ ++ return IRQ_HANDLED; ++} ++ ++static void jz4740_clockevent_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *cd) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); ++ jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); ++ case CLOCK_EVT_MODE_RESUME: ++ jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); ++ jz4740_timer_enable(TIMER_CLOCKEVENT); ++ break; ++ case CLOCK_EVT_MODE_ONESHOT: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ jz4740_timer_disable(TIMER_CLOCKEVENT); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int jz4740_clockevent_set_next(unsigned long evt, ++ struct clock_event_device *cd) ++{ ++ jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); ++ jz4740_timer_set_period(TIMER_CLOCKEVENT, evt); ++ jz4740_timer_enable(TIMER_CLOCKEVENT); ++ ++ return 0; ++} ++ ++static struct clock_event_device jz4740_clockevent = { ++ .name = "jz4740-timer", ++ .features = CLOCK_EVT_FEAT_PERIODIC, ++ .set_next_event = jz4740_clockevent_set_next, ++ .set_mode = jz4740_clockevent_set_mode, ++ .rating = 200, ++ .irq = JZ4740_IRQ_TCU0, ++}; ++ ++static struct irqaction timer_irqaction = { ++ .handler = jz4740_clockevent_irq, ++ .flags = IRQF_PERCPU | IRQF_TIMER | IRQF_DISABLED, ++ .name = "jz4740-timerirq", ++ .dev_id = &jz4740_clockevent, ++}; ++ ++void __init plat_time_init(void) ++{ ++ int ret; ++ uint32_t clk_rate; ++ uint16_t ctrl; ++ ++ jz4740_timer_init(); ++ ++ clk_rate = jz4740_clock_bdata.ext_rate >> 4; ++ jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ); ++ ++ clockevent_set_clock(&jz4740_clockevent, clk_rate); ++ jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent); ++ jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent); ++ jz4740_clockevent.cpumask = cpumask_of(0); ++ ++ clockevents_register_device(&jz4740_clockevent); ++ ++ clocksource_set_clock(&jz4740_clocksource, clk_rate); ++ ret = clocksource_register(&jz4740_clocksource); ++ ++ if (ret) ++ printk(KERN_ERR "Failed to register clocksource: %d\n", ret); ++ ++ setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction); ++ ++ ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT; ++ ++ jz4740_timer_set_ctrl(TIMER_CLOCKEVENT, ctrl); ++ jz4740_timer_set_ctrl(TIMER_CLOCKSOURCE, ctrl); ++ ++ jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); ++ jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); ++ ++ jz4740_timer_irq_full_disable(TIMER_CLOCKSOURCE); ++ jz4740_timer_set_period(TIMER_CLOCKSOURCE, 0xffff); ++ ++ jz4740_timer_enable(TIMER_CLOCKEVENT); ++ jz4740_timer_enable(TIMER_CLOCKSOURCE); ++} +diff --git a/arch/mips/jz4740/timer.c b/arch/mips/jz4740/timer.c +new file mode 100644 +index 0000000..208f14c +--- /dev/null ++++ b/arch/mips/jz4740/timer.c +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 platform timer 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 "timer.h" ++ ++#include ++ ++void __iomem *jz4740_timer_base; ++ ++void jz4740_timer_enable_watchdog(void) ++{ ++ writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR); ++} ++ ++void jz4740_timer_disable_watchdog(void) ++{ ++ writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET); ++} ++ ++void __init jz4740_timer_init(void) ++{ ++ jz4740_timer_base = ioremap(CPHYSADDR(JZ4740_TCU_BASE_ADDR), 0x100); ++ ++ if (!jz4740_timer_base) ++ panic("Failed to ioremap timer registers"); ++ ++ /* Disable all timers except those used as system timers */ ++ writel(0x100fc, jz4740_timer_base + JZ_REG_TIMER_STOP_SET); ++} +diff --git a/arch/mips/jz4740/timer.h b/arch/mips/jz4740/timer.h +new file mode 100644 +index 0000000..77d748c +--- /dev/null ++++ b/arch/mips/jz4740/timer.h +@@ -0,0 +1,130 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * JZ4740 platform timer 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. ++ * ++ */ ++ ++#ifndef __MIPS_JZ4740_TIMER_H__ ++#define __MIPS_JZ4740_TIMER_H__ ++ ++#include ++#include ++ ++#define JZ_REG_TIMER_STOP 0x1C ++#define JZ_REG_TIMER_STOP_SET 0x2C ++#define JZ_REG_TIMER_STOP_CLEAR 0x3C ++#define JZ_REG_TIMER_ENABLE 0x10 ++#define JZ_REG_TIMER_ENABLE_SET 0x14 ++#define JZ_REG_TIMER_ENABLE_CLEAR 0x18 ++#define JZ_REG_TIMER_FLAG 0x20 ++#define JZ_REG_TIMER_FLAG_SET 0x24 ++#define JZ_REG_TIMER_FLAG_CLEAR 0x28 ++#define JZ_REG_TIMER_MASK 0x30 ++#define JZ_REG_TIMER_MASK_SET 0x34 ++#define JZ_REG_TIMER_MASK_CLEAR 0x38 ++ ++#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x40) ++#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x44) ++#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x48) ++#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x4C) ++ ++#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10) ++#define JZ_TIMER_IRQ_FULL(x) BIT(x) ++ ++#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW BIT(8) ++#define JZ_TIMER_CTRL_PWM_ENABLE BIT(7) ++#define JZ_TIMER_CTRL_PRESCALE_MASK 0x1c ++#define JZ_TIMER_CTRL_PRESCALE_OFFSET 0x3 ++#define JZ_TIMER_CTRL_PRESCALE_1 (0 << 3) ++#define JZ_TIMER_CTRL_PRESCALE_4 (1 << 3) ++#define JZ_TIMER_CTRL_PRESCALE_16 (2 << 3) ++#define JZ_TIMER_CTRL_PRESCALE_64 (3 << 3) ++#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3) ++#define JZ_TIMER_CTRL_PRESCALE_1024 (5 << 3) ++ ++#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET) ++ ++#define JZ_TIMER_CTRL_SRC_EXT BIT(2) ++#define JZ_TIMER_CTRL_SRC_RTC BIT(1) ++#define JZ_TIMER_CTRL_SRC_PCLK BIT(0) ++ ++extern void __iomem *jz4740_timer_base; ++void __init jz4740_timer_init(void); ++ ++static inline void jz4740_timer_stop(unsigned int timer) ++{ ++ writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET); ++} ++ ++static inline void jz4740_timer_start(unsigned int timer) ++{ ++ writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR); ++} ++ ++static inline bool jz4740_timer_is_enabled(unsigned int timer) ++{ ++ return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer); ++} ++ ++static inline void jz4740_timer_enable(unsigned int timer) ++{ ++ writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET); ++} ++ ++static inline void jz4740_timer_disable(unsigned int timer) ++{ ++ writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR); ++} ++ ++ ++static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period) ++{ ++ writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer)); ++} ++ ++static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty) ++{ ++ writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer)); ++} ++ ++static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count) ++{ ++ writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer)); ++} ++ ++static inline uint16_t jz4740_timer_get_count(unsigned int timer) ++{ ++ return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer)); ++} ++ ++static inline void jz4740_timer_ack_full(unsigned int timer) ++{ ++ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR); ++} ++ ++static inline void jz4740_timer_irq_full_enable(unsigned int timer) ++{ ++ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR); ++ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR); ++} ++ ++static inline void jz4740_timer_irq_full_disable(unsigned int timer) ++{ ++ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET); ++} ++ ++static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl) ++{ ++ writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer)); ++} ++ ++#endif +diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c +index be5bb16..926c260 100644 +--- a/arch/mips/kernel/cpu-probe.c ++++ b/arch/mips/kernel/cpu-probe.c +@@ -163,6 +163,7 @@ void __init check_wait(void) + case CPU_BCM6358: + case CPU_CAVIUM_OCTEON: + case CPU_CAVIUM_OCTEON_PLUS: ++ case CPU_JZRISC: + cpu_wait = r4k_wait; + break; + +@@ -932,6 +933,22 @@ platform: + } + } + ++static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) ++{ ++ decode_configs(c); ++ /* JZRISC does not implement the CP0 counter. */ ++ c->options &= ~MIPS_CPU_COUNTER; ++ switch (c->processor_id & 0xff00) { ++ case PRID_IMP_JZRISC: ++ c->cputype = CPU_JZRISC; ++ __cpu_name[cpu] = "Ingenic JZRISC"; ++ break; ++ default: ++ panic("Unknown Ingenic Processor ID!"); ++ break; ++ } ++} ++ + const char *__cpu_name[NR_CPUS]; + const char *__elf_platform; + +@@ -970,6 +987,9 @@ __cpuinit void cpu_probe(void) + case PRID_COMP_CAVIUM: + cpu_probe_cavium(c, cpu); + break; ++ case PRID_COMP_INGENIC: ++ cpu_probe_ingenic(c, cpu); ++ break; + } + + BUG_ON(!__cpu_name[cpu]); +diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c +index 86f004d..4510e61 100644 +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -409,6 +409,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.34/002-xburst-cache-quirks.patch b/target/linux/xburst/patches-2.6.34/002-xburst-cache-quirks.patch new file mode 100644 index 000000000..f07df44f3 --- /dev/null +++ b/target/linux/xburst/patches-2.6.34/002-xburst-cache-quirks.patch @@ -0,0 +1,339 @@ +From 3d317cc06fce61787e4429b98d6073e69a6b6cd7 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Sat, 24 Apr 2010 17:34:29 +0200 +Subject: [PATCH] JZ4740 cache quirks + +--- + arch/mips/include/asm/r4kcache.h | 231 ++++++++++++++++++++++++++++++++++++++ + 1 files changed, 231 insertions(+), 0 deletions(-) + +diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h +index 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 */ +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.34/005-add-qi_lb60-board-support.patch b/target/linux/xburst/patches-2.6.34/005-add-qi_lb60-board-support.patch new file mode 100644 index 000000000..b06debfaf --- /dev/null +++ b/target/linux/xburst/patches-2.6.34/005-add-qi_lb60-board-support.patch @@ -0,0 +1,594 @@ +From 876a111075de6fcffbaa0814ee4118ac739df1a9 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Sat, 24 Apr 2010 17:24:26 +0200 +Subject: [PATCH] Add qi_lb60 board support + +--- + arch/mips/include/asm/mach-jz4740/board-qi_lb60.h | 51 +++ + arch/mips/jz4740/Kconfig | 4 + + arch/mips/jz4740/Makefile | 2 + + arch/mips/jz4740/board-qi_lb60.c | 486 +++++++++++++++++++++ + 4 files changed, 543 insertions(+), 0 deletions(-) + create mode 100644 arch/mips/include/asm/mach-jz4740/board-qi_lb60.h + create mode 100644 arch/mips/jz4740/board-qi_lb60.c + +diff --git a/arch/mips/include/asm/mach-jz4740/board-qi_lb60.h b/arch/mips/include/asm/mach-jz4740/board-qi_lb60.h +new file mode 100644 +index 0000000..cfbf073 +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/board-qi_lb60.h +@@ -0,0 +1,51 @@ ++/* ++ * 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 as published by ++ * the Free Software Foundation, either version 3 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, see . ++ */ ++ ++#ifndef __ASM_JZ4740_QI_LB60_H__ ++#define __ASM_JZ4740_QI_LB60_H__ ++ ++#include ++ ++/* ++ * GPIO ++ */ ++#define GPIO_DC_DETE_N JZ_GPIO_PORTC(26) ++#define GPIO_CHARG_STAT_N JZ_GPIO_PORTC(27) ++#define GPIO_LED_EN JZ_GPIO_PORTC(28) ++#define GPIO_LCD_CS JZ_GPIO_PORTC(21) ++#define GPIO_DISP_OFF_N JZ_GPIO_PORTD(21) ++#define GPIO_PWM JZ_GPIO_PORTD(27) ++#define GPIO_WAKEUP_N JZ_GPIO_PORTD(29) ++ ++#define GPIO_AMP_EN JZ_GPIO_PORTD(4) ++ ++#define GPIO_SD_CD_N JZ_GPIO_PORTD(0) ++#define GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(2) ++ ++#define GPIO_USB_DETE JZ_GPIO_PORTD(28) ++#define GPIO_BUZZ_PWM JZ_GPIO_PORTD(27) ++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE ++ ++#define GPIO_AUDIO_POP JZ_GPIO_PORTB(29) ++#define GPIO_COB_TEST JZ_GPIO_PORTB(30) ++ ++#define GPIO_KEYOUT_BASE JZ_GPIO_PORTC(10) ++#define GPIO_KEYIN_BASE JZ_GPIO_PORTD(18) ++#define GPIO_KEYIN_8 JZ_GPIO_PORTD(26) ++ ++#endif /* __ASM_JZ4740_QI_LB60_H__ */ +diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig +index 5f6da09..3de3b99 100644 +--- a/arch/mips/jz4740/Kconfig ++++ b/arch/mips/jz4740/Kconfig +@@ -3,6 +3,10 @@ choice + depends on MACH_JZ + default JZ4740_QI_LB60 + ++config JZ4740_QI_LB60 ++ bool "Qi Hardware Ben NanoNote" ++ select SOC_JZ4740 ++ + endchoice + + config HAVE_PWM +diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile +index e389ddd..deca88e 100644 +--- a/arch/mips/jz4740/Makefile ++++ b/arch/mips/jz4740/Makefile +@@ -11,6 +11,8 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o + + # board specific support + ++obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o ++ + # PM support + + obj-$(CONFIG_PM) += pm.o +diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c +new file mode 100644 +index 0000000..b3cc308 +--- /dev/null ++++ b/arch/mips/jz4740/board-qi_lb60.c +@@ -0,0 +1,486 @@ ++/* ++ * 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 2 or later ++ * 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 "clock.h" ++ ++static bool is_avt2; ++ ++/* NAND */ ++static struct nand_ecclayout qi_lb60_ecclayout_1gb = { ++ .eccbytes = 36, ++ .eccpos = { ++ 6, 7, 8, 9, 10, 11, 12, 13, ++ 14, 15, 16, 17, 18, 19, 20, 21, ++ 22, 23, 24, 25, 26, 27, 28, 29, ++ 30, 31, 32, 33, 34, 35, 36, 37, ++ 38, 39, 40, 41}, ++ .oobfree = { ++ {.offset = 2, ++ .length = 4}, ++ {.offset = 42, ++ .length = 22}} ++}; ++ ++static struct mtd_partition qi_lb60_partitions_1gb[] = { ++ { .name = "NAND BOOT partition", ++ .offset = 0 * 0x100000, ++ .size = 4 * 0x100000, ++ }, ++ { .name = "NAND KERNEL partition", ++ .offset = 4 * 0x100000, ++ .size = 4 * 0x100000, ++ }, ++ { .name = "NAND ROOTFS partition", ++ .offset = 8 * 0x100000, ++ .size = (504 + 512) * 0x100000, ++ }, ++}; ++ ++static struct nand_ecclayout qi_lb60_ecclayout_2gb = { ++ .eccbytes = 72, ++ .eccpos = { ++ 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, 42, 43, ++ 44, 45, 46, 47, 48, 49, 50, 51, ++ 52, 53, 54, 55, 56, 57, 58, 59, ++ 60, 61, 62, 63, 64, 65, 66, 67, ++ 68, 69, 70, 71, 72, 73, 74, 75, ++ 76, 77, 78, 79, 80, 81, 82, 83}, ++ .oobfree = { ++ { .offset = 2, .length = 10}, ++ { .offset = 84, .length = 44}, ++ }, ++}; ++ ++static struct mtd_partition qi_lb60_partitions_2gb[] = { ++ { .name = "NAND BOOT partition", ++ .offset = 0 * 0x100000, ++ .size = 4 * 0x100000, ++ }, ++ { .name = "NAND KERNEL partition", ++ .offset = 4 * 0x100000, ++ .size = 4 * 0x100000, ++ }, ++ { .name = "NAND ROOTFS partition", ++ .offset = 8 * 0x100000, ++ .size = (504 + 512 + 1024) * 0x100000, ++ }, ++}; ++ ++static void qi_lb60_nand_ident(struct platform_device *pdev, ++ struct nand_chip *chip, struct mtd_partition **partitions, ++ int *num_partitions) ++{ ++ if (chip->page_shift == 12) { ++ chip->ecc.layout = &qi_lb60_ecclayout_2gb; ++ *partitions = qi_lb60_partitions_2gb; ++ *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb); ++ } else { ++ chip->ecc.layout = &qi_lb60_ecclayout_1gb; ++ *partitions = qi_lb60_partitions_1gb; ++ *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb); ++ } ++} ++ ++static struct jz_nand_platform_data qi_lb60_nand_pdata = { ++ .ident_callback = qi_lb60_nand_ident, ++ .busy_gpio = 94, ++}; ++ ++/* Keyboard*/ ++ ++/* #define KEEP_UART_ALIVE ++ * don't define this. the keyboard and keyboard both work ++ */ ++ ++#define KEY_QI_QI KEY_F13 ++#define KEY_QI_UPRED KEY_RIGHTALT ++#define KEY_QI_VOLUP KEY_VOLUMEUP ++#define KEY_QI_VOLDOWN KEY_VOLUMEDOWN ++#define KEY_QI_FN KEY_LEFTCTRL ++ ++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_CAPSLOCK), /* 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_RIGHTCTRL), /* 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_LEFTSHIFT), /* S58 */ ++ KEY(7, 1, KEY_LEFTALT), /* S59 */ ++ KEY(7, 2, KEY_QI_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, ++ }, ++}; ++ ++/* Display */ ++static struct fb_videomode qi_lb60_video_modes[] = { ++ { ++ .name = "320x240", ++ .xres = 320, ++ .yres = 240, ++ .refresh = 30, ++ .left_margin = 140, ++ .right_margin = 273, ++ .upper_margin = 20, ++ .lower_margin = 2, ++ .hsync_len = 1, ++ .vsync_len = 1, ++ .sync = 0, ++ .vmode = FB_VMODE_NONINTERLACED, ++ }, ++}; ++ ++static struct jz4740_fb_platform_data qi_lb60_fb_pdata = { ++ .width = 60, ++ .height = 45, ++ .num_modes = ARRAY_SIZE(qi_lb60_video_modes), ++ .modes = qi_lb60_video_modes, ++ .bpp = 24, ++ .lcd_type = JZ_LCD_TYPE_8BIT_SERIAL, ++ .pixclk_falling_edge = 1, ++}; ++ ++ ++struct spi_gpio_platform_data spigpio_platform_data = { ++ .sck = JZ_GPIO_PORTC(23), ++ .mosi = JZ_GPIO_PORTC(22), ++ .miso = -1, ++ .num_chipselect = 1, ++}; ++ ++static struct platform_device spigpio_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &spigpio_platform_data, ++ }, ++}; ++ ++static struct spi_board_info qi_lb60_spi_board_info[] = { ++ { ++ .modalias = "gpm940b0", ++ .controller_data = (void *)JZ_GPIO_PORTC(21), ++ .chip_select = 0, ++ .bus_num = 1, ++ .max_speed_hz = 30 * 1000, ++ .mode = SPI_3WIRE, ++ }, ++}; ++ ++/* Battery */ ++static struct jz_battery_platform_data qi_lb60_battery_pdata = { ++ .gpio_charge = GPIO_CHARG_STAT_N, ++ .gpio_charge_active_low = 1, ++ .info = { ++ .name = "battery", ++ .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, ++ .voltage_max_design = 4200000, ++ .voltage_min_design = 3600000, ++ }, ++}; ++ ++static char *qi_lb60_batteries[] = { ++ "battery", ++}; ++ ++static struct gpio_charger_platform_data qi_lb60_charger_pdata = { ++ .name = "USB", ++ .type = POWER_SUPPLY_TYPE_USB, ++ .gpio = GPIO_USB_DETE, ++ .gpio_active_low = 1, ++ .batteries = qi_lb60_batteries, ++ .num_batteries = ARRAY_SIZE(qi_lb60_batteries), ++}; ++ ++static struct platform_device qi_lb60_charger_device = { ++ .name = "gpio-charger", ++ .dev = { ++ .platform_data = &qi_lb60_charger_pdata, ++ }, ++}; ++ ++/* GPIO Key: power */ ++static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = { ++ [0] = { ++ .code = KEY_POWER, ++ .gpio = GPIO_WAKEUP_N, ++ .active_low = 1, ++ .desc = "Power", ++ .wakeup = 1, ++ }, ++}; ++ ++static struct gpio_keys_platform_data qi_lb60_gpio_keys_data = { ++ .nbuttons = ARRAY_SIZE(qi_lb60_gpio_keys_buttons), ++ .buttons = qi_lb60_gpio_keys_buttons, ++}; ++ ++static struct platform_device qi_lb60_gpio_keys = { ++ .name = "gpio-keys", ++ .id = -1, ++ .dev = { ++ .platform_data = &qi_lb60_gpio_keys_data, ++ } ++}; ++ ++static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = { ++ .gpio_card_detect = JZ_GPIO_PORTD(0), ++ .gpio_read_only = -1, ++ .gpio_power = JZ_GPIO_PORTD(2), ++ .power_active_low = 1, ++}; ++ ++static struct regulator_consumer_supply avt2_usb_regulator_consumer = ++ REGULATOR_SUPPLY("vbus", "jz4740-ohci"); ++ ++static struct regulator_init_data avt2_usb_regulator_init_data = { ++ .num_consumer_supplies = 1, ++ .consumer_supplies = &avt2_usb_regulator_consumer, ++ .constraints = { ++ .name = "USB power", ++ .min_uV = 5000000, ++ .max_uV = 5000000, ++ .valid_modes_mask = REGULATOR_MODE_NORMAL, ++ .valid_ops_mask = REGULATOR_CHANGE_STATUS, ++ }, ++}; ++ ++static struct fixed_voltage_config avt2_usb_regulator_data = { ++ .supply_name = "USB power", ++ .microvolts = 5000000, ++ .gpio = JZ_GPIO_PORTB(17), ++ .init_data = &avt2_usb_regulator_init_data, ++}; ++ ++static struct platform_device avt2_usb_regulator_device = { ++ .name = "reg-fixed-voltage", ++ .id = -1, ++ .dev = { ++ .platform_data = &avt2_usb_regulator_data, ++ } ++}; ++ ++static struct led_pwm qi_lb60_pizo_led = { ++ .name = "nanonote::pizo", ++ .pwm_id = 4, ++ .max_brightness = 255, ++ .pwm_period_ns = 1000000, ++}; ++ ++static struct led_pwm_platform_data qi_lb60_pizo_data = { ++ .num_leds = 1, ++ .leds = &qi_lb60_pizo_led, ++}; ++ ++static struct platform_device qi_lb60_pizo_device = { ++ .name = "leds_pwm", ++ .id = -1, ++ .dev = { ++ .platform_data = &qi_lb60_pizo_data, ++ } ++}; ++ ++static struct platform_device *jz_platform_devices[] __initdata = { ++ &jz4740_usb_gdt_device, ++ &jz4740_mmc_device, ++ &jz4740_nand_device, ++ &qi_lb60_keypad, ++ &spigpio_device, ++ &jz4740_framebuffer_device, ++ &jz4740_i2s_device, ++ &jz4740_codec_device, ++ &jz4740_rtc_device, ++ &jz4740_adc_device, ++ &jz4740_battery_device, ++ &qi_lb60_gpio_keys, ++ &qi_lb60_charger_device, ++ &qi_lb60_pizo_device, ++}; ++ ++static void __init board_gpio_setup(void) ++{ ++ /* We only need to enable/disable pullup here for pins used in generic ++ * drivers. Everything else is done by the drivers themselfs. */ ++ jz_gpio_disable_pullup(GPIO_SD_VCC_EN_N); ++ jz_gpio_disable_pullup(GPIO_SD_CD_N); ++} ++ ++static int __init qi_lb60_init_platform_devices(void) ++{ ++ jz4740_framebuffer_device.dev.platform_data = &qi_lb60_fb_pdata; ++ jz4740_nand_device.dev.platform_data = &qi_lb60_nand_pdata; ++ jz4740_battery_device.dev.platform_data = &qi_lb60_battery_pdata; ++ jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; ++ ++ spi_register_board_info(qi_lb60_spi_board_info, ++ ARRAY_SIZE(qi_lb60_spi_board_info)); ++ ++ if (is_avt2) { ++ platform_device_register(&avt2_usb_regulator_device); ++ platform_device_register(&jz4740_usb_ohci_device); ++ } ++ ++ return platform_add_devices(jz_platform_devices, ++ ARRAY_SIZE(jz_platform_devices)); ++ ++} ++ ++struct jz4740_clock_board_data jz4740_clock_bdata = { ++ .ext_rate = 12000000, ++ .rtc_rate = 32768, ++}; ++ ++extern int jz_gpiolib_init(void); ++ ++static __init int board_avt2(char *str) ++{ ++ qi_lb60_mmc_pdata.card_detect_active_low = 1; ++ qi_lb60_mmc_pdata.power_active_low = 1; ++ is_avt2 = true; ++ ++ return 1; ++} ++ ++__setup("avt2", board_avt2); ++ ++static int __init qi_lb60_board_setup(void) ++{ ++ printk(KERN_INFO "Qi Hardware JZ4740 QI_LB60 setup\n"); ++ if (jz_gpiolib_init()) ++ panic("Failed to initalize jz gpio\n"); ++ ++ jz4740_clock_init(); ++ board_gpio_setup(); ++ ++ if (qi_lb60_init_platform_devices()) ++ panic("Failed to initalize platform devices\n"); ++ ++ return 0; ++} ++ ++arch_initcall(qi_lb60_board_setup); +-- +1.5.6.5 + diff --git a/target/linux/xburst/patches-2.6.34/006-add-n516-board-support.patch b/target/linux/xburst/patches-2.6.34/006-add-n516-board-support.patch new file mode 100644 index 000000000..5f845d332 --- /dev/null +++ b/target/linux/xburst/patches-2.6.34/006-add-n516-board-support.patch @@ -0,0 +1,702 @@ +From 49f148f79887cec83c4b051c104072d770a6a9af Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Sat, 24 Apr 2010 17:25:01 +0200 +Subject: [PATCH] Add n516 board support + +--- + arch/mips/include/asm/mach-jz4740/board-n516.h | 39 +++ + arch/mips/jz4740/Kconfig | 4 + + arch/mips/jz4740/Makefile | 1 + + arch/mips/jz4740/board-n516-display.c | 393 ++++++++++++++++++++++++ + arch/mips/jz4740/board-n516.c | 206 +++++++++++++ + 5 files changed, 643 insertions(+), 0 deletions(-) + create mode 100644 arch/mips/include/asm/mach-jz4740/board-n516.h + create mode 100644 arch/mips/jz4740/board-n516-display.c + create mode 100644 arch/mips/jz4740/board-n516.c + +diff --git a/arch/mips/include/asm/mach-jz4740/board-n516.h b/arch/mips/include/asm/mach-jz4740/board-n516.h +new file mode 100644 +index 0000000..f3f1e0a +--- /dev/null ++++ b/arch/mips/include/asm/mach-jz4740/board-n516.h +@@ -0,0 +1,39 @@ ++/* ++ * linux/include/asm-mips/mach-jz4740/board-n516.h ++ * ++ * JZ4730-based N516 board definition. ++ * ++ * Copyright (C) 2009, Yauhen Kharuzhy ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef __ASM_JZ4740_N516_H__ ++#define __ASM_JZ4740_N516_H__ ++ ++#include ++ ++/* ++ * GPIO ++ */ ++#define GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(17) ++#define GPIO_SD_CD_N JZ_GPIO_PORTD(7) ++#define GPIO_SD_WP JZ_GPIO_PORTD(15) ++#define GPIO_USB_DETECT JZ_GPIO_PORTD(19) ++#define GPIO_CHARG_STAT_N JZ_GPIO_PORTD(16) ++#define GPIO_LED_ENABLE JZ_GPIO_PORTD(28) ++#define GPIO_LPC_INT JZ_GPIO_PORTD(14) ++#define GPIO_HPHONE_DETECT JZ_GPIO_PORTD(20) ++#define GPIO_SPEAKER_ENABLE JZ_GPIO_PORTD(21) ++ ++/* Display */ ++#define GPIO_DISPLAY_RST_L JZ_GPIO_PORTB(18) ++#define GPIO_DISPLAY_RDY JZ_GPIO_PORTB(17) ++#define GPIO_DISPLAY_STBY JZ_GPIO_PORTC(22) ++#define GPIO_DISPLAY_ERR JZ_GPIO_PORTC(23) ++#define GPIO_DISPLAY_OFF JZ_GPIO_PORTD(1) ++ ++#endif /* __ASM_JZ4740_N516_H__ */ +diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig +index 3de3b99..b987c27 100644 +--- a/arch/mips/jz4740/Kconfig ++++ b/arch/mips/jz4740/Kconfig +@@ -7,6 +7,10 @@ config JZ4740_QI_LB60 + bool "Qi Hardware Ben NanoNote" + select SOC_JZ4740 + ++config JZ4740_N516 ++ bool "Hanvon n516 eBook reader" ++ select SOC_JZ4740 ++ + endchoice + + config HAVE_PWM +diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile +index deca88e..9ed5e5b 100644 +--- a/arch/mips/jz4740/Makefile ++++ b/arch/mips/jz4740/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o + # board specific support + + obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o ++obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o + + # PM support + +diff --git a/arch/mips/jz4740/board-n516-display.c b/arch/mips/jz4740/board-n516-display.c +new file mode 100644 +index 0000000..44d8237 +--- /dev/null ++++ b/arch/mips/jz4740/board-n516-display.c +@@ -0,0 +1,393 @@ ++/* ++ * board-n516-display.c -- Platform device for N516 display ++ * ++ * Copyright (C) 2009, Yauhen Kharuzhy ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include