diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 6653017..1762b81 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -285,6 +285,7 @@ architectures: - sparc64 (Return probes not yet implemented.) - arm - ppc +- mips 3. Configuring Kprobes diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild new file mode 100644 index 0000000..e322d65 --- /dev/null +++ b/arch/mips/Kbuild @@ -0,0 +1,15 @@ +# Fail on warnings - also for files referenced in subdirs +# -Werror can be disabled for specific files using: +# CFLAGS_ := -Wno-error +subdir-ccflags-y := -Werror + +# platform specific definitions +include arch/mips/Kbuild.platforms +obj-y := $(platform-y) + +# mips object files +# The object files are linked as core-y files would be linked + +obj-y += kernel/ +obj-y += mm/ +obj-y += math-emu/ diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms new file mode 100644 index 0000000..78439b8 --- /dev/null +++ b/arch/mips/Kbuild.platforms @@ -0,0 +1,32 @@ +# All platforms listed in alphabetic order + +platforms += alchemy +platforms += ar7 +platforms += bcm47xx +platforms += bcm63xx +platforms += cavium-octeon +platforms += cobalt +platforms += dec +platforms += emma +platforms += jazz +platforms += jz4740 +platforms += lasat +platforms += loongson +platforms += mipssim +platforms += mti-malta +platforms += pmc-sierra +platforms += pnx833x +platforms += pnx8550 +platforms += powertv +platforms += rb532 +platforms += sgi-ip22 +platforms += sgi-ip27 +platforms += sgi-ip32 +platforms += sibyte +platforms += sni +platforms += txx9 +platforms += vr41xx +platforms += wrppmc + +# include the platform specific files +include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index cdaae94..36642df 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -10,6 +10,8 @@ config MIPS select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_KPROBES + select HAVE_KRETPROBES select RTC_LIB if !MACH_LOONGSON mainmenu "Linux/MIPS Kernel Configuration" @@ -23,8 +25,17 @@ choice prompt "System type" default SGI_IP22 -config MACH_ALCHEMY +config MIPS_ALCHEMY bool "Alchemy processor based machines" + select 64BIT_PHYS_ADDR + select CEVT_R4K_LIB + select CSRC_R4K_LIB + select IRQ_CPU + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_APM_EMULATION + select GENERIC_GPIO + select ARCH_WANT_OPTIONAL_GPIOLIB select SYS_SUPPORTS_ZBOOT config AR7 @@ -62,6 +73,7 @@ config BCM47XX select SSB_DRIVER_MIPS select SSB_DRIVER_EXTIF select SSB_EMBEDDED + select SSB_B43_PCI_BRIDGE if PCI select SSB_PCICORE_HOSTMODE if PCI select GENERIC_GPIO select SYS_HAS_EARLY_PRINTK @@ -162,6 +174,18 @@ config MACH_JAZZ Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and Olivetti M700-10 workstations. +config MACH_JZ4740 + bool "Ingenic JZ4740 based machines" + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select DMA_NONCOHERENT + select IRQ_CPU + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + select SYS_HAS_EARLY_PRINTK + select HAVE_PWM + config LASAT bool "LASAT Networks platforms" select CEVT_R4K @@ -686,6 +710,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" @@ -892,6 +917,9 @@ config CPU_LITTLE_ENDIAN endchoice +config EXPORT_UASM + bool + config SYS_SUPPORTS_APM_EMULATION bool diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 0b9c01a..f0d1960 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -130,26 +130,6 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap -# only gcc >= 4.4 have the loongson-specific support -cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON2E) += \ - $(call cc-option,-march=loongson2e,-march=r4600) -cflags-$(CONFIG_CPU_LOONGSON2F) += \ - $(call cc-option,-march=loongson2f,-march=r4600) -# enable the workarounds for loongson2f -ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS - ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-nop,),) - $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-nop) - else - cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-nop - endif - ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-jump,),) - $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-jump) - else - cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-jump - endif -endif - cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -Wa,-mips32 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ @@ -209,455 +189,7 @@ endif # # Board-dependent options and extra files # - -# -# Texas Instruments AR7 -# -core-$(CONFIG_AR7) += arch/mips/ar7/ -cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 -load-$(CONFIG_AR7) += 0xffffffff94100000 - -# -# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. -# -core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz -load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 - -# -# Common Alchemy Au1x00 stuff -# -core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/ - -# -# AMD Alchemy Pb1000 eval board -# -core-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1100 eval board -# -core-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1500 eval board -# -core-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1550 eval board -# -core-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1200 eval board -# -core-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 - -# -# AMD Alchemy Db1000 eval board -# -core-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 - -# -# AMD Alchemy Db1100 eval board -# -core-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 - -# -# AMD Alchemy Db1500 eval board -# -core-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 - -# -# AMD Alchemy Db1550 eval board -# -core-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 - -# -# AMD Alchemy Db1200 eval board -# -core-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 - -# -# AMD Alchemy Bosporus eval board -# -core-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 - -# -# AMD Alchemy Mirage eval board -# -core-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 - -# -# 4G-Systems eval board -# -libs-$(CONFIG_MIPS_MTX1) += arch/mips/alchemy/mtx-1/ -load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 - -# -# MyCable eval board -# -libs-$(CONFIG_MIPS_XXS1500) += arch/mips/alchemy/xxs1500/ -load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 - -# must be last for Alchemy systems for GPIO to work properly -cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 - - -# -# Cobalt Server -# -core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -cflags-$(CONFIG_MIPS_COBALT) += -I$(srctree)/arch/mips/include/asm/mach-cobalt -load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 - -# -# DECstation family -# -core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ -cflags-$(CONFIG_MACH_DECSTATION)+= -I$(srctree)/arch/mips/include/asm/mach-dec -libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ -load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 - -# -# Wind River PPMC Board (4KC + GT64120) -# -core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ -cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc -load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 - -# -# Loongson family -# -core-$(CONFIG_MACH_LOONGSON) += arch/mips/loongson/ -cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson \ - -mno-branch-likely -load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000 -load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000 - -# -# MIPS Malta board -# -core-$(CONFIG_MIPS_MALTA) += arch/mips/mti-malta/ -cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta -load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 -all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin - -# -# MIPS SIM -# -core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ -cflags-$(CONFIG_MIPS_SIM) += -I$(srctree)/arch/mips/include/asm/mach-mipssim -load-$(CONFIG_MIPS_SIM) += 0x80100000 - -# -# PMC-Sierra MSP SOCs -# -core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ -cflags-$(CONFIG_PMC_MSP) += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \ - -mno-branch-likely -load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 - -# -# PMC-Sierra Yosemite -# -core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/ -cflags-$(CONFIG_PMC_YOSEMITE) += -I$(srctree)/arch/mips/include/asm/mach-yosemite -load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 - -# -# LASAT platforms -# -core-$(CONFIG_LASAT) += arch/mips/lasat/ -cflags-$(CONFIG_LASAT) += -I$(srctree)/arch/mips/include/asm/mach-lasat -load-$(CONFIG_LASAT) += 0xffffffff80000000 - -# -# Common VR41xx -# -core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/ -cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx - -# -# ZAO Networks Capcella (VR4131) -# -load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 - -# -# Victor MP-C303/304 (VR4122) -# -load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 - -# -# IBM WorkPad z50 (VR4121) -# -core-$(CONFIG_IBM_WORKPAD) += arch/mips/vr41xx/ibm-workpad/ -load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 - -# -# CASIO CASSIPEIA E-55/65 (VR4111) -# -core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/ -load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 - -# -# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131) -# -load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 - -# NXP STB225 -core-$(CONFIG_SOC_PNX833X) += arch/mips/nxp/pnx833x/common/ -cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x -libs-$(CONFIG_NXP_STB220) += arch/mips/nxp/pnx833x/stb22x/ -load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 -libs-$(CONFIG_NXP_STB225) += arch/mips/nxp/pnx833x/stb22x/ -load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 - -# -# Common NXP PNX8550 -# -core-$(CONFIG_SOC_PNX8550) += arch/mips/nxp/pnx8550/common/ -cflags-$(CONFIG_SOC_PNX8550) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 - -# -# NXP PNX8550 JBS board -# -libs-$(CONFIG_PNX8550_JBS) += arch/mips/nxp/pnx8550/jbs/ -#cflags-$(CONFIG_PNX8550_JBS) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 -load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 - -# NXP PNX8550 STB810 board -# -libs-$(CONFIG_PNX8550_STB810) += arch/mips/nxp/pnx8550/stb810/ -load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 - -# -# Common NEC EMMAXXX -# -core-$(CONFIG_SOC_EMMA2RH) += arch/mips/emma/common/ -cflags-$(CONFIG_SOC_EMMA2RH) += -I$(srctree)/arch/mips/include/asm/mach-emma2rh - -# -# NEC EMMA2RH Mark-eins -# -core-$(CONFIG_NEC_MARKEINS) += arch/mips/emma/markeins/ -load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 - -# -# Cisco PowerTV Platform -# -core-$(CONFIG_POWERTV) += arch/mips/powertv/ -cflags-$(CONFIG_POWERTV) += -I$(srctree)/arch/mips/include/asm/mach-powertv -load-$(CONFIG_POWERTV) += 0xffffffff90800000 - -# -# SGI IP22 (Indy/Indigo2) -# -# Set the load address to >= 0xffffffff88069000 if you want to leave space for -# symmon, 0xffffffff80002000 for production kernels. Note that the value must -# be aligned to a multiple of the kernel stack size or the handling of the -# current variable will break so for 64-bit kernels we have to raise the start -# address by 8kb. -# -core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP22) += -I$(srctree)/arch/mips/include/asm/mach-ip22 -ifdef CONFIG_32BIT -load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 -endif -ifdef CONFIG_64BIT -load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 -endif - -# -# SGI-IP27 (Origin200/2000) -# -# Set the load address to >= 0xc000000000300000 if you want to leave space for -# symmon, 0xc00000000001c000 for production kernels. Note that the value must -# be 16kb aligned or the handling of the current variable will break. -# -ifdef CONFIG_SGI_IP27 -core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ -cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 -ifdef CONFIG_MAPPED_KERNEL -load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 -OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 -dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 -else -load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 -OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 -endif -endif - -# -# SGI IP28 (Indigo2 R10k) -# -# Set the load address to >= 0xa800000020080000 if you want to leave space for -# symmon, 0xa800000020004000 for production kernels ? Note that the value must -# be 16kb aligned or the handling of the current variable will break. -# Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys -# -ifdef CONFIG_SGI_IP28 - ifeq ($(call cc-option-yn,-mr10k-cache-barrier=store), n) - $(error gcc doesn't support needed option -mr10k-cache-barrier=store) - endif -endif -core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=store -I$(srctree)/arch/mips/include/asm/mach-ip28 -load-$(CONFIG_SGI_IP28) += 0xa800000020004000 - -# -# SGI-IP32 (O2) -# -# Set the load address to >= 80069000 if you want to leave space for symmon, -# 0xffffffff80004000 for production kernels. Note that the value must be aligned to -# a multiple of the kernel stack size or the handling of the current variable -# will break. -# -core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ -cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 -load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 - -# -# Sibyte SB1250/BCM1480 SOC -# -# This is a LIB so that it links at the end, and initcalls are later -# the sequence; but it is built as an object so that modules don't get -# removed (as happens, even if they have __initcall/module_init) -# -core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ -core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM112X) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL - -core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ -core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_SB1250) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL - -core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/ -core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x55) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL - -core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/ -core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x80) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL - -# -# Sibyte BCM91120x (Carmel) board -# Sibyte BCM91120C (CRhine) board -# Sibyte BCM91125C (CRhone) board -# Sibyte BCM91125E (Rhone) board -# Sibyte SWARM board -# Sibyte BCM91x80 (BigSur) board -# -core-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 - -# -# Broadcom BCM47XX boards -# -core-$(CONFIG_BCM47XX) += arch/mips/bcm47xx/ -cflags-$(CONFIG_BCM47XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm47xx -load-$(CONFIG_BCM47XX) := 0xffffffff80001000 - -# -# Broadcom BCM63XX boards -# -core-$(CONFIG_BCM63XX) += arch/mips/bcm63xx/ -cflags-$(CONFIG_BCM63XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm63xx/ -load-$(CONFIG_BCM63XX) := 0xffffffff80010000 - -# -# SNI RM -# -core-$(CONFIG_SNI_RM) += arch/mips/sni/ -cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm -ifdef CONFIG_CPU_LITTLE_ENDIAN -load-$(CONFIG_SNI_RM) += 0xffffffff80600000 -else -load-$(CONFIG_SNI_RM) += 0xffffffff80030000 -endif -all-$(CONFIG_SNI_RM) := $(COMPRESSION_FNAME).ecoff - -# -# Common TXx9 -# -core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX39XX) += -I$(srctree)/arch/mips/include/asm/mach-tx39xx -load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 -core-$(CONFIG_MACH_TX49XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX49XX) += -I$(srctree)/arch/mips/include/asm/mach-tx49xx -load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 - -# -# Toshiba JMR-TX3927 board -# -core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/txx9/jmr3927/ - -# -# Routerboard 532 board -# -core-$(CONFIG_MIKROTIK_RB532) += arch/mips/rb532/ -cflags-$(CONFIG_MIKROTIK_RB532) += -I$(srctree)/arch/mips/include/asm/mach-rc32434 -load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 - -# -# Toshiba RBTX49XX boards -# -core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ -core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ -core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ - -# -# Cavium Octeon -# -core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/ -cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon -core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/executive/ -ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL -load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000 -else -load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 -endif +include $(srctree)/arch/mips/Kbuild.platforms cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ @@ -706,7 +238,8 @@ head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o libs-y += arch/mips/lib/ -core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/ +# See arch/mips/Kbuild for content of core part of the kernel +core-y += arch/mips/ drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/ @@ -726,6 +259,9 @@ endif vmlinux.32: vmlinux $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ + +#obj-$(CONFIG_KPROBES) += kprobes.o + # # The 64-bit ELF tools are pretty broken so at this time we generate 64-bit # ELF files from 32-bit files by conversion. @@ -733,35 +269,19 @@ vmlinux.32: vmlinux vmlinux.64: vmlinux $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@ -makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1) -makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \ - VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1) - all: $(all-y) -vmlinuz: vmlinux FORCE - +@$(call makezboot,$@) +# boot +vmlinux.bin vmlinux.ecoff vmlinux.srec: $(vmlinux-32) FORCE + $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) arch/mips/boot/$@ -vmlinuz.bin: vmlinux - +@$(call makezboot,$@) +# boot/compressed +vmlinuz vmlinuz.bin vmlinuz.ecoff vmlinuz.srec: $(vmlinux-32) FORCE + $(Q)$(MAKE) $(build)=arch/mips/boot/compressed \ + VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $@ -vmlinuz.ecoff: vmlinux - +@$(call makezboot,$@) -vmlinuz.srec: vmlinux - +@$(call makezboot,$@) - -vmlinux.bin: $(vmlinux-32) - +@$(call makeboot,$@) - -vmlinux.ecoff: $(vmlinux-32) - +@$(call makeboot,$@) - -vmlinux.srec: $(vmlinux-32) - +@$(call makeboot,$@) - -CLEAN_FILES += vmlinux.ecoff \ - vmlinux.srec +CLEAN_FILES += vmlinux.32 vmlinux.64 archprepare: ifdef CONFIG_MIPS32_N32 @@ -780,9 +300,9 @@ install: $(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE) archclean: - @$(MAKE) $(clean)=arch/mips/boot - @$(MAKE) $(clean)=arch/mips/boot/compressed - @$(MAKE) $(clean)=arch/mips/lasat + $(Q)$(MAKE) $(clean)=arch/mips/boot + $(Q)$(MAKE) $(clean)=arch/mips/boot/compressed + $(Q)$(MAKE) $(clean)=arch/mips/lasat define archhelp echo ' install - install kernel into $(INSTALL_PATH)' @@ -796,11 +316,3 @@ define archhelp echo echo ' These will be default as apropriate for a configured platform.' endef - -CLEAN_FILES += vmlinux.32 \ - vmlinux.64 \ - vmlinux.ecoff \ - vmlinuz \ - vmlinuz.ecoff \ - vmlinuz.bin \ - vmlinuz.srec diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index df3b1a7..2ccfd4a 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -11,7 +11,7 @@ config ALCHEMY_GPIO_INDIRECT choice prompt "Machine type" - depends on MACH_ALCHEMY + depends on MIPS_ALCHEMY default MIPS_DB1000 config MIPS_MTX1 @@ -128,41 +128,33 @@ config MIPS_XXS1500 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK +config MIPS_GPR + bool "Trapeze ITS GPR board" + select SOC_AU1550 + select HW_HAS_PCI + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_HAS_EARLY_PRINTK + endchoice config SOC_AU1000 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1100 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1500 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1550 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1200 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 - -config SOC_AU1X00 - bool - select 64BIT_PHYS_ADDR - select CEVT_R4K_LIB - select CSRC_R4K_LIB - select IRQ_CPU - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_APM_EMULATION - select GENERIC_GPIO - select ARCH_WANT_OPTIONAL_GPIOLIB diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform new file mode 100644 index 0000000..96e9e41 --- /dev/null +++ b/arch/mips/alchemy/Platform @@ -0,0 +1,114 @@ +# +# Core Alchemy code +# +platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/common/ + + +# +# AMD Alchemy Pb1000 eval board +# +platform-$(CONFIG_MIPS_PB1000) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1100 eval board +# +platform-$(CONFIG_MIPS_PB1100) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1500 eval board +# +platform-$(CONFIG_MIPS_PB1500) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1550 eval board +# +platform-$(CONFIG_MIPS_PB1550) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1200 eval board +# +platform-$(CONFIG_MIPS_PB1200) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 + +# +# AMD Alchemy Db1000 eval board +# +platform-$(CONFIG_MIPS_DB1000) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 + +# +# AMD Alchemy Db1100 eval board +# +platform-$(CONFIG_MIPS_DB1100) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 + +# +# AMD Alchemy Db1500 eval board +# +platform-$(CONFIG_MIPS_DB1500) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 + +# +# AMD Alchemy Db1550 eval board +# +platform-$(CONFIG_MIPS_DB1550) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 + +# +# AMD Alchemy Db1200 eval board +# +platform-$(CONFIG_MIPS_DB1200) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 + +# +# AMD Alchemy Bosporus eval board +# +platform-$(CONFIG_MIPS_BOSPORUS) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 + +# +# AMD Alchemy Mirage eval board +# +platform-$(CONFIG_MIPS_MIRAGE) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 + +# +# 4G-Systems eval board +# +platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/ +load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 + +# +# MyCable eval board +# +platform-$(CONFIG_MIPS_XXS1500) += alchemy/xxs1500/ +load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 + +# +# Trapeze ITS GRP board +# +platform-$(CONFIG_MIPS_GPR) += alchemy/gpr/ +load-$(CONFIG_MIPS_GPR) += 0xffffffff80100000 + +# boards can specify their own in one of their include dirs. +# If they do, placing this line here at the end will make sure the +# compiler picks the board one. If they don't, it will make sure +# the alchemy generic gpio header is picked up. + +cflags-$(CONFIG_MIPS_ALCHEMY) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile index 06c0e65..27811fe 100644 --- a/arch/mips/alchemy/common/Makefile +++ b/arch/mips/alchemy/common/Makefile @@ -18,5 +18,3 @@ ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) endif obj-$(CONFIG_PCI) += pci.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c index 460c628..af0fe41 100644 --- a/arch/mips/alchemy/common/clocks.c +++ b/arch/mips/alchemy/common/clocks.c @@ -89,11 +89,7 @@ unsigned long au1xxx_calc_clock(void) * over backwards trying to determine the frequency. */ if (au1xxx_cpu_has_pll_wo()) -#ifdef CONFIG_SOC_AU1000_FREQUENCY - cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; -#else cpu_speed = 396000000; -#endif else cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index f9e5622..1dc55ee 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -21,6 +22,8 @@ #include #include +#include + #define PORT(_base, _irq) \ { \ .mapbase = _base, \ @@ -33,7 +36,6 @@ } static struct plat_serial8250_port au1x00_uart_data[] = { -#if defined(CONFIG_SERIAL_8250_AU1X00) #if defined(CONFIG_SOC_AU1000) PORT(UART0_PHYS_ADDR, AU1000_UART0_INT), PORT(UART1_PHYS_ADDR, AU1000_UART1_INT), @@ -54,7 +56,6 @@ static struct plat_serial8250_port au1x00_uart_data[] = { PORT(UART0_PHYS_ADDR, AU1200_UART0_INT), PORT(UART1_PHYS_ADDR, AU1200_UART1_INT), #endif -#endif /* CONFIG_SERIAL_8250_AU1X00 */ { }, }; @@ -436,17 +437,27 @@ static int __init au1xxx_platform_init(void) { unsigned int uartclk = get_au1x00_uart_baud_base() * 16; int err, i; + unsigned char ethaddr[6]; /* Fill up uartclk. */ for (i = 0; au1x00_uart_data[i].flags; i++) au1x00_uart_data[i].uartclk = uartclk; + /* use firmware-provided mac addr if available and necessary */ + i = prom_get_ethernet_addr(ethaddr); + if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac)) + memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); + err = platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices)); #ifndef CONFIG_SOC_AU1100 + ethaddr[5] += 1; /* next addr for 2nd MAC */ + if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac)) + memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6); + /* Register second MAC if enabled in pinfunc */ if (!err && !(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) - platform_device_register(&au1xxx_eth1_device); + err = platform_device_register(&au1xxx_eth1_device); #endif return err; diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile index ecbd37f..826449c 100644 --- a/arch/mips/alchemy/devboards/Makefile +++ b/arch/mips/alchemy/devboards/Makefile @@ -16,5 +16,3 @@ obj-$(CONFIG_MIPS_DB1500) += db1x00/ obj-$(CONFIG_MIPS_DB1550) += db1x00/ obj-$(CONFIG_MIPS_BOSPORUS) += db1x00/ obj-$(CONFIG_MIPS_MIRAGE) += db1x00/ - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c index 3cb95a9..3fa34c3 100644 --- a/arch/mips/alchemy/devboards/db1200/platform.c +++ b/arch/mips/alchemy/devboards/db1200/platform.c @@ -216,14 +216,14 @@ static struct resource db1200_ide_res[] = { } }; -static u64 ide_dmamask = DMA_32BIT_MASK; +static u64 ide_dmamask = DMA_BIT_MASK(32); static struct platform_device db1200_ide_dev = { .name = "au1200-ide", .id = 0, .dev = { .dma_mask = &ide_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), }, .num_resources = ARRAY_SIZE(db1200_ide_res), .resource = db1200_ide_res, @@ -385,12 +385,12 @@ static struct au1550_spi_info db1200_spi_platdata = { .activate_cs = db1200_spi_cs_en, }; -static u64 spi_dmamask = DMA_32BIT_MASK; +static u64 spi_dmamask = DMA_BIT_MASK(32); static struct platform_device db1200_spi_dev = { .dev = { .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &db1200_spi_platdata, }, .name = "au1550-spi", diff --git a/arch/mips/alchemy/devboards/db1x00/board_setup.c b/arch/mips/alchemy/devboards/db1x00/board_setup.c index 50c9bef..9e45971 100644 --- a/arch/mips/alchemy/devboards/db1x00/board_setup.c +++ b/arch/mips/alchemy/devboards/db1x00/board_setup.c @@ -79,7 +79,6 @@ static struct au1000_eth_platform_data eth0_pdata = { static void bosporus_power_off(void) { - printk(KERN_INFO "It's now safe to turn off power\n"); while (1) asm volatile (".set mips3 ; wait ; .set mips0"); } diff --git a/arch/mips/alchemy/devboards/pb1000/board_setup.c b/arch/mips/alchemy/devboards/pb1000/board_setup.c index 4ef50d8..f6540ec 100644 --- a/arch/mips/alchemy/devboards/pb1000/board_setup.c +++ b/arch/mips/alchemy/devboards/pb1000/board_setup.c @@ -47,9 +47,11 @@ static void board_reset(char *c) static void board_power_off(void) { - printk(KERN_ALERT "It's now safe to remove power\n"); while (1) - asm volatile (".set mips3 ; wait ; .set mips1"); + asm volatile ( + " .set mips32 \n" + " wait \n" + " .set mips0 \n"); } void __init board_setup(void) diff --git a/arch/mips/alchemy/devboards/pb1200/Makefile b/arch/mips/alchemy/devboards/pb1200/Makefile index 2ea9b02..18c1bd5 100644 --- a/arch/mips/alchemy/devboards/pb1200/Makefile +++ b/arch/mips/alchemy/devboards/pb1200/Makefile @@ -3,5 +3,3 @@ # obj-y := board_setup.o platform.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/gpr/Makefile b/arch/mips/alchemy/gpr/Makefile new file mode 100644 index 0000000..cb73fe2 --- /dev/null +++ b/arch/mips/alchemy/gpr/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2003 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for Trapeze ITS GPR board. +# + +obj-y += board_setup.o init.o platform.o diff --git a/arch/mips/alchemy/gpr/board_setup.c b/arch/mips/alchemy/gpr/board_setup.c new file mode 100644 index 0000000..ad2e3f1 --- /dev/null +++ b/arch/mips/alchemy/gpr/board_setup.c @@ -0,0 +1,93 @@ +/* + * Copyright 2010 Wolfgang Grandegger + * + * Copyright 2000-2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define UART1_ADDR KSEG1ADDR(UART1_PHYS_ADDR) +#define UART3_ADDR KSEG1ADDR(UART3_PHYS_ADDR) + +char irq_tab_alchemy[][5] __initdata = { + [0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, +}; + +static void gpr_reset(char *c) +{ + /* switch System-LED to orange (red# and green# on) */ + alchemy_gpio_direction_output(4, 0); + alchemy_gpio_direction_output(5, 0); + + /* trigger watchdog to reset board in 200ms */ + printk(KERN_EMERG "Triggering watchdog soft reset...\n"); + raw_local_irq_disable(); + alchemy_gpio_direction_output(1, 0); + udelay(1); + alchemy_gpio_set_value(1, 1); + while (1) + cpu_wait(); +} + +static void gpr_power_off(void) +{ + while (1) + cpu_wait(); +} + +void __init board_setup(void) +{ + printk(KERN_INFO "Tarpeze ITS GPR board\n"); + + pm_power_off = gpr_power_off; + _machine_halt = gpr_power_off; + _machine_restart = gpr_reset; + + /* Enable UART3 */ + au_writel(0x1, UART3_ADDR + UART_MOD_CNTRL);/* clock enable (CE) */ + au_writel(0x3, UART3_ADDR + UART_MOD_CNTRL); /* CE and "enable" */ + /* Enable UART1 */ + au_writel(0x1, UART1_ADDR + UART_MOD_CNTRL); /* clock enable (CE) */ + au_writel(0x3, UART1_ADDR + UART_MOD_CNTRL); /* CE and "enable" */ + + /* Take away Reset of UMTS-card */ + alchemy_gpio_direction_output(215, 1); + +#ifdef CONFIG_PCI +#if defined(__MIPSEB__) + au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif +#endif +} diff --git a/arch/mips/alchemy/gpr/init.c b/arch/mips/alchemy/gpr/init.c new file mode 100644 index 0000000..f044f4c --- /dev/null +++ b/arch/mips/alchemy/gpr/init.c @@ -0,0 +1,63 @@ +/* + * Copyright 2010 Wolfgang Grandegger + * + * Copyright 2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +#include + +const char *get_system_type(void) +{ + return "GPR"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtoul(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +void prom_putchar(unsigned char c) +{ + alchemy_uart_putchar(UART0_PHYS_ADDR, c); +} diff --git a/arch/mips/alchemy/gpr/platform.c b/arch/mips/alchemy/gpr/platform.c new file mode 100644 index 0000000..14b4662 --- /dev/null +++ b/arch/mips/alchemy/gpr/platform.c @@ -0,0 +1,183 @@ +/* + * GPR board platform device registration + * + * Copyright (C) 2010 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Watchdog + */ +static struct resource gpr_wdt_resource[] = { + [0] = { + .start = 1, + .end = 1, + .name = "gpr-adm6320-wdt", + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device gpr_wdt_device = { + .name = "adm6320-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(gpr_wdt_resource), + .resource = gpr_wdt_resource, +}; + +/* + * FLASH + * + * 0x00000000-0x00200000 : "kernel" + * 0x00200000-0x00a00000 : "rootfs" + * 0x01d00000-0x01f00000 : "config" + * 0x01c00000-0x01d00000 : "yamon" + * 0x01d00000-0x01d40000 : "yamon env vars" + * 0x00000000-0x00a00000 : "kernel+rootfs" + */ +static struct mtd_partition gpr_mtd_partitions[] = { + { + .name = "kernel", + .size = 0x00200000, + .offset = 0, + }, + { + .name = "rootfs", + .size = 0x00800000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "config", + .size = 0x00200000, + .offset = 0x01d00000, + }, + { + .name = "yamon", + .size = 0x00100000, + .offset = 0x01c00000, + }, + { + .name = "yamon env vars", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + }, + { + .name = "kernel+rootfs", + .size = 0x00a00000, + .offset = 0, + }, +}; + +static struct physmap_flash_data gpr_flash_data = { + .width = 4, + .nr_parts = ARRAY_SIZE(gpr_mtd_partitions), + .parts = gpr_mtd_partitions, +}; + +static struct resource gpr_mtd_resource = { + .start = 0x1e000000, + .end = 0x1fffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device gpr_mtd_device = { + .name = "physmap-flash", + .dev = { + .platform_data = &gpr_flash_data, + }, + .num_resources = 1, + .resource = &gpr_mtd_resource, +}; + +/* + * LEDs + */ +static struct gpio_led gpr_gpio_leds[] = { + { /* green */ + .name = "gpr:green", + .gpio = 4, + .active_low = 1, + }, + { /* red */ + .name = "gpr:red", + .gpio = 5, + .active_low = 1, + } +}; + +static struct gpio_led_platform_data gpr_led_data = { + .num_leds = ARRAY_SIZE(gpr_gpio_leds), + .leds = gpr_gpio_leds, +}; + +static struct platform_device gpr_led_devices = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpr_led_data, + } +}; + +/* + * I2C + */ +static struct i2c_gpio_platform_data gpr_i2c_data = { + .sda_pin = 209, + .sda_is_open_drain = 1, + .scl_pin = 210, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ + .timeout = HZ, + }; + +static struct platform_device gpr_i2c_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &gpr_i2c_data, +}; + +static struct i2c_board_info gpr_i2c_info[] __initdata = { + { + I2C_BOARD_INFO("lm83", 0x18), + .type = "lm83" + } +}; + +static struct platform_device *gpr_devices[] __initdata = { + &gpr_wdt_device, + &gpr_mtd_device, + &gpr_i2c_device, + &gpr_led_devices, +}; + +static int __init gpr_dev_init(void) +{ + i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info)); + + return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices)); +} +device_initcall(gpr_dev_init); diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile index 4a53815..81b540c 100644 --- a/arch/mips/alchemy/mtx-1/Makefile +++ b/arch/mips/alchemy/mtx-1/Makefile @@ -6,7 +6,4 @@ # Makefile for 4G Systems MTX-1 board. # -lib-y := init.o board_setup.o -obj-y := platform.o - -EXTRA_CFLAGS += -Werror +obj-y += init.o board_setup.o platform.o diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index 52d883d..6398fa9 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -60,9 +60,11 @@ static void mtx1_reset(char *c) static void mtx1_power_off(void) { - printk(KERN_ALERT "It's now safe to remove power\n"); while (1) - asm volatile (".set mips3 ; wait ; .set mips1"); + asm volatile ( + " .set mips32 \n" + " wait \n" + " .set mips0 \n"); } void __init board_setup(void) @@ -105,14 +107,10 @@ void __init board_setup(void) int mtx1_pci_idsel(unsigned int devsel, int assert) { -#define MTX_IDSEL_ONLY_0_AND_3 0 -#if MTX_IDSEL_ONLY_0_AND_3 - if (devsel != 0 && devsel != 3) { - printk(KERN_ERR "*** not 0 or 3\n"); - return 0; - } -#endif - + /* This function is only necessary to support a proprietary Cardbus + * adapter on the mtx-1 "singleboard" variant. It triggers a custom + * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals. + */ if (assert && devsel != 0) /* Suppress signal to Cardbus */ alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */ diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile index 4dc81d7..91defcf 100644 --- a/arch/mips/alchemy/xxs1500/Makefile +++ b/arch/mips/alchemy/xxs1500/Makefile @@ -5,6 +5,4 @@ # Makefile for MyCable XXS1500 board. # -lib-y := init.o board_setup.o platform.o - -EXTRA_CFLAGS += -Werror +obj-y += init.o board_setup.o platform.o diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c index 47b4292..b43c918 100644 --- a/arch/mips/alchemy/xxs1500/board_setup.c +++ b/arch/mips/alchemy/xxs1500/board_setup.c @@ -42,9 +42,11 @@ static void xxs1500_reset(char *c) static void xxs1500_power_off(void) { - printk(KERN_ALERT "It's now safe to remove power\n"); while (1) - asm volatile (".set mips3 ; wait ; .set mips1"); + asm volatile ( + " .set mips32 \n" + " wait \n" + " .set mips0 \n"); } void __init board_setup(void) diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile index 26bc5da..7435e44 100644 --- a/arch/mips/ar7/Makefile +++ b/arch/mips/ar7/Makefile @@ -8,4 +8,3 @@ obj-y := \ platform.o \ gpio.o \ clock.o -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/ar7/Platform b/arch/mips/ar7/Platform new file mode 100644 index 0000000..0bf85c4 --- /dev/null +++ b/arch/mips/ar7/Platform @@ -0,0 +1,6 @@ +# +# Texas Instruments AR7 +# +platform-$(CONFIG_AR7) += ar7/ +cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 +load-$(CONFIG_AR7) += 0xffffffff94100000 diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 8f31d1d..0da5b2b 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -292,40 +292,28 @@ static struct platform_device cpmac_high = { .num_resources = ARRAY_SIZE(cpmac_high_res), }; -static inline unsigned char char2hex(char h) +static void __init cpmac_get_mac(int instance, unsigned char *dev_addr) { - switch (h) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return h - '0'; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - return h - 'A' + 10; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - return h - 'a' + 10; - default: - return 0; - } -} - -static void cpmac_get_mac(int instance, unsigned char *dev_addr) -{ - int i; - char name[5], default_mac[ETH_ALEN], *mac; + char name[5], *mac; - mac = NULL; sprintf(name, "mac%c", 'a' + instance); mac = prom_getenv(name); - if (!mac) { + if (!mac && instance) { sprintf(name, "mac%c", 'a'); mac = prom_getenv(name); } - if (!mac) { - random_ether_addr(default_mac); - mac = default_mac; - } - for (i = 0; i < 6; i++) - dev_addr[i] = (char2hex(mac[i * 3]) << 4) + - char2hex(mac[i * 3 + 1]); + + if (mac) { + if (sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &dev_addr[0], &dev_addr[1], + &dev_addr[2], &dev_addr[3], + &dev_addr[4], &dev_addr[5]) != 6) { + pr_warning("cannot parse mac address, " + "using random address\n"); + random_ether_addr(dev_addr); + } + } else + random_ether_addr(dev_addr); } /***************************************************************************** diff --git a/arch/mips/bcm47xx/Platform b/arch/mips/bcm47xx/Platform new file mode 100644 index 0000000..874b7ca --- /dev/null +++ b/arch/mips/bcm47xx/Platform @@ -0,0 +1,7 @@ +# +# Broadcom BCM47XX boards +# +platform-$(CONFIG_BCM47XX) += bcm47xx/ +cflags-$(CONFIG_BCM47XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-bcm47xx +load-$(CONFIG_BCM47XX) := 0xffffffff80001000 diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index 06e03b2..e5b6615 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -69,7 +69,7 @@ int nvram_getenv(char *name, char *val, size_t val_len) char *var, *value, *end, *eq; if (!name) - return 1; + return NVRAM_ERR_INV_PARAM; if (!nvram_buf[0]) early_nvram_init(); @@ -89,6 +89,6 @@ int nvram_getenv(char *name, char *val, size_t val_len) return 0; } } - return 1; + return NVRAM_ERR_ENVNOTFOUND; } EXPORT_SYMBOL(nvram_getenv); diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 0fa646c..f6e9063 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -126,6 +126,7 @@ static __init void prom_init_cmdline(void) static __init void prom_init_mem(void) { unsigned long mem; + unsigned long max; /* Figure out memory size by finding aliases. * @@ -134,21 +135,26 @@ static __init void prom_init_mem(void) * want to reuse the memory used by CFE (around 4MB). That means cfe_* * functions stop to work at some point during the boot, we should only * call them at the beginning of the boot. + * + * BCM47XX uses 128MB for addressing the ram, if the system contains + * less that that amount of ram it remaps the ram more often into the + * available space. + * Accessing memory after 128MB will cause an exception. + * max contains the biggest possible address supported by the platform. + * If the method wants to try something above we assume 128MB ram. */ + max = ((unsigned long)(prom_init) | ((128 << 20) - 1)); for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { + if (((unsigned long)(prom_init) + mem) > max) { + mem = (128 << 20); + printk(KERN_DEBUG "assume 128MB RAM\n"); + break; + } if (*(unsigned long *)((unsigned long)(prom_init) + mem) == *(unsigned long *)(prom_init)) break; } - /* Ignoring the last page when ddr size is 128M. Cached - * accesses to last page is causing the processor to prefetch - * using address above 128M stepping out of the ddr address - * space. - */ - if (mem == 0x8000000) - mem -= 0x1000; - add_memory_region(0, mem, BOOT_MEM_RAM); } diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile index 00064b6..6dfdc69 100644 --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile @@ -3,5 +3,3 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/bcm63xx/Platform b/arch/mips/bcm63xx/Platform new file mode 100644 index 0000000..5f86b2f --- /dev/null +++ b/arch/mips/bcm63xx/Platform @@ -0,0 +1,7 @@ +# +# Broadcom BCM63XX boards +# +platform-$(CONFIG_BCM63XX) += bcm63xx/ +cflags-$(CONFIG_BCM63XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-bcm63xx/ +load-$(CONFIG_BCM63XX) := 0xffffffff80010000 diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore index 4667a5f..f210b09 100644 --- a/arch/mips/boot/.gitignore +++ b/arch/mips/boot/.gitignore @@ -3,3 +3,4 @@ elf2ecoff vmlinux.* zImage zImage.tmp +calc_vmlinuz_load_addr diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index e39a08e..85bcb5a 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -11,35 +11,32 @@ # Some DECstations need all possible sections of an ECOFF executable # ifdef CONFIG_MACH_DECSTATION - E2EFLAGS = -a -else - E2EFLAGS = + e2eflag := -a endif # # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # -drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options -strip-flags = $(addprefix --remove-section=,$(drop-sections)) - -VMLINUX = vmlinux - -all: vmlinux.ecoff vmlinux.srec - -vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) - $(obj)/elf2ecoff $(VMLINUX) $(obj)/vmlinux.ecoff $(E2EFLAGS) - -$(obj)/elf2ecoff: $(obj)/elf2ecoff.c - $(HOSTCC) -o $@ $^ - -vmlinux.bin: $(VMLINUX) - $(OBJCOPY) -O binary $(strip-flags) $(VMLINUX) $(obj)/vmlinux.bin - -vmlinux.srec: $(VMLINUX) - $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec - -clean-files += elf2ecoff \ - vmlinux.bin \ - vmlinux.ecoff \ - vmlinux.srec +drop-sections := .reginfo .mdebug .comment .note .pdr .options .MIPS.options +strip-flags := $(addprefix --remove-section=,$(drop-sections)) + +hostprogs-y := elf2ecoff + +targets := vmlinux.ecoff +quiet_cmd_ecoff = ECOFF $@ + cmd_ecoff = $(obj)/elf2ecoff $(VMLINUX) $@ $(e2eflag) +$(obj)/vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) FORCE + $(call if_changed,ecoff) + +targets += vmlinux.bin +quiet_cmd_bin = OBJCOPY $@ + cmd_bin = $(OBJCOPY) -O binary $(strip-flags) $(VMLINUX) $@ +$(obj)/vmlinux.bin: $(VMLINUX) FORCE + $(call if_changed,bin) + +targets += vmlinux.srec +quiet_cmd_srec = OBJCOPY $@ + cmd_srec = $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $@ +$(obj)/vmlinux.srec: $(VMLINUX) FORCE + $(call if_changed,srec) diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 790ddd3..ed9bb70 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -12,14 +12,6 @@ # Author: Wu Zhangjin # -# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE -VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1) -VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536)))) -# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE" -HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10))) -LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8) -VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32)))) - # set the default size of the mallocing area for decompressing BOOT_HEAP_SIZE := 0x400000 @@ -33,49 +25,61 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \ -DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | grep " kernel_entry" | cut -f1 -d \ ) -obj-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o +targets := head.o decompress.o dbg.o uart-16550.o uart-alchemy.o + +# decompressor objects (linked with vmlinuz) +vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o ifdef CONFIG_DEBUG_ZBOOT -obj-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o -obj-$(CONFIG_MACH_ALCHEMY) += $(obj)/uart-alchemy.o +vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o +vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o endif +targets += vmlinux.bin OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S -$(obj)/vmlinux.bin: $(KBUILD_IMAGE) +$(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE $(call if_changed,objcopy) -suffix_$(CONFIG_KERNEL_GZIP) = gz -suffix_$(CONFIG_KERNEL_BZIP2) = bz2 -suffix_$(CONFIG_KERNEL_LZMA) = lzma -suffix_$(CONFIG_KERNEL_LZO) = lzo tool_$(CONFIG_KERNEL_GZIP) = gzip tool_$(CONFIG_KERNEL_BZIP2) = bzip2 tool_$(CONFIG_KERNEL_LZMA) = lzma tool_$(CONFIG_KERNEL_LZO) = lzo -$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin + +targets += vmlinux.bin.z +$(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE $(call if_changed,$(tool_y)) -$(obj)/piggy.o: $(obj)/vmlinux.$(suffix_y) $(obj)/dummy.o - $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) \ - --add-section=.image=$< \ - --set-section-flags=.image=contents,alloc,load,readonly,data \ - $(obj)/dummy.o $@ +targets += piggy.o +OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.bin.z \ + --set-section-flags=.image=contents,alloc,load,readonly,data +$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE + $(call if_changed,objcopy) + +# Calculate the load address of the compressed kernel image +hostprogs-y := calc_vmlinuz_load_addr + +VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \ + $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T -vmlinuz: $(src)/ld.script $(obj-y) $(obj)/piggy.o - $(call if_changed,ld) - $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@ +vmlinuzobjs-y += $(obj)/piggy.o + +quiet_cmd_zld = LD $@ + cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@ +quiet_cmd_strip = STRIP $@ + cmd_strip = $(STRIP) -s $@ +vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr + $(call cmd,zld) + $(call cmd,strip) # # Some DECstations need all possible sections of an ECOFF executable # ifdef CONFIG_MACH_DECSTATION - E2EFLAGS = -a -else - E2EFLAGS = + e2eflag := -a endif # elf2ecoff can only handle 32bit image +hostprogs-y += ../elf2ecoff ifdef CONFIG_32BIT VMLINUZ = vmlinuz @@ -83,23 +87,22 @@ else VMLINUZ = vmlinuz.32 endif +quiet_cmd_32 = OBJCOPY $@ + cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ vmlinuz.32: vmlinuz - $(Q)$(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ + $(call cmd,32) +quiet_cmd_ecoff = ECOFF $@ + cmd_ecoff = $< $(VMLINUZ) $@ $(e2eflag) vmlinuz.ecoff: $(obj)/../elf2ecoff $(VMLINUZ) - $(Q)$(obj)/../elf2ecoff $(VMLINUZ) vmlinuz.ecoff $(E2EFLAGS) - -$(obj)/../elf2ecoff: $(src)/../elf2ecoff.c - $(Q)$(HOSTCC) -o $@ $^ + $(call cmd,ecoff) OBJCOPYFLAGS_vmlinuz.bin := $(OBJCOPYFLAGS) -O binary vmlinuz.bin: vmlinuz - $(call if_changed,objcopy) + $(call cmd,objcopy) OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec vmlinuz.srec: vmlinuz - $(call if_changed,objcopy) + $(call cmd,objcopy) -clean: -clean-files += *.o \ - vmlinu* +clean-files := $(objtree)/vmlinuz.* diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c new file mode 100644 index 0000000..88c9d96 --- /dev/null +++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 "Wu Zhangjin" + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct stat sb; + uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr; + + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", + argv[0]); + return EXIT_FAILURE; + } + + if (stat(argv[1], &sb) == -1) { + perror("stat"); + return EXIT_FAILURE; + } + + /* Convert hex characters to dec number */ + errno = 0; + if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) { + if (errno != 0) + perror("sscanf"); + else + fprintf(stderr, "No matching characters\n"); + + return EXIT_FAILURE; + } + + vmlinux_size = (uint64_t)sb.st_size; + vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size; + + /* + * Align with 16 bytes: "greater than that used for any standard data + * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition). + */ + + vmlinuz_load_addr += (16 - vmlinux_size % 16); + + printf("0x%llx\n", vmlinuz_load_addr); + + return EXIT_SUCCESS; +} diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index 5db43c5..5cad0fa 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -1,9 +1,6 @@ /* - * Misc. bootloader code for many machines. - * * Copyright 2001 MontaVista Software Inc. - * Author: Matt Porter Derived from - * arch/ppc/boot/prep/misc.c + * Author: Matt Porter * * Copyright (C) 2009 Lemote, Inc. * Author: Wu Zhangjin @@ -19,12 +16,12 @@ #include -/* These two variables specify the free mem region +/* + * These two variables specify the free mem region * that can be used for temporary malloc area */ unsigned long free_mem_ptr; unsigned long free_mem_end_ptr; -char *zimage_start; /* The linker tells us where the image is. */ extern unsigned char __image_begin, __image_end; @@ -83,38 +80,31 @@ void *memset(void *s, int c, size_t n) void decompress_kernel(unsigned long boot_heap_start) { - int zimage_size; - - /* - * We link ourself to an arbitrary low address. When we run, we - * relocate outself to that address. __image_beign points to - * the part of the image where the zImage is. -- Tom - */ - zimage_start = (char *)(unsigned long)(&__image_begin); + unsigned long zimage_start, zimage_size; + + zimage_start = (unsigned long)(&__image_begin); zimage_size = (unsigned long)(&__image_end) - (unsigned long)(&__image_begin); - /* - * The zImage and initrd will be between start and _end, so they've - * already been moved once. We're good to go now. -- Tom - */ puts("zimage at: "); - puthex((unsigned long)zimage_start); + puthex(zimage_start); puts(" "); - puthex((unsigned long)(zimage_size + zimage_start)); + puthex(zimage_size + zimage_start); puts("\n"); - /* this area are prepared for mallocing when decompressing */ + /* This area are prepared for mallocing when decompressing */ free_mem_ptr = boot_heap_start; free_mem_end_ptr = boot_heap_start + BOOT_HEAP_SIZE; - /* Display standard Linux/MIPS boot prompt for kernel args */ + /* Display standard Linux/MIPS boot prompt */ puts("Uncompressing Linux at load address "); puthex(VMLINUX_LOAD_ADDRESS_ULL); puts("\n"); + /* Decompress the kernel with according algorithm */ - decompress(zimage_start, zimage_size, 0, 0, + decompress((char *)zimage_start, zimage_size, 0, 0, (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error); - /* FIXME: is there a need to flush cache here? */ + + /* FIXME: should we flush cache here? */ puts("Now, booting the kernel...\n"); } diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script index 613a35b..8e6b07c 100644 --- a/arch/mips/boot/compressed/ld.script +++ b/arch/mips/boot/compressed/ld.script @@ -2,61 +2,44 @@ * ld.script for compressed kernel support of MIPS * * Copyright (C) 2009 Lemote Inc. - * Author: Wu Zhangjin + * Author: Wu Zhangjin + * Copyright (C) 2010 "Wu Zhangjin" */ OUTPUT_ARCH(mips) ENTRY(start) SECTIONS { - /* . = VMLINUZ_LOAD_ADDRESS */ - /* read-only */ - _text = .; /* Text and read-only data */ - .text : { - _ftext = . ; + /* Text and read-only data */ + /* . = VMLINUZ_LOAD_ADDRESS; */ + .text : { *(.text) *(.rodata) - } = 0 - _etext = .; /* End of text section */ + } + /* End of text section */ - /* writable */ - .data : { /* Data */ - _fdata = . ; + /* Writable data */ + .data : { *(.data) - /* Put the compressed image here, so bss is on the end. */ + /* Put the compressed image here */ __image_begin = .; *(.image) __image_end = .; CONSTRUCTORS } - .sdata : { *(.sdata) } - . = ALIGN(4); - _edata = .; /* End of data section */ + . = ALIGN(16); + _edata = .; + /* End of data section */ /* BSS */ - __bss_start = .; - _fbss = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : { - *(.dynbss) + .bss : { *(.bss) - *(COMMON) } - . = ALIGN(4); - _end = . ; - - /* These are needed for ELF backends which have not yet been converted - * to the new style linker. */ - - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + . = ALIGN(16); + _end = .; /* Sections to be discarded */ - /DISCARD/ : { + /DISCARD/ : { *(.MIPS.options) *(.options) *(.pdr) diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 3e98763..19eb043 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -12,7 +12,6 @@ obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y += dma-octeon.o flash_setup.o obj-y += octeon-memcpy.o +obj-y += executive/ obj-$(CONFIG_SMP) += smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/cavium-octeon/Platform b/arch/mips/cavium-octeon/Platform new file mode 100644 index 0000000..1e43ccf --- /dev/null +++ b/arch/mips/cavium-octeon/Platform @@ -0,0 +1,11 @@ +# +# Cavium Octeon +# +platform-$(CONFIG_CPU_CAVIUM_OCTEON) += cavium-octeon/ +cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += \ + -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon +ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL +load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000 +else +load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 +endif diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c index b6df538..c664c8c 100644 --- a/arch/mips/cavium-octeon/cpu.c +++ b/arch/mips/cavium-octeon/cpu.c @@ -41,12 +41,8 @@ static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, return NOTIFY_OK; /* Let default notifier send signals */ } -static struct notifier_block cnmips_cu2_notifier = { - .notifier_call = cnmips_cu2_call, -}; - static int cnmips_cu2_setup(void) { - return register_cu2_notifier(&cnmips_cu2_notifier); + return cu2_notifier(cnmips_cu2_call, 0); } early_initcall(cnmips_cu2_setup); diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c index 0bf4bbe..b6847c8 100644 --- a/arch/mips/cavium-octeon/csrc-octeon.c +++ b/arch/mips/cavium-octeon/csrc-octeon.c @@ -53,7 +53,6 @@ static struct clocksource clocksource_mips = { unsigned long long notrace sched_clock(void) { /* 64-bit arithmatic can overflow, so use 128-bit. */ -#if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 3)) u64 t1, t2, t3; unsigned long long rv; u64 mult = clocksource_mips.mult; @@ -73,13 +72,6 @@ unsigned long long notrace sched_clock(void) : [cnt] "r" (cnt), [mult] "r" (mult), [shift] "r" (shift) : "hi", "lo"); return rv; -#else - /* GCC > 4.3 do it the easy way. */ - unsigned int __attribute__((mode(TI))) t; - t = read_c0_cvmcount(); - t = t * clocksource_mips.mult; - return (unsigned long long)(t >> clocksource_mips.shift); -#endif } void __init plat_time_init(void) @@ -88,3 +80,58 @@ void __init plat_time_init(void) clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); clocksource_register(&clocksource_mips); } + +static u64 octeon_udelay_factor; +static u64 octeon_ndelay_factor; + +void __init octeon_setup_delays(void) +{ + octeon_udelay_factor = octeon_get_clock_rate() / 1000000; + /* + * For __ndelay we divide by 2^16, so the factor is multiplied + * by the same amount. + */ + octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull; + + preset_lpj = octeon_get_clock_rate() / HZ; +} + +void __udelay(unsigned long us) +{ + u64 cur, end, inc; + + cur = read_c0_cvmcount(); + + inc = us * octeon_udelay_factor; + end = cur + inc; + + while (end > cur) + cur = read_c0_cvmcount(); +} +EXPORT_SYMBOL(__udelay); + +void __ndelay(unsigned long ns) +{ + u64 cur, end, inc; + + cur = read_c0_cvmcount(); + + inc = ((ns * octeon_ndelay_factor) >> 16); + end = cur + inc; + + while (end > cur) + cur = read_c0_cvmcount(); +} +EXPORT_SYMBOL(__ndelay); + +void __delay(unsigned long loops) +{ + u64 cur, end; + + cur = read_c0_cvmcount(); + end = cur + loops; + + while (end > cur) + cur = read_c0_cvmcount(); +} +EXPORT_SYMBOL(__delay); diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index be531ec..d22b5a2 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -99,13 +99,16 @@ dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) panic("dma_map_single: " "Attempt to map illegal memory address 0x%llx\n", physical); - else if ((physical + size >= - (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20)) - && physical < (4ull<<30)) - pr_warning("dma_map_single: Warning: " - "Mapping memory address that might " - "conflict with devices 0x%llx-0x%llx\n", - physical, physical+size-1); + else if (physical >= CVMX_PCIE_BAR1_PHYS_BASE && + physical + size < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE)) { + result = physical - CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_RC_BASE; + + if (((result+size-1) & dma_mask) != result+size-1) + panic("dma_map_single: Attempt to map address 0x%llx-0x%llx, which can't be accessed according to the dma mask 0x%llx\n", + physical, physical+size-1, dma_mask); + goto done; + } + /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ if ((physical >= 0x410000000ull) && physical < 0x420000000ull) result = physical - 0x400000000ull; diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index c424cd1..ce7500c 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -3,15 +3,13 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2008 Cavium Networks + * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks */ #include #include #include #include -#include -#include static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock); static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock); @@ -41,14 +39,14 @@ static void octeon_irq_core_ack(unsigned int irq) static void octeon_irq_core_eoi(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); unsigned int bit = irq - OCTEON_IRQ_SW0; /* * If an IRQ is being processed while we are disabling it the * handler will attempt to unmask the interrupt after it has * been disabled. */ - if (desc->status & IRQ_DISABLED) + if ((unlikely(desc->status & IRQ_DISABLED))) return; /* * We don't need to disable IRQs to make these atomic since @@ -106,6 +104,29 @@ static struct irq_chip octeon_irq_chip_core = { static void octeon_irq_ciu0_ack(unsigned int irq) { + switch (irq) { + case OCTEON_IRQ_GMX_DRP0: + case OCTEON_IRQ_GMX_DRP1: + case OCTEON_IRQ_IPD_DRP: + case OCTEON_IRQ_KEY_ZERO: + case OCTEON_IRQ_TIMER0: + case OCTEON_IRQ_TIMER1: + case OCTEON_IRQ_TIMER2: + case OCTEON_IRQ_TIMER3: + { + int index = cvmx_get_core_num() * 2; + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + /* + * CIU timer type interrupts must be acknoleged by + * writing a '1' bit to their sum0 bit. + */ + cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); + break; + } + default: + break; + } + /* * In order to avoid any locking accessing the CIU, we * acknowledge CIU interrupts by disabling all of them. This @@ -130,8 +151,54 @@ static void octeon_irq_ciu0_eoi(unsigned int irq) set_c0_status(0x100 << 2); } +static int next_coreid_for_irq(struct irq_desc *desc) +{ + +#ifdef CONFIG_SMP + int coreid; + int weight = cpumask_weight(desc->affinity); + + if (weight > 1) { + int cpu = smp_processor_id(); + for (;;) { + cpu = cpumask_next(cpu, desc->affinity); + if (cpu >= nr_cpu_ids) { + cpu = -1; + continue; + } else if (cpumask_test_cpu(cpu, cpu_online_mask)) { + break; + } + } + coreid = octeon_coreid_for_cpu(cpu); + } else if (weight == 1) { + coreid = octeon_coreid_for_cpu(cpumask_first(desc->affinity)); + } else { + coreid = cvmx_get_core_num(); + } + return coreid; +#else + return cvmx_get_core_num(); +#endif +} + static void octeon_irq_ciu0_enable(unsigned int irq) { + struct irq_desc *desc = irq_to_desc(irq); + int coreid = next_coreid_for_irq(desc); + unsigned long flags; + uint64_t en0; + int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ + + raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); + en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); + en0 |= 1ull << bit; + cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); + cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); + raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); +} + +static void octeon_irq_ciu0_enable_mbox(unsigned int irq) +{ int coreid = cvmx_get_core_num(); unsigned long flags; uint64_t en0; @@ -167,63 +234,76 @@ static void octeon_irq_ciu0_disable(unsigned int irq) } /* - * Enable the irq on the current core for chips that have the EN*_W1{S,C} - * registers. + * Enable the irq on the next core in the affinity set for chips that + * have the EN*_W1{S,C} registers. */ static void octeon_irq_ciu0_enable_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2; + int index; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + struct irq_desc *desc = irq_to_desc(irq); - cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); + if ((desc->status & IRQ_DISABLED) == 0) { + index = next_coreid_for_irq(desc) * 2; + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); + } } /* - * Disable the irq on the current core for chips that have the EN*_W1{S,C} - * registers. + * Enable the irq on the current CPU for chips that + * have the EN*_W1{S,C} registers. */ -static void octeon_irq_ciu0_ack_v2(unsigned int irq) +static void octeon_irq_ciu0_enable_mbox_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2; + int index; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); - cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); + index = cvmx_get_core_num() * 2; + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); } /* - * CIU timer type interrupts must be acknoleged by writing a '1' bit - * to their sum0 bit. + * Disable the irq on the current core for chips that have the EN*_W1{S,C} + * registers. */ -static void octeon_irq_ciu0_timer_ack(unsigned int irq) +static void octeon_irq_ciu0_ack_v2(unsigned int irq) { int index = cvmx_get_core_num() * 2; - uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); - cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); -} + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); -static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq) -{ - octeon_irq_ciu0_timer_ack(irq); - octeon_irq_ciu0_ack(irq); -} + switch (irq) { + case OCTEON_IRQ_GMX_DRP0: + case OCTEON_IRQ_GMX_DRP1: + case OCTEON_IRQ_IPD_DRP: + case OCTEON_IRQ_KEY_ZERO: + case OCTEON_IRQ_TIMER0: + case OCTEON_IRQ_TIMER1: + case OCTEON_IRQ_TIMER2: + case OCTEON_IRQ_TIMER3: + /* + * CIU timer type interrupts must be acknoleged by + * writing a '1' bit to their sum0 bit. + */ + cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); + break; + default: + break; + } -static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq) -{ - octeon_irq_ciu0_timer_ack(irq); - octeon_irq_ciu0_ack_v2(irq); + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); } /* * Enable the irq on the current core for chips that have the EN*_W1{S,C} * registers. */ -static void octeon_irq_ciu0_eoi_v2(unsigned int irq) +static void octeon_irq_ciu0_eoi_mbox_v2(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); int index = cvmx_get_core_num() * 2; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); - if ((desc->status & IRQ_DISABLED) == 0) + if (likely((desc->status & IRQ_DISABLED) == 0)) cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); } @@ -246,18 +326,30 @@ static void octeon_irq_ciu0_disable_all_v2(unsigned int irq) static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest) { int cpu; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; unsigned long flags; int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ + /* + * For non-v2 CIU, we will allow only single CPU affinity. + * This removes the need to do locking in the .ack/.eoi + * functions. + */ + if (cpumask_weight(dest) != 1) + return -EINVAL; + raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); for_each_online_cpu(cpu) { int coreid = octeon_coreid_for_cpu(cpu); uint64_t en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); - if (cpumask_test_cpu(cpu, dest)) + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; en0 |= 1ull << bit; - else + } else { en0 &= ~(1ull << bit); + } cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); } /* @@ -279,13 +371,18 @@ static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq, { int cpu; int index; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + for_each_online_cpu(cpu) { index = octeon_coreid_for_cpu(cpu) * 2; - if (cpumask_test_cpu(cpu, dest)) + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); - else + } else { cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); + } } return 0; } @@ -298,8 +395,7 @@ static struct irq_chip octeon_irq_chip_ciu0_v2 = { .name = "CIU0", .enable = octeon_irq_ciu0_enable_v2, .disable = octeon_irq_ciu0_disable_all_v2, - .ack = octeon_irq_ciu0_ack_v2, - .eoi = octeon_irq_ciu0_eoi_v2, + .eoi = octeon_irq_ciu0_enable_v2, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu0_set_affinity_v2, #endif @@ -309,36 +405,27 @@ static struct irq_chip octeon_irq_chip_ciu0 = { .name = "CIU0", .enable = octeon_irq_ciu0_enable, .disable = octeon_irq_ciu0_disable, - .ack = octeon_irq_ciu0_ack, .eoi = octeon_irq_ciu0_eoi, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu0_set_affinity, #endif }; -static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = { - .name = "CIU0-T", - .enable = octeon_irq_ciu0_enable_v2, - .disable = octeon_irq_ciu0_disable_all_v2, - .ack = octeon_irq_ciu0_timer_ack_v2, - .eoi = octeon_irq_ciu0_eoi_v2, -#ifdef CONFIG_SMP - .set_affinity = octeon_irq_ciu0_set_affinity_v2, -#endif +/* The mbox versions don't do any affinity or round-robin. */ +static struct irq_chip octeon_irq_chip_ciu0_mbox_v2 = { + .name = "CIU0-M", + .enable = octeon_irq_ciu0_enable_mbox_v2, + .disable = octeon_irq_ciu0_disable, + .eoi = octeon_irq_ciu0_eoi_mbox_v2, }; -static struct irq_chip octeon_irq_chip_ciu0_timer = { - .name = "CIU0-T", - .enable = octeon_irq_ciu0_enable, +static struct irq_chip octeon_irq_chip_ciu0_mbox = { + .name = "CIU0-M", + .enable = octeon_irq_ciu0_enable_mbox, .disable = octeon_irq_ciu0_disable, - .ack = octeon_irq_ciu0_timer_ack_v1, .eoi = octeon_irq_ciu0_eoi, -#ifdef CONFIG_SMP - .set_affinity = octeon_irq_ciu0_set_affinity, -#endif }; - static void octeon_irq_ciu1_ack(unsigned int irq) { /* @@ -365,10 +452,30 @@ static void octeon_irq_ciu1_eoi(unsigned int irq) static void octeon_irq_ciu1_enable(unsigned int irq) { - int coreid = cvmx_get_core_num(); + struct irq_desc *desc = irq_to_desc(irq); + int coreid = next_coreid_for_irq(desc); + unsigned long flags; + uint64_t en1; + int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ + + raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); + en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); + en1 |= 1ull << bit; + cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); + cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); + raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); +} + +/* + * Watchdog interrupts are special. They are associated with a single + * core, so we hardwire the affinity to that core. + */ +static void octeon_irq_ciu1_wd_enable(unsigned int irq) +{ unsigned long flags; uint64_t en1; int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ + int coreid = bit; raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); @@ -405,36 +512,43 @@ static void octeon_irq_ciu1_disable(unsigned int irq) */ static void octeon_irq_ciu1_enable_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2 + 1; + int index; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + struct irq_desc *desc = irq_to_desc(irq); - cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + if ((desc->status & IRQ_DISABLED) == 0) { + index = next_coreid_for_irq(desc) * 2 + 1; + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + } } /* - * Disable the irq on the current core for chips that have the EN*_W1{S,C} - * registers. + * Watchdog interrupts are special. They are associated with a single + * core, so we hardwire the affinity to that core. */ -static void octeon_irq_ciu1_ack_v2(unsigned int irq) +static void octeon_irq_ciu1_wd_enable_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2 + 1; + int index; + int coreid = irq - OCTEON_IRQ_WDOG0; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + struct irq_desc *desc = irq_to_desc(irq); - cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); + if ((desc->status & IRQ_DISABLED) == 0) { + index = coreid * 2 + 1; + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + } } /* - * Enable the irq on the current core for chips that have the EN*_W1{S,C} + * Disable the irq on the current core for chips that have the EN*_W1{S,C} * registers. */ -static void octeon_irq_ciu1_eoi_v2(unsigned int irq) +static void octeon_irq_ciu1_ack_v2(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; int index = cvmx_get_core_num() * 2 + 1; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); - if ((desc->status & IRQ_DISABLED) == 0) - cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); } /* @@ -457,19 +571,30 @@ static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest) { int cpu; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; unsigned long flags; int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ + /* + * For non-v2 CIU, we will allow only single CPU affinity. + * This removes the need to do locking in the .ack/.eoi + * functions. + */ + if (cpumask_weight(dest) != 1) + return -EINVAL; + raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); for_each_online_cpu(cpu) { int coreid = octeon_coreid_for_cpu(cpu); uint64_t en1 = - cvmx_read_csr(CVMX_CIU_INTX_EN1 - (coreid * 2 + 1)); - if (cpumask_test_cpu(cpu, dest)) + cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; en1 |= 1ull << bit; - else + } else { en1 &= ~(1ull << bit); + } cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); } /* @@ -491,13 +616,17 @@ static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq, { int cpu; int index; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); for_each_online_cpu(cpu) { index = octeon_coreid_for_cpu(cpu) * 2 + 1; - if (cpumask_test_cpu(cpu, dest)) + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); - else + } else { cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); + } } return 0; } @@ -507,11 +636,10 @@ static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq, * Newer octeon chips have support for lockless CIU operation. */ static struct irq_chip octeon_irq_chip_ciu1_v2 = { - .name = "CIU0", + .name = "CIU1", .enable = octeon_irq_ciu1_enable_v2, .disable = octeon_irq_ciu1_disable_all_v2, - .ack = octeon_irq_ciu1_ack_v2, - .eoi = octeon_irq_ciu1_eoi_v2, + .eoi = octeon_irq_ciu1_enable_v2, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu1_set_affinity_v2, #endif @@ -521,103 +649,36 @@ static struct irq_chip octeon_irq_chip_ciu1 = { .name = "CIU1", .enable = octeon_irq_ciu1_enable, .disable = octeon_irq_ciu1_disable, - .ack = octeon_irq_ciu1_ack, .eoi = octeon_irq_ciu1_eoi, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu1_set_affinity, #endif }; -#ifdef CONFIG_PCI_MSI - -static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); - -static void octeon_irq_msi_ack(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } else { - /* - * These chips have PCIe. Thankfully the ACK doesn't - * need any locking. - */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } -} - -static void octeon_irq_msi_eoi(unsigned int irq) -{ - /* Nothing needed */ -} - -static void octeon_irq_msi_enable(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* - * Octeon PCI doesn't have the ability to mask/unmask - * MSI interrupts individually. Instead of - * masking/unmasking them in groups of 16, we simple - * assume MSI devices are well behaved. MSI - * interrupts are always enable and the ACK is assumed - * to be enough. - */ - } else { - /* These chips have PCIe. Note that we only support - * the first 64 MSI interrupts. Unfortunately all the - * MSI enables are in the same register. We use - * MSI0's lock to control access to them all. - */ - uint64_t en; - unsigned long flags; - raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); - en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0); - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); - cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); - } -} - -static void octeon_irq_msi_disable(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* See comment in enable */ - } else { - /* - * These chips have PCIe. Note that we only support - * the first 64 MSI interrupts. Unfortunately all the - * MSI enables are in the same register. We use - * MSI0's lock to control access to them all. - */ - uint64_t en; - unsigned long flags; - raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); - en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); - cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); - } -} +static struct irq_chip octeon_irq_chip_ciu1_wd_v2 = { + .name = "CIU1-W", + .enable = octeon_irq_ciu1_wd_enable_v2, + .disable = octeon_irq_ciu1_disable_all_v2, + .eoi = octeon_irq_ciu1_wd_enable_v2, +}; -static struct irq_chip octeon_irq_chip_msi = { - .name = "MSI", - .enable = octeon_irq_msi_enable, - .disable = octeon_irq_msi_disable, - .ack = octeon_irq_msi_ack, - .eoi = octeon_irq_msi_eoi, +static struct irq_chip octeon_irq_chip_ciu1_wd = { + .name = "CIU1-W", + .enable = octeon_irq_ciu1_wd_enable, + .disable = octeon_irq_ciu1_disable, + .eoi = octeon_irq_ciu1_eoi, }; -#endif + +static void (*octeon_ciu0_ack)(unsigned int); +static void (*octeon_ciu1_ack)(unsigned int); void __init arch_init_irq(void) { - int irq; + unsigned int irq; struct irq_chip *chip0; - struct irq_chip *chip0_timer; + struct irq_chip *chip0_mbox; struct irq_chip *chip1; + struct irq_chip *chip1_wd; #ifdef CONFIG_SMP /* Set the default affinity to the boot cpu. */ @@ -631,13 +692,19 @@ void __init arch_init_irq(void) if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { + octeon_ciu0_ack = octeon_irq_ciu0_ack_v2; + octeon_ciu1_ack = octeon_irq_ciu1_ack_v2; chip0 = &octeon_irq_chip_ciu0_v2; - chip0_timer = &octeon_irq_chip_ciu0_timer_v2; + chip0_mbox = &octeon_irq_chip_ciu0_mbox_v2; chip1 = &octeon_irq_chip_ciu1_v2; + chip1_wd = &octeon_irq_chip_ciu1_wd_v2; } else { + octeon_ciu0_ack = octeon_irq_ciu0_ack; + octeon_ciu1_ack = octeon_irq_ciu1_ack; chip0 = &octeon_irq_chip_ciu0; - chip0_timer = &octeon_irq_chip_ciu0_timer; + chip0_mbox = &octeon_irq_chip_ciu0_mbox; chip1 = &octeon_irq_chip_ciu1; + chip1_wd = &octeon_irq_chip_ciu1_wd; } /* 0 - 15 reserved for i8259 master and slave controller. */ @@ -651,34 +718,23 @@ void __init arch_init_irq(void) /* 24 - 87 CIU_INT_SUM0 */ for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { switch (irq) { - case OCTEON_IRQ_GMX_DRP0: - case OCTEON_IRQ_GMX_DRP1: - case OCTEON_IRQ_IPD_DRP: - case OCTEON_IRQ_KEY_ZERO: - case OCTEON_IRQ_TIMER0: - case OCTEON_IRQ_TIMER1: - case OCTEON_IRQ_TIMER2: - case OCTEON_IRQ_TIMER3: - set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq); + case OCTEON_IRQ_MBOX0: + case OCTEON_IRQ_MBOX1: + set_irq_chip_and_handler(irq, chip0_mbox, handle_percpu_irq); break; default: - set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); + set_irq_chip_and_handler(irq, chip0, handle_fasteoi_irq); break; } } /* 88 - 151 CIU_INT_SUM1 */ - for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_RESERVED151; irq++) { - set_irq_chip_and_handler(irq, chip1, handle_percpu_irq); - } + for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_WDOG15; irq++) + set_irq_chip_and_handler(irq, chip1_wd, handle_fasteoi_irq); + + for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED151; irq++) + set_irq_chip_and_handler(irq, chip1, handle_fasteoi_irq); -#ifdef CONFIG_PCI_MSI - /* 152 - 215 PCI/PCIe MSI interrupts */ - for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_BIT63; irq++) { - set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, - handle_percpu_irq); - } -#endif set_c0_status(0x300 << 2); } @@ -693,6 +749,7 @@ asmlinkage void plat_irq_dispatch(void) unsigned long cop0_status; uint64_t ciu_en; uint64_t ciu_sum; + unsigned int irq; while (1) { cop0_cause = read_c0_cause(); @@ -704,18 +761,24 @@ asmlinkage void plat_irq_dispatch(void) ciu_sum = cvmx_read_csr(ciu_sum0_address); ciu_en = cvmx_read_csr(ciu_en0_address); ciu_sum &= ciu_en; - if (likely(ciu_sum)) - do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1); - else + if (likely(ciu_sum)) { + irq = fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1; + octeon_ciu0_ack(irq); + do_IRQ(irq); + } else { spurious_interrupt(); + } } else if (unlikely(cop0_cause & STATUSF_IP3)) { ciu_sum = cvmx_read_csr(ciu_sum1_address); ciu_en = cvmx_read_csr(ciu_en1_address); ciu_sum &= ciu_en; - if (likely(ciu_sum)) - do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1); - else + if (likely(ciu_sum)) { + irq = fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1; + octeon_ciu1_ack(irq); + do_IRQ(irq); + } else { spurious_interrupt(); + } } else if (likely(cop0_cause)) { do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE); } else { @@ -725,54 +788,84 @@ asmlinkage void plat_irq_dispatch(void) } #ifdef CONFIG_HOTPLUG_CPU -static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu) -{ - unsigned int isset; - int coreid = octeon_coreid_for_cpu(cpu); - int bit = (irq < OCTEON_IRQ_WDOG0) ? - irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0; - if (irq < 64) { - isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) & - (1ull << bit)) >> bit; - } else { - isset = (cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)) & - (1ull << bit)) >> bit; - } - return isset; -} void fixup_irqs(void) { - int irq; + int irq; + struct irq_desc *desc; + cpumask_t new_affinity; + unsigned long flags; + int do_set_affinity; + int cpu; + + cpu = smp_processor_id(); for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) octeon_irq_core_disable_local(irq); - for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_GPIO15; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu0.disable(irq); - octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); - } - } - -#if 0 - for (irq = OCTEON_IRQ_MBOX0; irq <= OCTEON_IRQ_MBOX1; irq++) - octeon_irq_mailbox_mask(irq); -#endif - for (irq = OCTEON_IRQ_UART0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu0.disable(irq); - octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); - } - } + for (irq = OCTEON_IRQ_WORKQ0; irq < OCTEON_IRQ_LAST; irq++) { + desc = irq_to_desc(irq); + switch (irq) { + case OCTEON_IRQ_MBOX0: + case OCTEON_IRQ_MBOX1: + /* The eoi function will disable them on this CPU. */ + desc->chip->eoi(irq); + break; + case OCTEON_IRQ_WDOG0: + case OCTEON_IRQ_WDOG1: + case OCTEON_IRQ_WDOG2: + case OCTEON_IRQ_WDOG3: + case OCTEON_IRQ_WDOG4: + case OCTEON_IRQ_WDOG5: + case OCTEON_IRQ_WDOG6: + case OCTEON_IRQ_WDOG7: + case OCTEON_IRQ_WDOG8: + case OCTEON_IRQ_WDOG9: + case OCTEON_IRQ_WDOG10: + case OCTEON_IRQ_WDOG11: + case OCTEON_IRQ_WDOG12: + case OCTEON_IRQ_WDOG13: + case OCTEON_IRQ_WDOG14: + case OCTEON_IRQ_WDOG15: + /* + * These have special per CPU semantics and + * are handled in the watchdog driver. + */ + break; + default: + raw_spin_lock_irqsave(&desc->lock, flags); + /* + * If this irq has an action, it is in use and + * must be migrated if it has affinity to this + * cpu. + */ + if (desc->action && cpumask_test_cpu(cpu, desc->affinity)) { + if (cpumask_weight(desc->affinity) > 1) { + /* + * It has multi CPU affinity, + * just remove this CPU from + * the affinity set. + */ + cpumask_copy(&new_affinity, desc->affinity); + cpumask_clear_cpu(cpu, &new_affinity); + } else { + /* + * Otherwise, put it on lowest + * numbered online CPU. + */ + cpumask_clear(&new_affinity); + cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); + } + do_set_affinity = 1; + } else { + do_set_affinity = 0; + } + raw_spin_unlock_irqrestore(&desc->lock, flags); + + if (do_set_affinity) + irq_set_affinity(irq, &new_affinity); - for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED135; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu1.disable(irq); - octeon_irq_ciu1_set_affinity(irq, &cpu_online_map); + break; } } } diff --git a/arch/mips/cavium-octeon/octeon_boot.h b/arch/mips/cavium-octeon/octeon_boot.h index 0f7f84a..428864b 100644 --- a/arch/mips/cavium-octeon/octeon_boot.h +++ b/arch/mips/cavium-octeon/octeon_boot.h @@ -23,14 +23,16 @@ #include struct boot_init_vector { - uint32_t stack_addr; - uint32_t code_addr; + /* First stage address - in ram instead of flash */ + uint64_t code_addr; + /* Setup code for application, NOT application entry point */ uint32_t app_start_func_addr; + /* k0 is used for global data - needs to be passed to other cores */ uint32_t k0_val; - uint32_t flags; - uint32_t boot_info_addr; + /* Address of boot info block structure */ + uint64_t boot_info_addr; + uint32_t flags; /* flags */ uint32_t pad; - uint32_t pad2; }; /* similar to bootloader's linux_app_boot_info but without global data */ @@ -40,7 +42,7 @@ struct linux_app_boot_info { uint32_t avail_coremask; uint32_t pci_console_active; uint32_t icache_prefetch_disable; - uint32_t InitTLBStart_addr; + uint64_t InitTLBStart_addr; uint32_t start_app_addr; uint32_t cur_exception_base; uint32_t no_mark_private_data; @@ -58,7 +60,7 @@ struct linux_app_boot_info { #define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" -#define LABI_SIGNATURE 0xAABBCCDD +#define LABI_SIGNATURE 0xAABBCC01 /* from uboot-headers/octeon_mem_map.h */ #define EXCEPTION_BASE_INCR (4 * 1024) diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c index 83eac37..638adab 100644 --- a/arch/mips/cavium-octeon/serial.c +++ b/arch/mips/cavium-octeon/serial.c @@ -18,11 +18,7 @@ #include -#ifdef CONFIG_GDB_CONSOLE -#define DEBUG_UART 0 -#else #define DEBUG_UART 1 -#endif unsigned int octeon_serial_in(struct uart_port *up, int offset) { diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index d1b5ffa..69197cb 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -32,6 +32,7 @@ #include #include +#include #ifdef CONFIG_CAVIUM_DECODE_RSL extern void cvmx_interrupt_rsl_decode(void); @@ -578,9 +579,6 @@ void __init prom_init(void) } if (strstr(arcs_cmdline, "console=") == NULL) { -#ifdef CONFIG_GDB_CONSOLE - strcat(arcs_cmdline, " console=gdb"); -#else #ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL strcat(arcs_cmdline, " console=ttyS0,115200"); #else @@ -589,7 +587,6 @@ void __init prom_init(void) else strcat(arcs_cmdline, " console=ttyS0,115200"); #endif -#endif } if (octeon_is_simulation()) { @@ -598,13 +595,13 @@ void __init prom_init(void) * the filesystem. Also specify the calibration delay * to avoid calculating it every time. */ - strcat(arcs_cmdline, " rw root=1f00" - " lpj=60176 slram=root,0x40000000,+1073741824"); + strcat(arcs_cmdline, " rw root=1f00 slram=root,0x40000000,+1073741824"); } mips_hpt_frequency = octeon_get_clock_rate(); octeon_init_cvmcount(); + octeon_setup_delays(); _machine_restart = octeon_restart; _machine_halt = octeon_halt; @@ -613,6 +610,22 @@ void __init prom_init(void) register_smp_ops(&octeon_smp_ops); } +/* Exclude a single page from the regions obtained in plat_mem_setup. */ +static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) +{ + if (addr > *mem && addr < *mem + *size) { + u64 inc = addr - *mem; + add_memory_region(*mem, inc, BOOT_MEM_RAM); + *mem += inc; + *size -= inc; + } + + if (addr == *mem && *size > PAGE_SIZE) { + *mem += PAGE_SIZE; + *size -= PAGE_SIZE; + } +} + void __init plat_mem_setup(void) { uint64_t mem_alloc_size; @@ -663,12 +676,27 @@ void __init plat_mem_setup(void) CVMX_BOOTMEM_FLAG_NO_LOCKING); #endif if (memory >= 0) { + u64 size = mem_alloc_size; + + /* + * exclude a page at the beginning and end of + * the 256MB PCIe 'hole' so the kernel will not + * try to allocate multi-page buffers that + * span the discontinuity. + */ + memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE, + &memory, &size); + memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + + CVMX_PCIE_BAR1_PHYS_SIZE, + &memory, &size); + /* * This function automatically merges address * regions next to each other if they are * received in incrementing order. */ - add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); + if (size) + add_memory_region(memory, size, BOOT_MEM_RAM); total += mem_alloc_size; } else { break; @@ -691,7 +719,10 @@ void __init plat_mem_setup(void) "cvmx_bootmem_phy_alloc\n"); } - +/* + * Emit one character to the boot UART. Exported for use by the + * watchdog timer. + */ int prom_putchar(char c) { uint64_t lsrval; @@ -705,6 +736,7 @@ int prom_putchar(char c) cvmx_write_csr(CVMX_MIO_UARTX_THR(octeon_uart), c & 0xffull); return 1; } +EXPORT_SYMBOL(prom_putchar); void prom_free_prom_memory(void) { diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 6d99b9d..391cefe 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2008 Cavium Networks + * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks */ #include #include @@ -27,7 +27,8 @@ volatile unsigned long octeon_processor_sp; volatile unsigned long octeon_processor_gp; #ifdef CONFIG_HOTPLUG_CPU -static unsigned int InitTLBStart_addr; +uint64_t octeon_bootloader_entry_addr; +EXPORT_SYMBOL(octeon_bootloader_entry_addr); #endif static irqreturn_t mailbox_interrupt(int irq, void *dev_id) @@ -80,20 +81,13 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask, static void octeon_smp_hotplug_setup(void) { #ifdef CONFIG_HOTPLUG_CPU - uint32_t labi_signature; - - labi_signature = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - labi_signature))); - if (labi_signature != LABI_SIGNATURE) - pr_err("The bootloader version on this board is incorrect\n"); - InitTLBStart_addr = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - InitTLBStart_addr))); + struct linux_app_boot_info *labi; + + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); + if (labi->labi_signature != LABI_SIGNATURE) + panic("The bootloader version on this board is incorrect."); + + octeon_bootloader_entry_addr = labi->InitTLBStart_addr; #endif } @@ -102,24 +96,47 @@ static void octeon_smp_setup(void) const int coreid = cvmx_get_core_num(); int cpus; int id; - int core_mask = octeon_get_boot_coremask(); +#ifdef CONFIG_HOTPLUG_CPU + unsigned int num_cores = cvmx_octeon_num_cores(); +#endif + + /* The present CPUs are initially just the boot cpu (CPU 0). */ + for (id = 0; id < NR_CPUS; id++) { + set_cpu_possible(id, id == 0); + set_cpu_present(id, id == 0); + } - cpus_clear(cpu_possible_map); __cpu_number_map[coreid] = 0; __cpu_logical_map[0] = coreid; - cpu_set(0, cpu_possible_map); + /* The present CPUs get the lowest CPU numbers. */ cpus = 1; - for (id = 0; id < 16; id++) { + for (id = 0; id < NR_CPUS; id++) { if ((id != coreid) && (core_mask & (1 << id))) { - cpu_set(cpus, cpu_possible_map); + set_cpu_possible(cpus, true); + set_cpu_present(cpus, true); __cpu_number_map[id] = cpus; __cpu_logical_map[cpus] = id; cpus++; } } - cpu_present_map = cpu_possible_map; + +#ifdef CONFIG_HOTPLUG_CPU + /* + * The possible CPUs are all those present on the chip. We + * will assign CPU numbers for possible cores as well. Cores + * are always consecutively numberd from 0. + */ + for (id = 0; id < num_cores && id < NR_CPUS; id++) { + if (!(core_mask & (1 << id))) { + set_cpu_possible(cpus, true); + __cpu_number_map[id] = cpus; + __cpu_logical_map[cpus] = id; + cpus++; + } + } +#endif octeon_smp_hotplug_setup(); } @@ -158,18 +175,21 @@ static void octeon_init_secondary(void) { const int coreid = cvmx_get_core_num(); union cvmx_ciu_intx_sum0 interrupt_enable; + unsigned int sr; #ifdef CONFIG_HOTPLUG_CPU - unsigned int cur_exception_base; - - cur_exception_base = cvmx_read64_uint32( - CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - cur_exception_base))); - /* cur_exception_base is incremented in bootloader after setting */ - write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR)); + struct linux_app_boot_info *labi; + + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); + + if (labi->labi_signature != LABI_SIGNATURE) + panic("The bootloader version on this board is incorrect."); #endif + + sr = set_c0_status(ST0_BEV); + write_c0_ebase((u32)ebase); + write_c0_status(sr); + octeon_check_cpu_bist(); octeon_init_cvmcount(); /* @@ -276,8 +296,8 @@ static int octeon_cpu_disable(void) static void octeon_cpu_die(unsigned int cpu) { int coreid = cpu_logical_map(cpu); - uint32_t avail_coremask; - struct cvmx_bootmem_named_block_desc *block_desc; + uint32_t mask, new_mask; + const struct cvmx_bootmem_named_block_desc *block_desc; while (per_cpu(cpu_state, cpu) != CPU_DEAD) cpu_relax(); @@ -286,52 +306,40 @@ static void octeon_cpu_die(unsigned int cpu) * This is a bit complicated strategics of getting/settig available * cores mask, copied from bootloader */ + + mask = 1 << coreid; /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); if (!block_desc) { - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof - (struct linux_app_boot_info, - avail_coremask))); - } else { /* alternative, already initialized */ - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - block_desc->base_addr + - AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); - } + struct linux_app_boot_info *labi; - avail_coremask |= 1 << coreid; + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); - /* Setting avail_coremask for bootoct binary */ - if (!block_desc) { - cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - avail_coremask)), - avail_coremask); - } else { - cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - block_desc->base_addr + - AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK), - avail_coremask); + labi->avail_coremask |= mask; + new_mask = labi->avail_coremask; + } else { /* alternative, already initialized */ + uint32_t *p = (uint32_t *)PHYS_TO_XKSEG_CACHED(block_desc->base_addr + + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK); + *p |= mask; + new_mask = *p; } - pr_info("Reset core %d. Available Coremask = %x\n", coreid, - avail_coremask); + pr_info("Reset core %d. Available Coremask = 0x%x \n", coreid, new_mask); + mb(); cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); cvmx_write_csr(CVMX_CIU_PP_RST, 0); } void play_dead(void) { - int coreid = cvmx_get_core_num(); + int cpu = cpu_number_map(cvmx_get_core_num()); idle_task_exit(); octeon_processor_boot = 0xff; - per_cpu(cpu_state, coreid) = CPU_DEAD; + per_cpu(cpu_state, cpu) = CPU_DEAD; + + mb(); while (1) /* core will be reset here */ ; @@ -344,29 +352,27 @@ static void start_after_reset(void) kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ } -int octeon_update_boot_vector(unsigned int cpu) +static int octeon_update_boot_vector(unsigned int cpu) { int coreid = cpu_logical_map(cpu); - unsigned int avail_coremask; - struct cvmx_bootmem_named_block_desc *block_desc; + uint32_t avail_coremask; + const struct cvmx_bootmem_named_block_desc *block_desc; struct boot_init_vector *boot_vect = - (struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + - BOOTLOADER_BOOT_VECTOR); + (struct boot_init_vector *)PHYS_TO_XKSEG_CACHED(BOOTLOADER_BOOT_VECTOR); block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); if (!block_desc) { - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - avail_coremask))); + struct linux_app_boot_info *labi; + + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); + + avail_coremask = labi->avail_coremask; + labi->avail_coremask &= ~(1 << coreid); } else { /* alternative, already initialized */ - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - block_desc->base_addr + - AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); + avail_coremask = *(uint32_t *)PHYS_TO_XKSEG_CACHED( + block_desc->base_addr + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK); } if (!(avail_coremask & (1 << coreid))) { @@ -377,9 +383,9 @@ int octeon_update_boot_vector(unsigned int cpu) boot_vect[coreid].app_start_func_addr = (uint32_t) (unsigned long) start_after_reset; - boot_vect[coreid].code_addr = InitTLBStart_addr; + boot_vect[coreid].code_addr = octeon_bootloader_entry_addr; - CVMX_SYNC; + mb(); cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); @@ -405,17 +411,11 @@ static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata octeon_cpu_notifier = { - .notifier_call = octeon_cpu_callback, -}; - static int __cpuinit register_cavium_notifier(void) { - register_hotcpu_notifier(&octeon_cpu_notifier); - + hotcpu_notifier(octeon_cpu_callback, 0); return 0; } - late_initcall(register_cavium_notifier); #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile index 2379262..61a334a 100644 --- a/arch/mips/cobalt/Makefile +++ b/arch/mips/cobalt/Makefile @@ -7,5 +7,3 @@ obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_EARLY_PRINTK) += console.o obj-$(CONFIG_MTD_PHYSMAP) += mtd.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/cobalt/Platform b/arch/mips/cobalt/Platform new file mode 100644 index 0000000..34123ef --- /dev/null +++ b/arch/mips/cobalt/Platform @@ -0,0 +1,6 @@ +# +# Cobalt Server +# +platform-$(CONFIG_MIPS_COBALT) += cobalt/ +cflags-$(CONFIG_MIPS_COBALT) += -I$(srctree)/arch/mips/include/asm/mach-cobalt +load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index f66d406..3a9ec6c 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1000=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1000=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index abb9a58..4589b84 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1100=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1100=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index 991c20a..9950f2a 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1200=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1200=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 5424c91..346ae63 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1500=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1500=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 949b6dc..10eafb9 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1550=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1550=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig new file mode 100644 index 0000000..17e2e62 --- /dev/null +++ b/arch/mips/configs/gpr_defconfig @@ -0,0 +1,2060 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.35-rc6 +# Fri Jul 23 19:28:52 2010 +# +CONFIG_MIPS=y + +# +# Machine selection +# +CONFIG_MIPS_ALCHEMY=y +# CONFIG_AR7 is not set +# CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MACH_LOONGSON is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_NEC_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_POWERTV 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_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +CONFIG_ALCHEMY_GPIOINT_AU1000=y +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_XXS1500 is not set +CONFIG_MIPS_GPR=y +CONFIG_SOC_AU1550=y +CONFIG_LOONGSON_UART_BASE=y +# CONFIG_LOONGSON_MC146818 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# 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_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX 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_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_HARDWARE_WATCHPOINTS=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_32KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_64BIT_PHYS_ADDR=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_KEXEC is not set +CONFIG_SECCOMP=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_OPROFILE is not set +CONFIG_HAVE_OPROFILE=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +CONFIG_MMU=y +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_TPROXY is not set +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_MARK=m +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +CONFIG_NETFILTER_XT_MATCH_HL=m +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +CONFIG_NETFILTER_XT_MATCH_REALM=m +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +# CONFIG_IP_VS_PROTO_SCTP is not set + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +# CONFIG_BRIDGE_EBT_NFLOG is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +CONFIG_IP_DCCP_TFRC_LIB=y +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_RDS is not set +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +# CONFIG_L2TP is not set +CONFIG_STP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_WAN_ROUTER=m +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +# CONFIG_NET_SCH_MULTIQ is not set +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +# CONFIG_NET_SCH_DRR is not set +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=m +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_DS1682 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_CB710_CORE is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=m +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_HOST_SMP=y +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# You can enable one or both FireWire driver stacks. +# + +# +# The newer stack is recommended. +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_IFB is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_MIPS_AU1X00_ENET=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_ATL2 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_ATMEL is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_ADM8211 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MWL8K is not set +CONFIG_ATH_COMMON=y +CONFIG_ATH_DEBUG=y +CONFIG_ATH5K=y +CONFIG_ATH5K_DEBUG=y +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_AR9170_USB is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWLWIFI is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +# CONFIG_WL12XX is not set +# CONFIG_ZD1211RW is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +CONFIG_WAN=y +CONFIG_LANMEDIA=m +CONFIG_HDLC=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_X25=m +CONFIG_PCI200SYN=m +CONFIG_WANXL=m +# CONFIG_PC300TOO is not set +CONFIG_FARSYNC=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_WAN_ROUTER_DRIVERS=m +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +# CONFIG_ATM_SOLOS is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLHC=m +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_NET_FC=y +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_AU1550 is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_SCH is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_CS5535 is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_LANGWELL is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +CONFIG_SENSORS_LM83=y +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +# CONFIG_SSB_B43_PCI_BRIDGE is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +# CONFIG_SSB_DRIVER_MIPS is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TC35892 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_ADP8860 is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m + +# +# Special HID drivers +# +# CONFIG_HID_3M_PCT is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CANDO is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EGALAX is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MOSART is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_QUANTA is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_STANTUM is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_LIBUSUAL=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=y +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ATM is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FSNOTIFY is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_INOTIFY_USER is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_LKDTM is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_EARLY_PRINTK=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw ip=auto" +# CONFIG_CMDLINE_OVERRIDE is not set +# CONFIG_SPINLOCK_TEST is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +CONFIG_CRYPTO_KHAZAD=m +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index cff8f4c..10d20aa 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_MTX1=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1500=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index 97382b6..778f726 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_PB1100=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1100=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1200_defconfig b/arch/mips/configs/pb1200_defconfig index e9ad773..0f908c6 100644 --- a/arch/mips/configs/pb1200_defconfig +++ b/arch/mips/configs/pb1200_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_PB1200=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1200=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index 7497d33..1c5fe6f 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_PB1500=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1500=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index aa526f5..49494b0 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_ALCHEMY_GPIOINT_AU1000=y CONFIG_MIPS_PB1550=y # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1550=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig index 7291633..af0ab73 100644 --- a/arch/mips/configs/powertv_defconfig +++ b/arch/mips/configs/powertv_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.31-rc5 -# Fri Aug 28 14:49:33 2009 +# Linux kernel version: 2.6.35-rc3 +# Thu Jul 1 11:03:28 2010 # CONFIG_MIPS=y @@ -11,11 +11,12 @@ CONFIG_MIPS=y # CONFIG_MACH_ALCHEMY is not set # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MACH_JAZZ is not set # CONFIG_LASAT is not set -# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MACH_LOONGSON is not set # CONFIG_MIPS_MALTA is not set # CONFIG_MIPS_SIM is not set # CONFIG_NEC_MARKEINS is not set @@ -50,7 +51,6 @@ CONFIG_POWERTV=y # CONFIG_MIN_RUNTIME_RESOURCES is not set # CONFIG_BOOTLOADER_DRIVER is not set CONFIG_BOOTLOADER_FAMILY="R2" -CONFIG_CSRC_POWERTV=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set @@ -65,9 +65,9 @@ CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y +CONFIG_CSRC_POWERTV=y CONFIG_DMA_NONCOHERENT=y -CONFIG_DMA_NEED_PCI_MAP_STATE=y -# CONFIG_EARLY_PRINTK is not set +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_SYS_HAS_EARLY_PRINTK=y # CONFIG_NO_IOPORT is not set CONFIG_CPU_BIG_ENDIAN=y @@ -79,7 +79,8 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # # CPU selection # -# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_LOONGSON2E is not set +# CONFIG_CPU_LOONGSON2F is not set # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y # CONFIG_CPU_MIPS64_R1 is not set @@ -122,7 +123,7 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_MIPS_MT_DISABLED=y # CONFIG_MIPS_MT_SMP is not set # CONFIG_MIPS_MT_SMTC is not set -CONFIG_CPU_HAS_LLSC=y +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set CONFIG_CPU_MIPSR2_IRQ_VI=y CONFIG_CPU_MIPSR2_IRQ_EI=y CONFIG_CPU_HAS_SYNC=y @@ -144,8 +145,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y @@ -177,6 +177,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="mips-linux-" CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set @@ -190,19 +191,15 @@ CONFIG_SYSVIPC_SYSCTL=y # # RCU Subsystem # -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=16 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set -# CONFIG_CGROUPS is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set @@ -211,6 +208,7 @@ CONFIG_INITRAMFS_SOURCE="" # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -234,18 +232,16 @@ CONFIG_SHMEM=y CONFIG_AIO=y # -# Performance Counters +# Kernel Performance Events And Counters # # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_PCI_QUIRKS=y # CONFIG_SLUB_DEBUG is not set -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # @@ -253,7 +249,7 @@ CONFIG_HAVE_OPROFILE=y # # CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 CONFIG_MODULES=y @@ -271,15 +267,41 @@ CONFIG_LBDAF=y # IO Schedulers # CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -# CONFIG_DEFAULT_AS is not set # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set CONFIG_DEFAULT_NOOP=y CONFIG_DEFAULT_IOSCHED="noop" -# CONFIG_PROBE_INITRD_HEADER is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set # CONFIG_FREEZER is not set # @@ -289,7 +311,6 @@ CONFIG_HW_HAS_PCI=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -318,7 +339,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -390,12 +410,26 @@ CONFIG_NETFILTER_ADVANCED=y # CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +# CONFIG_NETFILTER_XT_MARK is not set + +# +# Xtables targets +# # CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set # CONFIG_NETFILTER_XT_TARGET_MARK is not set # CONFIG_NETFILTER_XT_TARGET_NFLOG is not set # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set # CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set # CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set + +# +# Xtables matches +# # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set # CONFIG_NETFILTER_XT_MATCH_DCCP is not set # CONFIG_NETFILTER_XT_MATCH_DSCP is not set @@ -465,10 +499,13 @@ CONFIG_IP6_NF_FILTER=y # CONFIG_IP6_NF_RAW is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set +# CONFIG_L2TP is not set CONFIG_STP=y CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -526,10 +563,21 @@ CONFIG_NET_SCH_FIFO=y # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set -# CONFIG_WIRELESS is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# + +# +# Some wireless drivers require a rate control algorithm +# # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set +# CONFIG_CAIF is not set # # Device Drivers @@ -539,6 +587,7 @@ CONFIG_NET_SCH_FIFO=y # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y @@ -550,9 +599,9 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_CONNECTOR is not set CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AR7_PARTS is not set @@ -568,6 +617,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set # CONFIG_MTD_OOPS is not set # @@ -611,11 +661,16 @@ CONFIG_MTD_CFI_I2=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_SM_COMMON is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_DENALI is not set +CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018 CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_CAFE is not set # CONFIG_MTD_NAND_NANDSIM is not set @@ -641,6 +696,10 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_UB is not set @@ -658,6 +717,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -693,64 +753,95 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# # CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_SATA_INIC162X is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y -# CONFIG_SATA_SVW is not set + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# # CONFIG_ATA_PIIX is not set # CONFIG_SATA_MV is not set # CONFIG_SATA_NV is not set -# CONFIG_PDC_ADMA is not set -# CONFIG_SATA_QSTOR is not set # CONFIG_SATA_PROMISE is not set -# CONFIG_SATA_SX4 is not set # CONFIG_SATA_SIL is not set # CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set # CONFIG_SATA_ULI is not set # CONFIG_SATA_VIA is not set # CONFIG_SATA_VITESSE is not set -# CONFIG_SATA_INIC162X is not set + +# +# PATA SFF controllers with BMDMA +# # CONFIG_PATA_ALI is not set # CONFIG_PATA_AMD is not set # CONFIG_PATA_ARTOP is not set # CONFIG_PATA_ATIIXP is not set -# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_ATP867X is not set # CONFIG_PATA_CMD64X is not set # CONFIG_PATA_CS5520 is not set # CONFIG_PATA_CS5530 is not set # CONFIG_PATA_CYPRESS is not set # CONFIG_PATA_EFAR is not set -# CONFIG_ATA_GENERIC is not set # CONFIG_PATA_HPT366 is not set # CONFIG_PATA_HPT37X is not set # CONFIG_PATA_HPT3X2N is not set # CONFIG_PATA_HPT3X3 is not set -# CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set # CONFIG_PATA_JMICRON is not set -# CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set -# CONFIG_PATA_MPIIX is not set -# CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set # CONFIG_PATA_NINJA32 is not set -# CONFIG_PATA_NS87410 is not set # CONFIG_PATA_NS87415 is not set -# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set # CONFIG_PATA_PDC_OLD is not set # CONFIG_PATA_RADISYS is not set -# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_RDC is not set # CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set # CONFIG_PATA_SERVERWORKS is not set -# CONFIG_PATA_PDC2027X is not set # CONFIG_PATA_SIL680 is not set # CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set # CONFIG_PATA_PLATFORM is not set -# CONFIG_PATA_SCH is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set # CONFIG_FUSION is not set @@ -763,7 +854,7 @@ CONFIG_ATA_SFF=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -787,6 +878,7 @@ CONFIG_MII=y # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set # CONFIG_ETHOC is not set +# CONFIG_SMSC911X is not set # CONFIG_DNET is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set @@ -800,6 +892,7 @@ CONFIG_MII=y # CONFIG_NET_PCI is not set # CONFIG_B44 is not set # CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set # CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set @@ -829,6 +922,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -841,16 +936,12 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set # CONFIG_TR is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set +# CONFIG_WLAN is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -864,6 +955,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_USB_PEGASUS is not set CONFIG_USB_RTL8150=y # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -873,6 +965,7 @@ CONFIG_USB_RTL8150=y # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_VMXNET3 is not set # CONFIG_ISDN is not set # CONFIG_PHONE is not set @@ -882,6 +975,7 @@ CONFIG_USB_RTL8150=y CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set # CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set # # Userland interfaces @@ -913,6 +1007,7 @@ CONFIG_INPUT_EVDEV=y # CONFIG_VT is not set # CONFIG_DEVKMEM is not set # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set # CONFIG_NOZOMI is not set # @@ -924,6 +1019,9 @@ CONFIG_INPUT_EVDEV=y # Non-8250 serial port support # # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -934,6 +1032,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set # CONFIG_I2C is not set # CONFIG_SPI is not set @@ -945,7 +1044,6 @@ CONFIG_DEVPORT=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set CONFIG_SSB_POSSIBLE=y @@ -953,20 +1051,14 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_SUPPORT is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set # # Graphics support # +# CONFIG_VGA_ARB is not set # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -980,7 +1072,6 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y -# CONFIG_HID_DEBUG is not set # CONFIG_HIDRAW is not set # @@ -993,31 +1084,43 @@ CONFIG_USB_HIDDEV=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set # CONFIG_HID_A4TECH is not set # CONFIG_HID_APPLE is not set # CONFIG_HID_BELKIN is not set +# CONFIG_HID_CANDO is not set # CONFIG_HID_CHERRY is not set # CONFIG_HID_CHICONY is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EGALAX is not set # CONFIG_HID_EZKEY is not set # CONFIG_HID_KYE is not set # CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set # CONFIG_HID_KENSINGTON is not set # CONFIG_HID_LOGITECH is not set # CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_QUANTA is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_ROCCAT_KONE is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SONY is not set +# CONFIG_HID_STANTUM is not set # CONFIG_HID_SUNPLUS is not set # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set # CONFIG_HID_TOPSEED is not set # CONFIG_HID_THRUSTMASTER is not set # CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -1032,7 +1135,6 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_DEVICE_CLASS is not set # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_USB_MON is not set @@ -1050,6 +1152,7 @@ CONFIG_USB_EHCI_HCD=y # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set @@ -1133,6 +1236,7 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_SERIAL_NAVMAN is not set # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set # CONFIG_USB_SERIAL_QUALCOMM is not set # CONFIG_USB_SERIAL_SPCP8X5 is not set # CONFIG_USB_SERIAL_HP4X is not set @@ -1146,6 +1250,8 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_SERIAL_OPTION is not set # CONFIG_USB_SERIAL_OMNINET is not set # CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set # CONFIG_USB_SERIAL_DEBUG is not set # @@ -1158,7 +1264,6 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1171,7 +1276,6 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1189,10 +1293,6 @@ CONFIG_RTC_LIB=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set - -# -# TI VLYNQ -# # CONFIG_STAGING is not set # @@ -1214,6 +1314,7 @@ CONFIG_JBD=y # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y # CONFIG_DNOTIFY is not set @@ -1274,6 +1375,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1284,7 +1386,6 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1299,6 +1400,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1360,6 +1462,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -1393,15 +1496,25 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set @@ -1410,19 +1523,22 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -# CONFIG_KMEMCHECK is not set +# CONFIG_EARLY_PRINTK is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="rw dhash_entries=1024 ihash_entries=1024 ip=10.0.1.3:10.0.1.1:10.0.1.1:255.255.255.0:zeus:eth0: root=/dev/nfs nfsroot=/nfsroot/cramfs,wsize=512,rsize=512,tcp nokgdb console=ttyUSB0,115200 memsize=252M" +CONFIG_CMDLINE="" # CONFIG_CMDLINE_OVERRIDE is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_RUNTIME_DEBUG is not set +# CONFIG_SPINLOCK_TEST is not set # # Security options @@ -1430,13 +1546,16 @@ CONFIG_CMDLINE="rw dhash_entries=1024 ihash_entries=1024 ip=10.0.1.3:10.0.1.1:10 # CONFIG_KEYS is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" CONFIG_CRYPTO=y # # Crypto core or helper # -# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y CONFIG_CRYPTO_AEAD=y @@ -1479,11 +1598,13 @@ CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set # # Digest # # CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_MICHAEL_MIC is not set diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile index c530208..9eb2f9c 100644 --- a/arch/mips/dec/Makefile +++ b/arch/mips/dec/Makefile @@ -8,5 +8,3 @@ obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \ obj-$(CONFIG_PROM_CONSOLE) += promcon.o obj-$(CONFIG_TC) += tc.o obj-$(CONFIG_CPU_HAS_WB) += wbflush.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/dec/Platform b/arch/mips/dec/Platform new file mode 100644 index 0000000..3adbcbd --- /dev/null +++ b/arch/mips/dec/Platform @@ -0,0 +1,8 @@ +# +# DECstation family +# +platform-$(CONFIG_MACH_DECSTATION) = dec/ +cflags-$(CONFIG_MACH_DECSTATION) += \ + -I$(srctree)/arch/mips/include/asm/mach-dec +libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ +load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 diff --git a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c index 9f0972f..c239c25 100644 --- a/arch/mips/dec/promcon.c +++ b/arch/mips/dec/promcon.c @@ -33,8 +33,7 @@ static int __init prom_console_setup(struct console *co, char *options) return 0; } -static struct console sercons = -{ +static struct console sercons = { .name = "ttyS", .write = prom_console_write, .setup = prom_console_setup, diff --git a/arch/mips/emma/Makefile b/arch/mips/emma/Makefile new file mode 100644 index 0000000..4254a31 --- /dev/null +++ b/arch/mips/emma/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_SOC_EMMA2RH) += common/ + +# +# NEC EMMA2RH Mark-eins +# +obj-$(CONFIG_NEC_MARKEINS) += markeins/ diff --git a/arch/mips/emma/Platform b/arch/mips/emma/Platform new file mode 100644 index 0000000..0282f7f --- /dev/null +++ b/arch/mips/emma/Platform @@ -0,0 +1,4 @@ +platform-$(CONFIG_SOC_EMMA2RH) += emma/ +cflags-$(CONFIG_SOC_EMMA2RH) += \ + -I$(srctree)/arch/mips/include/asm/mach-emma2rh +load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 diff --git a/arch/mips/emma/markeins/irq.c b/arch/mips/emma/markeins/irq.c index 9504b7e..3a96799 100644 --- a/arch/mips/emma/markeins/irq.c +++ b/arch/mips/emma/markeins/irq.c @@ -301,7 +301,7 @@ void __init arch_init_irq(void) /* setup cascade interrupts */ setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade); - setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade); + setup_irq(MIPS_CPU_IRQ_BASE + 2, &irq_cascade); } asmlinkage void plat_irq_dispatch(void) @@ -309,13 +309,13 @@ asmlinkage void plat_irq_dispatch(void) unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP7) - do_IRQ(CPU_IRQ_BASE + 7); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & STATUSF_IP2) emma2rh_irq_dispatch(); else if (pending & STATUSF_IP1) - do_IRQ(CPU_IRQ_BASE + 1); + do_IRQ(MIPS_CPU_IRQ_BASE + 1); else if (pending & STATUSF_IP0) - do_IRQ(CPU_IRQ_BASE + 0); + do_IRQ(MIPS_CPU_IRQ_BASE + 0); else spurious_interrupt(); } diff --git a/arch/mips/emma/markeins/setup.c b/arch/mips/emma/markeins/setup.c index 9b3f51e..feceebc 100644 --- a/arch/mips/emma/markeins/setup.c +++ b/arch/mips/emma/markeins/setup.c @@ -52,7 +52,6 @@ static void markeins_machine_halt(void) static void markeins_machine_power_off(void) { - printk("EMMA2RH Mark-eins halted. Please turn off the power.\n"); markeins_led("poweroff."); while (1) ; } diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile deleted file mode 100644 index b49d282..0000000 --- a/arch/mips/gt64120/wrppmc/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# 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 2006 Wind River System, Inc. -# Author: Rongkai.Zhan -# -# Makefile for the Wind River MIPS 4KC PPMC Eval Board -# - -obj-y += irq.o pci.o reset.o serial.o setup.o time.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c deleted file mode 100644 index c6e7062..0000000 --- a/arch/mips/gt64120/wrppmc/irq.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * irq.c: GT64120 Interrupt Controller - * - * Copyright (C) 2006, Wind River System Inc. - * Author: Rongkai.Zhan, - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include - -#include -#include -#include - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP7) - do_IRQ(WRPPMC_MIPS_TIMER_IRQ); /* CPU Compare/Count internal timer */ - else if (pending & STATUSF_IP6) - do_IRQ(WRPPMC_UART16550_IRQ); /* UART 16550 port */ - else if (pending & STATUSF_IP3) - do_IRQ(WRPPMC_PCI_INTA_IRQ); /* PCI INT_A */ - else - spurious_interrupt(); -} - -/** - * Initialize GT64120 Interrupt Controller - */ -void gt64120_init_pic(void) -{ - /* clear CPU Interrupt Cause Registers */ - GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); - GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); - - /* Disable all interrupts from GT64120 bridge chip */ - GT_WRITE(GT_INTRMASK_OFS, 0x00); - GT_WRITE(GT_HINTRMASK_OFS, 0x00); - GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); - GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); -} - -void __init arch_init_irq(void) -{ - /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ - mips_cpu_irq_init(); - - gt64120_init_pic(); -} diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c deleted file mode 100644 index d06192f..0000000 --- a/arch/mips/gt64120/wrppmc/pci.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * pci.c: GT64120 PCI support. - * - * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan - * - * 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 - -extern struct pci_ops gt64xxx_pci0_ops; - -static struct resource pci0_io_resource = { - .name = "pci_0 io", - .start = GT_PCI_IO_BASE, - .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, - .flags = IORESOURCE_IO, -}; - -static struct resource pci0_mem_resource = { - .name = "pci_0 memory", - .start = GT_PCI_MEM_BASE, - .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct pci_controller hose_0 = { - .pci_ops = >64xxx_pci0_ops, - .io_resource = &pci0_io_resource, - .mem_resource = &pci0_mem_resource, -}; - -static int __init gt64120_pci_init(void) -{ - u32 tmp; - - tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ - tmp = GT_READ(GT_PCI0_BARE_OFS); - - /* reset the whole PCI I/O space range */ - ioport_resource.start = GT_PCI_IO_BASE; - ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; - - register_pci_controller(&hose_0); - return 0; -} - -arch_initcall(gt64120_pci_init); diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c deleted file mode 100644 index cc5474b..0000000 --- a/arch/mips/gt64120/wrppmc/reset.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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) 1997 Ralf Baechle - */ -#include -#include - -#include -#include -#include - -void wrppmc_machine_restart(char *command) -{ - /* - * Ouch, we're still alive ... This time we take the silver bullet ... - * ... and find that we leave the hardware in a state in which the - * kernel in the flush locks up somewhen during of after the PCI - * detection stuff. - */ - local_irq_disable(); - set_c0_status(ST0_BEV | ST0_ERL); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -} - -void wrppmc_machine_halt(void) -{ - local_irq_disable(); - - printk(KERN_NOTICE "You can safely turn off the power\n"); - while (1) { - if (cpu_wait) - cpu_wait(); - } -} diff --git a/arch/mips/gt64120/wrppmc/serial.c b/arch/mips/gt64120/wrppmc/serial.c deleted file mode 100644 index 6f9d085..0000000 --- a/arch/mips/gt64120/wrppmc/serial.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Registration of WRPPMC UART platform device. - * - * Copyright (C) 2007 Yoichi Yuasa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include - -#include - -static struct resource wrppmc_uart_resource[] __initdata = { - { - .start = WRPPMC_UART16550_BASE, - .end = WRPPMC_UART16550_BASE + 7, - .flags = IORESOURCE_MEM, - }, - { - .start = WRPPMC_UART16550_IRQ, - .end = WRPPMC_UART16550_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct plat_serial8250_port wrppmc_serial8250_port[] = { - { - .irq = WRPPMC_UART16550_IRQ, - .uartclk = WRPPMC_UART16550_CLOCK, - .iotype = UPIO_MEM, - .flags = UPF_IOREMAP | UPF_SKIP_TEST, - .mapbase = WRPPMC_UART16550_BASE, - }, - {}, -}; - -static __init int wrppmc_uart_add(void) -{ - struct platform_device *pdev; - int retval; - - pdev = platform_device_alloc("serial8250", -1); - if (!pdev) - return -ENOMEM; - - pdev->id = PLAT8250_DEV_PLATFORM; - pdev->dev.platform_data = wrppmc_serial8250_port; - - retval = platform_device_add_resources(pdev, wrppmc_uart_resource, - ARRAY_SIZE(wrppmc_uart_resource)); - if (retval) - goto err_free_device; - - retval = platform_device_add(pdev); - if (retval) - goto err_free_device; - - return 0; - -err_free_device: - platform_device_put(pdev); - - return retval; -} -device_initcall(wrppmc_uart_add); diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c deleted file mode 100644 index ca65c84..0000000 --- a/arch/mips/gt64120/wrppmc/setup.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * setup.c: Setup pointers to hardware dependent routines. - * - * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -unsigned long gt64120_base = KSEG1ADDR(0x14000000); - -#ifdef WRPPMC_EARLY_DEBUG - -static volatile unsigned char * wrppmc_led = \ - (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); - -/* - * PPMC LED control register: - * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) - * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) - * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) - */ -void wrppmc_led_on(int mask) -{ - unsigned char value = *wrppmc_led; - - value &= (0xF8 | mask); - *wrppmc_led = value; -} - -/* If mask = 0, turn off all LEDs */ -void wrppmc_led_off(int mask) -{ - unsigned char value = *wrppmc_led; - - value |= (0x7 & mask); - *wrppmc_led = value; -} - -/* - * We assume that bootloader has initialized UART16550 correctly - */ -void __init wrppmc_early_putc(char ch) -{ - static volatile unsigned char *wrppmc_uart = \ - (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); - unsigned char value; - - /* Wait until Transmit-Holding-Register is empty */ - while (1) { - value = *(wrppmc_uart + 5); - if (value & 0x20) - break; - } - - *wrppmc_uart = ch; -} - -void __init wrppmc_early_printk(const char *fmt, ...) -{ - static char pbuf[256] = {'\0', }; - char *ch = pbuf; - va_list args; - unsigned int i; - - memset(pbuf, 0, 256); - va_start(args, fmt); - i = vsprintf(pbuf, fmt, args); - va_end(args); - - /* Print the string */ - while (*ch != '\0') { - wrppmc_early_putc(*ch); - /* if print '\n', also print '\r' */ - if (*ch++ == '\n') - wrppmc_early_putc('\r'); - } -} -#endif /* WRPPMC_EARLY_DEBUG */ - -void __init prom_free_prom_memory(void) -{ -} - -void __init plat_mem_setup(void) -{ - extern void wrppmc_machine_restart(char *command); - extern void wrppmc_machine_halt(void); - - _machine_restart = wrppmc_machine_restart; - _machine_halt = wrppmc_machine_halt; - pm_power_off = wrppmc_machine_halt; - - /* This makes the operations of 'in/out[bwl]' to the - * physical address ( < KSEG0) can work via KSEG1 - */ - set_io_port_base(KSEG1); -} - -const char *get_system_type(void) -{ - return "Wind River PPMC (GT64120)"; -} - -/* - * Initializes basic routines and structures pointers, memory size (as - * given by the bios and saves the command line. - */ -void __init prom_init(void) -{ - add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); - add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); - - wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", - WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); -} diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c deleted file mode 100644 index 668dbd5..0000000 --- a/arch/mips/gt64120/wrppmc/time.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * time.c: MIPS CPU Count/Compare timer hookup - * - * Author: Mark.Zhan, - * - * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006, Wind River System Inc. - */ -#include -#include -#include - -#include -#include - -#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ - -/* - * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect - * - * NOTE: We disable all GT64120 timers, and use MIPS processor internal - * timer as the source of kernel clock tick. - */ -void __init plat_time_init(void) -{ - /* Disable GT64120 timers */ - GT_WRITE(GT_TC_CONTROL_OFS, 0x00); - GT_WRITE(GT_TC0_OFS, 0x00); - GT_WRITE(GT_TC1_OFS, 0x00); - GT_WRITE(GT_TC2_OFS, 0x00); - GT_WRITE(GT_TC3_OFS, 0x00); - - /* Use MIPS compare/count internal timer */ - mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; -} diff --git a/arch/mips/include/asm/arch_hweight.h b/arch/mips/include/asm/arch_hweight.h new file mode 100644 index 0000000..712a744 --- /dev/null +++ b/arch/mips/include/asm/arch_hweight.h @@ -0,0 +1,38 @@ +/* + * 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. + * + */ +#ifndef _ASM_ARCH_HWEIGHT_H +#define _ASM_ARCH_HWEIGHT_H + +#ifdef ARCH_HAS_USABLE_BUILTIN_POPCOUNT + +#include + +static inline unsigned int __arch_hweight32(unsigned int w) +{ + return __builtin_popcount(w); +} + +static inline unsigned int __arch_hweight16(unsigned int w) +{ + return __builtin_popcount(w & 0xffff); +} + +static inline unsigned int __arch_hweight8(unsigned int w) +{ + return __builtin_popcount(w & 0xff); +} + +static inline unsigned long __arch_hweight64(__u64 w) +{ + return __builtin_popcountll(w); +} + +#else +#include +#endif + +#endif /* _ASM_ARCH_HWEIGHT_H */ diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 9255cfb..b0ce7ca 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -700,7 +700,10 @@ static inline int ffs(int word) #ifdef __KERNEL__ #include -#include + +#include +#include + #include #include #include 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/break.h b/arch/mips/include/asm/break.h index 44437ed..9161e68 100644 --- a/arch/mips/include/asm/break.h +++ b/arch/mips/include/asm/break.h @@ -30,6 +30,8 @@ #define BRK_BUG 512 /* Used by BUG() */ #define BRK_KDB 513 /* Used in KDB_ENTER() */ #define BRK_MEMU 514 /* Used by FPU emulator */ +#define BRK_KPROBE_BP 515 /* Kprobe break */ +#define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */ #define BRK_MULOVF 1023 /* Multiply overflow */ #endif /* __ASM_BREAK_H */ diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index 256ad2c..8f99c11 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h @@ -62,6 +62,8 @@ * RM7000-specific cacheops */ #define Page_Invalidate_T 0x16 +#define Index_Store_Tag_T 0x0a +#define Index_Load_Tag_T 0x06 /* * R10000-specific cacheops diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h index 6b04c98..2cb2f0c 100644 --- a/arch/mips/include/asm/cop2.h +++ b/arch/mips/include/asm/cop2.h @@ -9,6 +9,8 @@ #ifndef __ASM_COP2_H #define __ASM_COP2_H +#include + enum cu2_ops { CU2_EXCEPTION, CU2_LWC2_OP, @@ -20,4 +22,14 @@ enum cu2_ops { extern int register_cu2_notifier(struct notifier_block *nb); extern int cu2_notifier_call_chain(unsigned long val, void *v); +#define cu2_notifier(fn, pri) \ +({ \ + static struct notifier_block fn##_nb __cpuinitdata = { \ + .notifier_call = fn, \ + .priority = pri \ + }; \ + \ + register_cu2_notifier(&fn##_nb); \ +}) + #endif /* __ASM_COP2_H */ diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index ac73ced..ca400f7 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -159,7 +159,8 @@ /* * MIPS32, MIPS64, VR5500, IDT32332, IDT32334 and maybe a few other - * pre-MIPS32/MIPS53 processors have CLO, CLZ. For 64-bit kernels + * pre-MIPS32/MIPS53 processors have CLO, CLZ. The IDT RC64574 is 64-bit and + * has CLO and CLZ but not DCLO nor DCLZ. For 64-bit kernels * cpu_has_clo_clz also indicates the availability of DCLO and DCLZ. */ # ifndef cpu_has_clo_clz diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a5acda4..b201a8f 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 */ @@ -219,6 +225,7 @@ enum cpu_type_enum { CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BCM3302, CPU_BCM4710, CPU_BCM6338, CPU_BCM6345, CPU_BCM6348, CPU_BCM6358, + CPU_JZRISC, /* * MIPS64 class processors diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index ea77a42..fd1d39e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -372,4 +372,9 @@ extern const char *__elf_platform; struct linux_binprm; extern int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp); + +struct mm_struct; +extern unsigned long arch_randomize_brk(struct mm_struct *mm); +#define arch_randomize_brk arch_randomize_brk + #endif /* _ASM_ELF_H */ diff --git a/arch/mips/include/asm/emma/emma2rh.h b/arch/mips/include/asm/emma/emma2rh.h index 2afb2fe..c1449d2 100644 --- a/arch/mips/include/asm/emma/emma2rh.h +++ b/arch/mips/include/asm/emma/emma2rh.h @@ -99,88 +99,22 @@ #define EMMA2RH_PCI_CONFIG_BASE EMMA2RH_PCI_IO_BASE #define EMMA2RH_PCI_CONFIG_SIZE EMMA2RH_PCI_IO_SIZE -#define NUM_CPU_IRQ 8 #define NUM_EMMA2RH_IRQ 96 -#define CPU_EMMA2RH_CASCADE 2 -#define CPU_IRQ_BASE MIPS_CPU_IRQ_BASE -#define EMMA2RH_IRQ_BASE (CPU_IRQ_BASE + NUM_CPU_IRQ) +#define EMMA2RH_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) /* * emma2rh irq defs */ -#define EMMA2RH_IRQ_INT0 (0 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT1 (1 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT2 (2 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT3 (3 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT4 (4 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT5 (5 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT6 (6 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT7 (7 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT8 (8 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT9 (9 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT10 (10 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT11 (11 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT12 (12 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT13 (13 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT14 (14 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT15 (15 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT16 (16 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT17 (17 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT18 (18 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT19 (19 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT20 (20 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT21 (21 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT22 (22 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT23 (23 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT24 (24 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT25 (25 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT26 (26 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT27 (27 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT28 (28 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT29 (29 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT30 (30 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT31 (31 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT32 (32 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT33 (33 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT34 (34 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT35 (35 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT36 (36 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT37 (37 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT38 (38 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT39 (39 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT40 (40 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT41 (41 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT42 (42 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT43 (43 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT44 (44 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT45 (45 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT46 (46 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT47 (47 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT48 (48 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT49 (49 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT50 (50 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT51 (51 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT52 (52 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT53 (53 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT54 (54 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT55 (55 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT56 (56 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT57 (57 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT58 (58 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT59 (59 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT60 (60 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT61 (61 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT62 (62 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT63 (63 + EMMA2RH_IRQ_BASE) - -#define EMMA2RH_IRQ_PFUR0 EMMA2RH_IRQ_INT49 -#define EMMA2RH_IRQ_PFUR1 EMMA2RH_IRQ_INT50 -#define EMMA2RH_IRQ_PFUR2 EMMA2RH_IRQ_INT51 -#define EMMA2RH_IRQ_PIIC0 EMMA2RH_IRQ_INT56 -#define EMMA2RH_IRQ_PIIC1 EMMA2RH_IRQ_INT57 -#define EMMA2RH_IRQ_PIIC2 EMMA2RH_IRQ_INT58 +#define EMMA2RH_IRQ_INT(n) (EMMA2RH_IRQ_BASE + (n)) + +#define EMMA2RH_IRQ_PFUR0 EMMA2RH_IRQ_INT(49) +#define EMMA2RH_IRQ_PFUR1 EMMA2RH_IRQ_INT(50) +#define EMMA2RH_IRQ_PFUR2 EMMA2RH_IRQ_INT(51) +#define EMMA2RH_IRQ_PIIC0 EMMA2RH_IRQ_INT(56) +#define EMMA2RH_IRQ_PIIC1 EMMA2RH_IRQ_INT(57) +#define EMMA2RH_IRQ_PIIC2 EMMA2RH_IRQ_INT(58) /* * EMMA2RH Register Access diff --git a/arch/mips/include/asm/emma/markeins.h b/arch/mips/include/asm/emma/markeins.h index 2618bf2..bf2d229 100644 --- a/arch/mips/include/asm/emma/markeins.h +++ b/arch/mips/include/asm/emma/markeins.h @@ -25,44 +25,13 @@ #define NUM_EMMA2RH_IRQ_SW 32 #define NUM_EMMA2RH_IRQ_GPIO 32 -#define EMMA2RH_SW_CASCADE (EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0) -#define EMMA2RH_GPIO_CASCADE (EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0) +#define EMMA2RH_SW_CASCADE (EMMA2RH_IRQ_INT(7) - EMMA2RH_IRQ_INT(0)) +#define EMMA2RH_GPIO_CASCADE (EMMA2RH_IRQ_INT(46) - EMMA2RH_IRQ_INT(0)) #define EMMA2RH_SW_IRQ_BASE (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ) #define EMMA2RH_GPIO_IRQ_BASE (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW) -#define EMMA2RH_SW_IRQ_INT0 (0+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT1 (1+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT2 (2+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT3 (3+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT4 (4+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT5 (5+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT6 (6+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT7 (7+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT8 (8+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT9 (9+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT10 (10+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT11 (11+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT12 (12+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT13 (13+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT14 (14+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT15 (15+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT16 (16+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT17 (17+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT18 (18+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT19 (19+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT20 (20+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT21 (21+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT22 (22+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT23 (23+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT24 (24+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT25 (25+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT26 (26+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT27 (27+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT28 (28+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT29 (29+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT30 (30+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT31 (31+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT(n) (EMMA2RH_SW_IRQ_BASE + (n)) #define MARKEINS_PCI_IRQ_INTA EMMA2RH_GPIO_IRQ_BASE+15 #define MARKEINS_PCI_IRQ_INTB EMMA2RH_GPIO_IRQ_BASE+16 diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 0eaf77f..4e33216 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -87,7 +87,7 @@ do { \ : "=r" (tmp)); \ } while (0) -#elif defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MACH_ALCHEMY) +#elif defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MIPS_ALCHEMY) /* * These are slightly complicated by the fact that we guarantee R1 kernels to @@ -138,7 +138,7 @@ do { \ __instruction_hazard(); \ } while (0) -#elif defined(CONFIG_MACH_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ +#elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \ defined(CONFIG_CPU_R5500) diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h index 6489f00..444ff71 100644 --- a/arch/mips/include/asm/inst.h +++ b/arch/mips/include/asm/inst.h @@ -247,6 +247,12 @@ struct ma_format { /* FPU multipy and add format (MIPS IV) */ unsigned int fmt : 2; }; +struct b_format { /* BREAK and SYSCALL */ + unsigned int opcode:6; + unsigned int code:20; + unsigned int func:6; +}; + #elif defined(__MIPSEL__) struct j_format { /* Jump format */ @@ -314,6 +320,12 @@ struct ma_format { /* FPU multipy and add format (MIPS IV) */ unsigned int opcode : 6; }; +struct b_format { /* BREAK and SYSCALL */ + unsigned int func:6; + unsigned int code:20; + unsigned int opcode:6; +}; + #else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ #error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" #endif @@ -328,7 +340,8 @@ union mips_instruction { struct c_format c_format; struct r_format r_format; struct f_format f_format; - struct ma_format ma_format; + struct ma_format ma_format; + struct b_format b_format; }; /* HACHACHAHCAHC ... */ diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h index 5bf62aa..6a9af5f 100644 --- a/arch/mips/include/asm/kdebug.h +++ b/arch/mips/include/asm/kdebug.h @@ -8,6 +8,9 @@ enum die_val { DIE_FP, DIE_TRAP, DIE_RI, + DIE_PAGE_FAULT, + DIE_BREAK, + DIE_SSTEPBP }; #endif /* _ASM_MIPS_KDEBUG_H */ diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h new file mode 100644 index 0000000..e6ea4d4 --- /dev/null +++ b/arch/mips/include/asm/kprobes.h @@ -0,0 +1,92 @@ +/* + * Kernel Probes (KProbes) + * include/asm-mips/kprobes.h + * + * Copyright 2006 Sony Corp. + * Copyright 2010 Cavium Networks + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_KPROBES_H +#define _ASM_KPROBES_H + +#include +#include + +#include +#include +#include + +#define __ARCH_WANT_KPROBES_INSN_SLOT + +struct kprobe; +struct pt_regs; + +typedef union mips_instruction kprobe_opcode_t; + +#define MAX_INSN_SIZE 2 + +#define flush_insn_slot(p) \ +do { \ + flush_icache_range((unsigned long)p->addr, \ + (unsigned long)p->addr + \ + (MAX_INSN_SIZE * sizeof(kprobe_opcode_t))); \ +} while (0) + + +#define kretprobe_blacklist_size 0 + +void arch_remove_kprobe(struct kprobe *p); + +/* Architecture specific copy of original instruction*/ +struct arch_specific_insn { + /* copy of the original instruction */ + kprobe_opcode_t *insn; +}; + +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long old_SR; + unsigned long saved_SR; + unsigned long saved_epc; +}; + +#define MAX_JPROBES_STACK_SIZE 128 +#define MAX_JPROBES_STACK_ADDR \ + (((unsigned long)current_thread_info()) + THREAD_SIZE - 32 - sizeof(struct pt_regs)) + +#define MIN_JPROBES_STACK_SIZE(ADDR) \ + ((((ADDR) + MAX_JPROBES_STACK_SIZE) > MAX_JPROBES_STACK_ADDR) \ + ? MAX_JPROBES_STACK_ADDR - (ADDR) \ + : MAX_JPROBES_STACK_SIZE) + + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_old_SR; + unsigned long kprobe_saved_SR; + unsigned long kprobe_saved_epc; + unsigned long jprobe_saved_sp; + struct pt_regs jprobe_saved_regs; + u8 jprobes_stack[MAX_JPROBES_STACK_SIZE]; + struct prev_kprobe prev_kprobe; +}; + +extern int kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data); + +#endif /* _ASM_KPROBES_H */ diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h b/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h index bae9b75..49dc8d9 100644 --- a/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h +++ b/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h @@ -9,6 +9,7 @@ struct au1000_eth_platform_data { int phy_addr; int phy_busid; int phy_irq; + char mac[6]; }; void __init au1xxx_override_eth_cfg(unsigned port, diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h index 0d8cc14..c58ebd8 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h @@ -31,6 +31,9 @@ struct nvram_header { #define NVRAM_MAX_VALUE_LEN 255 #define NVRAM_MAX_PARAM_LEN 64 +#define NVRAM_ERR_INV_PARAM -8 +#define NVRAM_ERR_ENVNOTFOUND -9 + extern int nvram_getenv(char *name, char *val, size_t val_len); #endif diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index bbf0540..b952fc7 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h @@ -61,21 +61,18 @@ #define kernel_uses_smartmips_rixi (cpu_data[0].cputype == CPU_CAVIUM_OCTEON_PLUS) -#define ARCH_HAS_READ_CURRENT_TIMER 1 #define ARCH_HAS_IRQ_PER_CPU 1 #define ARCH_HAS_SPINLOCK_PREFETCH 1 #define spin_lock_prefetch(x) prefetch(x) #define PREFETCH_STRIDE 128 -static inline int read_current_timer(unsigned long *result) -{ - asm volatile ("rdhwr %0,$31\n" -#ifndef CONFIG_64BIT - "\tsll %0, 0" +#ifdef __OCTEON__ +/* + * All gcc versions that have OCTEON support define __OCTEON__ and have the + * __builtin_popcount support. + */ +#define ARCH_HAS_USABLE_BUILTIN_POPCOUNT 1 #endif - : "=r" (*result)); - return 0; -} static inline int octeon_has_saa(void) { diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h index d32220f..6ddab8a 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h @@ -172,71 +172,9 @@ #ifdef CONFIG_PCI_MSI /* 152 - 215 represent the MSI interrupts 0-63 */ #define OCTEON_IRQ_MSI_BIT0 152 -#define OCTEON_IRQ_MSI_BIT1 153 -#define OCTEON_IRQ_MSI_BIT2 154 -#define OCTEON_IRQ_MSI_BIT3 155 -#define OCTEON_IRQ_MSI_BIT4 156 -#define OCTEON_IRQ_MSI_BIT5 157 -#define OCTEON_IRQ_MSI_BIT6 158 -#define OCTEON_IRQ_MSI_BIT7 159 -#define OCTEON_IRQ_MSI_BIT8 160 -#define OCTEON_IRQ_MSI_BIT9 161 -#define OCTEON_IRQ_MSI_BIT10 162 -#define OCTEON_IRQ_MSI_BIT11 163 -#define OCTEON_IRQ_MSI_BIT12 164 -#define OCTEON_IRQ_MSI_BIT13 165 -#define OCTEON_IRQ_MSI_BIT14 166 -#define OCTEON_IRQ_MSI_BIT15 167 -#define OCTEON_IRQ_MSI_BIT16 168 -#define OCTEON_IRQ_MSI_BIT17 169 -#define OCTEON_IRQ_MSI_BIT18 170 -#define OCTEON_IRQ_MSI_BIT19 171 -#define OCTEON_IRQ_MSI_BIT20 172 -#define OCTEON_IRQ_MSI_BIT21 173 -#define OCTEON_IRQ_MSI_BIT22 174 -#define OCTEON_IRQ_MSI_BIT23 175 -#define OCTEON_IRQ_MSI_BIT24 176 -#define OCTEON_IRQ_MSI_BIT25 177 -#define OCTEON_IRQ_MSI_BIT26 178 -#define OCTEON_IRQ_MSI_BIT27 179 -#define OCTEON_IRQ_MSI_BIT28 180 -#define OCTEON_IRQ_MSI_BIT29 181 -#define OCTEON_IRQ_MSI_BIT30 182 -#define OCTEON_IRQ_MSI_BIT31 183 -#define OCTEON_IRQ_MSI_BIT32 184 -#define OCTEON_IRQ_MSI_BIT33 185 -#define OCTEON_IRQ_MSI_BIT34 186 -#define OCTEON_IRQ_MSI_BIT35 187 -#define OCTEON_IRQ_MSI_BIT36 188 -#define OCTEON_IRQ_MSI_BIT37 189 -#define OCTEON_IRQ_MSI_BIT38 190 -#define OCTEON_IRQ_MSI_BIT39 191 -#define OCTEON_IRQ_MSI_BIT40 192 -#define OCTEON_IRQ_MSI_BIT41 193 -#define OCTEON_IRQ_MSI_BIT42 194 -#define OCTEON_IRQ_MSI_BIT43 195 -#define OCTEON_IRQ_MSI_BIT44 196 -#define OCTEON_IRQ_MSI_BIT45 197 -#define OCTEON_IRQ_MSI_BIT46 198 -#define OCTEON_IRQ_MSI_BIT47 199 -#define OCTEON_IRQ_MSI_BIT48 200 -#define OCTEON_IRQ_MSI_BIT49 201 -#define OCTEON_IRQ_MSI_BIT50 202 -#define OCTEON_IRQ_MSI_BIT51 203 -#define OCTEON_IRQ_MSI_BIT52 204 -#define OCTEON_IRQ_MSI_BIT53 205 -#define OCTEON_IRQ_MSI_BIT54 206 -#define OCTEON_IRQ_MSI_BIT55 207 -#define OCTEON_IRQ_MSI_BIT56 208 -#define OCTEON_IRQ_MSI_BIT57 209 -#define OCTEON_IRQ_MSI_BIT58 210 -#define OCTEON_IRQ_MSI_BIT59 211 -#define OCTEON_IRQ_MSI_BIT60 212 -#define OCTEON_IRQ_MSI_BIT61 213 -#define OCTEON_IRQ_MSI_BIT62 214 -#define OCTEON_IRQ_MSI_BIT63 215 +#define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255) -#define OCTEON_IRQ_LAST 216 +#define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) #else #define OCTEON_IRQ_LAST 152 #endif 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..f373186 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/base.h @@ -0,0 +1,26 @@ +#ifndef __ASM_MACH_JZ4740_BASE_H__ +#define __ASM_MACH_JZ4740_BASE_H__ + +#define JZ4740_CPM_BASE_ADDR 0x10000000 +#define JZ4740_INTC_BASE_ADDR 0x10001000 +#define JZ4740_WDT_BASE_ADDR 0x10002000 +#define JZ4740_TCU_BASE_ADDR 0x10002010 +#define JZ4740_RTC_BASE_ADDR 0x10003000 +#define JZ4740_GPIO_BASE_ADDR 0x10010000 +#define JZ4740_AIC_BASE_ADDR 0x10020000 +#define JZ4740_MSC_BASE_ADDR 0x10021000 +#define JZ4740_UART0_BASE_ADDR 0x10030000 +#define JZ4740_UART1_BASE_ADDR 0x10031000 +#define JZ4740_I2C_BASE_ADDR 0x10042000 +#define JZ4740_SSI_BASE_ADDR 0x10043000 +#define JZ4740_SADC_BASE_ADDR 0x10070000 +#define JZ4740_EMC_BASE_ADDR 0x13010000 +#define JZ4740_DMAC_BASE_ADDR 0x13020000 +#define JZ4740_UHC_BASE_ADDR 0x13030000 +#define JZ4740_UDC_BASE_ADDR 0x13040000 +#define JZ4740_LCD_BASE_ADDR 0x13050000 +#define JZ4740_SLCD_BASE_ADDR 0x13050000 +#define JZ4740_CIM_BASE_ADDR 0x13060000 +#define JZ4740_IPU_BASE_ADDR 0x13080000 + +#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..1b7408d --- /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/cpu-feature-overrides.h b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h new file mode 100644 index 0000000..d12e5c6 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h @@ -0,0 +1,51 @@ +/* + * 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. + * + */ +#ifndef __ASM_MACH_JZ4740_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_JZ4740_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 0 +#define cpu_has_watch 1 +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 +#define kernel_uses_llsc 1 +#define cpu_has_vtag_icache 1 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_pindexed_dcache 0 +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 + +#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..a3be121 --- /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_32BIT = 0, + JZ4740_DMA_WIDTH_8BIT = 1, + JZ4740_DMA_WIDTH_16BIT = 2, +}; + +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..7b74703 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/gpio.h @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * 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_LCD_CLS JZ_GPIO_PORTB(17) +#define JZ_GPIO_LCD_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_LCD_CLS JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_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..a865c98 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/irq.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * 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) (JZ4740_IRQ(32) + (X)) + +#define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x)) +#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x)) + +#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(176) + +#define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6) + +#endif diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_fb.h b/arch/mips/include/asm/mach-jz4740/jz4740_fb.h new file mode 100644 index 0000000..6a50e6f --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/jz4740_fb.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009, 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_MACH_JZ4740_JZ4740_FB_H__ +#define __ASM_MACH_JZ4740_JZ4740_FB_H__ + +#include + +enum jz4740_fb_lcd_type { + JZ_LCD_TYPE_GENERIC_16_BIT = 0, + JZ_LCD_TYPE_GENERIC_18_BIT = 0 | (1 << 4), + JZ_LCD_TYPE_SPECIAL_TFT_1 = 1, + JZ_LCD_TYPE_SPECIAL_TFT_2 = 2, + JZ_LCD_TYPE_SPECIAL_TFT_3 = 3, + JZ_LCD_TYPE_NON_INTERLACED_CCIR656 = 5, + JZ_LCD_TYPE_INTERLACED_CCIR656 = 7, + JZ_LCD_TYPE_SINGLE_COLOR_STN = 8, + JZ_LCD_TYPE_SINGLE_MONOCHROME_STN = 9, + JZ_LCD_TYPE_DUAL_COLOR_STN = 10, + JZ_LCD_TYPE_DUAL_MONOCHROME_STN = 11, + JZ_LCD_TYPE_8BIT_SERIAL = 12, +}; + +#define JZ4740_FB_SPECIAL_TFT_CONFIG(start, stop) (((start) << 16) | (stop)) + +/* +* width: width of the lcd display in mm +* height: height of the lcd display in mm +* num_modes: size of modes +* modes: list of valid video modes +* bpp: bits per pixel for the lcd +* lcd_type: lcd type +*/ + +struct jz4740_fb_platform_data { + unsigned int width; + unsigned int height; + + size_t num_modes; + struct fb_videomode *modes; + + unsigned int bpp; + enum jz4740_fb_lcd_type lcd_type; + + struct { + uint32_t spl; + uint32_t cls; + uint32_t ps; + uint32_t rev; + } special_tft_config; + + unsigned pixclk_falling_edge:1; + unsigned date_enable_active_low:1; +}; + +#endif diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_mmc.h b/arch/mips/include/asm/mach-jz4740/jz4740_mmc.h new file mode 100644 index 0000000..8543f43 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/jz4740_mmc.h @@ -0,0 +1,15 @@ +#ifndef __LINUX_MMC_JZ4740_MMC +#define __LINUX_MMC_JZ4740_MMC + +struct jz4740_mmc_platform_data { + int gpio_power; + int gpio_card_detect; + int gpio_read_only; + unsigned card_detect_active_low:1; + unsigned read_only_active_low:1; + unsigned power_active_low:1; + + unsigned data_1bit:1; +}; + +#endif diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h new file mode 100644 index 0000000..bb5b9a4 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC NAND controller driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __ASM_MACH_JZ4740_JZ4740_NAND_H__ +#define __ASM_MACH_JZ4740_JZ4740_NAND_H__ + +#include +#include + +struct jz_nand_platform_data { + int num_partitions; + struct mtd_partition *partitions; + + struct nand_ecclayout *ecc_layout; + + unsigned int busy_gpio; + + void (*ident_callback)(struct platform_device *, struct nand_chip *, + struct mtd_partition **, int *num_partitions); +}; + +#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..8987a76 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * 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_udc_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_pcm_device; +extern struct platform_device jz4740_codec_device; +extern struct platform_device jz4740_adc_device; + +void jz4740_serial_device_register(void); + +#endif 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..9baa03c --- /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/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index fcdbe3a..cb6985f 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -45,7 +45,6 @@ static inline void prom_init_uart_base(void) /* irq operation functions */ extern void bonito_irqdispatch(void); extern void __init bonito_irq_init(void); -extern void __init set_irq_trigger_mode(void); extern void __init mach_init_irq(void); extern void mach_irq_dispatch(unsigned int pending); extern int mach_i8259_irq(void); @@ -63,6 +62,14 @@ extern int mach_i8259_irq(void); #define LOONGSON_IRQ_BASE 32 #define LOONGSON2_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */ +#include +static inline void do_perfcnt_IRQ(void) +{ +#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) + do_IRQ(LOONGSON2_PERFCNT_IRQ); +#endif +} + #define LOONGSON_FLASH_BASE 0x1c000000 #define LOONGSON_FLASH_SIZE 0x02000000 /* 32M */ #define LOONGSON_FLASH_TOP (LOONGSON_FLASH_BASE+LOONGSON_FLASH_SIZE-1) diff --git a/arch/mips/include/asm/mach-pb1x00/pb1550.h b/arch/mips/include/asm/mach-pb1x00/pb1550.h index 5879641..fc4d766 100644 --- a/arch/mips/include/asm/mach-pb1x00/pb1550.h +++ b/arch/mips/include/asm/mach-pb1x00/pb1550.h @@ -40,14 +40,6 @@ #define SMBUS_PSC_BASE PSC2_BASE_ADDR #define I2S_PSC_BASE PSC3_BASE_ADDR -#if defined(CONFIG_MTD_PB1550_BOOT) && defined(CONFIG_MTD_PB1550_USER) -#define PB1550_BOTH_BANKS -#elif defined(CONFIG_MTD_PB1550_BOOT) && !defined(CONFIG_MTD_PB1550_USER) -#define PB1550_BOOT_ONLY -#elif !defined(CONFIG_MTD_PB1550_BOOT) && defined(CONFIG_MTD_PB1550_USER) -#define PB1550_USER_ONLY -#endif - /* * Timing values as described in databook, * ns value stripped of * lower 2 bits. diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h index bcad43a..c7077a6 100644 --- a/arch/mips/include/asm/mach-powertv/asic.h +++ b/arch/mips/include/asm/mach-powertv/asic.h @@ -20,6 +20,7 @@ #define _ASM_MACH_POWERTV_ASIC_H #include +#include #include #define DVR_CAPABLE (1<<0) @@ -40,19 +41,23 @@ enum family_type { FAMILY_8600VZB, FAMILY_1500VZE, FAMILY_1500VZF, + FAMILY_8700, FAMILIES }; /* Register maps for each ASIC */ extern const struct register_map calliope_register_map; extern const struct register_map cronus_register_map; +extern const struct register_map gaia_register_map; extern const struct register_map zeus_register_map; extern struct resource dvr_cronus_resources[]; +extern struct resource dvr_gaia_resources[]; extern struct resource dvr_zeus_resources[]; extern struct resource non_dvr_calliope_resources[]; extern struct resource non_dvr_cronus_resources[]; extern struct resource non_dvr_cronuslite_resources[]; +extern struct resource non_dvr_gaia_resources[]; extern struct resource non_dvr_vz_calliope_resources[]; extern struct resource non_dvr_vze_calliope_resources[]; extern struct resource non_dvr_vzf_calliope_resources[]; @@ -67,16 +72,24 @@ extern int platform_supports_ffs(void); extern int platform_supports_pcie(void); extern int platform_supports_display(void); extern void configure_platform(void); -extern void platform_configure_usb_ehci(void); -extern void platform_unconfigure_usb_ehci(void); -extern void platform_configure_usb_ohci(void); -extern void platform_unconfigure_usb_ohci(void); /* Platform Resources */ #define ASIC_RESOURCE_GET_EXISTS 1 extern struct resource *asic_resource_get(const char *name); extern void platform_release_memory(void *baddr, int size); +/* USB configuration */ +struct usb_hcd; /* Forward reference */ +extern void platform_configure_usb_ehci(void); +extern void platform_unconfigure_usb_ehci(void); +extern void platform_configure_usb_ohci(void); +extern void platform_unconfigure_usb_ohci(void); + +/* Resource for ASIC registers */ +extern struct resource asic_resource; +extern int platform_usb_devices_init(struct platform_device **echi_dev, + struct platform_device **ohci_dev); + /* Reboot Cause */ extern void set_reboot_cause(char code, unsigned int data, unsigned int data2); extern void set_locked_reboot_cause(char code, unsigned int data, diff --git a/arch/mips/include/asm/mach-powertv/asic_reg_map.h b/arch/mips/include/asm/mach-powertv/asic_reg_map.h index 6f26cb0..20348e8 100644 --- a/arch/mips/include/asm/mach-powertv/asic_reg_map.h +++ b/arch/mips/include/asm/mach-powertv/asic_reg_map.h @@ -64,7 +64,7 @@ REGISTER_MAP_ELEMENT(int_level_0_1) REGISTER_MAP_ELEMENT(int_level_0_0) REGISTER_MAP_ELEMENT(int_docsis_en) REGISTER_MAP_ELEMENT(mips_pll_setup) -REGISTER_MAP_ELEMENT(usb_fs) +REGISTER_MAP_ELEMENT(fs432x4b4_usb_ctl) REGISTER_MAP_ELEMENT(test_bus) REGISTER_MAP_ELEMENT(crt_spare) REGISTER_MAP_ELEMENT(usb2_ohci_int_mask) diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h index 1e11236..deecb26 100644 --- a/arch/mips/include/asm/mach-powertv/asic_regs.h +++ b/arch/mips/include/asm/mach-powertv/asic_regs.h @@ -27,7 +27,8 @@ enum asic_type { ASIC_CALLIOPE, ASIC_CRONUS, ASIC_CRONUSLITE, - ASICS + ASIC_GAIA, + ASICS /* Number of supported ASICs */ }; /* hardcoded values read from Chip Version registers */ @@ -37,6 +38,7 @@ enum asic_type { #define NAND_FLASH_BASE 0x03000000 #define CALLIOPE_IO_BASE 0x08000000 +#define GAIA_IO_BASE 0x09000000 #define CRONUS_IO_BASE 0x09000000 #define ZEUS_IO_BASE 0x09000000 @@ -99,6 +101,7 @@ static inline void register_map_virtualize(struct register_map *map) } extern struct register_map _asic_register_map; +extern unsigned long asic_phy_base; /* * Macros to interface to registers through their ioremapped address diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h index 5b8d5eb..f76029c 100644 --- a/arch/mips/include/asm/mach-powertv/dma-coherence.h +++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h @@ -65,21 +65,21 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) { if (is_kseg2(addr)) - return phys_to_bus(virt_to_phys_from_pte(addr)); + return phys_to_dma(virt_to_phys_from_pte(addr)); else - return phys_to_bus(virt_to_phys(addr)); + return phys_to_dma(virt_to_phys(addr)); } static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) { - return phys_to_bus(page_to_phys(page)); + return phys_to_dma(page_to_phys(page)); } static inline unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) { - return bus_to_phys(dma_addr); + return dma_to_phys(dma_addr); } static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h index e6276d5..076f2ee 100644 --- a/arch/mips/include/asm/mach-powertv/ioremap.h +++ b/arch/mips/include/asm/mach-powertv/ioremap.h @@ -10,64 +10,101 @@ #define __ASM_MACH_POWERTV_IOREMAP_H #include +#include +#include -#define LOW_MEM_BOUNDARY_PHYS 0x20000000 -#define LOW_MEM_BOUNDARY_MASK (~(LOW_MEM_BOUNDARY_PHYS - 1)) +#include +#include + +/* We're going to mess with bits, so get sizes */ +#define IOR_BPC 8 /* Bits per char */ +#define IOR_PHYS_BITS (IOR_BPC * sizeof(phys_addr_t)) +#define IOR_DMA_BITS (IOR_BPC * sizeof(dma_addr_t)) /* - * The bus addresses are different than the physical addresses that - * the processor sees by an offset. This offset varies by ASIC - * version. Define a variable to hold the offset and some macros to - * make the conversion simpler. */ -extern unsigned long phys_to_bus_offset; - -#ifdef CONFIG_HIGHMEM -#define MEM_GAP_PHYS 0x60000000 + * Define the granularity of physical/DMA mapping in terms of the number + * of bits that defines the offset within a grain. These will be the + * least significant bits of the address. The rest of a physical or DMA + * address will be used to index into an appropriate table to find the + * offset to add to the address to yield the corresponding DMA or physical + * address, respectively. + */ +#define IOR_LSBITS 22 /* Bits in a grain */ + /* - * TODO: We will use the hard code for conversion between physical and - * bus until the bootloader releases their device tree to us. + * Compute the number of most significant address bits after removing those + * used for the offset within a grain and then compute the number of table + * entries for the conversion. */ -#define phys_to_bus(x) (((x) < LOW_MEM_BOUNDARY_PHYS) ? \ - ((x) + phys_to_bus_offset) : (x)) -#define bus_to_phys(x) (((x) < MEM_GAP_PHYS_ADDR) ? \ - ((x) - phys_to_bus_offset) : (x)) -#else -#define phys_to_bus(x) ((x) + phys_to_bus_offset) -#define bus_to_phys(x) ((x) - phys_to_bus_offset) -#endif +#define IOR_PHYS_MSBITS (IOR_PHYS_BITS - IOR_LSBITS) +#define IOR_NUM_PHYS_TO_DMA ((phys_addr_t) 1 << IOR_PHYS_MSBITS) + +#define IOR_DMA_MSBITS (IOR_DMA_BITS - IOR_LSBITS) +#define IOR_NUM_DMA_TO_PHYS ((dma_addr_t) 1 << IOR_DMA_MSBITS) /* - * Determine whether the address we are given is for an ASIC device - * Params: addr Address to check - * Returns: Zero if the address is not for ASIC devices, non-zero - * if it is. + * Define data structures used as elements in the arrays for the conversion + * between physical and DMA addresses. We do some slightly fancy math to + * compute the width of the offset element of the conversion tables so + * that we can have the smallest conversion tables. Next, round up the + * sizes to the next higher power of two, i.e. the offset element will have + * 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any + * bits. Finally, we compute a shift value that puts the most significant + * bits of the offset into the most significant bits of the offset element. + * This makes it more efficient on processors without barrel shifters and + * easier to see the values if the conversion table is dumped in binary. */ -static inline int asic_is_device_addr(phys_t addr) +#define _IOR_OFFSET_WIDTH(n) (1 << order_base_2(n)) +#define IOR_OFFSET_WIDTH(n) \ + (_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n)) + +#define IOR_PHYS_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS) +#define IOR_PHYS_SHIFT (IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS) + +#define IOR_DMA_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_DMA_MSBITS) +#define IOR_DMA_SHIFT (IOR_DMA_BITS - IOR_DMA_OFFSET_BITS) + +struct ior_phys_to_dma { + dma_addr_t offset:IOR_DMA_OFFSET_BITS __packed + __aligned((IOR_DMA_OFFSET_BITS / IOR_BPC)); +}; + +struct ior_dma_to_phys { + dma_addr_t offset:IOR_PHYS_OFFSET_BITS __packed + __aligned((IOR_PHYS_OFFSET_BITS / IOR_BPC)); +}; + +extern struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA]; +extern struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS]; + +static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys) { - return !((phys_t)addr & (phys_t) LOW_MEM_BOUNDARY_MASK); + return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset; } -/* - * Determine whether the address we are given is external RAM mappable - * into KSEG1. - * Params: addr Address to check - * Returns: Zero if the address is not for external RAM and - */ -static inline int asic_is_lowmem_ram_addr(phys_t addr) +static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma) { - /* - * The RAM always starts at the following address in the processor's - * physical address space - */ - static const phys_t phys_ram_base = 0x10000000; - phys_t bus_ram_base; + return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset; +} - bus_ram_base = phys_to_bus_offset + phys_ram_base; +/* These are not portable and should not be used in drivers. Drivers should + * be using ioremap() and friends to map physical addreses to virtual + * addresses and dma_map*() and friends to map virtual addresses into DMA + * addresses and back. + */ +static inline dma_addr_t phys_to_dma(phys_addr_t phys) +{ + return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT); +} - return addr >= bus_ram_base && - addr < (bus_ram_base + (LOW_MEM_BOUNDARY_PHYS - phys_ram_base)); +static inline phys_addr_t dma_to_phys(dma_addr_t dma) +{ + return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT); } +extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias, + dma_addr_t size); + /* * Allow physical addresses to be fixed up to help peripherals located * outside the low 32-bit range -- generic pass-through version. @@ -77,10 +114,50 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) return phys_addr; } -static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, +/* + * Handle the special case of addresses the area aliased into the first + * 512 MiB of the processor's physical address space. These turn into either + * kseg0 or kseg1 addresses, depending on flags. + */ +static inline void __iomem *plat_ioremap(phys_t start, unsigned long size, unsigned long flags) { - return NULL; + phys_addr_t start_offset; + void __iomem *result = NULL; + + /* Start by checking to see whether this is an aliased address */ + start_offset = _dma_to_phys_offset_raw(start); + + /* + * If: + * o the memory is aliased into the first 512 MiB, and + * o the start and end are in the same RAM bank, and + * o we don't have a zero size or wrap around, and + * o we are supposed to create an uncached mapping, + * handle this is a kseg0 or kseg1 address + */ + if (start_offset != 0) { + phys_addr_t last; + dma_addr_t dma_to_phys_offset; + + last = start + size - 1; + dma_to_phys_offset = + _dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT; + + if (dma_to_phys_offset == start_offset && + size != 0 && start <= last) { + phys_t adjusted_start; + adjusted_start = start + start_offset; + if (flags == _CACHE_UNCACHED) + result = (void __iomem *) (unsigned long) + CKSEG1ADDR(adjusted_start); + else + result = (void __iomem *) (unsigned long) + CKSEG0ADDR(adjusted_start); + } + } + + return result; } static inline int plat_iounmap(const volatile void __iomem *addr) diff --git a/arch/mips/include/asm/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h index 913ff19..b74caf6 100644 --- a/arch/mips/include/asm/mach-tx49xx/kmalloc.h +++ b/arch/mips/include/asm/mach-tx49xx/kmalloc.h @@ -1,8 +1,6 @@ #ifndef __ASM_MACH_TX49XX_KMALLOC_H #define __ASM_MACH_TX49XX_KMALLOC_H -/* - * All happy, no need to define ARCH_KMALLOC_MINALIGN - */ +#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES #endif /* __ASM_MACH_TX49XX_KMALLOC_H */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index c6e3c93..335474c 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -408,6 +408,7 @@ #define STATUSB_IP15 7 #define STATUSF_IP15 (_ULCAST_(1) << 7) #define ST0_CH 0x00040000 +#define ST0_NMI 0x00080000 #define ST0_SR 0x00100000 #define ST0_TS 0x00200000 #define ST0_BEV 0x00400000 diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index ca6214b..917a6c4 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -50,6 +50,7 @@ extern void octeon_crypto_disable(struct octeon_cop2_state *state, extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task); extern void octeon_init_cvmcount(void); +extern void octeon_setup_delays(void); #define OCTEON_ARGV_MAX_ARGS 64 #define OCTOEN_SERIAL_LEN 20 @@ -253,4 +254,6 @@ static inline uint32_t octeon_npi_read32(uint64_t address) extern struct cvmx_bootinfo *octeon_bootinfo; +extern uint64_t octeon_bootloader_entry_addr; + #endif /* __ASM_OCTEON_OCTEON_H */ diff --git a/arch/mips/include/asm/octeon/pci-octeon.h b/arch/mips/include/asm/octeon/pci-octeon.h index 6ac5d3e..ece7804 100644 --- a/arch/mips/include/asm/octeon/pci-octeon.h +++ b/arch/mips/include/asm/octeon/pci-octeon.h @@ -15,6 +15,19 @@ #define PCI_CONFIG_SPACE_DELAY 10000 /* + * The physical memory base mapped by BAR1. 256MB at the end of the + * first 4GB. + */ +#define CVMX_PCIE_BAR1_PHYS_BASE ((1ull << 32) - (1ull << 28)) +#define CVMX_PCIE_BAR1_PHYS_SIZE (1ull << 28) + +/* + * The RC base of BAR1. gen1 has a 39-bit BAR2, gen2 has 41-bit BAR2, + * place BAR1 so it is the same for both. + */ +#define CVMX_PCIE_BAR1_RC_BASE (1ull << 41) + +/* * pcibios_map_irq() is defined inside pci-octeon.c. All it does is * call the Octeon specific version pointed to by this variable. This * function needs to change for PCI or PCIe based hosts. diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 3beea14..576397c 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -140,6 +140,11 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? 15 : 14; } +#ifdef CONFIG_CPU_CAVIUM_OCTEON +/* MSI arch hook for OCTEON */ +#define arch_setup_msi_irqs arch_setup_msi_irqs +#endif + extern int pci_probe_only; extern char * (*pcibios_plat_setup)(char *str); diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h index 54ef1a9..786d82d 100644 --- a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h @@ -124,10 +124,6 @@ extern void prom_meminit(void); extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); -#ifdef CONFIG_MTD_PMC_MSP_RAMROOT -extern bool get_ramroot(void **start, unsigned long *size); -#endif - extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr); extern unsigned long get_deviceid(void); extern char identify_enet(unsigned long interface_num); diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 5d33b72..0d629bb 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -34,6 +34,11 @@ extern void (*cpu_wait)(void); extern unsigned int vced_count, vcei_count; /* + * MIPS does have an arch_pick_mmap_layout() + */ +#define HAVE_ARCH_PICK_MMAP_LAYOUT 1 + +/* * A special page (the vdso) is mapped into all processes at the very * top of the virtual memory space. */ @@ -52,6 +57,9 @@ extern unsigned int vced_count, vcei_count; * space during mmap's. */ #define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE)) + +#define TASK_IS_32BIT_ADDR 1 + #endif #ifdef CONFIG_64BIT @@ -77,6 +85,9 @@ extern unsigned int vced_count, vcei_count; PAGE_ALIGN(TASK_SIZE32 / 3) : PAGE_ALIGN(TASK_SIZE / 3)) #define TASK_SIZE_OF(tsk) \ (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) + +#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR) + #endif #ifdef __KERNEL__ @@ -218,7 +229,6 @@ struct thread_struct { unsigned long cp0_badvaddr; /* Last user fault */ unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ unsigned long error_code; - unsigned long trap_no; unsigned long irix_trampoline; /* Wheee... */ unsigned long irix_oldctx; #ifdef CONFIG_CPU_CAVIUM_OCTEON @@ -290,7 +300,6 @@ struct thread_struct { .cp0_badvaddr = 0, \ .cp0_baduaddr = 0, \ .error_code = 0, \ - .trap_no = 0, \ .irix_trampoline = 0, \ .irix_oldctx = 0, \ /* \ diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index cdc6a46..9f1b8db 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -137,6 +137,7 @@ extern int ptrace_set_watch_regs(struct task_struct *child, */ #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) +#define regs_return_value(_regs) ((_regs)->regs[2]) #define instruction_pointer(regs) ((regs)->cp0_epc) #define profile_pc(regs) instruction_pointer(regs) diff --git a/arch/mips/include/asm/sn/agent.h b/arch/mips/include/asm/sn/agent.h index ac4ea85..dc81114 100644 --- a/arch/mips/include/asm/sn/agent.h +++ b/arch/mips/include/asm/sn/agent.h @@ -11,7 +11,6 @@ #ifndef _ASM_SGI_SN_AGENT_H #define _ASM_SGI_SN_AGENT_H -#include #include #include diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 697e40c..892062d 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -10,44 +10,55 @@ #include +#ifdef CONFIG_EXPORT_UASM +#include +#define __uasminit +#define __uasminitdata +#define UASM_EXPORT_SYMBOL(sym) EXPORT_SYMBOL(sym) +#else +#define __uasminit __cpuinit +#define __uasminitdata __cpuinitdata +#define UASM_EXPORT_SYMBOL(sym) +#endif + #define Ip_u1u2u3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u1u2(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u1u2s3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2s3u1(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) #define Ip_u2u1s3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2u1msbu3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ unsigned int d) #define Ip_u1u2(op) \ -void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) +void __uasminit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) #define Ip_u1s2(op) \ -void __cpuinit uasm_i##op(u32 **buf, unsigned int a, signed int b) +void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b) -#define Ip_u1(op) void __cpuinit uasm_i##op(u32 **buf, unsigned int a) +#define Ip_u1(op) void __uasminit uasm_i##op(u32 **buf, unsigned int a) -#define Ip_0(op) void __cpuinit uasm_i##op(u32 **buf) +#define Ip_0(op) void __uasminit uasm_i##op(u32 **buf) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); @@ -71,6 +82,7 @@ Ip_u2u1u3(_dsra); Ip_u2u1u3(_dsrl); Ip_u2u1u3(_dsrl32); Ip_u2u1u3(_drotr); +Ip_u2u1u3(_drotr32); Ip_u3u1u2(_dsubu); Ip_0(_eret); Ip_u1(_j); @@ -111,7 +123,7 @@ struct uasm_label { int lab; }; -void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); +void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); #ifdef CONFIG_64BIT int uasm_in_compat_space_p(long addr); #endif @@ -121,7 +133,7 @@ void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); void UASM_i_LA(u32 **buf, unsigned int rs, long addr); #define UASM_L_LA(lb) \ -static inline void __cpuinit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ +static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ { \ uasm_build_label(lab, addr, label##lb); \ } @@ -176,6 +188,15 @@ static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1, uasm_i_dsrl32(p, a1, a2, a3 - 32); } +static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, + unsigned int a2, unsigned int a3) +{ + if (a3 < 32) + uasm_i_drotr(p, a1, a2, a3); + else + uasm_i_drotr32(p, a1, a2, a3 - 32); +} + static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { @@ -213,3 +234,7 @@ void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid); +void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid); diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile index 5aee0c2..dd9d99b 100644 --- a/arch/mips/jazz/Makefile +++ b/arch/mips/jazz/Makefile @@ -3,5 +3,3 @@ # obj-y := irq.o jazzdma.o reset.o setup.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/jazz/Platform b/arch/mips/jazz/Platform new file mode 100644 index 0000000..3373788 --- /dev/null +++ b/arch/mips/jazz/Platform @@ -0,0 +1,6 @@ +# +# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. +# +platform-$(CONFIG_MACH_JAZZ) += jazz/ +cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz +load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig new file mode 100644 index 0000000..3e7141f --- /dev/null +++ b/arch/mips/jz4740/Kconfig @@ -0,0 +1,12 @@ +choice + prompt "Machine type" + depends on MACH_JZ4740 + default JZ4740_QI_LB60 + +config JZ4740_QI_LB60 + bool "Qi Hardware Ben NanoNote" + +endchoice + +config HAVE_PWM + bool diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile new file mode 100644 index 0000000..a604eae --- /dev/null +++ b/arch/mips/jz4740/Makefile @@ -0,0 +1,20 @@ +# +# 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 serial.o + +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 + +EXTRA_CFLAGS += -Werror -Wall diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform new file mode 100644 index 0000000..6a97230 --- /dev/null +++ b/arch/mips/jz4740/Platform @@ -0,0 +1,3 @@ +core-$(CONFIG_MACH_JZ4740) += arch/mips/jz4740/ +cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 +load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c new file mode 100644 index 0000000..5742bb4 --- /dev/null +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -0,0 +1,471 @@ +/* + * linux/arch/mips/jz4740/board-qi_lb60.c + * + * QI_LB60 board support + * + * Copyright (c) 2009 Qi Hardware inc., + * Author: Xiangfu Liu + * Copyright 2010, Lars-Petrer Clausen + * + * 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 "clock.h" + +static bool is_avt2; + +/* GPIOs */ +#define QI_LB60_GPIO_SD_CD JZ_GPIO_PORTD(0) +#define QI_LB60_GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(2) + +#define QI_LB60_GPIO_KEYOUT(x) (JZ_GPIO_PORTC(10) + (x)) +#define QI_LB60_GPIO_KEYIN(x) (JZ_GPIO_PORTD(18) + (x)) +#define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26) + +/* 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 } + }, +}; + +/* Early prototypes of the QI LB60 had only 1GB of NAND. + * In order to support these devices aswell the partition and ecc layout is + * initalized depending on the NAND size */ +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 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 */ + + KEY(7, 0, KEY_LEFTSHIFT), /* S58 */ + KEY(7, 1, KEY_LEFTALT), /* S59 */ + KEY(7, 2, KEY_QI_FN), /* S60 */ +}; + +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[] = { + QI_LB60_GPIO_KEYOUT(0), + QI_LB60_GPIO_KEYOUT(1), + QI_LB60_GPIO_KEYOUT(2), + QI_LB60_GPIO_KEYOUT(3), + QI_LB60_GPIO_KEYOUT(4), + QI_LB60_GPIO_KEYOUT(5), + QI_LB60_GPIO_KEYOUT(6), + QI_LB60_GPIO_KEYOUT(7), +}; + +static const unsigned int qi_lb60_keypad_rows[] = { + QI_LB60_GPIO_KEYIN(0), + QI_LB60_GPIO_KEYIN(1), + QI_LB60_GPIO_KEYIN(2), + QI_LB60_GPIO_KEYIN(3), + QI_LB60_GPIO_KEYIN(4), + QI_LB60_GPIO_KEYIN(5), + QI_LB60_GPIO_KEYIN(7), + QI_LB60_GPIO_KEYIN8, +}; + +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 = "ili8960", + .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 = JZ_GPIO_PORTC(27), + .gpio_charge_active_low = 1, + .info = { + .name = "battery", + .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, + .voltage_max_design = 4200000, + .voltage_min_design = 3600000, + }, +}; + +/* GPIO Key: power */ +static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = { + [0] = { + .code = KEY_POWER, + .gpio = JZ_GPIO_PORTD(29), + .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 = QI_LB60_GPIO_SD_CD, + .gpio_read_only = -1, + .gpio_power = QI_LB60_GPIO_SD_VCC_EN_N, + .power_active_low = 1, +}; + +/* OHCI */ +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, + } +}; + +/* beeper */ +static struct platform_device qi_lb60_pwm_beeper = { + .name = "pwm-beeper", + .id = -1, + .dev = { + .platform_data = (void *)4, + }, +}; + +static struct platform_device *jz_platform_devices[] __initdata = { + &jz4740_udc_device, + &jz4740_mmc_device, + &jz4740_nand_device, + &qi_lb60_keypad, + &spigpio_device, + &jz4740_framebuffer_device, + &jz4740_pcm_device, + &jz4740_i2s_device, + &jz4740_codec_device, + &jz4740_rtc_device, + &jz4740_adc_device, + &qi_lb60_gpio_keys, + &qi_lb60_pwm_beeper, +}; + +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(QI_LB60_GPIO_SD_VCC_EN_N); + jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD); +} + +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_adc_device.dev.platform_data = &qi_lb60_battery_pdata; + jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; + + jz4740_serial_device_register(); + + 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, +}; + +static __init int board_avt2(char *str) +{ + qi_lb60_mmc_pdata.card_detect_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 %s setup\n", + is_avt2 ? "AVT2" : "LB60"); + + board_gpio_setup(); + + if (qi_lb60_init_platform_devices()) + panic("Failed to initalize platform devices\n"); + + return 0; +} +arch_initcall(qi_lb60_board_setup); diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c new file mode 100644 index 0000000..330a0f2 --- /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..118a8a5 --- /dev/null +++ b/arch/mips/jz4740/clock.c @@ -0,0 +1,924 @@ +/* + * 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) / n) * m) / 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_pll_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, +}; + +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[] = { + [0] = { + .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, + }, + [1] = { + .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, + }, + [2] = { + .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, + }, + [3] = { + .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, + }, + [4] = { + .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[] = { + [0] = { + .name = "udc", + .parent = &jz_clk_ext.clk, + .ops = &jz_clk_udc_ops, + }, + [1] = { + .name = "uart0", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_UART0, + .ops = &jz_clk_simple_ops, + }, + [2] = { + .name = "uart1", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_UART1, + .ops = &jz_clk_simple_ops, + }, + [3] = { + .name = "dma", + .parent = &jz_clk_high_speed_peripheral.clk, + .gate_bit = JZ_CLOCK_GATE_UART0, + .ops = &jz_clk_simple_ops, + }, + [4] = { + .name = "ipu", + .parent = &jz_clk_high_speed_peripheral.clk, + .gate_bit = JZ_CLOCK_GATE_IPU, + .ops = &jz_clk_simple_ops, + }, + [5] = { + .name = "adc", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_ADC, + .ops = &jz_clk_simple_ops, + }, + [6] = { + .name = "i2c", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_I2C, + .ops = &jz_clk_simple_ops, + }, + [7] = { + .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; + int enabled; + + if (!clk->ops->set_parent) + return -EINVAL; + + enabled = clk_is_enabled(clk); + if (enabled) + clk_disable(clk); + ret = clk->ops->set_parent(clk, parent); + if (enabled) + 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(-ENXIO); +} +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_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); +} + +static int jz4740_clock_init(void) +{ + uint32_t val; + + jz_clock_base = ioremap(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; +} +arch_initcall(jz4740_clock_init); diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h new file mode 100644 index 0000000..5d07499 --- /dev/null +++ b/arch/mips/jz4740/clock.h @@ -0,0 +1,76 @@ +/* + * 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 __MIPS_JZ4740_CLOCK_H__ +#define __MIPS_JZ4740_CLOCK_H__ + +#include + +struct jz4740_clock_board_data { + unsigned long ext_rate; + unsigned long rtc_rate; +}; + +extern struct jz4740_clock_board_data jz4740_clock_bdata; + +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..5ebe75a --- /dev/null +++ b/arch/mips/jz4740/dma.c @@ -0,0 +1,289 @@ +/* + * 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; + + 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; + + jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd); + jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), 0); + 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_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE, + JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC | + JZ_DMA_STATUS_CTRL_ENABLE); + + jz4740_dma_write_mask(JZ_REG_DMA_CTRL, + JZ_DMA_CTRL_ENABLE, + JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE); +} +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; +} + +static int jz4740_dma_init(void) +{ + unsigned int ret; + + jz4740_dma_base = ioremap(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..38f60f3 --- /dev/null +++ b/arch/mips/jz4740/gpio.c @@ -0,0 +1,604 @@ +/* + * 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 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); + +int gpio_to_irq(unsigned gpio) +{ + return JZ4740_IRQ_GPIO(0) + gpio; +} +EXPORT_SYMBOL_GPL(gpio_to_irq); + +int irq_to_gpio(unsigned irq) +{ + return irq - JZ4740_IRQ_GPIO(0); +} +EXPORT_SYMBOL_GPL(irq_to_gpio); + +#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f) + +static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq) +{ + uint32_t value; + void __iomem *reg; + uint32_t mask = IRQ_TO_BIT(irq); + + if (!(chip->edge_trigger_both & mask)) + return; + + reg = chip->base; + + value = readl(chip->base + JZ_REG_GPIO_PIN); + if (value & mask) + reg += JZ_REG_GPIO_DIRECTION_CLEAR; + else + reg += JZ_REG_GPIO_DIRECTION_SET; + + writel(mask, 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); + + if (!flag) + return; + + gpio_irq = __fls(flag); + + jz_gpio_check_trigger_both(chip, irq); + + 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) +{ + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + writel(IRQ_TO_BIT(irq), chip->base + 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) +{ + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + + jz_gpio_check_trigger_both(chip, 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(chip->base + 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; +} + +/* + * 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(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_data(irq, chip); + set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq); + } + + return 0; +} + +static int __init jz4740_gpio_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; +} +arch_initcall(jz4740_gpio_init); + +#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..7d33ff8 --- /dev/null +++ b/arch/mips/jz4740/irq.c @@ -0,0 +1,167 @@ +/* + * 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 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, + .mask_ack = intc_irq_mask, + .unmask = intc_irq_unmask, + .set_wake = intc_irq_set_wake, +}; + +static irqreturn_t jz4740_cascade(int irq, void *data) +{ + uint32_t irq_reg; + + irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); + + if (irq_reg) + generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE); + + return IRQ_HANDLED; +} + +static struct irqaction jz4740_cascade_action = { + .handler = jz4740_cascade, + .name = "JZ4740 cascade interrupt", +}; + +void __init arch_init_irq(void) +{ + int i; + mips_cpu_irq_init(); + + jz_intc_base = ioremap(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..56b5ead --- /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..95bc2b5 --- /dev/null +++ b/arch/mips/jz4740/platform.c @@ -0,0 +1,291 @@ +/* + * 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 +#include + +#include +#include + +#include "serial.h" +#include "clock.h" + +/* OHCI controller */ +static struct resource jz4740_usb_ohci_resources[] = { + { + .start = JZ4740_UHC_BASE_ADDR, + .end = JZ4740_UHC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_UHC, + .end = JZ4740_IRQ_UHC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device jz4740_usb_ohci_device = { + .name = "jz4740-ohci", + .id = -1, + .dev = { + .dma_mask = &jz4740_usb_ohci_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(jz4740_usb_ohci_resources), + .resource = jz4740_usb_ohci_resources, +}; + +/* UDC (USB gadget controller) */ +static struct resource jz4740_usb_gdt_resources[] = { + { + .start = JZ4740_UDC_BASE_ADDR, + .end = JZ4740_UDC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_UDC, + .end = JZ4740_IRQ_UDC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device jz4740_udc_device = { + .name = "jz-udc", + .id = -1, + .dev = { + .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(jz4740_usb_gdt_resources), + .resource = jz4740_usb_gdt_resources, +}; + +/* MMC/SD controller */ +static struct resource jz4740_mmc_resources[] = { + { + .start = JZ4740_MSC_BASE_ADDR, + .end = JZ4740_MSC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_MSC, + .end = JZ4740_IRQ_MSC, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device jz4740_mmc_device = { + .name = "jz4740-mmc", + .id = 0, + .dev = { + .dma_mask = &jz4740_mmc_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(jz4740_mmc_resources), + .resource = jz4740_mmc_resources, +}; + +/* RTC controller */ +static struct resource jz4740_rtc_resources[] = { + { + .start = JZ4740_RTC_BASE_ADDR, + .end = JZ4740_RTC_BASE_ADDR + 0x38 - 1, + .flags = IORESOURCE_MEM, + }, + { + .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[] = { + { + .start = JZ4740_I2C_BASE_ADDR, + .end = JZ4740_I2C_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_I2C, + .end = JZ4740_IRQ_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device jz4740_i2c_device = { + .name = "jz4740-i2c", + .id = 0, + .num_resources = ARRAY_SIZE(jz4740_i2c_resources), + .resource = jz4740_i2c_resources, +}; + +/* NAND controller */ +static struct resource jz4740_nand_resources[] = { + { + .name = "mmio", + .start = JZ4740_EMC_BASE_ADDR, + .end = JZ4740_EMC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "bank", + .start = 0x18000000, + .end = 0x180C0000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device jz4740_nand_device = { + .name = "jz4740-nand", + .num_resources = ARRAY_SIZE(jz4740_nand_resources), + .resource = jz4740_nand_resources, +}; + +/* LCD controller */ +static struct resource jz4740_framebuffer_resources[] = { + { + .start = JZ4740_LCD_BASE_ADDR, + .end = JZ4740_LCD_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +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_framebuffer_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +/* I2S controller */ +static struct resource jz4740_i2s_resources[] = { + { + .start = JZ4740_AIC_BASE_ADDR, + .end = 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, +}; + +/* PCM */ +struct platform_device jz4740_pcm_device = { + .name = "jz4740-pcm", + .id = -1, +}; + +/* Codec */ +static struct resource jz4740_codec_resources[] = { + { + .start = JZ4740_AIC_BASE_ADDR + 0x80, + .end = 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, +}; + +/* ADC controller */ +static struct resource jz4740_adc_resources[] = { + { + .start = JZ4740_SADC_BASE_ADDR, + .end = JZ4740_SADC_BASE_ADDR + 0x30, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_SADC, + .end = JZ4740_IRQ_SADC, + .flags = IORESOURCE_IRQ, + }, + { + .start = JZ4740_IRQ_ADC_BASE, + .end = JZ4740_IRQ_ADC_BASE, + .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, +}; + +/* Serial */ +#define JZ4740_UART_DATA(_id) \ + { \ + .flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \ + .iotype = UPIO_MEM, \ + .regshift = 2, \ + .serial_out = jz4740_serial_out, \ + .type = PORT_16550, \ + .mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \ + .irq = JZ4740_IRQ_UART ## _id, \ + } + +static struct plat_serial8250_port jz4740_uart_data[] = { + JZ4740_UART_DATA(0), + JZ4740_UART_DATA(1), + {}, +}; + +static struct platform_device jz4740_uart_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = jz4740_uart_data, + }, +}; + +void jz4740_serial_device_register(void) +{ + struct plat_serial8250_port *p; + + for (p = jz4740_uart_data; p->flags != 0; ++p) + p->uartclk = jz4740_clock_bdata.ext_rate; + + platform_device_register(&jz4740_uart_device); +} diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c new file mode 100644 index 0000000..a999458 --- /dev/null +++ b/arch/mips/jz4740/pm.c @@ -0,0 +1,56 @@ +/* + * 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 jz4740_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 jz4740_pm_ops = { + .valid = suspend_valid_only_mem, + .enter = jz4740_pm_enter, +}; + +static int __init jz4740_pm_init(void) +{ + suspend_set_ops(&jz4740_pm_ops); + return 0; + +} +late_initcall(jz4740_pm_init); diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c new file mode 100644 index 0000000..cfeac15 --- /dev/null +++ b/arch/mips/jz4740/prom.c @@ -0,0 +1,68 @@ +/* + * 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(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 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..a26a6fa --- /dev/null +++ b/arch/mips/jz4740/pwm.c @@ -0,0 +1,177 @@ +/* + * 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 (id < 2 || id > 7 || !jz4740_pwm_clk) + return ERR_PTR(-ENODEV); + + 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(KERN_ERR "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 = period - tmp; + + if (duty >= period) + duty = period - 1; + + is_enabled = jz4740_timer_is_enabled(id); + if (is_enabled) + pwm_disable(pwm); + + 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_SRC_EXT | + JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN; + + jz4740_timer_set_ctrl(id, ctrl); + + if (is_enabled) + pwm_enable(pwm); + + return 0; +} + +int pwm_enable(struct pwm_device *pwm) +{ + uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id); + + ctrl |= JZ_TIMER_CTRL_PWM_ENABLE; + jz4740_timer_set_ctrl(pwm->id, ctrl); + jz4740_timer_enable(pwm->id); + + return 0; +} + +void pwm_disable(struct pwm_device *pwm) +{ + uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id); + + ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE; + jz4740_timer_disable(pwm->id); + jz4740_timer_set_ctrl(pwm->id, ctrl); +} + +static int __init jz4740_pwm_init(void) +{ + int ret = 0; + + jz4740_pwm_clk = clk_get(NULL, "ext"); + + if (IS_ERR(jz4740_pwm_clk)) { + ret = PTR_ERR(jz4740_pwm_clk); + jz4740_pwm_clk = NULL; + } + + return ret; +} +subsys_initcall(jz4740_pwm_init); diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c new file mode 100644 index 0000000..5f1fb95 --- /dev/null +++ b/arch/mips/jz4740/reset.c @@ -0,0 +1,79 @@ +/* + * 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 + +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(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(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..5202ab4 --- /dev/null +++ b/arch/mips/jz4740/reset.h @@ -0,0 +1,6 @@ +#ifndef __MIPS_JZ4740_RESET_H__ +#define __MIPS_JZ4740_RESET_H__ + +extern void jz4740_reset_init(void); + +#endif diff --git a/arch/mips/jz4740/serial.c b/arch/mips/jz4740/serial.c new file mode 100644 index 0000000..d23de45 --- /dev/null +++ b/arch/mips/jz4740/serial.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 serial 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 + +void jz4740_serial_out(struct uart_port *p, int offset, int value) +{ + switch (offset) { + case UART_FCR: + value |= 0x10; /* Enable uart module */ + break; + case UART_IER: + value |= (value & 0x4) << 2; + break; + default: + break; + } + writeb(value, p->membase + (offset << p->regshift)); +} diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h new file mode 100644 index 0000000..b9fe3ad --- /dev/null +++ b/arch/mips/jz4740/serial.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 serial 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_SERIAL_H__ + +void jz4740_serial_out(struct uart_port *p, int offset, int value); + +#endif diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c new file mode 100644 index 0000000..6a9e14d --- /dev/null +++ b/arch/mips/jz4740/setup.c @@ -0,0 +1,29 @@ +/* + * 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 "reset.h" + +void __init plat_mem_setup(void) +{ + jz4740_reset_init(); +} + +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..fe01678 --- /dev/null +++ b/arch/mips/jz4740/time.c @@ -0,0 +1,144 @@ +/* + * 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, + .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_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..b2c0151 --- /dev/null +++ b/arch/mips/jz4740/timer.c @@ -0,0 +1,48 @@ +/* + * 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(JZ4740_TCU_BASE_ADDR, 0x100); + + if (!jz4740_timer_base) + panic("Failed to ioremap timer registers"); + + /* Disable all timer clocks except for those used as system timers */ + writel(0x000100fc, jz4740_timer_base + JZ_REG_TIMER_STOP_SET); + + /* Timer irqs are unmasked by default, mask them */ + writel(0x00ff00ff, jz4740_timer_base + JZ_REG_TIMER_MASK_SET); +} diff --git a/arch/mips/jz4740/timer.h b/arch/mips/jz4740/timer.h new file mode 100644 index 0000000..fca3994 --- /dev/null +++ b/arch/mips/jz4740/timer.h @@ -0,0 +1,136 @@ +/* + * 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 0x0C +#define JZ_REG_TIMER_STOP_SET 0x1C +#define JZ_REG_TIMER_STOP_CLEAR 0x2C +#define JZ_REG_TIMER_ENABLE 0x00 +#define JZ_REG_TIMER_ENABLE_SET 0x04 +#define JZ_REG_TIMER_ENABLE_CLEAR 0x08 +#define JZ_REG_TIMER_FLAG 0x10 +#define JZ_REG_TIMER_FLAG_SET 0x14 +#define JZ_REG_TIMER_FLAG_CLEAR 0x18 +#define JZ_REG_TIMER_MASK 0x20 +#define JZ_REG_TIMER_MASK_SET 0x24 +#define JZ_REG_TIMER_MASK_CLEAR 0x28 + +#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30) +#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34) +#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38) +#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C) + +#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10) +#define JZ_TIMER_IRQ_FULL(x) BIT(x) + +#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN BIT(9) +#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)); +} + +static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer) +{ + return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer)); +} + +#endif diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 7a6ac50..06f8482 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o obj-$(CONFIG_IRQ_GIC) += irq-gic.o +obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-64.o obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o @@ -101,6 +102,4 @@ obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/ -EXTRA_CFLAGS += -Werror - CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index ca6c832..6b30fb2 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -126,7 +126,6 @@ void output_thread_defines(void) thread.cp0_baduaddr); OFFSET(THREAD_ECODE, task_struct, \ thread.error_code); - OFFSET(THREAD_TRAPNO, task_struct, thread.trap_no); OFFSET(THREAD_TRAMP, task_struct, \ thread.irix_trampoline); OFFSET(THREAD_OLDCTX, task_struct, \ diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 0b2450c..2a4d50f 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -163,7 +163,6 @@ int c0_compare_int_usable(void) int __cpuinit r4k_clockevent_init(void) { - uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq; @@ -188,9 +187,9 @@ int __cpuinit r4k_clockevent_init(void) cd->name = "MIPS"; cd->features = CLOCK_EVT_FEAT_ONESHOT; + clockevent_set_clock(cd, mips_hpt_frequency); + /* Calculate the min / max delta */ - cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); - cd->shift = 32; cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); cd->min_delta_ns = clockevent_delta2ns(0x300, cd); diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index 408d0a0..b8bb8ba 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -239,7 +239,7 @@ static inline void check_daddi(void) panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } -int daddiu_bug __cpuinitdata = -1; +int daddiu_bug = -1; static inline void check_daddiu(void) { diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 3562b85..b1b304e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -187,6 +187,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; @@ -760,6 +761,9 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c) ok = decode_config4(c); mips_probe_watch_registers(c); + + if (cpu_has_mips_r2) + c->core = read_c0_ebase() & 0x3ff; } static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) @@ -956,6 +960,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; @@ -994,6 +1014,9 @@ __cpuinit void cpu_probe(void) case PRID_COMP_CAVIUM: cpu_probe_cavium(c, cpu); break; + case PRID_COMP_INGENIC: + cpu_probe_ingenic(c, cpu); + break; } BUG_ON(!__cpu_name[cpu]); diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c new file mode 100644 index 0000000..ee28683 --- /dev/null +++ b/arch/mips/kernel/kprobes.c @@ -0,0 +1,557 @@ +/* + * Kernel Probes (KProbes) + * arch/mips/kernel/kprobes.c + * + * Copyright 2006 Sony Corp. + * Copyright 2010 Cavium Networks + * + * Some portions copied from the powerpc version. + * + * Copyright (C) IBM Corporation, 2002, 2004 + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +static const union mips_instruction breakpoint_insn = { + .b_format = { + .opcode = spec_op, + .code = BRK_KPROBE_BP, + .func = break_op + } +}; + +static const union mips_instruction breakpoint2_insn = { + .b_format = { + .opcode = spec_op, + .code = BRK_KPROBE_SSTEPBP, + .func = break_op + } +}; + +DEFINE_PER_CPU(struct kprobe *, current_kprobe); +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + +static int __kprobes insn_has_delayslot(union mips_instruction insn) +{ + switch (insn.i_format.opcode) { + + /* + * This group contains: + * jr and jalr are in r_format format. + */ + case spec_op: + switch (insn.r_format.func) { + case jr_op: + case jalr_op: + break; + default: + goto insn_ok; + } + + /* + * This group contains: + * bltz_op, bgez_op, bltzl_op, bgezl_op, + * bltzal_op, bgezal_op, bltzall_op, bgezall_op. + */ + case bcond_op: + + /* + * These are unconditional and in j_format. + */ + case jal_op: + case j_op: + + /* + * These are conditional and in i_format. + */ + case beq_op: + case beql_op: + case bne_op: + case bnel_op: + case blez_op: + case blezl_op: + case bgtz_op: + case bgtzl_op: + + /* + * These are the FPA/cp1 branch instructions. + */ + case cop1_op: + +#ifdef CONFIG_CPU_CAVIUM_OCTEON + case lwc2_op: /* This is bbit0 on Octeon */ + case ldc2_op: /* This is bbit032 on Octeon */ + case swc2_op: /* This is bbit1 on Octeon */ + case sdc2_op: /* This is bbit132 on Octeon */ +#endif + return 1; + default: + break; + } +insn_ok: + return 0; +} + +int __kprobes arch_prepare_kprobe(struct kprobe *p) +{ + union mips_instruction insn; + union mips_instruction prev_insn; + int ret = 0; + + prev_insn = p->addr[-1]; + insn = p->addr[0]; + + if (insn_has_delayslot(insn) || insn_has_delayslot(prev_insn)) { + pr_notice("Kprobes for branch and jump instructions are not supported\n"); + ret = -EINVAL; + goto out; + } + + /* insn: must be on special executable page on mips. */ + p->ainsn.insn = get_insn_slot(); + if (!p->ainsn.insn) { + ret = -ENOMEM; + goto out; + } + + /* + * In the kprobe->ainsn.insn[] array we store the original + * instruction at index zero and a break trap instruction at + * index one. + */ + + memcpy(&p->ainsn.insn[0], p->addr, sizeof(kprobe_opcode_t)); + p->ainsn.insn[1] = breakpoint2_insn; + p->opcode = *p->addr; + +out: + return ret; +} + +void __kprobes arch_arm_kprobe(struct kprobe *p) +{ + *p->addr = breakpoint_insn; + flush_insn_slot(p); +} + +void __kprobes arch_disarm_kprobe(struct kprobe *p) +{ + *p->addr = p->opcode; + flush_insn_slot(p); +} + +void __kprobes arch_remove_kprobe(struct kprobe *p) +{ + free_insn_slot(p->ainsn.insn, 0); +} + +static void save_previous_kprobe(struct kprobe_ctlblk *kcb) +{ + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.old_SR = kcb->kprobe_old_SR; + kcb->prev_kprobe.saved_SR = kcb->kprobe_saved_SR; + kcb->prev_kprobe.saved_epc = kcb->kprobe_saved_epc; +} + +static void restore_previous_kprobe(struct kprobe_ctlblk *kcb) +{ + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_old_SR = kcb->prev_kprobe.old_SR; + kcb->kprobe_saved_SR = kcb->prev_kprobe.saved_SR; + kcb->kprobe_saved_epc = kcb->prev_kprobe.saved_epc; +} + +static void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) +{ + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_SR = kcb->kprobe_old_SR = (regs->cp0_status & ST0_IE); + kcb->kprobe_saved_epc = regs->cp0_epc; +} + +static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) +{ + regs->cp0_status &= ~ST0_IE; + + /* single step inline if the instruction is a break */ + if (p->opcode.word == breakpoint_insn.word || + p->opcode.word == breakpoint2_insn.word) + regs->cp0_epc = (unsigned long)p->addr; + else + regs->cp0_epc = (unsigned long)&p->ainsn.insn[0]; +} + +static int __kprobes kprobe_handler(struct pt_regs *regs) +{ + struct kprobe *p; + int ret = 0; + kprobe_opcode_t *addr; + struct kprobe_ctlblk *kcb; + + addr = (kprobe_opcode_t *) regs->cp0_epc; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); + + /* Check we're not actually recursing */ + if (kprobe_running()) { + p = get_kprobe(addr); + if (p) { + if (kcb->kprobe_status == KPROBE_HIT_SS && + p->ainsn.insn->word == breakpoint_insn.word) { + regs->cp0_status &= ~ST0_IE; + regs->cp0_status |= kcb->kprobe_saved_SR; + goto no_kprobe; + } + /* + * We have reentered the kprobe_handler(), since + * another probe was hit while within the handler. + * We here save the original kprobes variables and + * just single step on the instruction of the new probe + * without calling any user handlers. + */ + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); + kprobes_inc_nmissed_count(p); + prepare_singlestep(p, regs); + kcb->kprobe_status = KPROBE_REENTER; + return 1; + } else { + if (addr->word != breakpoint_insn.word) { + /* + * The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + ret = 1; + goto no_kprobe; + } + p = __get_cpu_var(current_kprobe); + if (p->break_handler && p->break_handler(p, regs)) + goto ss_probe; + } + goto no_kprobe; + } + + p = get_kprobe(addr); + if (!p) { + if (addr->word != breakpoint_insn.word) { + /* + * The breakpoint instruction was removed right + * after we hit it. Another cpu has removed + * either a probepoint or a debugger breakpoint + * at this address. In either case, no further + * handling of this interrupt is appropriate. + */ + ret = 1; + } + /* Not one of ours: let kernel handle it */ + goto no_kprobe; + } + + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + + if (p->pre_handler && p->pre_handler(p, regs)) { + /* handler has already set things up, so skip ss setup */ + return 1; + } + +ss_probe: + prepare_singlestep(p, regs); + kcb->kprobe_status = KPROBE_HIT_SS; + return 1; + +no_kprobe: + preempt_enable_no_resched(); + return ret; + +} + +/* + * Called after single-stepping. p->addr is the address of the + * instruction whose first byte has been replaced by the "break 0" + * instruction. To avoid the SMP problems that can occur when we + * temporarily put back the original opcode to single-step, we + * single-stepped a copy of the instruction. The address of this + * copy is p->ainsn.insn. + * + * This function prepares to return from the post-single-step + * breakpoint trap. + */ +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, + struct kprobe_ctlblk *kcb) +{ + unsigned long orig_epc = kcb->kprobe_saved_epc; + regs->cp0_epc = orig_epc + 4; +} + +static inline int post_kprobe_handler(struct pt_regs *regs) +{ + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) + return 0; + + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); + } + + resume_execution(cur, regs, kcb); + + regs->cp0_status |= kcb->kprobe_saved_SR; + + /* Restore back the original saved kprobes variables and continue. */ + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); + goto out; + } + reset_current_kprobe(); +out: + preempt_enable_no_resched(); + + return 1; +} + +static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) +{ + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) + return 1; + + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + regs->cp0_status |= kcb->kprobe_old_SR; + + reset_current_kprobe(); + preempt_enable_no_resched(); + } + return 0; +} + +/* + * Wrapper routine for handling exceptions. + */ +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) +{ + + struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; + + switch (val) { + case DIE_BREAK: + if (kprobe_handler(args->regs)) + ret = NOTIFY_STOP; + break; + case DIE_SSTEPBP: + if (post_kprobe_handler(args->regs)) + ret = NOTIFY_STOP; + break; + + case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); + + if (kprobe_running() + && kprobe_fault_handler(args->regs, args->trapnr)) + ret = NOTIFY_STOP; + preempt_enable(); + break; + default: + break; + } + return ret; +} + +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + struct jprobe *jp = container_of(p, struct jprobe, kp); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + kcb->jprobe_saved_regs = *regs; + kcb->jprobe_saved_sp = regs->regs[29]; + + memcpy(kcb->jprobes_stack, (void *)kcb->jprobe_saved_sp, + MIN_JPROBES_STACK_SIZE(kcb->jprobe_saved_sp)); + + regs->cp0_epc = (unsigned long)(jp->entry); + + return 1; +} + +/* Defined in the inline asm below. */ +void jprobe_return_end(void); + +void __kprobes jprobe_return(void) +{ + /* Assembler quirk necessitates this '0,code' business. */ + asm volatile( + "break 0,%0\n\t" + ".globl jprobe_return_end\n" + "jprobe_return_end:\n" + : : "n" (BRK_KPROBE_BP) : "memory"); +} + +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +{ + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (regs->cp0_epc >= (unsigned long)jprobe_return && + regs->cp0_epc <= (unsigned long)jprobe_return_end) { + *regs = kcb->jprobe_saved_regs; + memcpy((void *)kcb->jprobe_saved_sp, kcb->jprobes_stack, + MIN_JPROBES_STACK_SIZE(kcb->jprobe_saved_sp)); + preempt_enable_no_resched(); + + return 1; + } + return 0; +} + +/* + * Function return probe trampoline: + * - init_kprobes() establishes a probepoint here + * - When the probed function returns, this probe causes the + * handlers to fire + */ +static void __used kretprobe_trampoline_holder(void) +{ + asm volatile( + ".set push\n\t" + /* Keep the assembler from reordering and placing JR here. */ + ".set noreorder\n\t" + "nop\n\t" + ".global kretprobe_trampoline\n" + "kretprobe_trampoline:\n\t" + "nop\n\t" + ".set pop" + : : : "memory"); +} + +void kretprobe_trampoline(void); + +void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + ri->ret_addr = (kprobe_opcode_t *) regs->regs[31]; + + /* Replace the return addr with trampoline addr */ + regs->regs[31] = (unsigned long)kretprobe_trampoline; +} + +/* + * Called when the probe at kretprobe trampoline is hit + */ +static int __kprobes trampoline_probe_handler(struct kprobe *p, + struct pt_regs *regs) +{ + struct kretprobe_instance *ri = NULL; + struct hlist_head *head, empty_rp; + struct hlist_node *node, *tmp; + unsigned long flags, orig_ret_address = 0; + unsigned long trampoline_address = (unsigned long)kretprobe_trampoline; + + INIT_HLIST_HEAD(&empty_rp); + kretprobe_hash_lock(current, &head, &flags); + + /* + * It is possible to have multiple instances associated with a given + * task either because an multiple functions in the call path + * have a return probe installed on them, and/or more than one return + * return probe was registered for a target function. + * + * We can handle this because: + * - instances are always inserted at the head of the list + * - when multiple return probes are registered for the same + * function, the first instance's ret_addr will point to the + * real return address, and all the rest will point to + * kretprobe_trampoline + */ + hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { + if (ri->task != current) + /* another task is sharing our hash bucket */ + continue; + + if (ri->rp && ri->rp->handler) + ri->rp->handler(ri, regs); + + orig_ret_address = (unsigned long)ri->ret_addr; + recycle_rp_inst(ri, &empty_rp); + + if (orig_ret_address != trampoline_address) + /* + * This is the real return address. Any other + * instances associated with this task are for + * other calls deeper on the call stack + */ + break; + } + + kretprobe_assert(ri, orig_ret_address, trampoline_address); + instruction_pointer(regs) = orig_ret_address; + + reset_current_kprobe(); + kretprobe_hash_unlock(current, &flags); + preempt_enable_no_resched(); + + hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { + hlist_del(&ri->hlist); + kfree(ri); + } + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) + */ + return 1; +} + +int __kprobes arch_trampoline_kprobe(struct kprobe *p) +{ + if (p->addr == (kprobe_opcode_t *)kretprobe_trampoline) + return 1; + + return 0; +} + +static struct kprobe trampoline_p = { + .addr = (kprobe_opcode_t *)kretprobe_trampoline, + .pre_handler = trampoline_probe_handler +}; + +int __init arch_init_kprobes(void) +{ + return register_kprobe(&trampoline_p); +} diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 6bfcb7a..4c968e7 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -165,12 +165,12 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) /* arg3: Get frame pointer of current stack */ #ifdef CONFIG_FRAME_POINTER - move a2, fp + move a2, fp #else /* ! CONFIG_FRAME_POINTER */ #ifdef CONFIG_64BIT - PTR_LA a2, PT_SIZE(sp) + PTR_LA a2, PT_SIZE(sp) #else - PTR_LA a2, (PT_SIZE+8)(sp) + PTR_LA a2, (PT_SIZE+8)(sp) #endif #endif diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index a4facee..a3d6613 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -400,22 +400,22 @@ EXPORT(sysn32_call_table) PTR sys_ioprio_set PTR sys_ioprio_get PTR compat_sys_utimensat - PTR compat_sys_signalfd /* 5280 */ + PTR compat_sys_signalfd /* 6280 */ PTR sys_ni_syscall PTR sys_eventfd PTR sys_fallocate PTR sys_timerfd_create - PTR compat_sys_timerfd_gettime /* 5285 */ + PTR compat_sys_timerfd_gettime /* 6285 */ PTR compat_sys_timerfd_settime PTR sys_signalfd4 PTR sys_eventfd2 PTR sys_epoll_create1 - PTR sys_dup3 /* 5290 */ + PTR sys_dup3 /* 6290 */ PTR sys_pipe2 PTR sys_inotify_init1 PTR sys_preadv PTR sys_pwritev - PTR compat_sys_rt_tgsigqueueinfo /* 5295 */ + PTR compat_sys_rt_tgsigqueueinfo /* 6295 */ PTR sys_perf_event_open PTR sys_accept4 PTR compat_sys_recvmmsg diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 6cdca19..383aeb9 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -47,8 +47,12 @@ #endif /* CONFIG_MIPS_MT_SMTC */ volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ + int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ +EXPORT_SYMBOL(__cpu_number_map); + int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ +EXPORT_SYMBOL(__cpu_logical_map); /* Number of TCs (or siblings in Intel speak) per CPU core */ int smp_num_siblings = 1; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a95dea5..cfeb2c1 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -975,8 +975,7 @@ void ipi_decode(struct smtc_ipi *pipi) ipi_call_interrupt(); break; default: - printk("Impossible SMTC IPI Argument 0x%x\n", - (int)arg_copy); + printk("Impossible SMTC IPI Argument %p\n", arg_copy); break; } break; diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index dd81b0f..58bab2e 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -116,7 +118,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, (!vmm || addr + len <= vmm->vm_start)) return addr; } - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); else @@ -134,6 +136,51 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, } } +void arch_pick_mmap_layout(struct mm_struct *mm) +{ + unsigned long random_factor = 0UL; + + if (current->flags & PF_RANDOMIZE) { + random_factor = get_random_int(); + random_factor = random_factor << PAGE_SHIFT; + if (TASK_IS_32BIT_ADDR) + random_factor &= 0xfffffful; + else + random_factor &= 0xffffffful; + } + + mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; +} + +static inline unsigned long brk_rnd(void) +{ + unsigned long rnd = get_random_int(); + + rnd = rnd << PAGE_SHIFT; + /* 8MB for 32bit, 256MB for 64bit */ + if (TASK_IS_32BIT_ADDR) + rnd = rnd & 0x7ffffful; + else + rnd = rnd & 0xffffffful; + + return rnd; +} + +unsigned long arch_randomize_brk(struct mm_struct *mm) +{ + unsigned long base = mm->brk; + unsigned long ret; + + ret = PAGE_ALIGN(base + brk_rnd()); + + if (ret < mm->brk) + return mm->brk; + + return ret; +} + SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8527808..03ec001 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -334,7 +335,7 @@ void show_regs(struct pt_regs *regs) __show_regs((struct pt_regs *)regs); } -void show_registers(const struct pt_regs *regs) +void show_registers(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); @@ -356,9 +357,14 @@ void show_registers(const struct pt_regs *regs) printk("\n"); } +static int regs_to_trapnr(struct pt_regs *regs) +{ + return (regs->cp0_cause >> 2) & 0x1f; +} + static DEFINE_SPINLOCK(die_lock); -void __noreturn die(const char * str, struct pt_regs * regs) +void __noreturn die(const char *str, struct pt_regs *regs) { static int die_counter; int sig = SIGSEGV; @@ -366,7 +372,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) unsigned long dvpret = dvpe(); #endif /* CONFIG_MIPS_MT_SMTC */ - notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0); + notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV); console_verbose(); spin_lock_irq(&die_lock); @@ -375,7 +381,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) mips_mt_regdump(dvpret); #endif /* CONFIG_MIPS_MT_SMTC */ - if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) + if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP) sig = 0; printk("%s[#%d]:\n", str, ++die_counter); @@ -449,7 +455,7 @@ asmlinkage void do_be(struct pt_regs *regs) printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", data ? "Data" : "Instruction", field, regs->cp0_epc, field, regs->regs[31]); - if (notify_die(DIE_OOPS, "bus error", regs, SIGBUS, 0, 0) + if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) == NOTIFY_STOP) return; @@ -650,7 +656,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { siginfo_t info; - if (notify_die(DIE_FP, "FP exception", regs, SIGFPE, 0, 0) + if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) return; die_if_kernel("FP exception in kernel code", regs); @@ -713,11 +719,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, char b[40]; #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP - if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) + if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) return; #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ - if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) + if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) return; /* @@ -783,6 +789,25 @@ asmlinkage void do_bp(struct pt_regs *regs) if (bcode >= (1 << 10)) bcode >>= 10; + /* + * notify the kprobe handlers, if instruction is likely to + * pertain to them. + */ + switch (bcode) { + case BRK_KPROBE_BP: + if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) + return; + else + break; + case BRK_KPROBE_SSTEPBP: + if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) + return; + else + break; + default: + break; + } + do_trap_or_bp(regs, bcode, "Break"); return; @@ -815,7 +840,7 @@ asmlinkage void do_ri(struct pt_regs *regs) unsigned int opcode = 0; int status = -1; - if (notify_die(DIE_RI, "RI Fault", regs, SIGSEGV, 0, 0) + if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) == NOTIFY_STOP) return; @@ -907,11 +932,6 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, return NOTIFY_OK; } -static struct notifier_block default_cu2_notifier = { - .notifier_call = default_cu2_call, - .priority = 0x80000000, /* Run last */ -}; - asmlinkage void do_cpu(struct pt_regs *regs) { unsigned int __user *epc; @@ -1734,5 +1754,5 @@ void __init trap_init(void) sort_extable(__start___dbe_table, __stop___dbe_table); - register_cu2_notifier(&default_cu2_notifier); + cu2_notifier(default_cu2_call, 0x80000000); /* Run last */ } diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile index 3379160..9cc4e4d 100644 --- a/arch/mips/lasat/Makefile +++ b/arch/mips/lasat/Makefile @@ -12,5 +12,3 @@ obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o clean: make -C image clean - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/lasat/Platform b/arch/mips/lasat/Platform new file mode 100644 index 0000000..7602528 --- /dev/null +++ b/arch/mips/lasat/Platform @@ -0,0 +1,7 @@ +# +# LASAT platforms +# +platform-$(CONFIG_LASAT) += lasat/ +cflags-$(CONFIG_LASAT) += \ + -I$(srctree)/arch/mips/include/asm/mach-lasat +load-$(CONFIG_LASAT) += 0xffffffff80000000 diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform new file mode 100644 index 0000000..29692e5 --- /dev/null +++ b/arch/mips/loongson/Platform @@ -0,0 +1,32 @@ +# +# Loongson Processors' Support +# + +# Only gcc >= 4.4 have Loongson specific support +cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2E) += \ + $(call cc-option,-march=loongson2e,-march=r4600) +cflags-$(CONFIG_CPU_LOONGSON2F) += \ + $(call cc-option,-march=loongson2f,-march=r4600) +# Enable the workarounds for Loongson2f +ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS + ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-nop,),) + $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-nop) + else + cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-nop + endif + ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-jump,),) + $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-jump) + else + cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-jump + endif +endif + +# +# Loongson Machines' Support +# + +platform-$(CONFIG_MACH_LOONGSON) += loongson/ +cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely +load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000 +load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000 diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile index 510d4cd..f12e640 100644 --- a/arch/mips/loongson/common/cs5536/Makefile +++ b/arch/mips/loongson/common/cs5536/Makefile @@ -9,5 +9,3 @@ obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \ # Enable cs5536 mfgpt Timer # obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson/common/irq.c index 20e7328..5897471 100644 --- a/arch/mips/loongson/common/irq.c +++ b/arch/mips/loongson/common/irq.c @@ -21,19 +21,16 @@ void bonito_irqdispatch(void) /* workaround the IO dma problem: let cpu looping to allow DMA finish */ int_status = LOONGSON_INTISR; - if (int_status & (1 << 10)) { - while (int_status & (1 << 10)) { - udelay(1); - int_status = LOONGSON_INTISR; - } + while (int_status & (1 << 10)) { + udelay(1); + int_status = LOONGSON_INTISR; } /* Get pending sources, masked by current enables */ int_status = LOONGSON_INTISR & LOONGSON_INTEN; - if (int_status != 0) { + if (int_status) { i = __ffs(int_status); - int_status &= ~(1 << i); do_IRQ(LOONGSON_IRQ_BASE + i); } } @@ -56,9 +53,6 @@ void __init arch_init_irq(void) */ clear_c0_status(ST0_IM | ST0_BEV); - /* setting irq trigger mode */ - set_irq_trigger_mode(); - /* no steer */ LOONGSON_INTSTEER = 0; diff --git a/arch/mips/loongson/fuloong-2e/Makefile b/arch/mips/loongson/fuloong-2e/Makefile index 3aba5fc..b762272 100644 --- a/arch/mips/loongson/fuloong-2e/Makefile +++ b/arch/mips/loongson/fuloong-2e/Makefile @@ -3,5 +3,3 @@ # obj-y += irq.o reset.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c index 320e937..d61a042 100644 --- a/arch/mips/loongson/fuloong-2e/irq.c +++ b/arch/mips/loongson/fuloong-2e/irq.c @@ -30,7 +30,7 @@ asmlinkage void mach_irq_dispatch(unsigned int pending) if (pending & CAUSEF_IP7) do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & CAUSEF_IP6) /* perf counter loverflow */ - do_IRQ(LOONGSON2_PERFCNT_IRQ); + do_perfcnt_IRQ(); else if (pending & CAUSEF_IP5) i8259_irqdispatch(); else if (pending & CAUSEF_IP2) @@ -44,13 +44,6 @@ static struct irqaction cascade_irqaction = { .name = "cascade", }; -void __init set_irq_trigger_mode(void) -{ - /* most bonito irq should be level triggered */ - LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR | - LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES; -} - void __init mach_init_irq(void) { /* init all controller @@ -59,6 +52,10 @@ void __init mach_init_irq(void) * 32-63 ------> bonito irq */ + /* most bonito irq should be level triggered */ + LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR | + LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES; + /* Sets the first-level interrupt dispatcher. */ mips_cpu_irq_init(); init_i8259_irqs(); diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index 1d8b4d2..081db10 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -19,7 +19,6 @@ #include #define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) /* cpu timer */ -#define LOONGSON_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */ #define LOONGSON_NORTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 6) /* bonito */ #define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 3) /* cpu serial port */ #define LOONGSON_SOUTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 2) /* i8259 */ @@ -79,9 +78,7 @@ void mach_irq_dispatch(unsigned int pending) if (pending & CAUSEF_IP7) do_IRQ(LOONGSON_TIMER_IRQ); else if (pending & CAUSEF_IP6) { /* North Bridge, Perf counter */ -#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) - do_IRQ(LOONGSON2_PERFCNT_IRQ); -#endif + do_perfcnt_IRQ(); bonito_irqdispatch(); } else if (pending & CAUSEF_IP3) /* CPU UART */ do_IRQ(LOONGSON_UART_IRQ); @@ -91,13 +88,6 @@ void mach_irq_dispatch(unsigned int pending) spurious_interrupt(); } -void __init set_irq_trigger_mode(void) -{ - /* setup cs5536 as high level trigger */ - LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; - LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); -} - static irqreturn_t ip6_action(int cpl, void *dev_id) { return IRQ_HANDLED; @@ -122,6 +112,10 @@ void __init mach_init_irq(void) * 32-63 ------> bonito irq */ + /* setup cs5536 as high level trigger */ + LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; + LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); + /* Sets the first-level interrupt dispatcher. */ mips_cpu_irq_init(); init_i8259_irqs(); diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index d547efd..9660723 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -10,4 +10,3 @@ obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c index 25861a4..a8570e5 100644 --- a/arch/mips/math-emu/dp_modf.c +++ b/arch/mips/math-emu/dp_modf.c @@ -29,7 +29,7 @@ /* modf function is always exact for a finite number */ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip) +ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp *ip) { COMPXDP; diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 77b2b7c..2447862 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -69,8 +69,7 @@ int ieee754dp_tint(ieee754dp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { residue = xm << (64 - DP_MBITS + xe); round = (residue >> 63) != 0; sticky = (residue << 1) != 0; diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index d71113e..0f07ec2 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -71,8 +71,7 @@ s64 ieee754dp_tlong(ieee754dp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { /* Shifting a u64 64 times does not work, * so we do it in two steps. Be aware that xe * may be -1 */ diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c index 4b1dbac..7656894 100644 --- a/arch/mips/math-emu/sp_modf.c +++ b/arch/mips/math-emu/sp_modf.c @@ -29,7 +29,7 @@ /* modf function is always exact for a finite number */ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip) +ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp *ip) { COMPXSP; diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 1d73d2a..352dc3a 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -72,8 +72,7 @@ int ieee754sp_tint(ieee754sp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { /* Shifting a u32 32 times does not work, * so we do it in two steps. Be aware that xe * may be -1 */ diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index 4be21aa..92cd9c5 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -71,8 +71,7 @@ s64 ieee754sp_tlong(ieee754sp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { residue = xm << (32 - SP_MBITS + xe); round = (residue >> 31) != 0; sticky = (residue << 1) != 0; diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile index 41b9657..01410a3 100644 --- a/arch/mips/mipssim/Makefile +++ b/arch/mips/mipssim/Makefile @@ -21,5 +21,3 @@ obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o obj-$(CONFIG_EARLY_PRINTK) += sim_console.o obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mipssim/Platform b/arch/mips/mipssim/Platform new file mode 100644 index 0000000..3df60b8 --- /dev/null +++ b/arch/mips/mipssim/Platform @@ -0,0 +1,6 @@ +# +# MIPS SIM +# +platform-$(CONFIG_MIPS_SIM) += mipssim/ +cflags-$(CONFIG_MIPS_SIM) += -I$(srctree)/arch/mips/include/asm/mach-mipssim +load-$(CONFIG_MIPS_SIM) += 0x80100000 diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index f0e4355..d679c77 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -34,5 +34,3 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index b78f7d9..783ad00 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -16,8 +16,8 @@ #include #include #include -#include /* For unblank_screen() */ #include +#include #include #include @@ -25,13 +25,14 @@ #include #include #include /* For VMALLOC_END */ +#include /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { struct vm_area_struct * vma = NULL; @@ -47,6 +48,17 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, field, regs->cp0_epc); #endif +#ifdef CONFIG_KPROBES + /* + * This is to notify the fault handler of the kprobes. The + * exception code is redundant as it is also carried in REGS, + * but we pass it anyhow. + */ + if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1, + (regs->cp0_cause >> 2) & 0x1f, SIGSEGV) == NOTIFY_STOP) + return; +#endif + info.si_code = SEGV_MAPERR; /* diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index de69bfb..1ef75cd 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* for run_uncached() */ /* Primary cache parameters. */ @@ -25,11 +26,15 @@ /* Secondary cache parameters. */ #define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ +/* Tertiary cache parameters */ +#define tc_lsize 32 + extern unsigned long icache_way_size, dcache_way_size; +unsigned long tcache_size; #include -static int rm7k_tcache_enabled; +static int rm7k_tcache_init; /* * Writeback and invalidate the primary cache dcache before DMA. @@ -46,7 +51,7 @@ static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) blast_scache_range(addr, addr + size); - if (!rm7k_tcache_enabled) + if (!rm7k_tcache_init) return; a = addr & ~(tc_pagesize - 1); @@ -70,7 +75,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) blast_inv_scache_range(addr, addr + size); - if (!rm7k_tcache_enabled) + if (!rm7k_tcache_init) return; a = addr & ~(tc_pagesize - 1); @@ -83,6 +88,45 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) } } +static void blast_rm7k_tcache(void) +{ + unsigned long start = CKSEG0ADDR(0); + unsigned long end = start + tcache_size; + + write_c0_taglo(0); + + while (start < end) { + cache_op(Page_Invalidate_T, start); + start += tc_pagesize; + } +} + +/* + * This function is executed in uncached address space. + */ +static __cpuinit void __rm7k_tc_enable(void) +{ + int i; + + set_c0_config(RM7K_CONF_TE); + + write_c0_taglo(0); + write_c0_taghi(0); + + for (i = 0; i < tcache_size; i += tc_lsize) + cache_op(Index_Store_Tag_T, CKSEG0ADDR(i)); +} + +static __cpuinit void rm7k_tc_enable(void) +{ + if (read_c0_config() & RM7K_CONF_TE) + return; + + BUG_ON(tcache_size == 0); + + run_uncached(__rm7k_tc_enable); +} + /* * This function is executed in uncached address space. */ @@ -95,16 +139,8 @@ static __cpuinit void __rm7k_sc_enable(void) write_c0_taglo(0); write_c0_taghi(0); - for (i = 0; i < scache_size; i += sc_lsize) { - __asm__ __volatile__ ( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (CKSEG0ADDR(i)), "i" (Index_Store_Tag_SD)); - } + for (i = 0; i < scache_size; i += sc_lsize) + cache_op(Index_Store_Tag_SD, CKSEG0ADDR(i)); } static __cpuinit void rm7k_sc_enable(void) @@ -112,13 +148,29 @@ static __cpuinit void rm7k_sc_enable(void) if (read_c0_config() & RM7K_CONF_SE) return; - printk(KERN_INFO "Enabling secondary cache...\n"); + pr_info("Enabling secondary cache...\n"); run_uncached(__rm7k_sc_enable); + + if (rm7k_tcache_init) + rm7k_tc_enable(); +} + +static void rm7k_tc_disable(void) +{ + unsigned long flags; + + local_irq_save(flags); + blast_rm7k_tcache(); + clear_c0_config(RM7K_CONF_TE); + local_irq_save(flags); } static void rm7k_sc_disable(void) { clear_c0_config(RM7K_CONF_SE); + + if (rm7k_tcache_init) + rm7k_tc_disable(); } static struct bcache_ops rm7k_sc_ops = { @@ -128,6 +180,52 @@ static struct bcache_ops rm7k_sc_ops = { .bc_inv = rm7k_sc_inv }; +/* + * This is a probing function like the one found in c-r4k.c, we look for the + * wrap around point with different addresses. + */ +static __cpuinit void __probe_tcache(void) +{ + unsigned long flags, addr, begin, end, pow2; + + begin = (unsigned long) &_stext; + begin &= ~((8 * 1024 * 1024) - 1); + end = begin + (8 * 1024 * 1024); + + local_irq_save(flags); + + set_c0_config(RM7K_CONF_TE); + + /* Fill size-multiple lines with a valid tag */ + pow2 = (256 * 1024); + for (addr = begin; addr <= end; addr = (begin + pow2)) { + unsigned long *p = (unsigned long *) addr; + __asm__ __volatile__("nop" : : "r" (*p)); + pow2 <<= 1; + } + + /* Load first line with a 0 tag, to check after */ + write_c0_taglo(0); + write_c0_taghi(0); + cache_op(Index_Store_Tag_T, begin); + + /* Look for the wrap-around */ + pow2 = (512 * 1024); + for (addr = begin + (512 * 1024); addr <= end; addr = begin + pow2) { + cache_op(Index_Load_Tag_T, addr); + if (!read_c0_taglo()) + break; + pow2 <<= 1; + } + + addr -= begin; + tcache_size = addr; + + clear_c0_config(RM7K_CONF_TE); + + local_irq_restore(flags); +} + void __cpuinit rm7k_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data; @@ -147,27 +245,26 @@ void __cpuinit rm7k_sc_init(void) if (!(config & RM7K_CONF_SE)) rm7k_sc_enable(); + bcops = &rm7k_sc_ops; + /* * While we're at it let's deal with the tertiary cache. */ - if (!(config & RM7K_CONF_TC)) { - - /* - * We can't enable the L3 cache yet. There may be board-specific - * magic necessary to turn it on, and blindly asking the CPU to - * start using it would may give cache errors. - * - * Also, board-specific knowledge may allow us to use the - * CACHE Flash_Invalidate_T instruction if the tag RAM supports - * it, and may specify the size of the L3 cache so we don't have - * to probe it. - */ - printk(KERN_INFO "Tertiary cache present, %s enabled\n", - (config & RM7K_CONF_TE) ? "already" : "not (yet)"); - - if ((config & RM7K_CONF_TE)) - rm7k_tcache_enabled = 1; - } - bcops = &rm7k_sc_ops; + rm7k_tcache_init = 0; + tcache_size = 0; + + if (config & RM7K_CONF_TC) + return; + + /* + * No efficient way to ask the hardware for the size of the tcache, + * so must probe for it. + */ + run_uncached(__probe_tcache); + rm7k_tc_enable(); + rm7k_tcache_init = 1; + c->tcache.linesz = tc_lsize; + c->tcache.ways = 1; + pr_info("Tertiary cache size %ldK.\n", (tcache_size >> 10)); } 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); diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 611d564..d2647a4 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -62,12 +62,13 @@ enum opcode { insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, - insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal, - insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, - insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd, - insn_sd, insn_sll, insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, - insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, - insn_dins, insn_syscall + insn_dsrl32, insn_drotr, insn_drotr32, insn_dsubu, insn_eret, + insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, + insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_or, insn_ori, + insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, + insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, + insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, + insn_dins, insn_syscall, insn_bbit0, insn_bbit1 }; struct insn { @@ -85,7 +86,7 @@ struct insn { | (e) << RE_SH \ | (f) << FUNC_SH) -static struct insn insn_table[] __cpuinitdata = { +static struct insn insn_table[] __uasminitdata = { { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, @@ -108,6 +109,7 @@ static struct insn insn_table[] __cpuinitdata = { { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, + { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, @@ -141,12 +143,14 @@ static struct insn insn_table[] __cpuinitdata = { { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, + { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_invalid, 0, 0 } }; #undef M -static inline __cpuinit u32 build_rs(u32 arg) +static inline __uasminit u32 build_rs(u32 arg) { if (arg & ~RS_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -154,7 +158,7 @@ static inline __cpuinit u32 build_rs(u32 arg) return (arg & RS_MASK) << RS_SH; } -static inline __cpuinit u32 build_rt(u32 arg) +static inline __uasminit u32 build_rt(u32 arg) { if (arg & ~RT_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -162,7 +166,7 @@ static inline __cpuinit u32 build_rt(u32 arg) return (arg & RT_MASK) << RT_SH; } -static inline __cpuinit u32 build_rd(u32 arg) +static inline __uasminit u32 build_rd(u32 arg) { if (arg & ~RD_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -170,7 +174,7 @@ static inline __cpuinit u32 build_rd(u32 arg) return (arg & RD_MASK) << RD_SH; } -static inline __cpuinit u32 build_re(u32 arg) +static inline __uasminit u32 build_re(u32 arg) { if (arg & ~RE_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -178,7 +182,7 @@ static inline __cpuinit u32 build_re(u32 arg) return (arg & RE_MASK) << RE_SH; } -static inline __cpuinit u32 build_simm(s32 arg) +static inline __uasminit u32 build_simm(s32 arg) { if (arg > 0x7fff || arg < -0x8000) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -186,7 +190,7 @@ static inline __cpuinit u32 build_simm(s32 arg) return arg & 0xffff; } -static inline __cpuinit u32 build_uimm(u32 arg) +static inline __uasminit u32 build_uimm(u32 arg) { if (arg & ~IMM_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -194,7 +198,7 @@ static inline __cpuinit u32 build_uimm(u32 arg) return arg & IMM_MASK; } -static inline __cpuinit u32 build_bimm(s32 arg) +static inline __uasminit u32 build_bimm(s32 arg) { if (arg > 0x1ffff || arg < -0x20000) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -205,7 +209,7 @@ static inline __cpuinit u32 build_bimm(s32 arg) return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); } -static inline __cpuinit u32 build_jimm(u32 arg) +static inline __uasminit u32 build_jimm(u32 arg) { if (arg & ~((JIMM_MASK) << 2)) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -213,7 +217,7 @@ static inline __cpuinit u32 build_jimm(u32 arg) return (arg >> 2) & JIMM_MASK; } -static inline __cpuinit u32 build_scimm(u32 arg) +static inline __uasminit u32 build_scimm(u32 arg) { if (arg & ~SCIMM_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -221,7 +225,7 @@ static inline __cpuinit u32 build_scimm(u32 arg) return (arg & SCIMM_MASK) << SCIMM_SH; } -static inline __cpuinit u32 build_func(u32 arg) +static inline __uasminit u32 build_func(u32 arg) { if (arg & ~FUNC_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -229,7 +233,7 @@ static inline __cpuinit u32 build_func(u32 arg) return arg & FUNC_MASK; } -static inline __cpuinit u32 build_set(u32 arg) +static inline __uasminit u32 build_set(u32 arg) { if (arg & ~SET_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -241,7 +245,7 @@ static inline __cpuinit u32 build_set(u32 arg) * The order of opcode arguments is implicitly left to right, * starting with RS and ending with FUNC or IMM. */ -static void __cpuinit build_insn(u32 **buf, enum opcode opc, ...) +static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) { struct insn *ip = NULL; unsigned int i; @@ -291,67 +295,78 @@ static void __cpuinit build_insn(u32 **buf, enum opcode opc, ...) Ip_u1u2u3(op) \ { \ build_insn(buf, insn##op, a, b, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2u1u3(op) \ Ip_u2u1u3(op) \ { \ build_insn(buf, insn##op, b, a, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u3u1u2(op) \ Ip_u3u1u2(op) \ { \ build_insn(buf, insn##op, b, c, a); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1u2s3(op) \ Ip_u1u2s3(op) \ { \ build_insn(buf, insn##op, a, b, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2s3u1(op) \ Ip_u2s3u1(op) \ { \ build_insn(buf, insn##op, c, a, b); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2u1s3(op) \ Ip_u2u1s3(op) \ { \ build_insn(buf, insn##op, b, a, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2u1msbu3(op) \ Ip_u2u1msbu3(op) \ { \ build_insn(buf, insn##op, b, a, c+d-1, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1u2(op) \ Ip_u1u2(op) \ { \ build_insn(buf, insn##op, a, b); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1s2(op) \ Ip_u1s2(op) \ { \ build_insn(buf, insn##op, a, b); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1(op) \ Ip_u1(op) \ { \ build_insn(buf, insn##op, a); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_0(op) \ Ip_0(op) \ { \ build_insn(buf, insn##op); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); I_u2u1s3(_addiu) I_u3u1u2(_addu) @@ -375,6 +390,7 @@ I_u2u1u3(_dsra) I_u2u1u3(_dsrl) I_u2u1u3(_dsrl32) I_u2u1u3(_drotr) +I_u2u1u3(_drotr32) I_u3u1u2(_dsubu) I_0(_eret) I_u1(_j) @@ -408,16 +424,19 @@ I_u3u1u2(_xor) I_u2u1u3(_xori) I_u2u1msbu3(_dins); I_u1(_syscall); +I_u1u2s3(_bbit0); +I_u1u2s3(_bbit1); /* Handle labels. */ -void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) +void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) { (*lab)->addr = addr; (*lab)->lab = lid; (*lab)++; } +UASM_EXPORT_SYMBOL(uasm_build_label); -int __cpuinit uasm_in_compat_space_p(long addr) +int __uasminit uasm_in_compat_space_p(long addr) { /* Is this address in 32bit compat space? */ #ifdef CONFIG_64BIT @@ -426,8 +445,9 @@ int __cpuinit uasm_in_compat_space_p(long addr) return 1; #endif } +UASM_EXPORT_SYMBOL(uasm_in_compat_space_p); -static int __cpuinit uasm_rel_highest(long val) +static int __uasminit uasm_rel_highest(long val) { #ifdef CONFIG_64BIT return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; @@ -436,7 +456,7 @@ static int __cpuinit uasm_rel_highest(long val) #endif } -static int __cpuinit uasm_rel_higher(long val) +static int __uasminit uasm_rel_higher(long val) { #ifdef CONFIG_64BIT return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; @@ -445,17 +465,19 @@ static int __cpuinit uasm_rel_higher(long val) #endif } -int __cpuinit uasm_rel_hi(long val) +int __uasminit uasm_rel_hi(long val) { return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; } +UASM_EXPORT_SYMBOL(uasm_rel_hi); -int __cpuinit uasm_rel_lo(long val) +int __uasminit uasm_rel_lo(long val) { return ((val & 0xffff) ^ 0x8000) - 0x8000; } +UASM_EXPORT_SYMBOL(uasm_rel_lo); -void __cpuinit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) +void __uasminit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) { if (!uasm_in_compat_space_p(addr)) { uasm_i_lui(buf, rs, uasm_rel_highest(addr)); @@ -470,8 +492,9 @@ void __cpuinit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) } else uasm_i_lui(buf, rs, uasm_rel_hi(addr)); } +UASM_EXPORT_SYMBOL(UASM_i_LA_mostly); -void __cpuinit UASM_i_LA(u32 **buf, unsigned int rs, long addr) +void __uasminit UASM_i_LA(u32 **buf, unsigned int rs, long addr) { UASM_i_LA_mostly(buf, rs, addr); if (uasm_rel_lo(addr)) { @@ -481,9 +504,10 @@ void __cpuinit UASM_i_LA(u32 **buf, unsigned int rs, long addr) uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr)); } } +UASM_EXPORT_SYMBOL(UASM_i_LA); /* Handle relocations. */ -void __cpuinit +void __uasminit uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) { (*rel)->addr = addr; @@ -491,8 +515,9 @@ uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) (*rel)->lab = lid; (*rel)++; } +UASM_EXPORT_SYMBOL(uasm_r_mips_pc16); -static inline void __cpuinit +static inline void __uasminit __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { long laddr = (long)lab->addr; @@ -509,7 +534,7 @@ __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) } } -void __cpuinit +void __uasminit uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { struct uasm_label *l; @@ -519,24 +544,27 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) if (rel->lab == l->lab) __resolve_relocs(rel, l); } +UASM_EXPORT_SYMBOL(uasm_resolve_relocs); -void __cpuinit +void __uasminit uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) { for (; rel->lab != UASM_LABEL_INVALID; rel++) if (rel->addr >= first && rel->addr < end) rel->addr += off; } +UASM_EXPORT_SYMBOL(uasm_move_relocs); -void __cpuinit +void __uasminit uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) { for (; lab->lab != UASM_LABEL_INVALID; lab++) if (lab->addr >= first && lab->addr < end) lab->addr += off; } +UASM_EXPORT_SYMBOL(uasm_move_labels); -void __cpuinit +void __uasminit uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, u32 *end, u32 *target) { @@ -547,8 +575,9 @@ uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, uasm_move_relocs(rel, first, end, off); uasm_move_labels(lab, first, end, off); } +UASM_EXPORT_SYMBOL(uasm_copy_handler); -int __cpuinit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) +int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) { for (; rel->lab != UASM_LABEL_INVALID; rel++) { if (rel->addr == addr @@ -559,61 +588,88 @@ int __cpuinit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) return 0; } +UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay); /* Convenience functions for labeled branches. */ -void __cpuinit +void __uasminit uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bltz(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bltz); -void __cpuinit +void __uasminit uasm_il_b(u32 **p, struct uasm_reloc **r, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_b(p, 0); } +UASM_EXPORT_SYMBOL(uasm_il_b); -void __cpuinit +void __uasminit uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_beqz(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_beqz); -void __cpuinit +void __uasminit uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_beqzl(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_beqzl); -void __cpuinit +void __uasminit uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, unsigned int reg2, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bne(p, reg1, reg2, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bne); -void __cpuinit +void __uasminit uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bnez(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bnez); -void __cpuinit +void __uasminit uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bgezl(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bgezl); -void __cpuinit +void __uasminit uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bgez(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bgez); + +void __uasminit +uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid) +{ + uasm_r_mips_pc16(r, *p, lid); + uasm_i_bbit0(p, reg, bit, 0); +} +UASM_EXPORT_SYMBOL(uasm_il_bbit0); + +void __uasminit +uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid) +{ + uasm_r_mips_pc16(r, *p, lid); + uasm_i_bbit1(p, reg, bit, 0); +} +UASM_EXPORT_SYMBOL(uasm_il_bbit1); diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 32e8478..6079ef3 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -15,5 +15,3 @@ obj-$(CONFIG_PCI) += malta-pci.o # FIXME FIXME FIXME obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mti-malta/Platform b/arch/mips/mti-malta/Platform new file mode 100644 index 0000000..5b548b5 --- /dev/null +++ b/arch/mips/mti-malta/Platform @@ -0,0 +1,7 @@ +# +# MIPS Malta board +# +platform-$(CONFIG_MIPS_MALTA) += mti-malta/ +cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta +load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 +all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin diff --git a/arch/mips/nxp/pnx833x/common/Makefile b/arch/mips/nxp/pnx833x/common/Makefile deleted file mode 100644 index 4a16f3b..0000000 --- a/arch/mips/nxp/pnx833x/common/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-y := interrupts.o platform.o prom.o setup.o reset.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/nxp/pnx833x/common/interrupts.c b/arch/mips/nxp/pnx833x/common/interrupts.c deleted file mode 100644 index 941916f..0000000 --- a/arch/mips/nxp/pnx833x/common/interrupts.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * interrupts.c: Interrupt mappings for PNX833X. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int mips_cpu_timer_irq; - -static const unsigned int irq_prio[PNX833X_PIC_NUM_IRQ] = -{ - 0, /* unused */ - 4, /* PNX833X_PIC_I2C0_INT 1 */ - 4, /* PNX833X_PIC_I2C1_INT 2 */ - 1, /* PNX833X_PIC_UART0_INT 3 */ - 1, /* PNX833X_PIC_UART1_INT 4 */ - 6, /* PNX833X_PIC_TS_IN0_DV_INT 5 */ - 6, /* PNX833X_PIC_TS_IN0_DMA_INT 6 */ - 7, /* PNX833X_PIC_GPIO_INT 7 */ - 4, /* PNX833X_PIC_AUDIO_DEC_INT 8 */ - 5, /* PNX833X_PIC_VIDEO_DEC_INT 9 */ - 4, /* PNX833X_PIC_CONFIG_INT 10 */ - 4, /* PNX833X_PIC_AOI_INT 11 */ - 9, /* PNX833X_PIC_SYNC_INT 12 */ - 9, /* PNX8335_PIC_SATA_INT 13 */ - 4, /* PNX833X_PIC_OSD_INT 14 */ - 9, /* PNX833X_PIC_DISP1_INT 15 */ - 4, /* PNX833X_PIC_DEINTERLACER_INT 16 */ - 9, /* PNX833X_PIC_DISPLAY2_INT 17 */ - 4, /* PNX833X_PIC_VC_INT 18 */ - 4, /* PNX833X_PIC_SC_INT 19 */ - 9, /* PNX833X_PIC_IDE_INT 20 */ - 9, /* PNX833X_PIC_IDE_DMA_INT 21 */ - 6, /* PNX833X_PIC_TS_IN1_DV_INT 22 */ - 6, /* PNX833X_PIC_TS_IN1_DMA_INT 23 */ - 4, /* PNX833X_PIC_SGDX_DMA_INT 24 */ - 4, /* PNX833X_PIC_TS_OUT_INT 25 */ - 4, /* PNX833X_PIC_IR_INT 26 */ - 3, /* PNX833X_PIC_VMSP1_INT 27 */ - 3, /* PNX833X_PIC_VMSP2_INT 28 */ - 4, /* PNX833X_PIC_PIBC_INT 29 */ - 4, /* PNX833X_PIC_TS_IN0_TRD_INT 30 */ - 4, /* PNX833X_PIC_SGDX_TPD_INT 31 */ - 5, /* PNX833X_PIC_USB_INT 32 */ - 4, /* PNX833X_PIC_TS_IN1_TRD_INT 33 */ - 4, /* PNX833X_PIC_CLOCK_INT 34 */ - 4, /* PNX833X_PIC_SGDX_PARSER_INT 35 */ - 4, /* PNX833X_PIC_VMSP_DMA_INT 36 */ -#if defined(CONFIG_SOC_PNX8335) - 4, /* PNX8335_PIC_MIU_INT 37 */ - 4, /* PNX8335_PIC_AVCHIP_IRQ_INT 38 */ - 9, /* PNX8335_PIC_SYNC_HD_INT 39 */ - 9, /* PNX8335_PIC_DISP_HD_INT 40 */ - 9, /* PNX8335_PIC_DISP_SCALER_INT 41 */ - 4, /* PNX8335_PIC_OSD_HD1_INT 42 */ - 4, /* PNX8335_PIC_DTL_WRITER_Y_INT 43 */ - 4, /* PNX8335_PIC_DTL_WRITER_C_INT 44 */ - 4, /* PNX8335_PIC_DTL_EMULATOR_Y_IR_INT 45 */ - 4, /* PNX8335_PIC_DTL_EMULATOR_C_IR_INT 46 */ - 4, /* PNX8335_PIC_DENC_TTX_INT 47 */ - 4, /* PNX8335_PIC_MMI_SIF0_INT 48 */ - 4, /* PNX8335_PIC_MMI_SIF1_INT 49 */ - 4, /* PNX8335_PIC_MMI_CDMMU_INT 50 */ - 4, /* PNX8335_PIC_PIBCS_INT 51 */ - 12, /* PNX8335_PIC_ETHERNET_INT 52 */ - 3, /* PNX8335_PIC_VMSP1_0_INT 53 */ - 3, /* PNX8335_PIC_VMSP1_1_INT 54 */ - 4, /* PNX8335_PIC_VMSP1_DMA_INT 55 */ - 4, /* PNX8335_PIC_TDGR_DE_INT 56 */ - 4, /* PNX8335_PIC_IR1_IRQ_INT 57 */ -#endif -}; - -static void pnx833x_timer_dispatch(void) -{ - do_IRQ(mips_cpu_timer_irq); -} - -static void pic_dispatch(void) -{ - unsigned int irq = PNX833X_REGFIELD(PIC_INT_SRC, INT_SRC); - - if ((irq >= 1) && (irq < (PNX833X_PIC_NUM_IRQ))) { - unsigned long priority = PNX833X_PIC_INT_PRIORITY; - PNX833X_PIC_INT_PRIORITY = irq_prio[irq]; - - if (irq == PNX833X_PIC_GPIO_INT) { - unsigned long mask = PNX833X_PIO_INT_STATUS & PNX833X_PIO_INT_ENABLE; - int pin; - while ((pin = ffs(mask & 0xffff))) { - pin -= 1; - do_IRQ(PNX833X_GPIO_IRQ_BASE + pin); - mask &= ~(1 << pin); - } - } else { - do_IRQ(irq + PNX833X_PIC_IRQ_BASE); - } - - PNX833X_PIC_INT_PRIORITY = priority; - } else { - printk(KERN_ERR "plat_irq_dispatch: unexpected irq %u\n", irq); - } -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause(); - - if (pending & STATUSF_IP4) - pic_dispatch(); - else if (pending & STATUSF_IP7) - do_IRQ(PNX833X_TIMER_IRQ); - else - spurious_interrupt(); -} - -static inline void pnx833x_hard_enable_pic_irq(unsigned int irq) -{ - /* Currently we do this by setting IRQ priority to 1. - If priority support is being implemented, 1 should be repalced - by a better value. */ - PNX833X_PIC_INT_REG(irq) = irq_prio[irq]; -} - -static inline void pnx833x_hard_disable_pic_irq(unsigned int irq) -{ - /* Disable IRQ by writing setting it's priority to 0 */ - PNX833X_PIC_INT_REG(irq) = 0; -} - -static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */ -#define IRQFLAG_STARTED 1 -#define IRQFLAG_DISABLED 2 - -static DEFINE_RAW_SPINLOCK(pnx833x_irq_lock); - -static unsigned int pnx833x_startup_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */ - pnx833x_hard_enable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); - return 0; -} - -static void pnx833x_shutdown_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] = 0; /* not started */ - pnx833x_hard_disable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); -} - -static void pnx833x_enable_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] &= ~IRQFLAG_DISABLED; - if (irqflags[pic_irq] == IRQFLAG_STARTED) - pnx833x_hard_enable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); -} - -static void pnx833x_disable_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] |= IRQFLAG_DISABLED; - pnx833x_hard_disable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); -} - -static void pnx833x_ack_pic_irq(unsigned int irq) -{ -} - -static void pnx833x_end_pic_irq(unsigned int irq) -{ -} - -static DEFINE_RAW_SPINLOCK(pnx833x_gpio_pnx833x_irq_lock); - -static unsigned int pnx833x_startup_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_enable_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); - return 0; -} - -static void pnx833x_enable_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_enable_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); -} - -static void pnx833x_disable_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_disable_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); -} - -static void pnx833x_ack_gpio_irq(unsigned int irq) -{ -} - -static void pnx833x_end_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_clear_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); -} - -static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - int gpio_mode; - - switch (flow_type) { - case IRQ_TYPE_EDGE_RISING: - gpio_mode = GPIO_INT_EDGE_RISING; - break; - case IRQ_TYPE_EDGE_FALLING: - gpio_mode = GPIO_INT_EDGE_FALLING; - break; - case IRQ_TYPE_EDGE_BOTH: - gpio_mode = GPIO_INT_EDGE_BOTH; - break; - case IRQ_TYPE_LEVEL_HIGH: - gpio_mode = GPIO_INT_LEVEL_HIGH; - break; - case IRQ_TYPE_LEVEL_LOW: - gpio_mode = GPIO_INT_LEVEL_LOW; - break; - default: - gpio_mode = GPIO_INT_NONE; - break; - } - - pnx833x_gpio_setup_irq(gpio_mode, pin); - - return 0; -} - -static struct irq_chip pnx833x_pic_irq_type = { - .name = "PNX-PIC", - .startup = pnx833x_startup_pic_irq, - .shutdown = pnx833x_shutdown_pic_irq, - .enable = pnx833x_enable_pic_irq, - .disable = pnx833x_disable_pic_irq, - .ack = pnx833x_ack_pic_irq, - .end = pnx833x_end_pic_irq -}; - -static struct irq_chip pnx833x_gpio_irq_type = { - .name = "PNX-GPIO", - .startup = pnx833x_startup_gpio_irq, - .shutdown = pnx833x_disable_gpio_irq, - .enable = pnx833x_enable_gpio_irq, - .disable = pnx833x_disable_gpio_irq, - .ack = pnx833x_ack_gpio_irq, - .end = pnx833x_end_gpio_irq, - .set_type = pnx833x_set_type_gpio_irq -}; - -void __init arch_init_irq(void) -{ - unsigned int irq; - - /* setup standard internal cpu irqs */ - mips_cpu_irq_init(); - - /* Set IRQ information in irq_desc */ - for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { - pnx833x_hard_disable_pic_irq(irq); - set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); - } - - for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) - set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); - - /* Set PIC priority limiter register to 0 */ - PNX833X_PIC_INT_PRIORITY = 0; - - /* Setup GPIO IRQ dispatching */ - pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); - - /* Enable PIC IRQs (HWIRQ2) */ - if (cpu_has_vint) - set_vi_handler(4, pic_dispatch); - - write_c0_status(read_c0_status() | IE_IRQ2); -} - -unsigned int __cpuinit get_c0_compare_int(void) -{ - if (cpu_has_vint) - set_vi_handler(cp0_compare_irq, pnx833x_timer_dispatch); - - mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; - return mips_cpu_timer_irq; -} - -void __init plat_time_init(void) -{ - /* calculate mips_hpt_frequency based on PNX833X_CLOCK_CPUCP_CTL reg */ - - extern unsigned long mips_hpt_frequency; - unsigned long reg = PNX833X_CLOCK_CPUCP_CTL; - - if (!(PNX833X_BIT(reg, CLOCK_CPUCP_CTL, EXIT_RESET))) { - /* Functional clock is disabled so use crystal frequency */ - mips_hpt_frequency = 25; - } else { -#if defined(CONFIG_SOC_PNX8335) - /* Functional clock is enabled, so get clock multiplier */ - mips_hpt_frequency = 90 + (10 * PNX8335_REGFIELD(CLOCK_PLL_CPU_CTL, FREQ)); -#else - static const unsigned long int freq[4] = {240, 160, 120, 80}; - mips_hpt_frequency = freq[PNX833X_FIELD(reg, CLOCK_CPUCP_CTL, DIV_CLOCK)]; -#endif - } - - printk(KERN_INFO "CPU clock is %ld MHz\n", mips_hpt_frequency); - - mips_hpt_frequency *= 500000; -} diff --git a/arch/mips/nxp/pnx833x/common/platform.c b/arch/mips/nxp/pnx833x/common/platform.c deleted file mode 100644 index 01f8345..0000000 --- a/arch/mips/nxp/pnx833x/common/platform.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * platform.c: platform support for PNX833X. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_I2C_PNX0105 -/* Until i2c driver available in kernel.*/ -#include -#endif - -#include -#include -#include - -static u64 uart_dmamask = DMA_BIT_MASK(32); - -static struct resource pnx833x_uart_resources[] = { - [0] = { - .start = PNX833X_UART0_PORTS_START, - .end = PNX833X_UART0_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX833X_PIC_UART0_INT, - .end = PNX833X_PIC_UART0_INT, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = PNX833X_UART1_PORTS_START, - .end = PNX833X_UART1_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [3] = { - .start = PNX833X_PIC_UART1_INT, - .end = PNX833X_PIC_UART1_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -struct pnx8xxx_port pnx8xxx_ports[] = { - [0] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX833X_UART0_PORTS_START, - .mapbase = PNX833X_UART0_PORTS_START, - .irq = PNX833X_PIC_UART0_INT, - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - }, - [1] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX833X_UART1_PORTS_START, - .mapbase = PNX833X_UART1_PORTS_START, - .irq = PNX833X_PIC_UART1_INT, - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - }, -}; - -static struct platform_device pnx833x_uart_device = { - .name = "pnx8xxx-uart", - .id = -1, - .dev = { - .dma_mask = &uart_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = pnx8xxx_ports, - }, - .num_resources = ARRAY_SIZE(pnx833x_uart_resources), - .resource = pnx833x_uart_resources, -}; - -static u64 ehci_dmamask = DMA_BIT_MASK(32); - -static struct resource pnx833x_usb_ehci_resources[] = { - [0] = { - .start = PNX833X_USB_PORTS_START, - .end = PNX833X_USB_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX833X_PIC_USB_INT, - .end = PNX833X_PIC_USB_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pnx833x_usb_ehci_device = { - .name = "pnx833x-ehci", - .id = -1, - .dev = { - .dma_mask = &ehci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(pnx833x_usb_ehci_resources), - .resource = pnx833x_usb_ehci_resources, -}; - -#ifdef CONFIG_I2C_PNX0105 -static struct resource pnx833x_i2c0_resources[] = { - { - .start = PNX833X_I2C0_PORTS_START, - .end = PNX833X_I2C0_PORTS_END, - .flags = IORESOURCE_MEM, - }, - { - .start = PNX833X_PIC_I2C0_INT, - .end = PNX833X_PIC_I2C0_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource pnx833x_i2c1_resources[] = { - { - .start = PNX833X_I2C1_PORTS_START, - .end = PNX833X_I2C1_PORTS_END, - .flags = IORESOURCE_MEM, - }, - { - .start = PNX833X_PIC_I2C1_INT, - .end = PNX833X_PIC_I2C1_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { - { - .base = PNX833X_I2C0_PORTS_START, - .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ - .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */ - .bus_addr = 0, /* no slave support */ - }, - { - .base = PNX833X_I2C1_PORTS_START, - .irq = -1, /* on high freq, polling is faster */ - /*.irq = PNX833X_PIC_I2C1_INT,*/ - .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */ - .bus_addr = 0, /* no slave support */ - }, -}; - -static struct platform_device pnx833x_i2c0_device = { - .name = "i2c-pnx0105", - .id = 0, - .dev = { - .platform_data = &pnx833x_i2c_dev[0], - }, - .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources), - .resource = pnx833x_i2c0_resources, -}; - -static struct platform_device pnx833x_i2c1_device = { - .name = "i2c-pnx0105", - .id = 1, - .dev = { - .platform_data = &pnx833x_i2c_dev[1], - }, - .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources), - .resource = pnx833x_i2c1_resources, -}; -#endif - -static u64 ethernet_dmamask = DMA_BIT_MASK(32); - -static struct resource pnx833x_ethernet_resources[] = { - [0] = { - .start = PNX8335_IP3902_PORTS_START, - .end = PNX8335_IP3902_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8335_PIC_ETHERNET_INT, - .end = PNX8335_PIC_ETHERNET_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pnx833x_ethernet_device = { - .name = "ip3902-eth", - .id = -1, - .dev = { - .dma_mask = ðernet_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(pnx833x_ethernet_resources), - .resource = pnx833x_ethernet_resources, -}; - -static struct resource pnx833x_sata_resources[] = { - [0] = { - .start = PNX8335_SATA_PORTS_START, - .end = PNX8335_SATA_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8335_PIC_SATA_INT, - .end = PNX8335_PIC_SATA_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pnx833x_sata_device = { - .name = "pnx833x-sata", - .id = -1, - .num_resources = ARRAY_SIZE(pnx833x_sata_resources), - .resource = pnx833x_sata_resources, -}; - -static const char *part_probes[] = { - "cmdlinepart", - NULL -}; - -static void -pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) -{ - struct nand_chip *this = mtd->priv; - unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; - - if (cmd == NAND_CMD_NONE) - return; - - if (ctrl & NAND_CLE) - writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_CLE_MASK)); - else - writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_ALE_MASK)); -} - -static struct platform_nand_data pnx833x_flash_nand_data = { - .chip = { - .chip_delay = 25, - .part_probe_types = part_probes, - }, - .ctrl = { - .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl - } -}; - -/* - * Set start to be the correct address (PNX8335_NAND_BASE with no 0xb!!), - * 12 bytes more seems to be the standard that allows for NAND access. - */ -static struct resource pnx833x_flash_nand_resource = { - .start = PNX8335_NAND_BASE, - .end = PNX8335_NAND_BASE + 12, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device pnx833x_flash_nand = { - .name = "gen_nand", - .id = -1, - .num_resources = 1, - .resource = &pnx833x_flash_nand_resource, - .dev = { - .platform_data = &pnx833x_flash_nand_data, - }, -}; - -static struct platform_device *pnx833x_platform_devices[] __initdata = { - &pnx833x_uart_device, - &pnx833x_usb_ehci_device, -#ifdef CONFIG_I2C_PNX0105 - &pnx833x_i2c0_device, - &pnx833x_i2c1_device, -#endif - &pnx833x_ethernet_device, - &pnx833x_sata_device, - &pnx833x_flash_nand, -}; - -static int __init pnx833x_platform_init(void) -{ - int res; - - res = platform_add_devices(pnx833x_platform_devices, - ARRAY_SIZE(pnx833x_platform_devices)); - - return res; -} - -arch_initcall(pnx833x_platform_init); diff --git a/arch/mips/nxp/pnx833x/common/prom.c b/arch/mips/nxp/pnx833x/common/prom.c deleted file mode 100644 index 29969f9..0000000 --- a/arch/mips/nxp/pnx833x/common/prom.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * prom.c: - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include - -void __init prom_init_cmdline(void) -{ - int argc = fw_arg0; - char **argv = (char **)fw_arg1; - char *c = &(arcs_cmdline[0]); - int i; - - for (i = 1; i < argc; i++) { - strcpy(c, argv[i]); - c += strlen(argv[i]); - if (i < argc-1) - *c++ = ' '; - } - *c = 0; -} - -char __init *prom_getenv(char *envname) -{ - extern char **prom_envp; - char **env = prom_envp; - int i; - - i = strlen(envname); - - while (*env) { - if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') - return *env + i + 1; - env++; - } - - return 0; -} - -void __init prom_free_prom_memory(void) -{ -} diff --git a/arch/mips/nxp/pnx833x/common/reset.c b/arch/mips/nxp/pnx833x/common/reset.c deleted file mode 100644 index e0ea96d..0000000 --- a/arch/mips/nxp/pnx833x/common/reset.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * reset.c: reset support for PNX833X. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include - -void pnx833x_machine_restart(char *command) -{ - PNX833X_RESET_CONTROL_2 = 0; - PNX833X_RESET_CONTROL = 0; -} - -void pnx833x_machine_halt(void) -{ - while (1) - __asm__ __volatile__ ("wait"); - -} - -void pnx833x_machine_power_off(void) -{ - pnx833x_machine_halt(); -} diff --git a/arch/mips/nxp/pnx833x/common/setup.c b/arch/mips/nxp/pnx833x/common/setup.c deleted file mode 100644 index e51fbc4..0000000 --- a/arch/mips/nxp/pnx833x/common/setup.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * setup.c: Setup PNX833X Soc. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -extern void pnx833x_board_setup(void); -extern void pnx833x_machine_restart(char *); -extern void pnx833x_machine_halt(void); -extern void pnx833x_machine_power_off(void); - -int __init plat_mem_setup(void) -{ - /* fake pci bus to avoid bounce buffers */ - PCI_DMA_BUS_IS_PHYS = 1; - - /* set mips clock to 320MHz */ -#if defined(CONFIG_SOC_PNX8335) - PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); -#endif - pnx833x_gpio_init(); /* so it will be ready in board_setup() */ - - pnx833x_board_setup(); - - _machine_restart = pnx833x_machine_restart; - _machine_halt = pnx833x_machine_halt; - pm_power_off = pnx833x_machine_power_off; - - /* IO/MEM resources. */ - set_io_port_base(KSEG1); - ioport_resource.start = 0; - ioport_resource.end = ~0; - iomem_resource.start = 0; - iomem_resource.end = ~0; - - return 0; -} diff --git a/arch/mips/nxp/pnx833x/stb22x/Makefile b/arch/mips/nxp/pnx833x/stb22x/Makefile deleted file mode 100644 index f81c580..0000000 --- a/arch/mips/nxp/pnx833x/stb22x/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -lib-y := board.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/nxp/pnx833x/stb22x/board.c b/arch/mips/nxp/pnx833x/stb22x/board.c deleted file mode 100644 index 644eb7c..0000000 --- a/arch/mips/nxp/pnx833x/stb22x/board.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * board.c: STB225 board support. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include - -/* endianess twiddlers */ -#define PNX8335_DEBUG0 0x4400 -#define PNX8335_DEBUG1 0x4404 -#define PNX8335_DEBUG2 0x4408 -#define PNX8335_DEBUG3 0x440c -#define PNX8335_DEBUG4 0x4410 -#define PNX8335_DEBUG5 0x4414 -#define PNX8335_DEBUG6 0x4418 -#define PNX8335_DEBUG7 0x441c - -int prom_argc; -char **prom_argv, **prom_envp; - -extern void prom_init_cmdline(void); -extern char *prom_getenv(char *envname); - -const char *get_system_type(void) -{ - return "NXP STB22x"; -} - -static inline unsigned long env_or_default(char *env, unsigned long dfl) -{ - char *str = prom_getenv(env); - return str ? simple_strtol(str, 0, 0) : dfl; -} - -void __init prom_init(void) -{ - unsigned long memsize; - - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - - memsize = env_or_default("memsize", 0x02000000); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} - -void __init pnx833x_board_setup(void) -{ - pnx833x_gpio_select_function_alt(4); - pnx833x_gpio_select_output(4); - pnx833x_gpio_select_function_alt(5); - pnx833x_gpio_select_input(5); - pnx833x_gpio_select_function_alt(6); - pnx833x_gpio_select_input(6); - pnx833x_gpio_select_function_alt(7); - pnx833x_gpio_select_output(7); - - pnx833x_gpio_select_function_alt(25); - pnx833x_gpio_select_function_alt(26); - - pnx833x_gpio_select_function_alt(27); - pnx833x_gpio_select_function_alt(28); - pnx833x_gpio_select_function_alt(29); - pnx833x_gpio_select_function_alt(30); - pnx833x_gpio_select_function_alt(31); - pnx833x_gpio_select_function_alt(32); - pnx833x_gpio_select_function_alt(33); - -#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) - /* Setup MIU for NAND access on CS0... - * - * (it seems that we must also configure CS1 for reliable operation, - * otherwise the first read ID command will fail if it's read as 4 bytes - * but pass if it's read as 1 word.) - */ - - /* Setup MIU CS0 & CS1 timing */ - PNX833X_MIU_SEL0 = 0; - PNX833X_MIU_SEL1 = 0; - PNX833X_MIU_SEL0_TIMING = 0x50003081; - PNX833X_MIU_SEL1_TIMING = 0x50003081; - - /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ - pnx833x_gpio_select_function_alt(0); - - /* Setup GPIO 04 to input NAND read/busy signal */ - pnx833x_gpio_select_function_io(4); - pnx833x_gpio_select_input(4); - - /* Setup GPIO 05 to disable NAND write protect */ - pnx833x_gpio_select_function_io(5); - pnx833x_gpio_select_output(5); - pnx833x_gpio_write(1, 5); - -#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) - - /* Set up MIU for 16-bit NOR access on CS0 and CS1... */ - - /* Setup MIU CS0 & CS1 timing */ - PNX833X_MIU_SEL0 = 1; - PNX833X_MIU_SEL1 = 1; - PNX833X_MIU_SEL0_TIMING = 0x6A08D082; - PNX833X_MIU_SEL1_TIMING = 0x6A08D082; - - /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ - pnx833x_gpio_select_function_alt(0); -#endif -} diff --git a/arch/mips/nxp/pnx8550/common/Makefile b/arch/mips/nxp/pnx8550/common/Makefile deleted file mode 100644 index dd9e7b1..0000000 --- a/arch/mips/nxp/pnx8550/common/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# Per Hallsmark, per.hallsmark@mvista.com -# -# ######################################################################## -# -# This program is free software; you can distribute it and/or modify it -# under the terms of the GNU General Public License (Version 2) as -# published by the Free Software Foundation. -# -# This program is distributed in the hope it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -# -# ####################################################################### -# -# Makefile for the PNX8550 specific kernel interface routines -# under Linux. -# - -obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o -obj-$(CONFIG_PCI) += pci.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/nxp/pnx8550/common/int.c b/arch/mips/nxp/pnx8550/common/int.c deleted file mode 100644 index cfed505..0000000 --- a/arch/mips/nxp/pnx8550/common/int.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * - * Copyright (C) 2005 Embedded Alley Solutions, Inc - * Ported to 2.6. - * - * Per Hallsmark, per.hallsmark@mvista.com - * Copyright (C) 2000, 2001 MIPS Technologies, Inc. - * Copyright (C) 2001 Ralf Baechle - * - * Cleaned up and bug fixing: Pete Popov, ppopov@embeddedalley.com - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* default prio for interrupts */ -/* first one is a no-no so therefore always prio 0 (disabled) */ -static char gic_prio[PNX8550_INT_GIC_TOTINT] = { - 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49 - 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69 - 1 // 70 -}; - -static void hw0_irqdispatch(int irq) -{ - /* find out which interrupt */ - irq = PNX8550_GIC_VECTOR_0 >> 3; - - if (irq == 0) { - printk("hw0_irqdispatch: irq 0, spurious interrupt?\n"); - return; - } - do_IRQ(PNX8550_INT_GIC_MIN + irq); -} - - -static void timer_irqdispatch(int irq) -{ - irq = (0x01c0 & read_c0_config7()) >> 6; - - if (unlikely(irq == 0)) { - printk("timer_irqdispatch: irq 0, spurious interrupt?\n"); - return; - } - - if (irq & 0x1) - do_IRQ(PNX8550_INT_TIMER1); - if (irq & 0x2) - do_IRQ(PNX8550_INT_TIMER2); - if (irq & 0x4) - do_IRQ(PNX8550_INT_TIMER3); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP2) - hw0_irqdispatch(2); - else if (pending & STATUSF_IP7) { - if (read_c0_config7() & 0x01c0) - timer_irqdispatch(7); - } else - spurious_interrupt(); -} - -static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) -{ - unsigned long status = read_c0_status(); - - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - - write_c0_status(status); -} - -static inline void mask_gic_int(unsigned int irq_nr) -{ - /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */ - PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */ -} - -static inline void unmask_gic_int(unsigned int irq_nr) -{ - /* set prio mask to lower four bits and enable interrupt */ - PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr]; -} - -static inline void mask_irq(unsigned int irq_nr) -{ - if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { - modify_cp0_intmask(1 << irq_nr, 0); - } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_GIC_MAX)) { - mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); - } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_TIMER_MAX)) { - modify_cp0_intmask(1 << 7, 0); - } else { - printk("mask_irq: irq %d doesn't exist!\n", irq_nr); - } -} - -static inline void unmask_irq(unsigned int irq_nr) -{ - if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { - modify_cp0_intmask(0, 1 << irq_nr); - } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_GIC_MAX)) { - unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); - } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_TIMER_MAX)) { - modify_cp0_intmask(0, 1 << 7); - } else { - printk("mask_irq: irq %d doesn't exist!\n", irq_nr); - } -} - -int pnx8550_set_gic_priority(int irq, int priority) -{ - int gic_irq = irq-PNX8550_INT_GIC_MIN; - int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf; - - gic_prio[gic_irq] = priority; - PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]); - - return prev_priority; -} - -static struct irq_chip level_irq_type = { - .name = "PNX Level IRQ", - .ack = mask_irq, - .mask = mask_irq, - .mask_ack = mask_irq, - .unmask = unmask_irq, -}; - -static struct irqaction gic_action = { - .handler = no_action, - .flags = IRQF_DISABLED, - .name = "GIC", -}; - -static struct irqaction timer_action = { - .handler = no_action, - .flags = IRQF_DISABLED | IRQF_TIMER, - .name = "Timer", -}; - -void __init arch_init_irq(void) -{ - int i; - int configPR; - - for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { - set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); - mask_irq(i); /* mask the irq just in case */ - } - - /* init of GIC/IPC interrupts */ - /* should be done before cp0 since cp0 init enables the GIC int */ - for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) { - int gic_int_line = i - PNX8550_INT_GIC_MIN; - if (gic_int_line == 0 ) - continue; // don't fiddle with int 0 - /* - * enable change of TARGET, ENABLE and ACTIVE_LOW bits - * set TARGET 0 to route through hw0 interrupt - * set ACTIVE_LOW 0 active high (correct?) - * - * We really should setup an interrupt description table - * to do this nicely. - * Note, PCI INTA is active low on the bus, but inverted - * in the GIC, so to us it's active high. - */ - PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000; - - /* mask/priority is still 0 so we will not get any - * interrupts until it is unmasked */ - - set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); - } - - /* Priority level 0 */ - PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0; - - /* Set int vector table address */ - PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0; - - set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type, - handle_level_irq); - setup_irq(MIPS_CPU_GIC_IRQ, &gic_action); - - /* init of Timer interrupts */ - for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) - set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); - - /* Stop Timer 1-3 */ - configPR = read_c0_config7(); - configPR |= 0x00000038; - write_c0_config7(configPR); - - set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type, - handle_level_irq); - setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action); -} - -EXPORT_SYMBOL(pnx8550_set_gic_priority); diff --git a/arch/mips/nxp/pnx8550/common/platform.c b/arch/mips/nxp/pnx8550/common/platform.c deleted file mode 100644 index 5264cc0..0000000 --- a/arch/mips/nxp/pnx8550/common/platform.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Platform device support for NXP PNX8550 SoCs - * - * Copyright 2005, Embedded Alley Solutions, Inc - * - * Based on arch/mips/au1000/common/platform.c - * Platform device support for Au1x00 SoCs. - * - * Copyright 2004, Matt Porter - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static struct resource pnx8550_usb_ohci_resources[] = { - [0] = { - .start = PNX8550_USB_OHCI_OP_BASE, - .end = PNX8550_USB_OHCI_OP_BASE + - PNX8550_USB_OHCI_OP_LEN, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8550_INT_USB, - .end = PNX8550_INT_USB, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource pnx8550_uart_resources[] = { - [0] = { - .start = PNX8550_UART_PORT0, - .end = PNX8550_UART_PORT0 + 0xfff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8550_UART_INT(0), - .end = PNX8550_UART_INT(0), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = PNX8550_UART_PORT1, - .end = PNX8550_UART_PORT1 + 0xfff, - .flags = IORESOURCE_MEM, - }, - [3] = { - .start = PNX8550_UART_INT(1), - .end = PNX8550_UART_INT(1), - .flags = IORESOURCE_IRQ, - }, -}; - -struct pnx8xxx_port pnx8xxx_ports[] = { - [0] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX8550_UART_PORT0, - .mapbase = PNX8550_UART_PORT0, - .irq = PNX8550_UART_INT(0), - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - }, - [1] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX8550_UART_PORT1, - .mapbase = PNX8550_UART_PORT1, - .irq = PNX8550_UART_INT(1), - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - }, -}; - -/* The dmamask must be set for OHCI to work */ -static u64 ohci_dmamask = DMA_BIT_MASK(32); - -static u64 uart_dmamask = DMA_BIT_MASK(32); - -static struct platform_device pnx8550_usb_ohci_device = { - .name = "pnx8550-ohci", - .id = -1, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(pnx8550_usb_ohci_resources), - .resource = pnx8550_usb_ohci_resources, -}; - -static struct platform_device pnx8550_uart_device = { - .name = "pnx8xxx-uart", - .id = -1, - .dev = { - .dma_mask = &uart_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = pnx8xxx_ports, - }, - .num_resources = ARRAY_SIZE(pnx8550_uart_resources), - .resource = pnx8550_uart_resources, -}; - -static struct platform_device *pnx8550_platform_devices[] __initdata = { - &pnx8550_usb_ohci_device, - &pnx8550_uart_device, -}; - -static int __init pnx8550_platform_init(void) -{ - return platform_add_devices(pnx8550_platform_devices, - ARRAY_SIZE(pnx8550_platform_devices)); -} - -arch_initcall(pnx8550_platform_init); diff --git a/arch/mips/nxp/pnx8550/common/proc.c b/arch/mips/nxp/pnx8550/common/proc.c deleted file mode 100644 index 3bba5ec..0000000 --- a/arch/mips/nxp/pnx8550/common/proc.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -static int pnx8550_timers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) -{ - int len = 0; - int configPR = read_c0_config7(); - - if (offset==0) { - len += sprintf(&page[len], "Timer: count, compare, tc, status\n"); - len += sprintf(&page[len], " 1: %11i, %8i, %1i, %s\n", - read_c0_count(), read_c0_compare(), - (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on"); - len += sprintf(&page[len], " 2: %11i, %8i, %1i, %s\n", - read_c0_count2(), read_c0_compare2(), - (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on"); - len += sprintf(&page[len], " 3: %11i, %8i, %1i, %s\n", - read_c0_count3(), read_c0_compare3(), - (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on"); - } - - return len; -} - -static int pnx8550_registers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) -{ - int len = 0; - - if (offset==0) { - len += sprintf(&page[len], "config1: %#10.8x\n", read_c0_config1()); - len += sprintf(&page[len], "config2: %#10.8x\n", read_c0_config2()); - len += sprintf(&page[len], "config3: %#10.8x\n", read_c0_config3()); - len += sprintf(&page[len], "configPR: %#10.8x\n", read_c0_config7()); - len += sprintf(&page[len], "status: %#10.8x\n", read_c0_status()); - len += sprintf(&page[len], "cause: %#10.8x\n", read_c0_cause()); - len += sprintf(&page[len], "count: %#10.8x\n", read_c0_count()); - len += sprintf(&page[len], "count_2: %#10.8x\n", read_c0_count2()); - len += sprintf(&page[len], "count_3: %#10.8x\n", read_c0_count3()); - len += sprintf(&page[len], "compare: %#10.8x\n", read_c0_compare()); - len += sprintf(&page[len], "compare_2: %#10.8x\n", read_c0_compare2()); - len += sprintf(&page[len], "compare_3: %#10.8x\n", read_c0_compare3()); - } - - return len; -} - -static struct proc_dir_entry* pnx8550_dir; -static struct proc_dir_entry* pnx8550_timers; -static struct proc_dir_entry* pnx8550_registers; - -static int pnx8550_proc_init( void ) -{ - - // Create /proc/pnx8550 - pnx8550_dir = proc_mkdir("pnx8550", NULL); - if (!pnx8550_dir) { - printk(KERN_ERR "Can't create pnx8550 proc dir\n"); - return -1; - } - - // Create /proc/pnx8550/timers - pnx8550_timers = create_proc_read_entry( - "timers", - 0, - pnx8550_dir, - pnx8550_timers_read, - NULL); - - if (!pnx8550_timers) - printk(KERN_ERR "Can't create pnx8550 timers proc file\n"); - - // Create /proc/pnx8550/registers - pnx8550_registers = create_proc_read_entry( - "registers", - 0, - pnx8550_dir, - pnx8550_registers_read, - NULL); - - if (!pnx8550_registers) - printk(KERN_ERR "Can't create pnx8550 registers proc file\n"); - - return 0; -} - -__initcall(pnx8550_proc_init); diff --git a/arch/mips/nxp/pnx8550/common/prom.c b/arch/mips/nxp/pnx8550/common/prom.c deleted file mode 100644 index 32f7009..0000000 --- a/arch/mips/nxp/pnx8550/common/prom.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Per Hallsmark, per.hallsmark@mvista.com - * - * Based on jmr3927/common/prom.c - * - * 2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is - * licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include -#include -#include -#include -#include - -#include -#include - -/* #define DEBUG_CMDLINE */ - -extern int prom_argc; -extern char **prom_argv, **prom_envp; - -typedef struct -{ - char *name; -/* char *val; */ -}t_env_var; - - -char * prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - -void __init prom_init_cmdline(void) -{ - int i; - - arcs_cmdline[0] = '\0'; - for (i = 0; i < prom_argc; i++) { - strcat(arcs_cmdline, prom_argv[i]); - strcat(arcs_cmdline, " "); - } -} - -char *prom_getenv(char *envname) -{ - /* - * Return a pointer to the given environment variable. - * Environment variables are stored in the form of "memsize=64". - */ - - t_env_var *env = (t_env_var *)prom_envp; - int i; - - i = strlen(envname); - - while(env->name) { - if(strncmp(envname, env->name, i) == 0) { - return(env->name + strlen(envname) + 1); - } - env++; - } - return(NULL); -} - -inline unsigned char str2hexnum(unsigned char c) -{ - if(c >= '0' && c <= '9') - return c - '0'; - if(c >= 'a' && c <= 'f') - return c - 'a' + 10; - if(c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; /* foo */ -} - -inline void str2eaddr(unsigned char *ea, unsigned char *str) -{ - int i; - - for(i = 0; i < 6; i++) { - unsigned char num; - - if((*str == '.') || (*str == ':')) - str++; - num = str2hexnum(*str++) << 4; - num |= (str2hexnum(*str++)); - ea[i] = num; - } -} - -int get_ethernet_addr(char *ethernet_addr) -{ - char *ethaddr_str; - - ethaddr_str = prom_getenv("ethaddr"); - if (!ethaddr_str) { - printk("ethaddr not set in boot prom\n"); - return -1; - } - str2eaddr(ethernet_addr, ethaddr_str); - return 0; -} - -void __init prom_free_prom_memory(void) -{ -} - -extern int pnx8550_console_port; - -/* used by early printk */ -void prom_putchar(char c) -{ - if (pnx8550_console_port != -1) { - /* Wait until FIFO not full */ - while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) >= 16) - ; - /* Send one char */ - ip3106_fifo(UART_BASE, pnx8550_console_port) = c; - } -} - -EXPORT_SYMBOL(get_ethernet_addr); -EXPORT_SYMBOL(str2eaddr); diff --git a/arch/mips/nxp/pnx8550/common/reset.c b/arch/mips/nxp/pnx8550/common/reset.c deleted file mode 100644 index fadd874..0000000 --- a/arch/mips/nxp/pnx8550/common/reset.c +++ /dev/null @@ -1,50 +0,0 @@ -/*. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Reset the PNX8550 board. - * - */ -#include - -#include -#include - -void pnx8550_machine_restart(char *command) -{ - char head[] = "************* Machine restart *************"; - char foot[] = "*******************************************"; - - printk("\n\n"); - printk("%s\n", head); - if (command != NULL) - printk("* %s\n", command); - printk("%s\n", foot); - - PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST; -} - -void pnx8550_machine_halt(void) -{ - printk("*** Machine halt. (Not implemented) ***\n"); -} - -void pnx8550_machine_power_off(void) -{ - printk("*** Machine power off. (Not implemented) ***\n"); -} diff --git a/arch/mips/nxp/pnx8550/common/time.c b/arch/mips/nxp/pnx8550/common/time.c deleted file mode 100644 index 8836c62..0000000 --- a/arch/mips/nxp/pnx8550/common/time.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2001, 2002, 2003 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) - * - * Common time service routines for MIPS machines. See - * Documents/MIPS/README.txt. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -static unsigned long cpj; - -static cycle_t hpt_read(struct clocksource *cs) -{ - return read_c0_count2(); -} - -static struct clocksource pnx_clocksource = { - .name = "pnx8xxx", - .rating = 200, - .read = hpt_read, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *c = dev_id; - - /* clear MATCH, signal the event */ - c->event_handler(c); - - return IRQ_HANDLED; -} - -static struct irqaction pnx8xxx_timer_irq = { - .handler = pnx8xxx_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, - .name = "pnx8xxx_timer", -}; - -static irqreturn_t monotonic_interrupt(int irq, void *dev_id) -{ - /* Timer 2 clear interrupt */ - write_c0_compare2(-1); - return IRQ_HANDLED; -} - -static struct irqaction monotonic_irqaction = { - .handler = monotonic_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, - .name = "Monotonic timer", -}; - -static int pnx8xxx_set_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - write_c0_compare(delta); - return 0; -} - -static struct clock_event_device pnx8xxx_clockevent = { - .name = "pnx8xxx_clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = pnx8xxx_set_next_event, -}; - -static inline void timer_ack(void) -{ - write_c0_compare(cpj); -} - -__init void plat_time_init(void) -{ - unsigned int configPR; - unsigned int n; - unsigned int m; - unsigned int p; - unsigned int pow2p; - - pnx8xxx_clockevent.cpumask = cpu_none_mask; - clockevents_register_device(&pnx8xxx_clockevent); - clocksource_register(&pnx_clocksource); - - /* Timer 1 start */ - configPR = read_c0_config7(); - configPR &= ~0x00000008; - write_c0_config7(configPR); - - /* Timer 2 start */ - configPR = read_c0_config7(); - configPR &= ~0x00000010; - write_c0_config7(configPR); - - /* Timer 3 stop */ - configPR = read_c0_config7(); - configPR |= 0x00000020; - write_c0_config7(configPR); - - - /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ - /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ - - n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; - m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; - p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; - pow2p = (1 << p); - - db_assert(m != 0 && pow2p != 0); - - /* - * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 - * (a.k.a. 8-10). Divide by HZ for a timer offset that results in - * HZ timer interrupts per second. - */ - mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p)); - cpj = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); - write_c0_count(0); - timer_ack(); - - /* Setup Timer 2 */ - write_c0_count2(0); - write_c0_compare2(0xffffffff); - - setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); - setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); -} diff --git a/arch/mips/nxp/pnx8550/jbs/Makefile b/arch/mips/nxp/pnx8550/jbs/Makefile deleted file mode 100644 index ad6a8ca..0000000 --- a/arch/mips/nxp/pnx8550/jbs/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -# Makefile for the NXP JBS Board. - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/nxp/pnx8550/jbs/board_setup.c b/arch/mips/nxp/pnx8550/jbs/board_setup.c deleted file mode 100644 index 57dd903..0000000 --- a/arch/mips/nxp/pnx8550/jbs/board_setup.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * JBS Specific board startup routines. - * - * Copyright 2005, Embedded Alley Solutions, Inc - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -void __init board_setup(void) -{ - unsigned long configpr; - - configpr = read_c0_config7(); - configpr |= (1<<19); /* enable tlb */ - write_c0_config7(configpr); - BARRIER; -} diff --git a/arch/mips/nxp/pnx8550/jbs/init.c b/arch/mips/nxp/pnx8550/jbs/init.c deleted file mode 100644 index d59b4a4..0000000 --- a/arch/mips/nxp/pnx8550/jbs/init.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2005 Embedded Alley Solutions, Inc - * source@embeddedalley.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -int prom_argc; -char **prom_argv, **prom_envp; -extern void __init prom_init_cmdline(void); -extern char *prom_getenv(char *envname); - -const char *get_system_type(void) -{ - return "NXP PNX8550/JBS"; -} - -void __init prom_init(void) -{ - unsigned long memsize; - - //memsize = 0x02800000; /* Trimedia uses memory above */ - memsize = 0x08000000; /* Trimedia uses memory above */ - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/nxp/pnx8550/jbs/irqmap.c b/arch/mips/nxp/pnx8550/jbs/irqmap.c deleted file mode 100644 index 7fc8984..0000000 --- a/arch/mips/nxp/pnx8550/jbs/irqmap.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * NXP JBS board irqmap. - * - * Copyright 2005 Embedded Alley Solutions, Inc - * source@embeddealley.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -char pnx8550_irq_tab[][5] __initdata = { - [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, -}; diff --git a/arch/mips/nxp/pnx8550/stb810/Makefile b/arch/mips/nxp/pnx8550/stb810/Makefile deleted file mode 100644 index ab91d72..0000000 --- a/arch/mips/nxp/pnx8550/stb810/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -# Makefile for the NXP STB810 Board. - -lib-y := prom_init.o board_setup.o irqmap.o diff --git a/arch/mips/nxp/pnx8550/stb810/board_setup.c b/arch/mips/nxp/pnx8550/stb810/board_setup.c deleted file mode 100644 index af2a55e..0000000 --- a/arch/mips/nxp/pnx8550/stb810/board_setup.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * STB810 specific board startup routines. - * - * Based on the arch/mips/nxp/pnx8550/jbs/board_setup.c - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * Copyright 2005 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -void __init board_setup(void) -{ - unsigned long configpr; - - configpr = read_c0_config7(); - configpr |= (1<<19); /* enable tlb */ - write_c0_config7(configpr); -} diff --git a/arch/mips/nxp/pnx8550/stb810/irqmap.c b/arch/mips/nxp/pnx8550/stb810/irqmap.c deleted file mode 100644 index 8c03496..0000000 --- a/arch/mips/nxp/pnx8550/stb810/irqmap.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * NXP STB810 board irqmap. - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * Copyright 2005 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include - -char pnx8550_irq_tab[][5] __initdata = { - [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, -}; diff --git a/arch/mips/nxp/pnx8550/stb810/prom_init.c b/arch/mips/nxp/pnx8550/stb810/prom_init.c deleted file mode 100644 index ca7f4ad..0000000 --- a/arch/mips/nxp/pnx8550/stb810/prom_init.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * STB810 specific prom routines - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * Copyright 2005 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -int prom_argc; -char **prom_argv, **prom_envp; -extern void __init prom_init_cmdline(void); -extern char *prom_getenv(char *envname); - -const char *get_system_type(void) -{ - return "NXP PNX8950/STB810"; -} - -void __init prom_init(void) -{ - unsigned long memsize; - - prom_argc = (int) fw_arg0; - prom_argv = (char **) fw_arg1; - prom_envp = (char **) fw_arg2; - - prom_init_cmdline(); - - memsize = 0x08000000; /* Trimedia uses memory above */ - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 03742e6..d808049 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005-2009 Cavium Networks + * Copyright (C) 2005-2009, 2010 Cavium Networks */ #include #include @@ -22,7 +22,7 @@ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is * in use. */ -static uint64_t msi_free_irq_bitmask; +static u64 msi_free_irq_bitmask[4]; /* * Each bit in msi_multiple_irq_bitmask tells that the device using @@ -30,7 +30,7 @@ static uint64_t msi_free_irq_bitmask; * is used so we can disable all of the MSI interrupts when a device * uses multiple. */ -static uint64_t msi_multiple_irq_bitmask; +static u64 msi_multiple_irq_bitmask[4]; /* * This lock controls updates to msi_free_irq_bitmask and @@ -38,6 +38,11 @@ static uint64_t msi_multiple_irq_bitmask; */ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); +/* + * Number of MSI IRQs used. This variable is set up in + * the module init time. + */ +static int msi_irq_size; /** * Called when a driver request MSI interrupts instead of the @@ -54,12 +59,13 @@ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { struct msi_msg msg; - uint16_t control; + u16 control; int configured_private_bits; int request_private_bits; - int irq; + int irq = 0; int irq_step; - uint64_t search_mask; + u64 search_mask; + int index; /* * Read the MSI config to figure out how many IRQs this device @@ -111,29 +117,31 @@ try_only_one: * use. */ spin_lock(&msi_free_irq_bitmask_lock); - for (irq = 0; irq < 64; irq += irq_step) { - if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) { - msi_free_irq_bitmask |= search_mask << irq; - msi_multiple_irq_bitmask |= (search_mask >> 1) << irq; - break; + for (index = 0; index < msi_irq_size/64; index++) { + for (irq = 0; irq < 64; irq += irq_step) { + if ((msi_free_irq_bitmask[index] & (search_mask << irq)) == 0) { + msi_free_irq_bitmask[index] |= search_mask << irq; + msi_multiple_irq_bitmask[index] |= (search_mask >> 1) << irq; + goto msi_irq_allocated; + } } } +msi_irq_allocated: spin_unlock(&msi_free_irq_bitmask_lock); /* Make sure the search for available interrupts didn't fail */ if (irq >= 64) { if (request_private_bits) { - pr_err("arch_setup_msi_irq: Unable to find %d free " - "interrupts, trying just one", + pr_err("arch_setup_msi_irq: Unable to find %d free interrupts, trying just one", 1 << request_private_bits); request_private_bits = 0; goto try_only_one; } else - panic("arch_setup_msi_irq: Unable to find a free MSI " - "interrupt"); + panic("arch_setup_msi_irq: Unable to find a free MSI interrupt"); } /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */ + irq += index*64; irq += OCTEON_IRQ_MSI_BIT0; switch (octeon_dma_bar_type) { @@ -169,6 +177,34 @@ try_only_one: return 0; } +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + struct msi_desc *entry; + int ret; + + /* + * MSI-X is not supported. + */ + if (type == PCI_CAP_ID_MSIX) + return -EINVAL; + + /* + * If an architecture wants to support multiple MSI, it needs to + * override arch_setup_msi_irqs() + */ + if (type == PCI_CAP_ID_MSI && nvec > 1) + return 1; + + list_for_each_entry(entry, &dev->msi_list, list) { + ret = arch_setup_msi_irq(dev, entry); + if (ret < 0) + return ret; + if (ret > 0) + return -ENOSPC; + } + + return 0; +} /** * Called when a device no longer needs its MSI interrupts. All @@ -179,12 +215,18 @@ try_only_one: void arch_teardown_msi_irq(unsigned int irq) { int number_irqs; - uint64_t bitmask; + u64 bitmask; + int index = 0; + int irq0; - if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63)) + if ((irq < OCTEON_IRQ_MSI_BIT0) + || (irq > msi_irq_size + OCTEON_IRQ_MSI_BIT0)) panic("arch_teardown_msi_irq: Attempted to teardown illegal " "MSI interrupt (%d)", irq); + irq -= OCTEON_IRQ_MSI_BIT0; + index = irq / 64; + irq0 = irq % 64; /* * Count the number of IRQs we need to free by looking at the @@ -192,97 +234,198 @@ void arch_teardown_msi_irq(unsigned int irq) * IRQ is also owned by this device. */ number_irqs = 0; - while ((irq+number_irqs < 64) && - (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs)))) + while ((irq0 + number_irqs < 64) && + (msi_multiple_irq_bitmask[index] + & (1ull << (irq0 + number_irqs)))) number_irqs++; number_irqs++; /* Mask with one bit for each IRQ */ bitmask = (1 << number_irqs) - 1; /* Shift the mask to the correct bit location */ - bitmask <<= irq; - if ((msi_free_irq_bitmask & bitmask) != bitmask) + bitmask <<= irq0; + if ((msi_free_irq_bitmask[index] & bitmask) != bitmask) panic("arch_teardown_msi_irq: Attempted to teardown MSI " "interrupt (%d) not in use", irq); /* Checks are done, update the in use bitmask */ spin_lock(&msi_free_irq_bitmask_lock); - msi_free_irq_bitmask &= ~bitmask; - msi_multiple_irq_bitmask &= ~bitmask; + msi_free_irq_bitmask[index] &= ~bitmask; + msi_multiple_irq_bitmask[index] &= ~bitmask; spin_unlock(&msi_free_irq_bitmask_lock); } +static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); + +static u64 msi_rcv_reg[4]; +static u64 mis_ena_reg[4]; + +static void octeon_irq_msi_enable_pcie(unsigned int irq) +{ + u64 en; + unsigned long flags; + int msi_number = irq - OCTEON_IRQ_MSI_BIT0; + int irq_index = msi_number >> 6; + int irq_bit = msi_number & 0x3f; + + raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); + en = cvmx_read_csr(mis_ena_reg[irq_index]); + en |= 1ull << irq_bit; + cvmx_write_csr(mis_ena_reg[irq_index], en); + cvmx_read_csr(mis_ena_reg[irq_index]); + raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); +} + +static void octeon_irq_msi_disable_pcie(unsigned int irq) +{ + u64 en; + unsigned long flags; + int msi_number = irq - OCTEON_IRQ_MSI_BIT0; + int irq_index = msi_number >> 6; + int irq_bit = msi_number & 0x3f; + + raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); + en = cvmx_read_csr(mis_ena_reg[irq_index]); + en &= ~(1ull << irq_bit); + cvmx_write_csr(mis_ena_reg[irq_index], en); + cvmx_read_csr(mis_ena_reg[irq_index]); + raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); +} + +static struct irq_chip octeon_irq_chip_msi_pcie = { + .name = "MSI", + .enable = octeon_irq_msi_enable_pcie, + .disable = octeon_irq_msi_disable_pcie, +}; + +static void octeon_irq_msi_enable_pci(unsigned int irq) +{ + /* + * Octeon PCI doesn't have the ability to mask/unmask MSI + * interrupts individually. Instead of masking/unmasking them + * in groups of 16, we simple assume MSI devices are well + * behaved. MSI interrupts are always enable and the ACK is + * assumed to be enough + */ +} + +static void octeon_irq_msi_disable_pci(unsigned int irq) +{ + /* See comment in enable */ +} + +static struct irq_chip octeon_irq_chip_msi_pci = { + .name = "MSI", + .enable = octeon_irq_msi_enable_pci, + .disable = octeon_irq_msi_disable_pci, +}; /* * Called by the interrupt handling code when an MSI interrupt * occurs. */ -static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) +static irqreturn_t __octeon_msi_do_interrupt(int index, u64 msi_bits) { - uint64_t msi_bits; int irq; + int bit; - if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) - msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0); - else - msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV); - irq = fls64(msi_bits); - if (irq) { - irq += OCTEON_IRQ_MSI_BIT0 - 1; - if (irq_desc[irq].action) { - do_IRQ(irq); - return IRQ_HANDLED; - } else { - pr_err("Spurious MSI interrupt %d\n", irq); - if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCIe */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - - OCTEON_IRQ_MSI_BIT0)); - } else { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - - OCTEON_IRQ_MSI_BIT0)); - } - } + bit = fls64(msi_bits); + if (bit) { + bit--; + /* Acknowledge it first. */ + cvmx_write_csr(msi_rcv_reg[index], 1ull << bit); + + irq = bit + OCTEON_IRQ_MSI_BIT0 + 64 * index; + do_IRQ(irq); + return IRQ_HANDLED; } return IRQ_NONE; } +#define OCTEON_MSI_INT_HANDLER_X(x) \ +static irqreturn_t octeon_msi_interrupt##x(int cpl, void *dev_id) \ +{ \ + u64 msi_bits = cvmx_read_csr(msi_rcv_reg[(x)]); \ + return __octeon_msi_do_interrupt((x), msi_bits); \ +} + +/* + * Create octeon_msi_interrupt{0-3} function body + */ +OCTEON_MSI_INT_HANDLER_X(0); +OCTEON_MSI_INT_HANDLER_X(1); +OCTEON_MSI_INT_HANDLER_X(2); +OCTEON_MSI_INT_HANDLER_X(3); /* * Initializes the MSI interrupt handling code */ -int octeon_msi_initialize(void) +int __init octeon_msi_initialize(void) { + int irq; + struct irq_chip *msi; + + if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) { + msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0; + msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1; + msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2; + msi_rcv_reg[3] = CVMX_PEXP_NPEI_MSI_RCV3; + mis_ena_reg[0] = CVMX_PEXP_NPEI_MSI_ENB0; + mis_ena_reg[1] = CVMX_PEXP_NPEI_MSI_ENB1; + mis_ena_reg[2] = CVMX_PEXP_NPEI_MSI_ENB2; + mis_ena_reg[3] = CVMX_PEXP_NPEI_MSI_ENB3; + msi = &octeon_irq_chip_msi_pcie; + } else { + msi_rcv_reg[0] = CVMX_NPI_NPI_MSI_RCV; +#define INVALID_GENERATE_ADE 0x8700000000000000ULL; + msi_rcv_reg[1] = INVALID_GENERATE_ADE; + msi_rcv_reg[2] = INVALID_GENERATE_ADE; + msi_rcv_reg[3] = INVALID_GENERATE_ADE; + mis_ena_reg[0] = INVALID_GENERATE_ADE; + mis_ena_reg[1] = INVALID_GENERATE_ADE; + mis_ena_reg[2] = INVALID_GENERATE_ADE; + mis_ena_reg[3] = INVALID_GENERATE_ADE; + msi = &octeon_irq_chip_msi_pci; + } + + for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++) + set_irq_chip_and_handler(irq, msi, handle_simple_irq); + if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[0:63]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0, + 0, "MSI[0:63]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt1, + 0, "MSI[64:127]", octeon_msi_interrupt1)) + panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt2, + 0, "MSI[127:191]", octeon_msi_interrupt2)) + panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt3, + 0, "MSI[192:255]", octeon_msi_interrupt3)) + panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); + + msi_irq_size = 256; } else if (octeon_is_pci_host()) { - if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[0:15]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0, + 0, "MSI[0:15]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); - if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[16:31]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt0, + 0, "MSI[16:31]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); - if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[32:47]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt0, + 0, "MSI[32:47]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); - if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[48:63]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt0, + 0, "MSI[48:63]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); - + msi_irq_size = 64; } return 0; } - subsys_initcall(octeon_msi_initialize); diff --git a/arch/mips/pci/ops-titan-ht.c b/arch/mips/pci/ops-titan-ht.c index 749c192..57d54ad 100644 --- a/arch/mips/pci/ops-titan-ht.c +++ b/arch/mips/pci/ops-titan-ht.c @@ -32,7 +32,7 @@ #include static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn, - int offset, u32 * val) + int offset, u32 *val) { volatile uint32_t address; int busno; @@ -64,7 +64,7 @@ static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn, } static int titan_ht_config_read(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 * val) + int offset, int size, u32 *val) { uint32_t dword; diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index 6aa5c54..861361e 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -402,6 +402,10 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) npei_ctl_status2.s.mps = 0; /* Max read request size = 128 bytes for best Octeon DMA performance */ npei_ctl_status2.s.mrrs = 0; + if (pcie_port) + npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ + else + npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ @@ -666,6 +670,8 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) static int cvmx_pcie_rc_initialize(int pcie_port) { int i; + int base; + u64 addr_swizzle; union cvmx_ciu_soft_prst ciu_soft_prst; union cvmx_pescx_bist_status pescx_bist_status; union cvmx_pescx_bist_status2 pescx_bist_status2; @@ -674,6 +680,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port) union cvmx_npei_mem_access_subidx mem_access_subid; union cvmx_npei_dbg_data npei_dbg_data; union cvmx_pescx_ctl_status2 pescx_ctl_status2; + union cvmx_npei_bar1_indexx bar1_index; /* * Make sure we aren't trying to setup a target mode interface @@ -918,12 +925,30 @@ static int cvmx_pcie_rc_initialize(int pcie_port) /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); - /* - * Disable Octeon's BAR1. It isn't needed in RC mode since - * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into - * the 2nd 256MB of memory. - */ - cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); + /* BAR1 follows BAR2 with a gap. */ + cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); + + bar1_index.u32 = 0; + bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); + bar1_index.s.ca = 1; /* Not Cached */ + bar1_index.s.end_swp = 1; /* Endian Swap mode */ + bar1_index.s.addr_v = 1; /* Valid entry */ + + base = pcie_port ? 16 : 0; + + /* Big endian swizzle for 32-bit PEXP_NCB register. */ +#ifdef __MIPSEB__ + addr_swizzle = 4; +#else + addr_swizzle = 0; +#endif + for (i = 0; i < 16; i++) { + cvmx_write64_uint32((CVMX_PEXP_NPEI_BAR1_INDEXX(base) ^ addr_swizzle), + bar1_index.u32); + base++; + /* 256MB / 16 >> 22 == 4 */ + bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); + } /* * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take diff --git a/arch/mips/pmc-sierra/Platform b/arch/mips/pmc-sierra/Platform new file mode 100644 index 0000000..f092f25 --- /dev/null +++ b/arch/mips/pmc-sierra/Platform @@ -0,0 +1,14 @@ +# +# PMC-Sierra MSP SOCs +# +platform-$(CONFIG_PMC_MSP) += pmc-sierra/msp71xx/ +cflags-$(CONFIG_PMC_MSP) += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \ + -mno-branch-likely +load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 + +# +# PMC-Sierra Yosemite +# +platform-$(CONFIG_PMC_YOSEMITE) += pmc-sierra/yosemite/ +cflags-$(CONFIG_PMC_YOSEMITE) += -I$(srctree)/arch/mips/include/asm/mach-yosemite +load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c index 11769b5..c841f08 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c @@ -32,9 +32,6 @@ #include #include #include -#ifdef CONFIG_PMCTWILED -#include -#endif /* For hwbutton_interrupt->initial_state */ #define HWBUTTON_HI 0x1 @@ -82,10 +79,6 @@ static void standby_on(void *data) printk(KERN_WARNING "STANDBY switch was set to ON (not implemented)\n"); /* TODO: Put board in standby mode */ -#ifdef CONFIG_PMCTWILED - msp_led_turn_off(MSP_LED_PWRSTANDBY_GREEN); - msp_led_turn_on(MSP_LED_PWRSTANDBY_RED); -#endif } static void standby_off(void *data) @@ -94,10 +87,6 @@ static void standby_off(void *data) "STANDBY switch was set to OFF (not implemented)\n"); /* TODO: Take out of standby mode */ -#ifdef CONFIG_PMCTWILED - msp_led_turn_on(MSP_LED_PWRSTANDBY_GREEN); - msp_led_turn_off(MSP_LED_PWRSTANDBY_RED); -#endif } static struct hwbutton_interrupt softreset_sw = { diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c index 5aec405..86b98e9 100644 --- a/arch/mips/pmc-sierra/yosemite/ht-irq.c +++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c @@ -35,18 +35,17 @@ */ void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_bus *current_bus = bus; - struct pci_dev *devices; - struct list_head *devices_link; + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; list_for_each(devices_link, &(current_bus->devices)) { - devices = pci_dev_b(devices_link); - if (devices == NULL) - continue; + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; } /* * PLX and SPKT related changes go here */ - } diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c index 51021cf..25bbbf4 100644 --- a/arch/mips/pmc-sierra/yosemite/irq.c +++ b/arch/mips/pmc-sierra/yosemite/irq.c @@ -150,8 +150,4 @@ void __init arch_init_irq(void) mips_cpu_irq_init(); rm7k_cpu_irq_init(); rm9k_cpu_irq_init(); - -#ifdef CONFIG_GDB_CONSOLE - register_gdb_console(); -#endif } diff --git a/arch/mips/pnx833x/Makefile b/arch/mips/pnx833x/Makefile new file mode 100644 index 0000000..02c4698 --- /dev/null +++ b/arch/mips/pnx833x/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SOC_PNX833X) += common/ +obj-$(CONFIG_NXP_STB220) += stb22x/ +obj-$(CONFIG_NXP_STB225) += stb22x/ diff --git a/arch/mips/pnx833x/Platform b/arch/mips/pnx833x/Platform new file mode 100644 index 0000000..7e6ec4d --- /dev/null +++ b/arch/mips/pnx833x/Platform @@ -0,0 +1,5 @@ +# NXP STB225 +platform-$(CONFIG_SOC_PNX833X) += pnx833x/ +cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x +load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 +load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 diff --git a/arch/mips/pnx833x/common/Makefile b/arch/mips/pnx833x/common/Makefile new file mode 100644 index 0000000..1a46dd2 --- /dev/null +++ b/arch/mips/pnx833x/common/Makefile @@ -0,0 +1 @@ +obj-y := interrupts.o platform.o prom.o setup.o reset.o diff --git a/arch/mips/pnx833x/common/interrupts.c b/arch/mips/pnx833x/common/interrupts.c new file mode 100644 index 0000000..941916f --- /dev/null +++ b/arch/mips/pnx833x/common/interrupts.c @@ -0,0 +1,379 @@ +/* + * interrupts.c: Interrupt mappings for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int mips_cpu_timer_irq; + +static const unsigned int irq_prio[PNX833X_PIC_NUM_IRQ] = +{ + 0, /* unused */ + 4, /* PNX833X_PIC_I2C0_INT 1 */ + 4, /* PNX833X_PIC_I2C1_INT 2 */ + 1, /* PNX833X_PIC_UART0_INT 3 */ + 1, /* PNX833X_PIC_UART1_INT 4 */ + 6, /* PNX833X_PIC_TS_IN0_DV_INT 5 */ + 6, /* PNX833X_PIC_TS_IN0_DMA_INT 6 */ + 7, /* PNX833X_PIC_GPIO_INT 7 */ + 4, /* PNX833X_PIC_AUDIO_DEC_INT 8 */ + 5, /* PNX833X_PIC_VIDEO_DEC_INT 9 */ + 4, /* PNX833X_PIC_CONFIG_INT 10 */ + 4, /* PNX833X_PIC_AOI_INT 11 */ + 9, /* PNX833X_PIC_SYNC_INT 12 */ + 9, /* PNX8335_PIC_SATA_INT 13 */ + 4, /* PNX833X_PIC_OSD_INT 14 */ + 9, /* PNX833X_PIC_DISP1_INT 15 */ + 4, /* PNX833X_PIC_DEINTERLACER_INT 16 */ + 9, /* PNX833X_PIC_DISPLAY2_INT 17 */ + 4, /* PNX833X_PIC_VC_INT 18 */ + 4, /* PNX833X_PIC_SC_INT 19 */ + 9, /* PNX833X_PIC_IDE_INT 20 */ + 9, /* PNX833X_PIC_IDE_DMA_INT 21 */ + 6, /* PNX833X_PIC_TS_IN1_DV_INT 22 */ + 6, /* PNX833X_PIC_TS_IN1_DMA_INT 23 */ + 4, /* PNX833X_PIC_SGDX_DMA_INT 24 */ + 4, /* PNX833X_PIC_TS_OUT_INT 25 */ + 4, /* PNX833X_PIC_IR_INT 26 */ + 3, /* PNX833X_PIC_VMSP1_INT 27 */ + 3, /* PNX833X_PIC_VMSP2_INT 28 */ + 4, /* PNX833X_PIC_PIBC_INT 29 */ + 4, /* PNX833X_PIC_TS_IN0_TRD_INT 30 */ + 4, /* PNX833X_PIC_SGDX_TPD_INT 31 */ + 5, /* PNX833X_PIC_USB_INT 32 */ + 4, /* PNX833X_PIC_TS_IN1_TRD_INT 33 */ + 4, /* PNX833X_PIC_CLOCK_INT 34 */ + 4, /* PNX833X_PIC_SGDX_PARSER_INT 35 */ + 4, /* PNX833X_PIC_VMSP_DMA_INT 36 */ +#if defined(CONFIG_SOC_PNX8335) + 4, /* PNX8335_PIC_MIU_INT 37 */ + 4, /* PNX8335_PIC_AVCHIP_IRQ_INT 38 */ + 9, /* PNX8335_PIC_SYNC_HD_INT 39 */ + 9, /* PNX8335_PIC_DISP_HD_INT 40 */ + 9, /* PNX8335_PIC_DISP_SCALER_INT 41 */ + 4, /* PNX8335_PIC_OSD_HD1_INT 42 */ + 4, /* PNX8335_PIC_DTL_WRITER_Y_INT 43 */ + 4, /* PNX8335_PIC_DTL_WRITER_C_INT 44 */ + 4, /* PNX8335_PIC_DTL_EMULATOR_Y_IR_INT 45 */ + 4, /* PNX8335_PIC_DTL_EMULATOR_C_IR_INT 46 */ + 4, /* PNX8335_PIC_DENC_TTX_INT 47 */ + 4, /* PNX8335_PIC_MMI_SIF0_INT 48 */ + 4, /* PNX8335_PIC_MMI_SIF1_INT 49 */ + 4, /* PNX8335_PIC_MMI_CDMMU_INT 50 */ + 4, /* PNX8335_PIC_PIBCS_INT 51 */ + 12, /* PNX8335_PIC_ETHERNET_INT 52 */ + 3, /* PNX8335_PIC_VMSP1_0_INT 53 */ + 3, /* PNX8335_PIC_VMSP1_1_INT 54 */ + 4, /* PNX8335_PIC_VMSP1_DMA_INT 55 */ + 4, /* PNX8335_PIC_TDGR_DE_INT 56 */ + 4, /* PNX8335_PIC_IR1_IRQ_INT 57 */ +#endif +}; + +static void pnx833x_timer_dispatch(void) +{ + do_IRQ(mips_cpu_timer_irq); +} + +static void pic_dispatch(void) +{ + unsigned int irq = PNX833X_REGFIELD(PIC_INT_SRC, INT_SRC); + + if ((irq >= 1) && (irq < (PNX833X_PIC_NUM_IRQ))) { + unsigned long priority = PNX833X_PIC_INT_PRIORITY; + PNX833X_PIC_INT_PRIORITY = irq_prio[irq]; + + if (irq == PNX833X_PIC_GPIO_INT) { + unsigned long mask = PNX833X_PIO_INT_STATUS & PNX833X_PIO_INT_ENABLE; + int pin; + while ((pin = ffs(mask & 0xffff))) { + pin -= 1; + do_IRQ(PNX833X_GPIO_IRQ_BASE + pin); + mask &= ~(1 << pin); + } + } else { + do_IRQ(irq + PNX833X_PIC_IRQ_BASE); + } + + PNX833X_PIC_INT_PRIORITY = priority; + } else { + printk(KERN_ERR "plat_irq_dispatch: unexpected irq %u\n", irq); + } +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & STATUSF_IP4) + pic_dispatch(); + else if (pending & STATUSF_IP7) + do_IRQ(PNX833X_TIMER_IRQ); + else + spurious_interrupt(); +} + +static inline void pnx833x_hard_enable_pic_irq(unsigned int irq) +{ + /* Currently we do this by setting IRQ priority to 1. + If priority support is being implemented, 1 should be repalced + by a better value. */ + PNX833X_PIC_INT_REG(irq) = irq_prio[irq]; +} + +static inline void pnx833x_hard_disable_pic_irq(unsigned int irq) +{ + /* Disable IRQ by writing setting it's priority to 0 */ + PNX833X_PIC_INT_REG(irq) = 0; +} + +static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */ +#define IRQFLAG_STARTED 1 +#define IRQFLAG_DISABLED 2 + +static DEFINE_RAW_SPINLOCK(pnx833x_irq_lock); + +static unsigned int pnx833x_startup_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */ + pnx833x_hard_enable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); + return 0; +} + +static void pnx833x_shutdown_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] = 0; /* not started */ + pnx833x_hard_disable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_enable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] &= ~IRQFLAG_DISABLED; + if (irqflags[pic_irq] == IRQFLAG_STARTED) + pnx833x_hard_enable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_disable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] |= IRQFLAG_DISABLED; + pnx833x_hard_disable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_ack_pic_irq(unsigned int irq) +{ +} + +static void pnx833x_end_pic_irq(unsigned int irq) +{ +} + +static DEFINE_RAW_SPINLOCK(pnx833x_gpio_pnx833x_irq_lock); + +static unsigned int pnx833x_startup_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_enable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); + return 0; +} + +static void pnx833x_enable_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_enable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static void pnx833x_disable_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_disable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static void pnx833x_ack_gpio_irq(unsigned int irq) +{ +} + +static void pnx833x_end_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_clear_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + int gpio_mode; + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + gpio_mode = GPIO_INT_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + gpio_mode = GPIO_INT_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + gpio_mode = GPIO_INT_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_HIGH: + gpio_mode = GPIO_INT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + gpio_mode = GPIO_INT_LEVEL_LOW; + break; + default: + gpio_mode = GPIO_INT_NONE; + break; + } + + pnx833x_gpio_setup_irq(gpio_mode, pin); + + return 0; +} + +static struct irq_chip pnx833x_pic_irq_type = { + .name = "PNX-PIC", + .startup = pnx833x_startup_pic_irq, + .shutdown = pnx833x_shutdown_pic_irq, + .enable = pnx833x_enable_pic_irq, + .disable = pnx833x_disable_pic_irq, + .ack = pnx833x_ack_pic_irq, + .end = pnx833x_end_pic_irq +}; + +static struct irq_chip pnx833x_gpio_irq_type = { + .name = "PNX-GPIO", + .startup = pnx833x_startup_gpio_irq, + .shutdown = pnx833x_disable_gpio_irq, + .enable = pnx833x_enable_gpio_irq, + .disable = pnx833x_disable_gpio_irq, + .ack = pnx833x_ack_gpio_irq, + .end = pnx833x_end_gpio_irq, + .set_type = pnx833x_set_type_gpio_irq +}; + +void __init arch_init_irq(void) +{ + unsigned int irq; + + /* setup standard internal cpu irqs */ + mips_cpu_irq_init(); + + /* Set IRQ information in irq_desc */ + for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { + pnx833x_hard_disable_pic_irq(irq); + set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); + } + + for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) + set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); + + /* Set PIC priority limiter register to 0 */ + PNX833X_PIC_INT_PRIORITY = 0; + + /* Setup GPIO IRQ dispatching */ + pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); + + /* Enable PIC IRQs (HWIRQ2) */ + if (cpu_has_vint) + set_vi_handler(4, pic_dispatch); + + write_c0_status(read_c0_status() | IE_IRQ2); +} + +unsigned int __cpuinit get_c0_compare_int(void) +{ + if (cpu_has_vint) + set_vi_handler(cp0_compare_irq, pnx833x_timer_dispatch); + + mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; + return mips_cpu_timer_irq; +} + +void __init plat_time_init(void) +{ + /* calculate mips_hpt_frequency based on PNX833X_CLOCK_CPUCP_CTL reg */ + + extern unsigned long mips_hpt_frequency; + unsigned long reg = PNX833X_CLOCK_CPUCP_CTL; + + if (!(PNX833X_BIT(reg, CLOCK_CPUCP_CTL, EXIT_RESET))) { + /* Functional clock is disabled so use crystal frequency */ + mips_hpt_frequency = 25; + } else { +#if defined(CONFIG_SOC_PNX8335) + /* Functional clock is enabled, so get clock multiplier */ + mips_hpt_frequency = 90 + (10 * PNX8335_REGFIELD(CLOCK_PLL_CPU_CTL, FREQ)); +#else + static const unsigned long int freq[4] = {240, 160, 120, 80}; + mips_hpt_frequency = freq[PNX833X_FIELD(reg, CLOCK_CPUCP_CTL, DIV_CLOCK)]; +#endif + } + + printk(KERN_INFO "CPU clock is %ld MHz\n", mips_hpt_frequency); + + mips_hpt_frequency *= 500000; +} diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c new file mode 100644 index 0000000..01f8345 --- /dev/null +++ b/arch/mips/pnx833x/common/platform.c @@ -0,0 +1,319 @@ +/* + * platform.c: platform support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_I2C_PNX0105 +/* Until i2c driver available in kernel.*/ +#include +#endif + +#include +#include +#include + +static u64 uart_dmamask = DMA_BIT_MASK(32); + +static struct resource pnx833x_uart_resources[] = { + [0] = { + .start = PNX833X_UART0_PORTS_START, + .end = PNX833X_UART0_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX833X_PIC_UART0_INT, + .end = PNX833X_PIC_UART0_INT, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = PNX833X_UART1_PORTS_START, + .end = PNX833X_UART1_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = PNX833X_PIC_UART1_INT, + .end = PNX833X_PIC_UART1_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct pnx8xxx_port pnx8xxx_ports[] = { + [0] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX833X_UART0_PORTS_START, + .mapbase = PNX833X_UART0_PORTS_START, + .irq = PNX833X_PIC_UART0_INT, + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + }, + [1] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX833X_UART1_PORTS_START, + .mapbase = PNX833X_UART1_PORTS_START, + .irq = PNX833X_PIC_UART1_INT, + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + }, +}; + +static struct platform_device pnx833x_uart_device = { + .name = "pnx8xxx-uart", + .id = -1, + .dev = { + .dma_mask = &uart_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = pnx8xxx_ports, + }, + .num_resources = ARRAY_SIZE(pnx833x_uart_resources), + .resource = pnx833x_uart_resources, +}; + +static u64 ehci_dmamask = DMA_BIT_MASK(32); + +static struct resource pnx833x_usb_ehci_resources[] = { + [0] = { + .start = PNX833X_USB_PORTS_START, + .end = PNX833X_USB_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX833X_PIC_USB_INT, + .end = PNX833X_PIC_USB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_usb_ehci_device = { + .name = "pnx833x-ehci", + .id = -1, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(pnx833x_usb_ehci_resources), + .resource = pnx833x_usb_ehci_resources, +}; + +#ifdef CONFIG_I2C_PNX0105 +static struct resource pnx833x_i2c0_resources[] = { + { + .start = PNX833X_I2C0_PORTS_START, + .end = PNX833X_I2C0_PORTS_END, + .flags = IORESOURCE_MEM, + }, + { + .start = PNX833X_PIC_I2C0_INT, + .end = PNX833X_PIC_I2C0_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource pnx833x_i2c1_resources[] = { + { + .start = PNX833X_I2C1_PORTS_START, + .end = PNX833X_I2C1_PORTS_END, + .flags = IORESOURCE_MEM, + }, + { + .start = PNX833X_PIC_I2C1_INT, + .end = PNX833X_PIC_I2C1_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { + { + .base = PNX833X_I2C0_PORTS_START, + .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ + .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */ + .bus_addr = 0, /* no slave support */ + }, + { + .base = PNX833X_I2C1_PORTS_START, + .irq = -1, /* on high freq, polling is faster */ + /*.irq = PNX833X_PIC_I2C1_INT,*/ + .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */ + .bus_addr = 0, /* no slave support */ + }, +}; + +static struct platform_device pnx833x_i2c0_device = { + .name = "i2c-pnx0105", + .id = 0, + .dev = { + .platform_data = &pnx833x_i2c_dev[0], + }, + .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources), + .resource = pnx833x_i2c0_resources, +}; + +static struct platform_device pnx833x_i2c1_device = { + .name = "i2c-pnx0105", + .id = 1, + .dev = { + .platform_data = &pnx833x_i2c_dev[1], + }, + .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources), + .resource = pnx833x_i2c1_resources, +}; +#endif + +static u64 ethernet_dmamask = DMA_BIT_MASK(32); + +static struct resource pnx833x_ethernet_resources[] = { + [0] = { + .start = PNX8335_IP3902_PORTS_START, + .end = PNX8335_IP3902_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8335_PIC_ETHERNET_INT, + .end = PNX8335_PIC_ETHERNET_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_ethernet_device = { + .name = "ip3902-eth", + .id = -1, + .dev = { + .dma_mask = ðernet_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(pnx833x_ethernet_resources), + .resource = pnx833x_ethernet_resources, +}; + +static struct resource pnx833x_sata_resources[] = { + [0] = { + .start = PNX8335_SATA_PORTS_START, + .end = PNX8335_SATA_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8335_PIC_SATA_INT, + .end = PNX8335_PIC_SATA_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_sata_device = { + .name = "pnx833x-sata", + .id = -1, + .num_resources = ARRAY_SIZE(pnx833x_sata_resources), + .resource = pnx833x_sata_resources, +}; + +static const char *part_probes[] = { + "cmdlinepart", + NULL +}; + +static void +pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_CLE_MASK)); + else + writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_ALE_MASK)); +} + +static struct platform_nand_data pnx833x_flash_nand_data = { + .chip = { + .chip_delay = 25, + .part_probe_types = part_probes, + }, + .ctrl = { + .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl + } +}; + +/* + * Set start to be the correct address (PNX8335_NAND_BASE with no 0xb!!), + * 12 bytes more seems to be the standard that allows for NAND access. + */ +static struct resource pnx833x_flash_nand_resource = { + .start = PNX8335_NAND_BASE, + .end = PNX8335_NAND_BASE + 12, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device pnx833x_flash_nand = { + .name = "gen_nand", + .id = -1, + .num_resources = 1, + .resource = &pnx833x_flash_nand_resource, + .dev = { + .platform_data = &pnx833x_flash_nand_data, + }, +}; + +static struct platform_device *pnx833x_platform_devices[] __initdata = { + &pnx833x_uart_device, + &pnx833x_usb_ehci_device, +#ifdef CONFIG_I2C_PNX0105 + &pnx833x_i2c0_device, + &pnx833x_i2c1_device, +#endif + &pnx833x_ethernet_device, + &pnx833x_sata_device, + &pnx833x_flash_nand, +}; + +static int __init pnx833x_platform_init(void) +{ + int res; + + res = platform_add_devices(pnx833x_platform_devices, + ARRAY_SIZE(pnx833x_platform_devices)); + + return res; +} + +arch_initcall(pnx833x_platform_init); diff --git a/arch/mips/pnx833x/common/prom.c b/arch/mips/pnx833x/common/prom.c new file mode 100644 index 0000000..29969f9 --- /dev/null +++ b/arch/mips/pnx833x/common/prom.c @@ -0,0 +1,64 @@ +/* + * prom.c: + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +void __init prom_init_cmdline(void) +{ + int argc = fw_arg0; + char **argv = (char **)fw_arg1; + char *c = &(arcs_cmdline[0]); + int i; + + for (i = 1; i < argc; i++) { + strcpy(c, argv[i]); + c += strlen(argv[i]); + if (i < argc-1) + *c++ = ' '; + } + *c = 0; +} + +char __init *prom_getenv(char *envname) +{ + extern char **prom_envp; + char **env = prom_envp; + int i; + + i = strlen(envname); + + while (*env) { + if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') + return *env + i + 1; + env++; + } + + return 0; +} + +void __init prom_free_prom_memory(void) +{ +} diff --git a/arch/mips/pnx833x/common/reset.c b/arch/mips/pnx833x/common/reset.c new file mode 100644 index 0000000..e0ea96d --- /dev/null +++ b/arch/mips/pnx833x/common/reset.c @@ -0,0 +1,44 @@ +/* + * reset.c: reset support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include + +void pnx833x_machine_restart(char *command) +{ + PNX833X_RESET_CONTROL_2 = 0; + PNX833X_RESET_CONTROL = 0; +} + +void pnx833x_machine_halt(void) +{ + while (1) + __asm__ __volatile__ ("wait"); + +} + +void pnx833x_machine_power_off(void) +{ + pnx833x_machine_halt(); +} diff --git a/arch/mips/pnx833x/common/setup.c b/arch/mips/pnx833x/common/setup.c new file mode 100644 index 0000000..e51fbc4 --- /dev/null +++ b/arch/mips/pnx833x/common/setup.c @@ -0,0 +1,64 @@ +/* + * setup.c: Setup PNX833X Soc. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +extern void pnx833x_board_setup(void); +extern void pnx833x_machine_restart(char *); +extern void pnx833x_machine_halt(void); +extern void pnx833x_machine_power_off(void); + +int __init plat_mem_setup(void) +{ + /* fake pci bus to avoid bounce buffers */ + PCI_DMA_BUS_IS_PHYS = 1; + + /* set mips clock to 320MHz */ +#if defined(CONFIG_SOC_PNX8335) + PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); +#endif + pnx833x_gpio_init(); /* so it will be ready in board_setup() */ + + pnx833x_board_setup(); + + _machine_restart = pnx833x_machine_restart; + _machine_halt = pnx833x_machine_halt; + pm_power_off = pnx833x_machine_power_off; + + /* IO/MEM resources. */ + set_io_port_base(KSEG1); + ioport_resource.start = 0; + ioport_resource.end = ~0; + iomem_resource.start = 0; + iomem_resource.end = ~0; + + return 0; +} diff --git a/arch/mips/pnx833x/stb22x/Makefile b/arch/mips/pnx833x/stb22x/Makefile new file mode 100644 index 0000000..7b58006 --- /dev/null +++ b/arch/mips/pnx833x/stb22x/Makefile @@ -0,0 +1 @@ +obj-y := board.o diff --git a/arch/mips/pnx833x/stb22x/board.c b/arch/mips/pnx833x/stb22x/board.c new file mode 100644 index 0000000..644eb7c --- /dev/null +++ b/arch/mips/pnx833x/stb22x/board.c @@ -0,0 +1,133 @@ +/* + * board.c: STB225 board support. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +/* endianess twiddlers */ +#define PNX8335_DEBUG0 0x4400 +#define PNX8335_DEBUG1 0x4404 +#define PNX8335_DEBUG2 0x4408 +#define PNX8335_DEBUG3 0x440c +#define PNX8335_DEBUG4 0x4410 +#define PNX8335_DEBUG5 0x4414 +#define PNX8335_DEBUG6 0x4418 +#define PNX8335_DEBUG7 0x441c + +int prom_argc; +char **prom_argv, **prom_envp; + +extern void prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP STB22x"; +} + +static inline unsigned long env_or_default(char *env, unsigned long dfl) +{ + char *str = prom_getenv(env); + return str ? simple_strtol(str, 0, 0) : dfl; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize = env_or_default("memsize", 0x02000000); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +void __init pnx833x_board_setup(void) +{ + pnx833x_gpio_select_function_alt(4); + pnx833x_gpio_select_output(4); + pnx833x_gpio_select_function_alt(5); + pnx833x_gpio_select_input(5); + pnx833x_gpio_select_function_alt(6); + pnx833x_gpio_select_input(6); + pnx833x_gpio_select_function_alt(7); + pnx833x_gpio_select_output(7); + + pnx833x_gpio_select_function_alt(25); + pnx833x_gpio_select_function_alt(26); + + pnx833x_gpio_select_function_alt(27); + pnx833x_gpio_select_function_alt(28); + pnx833x_gpio_select_function_alt(29); + pnx833x_gpio_select_function_alt(30); + pnx833x_gpio_select_function_alt(31); + pnx833x_gpio_select_function_alt(32); + pnx833x_gpio_select_function_alt(33); + +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + /* Setup MIU for NAND access on CS0... + * + * (it seems that we must also configure CS1 for reliable operation, + * otherwise the first read ID command will fail if it's read as 4 bytes + * but pass if it's read as 1 word.) + */ + + /* Setup MIU CS0 & CS1 timing */ + PNX833X_MIU_SEL0 = 0; + PNX833X_MIU_SEL1 = 0; + PNX833X_MIU_SEL0_TIMING = 0x50003081; + PNX833X_MIU_SEL1_TIMING = 0x50003081; + + /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ + pnx833x_gpio_select_function_alt(0); + + /* Setup GPIO 04 to input NAND read/busy signal */ + pnx833x_gpio_select_function_io(4); + pnx833x_gpio_select_input(4); + + /* Setup GPIO 05 to disable NAND write protect */ + pnx833x_gpio_select_function_io(5); + pnx833x_gpio_select_output(5); + pnx833x_gpio_write(1, 5); + +#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) + + /* Set up MIU for 16-bit NOR access on CS0 and CS1... */ + + /* Setup MIU CS0 & CS1 timing */ + PNX833X_MIU_SEL0 = 1; + PNX833X_MIU_SEL1 = 1; + PNX833X_MIU_SEL0_TIMING = 0x6A08D082; + PNX833X_MIU_SEL1_TIMING = 0x6A08D082; + + /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ + pnx833x_gpio_select_function_alt(0); +#endif +} diff --git a/arch/mips/pnx8550/Makefile b/arch/mips/pnx8550/Makefile new file mode 100644 index 0000000..3f7e856 --- /dev/null +++ b/arch/mips/pnx8550/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SOC_PNX8550) += common/ +obj-$(CONFIG_PNX8550_JBS) += jbs/ +obj-$(CONFIG_PNX8550_STB810) += stb810/ diff --git a/arch/mips/pnx8550/Platform b/arch/mips/pnx8550/Platform new file mode 100644 index 0000000..0e7fbde --- /dev/null +++ b/arch/mips/pnx8550/Platform @@ -0,0 +1,7 @@ +platform-$(CONFIG_SOC_PNX8550) += pnx8550/ + +cflags-$(CONFIG_SOC_PNX8550) += \ + -I$(srctree)/arch/mips/include/asm/mach-pnx8550 + +load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 +load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 diff --git a/arch/mips/pnx8550/common/Makefile b/arch/mips/pnx8550/common/Makefile new file mode 100644 index 0000000..f8ce695 --- /dev/null +++ b/arch/mips/pnx8550/common/Makefile @@ -0,0 +1,26 @@ +# +# Per Hallsmark, per.hallsmark@mvista.com +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# ####################################################################### +# +# Makefile for the PNX8550 specific kernel interface routines +# under Linux. +# + +obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/mips/pnx8550/common/int.c b/arch/mips/pnx8550/common/int.c new file mode 100644 index 0000000..cfed505 --- /dev/null +++ b/arch/mips/pnx8550/common/int.c @@ -0,0 +1,236 @@ +/* + * + * Copyright (C) 2005 Embedded Alley Solutions, Inc + * Ported to 2.6. + * + * Per Hallsmark, per.hallsmark@mvista.com + * Copyright (C) 2000, 2001 MIPS Technologies, Inc. + * Copyright (C) 2001 Ralf Baechle + * + * Cleaned up and bug fixing: Pete Popov, ppopov@embeddedalley.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* default prio for interrupts */ +/* first one is a no-no so therefore always prio 0 (disabled) */ +static char gic_prio[PNX8550_INT_GIC_TOTINT] = { + 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49 + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69 + 1 // 70 +}; + +static void hw0_irqdispatch(int irq) +{ + /* find out which interrupt */ + irq = PNX8550_GIC_VECTOR_0 >> 3; + + if (irq == 0) { + printk("hw0_irqdispatch: irq 0, spurious interrupt?\n"); + return; + } + do_IRQ(PNX8550_INT_GIC_MIN + irq); +} + + +static void timer_irqdispatch(int irq) +{ + irq = (0x01c0 & read_c0_config7()) >> 6; + + if (unlikely(irq == 0)) { + printk("timer_irqdispatch: irq 0, spurious interrupt?\n"); + return; + } + + if (irq & 0x1) + do_IRQ(PNX8550_INT_TIMER1); + if (irq & 0x2) + do_IRQ(PNX8550_INT_TIMER2); + if (irq & 0x4) + do_IRQ(PNX8550_INT_TIMER3); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + + if (pending & STATUSF_IP2) + hw0_irqdispatch(2); + else if (pending & STATUSF_IP7) { + if (read_c0_config7() & 0x01c0) + timer_irqdispatch(7); + } else + spurious_interrupt(); +} + +static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +{ + unsigned long status = read_c0_status(); + + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + + write_c0_status(status); +} + +static inline void mask_gic_int(unsigned int irq_nr) +{ + /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */ + PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */ +} + +static inline void unmask_gic_int(unsigned int irq_nr) +{ + /* set prio mask to lower four bits and enable interrupt */ + PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr]; +} + +static inline void mask_irq(unsigned int irq_nr) +{ + if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { + modify_cp0_intmask(1 << irq_nr, 0); + } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_GIC_MAX)) { + mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); + } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_TIMER_MAX)) { + modify_cp0_intmask(1 << 7, 0); + } else { + printk("mask_irq: irq %d doesn't exist!\n", irq_nr); + } +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { + modify_cp0_intmask(0, 1 << irq_nr); + } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_GIC_MAX)) { + unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); + } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_TIMER_MAX)) { + modify_cp0_intmask(0, 1 << 7); + } else { + printk("mask_irq: irq %d doesn't exist!\n", irq_nr); + } +} + +int pnx8550_set_gic_priority(int irq, int priority) +{ + int gic_irq = irq-PNX8550_INT_GIC_MIN; + int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf; + + gic_prio[gic_irq] = priority; + PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]); + + return prev_priority; +} + +static struct irq_chip level_irq_type = { + .name = "PNX Level IRQ", + .ack = mask_irq, + .mask = mask_irq, + .mask_ack = mask_irq, + .unmask = unmask_irq, +}; + +static struct irqaction gic_action = { + .handler = no_action, + .flags = IRQF_DISABLED, + .name = "GIC", +}; + +static struct irqaction timer_action = { + .handler = no_action, + .flags = IRQF_DISABLED | IRQF_TIMER, + .name = "Timer", +}; + +void __init arch_init_irq(void) +{ + int i; + int configPR; + + for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + mask_irq(i); /* mask the irq just in case */ + } + + /* init of GIC/IPC interrupts */ + /* should be done before cp0 since cp0 init enables the GIC int */ + for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) { + int gic_int_line = i - PNX8550_INT_GIC_MIN; + if (gic_int_line == 0 ) + continue; // don't fiddle with int 0 + /* + * enable change of TARGET, ENABLE and ACTIVE_LOW bits + * set TARGET 0 to route through hw0 interrupt + * set ACTIVE_LOW 0 active high (correct?) + * + * We really should setup an interrupt description table + * to do this nicely. + * Note, PCI INTA is active low on the bus, but inverted + * in the GIC, so to us it's active high. + */ + PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000; + + /* mask/priority is still 0 so we will not get any + * interrupts until it is unmasked */ + + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + } + + /* Priority level 0 */ + PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0; + + /* Set int vector table address */ + PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0; + + set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type, + handle_level_irq); + setup_irq(MIPS_CPU_GIC_IRQ, &gic_action); + + /* init of Timer interrupts */ + for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + + /* Stop Timer 1-3 */ + configPR = read_c0_config7(); + configPR |= 0x00000038; + write_c0_config7(configPR); + + set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type, + handle_level_irq); + setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action); +} + +EXPORT_SYMBOL(pnx8550_set_gic_priority); diff --git a/arch/mips/pnx8550/common/pci.c b/arch/mips/pnx8550/common/pci.c new file mode 100644 index 0000000..98e86dd --- /dev/null +++ b/arch/mips/pnx8550/common/pci.c @@ -0,0 +1,134 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ +#include +#include +#include +#include + +#include +#include +#include + +static struct resource pci_io_resource = { + .start = PNX8550_PCIIO + 0x1000, /* reserve regacy I/O space */ + .end = PNX8550_PCIIO + PNX8550_PCIIO_SIZE, + .name = "pci IO space", + .flags = IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + .start = PNX8550_PCIMEM, + .end = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1, + .name = "pci memory space", + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops pnx8550_pci_ops; + +static struct pci_controller pnx8550_controller = { + .pci_ops = &pnx8550_pci_ops, + .io_map_base = PNX8550_PORT_BASE, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +/* Return the total size of DRAM-memory, (RANK0 + RANK1) */ +static inline unsigned long get_system_mem_size(void) +{ + /* Read IP2031_RANK0_ADDR_LO */ + unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); + /* Read IP2031_RANK1_ADDR_HI */ + unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); + + return dram_r1_hi - dram_r0_lo + 1; +} + +static int __init pnx8550_pci_setup(void) +{ + int pci_mem_code; + int mem_size = get_system_mem_size() >> 20; + + /* Clear the Global 2 Register, PCI Inta Output Enable Registers + Bit 1:Enable DAC Powerdown + -> 0:DACs are enabled and are working normally + 1:DACs are powerdown + Bit 0:Enable of PCI inta output + -> 0 = Disable PCI inta output + 1 = Enable PCI inta output + */ + PNX8550_GLB2_ENAB_INTA_O = 0; + + /* Calc the PCI mem size code */ + if (mem_size >= 128) + pci_mem_code = SIZE_128M; + else if (mem_size >= 64) + pci_mem_code = SIZE_64M; + else if (mem_size >= 32) + pci_mem_code = SIZE_32M; + else + pci_mem_code = SIZE_16M; + + /* Set PCI_XIO registers */ + outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO); + outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI); + outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO); + outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI); + + /* Send memory transaction via PCI_BASE2 */ + outl(0x00000001, PCI_BASE | PCI_IO); + + /* Unlock the setup register */ + outl(0xca, PCI_BASE | PCI_UNLOCKREG); + + /* + * BAR0 of PNX8550 (pci base 10) must be zero in order for ide + * to work, and in order for bus_to_baddr to work without any + * hacks. + */ + outl(0x00000000, PCI_BASE | PCI_BASE10); + + /* + *These two bars are set by default or the boot code. + * However, it's safer to set them here so we're not boot + * code dependent. + */ + outl(0x1be00000, PCI_BASE | PCI_BASE14); /* PNX MMIO */ + outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18); /* XIO */ + + outl(PCI_EN_TA | + PCI_EN_PCI2MMI | + PCI_EN_XIO | + PCI_SETUP_BASE18_SIZE(SIZE_32M) | + PCI_SETUP_BASE18_EN | + PCI_SETUP_BASE14_EN | + PCI_SETUP_BASE10_PREF | + PCI_SETUP_BASE10_SIZE(pci_mem_code) | + PCI_SETUP_CFGMANAGE_EN | + PCI_SETUP_PCIARB_EN, + PCI_BASE | + PCI_SETUP); /* PCI_SETUP */ + outl(0x00000000, PCI_BASE | PCI_CTRL); /* PCI_CONTROL */ + + register_pci_controller(&pnx8550_controller); + + return 0; +} + +arch_initcall(pnx8550_pci_setup); diff --git a/arch/mips/pnx8550/common/platform.c b/arch/mips/pnx8550/common/platform.c new file mode 100644 index 0000000..5264cc0 --- /dev/null +++ b/arch/mips/pnx8550/common/platform.c @@ -0,0 +1,133 @@ +/* + * Platform device support for NXP PNX8550 SoCs + * + * Copyright 2005, Embedded Alley Solutions, Inc + * + * Based on arch/mips/au1000/common/platform.c + * Platform device support for Au1x00 SoCs. + * + * Copyright 2004, Matt Porter + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct resource pnx8550_usb_ohci_resources[] = { + [0] = { + .start = PNX8550_USB_OHCI_OP_BASE, + .end = PNX8550_USB_OHCI_OP_BASE + + PNX8550_USB_OHCI_OP_LEN, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8550_INT_USB, + .end = PNX8550_INT_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource pnx8550_uart_resources[] = { + [0] = { + .start = PNX8550_UART_PORT0, + .end = PNX8550_UART_PORT0 + 0xfff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8550_UART_INT(0), + .end = PNX8550_UART_INT(0), + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = PNX8550_UART_PORT1, + .end = PNX8550_UART_PORT1 + 0xfff, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = PNX8550_UART_INT(1), + .end = PNX8550_UART_INT(1), + .flags = IORESOURCE_IRQ, + }, +}; + +struct pnx8xxx_port pnx8xxx_ports[] = { + [0] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX8550_UART_PORT0, + .mapbase = PNX8550_UART_PORT0, + .irq = PNX8550_UART_INT(0), + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + }, + [1] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX8550_UART_PORT1, + .mapbase = PNX8550_UART_PORT1, + .irq = PNX8550_UART_INT(1), + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + }, +}; + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = DMA_BIT_MASK(32); + +static u64 uart_dmamask = DMA_BIT_MASK(32); + +static struct platform_device pnx8550_usb_ohci_device = { + .name = "pnx8550-ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(pnx8550_usb_ohci_resources), + .resource = pnx8550_usb_ohci_resources, +}; + +static struct platform_device pnx8550_uart_device = { + .name = "pnx8xxx-uart", + .id = -1, + .dev = { + .dma_mask = &uart_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = pnx8xxx_ports, + }, + .num_resources = ARRAY_SIZE(pnx8550_uart_resources), + .resource = pnx8550_uart_resources, +}; + +static struct platform_device *pnx8550_platform_devices[] __initdata = { + &pnx8550_usb_ohci_device, + &pnx8550_uart_device, +}; + +static int __init pnx8550_platform_init(void) +{ + return platform_add_devices(pnx8550_platform_devices, + ARRAY_SIZE(pnx8550_platform_devices)); +} + +arch_initcall(pnx8550_platform_init); diff --git a/arch/mips/pnx8550/common/proc.c b/arch/mips/pnx8550/common/proc.c new file mode 100644 index 0000000..3bba5ec --- /dev/null +++ b/arch/mips/pnx8550/common/proc.c @@ -0,0 +1,110 @@ +/* + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +static int pnx8550_timers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) +{ + int len = 0; + int configPR = read_c0_config7(); + + if (offset==0) { + len += sprintf(&page[len], "Timer: count, compare, tc, status\n"); + len += sprintf(&page[len], " 1: %11i, %8i, %1i, %s\n", + read_c0_count(), read_c0_compare(), + (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on"); + len += sprintf(&page[len], " 2: %11i, %8i, %1i, %s\n", + read_c0_count2(), read_c0_compare2(), + (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on"); + len += sprintf(&page[len], " 3: %11i, %8i, %1i, %s\n", + read_c0_count3(), read_c0_compare3(), + (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on"); + } + + return len; +} + +static int pnx8550_registers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) +{ + int len = 0; + + if (offset==0) { + len += sprintf(&page[len], "config1: %#10.8x\n", read_c0_config1()); + len += sprintf(&page[len], "config2: %#10.8x\n", read_c0_config2()); + len += sprintf(&page[len], "config3: %#10.8x\n", read_c0_config3()); + len += sprintf(&page[len], "configPR: %#10.8x\n", read_c0_config7()); + len += sprintf(&page[len], "status: %#10.8x\n", read_c0_status()); + len += sprintf(&page[len], "cause: %#10.8x\n", read_c0_cause()); + len += sprintf(&page[len], "count: %#10.8x\n", read_c0_count()); + len += sprintf(&page[len], "count_2: %#10.8x\n", read_c0_count2()); + len += sprintf(&page[len], "count_3: %#10.8x\n", read_c0_count3()); + len += sprintf(&page[len], "compare: %#10.8x\n", read_c0_compare()); + len += sprintf(&page[len], "compare_2: %#10.8x\n", read_c0_compare2()); + len += sprintf(&page[len], "compare_3: %#10.8x\n", read_c0_compare3()); + } + + return len; +} + +static struct proc_dir_entry* pnx8550_dir; +static struct proc_dir_entry* pnx8550_timers; +static struct proc_dir_entry* pnx8550_registers; + +static int pnx8550_proc_init( void ) +{ + + // Create /proc/pnx8550 + pnx8550_dir = proc_mkdir("pnx8550", NULL); + if (!pnx8550_dir) { + printk(KERN_ERR "Can't create pnx8550 proc dir\n"); + return -1; + } + + // Create /proc/pnx8550/timers + pnx8550_timers = create_proc_read_entry( + "timers", + 0, + pnx8550_dir, + pnx8550_timers_read, + NULL); + + if (!pnx8550_timers) + printk(KERN_ERR "Can't create pnx8550 timers proc file\n"); + + // Create /proc/pnx8550/registers + pnx8550_registers = create_proc_read_entry( + "registers", + 0, + pnx8550_dir, + pnx8550_registers_read, + NULL); + + if (!pnx8550_registers) + printk(KERN_ERR "Can't create pnx8550 registers proc file\n"); + + return 0; +} + +__initcall(pnx8550_proc_init); diff --git a/arch/mips/pnx8550/common/prom.c b/arch/mips/pnx8550/common/prom.c new file mode 100644 index 0000000..32f7009 --- /dev/null +++ b/arch/mips/pnx8550/common/prom.c @@ -0,0 +1,128 @@ +/* + * + * Per Hallsmark, per.hallsmark@mvista.com + * + * Based on jmr3927/common/prom.c + * + * 2004 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include +#include + +#include +#include + +/* #define DEBUG_CMDLINE */ + +extern int prom_argc; +extern char **prom_argv, **prom_envp; + +typedef struct +{ + char *name; +/* char *val; */ +}t_env_var; + + +char * prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void __init prom_init_cmdline(void) +{ + int i; + + arcs_cmdline[0] = '\0'; + for (i = 0; i < prom_argc; i++) { + strcat(arcs_cmdline, prom_argv[i]); + strcat(arcs_cmdline, " "); + } +} + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + * Environment variables are stored in the form of "memsize=64". + */ + + t_env_var *env = (t_env_var *)prom_envp; + int i; + + i = strlen(envname); + + while(env->name) { + if(strncmp(envname, env->name, i) == 0) { + return(env->name + strlen(envname) + 1); + } + env++; + } + return(NULL); +} + +inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + if(c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; /* foo */ +} + +inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for(i = 0; i < 6; i++) { + unsigned char num; + + if((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + printk("ethaddr not set in boot prom\n"); + return -1; + } + str2eaddr(ethernet_addr, ethaddr_str); + return 0; +} + +void __init prom_free_prom_memory(void) +{ +} + +extern int pnx8550_console_port; + +/* used by early printk */ +void prom_putchar(char c) +{ + if (pnx8550_console_port != -1) { + /* Wait until FIFO not full */ + while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) >= 16) + ; + /* Send one char */ + ip3106_fifo(UART_BASE, pnx8550_console_port) = c; + } +} + +EXPORT_SYMBOL(get_ethernet_addr); +EXPORT_SYMBOL(str2eaddr); diff --git a/arch/mips/pnx8550/common/reset.c b/arch/mips/pnx8550/common/reset.c new file mode 100644 index 0000000..fadd874 --- /dev/null +++ b/arch/mips/pnx8550/common/reset.c @@ -0,0 +1,50 @@ +/*. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Reset the PNX8550 board. + * + */ +#include + +#include +#include + +void pnx8550_machine_restart(char *command) +{ + char head[] = "************* Machine restart *************"; + char foot[] = "*******************************************"; + + printk("\n\n"); + printk("%s\n", head); + if (command != NULL) + printk("* %s\n", command); + printk("%s\n", foot); + + PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST; +} + +void pnx8550_machine_halt(void) +{ + printk("*** Machine halt. (Not implemented) ***\n"); +} + +void pnx8550_machine_power_off(void) +{ + printk("*** Machine power off. (Not implemented) ***\n"); +} diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c new file mode 100644 index 0000000..64246c9 --- /dev/null +++ b/arch/mips/pnx8550/common/setup.c @@ -0,0 +1,145 @@ +/* + * + * 2.6 port, Embedded Alley Solutions, Inc + * + * Based on Per Hallsmark, per.hallsmark@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +extern void __init board_setup(void); +extern void pnx8550_machine_restart(char *); +extern void pnx8550_machine_halt(void); +extern void pnx8550_machine_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; +extern char *prom_getcmdline(void); + +struct resource standard_io_resources[] = { + { + .start = 0x00, + .end = 0x1f, + .name = "dma1", + .flags = IORESOURCE_BUSY + }, { + .start = 0x40, + .end = 0x5f, + .name = "timer", + .flags = IORESOURCE_BUSY + }, { + .start = 0x80, + .end = 0x8f, + .name = "dma page reg", + .flags = IORESOURCE_BUSY + }, { + .start = 0xc0, + .end = 0xdf, + .name = "dma2", + .flags = IORESOURCE_BUSY + }, +}; + +#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources) + +extern struct resource pci_io_resource; +extern struct resource pci_mem_resource; + +/* Return the total size of DRAM-memory, (RANK0 + RANK1) */ +unsigned long get_system_mem_size(void) +{ + /* Read IP2031_RANK0_ADDR_LO */ + unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); + /* Read IP2031_RANK1_ADDR_HI */ + unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); + + return dram_r1_hi - dram_r0_lo + 1; +} + +int pnx8550_console_port = -1; + +void __init plat_mem_setup(void) +{ + int i; + char* argptr; + + board_setup(); /* board specific setup */ + + _machine_restart = pnx8550_machine_restart; + _machine_halt = pnx8550_machine_halt; + pm_power_off = pnx8550_machine_power_off; + + /* Clear the Global 2 Register, PCI Inta Output Enable Registers + Bit 1:Enable DAC Powerdown + -> 0:DACs are enabled and are working normally + 1:DACs are powerdown + Bit 0:Enable of PCI inta output + -> 0 = Disable PCI inta output + 1 = Enable PCI inta output + */ + PNX8550_GLB2_ENAB_INTA_O = 0; + + /* IO/MEM resources. */ + set_io_port_base(PNX8550_PORT_BASE); + ioport_resource.start = 0; + ioport_resource.end = ~0; + iomem_resource.start = 0; + iomem_resource.end = ~0; + + /* Request I/O space for devices on this board */ + for (i = 0; i < STANDARD_IO_RESOURCES; i++) + request_resource(&ioport_resource, standard_io_resources + i); + + /* Place the Mode Control bit for GPIO pin 16 in primary function */ + /* Pin 16 is used by UART1, UA1_TX */ + outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) | + (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT), + PNX8550_GPIO_MC1); + + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "console=ttyS")) != NULL) { + argptr += strlen("console=ttyS"); + pnx8550_console_port = *argptr == '0' ? 0 : 1; + + /* We must initialize the UART (console) before early printk */ + /* Set LCR to 8-bit and BAUD to 38400 (no 5) */ + ip3106_lcr(UART_BASE, pnx8550_console_port) = + PNX8XXX_UART_LCR_8BIT; + ip3106_baud(UART_BASE, pnx8550_console_port) = 5; + } + + return; +} diff --git a/arch/mips/pnx8550/common/time.c b/arch/mips/pnx8550/common/time.c new file mode 100644 index 0000000..8836c62 --- /dev/null +++ b/arch/mips/pnx8550/common/time.c @@ -0,0 +1,151 @@ +/* + * Copyright 2001, 2002, 2003 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + * + * Common time service routines for MIPS machines. See + * Documents/MIPS/README.txt. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +static unsigned long cpj; + +static cycle_t hpt_read(struct clocksource *cs) +{ + return read_c0_count2(); +} + +static struct clocksource pnx_clocksource = { + .name = "pnx8xxx", + .rating = 200, + .read = hpt_read, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *c = dev_id; + + /* clear MATCH, signal the event */ + c->event_handler(c); + + return IRQ_HANDLED; +} + +static struct irqaction pnx8xxx_timer_irq = { + .handler = pnx8xxx_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .name = "pnx8xxx_timer", +}; + +static irqreturn_t monotonic_interrupt(int irq, void *dev_id) +{ + /* Timer 2 clear interrupt */ + write_c0_compare2(-1); + return IRQ_HANDLED; +} + +static struct irqaction monotonic_irqaction = { + .handler = monotonic_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .name = "Monotonic timer", +}; + +static int pnx8xxx_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + write_c0_compare(delta); + return 0; +} + +static struct clock_event_device pnx8xxx_clockevent = { + .name = "pnx8xxx_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = pnx8xxx_set_next_event, +}; + +static inline void timer_ack(void) +{ + write_c0_compare(cpj); +} + +__init void plat_time_init(void) +{ + unsigned int configPR; + unsigned int n; + unsigned int m; + unsigned int p; + unsigned int pow2p; + + pnx8xxx_clockevent.cpumask = cpu_none_mask; + clockevents_register_device(&pnx8xxx_clockevent); + clocksource_register(&pnx_clocksource); + + /* Timer 1 start */ + configPR = read_c0_config7(); + configPR &= ~0x00000008; + write_c0_config7(configPR); + + /* Timer 2 start */ + configPR = read_c0_config7(); + configPR &= ~0x00000010; + write_c0_config7(configPR); + + /* Timer 3 stop */ + configPR = read_c0_config7(); + configPR |= 0x00000020; + write_c0_config7(configPR); + + + /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ + /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ + + n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; + m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; + p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; + pow2p = (1 << p); + + db_assert(m != 0 && pow2p != 0); + + /* + * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 + * (a.k.a. 8-10). Divide by HZ for a timer offset that results in + * HZ timer interrupts per second. + */ + mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p)); + cpj = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); + write_c0_count(0); + timer_ack(); + + /* Setup Timer 2 */ + write_c0_count2(0); + write_c0_compare2(0xffffffff); + + setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); + setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); +} diff --git a/arch/mips/pnx8550/jbs/Makefile b/arch/mips/pnx8550/jbs/Makefile new file mode 100644 index 0000000..c4dc3d5 --- /dev/null +++ b/arch/mips/pnx8550/jbs/Makefile @@ -0,0 +1,4 @@ + +# Makefile for the NXP JBS Board. + +obj-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/pnx8550/jbs/board_setup.c b/arch/mips/pnx8550/jbs/board_setup.c new file mode 100644 index 0000000..57dd903 --- /dev/null +++ b/arch/mips/pnx8550/jbs/board_setup.c @@ -0,0 +1,56 @@ +/* + * JBS Specific board startup routines. + * + * Copyright 2005, Embedded Alley Solutions, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +void __init board_setup(void) +{ + unsigned long configpr; + + configpr = read_c0_config7(); + configpr |= (1<<19); /* enable tlb */ + write_c0_config7(configpr); + BARRIER; +} diff --git a/arch/mips/pnx8550/jbs/init.c b/arch/mips/pnx8550/jbs/init.c new file mode 100644 index 0000000..d59b4a4 --- /dev/null +++ b/arch/mips/pnx8550/jbs/init.c @@ -0,0 +1,53 @@ +/* + * + * Copyright 2005 Embedded Alley Solutions, Inc + * source@embeddedalley.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP PNX8550/JBS"; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + //memsize = 0x02800000; /* Trimedia uses memory above */ + memsize = 0x08000000; /* Trimedia uses memory above */ + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/pnx8550/jbs/irqmap.c b/arch/mips/pnx8550/jbs/irqmap.c new file mode 100644 index 0000000..7fc8984 --- /dev/null +++ b/arch/mips/pnx8550/jbs/irqmap.c @@ -0,0 +1,35 @@ +/* + * NXP JBS board irqmap. + * + * Copyright 2005 Embedded Alley Solutions, Inc + * source@embeddealley.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +char pnx8550_irq_tab[][5] __initdata = { + [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, +}; diff --git a/arch/mips/pnx8550/stb810/Makefile b/arch/mips/pnx8550/stb810/Makefile new file mode 100644 index 0000000..cb4ff02 --- /dev/null +++ b/arch/mips/pnx8550/stb810/Makefile @@ -0,0 +1,4 @@ + +# Makefile for the NXP STB810 Board. + +obj-y := prom_init.o board_setup.o irqmap.o diff --git a/arch/mips/pnx8550/stb810/board_setup.c b/arch/mips/pnx8550/stb810/board_setup.c new file mode 100644 index 0000000..af2a55e --- /dev/null +++ b/arch/mips/pnx8550/stb810/board_setup.c @@ -0,0 +1,41 @@ +/* + * STB810 specific board startup routines. + * + * Based on the arch/mips/nxp/pnx8550/jbs/board_setup.c + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2005 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +void __init board_setup(void) +{ + unsigned long configpr; + + configpr = read_c0_config7(); + configpr |= (1<<19); /* enable tlb */ + write_c0_config7(configpr); +} diff --git a/arch/mips/pnx8550/stb810/irqmap.c b/arch/mips/pnx8550/stb810/irqmap.c new file mode 100644 index 0000000..8c03496 --- /dev/null +++ b/arch/mips/pnx8550/stb810/irqmap.c @@ -0,0 +1,22 @@ +/* + * NXP STB810 board irqmap. + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2005 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +char pnx8550_irq_tab[][5] __initdata = { + [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, +}; diff --git a/arch/mips/pnx8550/stb810/prom_init.c b/arch/mips/pnx8550/stb810/prom_init.c new file mode 100644 index 0000000..ca7f4ad --- /dev/null +++ b/arch/mips/pnx8550/stb810/prom_init.c @@ -0,0 +1,46 @@ +/* + * STB810 specific prom routines + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2005 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP PNX8950/STB810"; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + prom_argc = (int) fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; + + prom_init_cmdline(); + + memsize = 0x08000000; /* Trimedia uses memory above */ + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index 0a0d73c..baf6e90 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile @@ -23,6 +23,9 @@ # under Linux. # -obj-y += init.o memory.o reset.o time.o powertv_setup.o asic/ pci/ +obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ + asic/ pci/ -EXTRA_CFLAGS += -Wall -Werror +obj-$(CONFIG_USB) += powertv-usb.o + +EXTRA_CFLAGS += -Wall diff --git a/arch/mips/powertv/Platform b/arch/mips/powertv/Platform new file mode 100644 index 0000000..4eb5af1 --- /dev/null +++ b/arch/mips/powertv/Platform @@ -0,0 +1,7 @@ +# +# Cisco PowerTV Platform +# +platform-$(CONFIG_POWERTV) += powertv/ +cflags-$(CONFIG_POWERTV) += \ + -I$(srctree)/arch/mips/include/asm/mach-powertv +load-$(CONFIG_POWERTV) += 0xffffffff90800000 diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile index bebfdcf..f0e95dc 100644 --- a/arch/mips/powertv/asic/Makefile +++ b/arch/mips/powertv/asic/Makefile @@ -16,8 +16,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -obj-y += asic-calliope.o asic-cronus.o asic-zeus.o asic_devices.o asic_int.o \ - irq_asic.o prealloc-calliope.o prealloc-cronus.o \ - prealloc-cronuslite.o prealloc-zeus.o +obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \ + asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \ + prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o EXTRA_CFLAGS += -Wall -Werror diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c index 1ae6623..0a170e0 100644 --- a/arch/mips/powertv/asic/asic-calliope.c +++ b/arch/mips/powertv/asic/asic-calliope.c @@ -77,7 +77,7 @@ const struct register_map calliope_register_map __initdata = { .int_docsis_en = {.phys = CALLIOPE_ADDR(0xA028F4)}, .mips_pll_setup = {.phys = CALLIOPE_ADDR(0x980000)}, - .usb_fs = {.phys = CALLIOPE_ADDR(0x980030)}, + .fs432x4b4_usb_ctl = {.phys = CALLIOPE_ADDR(0x980030)}, .test_bus = {.phys = CALLIOPE_ADDR(0x9800CC)}, .crt_spare = {.phys = CALLIOPE_ADDR(0x9800d4)}, .usb2_ohci_int_mask = {.phys = CALLIOPE_ADDR(0x9A000c)}, diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c index 5bb64bf..bbc0c12 100644 --- a/arch/mips/powertv/asic/asic-cronus.c +++ b/arch/mips/powertv/asic/asic-cronus.c @@ -77,13 +77,13 @@ const struct register_map cronus_register_map __initdata = { .int_docsis_en = {.phys = CRONUS_ADDR(0x2A28F4)}, .mips_pll_setup = {.phys = CRONUS_ADDR(0x1C0000)}, - .usb_fs = {.phys = CRONUS_ADDR(0x1C0018)}, + .fs432x4b4_usb_ctl = {.phys = CRONUS_ADDR(0x1C0028)}, .test_bus = {.phys = CRONUS_ADDR(0x1C00CC)}, .crt_spare = {.phys = CRONUS_ADDR(0x1c00d4)}, .usb2_ohci_int_mask = {.phys = CRONUS_ADDR(0x20000C)}, .usb2_strap = {.phys = CRONUS_ADDR(0x200014)}, .ehci_hcapbase = {.phys = CRONUS_ADDR(0x21FE00)}, - .ohci_hc_revision = {.phys = CRONUS_ADDR(0x1E0000)}, + .ohci_hc_revision = {.phys = CRONUS_ADDR(0x21fc00)}, .bcm1_bs_lmi_steer = {.phys = CRONUS_ADDR(0x2E0008)}, .usb2_control = {.phys = CRONUS_ADDR(0x2E004C)}, .usb2_stbus_obc = {.phys = CRONUS_ADDR(0x21FF00)}, diff --git a/arch/mips/powertv/asic/asic-gaia.c b/arch/mips/powertv/asic/asic-gaia.c new file mode 100644 index 0000000..91dda68 --- /dev/null +++ b/arch/mips/powertv/asic/asic-gaia.c @@ -0,0 +1,96 @@ +/* + * Locations of devices in the Gaia ASIC + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: David VomLehn + */ + +#include +#include + +const struct register_map gaia_register_map __initdata = { + .eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000}, + .eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038}, + .eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C}, + + .chipver3 = {.phys = GAIA_IO_BASE + 0x2A0800}, + .chipver2 = {.phys = GAIA_IO_BASE + 0x2A0804}, + .chipver1 = {.phys = GAIA_IO_BASE + 0x2A0808}, + .chipver0 = {.phys = GAIA_IO_BASE + 0x2A080C}, + + /* The registers of IRBlaster */ + .uart1_intstat = {.phys = GAIA_IO_BASE + 0x2A1800}, + .uart1_inten = {.phys = GAIA_IO_BASE + 0x2A1804}, + .uart1_config1 = {.phys = GAIA_IO_BASE + 0x2A1808}, + .uart1_config2 = {.phys = GAIA_IO_BASE + 0x2A180C}, + .uart1_divisorhi = {.phys = GAIA_IO_BASE + 0x2A1810}, + .uart1_divisorlo = {.phys = GAIA_IO_BASE + 0x2A1814}, + .uart1_data = {.phys = GAIA_IO_BASE + 0x2A1818}, + .uart1_status = {.phys = GAIA_IO_BASE + 0x2A181C}, + + .int_stat_3 = {.phys = GAIA_IO_BASE + 0x2A2800}, + .int_stat_2 = {.phys = GAIA_IO_BASE + 0x2A2804}, + .int_stat_1 = {.phys = GAIA_IO_BASE + 0x2A2808}, + .int_stat_0 = {.phys = GAIA_IO_BASE + 0x2A280C}, + .int_config = {.phys = GAIA_IO_BASE + 0x2A2810}, + .int_int_scan = {.phys = GAIA_IO_BASE + 0x2A2818}, + .ien_int_3 = {.phys = GAIA_IO_BASE + 0x2A2830}, + .ien_int_2 = {.phys = GAIA_IO_BASE + 0x2A2834}, + .ien_int_1 = {.phys = GAIA_IO_BASE + 0x2A2838}, + .ien_int_0 = {.phys = GAIA_IO_BASE + 0x2A283C}, + .int_level_3_3 = {.phys = GAIA_IO_BASE + 0x2A2880}, + .int_level_3_2 = {.phys = GAIA_IO_BASE + 0x2A2884}, + .int_level_3_1 = {.phys = GAIA_IO_BASE + 0x2A2888}, + .int_level_3_0 = {.phys = GAIA_IO_BASE + 0x2A288C}, + .int_level_2_3 = {.phys = GAIA_IO_BASE + 0x2A2890}, + .int_level_2_2 = {.phys = GAIA_IO_BASE + 0x2A2894}, + .int_level_2_1 = {.phys = GAIA_IO_BASE + 0x2A2898}, + .int_level_2_0 = {.phys = GAIA_IO_BASE + 0x2A289C}, + .int_level_1_3 = {.phys = GAIA_IO_BASE + 0x2A28A0}, + .int_level_1_2 = {.phys = GAIA_IO_BASE + 0x2A28A4}, + .int_level_1_1 = {.phys = GAIA_IO_BASE + 0x2A28A8}, + .int_level_1_0 = {.phys = GAIA_IO_BASE + 0x2A28AC}, + .int_level_0_3 = {.phys = GAIA_IO_BASE + 0x2A28B0}, + .int_level_0_2 = {.phys = GAIA_IO_BASE + 0x2A28B4}, + .int_level_0_1 = {.phys = GAIA_IO_BASE + 0x2A28B8}, + .int_level_0_0 = {.phys = GAIA_IO_BASE + 0x2A28BC}, + .int_docsis_en = {.phys = GAIA_IO_BASE + 0x2A28F4}, + + .mips_pll_setup = {.phys = GAIA_IO_BASE + 0x1C0000}, + .fs432x4b4_usb_ctl = {.phys = GAIA_IO_BASE + 0x1C0024}, + .test_bus = {.phys = GAIA_IO_BASE + 0x1C00CC}, + .crt_spare = {.phys = GAIA_IO_BASE + 0x1c0108}, + .usb2_ohci_int_mask = {.phys = GAIA_IO_BASE + 0x20000C}, + .usb2_strap = {.phys = GAIA_IO_BASE + 0x200014}, + .ehci_hcapbase = {.phys = GAIA_IO_BASE + 0x21FE00}, + .ohci_hc_revision = {.phys = GAIA_IO_BASE + 0x21fc00}, + .bcm1_bs_lmi_steer = {.phys = GAIA_IO_BASE + 0x2E0004}, + .usb2_control = {.phys = GAIA_IO_BASE + 0x2E004C}, + .usb2_stbus_obc = {.phys = GAIA_IO_BASE + 0x21FF00}, + .usb2_stbus_mess_size = {.phys = GAIA_IO_BASE + 0x21FF04}, + .usb2_stbus_chunk_size = {.phys = GAIA_IO_BASE + 0x21FF08}, + + .pcie_regs = {.phys = GAIA_IO_BASE + 0x220000}, + .tim_ch = {.phys = GAIA_IO_BASE + 0x2A2C10}, + .tim_cl = {.phys = GAIA_IO_BASE + 0x2A2C14}, + .gpio_dout = {.phys = GAIA_IO_BASE + 0x2A2C20}, + .gpio_din = {.phys = GAIA_IO_BASE + 0x2A2C24}, + .gpio_dir = {.phys = GAIA_IO_BASE + 0x2A2C2C}, + .watchdog = {.phys = GAIA_IO_BASE + 0x2A2C30}, + .front_panel = {.phys = GAIA_IO_BASE + 0x2A3800}, +}; diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c index 095cbe1..4a05bb0 100644 --- a/arch/mips/powertv/asic/asic-zeus.c +++ b/arch/mips/powertv/asic/asic-zeus.c @@ -77,7 +77,7 @@ const struct register_map zeus_register_map __initdata = { .int_docsis_en = {.phys = ZEUS_ADDR(0x2828F4)}, .mips_pll_setup = {.phys = ZEUS_ADDR(0x1a0000)}, - .usb_fs = {.phys = ZEUS_ADDR(0x1a0018)}, + .fs432x4b4_usb_ctl = {.phys = ZEUS_ADDR(0x1a0018)}, .test_bus = {.phys = ZEUS_ADDR(0x1a0238)}, .crt_spare = {.phys = ZEUS_ADDR(0x1a0090)}, .usb2_ohci_int_mask = {.phys = ZEUS_ADDR(0x1e000c)}, diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index 9ec523e..e56fa61 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -1,7 +1,6 @@ /* - * ASIC Device List Intialization * - * Description: Defines the platform resources for the SA settop. + * Description: Defines the platform resources for Gaia-based settops. * * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. * @@ -19,11 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * Author: Ken Eppinett - * David Schleef - * - * Description: Defines the platform resources for the SA settop. - * * NOTE: The bootloader allocates persistent memory at an address which is * 16 MiB below the end of the highest address in KSEG0. All fixed * address memory reservations must avoid this region. @@ -39,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -74,14 +67,13 @@ unsigned long asic_phy_base; unsigned long asic_base; EXPORT_SYMBOL(asic_base); /* Exported for testing */ struct resource *gp_resources; -static bool usb_configured; /* * Don't recommend to use it directly, it is usually used by kernel internally. * Portable code should be using interfaces such as ioremp, dma_map_single, etc. */ -unsigned long phys_to_bus_offset; -EXPORT_SYMBOL(phys_to_bus_offset); +unsigned long phys_to_dma_offset; +EXPORT_SYMBOL(phys_to_dma_offset); /* * @@ -97,101 +89,19 @@ struct resource asic_resource = { }; /* - * - * USB Host Resource Definition - * - */ - -static struct resource ehci_resources[] = { - { - .parent = &asic_resource, - .start = 0, - .end = 0xff, - .flags = IORESOURCE_MEM, - }, - { - .start = irq_usbehci, - .end = irq_usbehci, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ehci_dmamask = DMA_BIT_MASK(32); - -static struct platform_device ehci_device = { - .name = "powertv-ehci", - .id = 0, - .num_resources = 2, - .resource = ehci_resources, - .dev = { - .dma_mask = &ehci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static struct resource ohci_resources[] = { - { - .parent = &asic_resource, - .start = 0, - .end = 0xff, - .flags = IORESOURCE_MEM, - }, - { - .start = irq_usbohci, - .end = irq_usbohci, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ohci_dmamask = DMA_BIT_MASK(32); - -static struct platform_device ohci_device = { - .name = "powertv-ohci", - .id = 0, - .num_resources = 2, - .resource = ohci_resources, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static struct platform_device *platform_devices[] = { - &ehci_device, - &ohci_device, -}; - -/* - * - * Platform Configuration and Device Initialization - * - */ -static void __init fs_update(int pe, int md, int sdiv, int disable_div_by_3) -{ - int en_prg, byp, pwr, nsb, val; - int sout; - - sout = 1; - en_prg = 1; - byp = 0; - nsb = 1; - pwr = 1; - - val = ((sdiv << 29) | (md << 24) | (pe<<8) | (sout<<3) | (byp<<2) | - (nsb<<1) | (disable_div_by_3<<5)); - - asic_write(val, usb_fs); - asic_write(val | (en_prg<<4), usb_fs); - asic_write(val | (en_prg<<4) | pwr, usb_fs); -} - -/* * Allow override of bootloader-specified model + * Returns zero on success, a negative errno value on failure. This parameter + * allows overriding of the bootloader-specified model. */ static char __initdata cmdline[COMMAND_LINE_SIZE]; #define FORCEFAMILY_PARAM "forcefamily" +/* + * check_forcefamily - check for, and parse, forcefamily command line parameter + * @forced_family: Pointer to two-character array in which to store the + * value of the forcedfamily parameter, if any. + */ static __init int check_forcefamily(unsigned char forced_family[2]) { const char *p; @@ -231,14 +141,10 @@ static __init int check_forcefamily(unsigned char forced_family[2]) */ static __init noinline void platform_set_family(void) { -#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0)) - unsigned char forced_family[2]; unsigned short bootldr_family; - check_forcefamily(forced_family); - - if (forced_family[0] != '\0' && forced_family[1] != '\0') + if (check_forcefamily(forced_family) == 0) bootldr_family = BOOTLDRFAMILY(forced_family[0], forced_family[1]); else { @@ -289,6 +195,9 @@ static __init noinline void platform_set_family(void) case BOOTLDRFAMILY('F', '1'): platform_family = FAMILY_1500VZF; break; + case BOOTLDRFAMILY('8', '7'): + platform_family = FAMILY_8700; + break; default: platform_family = -1; } @@ -301,24 +210,9 @@ unsigned int platform_get_family(void) EXPORT_SYMBOL(platform_get_family); /* - * \brief usb_eye_configure() for optimizing the USB eye on Calliope. - * - * \param unsigned int value saved to the register. - * - * \return none - * - */ -static void __init usb_eye_configure(unsigned int value) -{ - asic_write(asic_read(crt_spare) | value, crt_spare); -} - -/* * platform_get_asic - determine the ASIC type. * - * \param none - * - * \return ASIC type; ASIC_UNKNOWN if none + * Returns the ASIC type, or ASIC_UNKNOWN if unknown * */ enum asic_type platform_get_asic(void) @@ -328,93 +222,10 @@ enum asic_type platform_get_asic(void) EXPORT_SYMBOL(platform_get_asic); /* - * platform_configure_usb - usb configuration based on platform type. - * @bcm1_usb2_ctl: value for the BCM1_USB2_CTL register, which is - * quirky - */ -static void __init platform_configure_usb(void) -{ - u32 bcm1_usb2_ctl; - - if (usb_configured) - return; - - switch (asic) { - case ASIC_ZEUS: - case ASIC_CRONUS: - case ASIC_CRONUSLITE: - fs_update(0x0000, 0x11, 0x02, 0); - bcm1_usb2_ctl = 0x803; - break; - - case ASIC_CALLIOPE: - fs_update(0x0000, 0x11, 0x02, 1); - - switch (platform_family) { - case FAMILY_1500VZE: - break; - - case FAMILY_1500VZF: - usb_eye_configure(0x003c0000); - break; - - default: - usb_eye_configure(0x00300000); - break; - } - - bcm1_usb2_ctl = 0x803; - break; - - default: - pr_err("Unknown ASIC type: %d\n", asic); - break; - } - - /* turn on USB power */ - asic_write(0, usb2_strap); - /* Enable all OHCI interrupts */ - asic_write(bcm1_usb2_ctl, usb2_control); - /* USB2_STBUS_OBC store32/load32 */ - asic_write(3, usb2_stbus_obc); - /* USB2_STBUS_MESS_SIZE 2 packets */ - asic_write(1, usb2_stbus_mess_size); - /* USB2_STBUS_CHUNK_SIZE 2 packets */ - asic_write(1, usb2_stbus_chunk_size); - - usb_configured = true; -} - -/* - * Set up the USB EHCI interface + * set_register_map - set ASIC register configuration + * @phys_base: Physical address of the base of the ASIC registers + * @map: Description of key ASIC registers */ -void platform_configure_usb_ehci() -{ - platform_configure_usb(); -} - -/* - * Set up the USB OHCI interface - */ -void platform_configure_usb_ohci() -{ - platform_configure_usb(); -} - -/* - * Shut the USB EHCI interface down--currently a NOP - */ -void platform_unconfigure_usb_ehci() -{ -} - -/* - * Shut the USB OHCI interface down--currently a NOP - */ -void platform_unconfigure_usb_ohci() -{ -} - static void __init set_register_map(unsigned long phys_base, const struct register_map *map) { @@ -526,6 +337,15 @@ void __init configure_platform(void) "DVR_CAPABLE\n"); break; + case FAMILY_8700: + platform_features = FFS_CAPABLE | PCIE_CAPABLE; + asic = ASIC_GAIA; + set_register_map(GAIA_IO_BASE, &gaia_register_map); + gp_resources = dvr_gaia_resources; + + pr_info("Platform: 8700 - GAIA, DVR_CAPABLE\n"); + break; + default: pr_crit("Platform: UNKNOWN PLATFORM\n"); break; @@ -533,10 +353,10 @@ void __init configure_platform(void) switch (asic) { case ASIC_ZEUS: - phys_to_bus_offset = 0x30000000; + phys_to_dma_offset = 0x30000000; break; case ASIC_CALLIOPE: - phys_to_bus_offset = 0x10000000; + phys_to_dma_offset = 0x10000000; break; case ASIC_CRONUSLITE: /* Fall through */ @@ -546,42 +366,16 @@ void __init configure_platform(void) * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000- * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000. */ - phys_to_bus_offset = 0x10000000; + phys_to_dma_offset = 0x10000000; break; default: - phys_to_bus_offset = 0x00000000; + phys_to_dma_offset = 0x00000000; break; } } -/** - * platform_devices_init - sets up USB device resourse. - */ -static int __init platform_devices_init(void) -{ - pr_notice("%s: ----- Initializing USB resources -----\n", __func__); - - asic_resource.start = asic_phy_base; - asic_resource.end += asic_resource.start; - - ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase); - ehci_resources[0].end += ehci_resources[0].start; - - ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision); - ohci_resources[0].end += ohci_resources[0].start; - - set_io_port_base(0); - - platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); - - return 0; -} - -arch_initcall(platform_devices_init); - /* - * - * BOOTMEM ALLOCATION + * RESOURCE ALLOCATION * */ /* @@ -603,7 +397,7 @@ void __init platform_alloc_bootmem(void) int size = gp_resources[i].end - gp_resources[i].start + 1; if ((gp_resources[i].start != 0) && ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) { - reserve_bootmem(bus_to_phys(gp_resources[i].start), + reserve_bootmem(dma_to_phys(gp_resources[i].start), size, 0); total += gp_resources[i].end - gp_resources[i].start + 1; @@ -627,7 +421,7 @@ void __init platform_alloc_bootmem(void) else { gp_resources[i].start = - phys_to_bus(virt_to_phys(mem)); + phys_to_dma(virt_to_phys(mem)); gp_resources[i].end = gp_resources[i].start + size - 1; total += size; @@ -691,7 +485,7 @@ static void __init pmem_setup_resource(void) if (resource && pmemaddr && pmemlen) { /* The address provided by bootloader is in kseg0. Convert to * a bus address. */ - resource->start = phys_to_bus(pmemaddr - 0x80000000); + resource->start = phys_to_dma(pmemaddr - 0x80000000); resource->end = resource->start + pmemlen - 1; pr_info("persistent memory: start=0x%x end=0x%x\n", diff --git a/arch/mips/powertv/asic/prealloc-gaia.c b/arch/mips/powertv/asic/prealloc-gaia.c new file mode 100644 index 0000000..8ac8c7a --- /dev/null +++ b/arch/mips/powertv/asic/prealloc-gaia.c @@ -0,0 +1,589 @@ +/* + * Memory pre-allocations for Gaia boxes. + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: David VomLehn + */ + +#include +#include + +/* + * DVR_CAPABLE GAIA RESOURCES + */ +struct resource dvr_gaia_resources[] __initdata = { + /* + * + * VIDEO1 / LX1 + * + */ + { + .name = "ST231aImage", /* Delta-Mu 1 image and ram */ + .start = 0x24000000, + .end = 0x241FFFFF, /* 2MiB */ + .flags = IORESOURCE_MEM, + }, + { + .name = "ST231aMonitor", /* 8KiB block ST231a monitor */ + .start = 0x24200000, + .end = 0x24201FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "MediaMemory1", + .start = 0x24202000, + .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_MEM, + }, + /* + * + * VIDEO2 / LX2 + * + */ + { + .name = "ST231bImage", /* Delta-Mu 2 image and ram */ + .start = 0x60000000, + .end = 0x601FFFFF, /* 2MiB */ + .flags = IORESOURCE_IO, + }, + { + .name = "ST231bMonitor", /* 8KiB block ST231b monitor */ + .start = 0x60200000, + .end = 0x60201FFF, + .flags = IORESOURCE_IO, + }, + { + .name = "MediaMemory2", + .start = 0x60202000, + .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_IO, + }, + /* + * + * Sysaudio Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * DSP_Image_Buff - DSP code and data images (1MB) + * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB) + * ADSC_AUX_Buff - ADSC AUX buffer (16KB) + * ADSC_Main_Buff - ADSC Main buffer (16KB) + * + */ + { + .name = "DSP_Image_Buff", + .start = 0x00000000, + .end = 0x000FFFFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_CPU_PCM_Buff", + .start = 0x00000000, + .end = 0x00009FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_AUX_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_Main_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + /* + * + * STAVEM driver/STAPI + * + * This driver requires: + * + * Arbitrary Based Buffers: + * This memory area is used for allocating buffers for Video decoding + * purposes. Allocation/De-allocation within this buffer is managed + * by the STAVMEM driver of the STAPI. They could be Decimated + * Picture Buffers, Intermediate Buffers, as deemed necessary for + * video decoding purposes, for any video decoders on Zeus. + * + */ + { + .name = "AVMEMPartition0", + .start = 0x63580000, + .end = 0x64180000 - 1, /* 12 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * DOCSIS Subsystem + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "Docsis", + .start = 0x62000000, + .end = 0x62700000 - 1, /* 7 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * GHW HAL Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * GraphicsHeap - PowerTV Graphics Heap + * + */ + { + .name = "GraphicsHeap", + .start = 0x62700000, + .end = 0x63500000 - 1, /* 14 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * multi com buffer area + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "MulticomSHM", + .start = 0x26000000, + .end = 0x26020000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * DMA Ring buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "BMM_Buffer", + .start = 0x00000000, + .end = 0x00280000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer for unit0 + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit0 + * + */ + { + .name = "DisplayBins0", + .start = 0x00000000, + .end = 0x00000FFF, /* 4 KB total */ + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit1 + * + */ + { + .name = "DisplayBins1", + .start = 0x64AD4000, + .end = 0x64AD5000 - 1, /* 4 KB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * ITFS + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "ITFS", + .start = 0x64180000, + /* 815,104 bytes each for 2 ITFS partitions. */ + .end = 0x6430DFFF, + .flags = IORESOURCE_IO, + }, + /* + * + * AVFS + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "AvfsDmaMem", + .start = 0x6430E000, + /* (945K * 8) = (128K *3) 5 playbacks / 3 server */ + .end = 0x64AD0000 - 1, + .flags = IORESOURCE_IO, + }, + { + .name = "AvfsFileSys", + .start = 0x64AD0000, + .end = 0x64AD1000 - 1, /* 4K */ + .flags = IORESOURCE_IO, + }, + /* + * + * Smartcard + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Read and write buffers for Internal/External cards + * + */ + { + .name = "SmartCardInfo", + .start = 0x64AD1000, + .end = 0x64AD3800 - 1, + .flags = IORESOURCE_IO, + }, + /* + * + * KAVNET + * NP Reset Vector - must be of the form xxCxxxxx + * NP Image - must be video bank 1 + * NP IPC - must be video bank 2 + */ + { + .name = "NP_Reset_Vector", + .start = 0x27c00000, + .end = 0x27c01000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_Image", + .start = 0x27020000, + .end = 0x27060000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_IPC", + .start = 0x63500000, + .end = 0x63580000 - 1, + .flags = IORESOURCE_IO, + }, + /* + * Add other resources here + */ + { }, +}; + +/* + * NON_DVR_CAPABLE GAIA RESOURCES + */ +struct resource non_dvr_gaia_resources[] __initdata = { + /* + * + * VIDEO1 / LX1 + * + */ + { + .name = "ST231aImage", /* Delta-Mu 1 image and ram */ + .start = 0x24000000, + .end = 0x241FFFFF, /* 2MiB */ + .flags = IORESOURCE_MEM, + }, + { + .name = "ST231aMonitor", /* 8KiB block ST231a monitor */ + .start = 0x24200000, + .end = 0x24201FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "MediaMemory1", + .start = 0x24202000, + .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_MEM, + }, + /* + * + * VIDEO2 / LX2 + * + */ + { + .name = "ST231bImage", /* Delta-Mu 2 image and ram */ + .start = 0x60000000, + .end = 0x601FFFFF, /* 2MiB */ + .flags = IORESOURCE_IO, + }, + { + .name = "ST231bMonitor", /* 8KiB block ST231b monitor */ + .start = 0x60200000, + .end = 0x60201FFF, + .flags = IORESOURCE_IO, + }, + { + .name = "MediaMemory2", + .start = 0x60202000, + .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_IO, + }, + /* + * + * Sysaudio Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * DSP_Image_Buff - DSP code and data images (1MB) + * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB) + * ADSC_AUX_Buff - ADSC AUX buffer (16KB) + * ADSC_Main_Buff - ADSC Main buffer (16KB) + * + */ + { + .name = "DSP_Image_Buff", + .start = 0x00000000, + .end = 0x000FFFFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_CPU_PCM_Buff", + .start = 0x00000000, + .end = 0x00009FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_AUX_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_Main_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + /* + * + * STAVEM driver/STAPI + * + * This driver requires: + * + * Arbitrary Based Buffers: + * This memory area is used for allocating buffers for Video decoding + * purposes. Allocation/De-allocation within this buffer is managed + * by the STAVMEM driver of the STAPI. They could be Decimated + * Picture Buffers, Intermediate Buffers, as deemed necessary for + * video decoding purposes, for any video decoders on Zeus. + * + */ + { + .name = "AVMEMPartition0", + .start = 0x63580000, + .end = 0x64180000 - 1, /* 12 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * DOCSIS Subsystem + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "Docsis", + .start = 0x62000000, + .end = 0x62700000 - 1, /* 7 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * GHW HAL Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * GraphicsHeap - PowerTV Graphics Heap + * + */ + { + .name = "GraphicsHeap", + .start = 0x62700000, + .end = 0x63500000 - 1, /* 14 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * multi com buffer area + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "MulticomSHM", + .start = 0x26000000, + .end = 0x26020000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * DMA Ring buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "BMM_Buffer", + .start = 0x00000000, + .end = 0x000AA000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer for unit0 + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit0 + * + */ + { + .name = "DisplayBins0", + .start = 0x00000000, + .end = 0x00000FFF, /* 4 KB total */ + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit1 + * + */ + { + .name = "DisplayBins1", + .start = 0x64AD4000, + .end = 0x64AD5000 - 1, /* 4 KB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * AVFS: player HAL memory + * + * + */ + { + .name = "AvfsDmaMem", + .start = 0x6430E000, + .end = 0x645D2C00 - 1, /* 945K * 3 for playback */ + .flags = IORESOURCE_IO, + }, + /* + * + * PMEM + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Persistent memory for diagnostics. + * + */ + { + .name = "DiagPersistentMemory", + .start = 0x00000000, + .end = 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * Smartcard + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Read and write buffers for Internal/External cards + * + */ + { + .name = "SmartCardInfo", + .start = 0x64AD1000, + .end = 0x64AD3800 - 1, + .flags = IORESOURCE_IO, + }, + /* + * + * KAVNET + * NP Reset Vector - must be of the form xxCxxxxx + * NP Image - must be video bank 1 + * NP IPC - must be video bank 2 + */ + { + .name = "NP_Reset_Vector", + .start = 0x27c00000, + .end = 0x27c01000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_Image", + .start = 0x27020000, + .end = 0x27060000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_IPC", + .start = 0x63500000, + .end = 0x63580000 - 1, + .flags = IORESOURCE_IO, + }, + { }, +}; diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c index 0afe227..8355228 100644 --- a/arch/mips/powertv/init.c +++ b/arch/mips/powertv/init.c @@ -117,8 +117,10 @@ void __init prom_init(void) board_nmi_handler_setup = mips_nmi_setup; board_ejtag_handler_setup = mips_ejtag_setup; - if (prom_argc == 1) + if (prom_argc == 1) { + strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE); + } configure_platform(); prom_meminit(); diff --git a/arch/mips/powertv/ioremap.c b/arch/mips/powertv/ioremap.c new file mode 100644 index 0000000..a77c6f6 --- /dev/null +++ b/arch/mips/powertv/ioremap.c @@ -0,0 +1,136 @@ +/* + * ioremap.c + * + * Support for mapping between dma_addr_t values a phys_addr_t values. + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: David VomLehn + * + * Description: Defines the platform resources for the SA settop. + * + * NOTE: The bootloader allocates persistent memory at an address which is + * 16 MiB below the end of the highest address in KSEG0. All fixed + * address memory reservations must avoid this region. + */ + +#include +#include + +#include + +/* + * Define the sizes of and masks for grains in physical and DMA space. The + * values are the same but the types are not. + */ +#define IOR_PHYS_GRAIN ((phys_addr_t) 1 << IOR_LSBITS) +#define IOR_PHYS_GRAIN_MASK (IOR_PHYS_GRAIN - 1) + +#define IOR_DMA_GRAIN ((dma_addr_t) 1 << IOR_LSBITS) +#define IOR_DMA_GRAIN_MASK (IOR_DMA_GRAIN - 1) + +/* + * Values that, when accessed by an index derived from a phys_addr_t and + * added to phys_addr_t value, yield a DMA address + */ +struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA]; +EXPORT_SYMBOL(_ior_phys_to_dma); + +/* + * Values that, when accessed by an index derived from a dma_addr_t and + * added to that dma_addr_t value, yield a physical address + */ +struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS]; +EXPORT_SYMBOL(_ior_dma_to_phys); + +/** + * setup_dma_to_phys - set up conversion from DMA to physical addresses + * @dma_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index + * into the array _dma_to_phys. + * @delta: Value that, when added to the DMA address, will yield the + * physical address + * @s: Number of bytes in the section of memory with the given delta + * between DMA and physical addresses. + */ +static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s) +{ + int dma_idx, first_idx, last_idx; + phys_addr_t first, last; + + /* + * Calculate the first and last indices, rounding the first up and + * the second down. + */ + first = dma & ~IOR_DMA_GRAIN_MASK; + last = (dma + s - 1) & ~IOR_DMA_GRAIN_MASK; + first_idx = first >> IOR_LSBITS; /* Convert to indices */ + last_idx = last >> IOR_LSBITS; + + for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++) + _ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT; +} + +/** + * setup_phys_to_dma - set up conversion from DMA to physical addresses + * @phys_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index + * into the array _phys_to_dma. + * @delta: Value that, when added to the DMA address, will yield the + * physical address + * @s: Number of bytes in the section of memory with the given delta + * between DMA and physical addresses. + */ +static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s) +{ + int phys_idx, first_idx, last_idx; + phys_addr_t first, last; + + /* + * Calculate the first and last indices, rounding the first up and + * the second down. + */ + first = phys & ~IOR_PHYS_GRAIN_MASK; + last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK; + first_idx = first >> IOR_LSBITS; /* Convert to indices */ + last_idx = last >> IOR_LSBITS; + + for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++) + _ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT; +} + +/** + * ioremap_add_map - add to the physical and DMA address conversion arrays + * @phys: Process's view of the address of the start of the memory chunk + * @dma: DMA address of the start of the memory chunk + * @size: Size, in bytes, of the chunk of memory + * + * NOTE: It might be obvious, but the assumption is that all @size bytes have + * the same offset between the physical address and the DMA address. + */ +void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size) +{ + if (size == 0) + return; + + if ((dma & IOR_DMA_GRAIN_MASK) != 0 || + (phys & IOR_PHYS_GRAIN_MASK) != 0 || + (size & IOR_PHYS_GRAIN_MASK) != 0) + pr_crit("Memory allocation must be in chunks of 0x%x bytes\n", + IOR_PHYS_GRAIN); + + setup_dma_to_phys(dma, phys - dma, size); + setup_phys_to_dma(phys, dma - phys, size); +} diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c index f49eb3d..73880ad 100644 --- a/arch/mips/powertv/memory.c +++ b/arch/mips/powertv/memory.c @@ -30,28 +30,141 @@ #include #include +#include +#include #include "init.h" /* Memory constants */ #define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */ #define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */ -#define DEFAULT_MEMSIZE MEBIBYTE(256) /* If no memsize provided */ -#define LOW_MEM_MAX MEBIBYTE(252) /* Max usable low mem */ -#define RES_BOOTLDR_MEMSIZE MEBIBYTE(1) /* Memory reserved for bldr */ -#define BOOT_MEM_SIZE KIBIBYTE(256) /* Memory reserved for bldr */ -#define PHYS_MEM_START 0x10000000 /* Start of physical memory */ +#define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */ -char __initdata cmdline[COMMAND_LINE_SIZE]; +#define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */ +#define RV_SIZE MEBIBYTE(4) /* Size of reset vector */ -void __init prom_meminit(void) +#define LOW_MEM_END 0x20000000 /* Highest low memory address */ +#define BLDR_ALIAS 0x10000000 /* Bootloader address */ +#define RV_PHYS 0x1fc00000 /* Reset vector address */ +#define LOW_RAM_END RV_PHYS /* End of real RAM in low mem */ + +/* + * Very low-level conversion from processor physical address to device + * DMA address for the first bank of memory. + */ +#define PHYS_TO_DMA(paddr) ((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS)) + +unsigned long ptv_memsize; + +/* + * struct low_mem_reserved - Items in low memmory that are reserved + * @start: Physical address of item + * @size: Size, in bytes, of this item + * @is_aliased: True if this is RAM aliased from another location. If false, + * it is something other than aliased RAM and the RAM in the + * unaliased address is still visible outside of low memory. + */ +struct low_mem_reserved { + phys_addr_t start; + phys_addr_t size; + bool is_aliased; +}; + +/* + * Must be in ascending address order + */ +struct low_mem_reserved low_mem_reserved[] = { + {BLDR_ALIAS, BLDR_SIZE, true}, /* Bootloader RAM */ + {RV_PHYS, RV_SIZE, false}, /* Reset vector */ +}; + +/* + * struct mem_layout - layout of a piece of the system RAM + * @phys: Physical address of the start of this piece of RAM. This is the + * address at which both the processor and I/O devices see the + * RAM. + * @alias: Alias of this piece of memory in order to make it appear in + * the low memory part of the processor's address space. I/O + * devices don't see anything here. + * @size: Size, in bytes, of this piece of RAM + */ +struct mem_layout { + phys_addr_t phys; + phys_addr_t alias; + phys_addr_t size; +}; + +/* + * struct mem_layout_list - list descriptor for layouts of system RAM pieces + * @family: Specifies the family being described + * @n: Number of &struct mem_layout elements + * @layout: Pointer to the list of &mem_layout structures + */ +struct mem_layout_list { + enum family_type family; + size_t n; + struct mem_layout *layout; +}; + +static struct mem_layout f1500_layout[] = { + {0x20000000, 0x10000000, MEBIBYTE(256)}, +}; + +static struct mem_layout f4500_layout[] = { + {0x40000000, 0x10000000, MEBIBYTE(256)}, + {0x20000000, 0x20000000, MEBIBYTE(32)}, +}; + +static struct mem_layout f8500_layout[] = { + {0x40000000, 0x10000000, MEBIBYTE(256)}, + {0x20000000, 0x20000000, MEBIBYTE(32)}, + {0x30000000, 0x30000000, MEBIBYTE(32)}, +}; + +static struct mem_layout fx600_layout[] = { + {0x20000000, 0x10000000, MEBIBYTE(256)}, + {0x60000000, 0x60000000, MEBIBYTE(128)}, +}; + +static struct mem_layout_list layout_list[] = { + {FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout}, + {FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout}, + {FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout}, + {FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout}, + {FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout}, + {FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout}, + {FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout}, + {FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout}, + {FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout}, + {FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout}, +}; + +/* If we can't determine the layout, use this */ +static struct mem_layout default_layout[] = { + {0x20000000, 0x10000000, MEBIBYTE(128)}, +}; + +/** + * register_non_ram - register low memory not available for RAM usage + */ +static __init void register_non_ram(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++) + add_memory_region(low_mem_reserved[i].start, + low_mem_reserved[i].size, BOOT_MEM_RESERVED); +} + +/** + * get_memsize - get the size of memory as a single bank + */ +static phys_addr_t get_memsize(void) { + static char cmdline[COMMAND_LINE_SIZE] __initdata; + phys_addr_t memsize = 0; char *memsize_str; - unsigned long memsize = 0; - unsigned int physend; char *ptr; - int low_mem; - int high_mem; /* Check the command line first for a memsize directive */ strcpy(cmdline, arcs_cmdline); @@ -73,96 +186,156 @@ void __init prom_meminit(void) if (memsize == 0) { if (_prom_memsize != 0) { memsize = _prom_memsize; - pr_info("_prom_memsize = 0x%lx\n", memsize); + pr_info("_prom_memsize = 0x%x\n", memsize); /* add in memory that the bootloader doesn't * report */ - memsize += BOOT_MEM_SIZE; + memsize += BLDR_SIZE; } else { memsize = DEFAULT_MEMSIZE; pr_info("Memsize not passed by bootloader, " - "defaulting to 0x%lx\n", memsize); + "defaulting to 0x%x\n", memsize); } } } - physend = PFN_ALIGN(&_end) - 0x80000000; - if (memsize > LOW_MEM_MAX) { - low_mem = LOW_MEM_MAX; - high_mem = memsize - low_mem; - } else { - low_mem = memsize; - high_mem = 0; + return memsize; +} + +/** + * register_low_ram - register an aliased section of RAM + * @p: Alias address of memory + * @n: Number of bytes in this section of memory + * + * Returns the number of bytes registered + * + */ +static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n) +{ + phys_addr_t s; + int i; + phys_addr_t orig_n; + + orig_n = n; + + BUG_ON(p + n > RV_PHYS); + + for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) { + phys_addr_t start; + phys_addr_t size; + + start = low_mem_reserved[i].start; + size = low_mem_reserved[i].size; + + /* Handle memory before this low memory section */ + if (p < start) { + phys_addr_t s; + s = min(n, start - p); + add_memory_region(p, s, BOOT_MEM_RAM); + p += s; + n -= s; + } + + /* Handle the low memory section itself. If it's aliased, + * we reduce the number of byes left, but if not, the RAM + * is available elsewhere and we don't reduce the number of + * bytes remaining. */ + if (p == start) { + if (low_mem_reserved[i].is_aliased) { + s = min(n, size); + n -= s; + p += s; + } else + p += n; + } } + return orig_n - n; +} + /* - * TODO: We will use the hard code for memory configuration until - * the bootloader releases their device tree to us. + * register_ram - register real RAM + * @p: Address of memory as seen by devices + * @alias: If the memory is seen at an additional address by the processor, + * this will be the address, otherwise it is the same as @p. + * @n: Number of bytes in this section of memory */ +static __init void register_ram(phys_addr_t p, phys_addr_t alias, + phys_addr_t n) +{ /* - * Add the memory reserved for use by the bootloader to the - * memory map. - */ - add_memory_region(PHYS_MEM_START, RES_BOOTLDR_MEMSIZE, - BOOT_MEM_RESERVED); -#ifdef CONFIG_HIGHMEM_256_128 - /* - * Add memory in low for general use by the kernel and its friends - * (like drivers, applications, etc). - */ - add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, - LOW_MEM_MAX - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); - /* - * Add the memory reserved for reset vector. - */ - add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED); - /* - * Add the memory reserved. - */ - add_memory_region(0x20000000, MEBIBYTE(1024 + 75), BOOT_MEM_RESERVED); - /* - * Add memory in high for general use by the kernel and its friends - * (like drivers, applications, etc). - * - * 75MB is reserved for devices which are using the memory in high. - */ - add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75), - BOOT_MEM_RAM); -#elif defined CONFIG_HIGHMEM_128_128 - /* - * Add memory in low for general use by the kernel and its friends - * (like drivers, applications, etc). - */ - add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, - MEBIBYTE(128) - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); - /* - * Add the memory reserved. - */ - add_memory_region(PHYS_MEM_START + MEBIBYTE(128), - MEBIBYTE(128 + 1024 + 75), BOOT_MEM_RESERVED); - /* - * Add memory in high for general use by the kernel and its friends - * (like drivers, applications, etc). - * - * 75MB is reserved for devices which are using the memory in high. - */ - add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75), - BOOT_MEM_RAM); -#else - /* Add low memory regions for either: - * - no-highmemory configuration case -OR- - * - highmemory "HIGHMEM_LOWBANK_ONLY" case - */ - /* - * Add memory for general use by the kernel and its friends - * (like drivers, applications, etc). + * If some or all of this memory has an alias, break it into the + * aliased and non-aliased portion. */ - add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, - low_mem - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); + if (p != alias) { + phys_addr_t alias_size; + phys_addr_t registered; + + alias_size = min(n, LOW_RAM_END - alias); + registered = register_low_ram(alias, alias_size); + ioremap_add_map(alias, p, n); + n -= registered; + p += registered; + } + +#ifdef CONFIG_HIGHMEM + if (n != 0) { + add_memory_region(p, n, BOOT_MEM_RAM); + ioremap_add_map(p, p, n); + } +#endif +} + +/** + * register_address_space - register things in the address space + * @memsize: Number of bytes of RAM installed + * + * Takes the given number of bytes of RAM and registers as many of the regions, + * or partial regions, as it can. So, the default configuration might have + * two regions with 256 MiB each. If the memsize passed in on the command line + * is 384 MiB, it will register the first region with 256 MiB and the second + * with 128 MiB. + */ +static __init void register_address_space(phys_addr_t memsize) +{ + int i; + phys_addr_t size; + size_t n; + struct mem_layout *layout; + enum family_type family; + /* - * Add the memory reserved for reset vector. + * Register all of the things that aren't available to the kernel as + * memory. */ - add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED); -#endif + register_non_ram(); + + /* Find the appropriate memory description */ + family = platform_get_family(); + + for (i = 0; i < ARRAY_SIZE(layout_list); i++) { + if (layout_list[i].family == family) + break; + } + + if (i == ARRAY_SIZE(layout_list)) { + n = ARRAY_SIZE(default_layout); + layout = default_layout; + } else { + n = layout_list[i].n; + layout = layout_list[i].layout; + } + + for (i = 0; memsize != 0 && i < n; i++) { + size = min(memsize, layout[i].size); + register_ram(layout[i].phys, layout[i].alias, size); + memsize -= size; + } +} + +void __init prom_meminit(void) +{ + ptv_memsize = get_memsize(); + register_address_space(ptv_memsize); } void __init prom_free_prom_memory(void) diff --git a/arch/mips/powertv/powertv-usb.c b/arch/mips/powertv/powertv-usb.c new file mode 100644 index 0000000..6ac85cf --- /dev/null +++ b/arch/mips/powertv/powertv-usb.c @@ -0,0 +1,403 @@ +/* + * powertv-usb.c + * + * Description: ASIC-specific USB device setup and shutdown + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * Copyright (C) 2009 Cisco Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Ken Eppinett + * David Schleef + * + * NOTE: The bootloader allocates persistent memory at an address which is + * 16 MiB below the end of the highest address in KSEG0. All fixed + * address memory reservations must avoid this region. + */ + +#include +#include +#include +#include +#include + +/* misc_clk_ctl1 values */ +#define MCC1_30MHZ_POWERUP_SELECT (1 << 14) +#define MCC1_DIV9 (1 << 13) +#define MCC1_ETHMIPS_POWERUP_SELECT (1 << 11) +#define MCC1_USB_POWERUP_SELECT (1 << 1) +#define MCC1_CLOCK108_POWERUP_SELECT (1 << 0) + +/* Possible values for clock select */ +#define MCC1_USB_CLOCK_HIGH_Z (0 << 4) +#define MCC1_USB_CLOCK_48MHZ (1 << 4) +#define MCC1_USB_CLOCK_24MHZ (2 << 4) +#define MCC1_USB_CLOCK_6MHZ (3 << 4) + +#define MCC1_CONFIG (MCC1_30MHZ_POWERUP_SELECT | \ + MCC1_DIV9 | \ + MCC1_ETHMIPS_POWERUP_SELECT | \ + MCC1_USB_POWERUP_SELECT | \ + MCC1_CLOCK108_POWERUP_SELECT) + +/* misc_clk_ctl2 values */ +#define MCC2_GMII_GCLK_TO_PAD (1 << 31) +#define MCC2_ETHER125_0_CLOCK_SELECT (1 << 29) +#define MCC2_RMII_0_CLOCK_SELECT (1 << 28) +#define MCC2_GMII_TX0_CLOCK_SELECT (1 << 27) +#define MCC2_GMII_RX0_CLOCK_SELECT (1 << 26) +#define MCC2_ETHER125_1_CLOCK_SELECT (1 << 24) +#define MCC2_RMII_1_CLOCK_SELECT (1 << 23) +#define MCC2_GMII_TX1_CLOCK_SELECT (1 << 22) +#define MCC2_GMII_RX1_CLOCK_SELECT (1 << 21) +#define MCC2_ETHER125_2_CLOCK_SELECT (1 << 19) +#define MCC2_RMII_2_CLOCK_SELECT (1 << 18) +#define MCC2_GMII_TX2_CLOCK_SELECT (1 << 17) +#define MCC2_GMII_RX2_CLOCK_SELECT (1 << 16) + +#define ETHER_CLK_CONFIG (MCC2_GMII_GCLK_TO_PAD | \ + MCC2_ETHER125_0_CLOCK_SELECT | \ + MCC2_RMII_0_CLOCK_SELECT | \ + MCC2_GMII_TX0_CLOCK_SELECT | \ + MCC2_GMII_RX0_CLOCK_SELECT | \ + MCC2_ETHER125_1_CLOCK_SELECT | \ + MCC2_RMII_1_CLOCK_SELECT | \ + MCC2_GMII_TX1_CLOCK_SELECT | \ + MCC2_GMII_RX1_CLOCK_SELECT | \ + MCC2_ETHER125_2_CLOCK_SELECT | \ + MCC2_RMII_2_CLOCK_SELECT | \ + MCC2_GMII_TX2_CLOCK_SELECT | \ + MCC2_GMII_RX2_CLOCK_SELECT) + +/* misc_clk_ctl2 definitions for Gaia */ +#define FSX4A_REF_SELECT (1 << 16) +#define FSX4B_REF_SELECT (1 << 17) +#define FSX4C_REF_SELECT (1 << 18) +#define DDR_PLL_REF_SELECT (1 << 19) +#define MIPS_PLL_REF_SELECT (1 << 20) + +/* Definitions for the QAM frequency select register FS432X4A4_QAM_CTL */ +#define QAM_FS_SDIV_SHIFT 29 +#define QAM_FS_MD_SHIFT 24 +#define QAM_FS_MD_MASK 0x1f /* Cut down to 5 bits */ +#define QAM_FS_PE_SHIFT 8 + +#define QAM_FS_DISABLE_DIVIDE_BY_3 (1 << 5) +#define QAM_FS_ENABLE_PROGRAM (1 << 4) +#define QAM_FS_ENABLE_OUTPUT (1 << 3) +#define QAM_FS_SELECT_TEST_BYPASS (1 << 2) +#define QAM_FS_DISABLE_DIGITAL_STANDBY (1 << 1) +#define QAM_FS_CHOOSE_FS (1 << 0) + +/* Definitions for fs432x4a_ctl register */ +#define QAM_FS_NSDIV_54MHZ (1 << 2) + +/* Definitions for bcm1_usb2_ctl register */ +#define BCM1_USB2_CTL_BISTOK (1 << 11) +#define BCM1_USB2_CTL_PORT2_SHIFT_JK (1 << 7) +#define BCM1_USB2_CTL_PORT1_SHIFT_JK (1 << 6) +#define BCM1_USB2_CTL_PORT2_FAST_EDGE (1 << 5) +#define BCM1_USB2_CTL_PORT1_FAST_EDGE (1 << 4) +#define BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH (1 << 1) +#define BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH (1 << 0) + +/* Definitions for crt_spare register */ +#define CRT_SPARE_PORT2_SHIFT_JK (1 << 21) +#define CRT_SPARE_PORT1_SHIFT_JK (1 << 20) +#define CRT_SPARE_PORT2_FAST_EDGE (1 << 19) +#define CRT_SPARE_PORT1_FAST_EDGE (1 << 18) +#define CRT_SPARE_DIVIDE_BY_9_FROM_432 (1 << 17) +#define CRT_SPARE_USB_DIVIDE_BY_9 (1 << 16) + +/* Definitions for usb2_stbus_obc register */ +#define USB_STBUS_OBC_STORE32_LOAD32 0x3 + +/* Definitions for usb2_stbus_mess_size register */ +#define USB2_STBUS_MESS_SIZE_2 0x1 /* 2 packets */ + +/* Definitions for usb2_stbus_chunk_size register */ +#define USB2_STBUS_CHUNK_SIZE_2 0x1 /* 2 packets */ + +/* Definitions for usb2_strap register */ +#define USB2_STRAP_HFREQ_SELECT 0x1 + +/* + * USB Host Resource Definition + */ + +static struct resource ehci_resources[] = { + { + .parent = &asic_resource, + .start = 0, + .end = 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = irq_usbehci, + .end = irq_usbehci, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ehci_dmamask = 0xffffffffULL; + +static struct platform_device ehci_device = { + .name = "powertv-ehci", + .id = 0, + .num_resources = 2, + .resource = ehci_resources, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct resource ohci_resources[] = { + { + .parent = &asic_resource, + .start = 0, + .end = 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = irq_usbohci, + .end = irq_usbohci, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ohci_dmamask = 0xffffffffULL; + +static struct platform_device ohci_device = { + .name = "powertv-ohci", + .id = 0, + .num_resources = 2, + .resource = ohci_resources, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, +}; + +static unsigned usb_users; +static DEFINE_SPINLOCK(usb_regs_lock); + +/* + * + * fs_update - set frequency synthesizer for USB + * @pe_bits Phase tap setting + * @md_bits Coarse selector bus for algorithm of phase tap + * @sdiv_bits Output divider setting + * @disable_div_by_3 Either QAM_FS_DISABLE_DIVIDE_BY_3 or zero + * @standby Either QAM_FS_DISABLE_DIGITAL_STANDBY or zero + * + * QAM frequency selection code, which affects the frequency at which USB + * runs. The frequency is calculated as: + * 2^15 * ndiv * Fin + * Fout = ------------------------------------------------------------ + * (sdiv * (ipe * (1 + md/32) - (ipe - 2^15)*(1 + (md + 1)/32))) + * where: + * Fin 54 MHz + * ndiv QAM_FS_NSDIV_54MHZ ? 8 : 16 + * sdiv 1 << (sdiv_bits + 1) + * ipe Same as pe_bits + * md A five-bit, two's-complement integer (range [-16, 15]), which + * is the lower 5 bits of md_bits. + */ +static void fs_update(u32 pe_bits, int md_bits, u32 sdiv_bits, + u32 disable_div_by_3, u32 standby) +{ + u32 val; + + val = ((sdiv_bits << QAM_FS_SDIV_SHIFT) | + ((md_bits & QAM_FS_MD_MASK) << QAM_FS_MD_SHIFT) | + (pe_bits << QAM_FS_PE_SHIFT) | + QAM_FS_ENABLE_OUTPUT | + standby | + disable_div_by_3); + asic_write(val, fs432x4b4_usb_ctl); + asic_write(val | QAM_FS_ENABLE_PROGRAM, fs432x4b4_usb_ctl); + asic_write(val | QAM_FS_ENABLE_PROGRAM | QAM_FS_CHOOSE_FS, + fs432x4b4_usb_ctl); +} + +/* + * usb_eye_configure - for optimizing the shape USB eye waveform + * @set: Bits to set in the register + * @clear: Bits to clear in the register; each bit with a one will + * be set in the register, zero bits will not be modified + */ +static void usb_eye_configure(u32 set, u32 clear) +{ + u32 old; + + old = asic_read(crt_spare); + old |= set; + old &= ~clear; + asic_write(old, crt_spare); +} + +/* + * platform_configure_usb - usb configuration based on platform type. + */ +static void platform_configure_usb(void) +{ + u32 bcm1_usb2_ctl_value; + enum asic_type asic_type; + unsigned long flags; + + spin_lock_irqsave(&usb_regs_lock, flags); + usb_users++; + + if (usb_users != 1) { + spin_unlock_irqrestore(&usb_regs_lock, flags); + return; + } + + asic_type = platform_get_asic(); + + switch (asic_type) { + case ASIC_ZEUS: + fs_update(0x0000, -15, 0x02, 0, 0); + bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + case ASIC_CRONUS: + case ASIC_CRONUSLITE: + usb_eye_configure(0, CRT_SPARE_USB_DIVIDE_BY_9); + fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3, + QAM_FS_DISABLE_DIGITAL_STANDBY); + bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + case ASIC_CALLIOPE: + fs_update(0x0000, -15, 0x02, QAM_FS_DISABLE_DIVIDE_BY_3, + QAM_FS_DISABLE_DIGITAL_STANDBY); + + switch (platform_get_family()) { + case FAMILY_1500VZE: + break; + + case FAMILY_1500VZF: + usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK | + CRT_SPARE_PORT1_SHIFT_JK | + CRT_SPARE_PORT2_FAST_EDGE | + CRT_SPARE_PORT1_FAST_EDGE, 0); + break; + + default: + usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK | + CRT_SPARE_PORT1_SHIFT_JK, 0); + break; + } + + bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK | + BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + case ASIC_GAIA: + fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3, + QAM_FS_DISABLE_DIGITAL_STANDBY); + bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK | + BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + default: + pr_err("Unknown ASIC type: %d\n", asic_type); + bcm1_usb2_ctl_value = 0; + break; + } + + /* turn on USB power */ + asic_write(0, usb2_strap); + /* Enable all OHCI interrupts */ + asic_write(bcm1_usb2_ctl_value, usb2_control); + /* usb2_stbus_obc store32/load32 */ + asic_write(USB_STBUS_OBC_STORE32_LOAD32, usb2_stbus_obc); + /* usb2_stbus_mess_size 2 packets */ + asic_write(USB2_STBUS_MESS_SIZE_2, usb2_stbus_mess_size); + /* usb2_stbus_chunk_size 2 packets */ + asic_write(USB2_STBUS_CHUNK_SIZE_2, usb2_stbus_chunk_size); + spin_unlock_irqrestore(&usb_regs_lock, flags); +} + +static void platform_unconfigure_usb(void) +{ + unsigned long flags; + + spin_lock_irqsave(&usb_regs_lock, flags); + usb_users--; + if (usb_users == 0) + asic_write(USB2_STRAP_HFREQ_SELECT, usb2_strap); + spin_unlock_irqrestore(&usb_regs_lock, flags); +} + +/* + * Set up the USB EHCI interface + */ +void platform_configure_usb_ehci() +{ + platform_configure_usb(); +} +EXPORT_SYMBOL(platform_configure_usb_ehci); + +/* + * Set up the USB OHCI interface + */ +void platform_configure_usb_ohci() +{ + platform_configure_usb(); +} +EXPORT_SYMBOL(platform_configure_usb_ohci); + +/* + * Shut the USB EHCI interface down + */ +void platform_unconfigure_usb_ehci() +{ + platform_unconfigure_usb(); +} +EXPORT_SYMBOL(platform_unconfigure_usb_ehci); + +/* + * Shut the USB OHCI interface down + */ +void platform_unconfigure_usb_ohci() +{ + platform_unconfigure_usb(); +} +EXPORT_SYMBOL(platform_unconfigure_usb_ohci); + +/** + * platform_devices_init - sets up USB device resourse. + */ +int __init platform_usb_devices_init(struct platform_device **ehci_dev, + struct platform_device **ohci_dev) +{ + *ehci_dev = &ehci_device; + ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase); + ehci_resources[0].end += ehci_resources[0].start; + + *ohci_dev = &ohci_device; + ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision); + ohci_resources[0].end += ohci_resources[0].start; + + return 0; +} diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c index af2cae0..3933c37 100644 --- a/arch/mips/powertv/powertv_setup.c +++ b/arch/mips/powertv/powertv_setup.c @@ -199,14 +199,8 @@ static int panic_handler(struct notifier_block *notifier_block, my_regs.cp0_status = read_c0_status(); } -#ifdef CONFIG_DIAGNOSTICS - failure_report((char *) cause_string, - have_die_regs ? &die_regs : &my_regs); - have_die_regs = false; -#else pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... " "zzzz... \n"); -#endif return NOTIFY_DONE; } diff --git a/arch/mips/rb532/Makefile b/arch/mips/rb532/Makefile index 8f0b6b6..efdecdb 100644 --- a/arch/mips/rb532/Makefile +++ b/arch/mips/rb532/Makefile @@ -3,5 +3,3 @@ # obj-y += irq.o time.o setup.o serial.o prom.o gpio.o devices.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/rb532/Platform b/arch/mips/rb532/Platform new file mode 100644 index 0000000..aeec45a --- /dev/null +++ b/arch/mips/rb532/Platform @@ -0,0 +1,7 @@ +# +# Routerboard 532 +# +platform-$(CONFIG_MIKROTIK_RB532) += rb532/ +cflags-$(CONFIG_MIKROTIK_RB532) += \ + -I$(srctree)/arch/mips/include/asm/mach-rc32434 +load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index 416b18f..cc53849 100644 --- a/arch/mips/sgi-ip22/Makefile +++ b/arch/mips/sgi-ip22/Makefile @@ -9,5 +9,3 @@ obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \ obj-$(CONFIG_SGI_IP22) += ip22-berr.o obj-$(CONFIG_SGI_IP28) += ip28-berr.o obj-$(CONFIG_EISA) += ip22-eisa.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip22/Platform b/arch/mips/sgi-ip22/Platform new file mode 100644 index 0000000..b7a4b7e --- /dev/null +++ b/arch/mips/sgi-ip22/Platform @@ -0,0 +1,34 @@ +# +# SGI IP22 (Indy/Indigo2) +# +# Set the load address to >= 0xffffffff88069000 if you want to leave space for +# symmon, 0xffffffff80002000 for production kernels. Note that the value must +# be aligned to a multiple of the kernel stack size or the handling of the +# current variable will break so for 64-bit kernels we have to raise the start +# address by 8kb. +# +platform-$(CONFIG_SGI_IP22) += sgi-ip22/ +cflags-$(CONFIG_SGI_IP22) += -I$(srctree)/arch/mips/include/asm/mach-ip22 +ifdef CONFIG_32BIT +load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 +endif +ifdef CONFIG_64BIT +load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 +endif + +# +# SGI IP28 (Indigo2 R10k) +# +# Set the load address to >= 0xa800000020080000 if you want to leave space for +# symmon, 0xa800000020004000 for production kernels ? Note that the value must +# be 16kb aligned or the handling of the current variable will break. +# Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys +# +ifdef CONFIG_SGI_IP28 + ifeq ($(call cc-option-yn,-mr10k-cache-barrier=store), n) + $(error gcc doesn't support needed option -mr10k-cache-barrier=store) + endif +endif +platform-$(CONFIG_SGI_IP28) += sgi-ip22/ +cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=store -I$(srctree)/arch/mips/include/asm/mach-ip28 +load-$(CONFIG_SGI_IP28) += 0xa800000020004000 diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index 31f4931..1f29e76 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -8,5 +8,3 @@ obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \ obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o obj-$(CONFIG_SMP) += ip27-smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip27/Platform b/arch/mips/sgi-ip27/Platform new file mode 100644 index 0000000..1fb9c2e --- /dev/null +++ b/arch/mips/sgi-ip27/Platform @@ -0,0 +1,19 @@ +# +# SGI-IP27 (Origin200/2000) +# +# Set the load address to >= 0xc000000000300000 if you want to leave space for +# symmon, 0xc00000000001c000 for production kernels. Note that the value must +# be 16kb aligned or the handling of the current variable will break. +# +ifdef CONFIG_SGI_IP27 +platform-$(CONFIG_SGI_IP27) += sgi-ip27/ +cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 +ifdef CONFIG_MAPPED_KERNEL +load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 +OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 +dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 +else +load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 +OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 +endif +endif diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c index dd830b3..7afe146 100644 --- a/arch/mips/sgi-ip27/ip27-klconfig.c +++ b/arch/mips/sgi-ip27/ip27-klconfig.c @@ -48,7 +48,7 @@ klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) return find_component(brd, (klinfo_t *)NULL, struct_type); } -lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) +lboard_t *find_lboard(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { @@ -60,7 +60,7 @@ lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) return (lboard_t *)NULL; } -lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) +lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { @@ -78,7 +78,7 @@ cnodeid_t get_cpu_cnode(cpuid_t cpu) return CPUID_TO_COMPACT_NODEID(cpu); } -klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) +klcpu_t *nasid_slice_to_cpuinfo(nasid_t nasid, int slice) { lboard_t *brd; klcpu_t *acpu; @@ -97,7 +97,7 @@ klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) return (klcpu_t *)NULL; } -klcpu_t * sn_get_cpuinfo(cpuid_t cpu) +klcpu_t *sn_get_cpuinfo(cpuid_t cpu) { nasid_t nasid; int slice; diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile index 31c9aa1..60f0227 100644 --- a/arch/mips/sgi-ip32/Makefile +++ b/arch/mips/sgi-ip32/Makefile @@ -5,5 +5,3 @@ obj-y += ip32-berr.o ip32-irq.o ip32-platform.o ip32-setup.o ip32-reset.o \ crime.o ip32-memory.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip32/Platform b/arch/mips/sgi-ip32/Platform new file mode 100644 index 0000000..0fea556 --- /dev/null +++ b/arch/mips/sgi-ip32/Platform @@ -0,0 +1,11 @@ +# +# SGI-IP32 (O2) +# +# Set the load address to >= 80069000 if you want to leave space for symmon, +# 0xffffffff80004000 for production kernels. Note that the value must be aligned to +# a multiple of the kernel stack size or the handling of the current variable +# will break. +# +platform-$(CONFIG_SGI_IP32) += sgi-ip32/ +cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 +load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 diff --git a/arch/mips/sibyte/Makefile b/arch/mips/sibyte/Makefile new file mode 100644 index 0000000..c8ed2c8 --- /dev/null +++ b/arch/mips/sibyte/Makefile @@ -0,0 +1,27 @@ +# +# Sibyte SB1250 / BCM1480 family of SOCs +# +obj-$(CONFIG_SIBYTE_BCM112X) += sb1250/ +obj-$(CONFIG_SIBYTE_BCM112X) += common/ +obj-$(CONFIG_SIBYTE_SB1250) += sb1250/ +obj-$(CONFIG_SIBYTE_SB1250) += common/ +obj-$(CONFIG_SIBYTE_BCM1x55) += bcm1480/ +obj-$(CONFIG_SIBYTE_BCM1x55) += common/ +obj-$(CONFIG_SIBYTE_BCM1x80) += bcm1480/ +obj-$(CONFIG_SIBYTE_BCM1x80) += common/ + +# +# Sibyte BCM91120x (Carmel) board +# Sibyte BCM91120C (CRhine) board +# Sibyte BCM91125C (CRhone) board +# Sibyte BCM91125E (Rhone) board +# Sibyte SWARM board +# Sibyte BCM91x80 (BigSur) board +# +obj-$(CONFIG_SIBYTE_CARMEL) += swarm/ +obj-$(CONFIG_SIBYTE_CRHINE) += swarm/ +obj-$(CONFIG_SIBYTE_CRHONE) += swarm/ +obj-$(CONFIG_SIBYTE_RHONE) += swarm/ +obj-$(CONFIG_SIBYTE_SENTOSA) += swarm/ +obj-$(CONFIG_SIBYTE_SWARM) += swarm/ +obj-$(CONFIG_SIBYTE_BIGSUR) += swarm/ diff --git a/arch/mips/sibyte/Platform b/arch/mips/sibyte/Platform new file mode 100644 index 0000000..911dfe3 --- /dev/null +++ b/arch/mips/sibyte/Platform @@ -0,0 +1,43 @@ +# +# These are all rather similar so we consider them a single platform +# +platform-$(CONFIG_SIBYTE_BCM112X) += sibyte/ +platform-$(CONFIG_SIBYTE_SB1250) += sibyte/ +platform-$(CONFIG_SIBYTE_BCM1x55) += sibyte/ +platform-$(CONFIG_SIBYTE_BCM1x80) += sibyte/ + +# +# Sibyte SB1250 / BCM1480 family of SOCs +# +cflags-$(CONFIG_SIBYTE_BCM112X) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL + +platform-$(CONFIG_SIBYTE_SB1250) += sibyte/ +cflags-$(CONFIG_SIBYTE_SB1250) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL + +cflags-$(CONFIG_SIBYTE_BCM1x55) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL + +cflags-$(CONFIG_SIBYTE_BCM1x80) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL + +# +# Sibyte BCM91120x (Carmel) board +# Sibyte BCM91120C (CRhine) board +# Sibyte BCM91125C (CRhone) board +# Sibyte BCM91125E (Rhone) board +# Sibyte SWARM board +# Sibyte BCM91x80 (BigSur) board +# +load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile index f292f7d..cdc4c56 100644 --- a/arch/mips/sibyte/bcm1480/Makefile +++ b/arch/mips/sibyte/bcm1480/Makefile @@ -1,5 +1,3 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile index 4f65983..36aa700 100644 --- a/arch/mips/sibyte/common/Makefile +++ b/arch/mips/sibyte/common/Makefile @@ -1,5 +1,3 @@ obj-y := cfe.o obj-$(CONFIG_SIBYTE_CFE_CONSOLE) += cfe_console.o obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile index 1896f4e..d3d969d 100644 --- a/arch/mips/sibyte/sb1250/Makefile +++ b/arch/mips/sibyte/sb1250/Makefile @@ -2,5 +2,3 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile index a7dbeeb..9d3bad3 100644 --- a/arch/mips/sni/Makefile +++ b/arch/mips/sni/Makefile @@ -4,5 +4,3 @@ obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o obj-$(CONFIG_EISA) += eisa.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sni/Platform b/arch/mips/sni/Platform new file mode 100644 index 0000000..2644a9d --- /dev/null +++ b/arch/mips/sni/Platform @@ -0,0 +1,11 @@ +# +# SNI RM +# +platform-$(CONFIG_SNI_RM) += sni/ +cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm +ifdef CONFIG_CPU_LITTLE_ENDIAN +load-$(CONFIG_SNI_RM) += 0xffffffff80600000 +else +load-$(CONFIG_SNI_RM) += 0xffffffff80030000 +endif +all-$(CONFIG_SNI_RM) := $(COMPRESSION_FNAME).ecoff diff --git a/arch/mips/txx9/Makefile b/arch/mips/txx9/Makefile new file mode 100644 index 0000000..34787da --- /dev/null +++ b/arch/mips/txx9/Makefile @@ -0,0 +1,17 @@ +# +# Common TXx9 +# +obj-$(CONFIG_MACH_TX39XX) += generic/ +obj-$(CONFIG_MACH_TX49XX) += generic/ + +# +# Toshiba JMR-TX3927 board +# +obj-$(CONFIG_TOSHIBA_JMR3927) += jmr3927/ + +# +# Toshiba RBTX49XX boards +# +obj-$(CONFIG_TOSHIBA_RBTX4927) += rbtx4927/ +obj-$(CONFIG_TOSHIBA_RBTX4938) += rbtx4938/ +obj-$(CONFIG_TOSHIBA_RBTX4939) += rbtx4939/ diff --git a/arch/mips/txx9/Platform b/arch/mips/txx9/Platform new file mode 100644 index 0000000..a801abb --- /dev/null +++ b/arch/mips/txx9/Platform @@ -0,0 +1,10 @@ +platform-$(CONFIG_MACH_TX39XX) += txx9/ +platform-$(CONFIG_MACH_TX49XX) += txx9/ + +cflags-$(CONFIG_MACH_TX39XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-tx39xx +cflags-$(CONFIG_MACH_TX49XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-tx49xx + +load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 +load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile index f2579ce..1863c16 100644 --- a/arch/mips/txx9/generic/Makefile +++ b/arch/mips/txx9/generic/Makefile @@ -11,5 +11,3 @@ obj-$(CONFIG_SOC_TX4939) += setup_tx4939.o irq_tx4939.o obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o obj-$(CONFIG_SPI) += spi_eeprom.o obj-$(CONFIG_TXX9_7SEGLED) += 7segled.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/jmr3927/Makefile b/arch/mips/txx9/jmr3927/Makefile index 20d61ac..9f5d5b6 100644 --- a/arch/mips/txx9/jmr3927/Makefile +++ b/arch/mips/txx9/jmr3927/Makefile @@ -3,5 +3,3 @@ # obj-y += prom.o irq.o setup.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4927/Makefile b/arch/mips/txx9/rbtx4927/Makefile index f3e1f59..60b24c8 100644 --- a/arch/mips/txx9/rbtx4927/Makefile +++ b/arch/mips/txx9/rbtx4927/Makefile @@ -1,3 +1 @@ obj-y += prom.o setup.o irq.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile index f3e1f59..60b24c8 100644 --- a/arch/mips/txx9/rbtx4938/Makefile +++ b/arch/mips/txx9/rbtx4938/Makefile @@ -1,3 +1 @@ obj-y += prom.o setup.o irq.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4939/Makefile b/arch/mips/txx9/rbtx4939/Makefile index 3232cd0..5c84625 100644 --- a/arch/mips/txx9/rbtx4939/Makefile +++ b/arch/mips/txx9/rbtx4939/Makefile @@ -1,3 +1 @@ obj-y += irq.o setup.o prom.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/vr41xx/Platform b/arch/mips/vr41xx/Platform new file mode 100644 index 0000000..b6c8d5c --- /dev/null +++ b/arch/mips/vr41xx/Platform @@ -0,0 +1,32 @@ +# +# NEC VR4100 series based machines +# +platform-$(CONFIG_MACH_VR41XX) += vr41xx/common/ +cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx + +# +# CASIO CASSIPEIA E-55/65 (VR4111) +# +platform-$(CONFIG_CASIO_E55) += vr41xx/casio-e55/ +load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 + +# +# IBM WorkPad z50 (VR4121) +# +platform-$(CONFIG_IBM_WORKPAD) += vr41xx/ibm-workpad/ +load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 + +# +# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131) +# +load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 + +# +# Victor MP-C303/304 (VR4122) +# +load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 + +# +# ZAO Networks Capcella (VR4131) +# +load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile index 7d5d83b..d0d84ec 100644 --- a/arch/mips/vr41xx/common/Makefile +++ b/arch/mips/vr41xx/common/Makefile @@ -3,5 +3,3 @@ # obj-y += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/wrppmc/Makefile b/arch/mips/wrppmc/Makefile new file mode 100644 index 0000000..307cc69 --- /dev/null +++ b/arch/mips/wrppmc/Makefile @@ -0,0 +1,12 @@ +# +# 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 2006 Wind River System, Inc. +# Author: Rongkai.Zhan +# +# Makefile for the Wind River MIPS 4Kc PPMC Eval Board +# + +obj-y += irq.o pci.o reset.o serial.o setup.o time.o diff --git a/arch/mips/wrppmc/Platform b/arch/mips/wrppmc/Platform new file mode 100644 index 0000000..e758645 --- /dev/null +++ b/arch/mips/wrppmc/Platform @@ -0,0 +1,7 @@ +# +# Wind River PPMC Board (4KC + GT64120) +# +platform-$(CONFIG_WR_PPMC) += wrppmc/ +cflags-$(CONFIG_WR_PPMC) += \ + -I$(srctree)/arch/mips/include/asm/mach-wrppmc +load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 diff --git a/arch/mips/wrppmc/irq.c b/arch/mips/wrppmc/irq.c new file mode 100644 index 0000000..c6e7062 --- /dev/null +++ b/arch/mips/wrppmc/irq.c @@ -0,0 +1,56 @@ +/* + * irq.c: GT64120 Interrupt Controller + * + * Copyright (C) 2006, Wind River System Inc. + * Author: Rongkai.Zhan, + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +#include +#include +#include + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + + if (pending & STATUSF_IP7) + do_IRQ(WRPPMC_MIPS_TIMER_IRQ); /* CPU Compare/Count internal timer */ + else if (pending & STATUSF_IP6) + do_IRQ(WRPPMC_UART16550_IRQ); /* UART 16550 port */ + else if (pending & STATUSF_IP3) + do_IRQ(WRPPMC_PCI_INTA_IRQ); /* PCI INT_A */ + else + spurious_interrupt(); +} + +/** + * Initialize GT64120 Interrupt Controller + */ +void gt64120_init_pic(void) +{ + /* clear CPU Interrupt Cause Registers */ + GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); + GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); + + /* Disable all interrupts from GT64120 bridge chip */ + GT_WRITE(GT_INTRMASK_OFS, 0x00); + GT_WRITE(GT_HINTRMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); +} + +void __init arch_init_irq(void) +{ + /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ + mips_cpu_irq_init(); + + gt64120_init_pic(); +} diff --git a/arch/mips/wrppmc/pci.c b/arch/mips/wrppmc/pci.c new file mode 100644 index 0000000..d06192f --- /dev/null +++ b/arch/mips/wrppmc/pci.c @@ -0,0 +1,54 @@ +/* + * pci.c: GT64120 PCI support. + * + * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan + * + * 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 + +extern struct pci_ops gt64xxx_pci0_ops; + +static struct resource pci0_io_resource = { + .name = "pci_0 io", + .start = GT_PCI_IO_BASE, + .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource pci0_mem_resource = { + .name = "pci_0 memory", + .start = GT_PCI_MEM_BASE, + .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller hose_0 = { + .pci_ops = >64xxx_pci0_ops, + .io_resource = &pci0_io_resource, + .mem_resource = &pci0_mem_resource, +}; + +static int __init gt64120_pci_init(void) +{ + u32 tmp; + + tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ + tmp = GT_READ(GT_PCI0_BARE_OFS); + + /* reset the whole PCI I/O space range */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + + register_pci_controller(&hose_0); + return 0; +} + +arch_initcall(gt64120_pci_init); diff --git a/arch/mips/wrppmc/reset.c b/arch/mips/wrppmc/reset.c new file mode 100644 index 0000000..cc5474b --- /dev/null +++ b/arch/mips/wrppmc/reset.c @@ -0,0 +1,40 @@ +/* + * 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) 1997 Ralf Baechle + */ +#include +#include + +#include +#include +#include + +void wrppmc_machine_restart(char *command) +{ + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + local_irq_disable(); + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void wrppmc_machine_halt(void) +{ + local_irq_disable(); + + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) { + if (cpu_wait) + cpu_wait(); + } +} diff --git a/arch/mips/wrppmc/serial.c b/arch/mips/wrppmc/serial.c new file mode 100644 index 0000000..6f9d085 --- /dev/null +++ b/arch/mips/wrppmc/serial.c @@ -0,0 +1,80 @@ +/* + * Registration of WRPPMC UART platform device. + * + * Copyright (C) 2007 Yoichi Yuasa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include + +static struct resource wrppmc_uart_resource[] __initdata = { + { + .start = WRPPMC_UART16550_BASE, + .end = WRPPMC_UART16550_BASE + 7, + .flags = IORESOURCE_MEM, + }, + { + .start = WRPPMC_UART16550_IRQ, + .end = WRPPMC_UART16550_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct plat_serial8250_port wrppmc_serial8250_port[] = { + { + .irq = WRPPMC_UART16550_IRQ, + .uartclk = WRPPMC_UART16550_CLOCK, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_SKIP_TEST, + .mapbase = WRPPMC_UART16550_BASE, + }, + {}, +}; + +static __init int wrppmc_uart_add(void) +{ + struct platform_device *pdev; + int retval; + + pdev = platform_device_alloc("serial8250", -1); + if (!pdev) + return -ENOMEM; + + pdev->id = PLAT8250_DEV_PLATFORM; + pdev->dev.platform_data = wrppmc_serial8250_port; + + retval = platform_device_add_resources(pdev, wrppmc_uart_resource, + ARRAY_SIZE(wrppmc_uart_resource)); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(wrppmc_uart_add); diff --git a/arch/mips/wrppmc/setup.c b/arch/mips/wrppmc/setup.c new file mode 100644 index 0000000..ca65c84 --- /dev/null +++ b/arch/mips/wrppmc/setup.c @@ -0,0 +1,128 @@ +/* + * setup.c: Setup pointers to hardware dependent routines. + * + * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +unsigned long gt64120_base = KSEG1ADDR(0x14000000); + +#ifdef WRPPMC_EARLY_DEBUG + +static volatile unsigned char * wrppmc_led = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); + +/* + * PPMC LED control register: + * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) + * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) + * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) + */ +void wrppmc_led_on(int mask) +{ + unsigned char value = *wrppmc_led; + + value &= (0xF8 | mask); + *wrppmc_led = value; +} + +/* If mask = 0, turn off all LEDs */ +void wrppmc_led_off(int mask) +{ + unsigned char value = *wrppmc_led; + + value |= (0x7 & mask); + *wrppmc_led = value; +} + +/* + * We assume that bootloader has initialized UART16550 correctly + */ +void __init wrppmc_early_putc(char ch) +{ + static volatile unsigned char *wrppmc_uart = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); + unsigned char value; + + /* Wait until Transmit-Holding-Register is empty */ + while (1) { + value = *(wrppmc_uart + 5); + if (value & 0x20) + break; + } + + *wrppmc_uart = ch; +} + +void __init wrppmc_early_printk(const char *fmt, ...) +{ + static char pbuf[256] = {'\0', }; + char *ch = pbuf; + va_list args; + unsigned int i; + + memset(pbuf, 0, 256); + va_start(args, fmt); + i = vsprintf(pbuf, fmt, args); + va_end(args); + + /* Print the string */ + while (*ch != '\0') { + wrppmc_early_putc(*ch); + /* if print '\n', also print '\r' */ + if (*ch++ == '\n') + wrppmc_early_putc('\r'); + } +} +#endif /* WRPPMC_EARLY_DEBUG */ + +void __init prom_free_prom_memory(void) +{ +} + +void __init plat_mem_setup(void) +{ + extern void wrppmc_machine_restart(char *command); + extern void wrppmc_machine_halt(void); + + _machine_restart = wrppmc_machine_restart; + _machine_halt = wrppmc_machine_halt; + pm_power_off = wrppmc_machine_halt; + + /* This makes the operations of 'in/out[bwl]' to the + * physical address ( < KSEG0) can work via KSEG1 + */ + set_io_port_base(KSEG1); +} + +const char *get_system_type(void) +{ + return "Wind River PPMC (GT64120)"; +} + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ +void __init prom_init(void) +{ + add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); + add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); + + wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", + WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); +} diff --git a/arch/mips/wrppmc/time.c b/arch/mips/wrppmc/time.c new file mode 100644 index 0000000..668dbd5 --- /dev/null +++ b/arch/mips/wrppmc/time.c @@ -0,0 +1,39 @@ +/* + * time.c: MIPS CPU Count/Compare timer hookup + * + * Author: Mark.Zhan, + * + * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. + */ +#include +#include +#include + +#include +#include + +#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ + +/* + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect + * + * NOTE: We disable all GT64120 timers, and use MIPS processor internal + * timer as the source of kernel clock tick. + */ +void __init plat_time_init(void) +{ + /* Disable GT64120 timers */ + GT_WRITE(GT_TC_CONTROL_OFS, 0x00); + GT_WRITE(GT_TC0_OFS, 0x00); + GT_WRITE(GT_TC1_OFS, 0x00); + GT_WRITE(GT_TC2_OFS, 0x00); + GT_WRITE(GT_TC3_OFS, 0x00); + + /* Use MIPS compare/count internal timer */ + mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; +} diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e19cf8e..c57e530 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -446,6 +446,16 @@ config SENSORS_IT87 This driver can also be built as a module. If so, the module will be called it87. +config SENSORS_JZ4740 + tristate "Ingenic JZ4740 SoC ADC driver" + depends on MACH_JZ4740 && MFD_JZ4740_ADC + help + If you say yes here you get support for reading adc values from the ADCIN + pin on Ingenic JZ4740 SoC based boards. + + This driver can also be build as a module. If so, the module will be + called jz4740-hwmon. + config SENSORS_LM63 tristate "National Semiconductor LM63 and LM64" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 2138ceb..c505774 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o +obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c new file mode 100644 index 0000000..1c8b3d9 --- /dev/null +++ b/drivers/hwmon/jz4740-hwmon.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC HWMON driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +struct jz4740_hwmon { + struct resource *mem; + void __iomem *base; + + int irq; + + struct mfd_cell *cell; + struct device *hwmon; + + struct completion read_completion; + + struct mutex lock; +}; + +static ssize_t jz4740_hwmon_show_name(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + return sprintf(buf, "jz4740\n"); +} + +static irqreturn_t jz4740_hwmon_irq(int irq, void *data) +{ + struct jz4740_hwmon *hwmon = data; + + complete(&hwmon->read_completion); + return IRQ_HANDLED; +} + +static ssize_t jz4740_hwmon_read_adcin(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); + struct completion *completion = &hwmon->read_completion; + unsigned long t; + unsigned long val; + int ret; + + mutex_lock(&hwmon->lock); + + INIT_COMPLETION(*completion); + + enable_irq(hwmon->irq); + hwmon->cell->enable(to_platform_device(dev)); + + t = wait_for_completion_interruptible_timeout(completion, HZ); + + if (t > 0) { + val = readw(hwmon->base) & 0xfff; + val = (val * 3300) >> 12; + ret = sprintf(buf, "%lu\n", val); + } else { + ret = t ? t : -ETIMEDOUT; + } + + hwmon->cell->disable(to_platform_device(dev)); + disable_irq(hwmon->irq); + + mutex_unlock(&hwmon->lock); + + return ret; +} + +static DEVICE_ATTR(name, S_IRUGO, jz4740_hwmon_show_name, NULL); +static DEVICE_ATTR(in0_input, S_IRUGO, jz4740_hwmon_read_adcin, NULL); + +static struct attribute *jz4740_hwmon_attributes[] = { + &dev_attr_name.attr, + &dev_attr_in0_input.attr, + NULL +}; + +static const struct attribute_group jz4740_hwmon_attr_group = { + .attrs = jz4740_hwmon_attributes, +}; + +static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) +{ + int ret; + struct jz4740_hwmon *hwmon; + + hwmon = kmalloc(sizeof(*hwmon), GFP_KERNEL); + if (!hwmon) { + dev_err(&pdev->dev, "Failed to allocate driver structure\n"); + return -ENOMEM; + } + + hwmon->cell = pdev->dev.platform_data; + + hwmon->irq = platform_get_irq(pdev, 0); + if (hwmon->irq < 0) { + ret = hwmon->irq; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); + goto err_free; + } + + hwmon->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!hwmon->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); + goto err_free; + } + + hwmon->mem = request_mem_region(hwmon->mem->start, + resource_size(hwmon->mem), pdev->name); + if (!hwmon->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + goto err_free; + } + + hwmon->base = ioremap_nocache(hwmon->mem->start, + resource_size(hwmon->mem)); + if (!hwmon->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); + goto err_release_mem_region; + } + + init_completion(&hwmon->read_completion); + mutex_init(&hwmon->lock); + + platform_set_drvdata(pdev, hwmon); + + ret = request_irq(hwmon->irq, jz4740_hwmon_irq, 0, pdev->name, hwmon); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); + goto err_iounmap; + } + disable_irq(hwmon->irq); + + ret = sysfs_create_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); + if (ret) { + dev_err(&pdev->dev, "Failed to create sysfs group: %d\n", ret); + goto err_free_irq; + } + + hwmon->hwmon = hwmon_device_register(&pdev->dev); + if (IS_ERR(hwmon->hwmon)) { + ret = PTR_ERR(hwmon->hwmon); + goto err_remove_file; + } + + return 0; + +err_remove_file: + sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); +err_free_irq: + free_irq(hwmon->irq, hwmon); +err_iounmap: + platform_set_drvdata(pdev, NULL); + iounmap(hwmon->base); +err_release_mem_region: + release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); +err_free: + kfree(hwmon); + + return ret; +} + +static int __devexit jz4740_hwmon_remove(struct platform_device *pdev) +{ + struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev); + + hwmon_device_unregister(hwmon->hwmon); + sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); + + free_irq(hwmon->irq, hwmon); + + iounmap(hwmon->base); + release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); + + platform_set_drvdata(pdev, NULL); + kfree(hwmon); + + return 0; +} + +struct platform_driver jz4740_hwmon_driver = { + .probe = jz4740_hwmon_probe, + .remove = __devexit_p(jz4740_hwmon_remove), + .driver = { + .name = "jz4740-hwmon", + .owner = THIS_MODULE, + }, +}; + +static int __init jz4740_hwmon_init(void) +{ + return platform_driver_register(&jz4740_hwmon_driver); +} +module_init(jz4740_hwmon_init); + +static void __exit jz4740_hwmon_exit(void) +{ + platform_driver_unregister(&jz4740_hwmon_driver); +} +module_exit(jz4740_hwmon_exit); + +MODULE_DESCRIPTION("JZ4740 SoC HWMON driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:jz4740-hwmon"); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index f06d06e..d25e22c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -432,3 +432,12 @@ config MMC_SH_MMCIF This selects the MMC Host Interface controler (MMCIF). This driver supports MMCIF in sh7724/sh7757/sh7372. + +config MMC_JZ4740 + tristate "JZ4740 SD/Multimedia Card Interface support" + depends on MACH_JZ4740 + help + This selects support for the SD/MMC controller on Ingenic JZ4740 + SoCs. + If you have a board based on such a SoC and with a SD/MMC slot, + say Y or M here. diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index e30c2ee..f4e53c9 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_MMC_CB710) += cb710-mmc.o obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o +obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o sdhci-of-y := sdhci-of-core.o diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c new file mode 100644 index 0000000..ad4f987 --- /dev/null +++ b/drivers/mmc/host/jz4740_mmc.c @@ -0,0 +1,1029 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SD/MMC controller driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define JZ_REG_MMC_STRPCL 0x00 +#define JZ_REG_MMC_STATUS 0x04 +#define JZ_REG_MMC_CLKRT 0x08 +#define JZ_REG_MMC_CMDAT 0x0C +#define JZ_REG_MMC_RESTO 0x10 +#define JZ_REG_MMC_RDTO 0x14 +#define JZ_REG_MMC_BLKLEN 0x18 +#define JZ_REG_MMC_NOB 0x1C +#define JZ_REG_MMC_SNOB 0x20 +#define JZ_REG_MMC_IMASK 0x24 +#define JZ_REG_MMC_IREG 0x28 +#define JZ_REG_MMC_CMD 0x2C +#define JZ_REG_MMC_ARG 0x30 +#define JZ_REG_MMC_RESP_FIFO 0x34 +#define JZ_REG_MMC_RXFIFO 0x38 +#define JZ_REG_MMC_TXFIFO 0x3C + +#define JZ_MMC_STRPCL_EXIT_MULTIPLE BIT(7) +#define JZ_MMC_STRPCL_EXIT_TRANSFER BIT(6) +#define JZ_MMC_STRPCL_START_READWAIT BIT(5) +#define JZ_MMC_STRPCL_STOP_READWAIT BIT(4) +#define JZ_MMC_STRPCL_RESET BIT(3) +#define JZ_MMC_STRPCL_START_OP BIT(2) +#define JZ_MMC_STRPCL_CLOCK_CONTROL (BIT(1) | BIT(0)) +#define JZ_MMC_STRPCL_CLOCK_STOP BIT(0) +#define JZ_MMC_STRPCL_CLOCK_START BIT(1) + + +#define JZ_MMC_STATUS_IS_RESETTING BIT(15) +#define JZ_MMC_STATUS_SDIO_INT_ACTIVE BIT(14) +#define JZ_MMC_STATUS_PRG_DONE BIT(13) +#define JZ_MMC_STATUS_DATA_TRAN_DONE BIT(12) +#define JZ_MMC_STATUS_END_CMD_RES BIT(11) +#define JZ_MMC_STATUS_DATA_FIFO_AFULL BIT(10) +#define JZ_MMC_STATUS_IS_READWAIT BIT(9) +#define JZ_MMC_STATUS_CLK_EN BIT(8) +#define JZ_MMC_STATUS_DATA_FIFO_FULL BIT(7) +#define JZ_MMC_STATUS_DATA_FIFO_EMPTY BIT(6) +#define JZ_MMC_STATUS_CRC_RES_ERR BIT(5) +#define JZ_MMC_STATUS_CRC_READ_ERROR BIT(4) +#define JZ_MMC_STATUS_TIMEOUT_WRITE BIT(3) +#define JZ_MMC_STATUS_CRC_WRITE_ERROR BIT(2) +#define JZ_MMC_STATUS_TIMEOUT_RES BIT(1) +#define JZ_MMC_STATUS_TIMEOUT_READ BIT(0) + +#define JZ_MMC_STATUS_READ_ERROR_MASK (BIT(4) | BIT(0)) +#define JZ_MMC_STATUS_WRITE_ERROR_MASK (BIT(3) | BIT(2)) + + +#define JZ_MMC_CMDAT_IO_ABORT BIT(11) +#define JZ_MMC_CMDAT_BUS_WIDTH_4BIT BIT(10) +#define JZ_MMC_CMDAT_DMA_EN BIT(8) +#define JZ_MMC_CMDAT_INIT BIT(7) +#define JZ_MMC_CMDAT_BUSY BIT(6) +#define JZ_MMC_CMDAT_STREAM BIT(5) +#define JZ_MMC_CMDAT_WRITE BIT(4) +#define JZ_MMC_CMDAT_DATA_EN BIT(3) +#define JZ_MMC_CMDAT_RESPONSE_FORMAT (BIT(2) | BIT(1) | BIT(0)) +#define JZ_MMC_CMDAT_RSP_R1 1 +#define JZ_MMC_CMDAT_RSP_R2 2 +#define JZ_MMC_CMDAT_RSP_R3 3 + +#define JZ_MMC_IRQ_SDIO BIT(7) +#define JZ_MMC_IRQ_TXFIFO_WR_REQ BIT(6) +#define JZ_MMC_IRQ_RXFIFO_RD_REQ BIT(5) +#define JZ_MMC_IRQ_END_CMD_RES BIT(2) +#define JZ_MMC_IRQ_PRG_DONE BIT(1) +#define JZ_MMC_IRQ_DATA_TRAN_DONE BIT(0) + + +#define JZ_MMC_CLK_RATE 24000000 + +enum jz4740_mmc_state { + JZ4740_MMC_STATE_READ_RESPONSE, + JZ4740_MMC_STATE_TRANSFER_DATA, + JZ4740_MMC_STATE_SEND_STOP, + JZ4740_MMC_STATE_DONE, +}; + +struct jz4740_mmc_host { + struct mmc_host *mmc; + struct platform_device *pdev; + struct jz4740_mmc_platform_data *pdata; + struct clk *clk; + + int irq; + int card_detect_irq; + + struct resource *mem; + void __iomem *base; + struct mmc_request *req; + struct mmc_command *cmd; + + unsigned long waiting; + + uint32_t cmdat; + + uint16_t irq_mask; + + spinlock_t lock; + + struct timer_list timeout_timer; + struct sg_mapping_iter miter; + enum jz4740_mmc_state state; +}; + +static void jz4740_mmc_set_irq_enabled(struct jz4740_mmc_host *host, + unsigned int irq, bool enabled) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (enabled) + host->irq_mask &= ~irq; + else + host->irq_mask |= irq; + spin_unlock_irqrestore(&host->lock, flags); + + writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK); +} + +static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host, + bool start_transfer) +{ + uint16_t val = JZ_MMC_STRPCL_CLOCK_START; + + if (start_transfer) + val |= JZ_MMC_STRPCL_START_OP; + + writew(val, host->base + JZ_REG_MMC_STRPCL); +} + +static void jz4740_mmc_clock_disable(struct jz4740_mmc_host *host) +{ + uint32_t status; + unsigned int timeout = 1000; + + writew(JZ_MMC_STRPCL_CLOCK_STOP, host->base + JZ_REG_MMC_STRPCL); + do { + status = readl(host->base + JZ_REG_MMC_STATUS); + } while (status & JZ_MMC_STATUS_CLK_EN && --timeout); +} + +static void jz4740_mmc_reset(struct jz4740_mmc_host *host) +{ + uint32_t status; + unsigned int timeout = 1000; + + writew(JZ_MMC_STRPCL_RESET, host->base + JZ_REG_MMC_STRPCL); + udelay(10); + do { + status = readl(host->base + JZ_REG_MMC_STATUS); + } while (status & JZ_MMC_STATUS_IS_RESETTING && --timeout); +} + +static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) +{ + struct mmc_request *req; + + req = host->req; + host->req = NULL; + + mmc_request_done(host->mmc, req); +} + +static unsigned int jz4740_mmc_poll_irq(struct jz4740_mmc_host *host, + unsigned int irq) +{ + unsigned int timeout = 0x800; + uint16_t status; + + do { + status = readw(host->base + JZ_REG_MMC_IREG); + } while (!(status & irq) && --timeout); + + if (timeout == 0) { + set_bit(0, &host->waiting); + mod_timer(&host->timeout_timer, jiffies + 5*HZ); + jz4740_mmc_set_irq_enabled(host, irq, true); + return true; + } + + return false; +} + +static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, + struct mmc_data *data) +{ + int status; + + status = readl(host->base + JZ_REG_MMC_STATUS); + if (status & JZ_MMC_STATUS_WRITE_ERROR_MASK) { + if (status & (JZ_MMC_STATUS_TIMEOUT_WRITE)) { + host->req->cmd->error = -ETIMEDOUT; + data->error = -ETIMEDOUT; + } else { + host->req->cmd->error = -EIO; + data->error = -EIO; + } + } +} + +static bool jz4740_mmc_write_data(struct jz4740_mmc_host *host, + struct mmc_data *data) +{ + struct sg_mapping_iter *miter = &host->miter; + void __iomem *fifo_addr = host->base + JZ_REG_MMC_TXFIFO; + uint32_t *buf; + bool timeout; + size_t i, j; + + while (sg_miter_next(miter)) { + buf = miter->addr; + i = miter->length / 4; + j = i / 8; + i = i & 0x7; + while (j) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + writel(buf[0], fifo_addr); + writel(buf[1], fifo_addr); + writel(buf[2], fifo_addr); + writel(buf[3], fifo_addr); + writel(buf[4], fifo_addr); + writel(buf[5], fifo_addr); + writel(buf[6], fifo_addr); + writel(buf[7], fifo_addr); + buf += 8; + --j; + } + if (unlikely(i)) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + while (i) { + writel(*buf, fifo_addr); + ++buf; + --i; + } + } + data->bytes_xfered += miter->length; + } + sg_miter_stop(miter); + + return false; + +poll_timeout: + miter->consumed = (void *)buf - miter->addr; + data->bytes_xfered += miter->consumed; + sg_miter_stop(miter); + + return true; +} + +static bool jz4740_mmc_read_data(struct jz4740_mmc_host *host, + struct mmc_data *data) +{ + struct sg_mapping_iter *miter = &host->miter; + void __iomem *fifo_addr = host->base + JZ_REG_MMC_RXFIFO; + uint32_t *buf; + uint32_t d; + uint16_t status; + size_t i, j; + unsigned int timeout; + + while (sg_miter_next(miter)) { + buf = miter->addr; + i = miter->length; + j = i / 32; + i = i & 0x1f; + while (j) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + buf[0] = readl(fifo_addr); + buf[1] = readl(fifo_addr); + buf[2] = readl(fifo_addr); + buf[3] = readl(fifo_addr); + buf[4] = readl(fifo_addr); + buf[5] = readl(fifo_addr); + buf[6] = readl(fifo_addr); + buf[7] = readl(fifo_addr); + + buf += 8; + --j; + } + + if (unlikely(i)) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + while (i >= 4) { + *buf++ = readl(fifo_addr); + i -= 4; + } + if (unlikely(i > 0)) { + d = readl(fifo_addr); + memcpy(buf, &d, i); + } + } + data->bytes_xfered += miter->length; + + /* This can go away once MIPS implements + * flush_kernel_dcache_page */ + flush_dcache_page(miter->page); + } + sg_miter_stop(miter); + + /* For whatever reason there is sometime one word more in the fifo then + * requested */ + timeout = 1000; + status = readl(host->base + JZ_REG_MMC_STATUS); + while (!(status & JZ_MMC_STATUS_DATA_FIFO_EMPTY) && --timeout) { + d = readl(fifo_addr); + status = readl(host->base + JZ_REG_MMC_STATUS); + } + + return false; + +poll_timeout: + miter->consumed = (void *)buf - miter->addr; + data->bytes_xfered += miter->consumed; + sg_miter_stop(miter); + + return true; +} + +static void jz4740_mmc_timeout(unsigned long data) +{ + struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)data; + + if (!test_and_clear_bit(0, &host->waiting)) + return; + + jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, false); + + host->req->cmd->error = -ETIMEDOUT; + jz4740_mmc_request_done(host); +} + +static void jz4740_mmc_read_response(struct jz4740_mmc_host *host, + struct mmc_command *cmd) +{ + int i; + uint16_t tmp; + void __iomem *fifo_addr = host->base + JZ_REG_MMC_RESP_FIFO; + + if (cmd->flags & MMC_RSP_136) { + tmp = readw(fifo_addr); + for (i = 0; i < 4; ++i) { + cmd->resp[i] = tmp << 24; + tmp = readw(fifo_addr); + cmd->resp[i] |= tmp << 8; + tmp = readw(fifo_addr); + cmd->resp[i] |= tmp >> 8; + } + } else { + cmd->resp[0] = readw(fifo_addr) << 24; + cmd->resp[0] |= readw(fifo_addr) << 8; + cmd->resp[0] |= readw(fifo_addr) & 0xff; + } +} + +static void jz4740_mmc_send_command(struct jz4740_mmc_host *host, + struct mmc_command *cmd) +{ + uint32_t cmdat = host->cmdat; + + host->cmdat &= ~JZ_MMC_CMDAT_INIT; + jz4740_mmc_clock_disable(host); + + host->cmd = cmd; + + if (cmd->flags & MMC_RSP_BUSY) + cmdat |= JZ_MMC_CMDAT_BUSY; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R1B: + case MMC_RSP_R1: + cmdat |= JZ_MMC_CMDAT_RSP_R1; + break; + case MMC_RSP_R2: + cmdat |= JZ_MMC_CMDAT_RSP_R2; + break; + case MMC_RSP_R3: + cmdat |= JZ_MMC_CMDAT_RSP_R3; + break; + default: + break; + } + + if (cmd->data) { + cmdat |= JZ_MMC_CMDAT_DATA_EN; + if (cmd->data->flags & MMC_DATA_WRITE) + cmdat |= JZ_MMC_CMDAT_WRITE; + if (cmd->data->flags & MMC_DATA_STREAM) + cmdat |= JZ_MMC_CMDAT_STREAM; + + writew(cmd->data->blksz, host->base + JZ_REG_MMC_BLKLEN); + writew(cmd->data->blocks, host->base + JZ_REG_MMC_NOB); + } + + writeb(cmd->opcode, host->base + JZ_REG_MMC_CMD); + writel(cmd->arg, host->base + JZ_REG_MMC_ARG); + writel(cmdat, host->base + JZ_REG_MMC_CMDAT); + + jz4740_mmc_clock_enable(host, 1); +} + +static void jz_mmc_prepare_data_transfer(struct jz4740_mmc_host *host) +{ + struct mmc_command *cmd = host->req->cmd; + struct mmc_data *data = cmd->data; + int direction; + + if (data->flags & MMC_DATA_READ) + direction = SG_MITER_TO_SG; + else + direction = SG_MITER_FROM_SG; + + sg_miter_start(&host->miter, data->sg, data->sg_len, direction); +} + + +static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) +{ + struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)devid; + struct mmc_command *cmd = host->req->cmd; + struct mmc_request *req = host->req; + bool timeout = false; + + if (cmd->error) + host->state = JZ4740_MMC_STATE_DONE; + + switch (host->state) { + case JZ4740_MMC_STATE_READ_RESPONSE: + if (cmd->flags & MMC_RSP_PRESENT) + jz4740_mmc_read_response(host, cmd); + + if (!cmd->data) + break; + + jz_mmc_prepare_data_transfer(host); + + case JZ4740_MMC_STATE_TRANSFER_DATA: + if (cmd->data->flags & MMC_DATA_READ) + timeout = jz4740_mmc_read_data(host, cmd->data); + else + timeout = jz4740_mmc_write_data(host, cmd->data); + + if (unlikely(timeout)) { + host->state = JZ4740_MMC_STATE_TRANSFER_DATA; + break; + } + + jz4740_mmc_transfer_check_state(host, cmd->data); + + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_DATA_TRAN_DONE); + if (unlikely(timeout)) { + host->state = JZ4740_MMC_STATE_SEND_STOP; + break; + } + writew(JZ_MMC_IRQ_DATA_TRAN_DONE, host->base + JZ_REG_MMC_IREG); + + case JZ4740_MMC_STATE_SEND_STOP: + if (!req->stop) + break; + + jz4740_mmc_send_command(host, req->stop); + + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_PRG_DONE); + if (timeout) { + host->state = JZ4740_MMC_STATE_DONE; + break; + } + case JZ4740_MMC_STATE_DONE: + break; + } + + if (!timeout) + jz4740_mmc_request_done(host); + + return IRQ_HANDLED; +} + +static irqreturn_t jz_mmc_irq(int irq, void *devid) +{ + struct jz4740_mmc_host *host = devid; + struct mmc_command *cmd = host->cmd; + uint16_t irq_reg, status, tmp; + + irq_reg = readw(host->base + JZ_REG_MMC_IREG); + + tmp = irq_reg; + irq_reg &= ~host->irq_mask; + + tmp &= ~(JZ_MMC_IRQ_TXFIFO_WR_REQ | JZ_MMC_IRQ_RXFIFO_RD_REQ | + JZ_MMC_IRQ_PRG_DONE | JZ_MMC_IRQ_DATA_TRAN_DONE); + + if (tmp != irq_reg) + writew(tmp & ~irq_reg, host->base + JZ_REG_MMC_IREG); + + if (irq_reg & JZ_MMC_IRQ_SDIO) { + writew(JZ_MMC_IRQ_SDIO, host->base + JZ_REG_MMC_IREG); + mmc_signal_sdio_irq(host->mmc); + irq_reg &= ~JZ_MMC_IRQ_SDIO; + } + + if (host->req && cmd && irq_reg) { + if (test_and_clear_bit(0, &host->waiting)) { + del_timer(&host->timeout_timer); + + status = readl(host->base + JZ_REG_MMC_STATUS); + + if (status & JZ_MMC_STATUS_TIMEOUT_RES) { + cmd->error = -ETIMEDOUT; + } else if (status & JZ_MMC_STATUS_CRC_RES_ERR) { + cmd->error = -EIO; + } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | + JZ_MMC_STATUS_CRC_WRITE_ERROR)) { + if (cmd->data) + cmd->data->error = -EIO; + cmd->error = -EIO; + } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | + JZ_MMC_STATUS_CRC_WRITE_ERROR)) { + if (cmd->data) + cmd->data->error = -EIO; + cmd->error = -EIO; + } + + jz4740_mmc_set_irq_enabled(host, irq_reg, false); + writew(irq_reg, host->base + JZ_REG_MMC_IREG); + + return IRQ_WAKE_THREAD; + } + } + + return IRQ_HANDLED; +} + +static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate) +{ + int div = 0; + int real_rate; + + jz4740_mmc_clock_disable(host); + clk_set_rate(host->clk, JZ_MMC_CLK_RATE); + + real_rate = clk_get_rate(host->clk); + + while (real_rate > rate && div < 7) { + ++div; + real_rate >>= 1; + } + + writew(div, host->base + JZ_REG_MMC_CLKRT); + return real_rate; +} + +static void jz4740_mmc_request(struct mmc_host *mmc, struct mmc_request *req) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + + host->req = req; + + writew(0xffff, host->base + JZ_REG_MMC_IREG); + + writew(JZ_MMC_IRQ_END_CMD_RES, host->base + JZ_REG_MMC_IREG); + jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, true); + + host->state = JZ4740_MMC_STATE_READ_RESPONSE; + set_bit(0, &host->waiting); + mod_timer(&host->timeout_timer, jiffies + 5*HZ); + jz4740_mmc_send_command(host, req->cmd); +} + +static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + if (ios->clock) + jz4740_mmc_set_clock_rate(host, ios->clock); + + switch (ios->power_mode) { + case MMC_POWER_UP: + jz4740_mmc_reset(host); + if (gpio_is_valid(host->pdata->gpio_power)) + gpio_set_value(host->pdata->gpio_power, + !host->pdata->power_active_low); + host->cmdat |= JZ_MMC_CMDAT_INIT; + clk_enable(host->clk); + break; + case MMC_POWER_ON: + break; + default: + if (gpio_is_valid(host->pdata->gpio_power)) + gpio_set_value(host->pdata->gpio_power, + host->pdata->power_active_low); + clk_disable(host->clk); + break; + } + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_1: + host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_4BIT; + break; + case MMC_BUS_WIDTH_4: + host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_4BIT; + break; + default: + break; + } +} + +static int jz4740_mmc_get_ro(struct mmc_host *mmc) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + if (!gpio_is_valid(host->pdata->gpio_read_only)) + return -ENOSYS; + + return gpio_get_value(host->pdata->gpio_read_only) ^ + host->pdata->read_only_active_low; +} + +static int jz4740_mmc_get_cd(struct mmc_host *mmc) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + if (!gpio_is_valid(host->pdata->gpio_card_detect)) + return -ENOSYS; + + return gpio_get_value(host->pdata->gpio_card_detect) ^ + host->pdata->card_detect_active_low; +} + +static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid) +{ + struct jz4740_mmc_host *host = devid; + + mmc_detect_change(host->mmc, HZ / 2); + + return IRQ_HANDLED; +} + +static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable); +} + +static const struct mmc_host_ops jz4740_mmc_ops = { + .request = jz4740_mmc_request, + .set_ios = jz4740_mmc_set_ios, + .get_ro = jz4740_mmc_get_ro, + .get_cd = jz4740_mmc_get_cd, + .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, +}; + +static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = { + JZ_GPIO_BULK_PIN(MSC_CMD), + JZ_GPIO_BULK_PIN(MSC_CLK), + JZ_GPIO_BULK_PIN(MSC_DATA0), + JZ_GPIO_BULK_PIN(MSC_DATA1), + JZ_GPIO_BULK_PIN(MSC_DATA2), + JZ_GPIO_BULK_PIN(MSC_DATA3), +}; + +static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio, + const char *name, bool output, int value) +{ + int ret; + + if (!gpio_is_valid(gpio)) + return 0; + + ret = gpio_request(gpio, name); + if (ret) { + dev_err(dev, "Failed to request %s gpio: %d\n", name, ret); + return ret; + } + + if (output) + gpio_direction_output(gpio, value); + else + gpio_direction_input(gpio); + + return 0; +} + +static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev) +{ + int ret; + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) + return 0; + + ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_card_detect, + "MMC detect change", false, 0); + if (ret) + goto err; + + ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_read_only, + "MMC read only", false, 0); + if (ret) + goto err_free_gpio_card_detect; + + ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, + "MMC read only", true, pdata->power_active_low); + if (ret) + goto err_free_gpio_read_only; + + return 0; + +err_free_gpio_read_only: + if (gpio_is_valid(pdata->gpio_read_only)) + gpio_free(pdata->gpio_read_only); +err_free_gpio_card_detect: + if (gpio_is_valid(pdata->gpio_card_detect)) + gpio_free(pdata->gpio_card_detect); +err: + return ret; +} + +static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev, + struct jz4740_mmc_host *host) +{ + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + + if (!gpio_is_valid(pdata->gpio_card_detect)) + return 0; + + host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect); + if (host->card_detect_irq < 0) { + dev_warn(&pdev->dev, "Failed to get card detect irq\n"); + return 0; + } + + return request_irq(host->card_detect_irq, jz4740_mmc_card_detect_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "MMC card detect", host); +} + +static void jz4740_mmc_free_gpios(struct platform_device *pdev) +{ + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) + return; + + if (gpio_is_valid(pdata->gpio_power)) + gpio_free(pdata->gpio_power); + if (gpio_is_valid(pdata->gpio_read_only)) + gpio_free(pdata->gpio_read_only); + if (gpio_is_valid(pdata->gpio_card_detect)) + gpio_free(pdata->gpio_card_detect); +} + +static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) +{ + size_t num_pins = ARRAY_SIZE(jz4740_mmc_pins); + if (host->pdata && host->pdata->data_1bit) + num_pins -= 3; + + return num_pins; +} + +static int __devinit jz4740_mmc_probe(struct platform_device* pdev) +{ + int ret; + struct mmc_host *mmc; + struct jz4740_mmc_host *host; + struct jz4740_mmc_platform_data *pdata; + + pdata = pdev->dev.platform_data; + + mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev); + if (!mmc) { + dev_err(&pdev->dev, "Failed to alloc mmc host structure\n"); + return -ENOMEM; + } + + host = mmc_priv(mmc); + host->pdata = pdata; + + host->irq = platform_get_irq(pdev, 0); + if (host->irq < 0) { + ret = host->irq; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); + goto err_free_host; + } + + host->clk = clk_get(&pdev->dev, "mmc"); + if (!host->clk) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get mmc clock\n"); + goto err_free_host; + } + + host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!host->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get base platform memory\n"); + goto err_clk_put; + } + + host->mem = request_mem_region(host->mem->start, + resource_size(host->mem), pdev->name); + if (!host->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request base memory region\n"); + goto err_clk_put; + } + + host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); + if (!host->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap base memory\n"); + goto err_release_mem_region; + } + + ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + if (ret) { + dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); + goto err_iounmap; + } + + ret = jz4740_mmc_request_gpios(pdev); + if (ret) + goto err_gpio_bulk_free; + + mmc->ops = &jz4740_mmc_ops; + mmc->f_min = JZ_MMC_CLK_RATE / 128; + mmc->f_max = JZ_MMC_CLK_RATE; + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->caps = (pdata && pdata->data_1bit) ? 0 : MMC_CAP_4_BIT_DATA; + mmc->caps |= MMC_CAP_SDIO_IRQ; + + mmc->max_blk_size = (1 << 10) - 1; + mmc->max_blk_count = (1 << 15) - 1; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + + mmc->max_phys_segs = 128; + mmc->max_hw_segs = 128; + mmc->max_seg_size = mmc->max_req_size; + + host->mmc = mmc; + host->pdev = pdev; + spin_lock_init(&host->lock); + host->irq_mask = 0xffff; + + ret = jz4740_mmc_request_cd_irq(pdev, host); + if (ret) { + dev_err(&pdev->dev, "Failed to request card detect irq\n"); + goto err_free_gpios; + } + + ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, + dev_name(&pdev->dev), host); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); + goto err_free_card_detect_irq; + } + + jz4740_mmc_reset(host); + jz4740_mmc_clock_disable(host); + setup_timer(&host->timeout_timer, jz4740_mmc_timeout, + (unsigned long)host); + /* It is not important when it times out, it just needs to timeout. */ + set_timer_slack(&host->timeout_timer, HZ); + + platform_set_drvdata(pdev, host); + ret = mmc_add_host(mmc); + + if (ret) { + dev_err(&pdev->dev, "Failed to add mmc host: %d\n", ret); + goto err_free_irq; + } + dev_info(&pdev->dev, "JZ SD/MMC card driver registered\n"); + + return 0; + +err_free_irq: + free_irq(host->irq, host); +err_free_card_detect_irq: + if (host->card_detect_irq >= 0) + free_irq(host->card_detect_irq, host); +err_free_gpios: + jz4740_mmc_free_gpios(pdev); +err_gpio_bulk_free: + jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); +err_iounmap: + iounmap(host->base); +err_release_mem_region: + release_mem_region(host->mem->start, resource_size(host->mem)); +err_clk_put: + clk_put(host->clk); +err_free_host: + platform_set_drvdata(pdev, NULL); + mmc_free_host(mmc); + + return ret; +} + +static int __devexit jz4740_mmc_remove(struct platform_device *pdev) +{ + struct jz4740_mmc_host *host = platform_get_drvdata(pdev); + + del_timer_sync(&host->timeout_timer); + jz4740_mmc_set_irq_enabled(host, 0xff, false); + jz4740_mmc_reset(host); + + mmc_remove_host(host->mmc); + + free_irq(host->irq, host); + if (host->card_detect_irq >= 0) + free_irq(host->card_detect_irq, host); + + jz4740_mmc_free_gpios(pdev); + jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + iounmap(host->base); + release_mem_region(host->mem->start, resource_size(host->mem)); + + clk_put(host->clk); + + platform_set_drvdata(pdev, NULL); + mmc_free_host(host->mmc); + + return 0; +} + +#ifdef CONFIG_PM + +static int jz4740_mmc_suspend(struct device *dev) +{ + struct jz4740_mmc_host *host = dev_get_drvdata(dev); + + mmc_suspend_host(host->mmc); + + jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + return 0; +} + +static int jz4740_mmc_resume(struct device *dev) +{ + struct jz4740_mmc_host *host = dev_get_drvdata(dev); + + jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + mmc_resume_host(host->mmc); + + return 0; +} + +const struct dev_pm_ops jz4740_mmc_pm_ops = { + .suspend = jz4740_mmc_suspend, + .resume = jz4740_mmc_resume, + .poweroff = jz4740_mmc_suspend, + .restore = jz4740_mmc_resume, +}; + +#define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) +#else +#define JZ4740_MMC_PM_OPS NULL +#endif + +static struct platform_driver jz4740_mmc_driver = { + .probe = jz4740_mmc_probe, + .remove = __devexit_p(jz4740_mmc_remove), + .driver = { + .name = "jz4740-mmc", + .owner = THIS_MODULE, + .pm = JZ4740_MMC_PM_OPS, + }, +}; + +static int __init jz4740_mmc_init(void) +{ + return platform_driver_register(&jz4740_mmc_driver); +} +module_init(jz4740_mmc_init); + +static void __exit jz4740_mmc_exit(void) +{ + platform_driver_unregister(&jz4740_mmc_driver); +} +module_exit(jz4740_mmc_exit); + +MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index ffc3720..362d177 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -526,4 +526,10 @@ config MTD_NAND_NUC900 This enables the driver for the NAND Flash on evaluation board based on w90p910 / NUC9xx. +config MTD_NAND_JZ4740 + tristate "Support for JZ4740 SoC NAND controller" + depends on MACH_JZ4740 + help + Enables support for NAND Flash on JZ4740 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index e8ab884..ac83dcd 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o obj-$(CONFIG_MTD_NAND_BCM_UMI) += bcm_umi_nand.o nand_bcm_umi.o obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o obj-$(CONFIG_MTD_NAND_RICOH) += r852.o +obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o nand-objs := nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c new file mode 100644 index 0000000..67343fc --- /dev/null +++ b/drivers/mtd/nand/jz4740_nand.c @@ -0,0 +1,516 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC NAND controller driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#define JZ_REG_NAND_CTRL 0x50 +#define JZ_REG_NAND_ECC_CTRL 0x100 +#define JZ_REG_NAND_DATA 0x104 +#define JZ_REG_NAND_PAR0 0x108 +#define JZ_REG_NAND_PAR1 0x10C +#define JZ_REG_NAND_PAR2 0x110 +#define JZ_REG_NAND_IRQ_STAT 0x114 +#define JZ_REG_NAND_IRQ_CTRL 0x118 +#define JZ_REG_NAND_ERR(x) (0x11C + ((x) << 2)) + +#define JZ_NAND_ECC_CTRL_PAR_READY BIT(4) +#define JZ_NAND_ECC_CTRL_ENCODING BIT(3) +#define JZ_NAND_ECC_CTRL_RS BIT(2) +#define JZ_NAND_ECC_CTRL_RESET BIT(1) +#define JZ_NAND_ECC_CTRL_ENABLE BIT(0) + +#define JZ_NAND_STATUS_ERR_COUNT (BIT(31) | BIT(30) | BIT(29)) +#define JZ_NAND_STATUS_PAD_FINISH BIT(4) +#define JZ_NAND_STATUS_DEC_FINISH BIT(3) +#define JZ_NAND_STATUS_ENC_FINISH BIT(2) +#define JZ_NAND_STATUS_UNCOR_ERROR BIT(1) +#define JZ_NAND_STATUS_ERROR BIT(0) + +#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1) +#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1) + +#define JZ_NAND_MEM_ADDR_OFFSET 0x10000 +#define JZ_NAND_MEM_CMD_OFFSET 0x08000 + +struct jz_nand { + struct mtd_info mtd; + struct nand_chip chip; + void __iomem *base; + struct resource *mem; + + void __iomem *bank_base; + struct resource *bank_mem; + + struct jz_nand_platform_data *pdata; + bool is_reading; +}; + +static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) +{ + return container_of(mtd, struct jz_nand, mtd); +} + +static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct nand_chip *chip = mtd->priv; + uint32_t reg; + + if (ctrl & NAND_CTRL_CHANGE) { + BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE)); + if (ctrl & NAND_ALE) + chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET; + else if (ctrl & NAND_CLE) + chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET; + else + chip->IO_ADDR_W = nand->bank_base; + + reg = readl(nand->base + JZ_REG_NAND_CTRL); + if (ctrl & NAND_NCE) + reg |= JZ_NAND_CTRL_ASSERT_CHIP(0); + else + reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0); + writel(reg, nand->base + JZ_REG_NAND_CTRL); + } + if (dat != NAND_CMD_NONE) + writeb(dat, chip->IO_ADDR_W); +} + +static int jz_nand_dev_ready(struct mtd_info *mtd) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + return gpio_get_value_cansleep(nand->pdata->busy_gpio); +} + +static void jz_nand_hwctl(struct mtd_info *mtd, int mode) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + uint32_t reg; + + writel(0, nand->base + JZ_REG_NAND_IRQ_STAT); + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + + reg |= JZ_NAND_ECC_CTRL_RESET; + reg |= JZ_NAND_ECC_CTRL_ENABLE; + reg |= JZ_NAND_ECC_CTRL_RS; + + switch (mode) { + case NAND_ECC_READ: + reg &= ~JZ_NAND_ECC_CTRL_ENCODING; + nand->is_reading = true; + break; + case NAND_ECC_WRITE: + reg |= JZ_NAND_ECC_CTRL_ENCODING; + nand->is_reading = false; + break; + default: + break; + } + + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); +} + +static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat, + uint8_t *ecc_code) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + uint32_t reg, status; + int i; + unsigned int timeout = 1000; + static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4, + 0x8b, 0xff, 0xb7, 0x6f}; + + if (nand->is_reading) + return 0; + + do { + status = readl(nand->base + JZ_REG_NAND_IRQ_STAT); + } while (!(status & JZ_NAND_STATUS_ENC_FINISH) && --timeout); + + if (timeout == 0) + return -1; + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg &= ~JZ_NAND_ECC_CTRL_ENABLE; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + for (i = 0; i < 9; ++i) + ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i); + + /* If the written data is completly 0xff, we also want to write 0xff as + * ecc, otherwise we will get in trouble when doing subpage writes. */ + if (memcmp(ecc_code, empty_block_ecc, 9) == 0) + memset(ecc_code, 0xff, 9); + + return 0; +} + +static void jz_nand_correct_data(uint8_t *dat, int index, int mask) +{ + int offset = index & 0x7; + uint16_t data; + + index += (index >> 3); + + data = dat[index]; + data |= dat[index+1] << 8; + + mask ^= (data >> offset) & 0x1ff; + data &= ~(0x1ff << offset); + data |= (mask << offset); + + dat[index] = data & 0xff; + dat[index+1] = (data >> 8) & 0xff; +} + +static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + int i, error_count, index; + uint32_t reg, status, error; + uint32_t t; + unsigned int timeout = 1000; + + t = read_ecc[0]; + + if (t == 0xff) { + for (i = 1; i < 9; ++i) + t &= read_ecc[i]; + + t &= dat[0]; + t &= dat[nand->chip.ecc.size / 2]; + t &= dat[nand->chip.ecc.size - 1]; + + if (t == 0xff) { + for (i = 1; i < nand->chip.ecc.size - 1; ++i) + t &= dat[i]; + if (t == 0xff) + return 0; + } + } + + for (i = 0; i < 9; ++i) + writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i); + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg |= JZ_NAND_ECC_CTRL_PAR_READY; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + do { + status = readl(nand->base + JZ_REG_NAND_IRQ_STAT); + } while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout); + + if (timeout == 0) + return -1; + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg &= ~JZ_NAND_ECC_CTRL_ENABLE; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + if (status & JZ_NAND_STATUS_ERROR) { + if (status & JZ_NAND_STATUS_UNCOR_ERROR) + return -1; + + error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29; + + for (i = 0; i < error_count; ++i) { + error = readl(nand->base + JZ_REG_NAND_ERR(i)); + index = ((error >> 16) & 0x1ff) - 1; + if (index >= 0 && index < 512) + jz_nand_correct_data(dat, index, error & 0x1ff); + } + + return error_count; + } + + return 0; +} + + +/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos + * handling. The ecc area is for 4k chips 72 bytes long and thus does not fit + * into the eccpos array. */ +static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + unsigned int ecc_offset = chip->page_shift; + + /* Read the OOB area first */ + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + + for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, eccsize); + + stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } + return 0; +} + +/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */ +static void jz_nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + const uint8_t *p = buf; + unsigned int ecc_offset = chip->page_shift; + + for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->write_buf(mtd, p, eccsize); + chip->ecc.calculate(mtd, p, &chip->oob_poi[i]); + } + + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +} + +#ifdef CONFIG_MTD_CMDLINE_PARTS +static const char *part_probes[] = {"cmdline", NULL}; +#endif + +static int jz_nand_ioremap_resource(struct platform_device *pdev, + const char *name, struct resource **res, void __iomem **base) +{ + int ret; + + *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + if (!*res) { + dev_err(&pdev->dev, "Failed to get platform %s memory\n", name); + ret = -ENXIO; + goto err; + } + + *res = request_mem_region((*res)->start, resource_size(*res), + pdev->name); + if (!*res) { + dev_err(&pdev->dev, "Failed to request %s memory region\n", name); + ret = -EBUSY; + goto err; + } + + *base = ioremap((*res)->start, resource_size(*res)); + if (!*base) { + dev_err(&pdev->dev, "Failed to ioremap %s memory region\n", name); + ret = -EBUSY; + goto err_release_mem; + } + + return 0; + +err_release_mem: + release_mem_region((*res)->start, resource_size(*res)); +err: + *res = NULL; + *base = NULL; + return ret; +} + +static int __devinit jz_nand_probe(struct platform_device *pdev) +{ + int ret; + struct jz_nand *nand; + struct nand_chip *chip; + struct mtd_info *mtd; + struct jz_nand_platform_data *pdata = pdev->dev.platform_data; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *partition_info; + int num_partitions = 0; +#endif + + nand = kzalloc(sizeof(*nand), GFP_KERNEL); + if (!nand) { + dev_err(&pdev->dev, "Failed to allocate device structure.\n"); + return -ENOMEM; + } + + ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base); + if (ret) + goto err_free; + ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem, + &nand->bank_base); + if (ret) + goto err_iounmap_mmio; + + if (pdata && gpio_is_valid(pdata->busy_gpio)) { + ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request busy gpio %d: %d\n", + pdata->busy_gpio, ret); + goto err_iounmap_mem; + } + } + + mtd = &nand->mtd; + chip = &nand->chip; + mtd->priv = chip; + mtd->owner = THIS_MODULE; + mtd->name = "jz4740-nand"; + + chip->ecc.hwctl = jz_nand_hwctl; + chip->ecc.calculate = jz_nand_calculate_ecc_rs; + chip->ecc.correct = jz_nand_correct_ecc_rs; + chip->ecc.mode = NAND_ECC_HW_OOB_FIRST; + chip->ecc.size = 512; + chip->ecc.bytes = 9; + + chip->ecc.read_page = jz_nand_read_page_hwecc_oob_first; + chip->ecc.write_page = jz_nand_write_page_hwecc; + + if (pdata) + chip->ecc.layout = pdata->ecc_layout; + + chip->chip_delay = 50; + chip->cmd_ctrl = jz_nand_cmd_ctrl; + + if (pdata && gpio_is_valid(pdata->busy_gpio)) + chip->dev_ready = jz_nand_dev_ready; + + chip->IO_ADDR_R = nand->bank_base; + chip->IO_ADDR_W = nand->bank_base; + + nand->pdata = pdata; + platform_set_drvdata(pdev, nand); + + writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL); + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) { + dev_err(&pdev->dev, "Failed to scan nand\n"); + goto err_gpio_free; + } + + if (pdata && pdata->ident_callback) { + pdata->ident_callback(pdev, chip, &pdata->partitions, + &pdata->num_partitions); + } + + ret = nand_scan_tail(mtd); + if (ret) { + dev_err(&pdev->dev, "Failed to scan nand\n"); + goto err_gpio_free; + } + +#ifdef CONFIG_MTD_PARTITIONS +#ifdef CONFIG_MTD_CMDLINE_PARTS + num_partitions = parse_mtd_partitions(mtd, part_probes, + &partition_info, 0); +#endif + if (num_partitions <= 0 && pdata) { + num_partitions = pdata->num_partitions; + partition_info = pdata->partitions; + } + + if (num_partitions > 0) + ret = add_mtd_partitions(mtd, partition_info, num_partitions); + else +#endif + ret = add_mtd_device(mtd); + + if (ret) { + dev_err(&pdev->dev, "Failed to add mtd device\n"); + goto err_nand_release; + } + + dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n"); + + return 0; + +err_nand_release: + nand_release(&nand->mtd); +err_gpio_free: + platform_set_drvdata(pdev, NULL); + gpio_free(pdata->busy_gpio); +err_iounmap_mem: + iounmap(nand->bank_base); +err_iounmap_mmio: + iounmap(nand->base); +err_free: + kfree(nand); + return ret; +} + +static int __devexit jz_nand_remove(struct platform_device *pdev) +{ + struct jz_nand *nand = platform_get_drvdata(pdev); + + nand_release(&nand->mtd); + + /* Deassert and disable all chips */ + writel(0, nand->base + JZ_REG_NAND_CTRL); + + iounmap(nand->bank_base); + release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem)); + iounmap(nand->base); + release_mem_region(nand->mem->start, resource_size(nand->mem)); + + platform_set_drvdata(pdev, NULL); + kfree(nand); + + return 0; +} + +struct platform_driver jz_nand_driver = { + .probe = jz_nand_probe, + .remove = __devexit_p(jz_nand_remove), + .driver = { + .name = "jz4740-nand", + .owner = THIS_MODULE, + }, +}; + +static int __init jz_nand_init(void) +{ + return platform_driver_register(&jz_nand_driver); +} +module_init(jz_nand_init); + +static void __exit jz_nand_exit(void) +{ + platform_driver_unregister(&jz_nand_driver); +} +module_exit(jz_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC"); +MODULE_ALIAS("platform:jz4740-nand"); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ce2fcdd..adead30 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -484,7 +484,7 @@ config XTENSA_XT2000_SONIC config MIPS_AU1X00_ENET tristate "MIPS AU1000 Ethernet support" - depends on SOC_AU1X00 + depends on MIPS_ALCHEMY select PHYLIB select CRC32 help diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index ece6128..17e7e27 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -104,14 +104,6 @@ MODULE_VERSION(DRV_VERSION); * complete immediately. */ -/* These addresses are only used if yamon doesn't tell us what - * the mac address is, and the mac address is not passed on the - * command line. - */ -static unsigned char au1000_mac_addr[6] __devinitdata = { - 0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00 -}; - struct au1000_private *au_macs[NUM_ETH_INTERFACES]; /* @@ -1002,7 +994,6 @@ static int __devinit au1000_probe(struct platform_device *pdev) db_dest_t *pDB, *pDBfree; int irq, i, err = 0; struct resource *base, *macen; - char ethaddr[6]; base = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!base) { @@ -1079,24 +1070,13 @@ static int __devinit au1000_probe(struct platform_device *pdev) } aup->mac_id = pdev->id; - if (pdev->id == 0) { - if (prom_get_ethernet_addr(ethaddr) == 0) - memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); - else { - netdev_info(dev, "No MAC address found\n"); - /* Use the hard coded MAC addresses */ - } - + if (pdev->id == 0) au1000_setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); - } else if (pdev->id == 1) + else if (pdev->id == 1) au1000_setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); - /* - * Assign to the Ethernet ports two consecutive MAC addresses - * to match those that are printed on their stickers - */ - memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); - dev->dev_addr[5] += pdev->id; + /* set a random MAC now in case platform_data doesn't provide one */ + random_ether_addr(dev->dev_addr); *aup->enable = 0; aup->mac_enabled = 0; @@ -1106,6 +1086,9 @@ static int __devinit au1000_probe(struct platform_device *pdev) dev_info(&pdev->dev, "no platform_data passed, PHY search on MAC0\n"); aup->phy1_search_mac0 = 1; } else { + if (is_valid_ether_addr(pd->mac)) + memcpy(dev->dev_addr, pd->mac, 6); + aup->phy_static_config = pd->phy_static_config; aup->phy_search_highest_addr = pd->phy_search_highest_addr; aup->phy1_search_mac0 = pd->phy1_search_mac0; diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d0f5ad3..c988514 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -157,11 +157,11 @@ config PCMCIA_M8XX config PCMCIA_AU1X00 tristate "Au1x00 pcmcia support" - depends on SOC_AU1X00 && PCMCIA + depends on MIPS_ALCHEMY && PCMCIA config PCMCIA_ALCHEMY_DEVBOARD tristate "Alchemy Db/Pb1xxx PCMCIA socket services" - depends on SOC_AU1X00 && PCMCIA + depends on MIPS_ALCHEMY && PCMCIA select 64BIT_PHYS_ADDR help Enable this driver of you want PCMCIA support on your Alchemy diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 8e9ba17..1e5506b 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -142,4 +142,15 @@ config CHARGER_PCF50633 help Say Y to include support for NXP PCF50633 Main Battery Charger. +config BATTERY_JZ4740 + tristate "Ingenic JZ4740 battery" + depends on MACH_JZ4740 + depends on MFD_JZ4740_ADC + help + Say Y to enable support for the battery on Ingenic JZ4740 based + boards. + + This driver can be build as a module. If so, the module will be + called jz4740-battery. + endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 0005080..cf95009 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -34,3 +34,4 @@ obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o +obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c new file mode 100644 index 0000000..20c4b95 --- /dev/null +++ b/drivers/power/jz4740-battery.c @@ -0,0 +1,445 @@ +/* + * Battery measurement code for Ingenic JZ SOC. + * + * Copyright (C) 2009 Jiejing Zhang + * Copyright (C) 2010, Lars-Peter Clausen + * + * based on tosa_battery.c + * + * Copyright (C) 2008 Marek Vasut +* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +struct jz_battery { + struct jz_battery_platform_data *pdata; + struct platform_device *pdev; + + struct resource *mem; + void __iomem *base; + + int irq; + int charge_irq; + + struct mfd_cell *cell; + + int status; + long voltage; + + struct completion read_completion; + + struct power_supply battery; + struct delayed_work work; +}; + +static inline struct jz_battery *psy_to_jz_battery(struct power_supply *psy) +{ + return container_of(psy, struct jz_battery, battery); +} + +static irqreturn_t jz_battery_irq_handler(int irq, void *devid) +{ + struct jz_battery *battery = devid; + + complete(&battery->read_completion); + return IRQ_HANDLED; +} + +static long jz_battery_read_voltage(struct jz_battery *battery) +{ + unsigned long t; + unsigned long val; + long voltage; + + INIT_COMPLETION(battery->read_completion); + + enable_irq(battery->irq); + battery->cell->enable(battery->pdev); + + t = wait_for_completion_interruptible_timeout(&battery->read_completion, + HZ); + + if (t > 0) { + val = readw(battery->base) & 0xfff; + + if (battery->pdata->info.voltage_max_design <= 2500000) + val = (val * 78125UL) >> 7UL; + else + val = ((val * 924375UL) >> 9UL) + 33000; + voltage = (long)val; + } else { + voltage = t ? t : -ETIMEDOUT; + } + + battery->cell->disable(battery->pdev); + disable_irq(battery->irq); + + return voltage; +} + +static int jz_battery_get_capacity(struct power_supply *psy) +{ + struct jz_battery *jz_battery = psy_to_jz_battery(psy); + struct power_supply_info *info = &jz_battery->pdata->info; + long voltage; + int ret; + int voltage_span; + + voltage = jz_battery_read_voltage(jz_battery); + + if (voltage < 0) + return voltage; + + voltage_span = info->voltage_max_design - info->voltage_min_design; + ret = ((voltage - info->voltage_min_design) * 100) / voltage_span; + + if (ret > 100) + ret = 100; + else if (ret < 0) + ret = 0; + + return ret; +} + +static int jz_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct jz_battery *jz_battery = psy_to_jz_battery(psy); + struct power_supply_info *info = &jz_battery->pdata->info; + long voltage; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = jz_battery->status; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = jz_battery->pdata->info.technology; + break; + case POWER_SUPPLY_PROP_HEALTH: + voltage = jz_battery_read_voltage(jz_battery); + if (voltage < info->voltage_min_design) + val->intval = POWER_SUPPLY_HEALTH_DEAD; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = jz_battery_get_capacity(psy); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = jz_battery_read_voltage(jz_battery); + if (val->intval < 0) + return val->intval; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = info->voltage_max_design; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = info->voltage_min_design; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 1; + break; + default: + return -EINVAL; + } + return 0; +} + +static void jz_battery_external_power_changed(struct power_supply *psy) +{ + struct jz_battery *jz_battery = psy_to_jz_battery(psy); + + cancel_delayed_work(&jz_battery->work); + schedule_delayed_work(&jz_battery->work, 0); +} + +static irqreturn_t jz_battery_charge_irq(int irq, void *data) +{ + struct jz_battery *jz_battery = data; + + cancel_delayed_work(&jz_battery->work); + schedule_delayed_work(&jz_battery->work, 0); + + return IRQ_HANDLED; +} + +static void jz_battery_update(struct jz_battery *jz_battery) +{ + int status; + long voltage; + bool has_changed = false; + int is_charging; + + if (gpio_is_valid(jz_battery->pdata->gpio_charge)) { + is_charging = gpio_get_value(jz_battery->pdata->gpio_charge); + is_charging ^= jz_battery->pdata->gpio_charge_active_low; + if (is_charging) + status = POWER_SUPPLY_STATUS_CHARGING; + else + status = POWER_SUPPLY_STATUS_NOT_CHARGING; + + if (status != jz_battery->status) { + jz_battery->status = status; + has_changed = true; + } + } + + voltage = jz_battery_read_voltage(jz_battery); + if (abs(voltage - jz_battery->voltage) < 50000) { + jz_battery->voltage = voltage; + has_changed = true; + } + + if (has_changed) + power_supply_changed(&jz_battery->battery); +} + +static enum power_supply_property jz_battery_properties[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_PRESENT, +}; + +static void jz_battery_work(struct work_struct *work) +{ + /* Too small interval will increase system workload */ + const int interval = HZ * 30; + struct jz_battery *jz_battery = container_of(work, struct jz_battery, + work.work); + + jz_battery_update(jz_battery); + schedule_delayed_work(&jz_battery->work, interval); +} + +static int __devinit jz_battery_probe(struct platform_device *pdev) +{ + int ret = 0; + struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data; + struct jz_battery *jz_battery; + struct power_supply *battery; + + jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL); + if (!jz_battery) { + dev_err(&pdev->dev, "Failed to allocate driver structure\n"); + return -ENOMEM; + } + + jz_battery->cell = pdev->dev.platform_data; + + jz_battery->irq = platform_get_irq(pdev, 0); + if (jz_battery->irq < 0) { + ret = jz_battery->irq; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); + goto err_free; + } + + jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!jz_battery->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); + goto err_free; + } + + jz_battery->mem = request_mem_region(jz_battery->mem->start, + resource_size(jz_battery->mem), pdev->name); + if (!jz_battery->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + goto err_free; + } + + jz_battery->base = ioremap_nocache(jz_battery->mem->start, + resource_size(jz_battery->mem)); + if (!jz_battery->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); + goto err_release_mem_region; + } + + battery = &jz_battery->battery; + battery->name = pdata->info.name; + battery->type = POWER_SUPPLY_TYPE_BATTERY; + battery->properties = jz_battery_properties; + battery->num_properties = ARRAY_SIZE(jz_battery_properties); + battery->get_property = jz_battery_get_property; + battery->external_power_changed = jz_battery_external_power_changed; + battery->use_for_apm = 1; + + jz_battery->pdata = pdata; + jz_battery->pdev = pdev; + + init_completion(&jz_battery->read_completion); + + INIT_DELAYED_WORK(&jz_battery->work, jz_battery_work); + + ret = request_irq(jz_battery->irq, jz_battery_irq_handler, 0, pdev->name, + jz_battery); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq %d\n", ret); + goto err_iounmap; + } + disable_irq(jz_battery->irq); + + if (gpio_is_valid(pdata->gpio_charge)) { + ret = gpio_request(pdata->gpio_charge, dev_name(&pdev->dev)); + if (ret) { + dev_err(&pdev->dev, "charger state gpio request failed.\n"); + goto err_free_irq; + } + ret = gpio_direction_input(pdata->gpio_charge); + if (ret) { + dev_err(&pdev->dev, "charger state gpio set direction failed.\n"); + goto err_free_gpio; + } + + jz_battery->charge_irq = gpio_to_irq(pdata->gpio_charge); + + if (jz_battery->charge_irq >= 0) { + ret = request_irq(jz_battery->charge_irq, + jz_battery_charge_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + dev_name(&pdev->dev), jz_battery); + if (ret) { + dev_err(&pdev->dev, "Failed to request charge irq: %d\n", ret); + goto err_free_gpio; + } + } + } else { + jz_battery->charge_irq = -1; + } + + if (jz_battery->pdata->info.voltage_max_design <= 2500000) + jz4740_adc_set_config(pdev->dev.parent, JZ_ADC_CONFIG_BAT_MB, + JZ_ADC_CONFIG_BAT_MB); + else + jz4740_adc_set_config(pdev->dev.parent, JZ_ADC_CONFIG_BAT_MB, 0); + + ret = power_supply_register(&pdev->dev, &jz_battery->battery); + if (ret) { + dev_err(&pdev->dev, "power supply battery register failed.\n"); + goto err_free_charge_irq; + } + + platform_set_drvdata(pdev, jz_battery); + schedule_delayed_work(&jz_battery->work, 0); + + return 0; + +err_free_charge_irq: + if (jz_battery->charge_irq >= 0) + free_irq(jz_battery->charge_irq, jz_battery); +err_free_gpio: + if (gpio_is_valid(pdata->gpio_charge)) + gpio_free(jz_battery->pdata->gpio_charge); +err_free_irq: + free_irq(jz_battery->irq, jz_battery); +err_iounmap: + platform_set_drvdata(pdev, NULL); + iounmap(jz_battery->base); +err_release_mem_region: + release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); +err_free: + kfree(jz_battery); + return ret; +} + +static int __devexit jz_battery_remove(struct platform_device *pdev) +{ + struct jz_battery *jz_battery = platform_get_drvdata(pdev); + + cancel_delayed_work_sync(&jz_battery->work); + + if (gpio_is_valid(jz_battery->pdata->gpio_charge)) { + if (jz_battery->charge_irq >= 0) + free_irq(jz_battery->charge_irq, jz_battery); + gpio_free(jz_battery->pdata->gpio_charge); + } + + power_supply_unregister(&jz_battery->battery); + + free_irq(jz_battery->irq, jz_battery); + + iounmap(jz_battery->base); + release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); + + return 0; +} + +#ifdef CONFIG_PM +static int jz_battery_suspend(struct device *dev) +{ + struct jz_battery *jz_battery = dev_get_drvdata(dev); + + cancel_delayed_work_sync(&jz_battery->work); + jz_battery->status = POWER_SUPPLY_STATUS_UNKNOWN; + + return 0; +} + +static int jz_battery_resume(struct device *dev) +{ + struct jz_battery *jz_battery = dev_get_drvdata(dev); + + schedule_delayed_work(&jz_battery->work, 0); + + return 0; +} + +static const struct dev_pm_ops jz_battery_pm_ops = { + .suspend = jz_battery_suspend, + .resume = jz_battery_resume, +}; + +#define JZ_BATTERY_PM_OPS (&jz_battery_pm_ops) +#else +#define JZ_BATTERY_PM_OPS NULL +#endif + +static struct platform_driver jz_battery_driver = { + .probe = jz_battery_probe, + .remove = __devexit_p(jz_battery_remove), + .driver = { + .name = "jz4740-battery", + .owner = THIS_MODULE, + .pm = JZ_BATTERY_PM_OPS, + }, +}; + +static int __init jz_battery_init(void) +{ + return platform_driver_register(&jz_battery_driver); +} +module_init(jz_battery_init); + +static void __exit jz_battery_exit(void) +{ + platform_driver_unregister(&jz_battery_driver); +} +module_exit(jz_battery_exit); + +MODULE_ALIAS("platform:jz4740-battery"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("JZ4740 SoC battery driver"); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 10ba12c..4301a6c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -774,7 +774,7 @@ config RTC_DRV_AT91SAM9_GPBR config RTC_DRV_AU1XXX tristate "Au1xxx Counter0 RTC support" - depends on SOC_AU1X00 + depends on MIPS_ALCHEMY help This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year counter) to be used as a RTC. @@ -905,4 +905,15 @@ config RTC_DRV_MPC5121 This driver can also be built as a module. If so, the module will be called rtc-mpc5121. +config RTC_DRV_JZ4740 + tristate "Ingenic JZ4740 SoC" + depends on RTC_CLASS + depends on MACH_JZ4740 + help + If you say yes here you get support for the Ingenic JZ4740 SoC RTC + controller. + + This driver can also be buillt as a module. If so, the module + will be called rtc-jz4740. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 5adbba7..fedf9bb 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o +obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c new file mode 100644 index 0000000..2619d57 --- /dev/null +++ b/drivers/rtc/rtc-jz4740.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC RTC driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#define JZ_REG_RTC_CTRL 0x00 +#define JZ_REG_RTC_SEC 0x04 +#define JZ_REG_RTC_SEC_ALARM 0x08 +#define JZ_REG_RTC_REGULATOR 0x0C +#define JZ_REG_RTC_HIBERNATE 0x20 +#define JZ_REG_RTC_SCRATCHPAD 0x34 + +#define JZ_RTC_CTRL_WRDY BIT(7) +#define JZ_RTC_CTRL_1HZ BIT(6) +#define JZ_RTC_CTRL_1HZ_IRQ BIT(5) +#define JZ_RTC_CTRL_AF BIT(4) +#define JZ_RTC_CTRL_AF_IRQ BIT(3) +#define JZ_RTC_CTRL_AE BIT(2) +#define JZ_RTC_CTRL_ENABLE BIT(0) + +struct jz4740_rtc { + struct resource *mem; + void __iomem *base; + + struct rtc_device *rtc; + + unsigned int irq; + + spinlock_t lock; +}; + +static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) +{ + return readl(rtc->base + reg); +} + +static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) +{ + uint32_t ctrl; + int timeout = 1000; + + do { + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); + + return timeout ? 0 : -EIO; +} + +static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, + uint32_t val) +{ + int ret; + ret = jz4740_rtc_wait_write_ready(rtc); + if (ret == 0) + writel(val, rtc->base + reg); + + return ret; +} + +static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, + bool set) +{ + int ret; + unsigned long flags; + uint32_t ctrl; + + spin_lock_irqsave(&rtc->lock, flags); + + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + + /* Don't clear interrupt flags by accident */ + ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; + + if (set) + ctrl |= mask; + else + ctrl &= ~mask; + + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); + + spin_unlock_irqrestore(&rtc->lock, flags); + + return ret; +} + +static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + uint32_t secs, secs2; + int timeout = 5; + + /* If the seconds register is read while it is updated, it can contain a + * bogus value. This can be avoided by making sure that two consecutive + * reads have the same value. + */ + secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); + secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); + + while (secs != secs2 && --timeout) { + secs = secs2; + secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); + } + + if (timeout == 0) + return -EIO; + + rtc_time_to_tm(secs, time); + + return rtc_valid_tm(time); +} + +static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + + return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); +} + +static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + uint32_t secs; + uint32_t ctrl; + + secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM); + + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + + alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE); + alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF); + + rtc_time_to_tm(secs, &alrm->time); + + return rtc_valid_tm(&alrm->time); +} + +static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + unsigned long secs; + + rtc_tm_to_time(&alrm->time, &secs); + + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); + if (!ret) + ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); + + return ret; +} + +static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable); +} + +static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); +} + +static struct rtc_class_ops jz4740_rtc_ops = { + .read_time = jz4740_rtc_read_time, + .set_mmss = jz4740_rtc_set_mmss, + .read_alarm = jz4740_rtc_read_alarm, + .set_alarm = jz4740_rtc_set_alarm, + .update_irq_enable = jz4740_rtc_update_irq_enable, + .alarm_irq_enable = jz4740_rtc_alarm_irq_enable, +}; + +static irqreturn_t jz4740_rtc_irq(int irq, void *data) +{ + struct jz4740_rtc *rtc = data; + uint32_t ctrl; + unsigned long events = 0; + + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + + if (ctrl & JZ_RTC_CTRL_1HZ) + events |= (RTC_UF | RTC_IRQF); + + if (ctrl & JZ_RTC_CTRL_AF) + events |= (RTC_AF | RTC_IRQF); + + rtc_update_irq(rtc->rtc, 1, events); + + jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); + + return IRQ_HANDLED; +} + +void jz4740_rtc_poweroff(struct device *dev) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1); +} +EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); + +static int __devinit jz4740_rtc_probe(struct platform_device *pdev) +{ + int ret; + struct jz4740_rtc *rtc; + uint32_t scratchpad; + + rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->irq = platform_get_irq(pdev, 0); + if (rtc->irq < 0) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform irq\n"); + goto err_free; + } + + rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rtc->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform mmio memory\n"); + goto err_free; + } + + rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem), + pdev->name); + if (!rtc->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + goto err_free; + } + + rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem)); + if (!rtc->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); + goto err_release_mem_region; + } + + spin_lock_init(&rtc->lock); + + platform_set_drvdata(pdev, rtc); + + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, + THIS_MODULE); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); + goto err_iounmap; + } + + ret = request_irq(rtc->irq, jz4740_rtc_irq, 0, + pdev->name, rtc); + if (ret) { + dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); + goto err_unregister_rtc; + } + + scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); + if (scratchpad != 0x12345678) { + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); + if (ret) { + dev_err(&pdev->dev, "Could not write write to RTC registers\n"); + goto err_free_irq; + } + } + + return 0; + +err_free_irq: + free_irq(rtc->irq, rtc); +err_unregister_rtc: + rtc_device_unregister(rtc->rtc); +err_iounmap: + platform_set_drvdata(pdev, NULL); + iounmap(rtc->base); +err_release_mem_region: + release_mem_region(rtc->mem->start, resource_size(rtc->mem)); +err_free: + kfree(rtc); + + return ret; +} + +static int __devexit jz4740_rtc_remove(struct platform_device *pdev) +{ + struct jz4740_rtc *rtc = platform_get_drvdata(pdev); + + free_irq(rtc->irq, rtc); + + rtc_device_unregister(rtc->rtc); + + iounmap(rtc->base); + release_mem_region(rtc->mem->start, resource_size(rtc->mem)); + + kfree(rtc); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +struct platform_driver jz4740_rtc_driver = { + .probe = jz4740_rtc_probe, + .remove = __devexit_p(jz4740_rtc_remove), + .driver = { + .name = "jz4740-rtc", + .owner = THIS_MODULE, + }, +}; + +static int __init jz4740_rtc_init(void) +{ + return platform_driver_register(&jz4740_rtc_driver); +} +module_init(jz4740_rtc_init); + +static void __exit jz4740_rtc_exit(void) +{ + platform_driver_unregister(&jz4740_rtc_driver); +} +module_exit(jz4740_rtc_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); +MODULE_ALIAS("platform:jz4740-rtc"); diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 891e1dd..09ef570 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -302,7 +302,7 @@ static const struct serial8250_config uart_config[] = { }, }; -#if defined (CONFIG_SERIAL_8250_AU1X00) +#if defined(CONFIG_MIPS_ALCHEMY) /* Au1x00 UART hardware has a weird register layout */ static const u8 au_io_in_map[] = { @@ -422,7 +422,6 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset) return readl(p->membase + offset); } -#ifdef CONFIG_SERIAL_8250_AU1X00 static unsigned int au_serial_in(struct uart_port *p, int offset) { offset = map_8250_in_reg(p, offset) << p->regshift; @@ -434,7 +433,6 @@ static void au_serial_out(struct uart_port *p, int offset, int value) offset = map_8250_out_reg(p, offset) << p->regshift; __raw_writel(value, p->membase + offset); } -#endif static unsigned int tsi_serial_in(struct uart_port *p, int offset) { @@ -503,12 +501,11 @@ static void set_io_from_upio(struct uart_port *p) p->serial_out = mem32_serial_out; break; -#ifdef CONFIG_SERIAL_8250_AU1X00 case UPIO_AU: p->serial_in = au_serial_in; p->serial_out = au_serial_out; break; -#endif + case UPIO_TSI: p->serial_in = tsi_serial_in; p->serial_out = tsi_serial_out; @@ -535,9 +532,7 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) switch (p->iotype) { case UPIO_MEM: case UPIO_MEM32: -#ifdef CONFIG_SERIAL_8250_AU1X00 case UPIO_AU: -#endif case UPIO_DWAPB: p->serial_out(p, offset, value); p->serial_in(p, UART_LCR); /* safe, no side-effects */ @@ -573,7 +568,7 @@ static inline void _serial_dl_write(struct uart_8250_port *up, int value) serial_outp(up, UART_DLM, value >> 8 & 0xff); } -#if defined(CONFIG_SERIAL_8250_AU1X00) +#if defined(CONFIG_MIPS_ALCHEMY) /* Au1x00 haven't got a standard divisor latch */ static int serial_dl_read(struct uart_8250_port *up) { @@ -2596,11 +2591,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (flags & UART_CONFIG_TYPE) autoconfig(up, probeflags); -#ifdef CONFIG_SERIAL_8250_AU1X00 /* if access method is AU, it is a 16550 with a quirk */ if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR; -#endif if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) autoconfig_irq(up); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 8b23165..e437ce8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -258,14 +258,6 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. -config SERIAL_8250_AU1X00 - bool "Au1x00 serial port support" - depends on SERIAL_8250 != n && SOC_AU1X00 - help - If you have an Au1x00 SOC based board and want to use the serial port, - say Y to this option. The driver can handle up to 4 serial ports, - depending on the SOC. If unsure, say N. - config SERIAL_8250_RM9K bool "Support for MIPS RM9xxx integrated serial port" depends on SERIAL_8250 != n && SERIAL_RM9000 diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 6a58cb1..4aa00e6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -45,7 +45,8 @@ config USB_ARCH_HAS_OHCI default y if STB03xxx default y if PPC_MPC52xx # MIPS: - default y if SOC_AU1X00 + default y if MIPS_ALCHEMY + default y if MACH_JZ4740 # SH: default y if CPU_SUBTYPE_SH7720 default y if CPU_SUBTYPE_SH7721 diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index fc57655..02864a2 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1031,7 +1031,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif -#ifdef CONFIG_SOC_AU1X00 +#ifdef CONFIG_MIPS_ALCHEMY #include "ohci-au1xxx.c" #define PLATFORM_DRIVER ohci_hcd_au1xxx_driver #endif @@ -1095,6 +1095,11 @@ MODULE_LICENSE ("GPL"); #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver #endif +#ifdef CONFIG_MACH_JZ4740 +#include "ohci-jz4740.c" +#define PLATFORM_DRIVER ohci_hcd_jz4740_driver +#endif + #if !defined(PCI_DRIVER) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c new file mode 100644 index 0000000..10e1872 --- /dev/null +++ b/drivers/usb/host/ohci-jz4740.c @@ -0,0 +1,276 @@ +/* + * 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 + +struct jz4740_ohci_hcd { + struct ohci_hcd ohci_hcd; + + struct regulator *vbus; + bool vbus_enabled; + struct clk *clk; +}; + +static inline struct jz4740_ohci_hcd *hcd_to_jz4740_hcd(struct usb_hcd *hcd) +{ + return (struct jz4740_ohci_hcd *)(hcd->hcd_priv); +} + +static inline struct usb_hcd *jz4740_hcd_to_hcd(struct jz4740_ohci_hcd *jz4740_ohci) +{ + return container_of((void *)jz4740_ohci, struct usb_hcd, hcd_priv); +} + +static int ohci_jz4740_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + ret = ohci_init(ohci); + if (ret < 0) + return ret; + + ohci->num_ports = 1; + + ret = ohci_run(ohci); + if (ret < 0) { + dev_err(hcd->self.controller, "Can not start %s", + hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } + return 0; +} + +static int ohci_jz4740_set_vbus_power(struct jz4740_ohci_hcd *jz4740_ohci, + bool enabled) +{ + int ret = 0; + + if (!jz4740_ohci->vbus) + return 0; + + if (enabled && !jz4740_ohci->vbus_enabled) { + ret = regulator_enable(jz4740_ohci->vbus); + if (ret) + dev_err(jz4740_hcd_to_hcd(jz4740_ohci)->self.controller, + "Could not power vbus\n"); + } else if (!enabled && jz4740_ohci->vbus_enabled) { + ret = regulator_disable(jz4740_ohci->vbus); + } + + if (ret == 0) + jz4740_ohci->vbus_enabled = enabled; + + return ret; +} + +static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength) +{ + struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); + int ret; + + switch (typeReq) { + case SetHubFeature: + if (wValue == USB_PORT_FEAT_POWER) + ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true); + break; + case ClearHubFeature: + if (wValue == USB_PORT_FEAT_POWER) + ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false); + break; + } + + if (ret) + return ret; + + return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); +} + + +static const struct hc_driver ohci_jz4740_hc_driver = { + .description = hcd_name, + .product_desc = "JZ4740 OHCI", + .hcd_priv_size = sizeof(struct jz4740_ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .start = ohci_jz4740_start, + .stop = ohci_stop, + .shutdown = ohci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_jz4740_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + + +static __devinit int jz4740_ohci_probe(struct platform_device *pdev) +{ + int ret; + struct usb_hcd *hcd; + struct jz4740_ohci_hcd *jz4740_ohci; + struct resource *res; + int irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_err(&pdev->dev, "Failed to get platform resource\n"); + return -ENOENT; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get platform irq\n"); + return irq; + } + + hcd = usb_create_hcd(&ohci_jz4740_hc_driver, &pdev->dev, "jz4740"); + if (!hcd) { + dev_err(&pdev->dev, "Failed to create hcd.\n"); + return -ENOMEM; + } + + jz4740_ohci = hcd_to_jz4740_hcd(hcd); + + res = request_mem_region(res->start, resource_size(res), hcd_name); + if (!res) { + dev_err(&pdev->dev, "Failed to request mem region.\n"); + ret = -EBUSY; + goto err_free; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->regs = ioremap(res->start, resource_size(res)); + + if (!hcd->regs) { + dev_err(&pdev->dev, "Failed to ioremap registers.\n"); + ret = -EBUSY; + goto err_release_mem; + } + + jz4740_ohci->clk = clk_get(&pdev->dev, "uhc"); + if (IS_ERR(jz4740_ohci->clk)) { + ret = PTR_ERR(jz4740_ohci->clk); + dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); + goto err_iounmap; + } + + jz4740_ohci->vbus = regulator_get(&pdev->dev, "vbus"); + if (IS_ERR(jz4740_ohci->vbus)) + jz4740_ohci->vbus = NULL; + + + clk_set_rate(jz4740_ohci->clk, 48000000); + clk_enable(jz4740_ohci->clk); + if (jz4740_ohci->vbus) + ohci_jz4740_set_vbus_power(jz4740_ohci, true); + + platform_set_drvdata(pdev, hcd); + + ohci_hcd_init(hcd_to_ohci(hcd)); + + ret = usb_add_hcd(hcd, irq, 0); + if (ret) { + dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret); + goto err_disable; + } + + return 0; + +err_disable: + platform_set_drvdata(pdev, NULL); + if (jz4740_ohci->vbus) { + regulator_disable(jz4740_ohci->vbus); + regulator_put(jz4740_ohci->vbus); + } + clk_disable(jz4740_ohci->clk); + + clk_put(jz4740_ohci->clk); +err_iounmap: + iounmap(hcd->regs); +err_release_mem: + release_mem_region(res->start, resource_size(res)); +err_free: + usb_put_hcd(hcd); + + return ret; +} + +static __devexit int jz4740_ohci_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); + + usb_remove_hcd(hcd); + + platform_set_drvdata(pdev, NULL); + + if (jz4740_ohci->vbus) { + regulator_disable(jz4740_ohci->vbus); + regulator_put(jz4740_ohci->vbus); + } + + clk_disable(jz4740_ohci->clk); + clk_put(jz4740_ohci->clk); + + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + usb_put_hcd(hcd); + + return 0; +} + +static struct platform_driver ohci_hcd_jz4740_driver = { + .probe = jz4740_ohci_probe, + .remove = __devexit_p(jz4740_ohci_remove), + .driver = { + .name = "jz4740-ohci", + .owner = THIS_MODULE, + }, +}; + +MODULE_ALIAS("platfrom:jz4740-ohci"); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3d94a14..9e711a1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2229,6 +2229,15 @@ config FB_BROADSHEET and could also have been called by other names when coupled with a bridge adapter. +config FB_JZ4740 + tristate "JZ4740 LCD framebuffer support" + depends on FB && MACH_JZ4740 + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + help + Framebuffer support for the JZ4740 SoC. + source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ddc2af2..f56a9ca 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ obj-$(CONFIG_FB_MSM) += msm/ obj-$(CONFIG_FB_NUC900) += nuc900fb.o +obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c new file mode 100644 index 0000000..670ecaa --- /dev/null +++ b/drivers/video/jz4740_fb.c @@ -0,0 +1,847 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC LCD framebuffer driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#define JZ_REG_LCD_CFG 0x00 +#define JZ_REG_LCD_VSYNC 0x04 +#define JZ_REG_LCD_HSYNC 0x08 +#define JZ_REG_LCD_VAT 0x0C +#define JZ_REG_LCD_DAH 0x10 +#define JZ_REG_LCD_DAV 0x14 +#define JZ_REG_LCD_PS 0x18 +#define JZ_REG_LCD_CLS 0x1C +#define JZ_REG_LCD_SPL 0x20 +#define JZ_REG_LCD_REV 0x24 +#define JZ_REG_LCD_CTRL 0x30 +#define JZ_REG_LCD_STATE 0x34 +#define JZ_REG_LCD_IID 0x38 +#define JZ_REG_LCD_DA0 0x40 +#define JZ_REG_LCD_SA0 0x44 +#define JZ_REG_LCD_FID0 0x48 +#define JZ_REG_LCD_CMD0 0x4C +#define JZ_REG_LCD_DA1 0x50 +#define JZ_REG_LCD_SA1 0x54 +#define JZ_REG_LCD_FID1 0x58 +#define JZ_REG_LCD_CMD1 0x5C + +#define JZ_LCD_CFG_SLCD BIT(31) +#define JZ_LCD_CFG_PS_DISABLE BIT(23) +#define JZ_LCD_CFG_CLS_DISABLE BIT(22) +#define JZ_LCD_CFG_SPL_DISABLE BIT(21) +#define JZ_LCD_CFG_REV_DISABLE BIT(20) +#define JZ_LCD_CFG_HSYNCM BIT(19) +#define JZ_LCD_CFG_PCLKM BIT(18) +#define JZ_LCD_CFG_INV BIT(17) +#define JZ_LCD_CFG_SYNC_DIR BIT(16) +#define JZ_LCD_CFG_PS_POLARITY BIT(15) +#define JZ_LCD_CFG_CLS_POLARITY BIT(14) +#define JZ_LCD_CFG_SPL_POLARITY BIT(13) +#define JZ_LCD_CFG_REV_POLARITY BIT(12) +#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11) +#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10) +#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9) +#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8) +#define JZ_LCD_CFG_18_BIT BIT(7) +#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4)) +#define JZ_LCD_CFG_MODE_MASK 0xf + +#define JZ_LCD_CTRL_BURST_4 (0x0 << 28) +#define JZ_LCD_CTRL_BURST_8 (0x1 << 28) +#define JZ_LCD_CTRL_BURST_16 (0x2 << 28) +#define JZ_LCD_CTRL_RGB555 BIT(27) +#define JZ_LCD_CTRL_OFUP BIT(26) +#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24) +#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24) +#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24) +#define JZ_LCD_CTRL_PDD_MASK (0xff << 16) +#define JZ_LCD_CTRL_EOF_IRQ BIT(13) +#define JZ_LCD_CTRL_SOF_IRQ BIT(12) +#define JZ_LCD_CTRL_OFU_IRQ BIT(11) +#define JZ_LCD_CTRL_IFU0_IRQ BIT(10) +#define JZ_LCD_CTRL_IFU1_IRQ BIT(9) +#define JZ_LCD_CTRL_DD_IRQ BIT(8) +#define JZ_LCD_CTRL_QDD_IRQ BIT(7) +#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6) +#define JZ_LCD_CTRL_LSB_FISRT BIT(5) +#define JZ_LCD_CTRL_DISABLE BIT(4) +#define JZ_LCD_CTRL_ENABLE BIT(3) +#define JZ_LCD_CTRL_BPP_1 0x0 +#define JZ_LCD_CTRL_BPP_2 0x1 +#define JZ_LCD_CTRL_BPP_4 0x2 +#define JZ_LCD_CTRL_BPP_8 0x3 +#define JZ_LCD_CTRL_BPP_15_16 0x4 +#define JZ_LCD_CTRL_BPP_18_24 0x5 + +#define JZ_LCD_CMD_SOF_IRQ BIT(15) +#define JZ_LCD_CMD_EOF_IRQ BIT(16) +#define JZ_LCD_CMD_ENABLE_PAL BIT(12) + +#define JZ_LCD_SYNC_MASK 0x3ff + +#define JZ_LCD_STATE_DISABLED BIT(0) + +struct jzfb_framedesc { + uint32_t next; + uint32_t addr; + uint32_t id; + uint32_t cmd; +} __packed; + +struct jzfb { + struct fb_info *fb; + struct platform_device *pdev; + void __iomem *base; + struct resource *mem; + struct jz4740_fb_platform_data *pdata; + + size_t vidmem_size; + void *vidmem; + dma_addr_t vidmem_phys; + struct jzfb_framedesc *framedesc; + dma_addr_t framedesc_phys; + + struct clk *ldclk; + struct clk *lpclk; + + unsigned is_enabled:1; + struct mutex lock; + + uint32_t pseudo_palette[16]; +}; + +static const struct fb_fix_screeninfo jzfb_fix __devinitdata = { + .id = "JZ4740 FB", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = { + JZ_GPIO_BULK_PIN(LCD_PCLK), + JZ_GPIO_BULK_PIN(LCD_HSYNC), + JZ_GPIO_BULK_PIN(LCD_VSYNC), + JZ_GPIO_BULK_PIN(LCD_DE), + JZ_GPIO_BULK_PIN(LCD_PS), + JZ_GPIO_BULK_PIN(LCD_REV), + JZ_GPIO_BULK_PIN(LCD_CLS), + JZ_GPIO_BULK_PIN(LCD_SPL), +}; + +static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = { + JZ_GPIO_BULK_PIN(LCD_DATA0), + JZ_GPIO_BULK_PIN(LCD_DATA1), + JZ_GPIO_BULK_PIN(LCD_DATA2), + JZ_GPIO_BULK_PIN(LCD_DATA3), + JZ_GPIO_BULK_PIN(LCD_DATA4), + JZ_GPIO_BULK_PIN(LCD_DATA5), + JZ_GPIO_BULK_PIN(LCD_DATA6), + JZ_GPIO_BULK_PIN(LCD_DATA7), + JZ_GPIO_BULK_PIN(LCD_DATA8), + JZ_GPIO_BULK_PIN(LCD_DATA9), + JZ_GPIO_BULK_PIN(LCD_DATA10), + JZ_GPIO_BULK_PIN(LCD_DATA11), + JZ_GPIO_BULK_PIN(LCD_DATA12), + JZ_GPIO_BULK_PIN(LCD_DATA13), + JZ_GPIO_BULK_PIN(LCD_DATA14), + JZ_GPIO_BULK_PIN(LCD_DATA15), + JZ_GPIO_BULK_PIN(LCD_DATA16), + JZ_GPIO_BULK_PIN(LCD_DATA17), +}; + +static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb) +{ + unsigned int num; + + switch (jzfb->pdata->lcd_type) { + case JZ_LCD_TYPE_GENERIC_16_BIT: + num = 4; + break; + case JZ_LCD_TYPE_GENERIC_18_BIT: + num = 4; + break; + case JZ_LCD_TYPE_8BIT_SERIAL: + num = 3; + break; + case JZ_LCD_TYPE_SPECIAL_TFT_1: + case JZ_LCD_TYPE_SPECIAL_TFT_2: + case JZ_LCD_TYPE_SPECIAL_TFT_3: + num = 8; + break; + default: + num = 0; + break; + } + return num; +} + +static unsigned int jzfb_num_data_pins(struct jzfb *jzfb) +{ + unsigned int num; + + switch (jzfb->pdata->lcd_type) { + case JZ_LCD_TYPE_GENERIC_16_BIT: + num = 16; + break; + case JZ_LCD_TYPE_GENERIC_18_BIT: + num = 18; + break; + case JZ_LCD_TYPE_8BIT_SERIAL: + num = 8; + break; + case JZ_LCD_TYPE_SPECIAL_TFT_1: + case JZ_LCD_TYPE_SPECIAL_TFT_2: + case JZ_LCD_TYPE_SPECIAL_TFT_3: + if (jzfb->pdata->bpp == 18) + num = 18; + else + num = 16; + break; + default: + num = 0; + break; + } + return num; +} + +/* Based on CNVT_TOHW macro from skeletonfb.c */ +static inline uint32_t jzfb_convert_color_to_hw(unsigned val, + struct fb_bitfield *bf) +{ + return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset; +} + +static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *fb) +{ + uint32_t color; + + if (regno >= 16) + return -EINVAL; + + color = jzfb_convert_color_to_hw(red, &fb->var.red); + color |= jzfb_convert_color_to_hw(green, &fb->var.green); + color |= jzfb_convert_color_to_hw(blue, &fb->var.blue); + color |= jzfb_convert_color_to_hw(transp, &fb->var.transp); + + ((uint32_t *)(fb->pseudo_palette))[regno] = color; + + return 0; +} + +static int jzfb_get_controller_bpp(struct jzfb *jzfb) +{ + switch (jzfb->pdata->bpp) { + case 18: + case 24: + return 32; + case 15: + return 16; + default: + return jzfb->pdata->bpp; + } +} + +static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, + struct fb_var_screeninfo *var) +{ + size_t i; + struct fb_videomode *mode = jzfb->pdata->modes; + + for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) { + if (mode->xres == var->xres && mode->yres == var->yres) + return mode; + } + + return NULL; +} + +static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) +{ + struct jzfb *jzfb = fb->par; + struct fb_videomode *mode; + + if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) && + var->bits_per_pixel != jzfb->pdata->bpp) + return -EINVAL; + + mode = jzfb_get_mode(jzfb, var); + if (mode == NULL) + return -EINVAL; + + fb_videomode_to_var(var, mode); + + switch (jzfb->pdata->bpp) { + case 8: + break; + case 15: + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 6; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + break; + case 16: + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + break; + case 18: + var->red.offset = 16; + var->red.length = 6; + var->green.offset = 8; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 6; + var->bits_per_pixel = 32; + break; + case 32: + case 24: + var->transp.offset = 24; + var->transp.length = 8; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->bits_per_pixel = 32; + break; + default: + break; + } + + return 0; +} + +static int jzfb_set_par(struct fb_info *info) +{ + struct jzfb *jzfb = info->par; + struct jz4740_fb_platform_data *pdata = jzfb->pdata; + struct fb_var_screeninfo *var = &info->var; + struct fb_videomode *mode; + uint16_t hds, vds; + uint16_t hde, vde; + uint16_t ht, vt; + uint32_t ctrl; + uint32_t cfg; + unsigned long rate; + + mode = jzfb_get_mode(jzfb, var); + if (mode == NULL) + return -EINVAL; + + if (mode == info->mode) + return 0; + + info->mode = mode; + + hds = mode->hsync_len + mode->left_margin; + hde = hds + mode->xres; + ht = hde + mode->right_margin; + + vds = mode->vsync_len + mode->upper_margin; + vde = vds + mode->yres; + vt = vde + mode->lower_margin; + + ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16; + + switch (pdata->bpp) { + case 1: + ctrl |= JZ_LCD_CTRL_BPP_1; + break; + case 2: + ctrl |= JZ_LCD_CTRL_BPP_2; + break; + case 4: + ctrl |= JZ_LCD_CTRL_BPP_4; + break; + case 8: + ctrl |= JZ_LCD_CTRL_BPP_8; + break; + case 15: + ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */ + case 16: + ctrl |= JZ_LCD_CTRL_BPP_15_16; + break; + case 18: + case 24: + case 32: + ctrl |= JZ_LCD_CTRL_BPP_18_24; + break; + default: + break; + } + + cfg = pdata->lcd_type & 0xf; + + if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT)) + cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; + + if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT)) + cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; + + if (pdata->pixclk_falling_edge) + cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; + + if (pdata->date_enable_active_low) + cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; + + if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT) + cfg |= JZ_LCD_CFG_18_BIT; + + if (mode->pixclock) { + rate = PICOS2KHZ(mode->pixclock) * 1000; + mode->refresh = rate / vt / ht; + } else { + if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL) + rate = mode->refresh * (vt + 2 * mode->xres) * ht; + else + rate = mode->refresh * vt * ht; + + mode->pixclock = KHZ2PICOS(rate / 1000); + } + + mutex_lock(&jzfb->lock); + if (!jzfb->is_enabled) + clk_enable(jzfb->ldclk); + else + ctrl |= JZ_LCD_CTRL_ENABLE; + + switch (pdata->lcd_type) { + case JZ_LCD_TYPE_SPECIAL_TFT_1: + case JZ_LCD_TYPE_SPECIAL_TFT_2: + case JZ_LCD_TYPE_SPECIAL_TFT_3: + writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL); + writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS); + writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS); + writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV); + break; + default: + cfg |= JZ_LCD_CFG_PS_DISABLE; + cfg |= JZ_LCD_CFG_CLS_DISABLE; + cfg |= JZ_LCD_CFG_SPL_DISABLE; + cfg |= JZ_LCD_CFG_REV_DISABLE; + break; + } + + writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC); + writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC); + + writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT); + + writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH); + writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV); + + writel(cfg, jzfb->base + JZ_REG_LCD_CFG); + + writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); + + if (!jzfb->is_enabled) + clk_disable(jzfb->ldclk); + + mutex_unlock(&jzfb->lock); + + clk_set_rate(jzfb->lpclk, rate); + clk_set_rate(jzfb->ldclk, rate * 3); + + return 0; +} + +static void jzfb_enable(struct jzfb *jzfb) +{ + uint32_t ctrl; + + clk_enable(jzfb->ldclk); + + jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + writel(0, jzfb->base + JZ_REG_LCD_STATE); + + writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); + + ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); + ctrl |= JZ_LCD_CTRL_ENABLE; + ctrl &= ~JZ_LCD_CTRL_DISABLE; + writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); +} + +static void jzfb_disable(struct jzfb *jzfb) +{ + uint32_t ctrl; + + ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); + ctrl |= JZ_LCD_CTRL_DISABLE; + writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); + do { + ctrl = readl(jzfb->base + JZ_REG_LCD_STATE); + } while (!(ctrl & JZ_LCD_STATE_DISABLED)); + + jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + clk_disable(jzfb->ldclk); +} + +static int jzfb_blank(int blank_mode, struct fb_info *info) +{ + struct jzfb *jzfb = info->par; + + switch (blank_mode) { + case FB_BLANK_UNBLANK: + mutex_lock(&jzfb->lock); + if (jzfb->is_enabled) { + mutex_unlock(&jzfb->lock); + return 0; + } + + jzfb_enable(jzfb); + jzfb->is_enabled = 1; + + mutex_unlock(&jzfb->lock); + break; + default: + mutex_lock(&jzfb->lock); + if (!jzfb->is_enabled) { + mutex_unlock(&jzfb->lock); + return 0; + } + + jzfb_disable(jzfb); + jzfb->is_enabled = 0; + + mutex_unlock(&jzfb->lock); + break; + } + + return 0; +} + +static int jzfb_alloc_devmem(struct jzfb *jzfb) +{ + int max_videosize = 0; + struct fb_videomode *mode = jzfb->pdata->modes; + void *page; + int i; + + for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) { + if (max_videosize < mode->xres * mode->yres) + max_videosize = mode->xres * mode->yres; + } + + max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3; + + jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev, + sizeof(*jzfb->framedesc), + &jzfb->framedesc_phys, GFP_KERNEL); + + if (!jzfb->framedesc) + return -ENOMEM; + + jzfb->vidmem_size = PAGE_ALIGN(max_videosize); + jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev, + jzfb->vidmem_size, + &jzfb->vidmem_phys, GFP_KERNEL); + + if (!jzfb->vidmem) + goto err_free_framedesc; + + for (page = jzfb->vidmem; + page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size); + page += PAGE_SIZE) { + SetPageReserved(virt_to_page(page)); + } + + jzfb->framedesc->next = jzfb->framedesc_phys; + jzfb->framedesc->addr = jzfb->vidmem_phys; + jzfb->framedesc->id = 0xdeafbead; + jzfb->framedesc->cmd = 0; + jzfb->framedesc->cmd |= max_videosize / 4; + + return 0; + +err_free_framedesc: + dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), + jzfb->framedesc, jzfb->framedesc_phys); + return -ENOMEM; +} + +static void jzfb_free_devmem(struct jzfb *jzfb) +{ + dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size, + jzfb->vidmem, jzfb->vidmem_phys); + dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), + jzfb->framedesc, jzfb->framedesc_phys); +} + +static struct fb_ops jzfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = jzfb_check_var, + .fb_set_par = jzfb_set_par, + .fb_blank = jzfb_blank, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_setcolreg = jzfb_setcolreg, +}; + +static int __devinit jzfb_probe(struct platform_device *pdev) +{ + int ret; + struct jzfb *jzfb; + struct fb_info *fb; + struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data; + struct resource *mem; + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENXIO; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&pdev->dev, "Failed to get register memory resource\n"); + return -ENXIO; + } + + mem = request_mem_region(mem->start, resource_size(mem), pdev->name); + if (!mem) { + dev_err(&pdev->dev, "Failed to request register memory region\n"); + return -EBUSY; + } + + fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); + if (!fb) { + dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); + ret = -ENOMEM; + goto err_release_mem_region; + } + + fb->fbops = &jzfb_ops; + fb->flags = FBINFO_DEFAULT; + + jzfb = fb->par; + jzfb->pdev = pdev; + jzfb->pdata = pdata; + jzfb->mem = mem; + + jzfb->ldclk = clk_get(&pdev->dev, "lcd"); + if (IS_ERR(jzfb->ldclk)) { + ret = PTR_ERR(jzfb->ldclk); + dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret); + goto err_framebuffer_release; + } + + jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk"); + if (IS_ERR(jzfb->lpclk)) { + ret = PTR_ERR(jzfb->lpclk); + dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret); + goto err_put_ldclk; + } + + jzfb->base = ioremap(mem->start, resource_size(mem)); + if (!jzfb->base) { + dev_err(&pdev->dev, "Failed to ioremap register memory region\n"); + ret = -EBUSY; + goto err_put_lpclk; + } + + platform_set_drvdata(pdev, jzfb); + + mutex_init(&jzfb->lock); + + fb_videomode_to_modelist(pdata->modes, pdata->num_modes, + &fb->modelist); + fb_videomode_to_var(&fb->var, pdata->modes); + fb->var.bits_per_pixel = pdata->bpp; + jzfb_check_var(&fb->var, fb); + + ret = jzfb_alloc_devmem(jzfb); + if (ret) { + dev_err(&pdev->dev, "Failed to allocate video memory\n"); + goto err_iounmap; + } + + fb->fix = jzfb_fix; + fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8; + fb->fix.mmio_start = mem->start; + fb->fix.mmio_len = resource_size(mem); + fb->fix.smem_start = jzfb->vidmem_phys; + fb->fix.smem_len = fb->fix.line_length * fb->var.yres; + fb->screen_base = jzfb->vidmem; + fb->pseudo_palette = jzfb->pseudo_palette; + + fb_alloc_cmap(&fb->cmap, 256, 0); + + clk_enable(jzfb->ldclk); + jzfb->is_enabled = 1; + + writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); + + fb->mode = NULL; + jzfb_set_par(fb); + + jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + ret = register_framebuffer(fb); + if (ret) { + dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret); + goto err_free_devmem; + } + + jzfb->fb = fb; + + return 0; + +err_free_devmem: + jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + fb_dealloc_cmap(&fb->cmap); + jzfb_free_devmem(jzfb); +err_iounmap: + iounmap(jzfb->base); +err_put_lpclk: + clk_put(jzfb->lpclk); +err_put_ldclk: + clk_put(jzfb->ldclk); +err_framebuffer_release: + framebuffer_release(fb); +err_release_mem_region: + release_mem_region(mem->start, resource_size(mem)); + return ret; +} + +static int __devexit jzfb_remove(struct platform_device *pdev) +{ + struct jzfb *jzfb = platform_get_drvdata(pdev); + + jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb); + + jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + iounmap(jzfb->base); + release_mem_region(jzfb->mem->start, resource_size(jzfb->mem)); + + fb_dealloc_cmap(&jzfb->fb->cmap); + jzfb_free_devmem(jzfb); + + platform_set_drvdata(pdev, NULL); + + clk_put(jzfb->lpclk); + clk_put(jzfb->ldclk); + + framebuffer_release(jzfb->fb); + + return 0; +} + +#ifdef CONFIG_PM + +static int jzfb_suspend(struct device *dev) +{ + struct jzfb *jzfb = dev_get_drvdata(dev); + + acquire_console_sem(); + fb_set_suspend(jzfb->fb, 1); + release_console_sem(); + + mutex_lock(&jzfb->lock); + if (jzfb->is_enabled) + jzfb_disable(jzfb); + mutex_unlock(&jzfb->lock); + + return 0; +} + +static int jzfb_resume(struct device *dev) +{ + struct jzfb *jzfb = dev_get_drvdata(dev); + clk_enable(jzfb->ldclk); + + mutex_lock(&jzfb->lock); + if (jzfb->is_enabled) + jzfb_enable(jzfb); + mutex_unlock(&jzfb->lock); + + acquire_console_sem(); + fb_set_suspend(jzfb->fb, 0); + release_console_sem(); + + return 0; +} + +static const struct dev_pm_ops jzfb_pm_ops = { + .suspend = jzfb_suspend, + .resume = jzfb_resume, + .poweroff = jzfb_suspend, + .restore = jzfb_resume, +}; + +#define JZFB_PM_OPS (&jzfb_pm_ops) + +#else +#define JZFB_PM_OPS NULL +#endif + +static struct platform_driver jzfb_driver = { + .probe = jzfb_probe, + .remove = __devexit_p(jzfb_remove), + .driver = { + .name = "jz4740-fb", + .pm = JZFB_PM_OPS, + }, +}; + +static int __init jzfb_init(void) +{ + return platform_driver_register(&jzfb_driver); +} +module_init(jzfb_init); + +static void __exit jzfb_exit(void) +{ + platform_driver_unregister(&jzfb_driver); +} +module_exit(jzfb_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver"); +MODULE_ALIAS("platform:jz4740-fb"); diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 9805483..3ee5e63 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1571,8 +1571,8 @@ out_err_iobase: if (default_par->mtrr_handle >= 0) mtrr_del(default_par->mtrr_handle, info->fix.smem_start, info->fix.smem_len); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); + release_region(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); out_err_screenbase: if (info->screen_base) iounmap(info->screen_base); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index afcfacc..b04b184 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -875,6 +875,24 @@ config TXX9_WDT help Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. +config OCTEON_WDT + tristate "Cavium OCTEON SOC family Watchdog Timer" + depends on CPU_CAVIUM_OCTEON + default y + select EXPORT_UASM if OCTEON_WDT = m + help + Hardware driver for OCTEON's on chip watchdog timer. + Enables the watchdog for all cores running Linux. It + installs a NMI handler and pokes the watchdog based on an + interrupt. On first expiration of the watchdog, the + interrupt handler pokes it. The second expiration causes an + NMI that prints a message. The third expiration causes a + global soft reset. + + When userspace has /dev/watchdog open, no poking is done + from the first interrupt, it is then only poked when the + device is written. + # PARISC Architecture # POWERPC Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 72f3e20..e30289a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -114,6 +114,8 @@ obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o obj-$(CONFIG_AR7_WDT) += ar7_wdt.o obj-$(CONFIG_TXX9_WDT) += txx9wdt.o +obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o +octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o # PARISC Architecture diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c new file mode 100644 index 0000000..2a41017 --- /dev/null +++ b/drivers/watchdog/octeon-wdt-main.c @@ -0,0 +1,745 @@ +/* + * Octeon Watchdog driver + * + * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks + * + * Some parts derived from wdt.c + * + * (c) Copyright 1996-1997 Alan Cox , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * 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. + * + * + * The OCTEON watchdog has a maximum timeout of 2^32 * io_clock. + * For most systems this is less than 10 seconds, so to allow for + * software to request longer watchdog heartbeats, we maintain software + * counters to count multiples of the base rate. If the system locks + * up in such a manner that we can not run the software counters, the + * only result is a watchdog reset sooner than was requested. But + * that is OK, because in this case userspace would likely not be able + * to do anything anyhow. + * + * The hardware watchdog interval we call the period. The OCTEON + * watchdog goes through several stages, after the first period an + * irq is asserted, then if it is not reset, after the next period NMI + * is asserted, then after an additional period a chip wide soft reset. + * So for the software counters, we reset watchdog after each period + * and decrement the counter. But for the last two periods we need to + * let the watchdog progress to the NMI stage so we disable the irq + * and let it proceed. Once in the NMI, we print the register state + * to the serial port and then wait for the reset. + * + * A watchdog is maintained for each CPU in the system, that way if + * one CPU suffers a lockup, we also get a register dump and reset. + * The userspace ping resets the watchdog on all CPUs. + * + * Before userspace opens the watchdog device, we still run the + * watchdogs to catch any lockups that may be kernel related. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/* The count needed to achieve timeout_sec. */ +static unsigned int timeout_cnt; + +/* The maximum period supported. */ +static unsigned int max_timeout_sec; + +/* The current period. */ +static unsigned int timeout_sec; + +/* Set to non-zero when userspace countdown mode active */ +static int do_coundown; +static unsigned int countdown_reset; +static unsigned int per_cpu_countdown[NR_CPUS]; + +static cpumask_t irq_enabled_cpus; + +#define WD_TIMO 60 /* Default heartbeat = 60 seconds */ + +static int heartbeat = WD_TIMO; +module_param(heartbeat, int, S_IRUGO); +MODULE_PARM_DESC(heartbeat, + "Watchdog heartbeat in seconds. (0 < heartbeat, default=" + __MODULE_STRING(WD_TIMO) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, S_IRUGO); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static unsigned long octeon_wdt_is_open; +static char expect_close; + +static u32 __initdata nmi_stage1_insns[64]; +/* We need one branch and therefore one relocation per target label. */ +static struct uasm_label __initdata labels[5]; +static struct uasm_reloc __initdata relocs[5]; + +enum lable_id { + label_enter_bootloader = 1 +}; + +/* Some CP0 registers */ +#define K0 26 +#define C0_CVMMEMCTL 11, 7 +#define C0_STATUS 12, 0 +#define C0_EBASE 15, 1 +#define C0_DESAVE 31, 0 + +void octeon_wdt_nmi_stage2(void); + +static void __init octeon_wdt_build_stage1(void) +{ + int i; + int len; + u32 *p = nmi_stage1_insns; +#ifdef CONFIG_HOTPLUG_CPU + struct uasm_label *l = labels; + struct uasm_reloc *r = relocs; +#endif + + /* + * For the next few instructions running the debugger may + * cause corruption of k0 in the saved registers. Since we're + * about to crash, nobody probably cares. + * + * Save K0 into the debug scratch register + */ + uasm_i_dmtc0(&p, K0, C0_DESAVE); + + uasm_i_mfc0(&p, K0, C0_STATUS); +#ifdef CONFIG_HOTPLUG_CPU + uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader); +#endif + /* Force 64-bit addressing enabled */ + uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX); + uasm_i_mtc0(&p, K0, C0_STATUS); + +#ifdef CONFIG_HOTPLUG_CPU + uasm_i_mfc0(&p, K0, C0_EBASE); + /* Coreid number in K0 */ + uasm_i_andi(&p, K0, K0, 0xf); + /* 8 * coreid in bits 16-31 */ + uasm_i_dsll_safe(&p, K0, K0, 3 + 16); + uasm_i_ori(&p, K0, K0, 0x8001); + uasm_i_dsll_safe(&p, K0, K0, 16); + uasm_i_ori(&p, K0, K0, 0x0700); + uasm_i_drotr_safe(&p, K0, K0, 32); + /* + * Should result in: 0x8001,0700,0000,8*coreid which is + * CVMX_CIU_WDOGX(coreid) - 0x0500 + * + * Now ld K0, CVMX_CIU_WDOGX(coreid) + */ + uasm_i_ld(&p, K0, 0x500, K0); + /* + * If bit one set handle the NMI as a watchdog event. + * otherwise transfer control to bootloader. + */ + uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader); + uasm_i_nop(&p); +#endif + + /* Clear Dcache so cvmseg works right. */ + uasm_i_cache(&p, 1, 0, 0); + + /* Use K0 to do a read/modify/write of CVMMEMCTL */ + uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL); + /* Clear out the size of CVMSEG */ + uasm_i_dins(&p, K0, 0, 0, 6); + /* Set CVMSEG to its largest value */ + uasm_i_ori(&p, K0, K0, 0x1c0 | 54); + /* Store the CVMMEMCTL value */ + uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL); + + /* Load the address of the second stage handler */ + UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2); + uasm_i_jr(&p, K0); + uasm_i_dmfc0(&p, K0, C0_DESAVE); + +#ifdef CONFIG_HOTPLUG_CPU + uasm_build_label(&l, p, label_enter_bootloader); + /* Jump to the bootloader and restore K0 */ + UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr); + uasm_i_jr(&p, K0); + uasm_i_dmfc0(&p, K0, C0_DESAVE); +#endif + uasm_resolve_relocs(relocs, labels); + + len = (int)(p - nmi_stage1_insns); + pr_debug("Synthesized NMI stage 1 handler (%d instructions).\n", len); + + pr_debug("\t.set push\n"); + pr_debug("\t.set noreorder\n"); + for (i = 0; i < len; i++) + pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]); + pr_debug("\t.set pop\n"); + + if (len > 32) + panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len); +} + +static int cpu2core(int cpu) +{ +#ifdef CONFIG_SMP + return cpu_logical_map(cpu); +#else + return cvmx_get_core_num(); +#endif +} + +static int core2cpu(int coreid) +{ +#ifdef CONFIG_SMP + return cpu_number_map(coreid); +#else + return 0; +#endif +} + +/** + * Poke the watchdog when an interrupt is received + * + * @cpl: + * @dev_id: + * + * Returns + */ +static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id) +{ + unsigned int core = cvmx_get_core_num(); + int cpu = core2cpu(core); + + if (do_coundown) { + if (per_cpu_countdown[cpu] > 0) { + /* We're alive, poke the watchdog */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + per_cpu_countdown[cpu]--; + } else { + /* Bad news, you are about to reboot. */ + disable_irq_nosync(cpl); + cpumask_clear_cpu(cpu, &irq_enabled_cpus); + } + } else { + /* Not open, just ping away... */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + } + return IRQ_HANDLED; +} + +/* From setup.c */ +extern int prom_putchar(char c); + +/** + * Write a string to the uart + * + * @str: String to write + */ +static void octeon_wdt_write_string(const char *str) +{ + /* Just loop writing one byte at a time */ + while (*str) + prom_putchar(*str++); +} + +/** + * Write a hex number out of the uart + * + * @value: Number to display + * @digits: Number of digits to print (1 to 16) + */ +static void octeon_wdt_write_hex(u64 value, int digits) +{ + int d; + int v; + for (d = 0; d < digits; d++) { + v = (value >> ((digits - d - 1) * 4)) & 0xf; + if (v >= 10) + prom_putchar('a' + v - 10); + else + prom_putchar('0' + v); + } +} + +const char *reg_name[] = { + "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" +}; + +/** + * NMI stage 3 handler. NMIs are handled in the following manner: + * 1) The first NMI handler enables CVMSEG and transfers from + * the bootbus region into normal memory. It is careful to not + * destroy any registers. + * 2) The second stage handler uses CVMSEG to save the registers + * and create a stack for C code. It then calls the third level + * handler with one argument, a pointer to the register values. + * 3) The third, and final, level handler is the following C + * function that prints out some useful infomration. + * + * @reg: Pointer to register state before the NMI + */ +void octeon_wdt_nmi_stage3(u64 reg[32]) +{ + u64 i; + + unsigned int coreid = cvmx_get_core_num(); + /* + * Save status and cause early to get them before any changes + * might happen. + */ + u64 cp0_cause = read_c0_cause(); + u64 cp0_status = read_c0_status(); + u64 cp0_error_epc = read_c0_errorepc(); + u64 cp0_epc = read_c0_epc(); + + /* Delay so output from all cores output is not jumbled together. */ + __delay(100000000ull * coreid); + + octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x"); + octeon_wdt_write_hex(coreid, 1); + octeon_wdt_write_string(" ***\r\n"); + for (i = 0; i < 32; i++) { + octeon_wdt_write_string("\t"); + octeon_wdt_write_string(reg_name[i]); + octeon_wdt_write_string("\t0x"); + octeon_wdt_write_hex(reg[i], 16); + if (i & 1) + octeon_wdt_write_string("\r\n"); + } + octeon_wdt_write_string("\terr_epc\t0x"); + octeon_wdt_write_hex(cp0_error_epc, 16); + + octeon_wdt_write_string("\tepc\t0x"); + octeon_wdt_write_hex(cp0_epc, 16); + octeon_wdt_write_string("\r\n"); + + octeon_wdt_write_string("\tstatus\t0x"); + octeon_wdt_write_hex(cp0_status, 16); + octeon_wdt_write_string("\tcause\t0x"); + octeon_wdt_write_hex(cp0_cause, 16); + octeon_wdt_write_string("\r\n"); + + octeon_wdt_write_string("\tsum0\t0x"); + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16); + octeon_wdt_write_string("\ten0\t0x"); + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16); + octeon_wdt_write_string("\r\n"); + + octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); +} + +static void octeon_wdt_disable_interrupt(int cpu) +{ + unsigned int core; + unsigned int irq; + union cvmx_ciu_wdogx ciu_wdog; + + core = cpu2core(cpu); + + irq = OCTEON_IRQ_WDOG0 + core; + + /* Poke the watchdog to clear out its state */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + + /* Disable the hardware. */ + ciu_wdog.u64 = 0; + cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); + + free_irq(irq, octeon_wdt_poke_irq); +} + +static void octeon_wdt_setup_interrupt(int cpu) +{ + unsigned int core; + unsigned int irq; + union cvmx_ciu_wdogx ciu_wdog; + + core = cpu2core(cpu); + + /* Disable it before doing anything with the interrupts. */ + ciu_wdog.u64 = 0; + cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); + + per_cpu_countdown[cpu] = countdown_reset; + + irq = OCTEON_IRQ_WDOG0 + core; + + if (request_irq(irq, octeon_wdt_poke_irq, + IRQF_DISABLED, "octeon_wdt", octeon_wdt_poke_irq)) + panic("octeon_wdt: Couldn't obtain irq %d", irq); + + cpumask_set_cpu(cpu, &irq_enabled_cpus); + + /* Poke the watchdog to clear out its state */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + + /* Finally enable the watchdog now that all handlers are installed */ + ciu_wdog.u64 = 0; + ciu_wdog.s.len = timeout_cnt; + ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */ + cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); +} + +static int octeon_wdt_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_DOWN_PREPARE: + octeon_wdt_disable_interrupt(cpu); + break; + case CPU_ONLINE: + case CPU_DOWN_FAILED: + octeon_wdt_setup_interrupt(cpu); + break; + default: + break; + } + return NOTIFY_OK; +} + +static void octeon_wdt_ping(void) +{ + int cpu; + int coreid; + + for_each_online_cpu(cpu) { + coreid = cpu2core(cpu); + cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); + per_cpu_countdown[cpu] = countdown_reset; + if ((countdown_reset || !do_coundown) && + !cpumask_test_cpu(cpu, &irq_enabled_cpus)) { + /* We have to enable the irq */ + int irq = OCTEON_IRQ_WDOG0 + coreid; + enable_irq(irq); + cpumask_set_cpu(cpu, &irq_enabled_cpus); + } + } +} + +static void octeon_wdt_calc_parameters(int t) +{ + unsigned int periods; + + timeout_sec = max_timeout_sec; + + + /* + * Find the largest interrupt period, that can evenly divide + * the requested heartbeat time. + */ + while ((t % timeout_sec) != 0) + timeout_sec--; + + periods = t / timeout_sec; + + /* + * The last two periods are after the irq is disabled, and + * then to the nmi, so we subtract them off. + */ + + countdown_reset = periods > 2 ? periods - 2 : 0; + heartbeat = t; + timeout_cnt = ((octeon_get_clock_rate() >> 8) * timeout_sec) >> 8; +} + +static int octeon_wdt_set_heartbeat(int t) +{ + int cpu; + int coreid; + union cvmx_ciu_wdogx ciu_wdog; + + if (t <= 0) + return -1; + + octeon_wdt_calc_parameters(t); + + for_each_online_cpu(cpu) { + coreid = cpu2core(cpu); + cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); + ciu_wdog.u64 = 0; + ciu_wdog.s.len = timeout_cnt; + ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */ + cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64); + cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); + } + octeon_wdt_ping(); /* Get the irqs back on. */ + return 0; +} + +/** + * octeon_wdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t octeon_wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + expect_close = 1; + } + } + octeon_wdt_ping(); + } + return count; +} + +/** + * octeon_wdt_ioctl: + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all + * watchdogs according to their available features. We only + * actually usefully support querying capabilities and setting + * the timeout. + */ + +static long octeon_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_heartbeat; + + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT| + WDIOF_MAGICCLOSE| + WDIOF_KEEPALIVEPING, + .firmware_version = 1, + .identity = "OCTEON", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_KEEPALIVE: + octeon_wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_heartbeat, p)) + return -EFAULT; + if (octeon_wdt_set_heartbeat(new_heartbeat)) + return -EINVAL; + /* Fall through. */ + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, p); + default: + return -ENOTTY; + } +} + +/** + * octeon_wdt_open: + * @inode: inode of device + * @file: file handle to device + * + * The watchdog device has been opened. The watchdog device is single + * open and on opening we do a ping to reset the counters. + */ + +static int octeon_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &octeon_wdt_is_open)) + return -EBUSY; + /* + * Activate + */ + octeon_wdt_ping(); + do_coundown = 1; + return nonseekable_open(inode, file); +} + +/** + * octeon_wdt_release: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int octeon_wdt_release(struct inode *inode, struct file *file) +{ + if (expect_close) { + do_coundown = 0; + octeon_wdt_ping(); + } else { + pr_crit("octeon_wdt: WDT device closed unexpectedly. WDT will not stop!\n"); + } + clear_bit(0, &octeon_wdt_is_open); + expect_close = 0; + return 0; +} + +static const struct file_operations octeon_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = octeon_wdt_write, + .unlocked_ioctl = octeon_wdt_ioctl, + .open = octeon_wdt_open, + .release = octeon_wdt_release, +}; + +static struct miscdevice octeon_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &octeon_wdt_fops, +}; + +static struct notifier_block octeon_wdt_cpu_notifier = { + .notifier_call = octeon_wdt_cpu_callback, +}; + + +/** + * Module/ driver initialization. + * + * Returns Zero on success + */ +static int __init octeon_wdt_init(void) +{ + int i; + int ret; + int cpu; + u64 *ptr; + + /* + * Watchdog time expiration length = The 16 bits of LEN + * represent the most significant bits of a 24 bit decrementer + * that decrements every 256 cycles. + * + * Try for a timeout of 5 sec, if that fails a smaller number + * of even seconds, + */ + max_timeout_sec = 6; + do { + max_timeout_sec--; + timeout_cnt = ((octeon_get_clock_rate() >> 8) * max_timeout_sec) >> 8; + } while (timeout_cnt > 65535); + + BUG_ON(timeout_cnt == 0); + + octeon_wdt_calc_parameters(heartbeat); + + pr_info("octeon_wdt: Initial granularity %d Sec.\n", timeout_sec); + + ret = misc_register(&octeon_wdt_miscdev); + if (ret) { + pr_err("octeon_wdt: cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + goto out; + } + + /* Build the NMI handler ... */ + octeon_wdt_build_stage1(); + + /* ... and install it. */ + ptr = (u64 *) nmi_stage1_insns; + for (i = 0; i < 16; i++) { + cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8); + cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]); + } + cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000); + + cpumask_clear(&irq_enabled_cpus); + + for_each_online_cpu(cpu) + octeon_wdt_setup_interrupt(cpu); + + register_hotcpu_notifier(&octeon_wdt_cpu_notifier); +out: + return ret; +} + +/** + * Module / driver shutdown + */ +static void __exit octeon_wdt_cleanup(void) +{ + int cpu; + + misc_deregister(&octeon_wdt_miscdev); + + unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); + + for_each_online_cpu(cpu) { + int core = cpu2core(cpu); + /* Disable the watchdog */ + cvmx_write_csr(CVMX_CIU_WDOGX(core), 0); + /* Free the interrupt handler */ + free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq); + } + /* + * Disable the boot-bus memory, the code it points to is soon + * to go missing. + */ + cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Cavium Networks "); +MODULE_DESCRIPTION("Cavium Networks Octeon Watchdog driver."); +module_init(octeon_wdt_init); +module_exit(octeon_wdt_cleanup); diff --git a/drivers/watchdog/octeon-wdt-nmi.S b/drivers/watchdog/octeon-wdt-nmi.S new file mode 100644 index 0000000..8a900a5 --- /dev/null +++ b/drivers/watchdog/octeon-wdt-nmi.S @@ -0,0 +1,64 @@ +/* + * 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) 2007 Cavium Networks + */ +#include +#include + +#define SAVE_REG(r) sd $r, -32768+6912-(32-r)*8($0) + + NESTED(octeon_wdt_nmi_stage2, 0, sp) + .set push + .set noreorder + .set noat + /* Save all registers to the top CVMSEG. This shouldn't + * corrupt any state used by the kernel. Also all registers + * should have the value right before the NMI. */ + SAVE_REG(0) + SAVE_REG(1) + SAVE_REG(2) + SAVE_REG(3) + SAVE_REG(4) + SAVE_REG(5) + SAVE_REG(6) + SAVE_REG(7) + SAVE_REG(8) + SAVE_REG(9) + SAVE_REG(10) + SAVE_REG(11) + SAVE_REG(12) + SAVE_REG(13) + SAVE_REG(14) + SAVE_REG(15) + SAVE_REG(16) + SAVE_REG(17) + SAVE_REG(18) + SAVE_REG(19) + SAVE_REG(20) + SAVE_REG(21) + SAVE_REG(22) + SAVE_REG(23) + SAVE_REG(24) + SAVE_REG(25) + SAVE_REG(26) + SAVE_REG(27) + SAVE_REG(28) + SAVE_REG(29) + SAVE_REG(30) + SAVE_REG(31) + /* Set the stack to begin right below the registers */ + li sp, -32768+6912-32*8 + /* Load the address of the third stage handler */ + dla a0, octeon_wdt_nmi_stage3 + /* Call the third stage handler */ + jal a0 + /* a0 is the address of the saved registers */ + move a0, sp + /* Loop forvever if we get here. */ +1: b 1b + nop + .set pop + END(octeon_wdt_nmi_stage2) diff --git a/include/linux/power/jz4740-battery.h b/include/linux/power/jz4740-battery.h new file mode 100644 index 0000000..19c9610 --- /dev/null +++ b/include/linux/power/jz4740-battery.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009, Jiejing Zhang + * + * 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_BATTERY_H +#define __JZ4740_BATTERY_H + +struct jz_battery_platform_data { + struct power_supply_info info; + int gpio_charge; /* GPIO port of Charger state */ + int gpio_charge_active_low; +}; + +#endif diff --git a/kernel/printk.c b/kernel/printk.c index 444b770..4ab0164 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include @@ -985,6 +987,32 @@ void resume_console(void) } /** + * console_cpu_notify - print deferred console messages after CPU hotplug + * @self: notifier struct + * @action: CPU hotplug event + * @hcpu: unused + * + * If printk() is called from a CPU that is not online yet, the messages + * will be spooled but will not show up on the console. This function is + * called when a new CPU comes online (or fails to come up), and ensures + * that any such output gets printed. + */ +static int __cpuinit console_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + switch (action) { + case CPU_ONLINE: + case CPU_DEAD: + case CPU_DYING: + case CPU_DOWN_FAILED: + case CPU_UP_CANCELED: + acquire_console_sem(); + release_console_sem(); + } + return NOTIFY_OK; +} + +/** * acquire_console_sem - lock the console system for exclusive use. * * Acquires a semaphore which guarantees that the caller has @@ -1371,7 +1399,7 @@ int unregister_console(struct console *console) } EXPORT_SYMBOL(unregister_console); -static int __init disable_boot_consoles(void) +static int __init printk_late_init(void) { struct console *con; @@ -1382,9 +1410,10 @@ static int __init disable_boot_consoles(void) unregister_console(con); } } + hotcpu_notifier(console_cpu_notify, 0); return 0; } -late_initcall(disable_boot_consoles); +late_initcall(printk_late_init); #if defined CONFIG_PRINTK diff --git a/samples/kprobes/kprobe_example.c b/samples/kprobes/kprobe_example.c index a681998..ebf5e0c 100644 --- a/samples/kprobes/kprobe_example.c +++ b/samples/kprobes/kprobe_example.c @@ -32,6 +32,11 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) " msr = 0x%lx\n", p->addr, regs->nip, regs->msr); #endif +#ifdef CONFIG_MIPS + printk(KERN_INFO "pre_handler: p->addr = 0x%p, epc = 0x%lx," + " status = 0x%lx\n", + p->addr, regs->cp0_epc, regs->cp0_status); +#endif /* A dump_stack() here will give a stack backtrace */ return 0; @@ -49,6 +54,10 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs, printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\n", p->addr, regs->msr); #endif +#ifdef CONFIG_MIPS + printk(KERN_INFO "post_handler: p->addr = 0x%p, status = 0x%lx\n", + p->addr, regs->cp0_status); +#endif } /*