Commit 9219a3b9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (37 commits)
  MIPS: Only write c0_framemask on CPUs which have this register.
  MIPS: Alchemy: new userspace suspend interface for development boards.
  MIPS: Alchemy: dbdma suspend/resume support.
  MIPS: Alchemy: Fix up PM code on Au1550/Au1200
  MIPS: Alchemy: move calc_clock function.
  MIPS: Alchemy: RTC counter clocksource / clockevent support.
  MIPS: make cp0 counter clocksource/event usable as fallback.
  MIPS: Alchemy: remove cpu_table.
  MIPS: Alchemy: remove get/set_au1x00_lcd_clock().
  MIPS: Print irq handler description
  MIPS: Alchemy: pb1200: update CPLD cascade irq handler.
  MIPS: Alchemy: update core interrupt code.
  MIPS: Alchemy: move commandline mangling out of common code
  MIPS: Alchemy: devboards: consolidate files
  MIPS: Alchemy: Move development board code to common subdirectory
  MIPS: Add Cavium OCTEON to arch/mips/Kconfig
  MIPS: Add defconfig for Cavium OCTEON.
  MIPS: Adjust the dma-common.c platform hooks.
  MIPS: Add Cavium OCTEON slot into proper tlb category.
  MIPS:  Compute branch returns for Cavium OCTEON specific branch instructions.
  ...
parents 23ead729 cde15b59
......@@ -595,6 +595,44 @@ config WR_PPMC
This enables support for the Wind River MIPS32 4KC PPMC evaluation
board, which is based on GT64120 bridge chip.
config CAVIUM_OCTEON_SIMULATOR
bool "Support for the Cavium Networks Octeon Simulator"
select CEVT_R4K
select 64BIT_PHYS_ADDR
select DMA_COHERENT
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select CPU_CAVIUM_OCTEON
help
The Octeon simulator is software performance model of the Cavium
Octeon Processor. It supports simulating Octeon processors on x86
hardware.
config CAVIUM_OCTEON_REFERENCE_BOARD
bool "Support for the Cavium Networks Octeon reference board"
select CEVT_R4K
select 64BIT_PHYS_ADDR
select DMA_COHERENT
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select SYS_HAS_EARLY_PRINTK
select CPU_CAVIUM_OCTEON
select SWAP_IO_SPACE
help
This option supports all of the Octeon reference boards from Cavium
Networks. It builds a kernel that dynamically determines the Octeon
CPU type and supports all known board reference implementations.
Some of the supported boards are:
EBT3000
EBH3000
EBH3100
Thunder
Kodama
Hikari
Say Y here for most Octeon reference boards.
endchoice
source "arch/mips/alchemy/Kconfig"
......@@ -607,6 +645,7 @@ source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
endmenu
......@@ -682,7 +721,11 @@ config CEVT_DS1287
config CEVT_GT641XX
bool
config CEVT_R4K_LIB
bool
config CEVT_R4K
select CEVT_R4K_LIB
bool
config CEVT_SB1250
......@@ -697,7 +740,11 @@ config CSRC_BCM1480
config CSRC_IOASIC
bool
config CSRC_R4K_LIB
bool
config CSRC_R4K
select CSRC_R4K_LIB
bool
config CSRC_SB1250
......@@ -835,6 +882,9 @@ config IRQ_GT641XX
config IRQ_GIC
bool
config IRQ_CPU_OCTEON
bool
config MIPS_BOARDS_GEN
bool
......@@ -924,7 +974,7 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT
int
default "4" if MACH_DECSTATION || MIKROTIK_RB532
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
default "4" if PMC_MSP4200_EVAL
default "5"
......@@ -1185,6 +1235,23 @@ config CPU_SB1
select CPU_SUPPORTS_HIGHMEM
select WEAK_ORDERING
config CPU_CAVIUM_OCTEON
bool "Cavium Octeon processor"
select IRQ_CPU
select IRQ_CPU_OCTEON
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_SMP
select NR_CPUS_DEFAULT_16
select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC
select CPU_SUPPORTS_HIGHMEM
help
The Cavium Octeon processor is a highly integrated chip containing
many ethernet hardware widgets for networking tasks. The processor
can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
Full details can be found at http://www.caviumnetworks.com.
endchoice
config SYS_HAS_CPU_LOONGSON2
......@@ -1285,7 +1352,7 @@ config CPU_MIPSR1
config CPU_MIPSR2
bool
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
config SYS_SUPPORTS_32BIT_KERNEL
bool
......
......@@ -144,6 +144,10 @@ cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \
cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap
cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \
-Wa,--trap
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon) -Wa,--trap
ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON))))
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
endif
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
......@@ -184,84 +188,84 @@ cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00
#
# AMD Alchemy Pb1000 eval board
#
libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/
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
#
libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/
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
#
libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/
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
#
libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/
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
#
libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/
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
#
libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/
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
#
libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/
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
#
libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/
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
#
libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/
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
#
libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/
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
#
libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/
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
#
libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/
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
......@@ -586,6 +590,18 @@ 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
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/
......
......@@ -128,9 +128,10 @@ config SOC_AU1200
config SOC_AU1X00
bool
select 64BIT_PHYS_ADDR
select CEVT_R4K
select CSRC_R4K
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_HARDIRQS_NO__DO_IRQ
......@@ -6,8 +6,8 @@
#
obj-y += prom.o irq.o puts.o time.o reset.o \
au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
sleeper.o cputable.o dma.o dbdma.o gpio.o
clocks.o platform.o power.o setup.o \
sleeper.o dma.o dbdma.o gpio.o
obj-$(CONFIG_PCI) += pci.o
......
/*
* BRIEF MODULE DESCRIPTION
* Au1xxx processor specific IRQ tables
*
* Copyright 2004 Embedded Edge, LLC
* dan@embeddededge.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 <linux/init.h>
#include <linux/kernel.h>
#include <au1000.h>
/* The IC0 interrupt table. This is processor, rather than
* board dependent, so no reason to keep this info in the board
* dependent files.
*
* Careful if you change match 2 request!
* The interrupt handler is called directly from the low level dispatch code.
*/
struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = {
#if defined(CONFIG_SOC_AU1000)
{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
#elif defined(CONFIG_SOC_AU1500)
{ AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
#elif defined(CONFIG_SOC_AU1100)
{ AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
/* { AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0 }, */
{ AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
#elif defined(CONFIG_SOC_AU1550)
{ AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
{ AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
{ AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
{ AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
{ AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
#elif defined(CONFIG_SOC_AU1200)
{ AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
{ AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0 },
#else
#error "Error: Unknown Alchemy SOC"
#endif
};
int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map);
......@@ -27,12 +27,21 @@
*/
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/time.h>
#include <asm/mach-au1x00/au1000.h>
/*
* I haven't found anyone that doesn't use a 12 MHz source clock,
* but just in case.....
*/
#define AU1000_SRC_CLK 12000000
static unsigned int au1x00_clock; /* Hz */
static unsigned int lcd_clock; /* KHz */
static unsigned long uart_baud_base;
static DEFINE_SPINLOCK(time_lock);
/*
* Set the au1000_clock
*/
......@@ -63,31 +72,45 @@ void set_au1x00_uart_baud_base(unsigned long new_baud_base)
}
/*
* Calculate the Au1x00's LCD clock based on the current
* cpu clock and the system bus clock, and try to keep it
* below 40 MHz (the Pb1000 board can lock-up if the LCD
* clock is over 40 MHz).
* We read the real processor speed from the PLL. This is important
* because it is more accurate than computing it from the 32 KHz
* counter, if it exists. If we don't have an accurate processor
* speed, all of the peripherals that derive their clocks based on
* this advertised speed will introduce error and sometimes not work
* properly. This function is futher convoluted to still allow configurations
* to do that in case they have really, really old silicon with a
* write-only PLL register. -- Dan
*/
void set_au1x00_lcd_clock(void)
unsigned long au1xxx_calc_clock(void)
{
unsigned int static_cfg0;
unsigned int sys_busclk = (get_au1x00_speed() / 1000) /
((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2);
unsigned long cpu_speed;
unsigned long flags;
static_cfg0 = au_readl(MEM_STCFG0);
spin_lock_irqsave(&time_lock, flags);
if (static_cfg0 & (1 << 11))
lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
/*
* On early Au1000, sys_cpupll was write-only. Since these
* silicon versions of Au1000 are not sold by AMD, we don't bend
* 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
lcd_clock = sys_busclk / 4;
cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
if (lcd_clock > 50000) /* Epson MAX */
printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n",
lcd_clock);
}
/* On Alchemy CPU:counter ratio is 1:1 */
mips_hpt_frequency = cpu_speed;
/* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
& 0x03) + 2) * 16));
unsigned int get_au1x00_lcd_clock(void)
{
return lcd_clock;
spin_unlock_irqrestore(&time_lock, flags);
set_au1x00_speed(cpu_speed);
return cpu_speed;
}
EXPORT_SYMBOL(get_au1x00_lcd_clock);
/*
* arch/mips/au1000/common/cputable.c
*
* Copyright (C) 2004 Dan Malek (dan@embeddededge.com)
* Copied from PowerPC and updated for Alchemy Au1xxx processors.
*
* Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <asm/mach-au1x00/au1000.h>
struct cpu_spec *cur_cpu_spec[NR_CPUS];
/* With some thought, we can probably use the mask to reduce the
* size of the table.
*/
struct cpu_spec cpu_specs[] = {
{ 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 },
{ 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 },
{ 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 },
{ 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 },
{ 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 },
{ 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 },
{ 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 },
{ 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 },
{ 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 },
{ 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 },
{ 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 },
{ 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 },
{ 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 },
{ 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 },
{ 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 },
{ 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 },
{ 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 }
};
void set_cpuspec(void)
{
struct cpu_spec *sp;
u32 prid;
prid = read_c0_prid();
sp = cpu_specs;
while ((prid & sp->prid_mask) != sp->prid_value)
sp++;
cur_cpu_spec[0] = sp;
}
......@@ -174,6 +174,11 @@ static dbdev_tab_t dbdev_tab[] = {
#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
#ifdef CONFIG_PM
static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][8];
#endif
static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
static dbdev_tab_t *find_dbdev_id(u32 id)
......@@ -975,4 +980,64 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
return nbytes;
}
#ifdef CONFIG_PM
void au1xxx_dbdma_suspend(void)
{
int i;
u32 addr;
addr = DDMA_GLOBAL_BASE;
au1xxx_dbdma_pm_regs[0][0] = au_readl(addr + 0x00);
au1xxx_dbdma_pm_regs[0][1] = au_readl(addr + 0x04);
au1xxx_dbdma_pm_regs[0][2] = au_readl(addr + 0x08);
au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
/* save channel configurations */
for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
au1xxx_dbdma_pm_regs[i][6] = au_readl(addr + 0x18);
/* halt channel */
au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
au_sync();
while (!(au_readl(addr + 0x14) & 1))
au_sync();
addr += 0x100; /* next channel base */
}
/* disable channel interrupts */
au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
au_sync();
}
void au1xxx_dbdma_resume(void)
{
int i;
u32 addr;
addr = DDMA_GLOBAL_BASE;
au_writel(au1xxx_dbdma_pm_regs[0][0], addr + 0x00);
au_writel(au1xxx_dbdma_pm_regs[0][1], addr + 0x04);
au_writel(au1xxx_dbdma_pm_regs[0][2], addr + 0x08);
au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
/* restore channel configurations */
for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
au_writel(au1xxx_dbdma_pm_regs[i][6], addr + 0x18);
au_sync();
addr += 0x100; /* next channel base */
}
}
#endif /* CONFIG_PM */
#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
This diff is collapsed.
This diff is collapsed.
......@@ -31,8 +31,6 @@
#include <asm/mach-au1x00/au1000.h>
extern int au_sleep(void);
void au1000_restart(char *command)
{
/* Set all integrated peripherals to disabled states */
......
......@@ -35,7 +35,6 @@
#include <asm/time.h>
#include <au1000.h>
#include <prom.h>
extern void __init board_setup(void);
extern void au1000_restart(char *);
......@@ -45,80 +44,34 @@ extern void set_cpuspec(void);
void __init plat_mem_setup(void)
{
struct cpu_spec *sp;
char *argptr;
unsigned long prid, cpufreq, bclk;
unsigned long est_freq;
set_cpuspec();
sp = cur_cpu_spec[0];
/* determine core clock */
est_freq = au1xxx_calc_clock();
est_freq += 5000; /* round */
est_freq -= est_freq % 10000;
printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
board_setup(); /* board specific setup */
prid = read_c0_prid();
if (sp->cpu_pll_wo)
#ifdef CONFIG_SOC_AU1000_FREQUENCY
cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000;
#else
cpufreq = 396;
#endif
else
cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12;
printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq);
_machine_restart = au1000_restart;
_machine_halt = au1000_halt;
pm_power_off = au1000_power_off;
if (sp->cpu_bclk) {
/* Enable BCLK switching */
bclk = au_readl(SYS_POWERCTRL);
au_writel(bclk | 0x60, SYS_POWERCTRL);
printk(KERN_INFO "BCLK switching enabled!\n");
}
board_setup(); /* board specific setup */
if (sp->cpu_od)
if (au1xxx_cpu_needs_config_od())
/* Various early Au1xx0 errata corrected by this */
set_c0_config(1 << 19); /* Set Config[OD] */
else
/* Clear to obtain best system bus performance */
clear_c0_config(1 << 19); /* Clear Config[OD] */
argptr = prom_getcmdline();
#ifdef CONFIG_SERIAL_8250_CONSOLE
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
#ifdef CONFIG_FB_AU1100
argptr = strstr(argptr, "video=");
if (argptr == NULL) {
argptr = prom_getcmdline();
/* default panel */
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
}
#endif
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
/* au1000 does not support vra, au1500 and au1100 do */
strcat(argptr, " au1000_audio=vra");
argptr = prom_getcmdline();
#endif
_machine_restart = au1000_restart;
_machine_halt = au1000_halt;
pm_power_off = au1000_power_off;
/* IO/MEM resources. */
set_io_port_base(0);
ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
au_sync();
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
au_writel(0, SYS_TOYTRIM);
}
#if defined(CONFIG_64BIT_PHYS_ADDR)
......
......@@ -15,16 +15,17 @@
#include <asm/regdef.h>
#include <asm/stackframe.h>
.extern __flush_cache_all
.text
.set macro
.set noreorder
.set noat
.align 5
/* Save all of the processor general registers and go to sleep.
* A wakeup condition will get us back here to restore the registers.
*/
LEAF(save_and_sleep)
LEAF(au1xxx_save_and_sleep)
subu sp, PT_SIZE
sw $1, PT_R1(sp)
sw $2, PT_R2(sp)
......@@ -33,14 +34,6 @@ LEAF(save_and_sleep)
sw $5, PT_R5(sp)
sw $6, PT_R6(sp)
sw $7, PT_R7(sp)
sw $8, PT_R8(sp)
sw $9, PT_R9(sp)
sw $10, PT_R10(sp)
sw $11, PT_R11(sp)
sw $12, PT_R12(sp)
sw $13, PT_R13(sp)
sw $14, PT_R14(sp)
sw $15, PT_R15(sp)
sw $16, PT_R16(sp)
sw $17, PT_R17(sp)
sw $18, PT_R18(sp)
......@@ -49,12 +42,9 @@ LEAF(save_and_sleep)
sw $21, PT_R21(sp)
sw $22, PT_R22(sp)
sw $23, PT_R23(sp)
sw $24, PT_R24(sp)
sw $25, PT_R25(sp)
sw $26, PT_R26(sp)
sw $27, PT_R27(sp)
sw $28, PT_R28(sp)
sw $29, PT_R29(sp)
sw $30, PT_R30(sp)
sw $31, PT_R31(sp)
mfc0 k0, CP0_STATUS
......@@ -66,20 +56,26 @@ LEAF(save_and_sleep)
mfc0 k0, CP0_CONFIG
sw k0, 0x14(sp)
/* flush caches to make sure context is in memory */
la t1, __flush_cache_all
lw t0, 0(t1)
jalr t0
nop
/* Now set up the scratch registers so the boot rom will
* return to this point upon wakeup.
* sys_scratch0 : SP
* sys_scratch1 : RA
*/
la k0, 1f
lui k1, 0xb190
ori k1, 0x18
sw sp, 0(k1)
ori k1, 0x1c
sw k0, 0(k1)
lui t3, 0xb190 /* sys_xxx */
sw sp, 0x0018(t3)
la k0, 3f /* resume path */
sw k0, 0x001c(t3)
/* Put SDRAM into self refresh. Preload instructions into cache,
* issue a precharge, then auto refresh, then sleep commands to it.
/* Put SDRAM into self refresh: Preload instructions into cache,
* issue a precharge, auto/self refresh, then sleep commands to it.
*/
la t0, sdsleep
la t0, 1f
.set mips3
cache 0x14, 0(t0)
cache 0x14, 32(t0)
......@@ -87,24 +83,57 @@ LEAF(save_and_sleep)
cache 0x14, 96(t0)
.set mips0
sdsleep:
lui k0, 0xb400
sw zero, 0x001c(k0) /* Precharge */
sw zero, 0x0020(k0) /* Auto refresh */
sw zero, 0x0030(k0) /* SDRAM sleep */
1: lui a0, 0xb400 /* mem_xxx */
#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
defined(CONFIG_SOC_AU1500)
sw zero, 0x001c(a0) /* Precharge */
sync
sw zero, 0x0020(a0) /* Auto Refresh */
sync
sw zero, 0x0030(a0) /* Sleep */
sync
#endif
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
sw zero, 0x08c0(a0) /* Precharge */
sync
sw zero, 0x08d0(a0) /* Self Refresh */
sync
/* wait for sdram to enter self-refresh mode */
lui t0, 0x0100
2: lw t1, 0x0850(a0) /* mem_sdstat */
and t2, t1, t0
beq t2, zero, 2b
nop
/* disable SDRAM clocks */
lui t0, 0xcfff
ori t0, t0, 0xffff
lw t1, 0x0840(a0) /* mem_sdconfiga */
and t1, t0, t1 /* clear CE[1:0] */
sw t1, 0x0840(a0) /* mem_sdconfiga */
sync
#endif
lui k1, 0xb190
sw zero, 0x0078(k1) /* get ready to sleep */
/* put power supply and processor to sleep */
sw zero, 0x0078(t3) /* sys_slppwr */
sync
sw zero, 0x007c(k1) /* Put processor to sleep */
sw zero, 0x007c(t3) /* sys_sleep */
sync
nop
nop
nop
nop
nop
nop
nop
nop
/* This is where we return upon wakeup.
* Reload all of the registers and return.
*/
1: nop
lw k0, 0x20(sp)
3: lw k0, 0x20(sp)
mtc0 k0, CP0_STATUS
lw k0, 0x1c(sp)
mtc0 k0, CP0_CONTEXT
......@@ -113,10 +142,11 @@ sdsleep:
lw k0, 0x14(sp)
mtc0 k0, CP0_CONFIG
/* We need to catch the ealry Alchemy SOCs with
/* We need to catch the early Alchemy SOCs with
* the write-only Config[OD] bit and set it back to one...
*/
jal au1x00_fixup_config_od
nop
lw $1, PT_R1(sp)
lw $2, PT_R2(sp)
lw $3, PT_R3(sp)
......@@ -124,14 +154,6 @@ sdsleep:
lw $5, PT_R5(sp)
lw $6, PT_R6(sp)
lw $7, PT_R7(sp)
lw $8, PT_R8(sp)
lw $9, PT_R9(sp)
lw $10, PT_R10(sp)
lw $11, PT_R11(sp)
lw $12, PT_R12(sp)
lw $13, PT_R13(sp)
lw $14, PT_R14(sp)
lw $15, PT_R15(sp)
lw $16, PT_R16(sp)
lw $17, PT_R17(sp)
lw $18, PT_R18(sp)
......@@ -140,15 +162,11 @@ sdsleep:
lw $21, PT_R21(sp)
lw $22, PT_R22(sp)
lw $23, PT_R23(sp)
lw $24, PT_R24(sp)
lw $25, PT_R25(sp)
lw $26, PT_R26(sp)
lw $27, PT_R27(sp)
lw $28, PT_R28(sp)
lw $29, PT_R29(sp)
lw $30, PT_R30(sp)
lw $31, PT_R31(sp)
addiu sp, PT_SIZE
jr ra
END(save_and_sleep)
addiu sp, PT_SIZE
END(au1xxx_save_and_sleep)
This diff is collapsed.
/*
* BRIEF MODULE DESCRIPTION
* PB1000 board setup
*
* Copyright 2001, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.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 <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <prom.h>
const char *get_system_type(void)
{
#ifdef CONFIG_MIPS_BOSPORUS
return "Alchemy Bosporus Gateway Reference";
#else
return "Alchemy Db1x00";
#endif
}
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_strtol(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
#
# Alchemy Develboards
#
obj-y += prom.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_MIPS_PB1000) += pb1000/
obj-$(CONFIG_MIPS_PB1100) += pb1100/
obj-$(CONFIG_MIPS_PB1200) += pb1200/
obj-$(CONFIG_MIPS_PB1500) += pb1500/
obj-$(CONFIG_MIPS_PB1550) += pb1550/
obj-$(CONFIG_MIPS_DB1000) += db1x00/
obj-$(CONFIG_MIPS_DB1100) += db1x00/
obj-$(CONFIG_MIPS_DB1200) += pb1200/
obj-$(CONFIG_MIPS_DB1500) += db1x00/
obj-$(CONFIG_MIPS_DB1550) += db1x00/
obj-$(CONFIG_MIPS_BOSPORUS) += db1x00/
obj-$(CONFIG_MIPS_MIRAGE) += db1x00/
......@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor DBAu1xx0 boards.
#
lib-y := init.o board_setup.o irqmap.o
obj-y := board_setup.o irqmap.o
......@@ -32,8 +32,20 @@
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/db1x00.h>
#include <prom.h>
static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
const char *get_system_type(void)
{
#ifdef CONFIG_MIPS_BOSPORUS
return "Alchemy Bosporus Gateway Reference";
#else
return "Alchemy Db1x00";
#endif
}
void board_reset(void)
{
/* Hit BCSR.SW_RESET[RESET] */
......@@ -43,6 +55,31 @@ void board_reset(void)
void __init board_setup(void)
{
u32 pin_func = 0;
char *argptr;
argptr = prom_getcmdline();
#ifdef CONFIG_SERIAL_8250_CONSOLE
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
#ifdef CONFIG_FB_AU1100
argptr = strstr(argptr, "video=");
if (argptr == NULL) {
argptr = prom_getcmdline();
/* default panel */
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
}
#endif
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
/* au1000 does not support vra, au1500 and au1100 do */
strcat(argptr, " au1000_audio=vra");
argptr = prom_getcmdline();
#endif
/* Not valid for Au1550 */
#if defined(CONFIG_IRDA) && \
......
......@@ -27,6 +27,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
......@@ -66,21 +67,24 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
#ifndef CONFIG_MIPS_MIRAGE
#ifdef CONFIG_MIPS_DB1550
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
{ AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
{ AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
#else
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
{ AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 Fully_Interted# */
{ AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 STSCHG# */
{ AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
{ AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 Fully_Interted# */
{ AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 STSCHG# */
{ AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
#endif
#else
{ AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
{ AU1000_GPIO_7, IRQF_TRIGGER_RISING, 0 }, /* touchscreen pen down */
#endif
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
......@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1000 board.
#
lib-y := init.o board_setup.o irqmap.o
obj-y := board_setup.o
......@@ -23,22 +23,48 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1000.h>
#include <prom.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_15, IRQF_TRIGGER_LOW, 0 },
};
const char *get_system_type(void)
{
return "Alchemy Pb1000";
}
void board_reset(void)
{
}
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
void __init board_setup(void)
{
u32 pin_func, static_cfg0;
u32 sys_freqctrl, sys_clksrc;
u32 prid = read_c0_prid();
#ifdef CONFIG_SERIAL_8250_CONSOLE
char *argptr = prom_getcmdline();
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
au_writel(8, SYS_AUXPLL);
au_writel(0, SYS_PINSTATERD);
......
......@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1100 board.
#
lib-y := init.o board_setup.o irqmap.o
obj-y := board_setup.o
......@@ -25,19 +25,66 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1100.h>
#include <prom.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_9, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card Fully_Inserted# */
{ AU1000_GPIO_10, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card STSCHG# */
{ AU1000_GPIO_11, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card IRQ# */
{ AU1000_GPIO_13, IRQF_TRIGGER_LOW, 0 }, /* DC_IRQ# */
};
const char *get_system_type(void)
{
return "Alchemy Pb1100";
}
void board_reset(void)
{
/* Hit BCSR.RST_VDDI[SOFT_RESET] */
au_writel(0x00000000, PB1100_RST_VDDI);
}
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
void __init board_setup(void)
{
volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;
char *argptr;
argptr = prom_getcmdline();
#ifdef CONFIG_SERIAL_8250_CONSOLE
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
#ifdef CONFIG_FB_AU1100
argptr = strstr(argptr, "video=");
if (argptr == NULL) {
argptr = prom_getcmdline();
/* default panel */
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
}
#endif
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
/* au1000 does not support vra, au1500 and au1100 do */
strcat(argptr, " au1000_audio=vra");
argptr = prom_getcmdline();
#endif
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
au_writel(8, SYS_AUXPLL);
......
......@@ -2,7 +2,6 @@
# Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards.
#
lib-y := init.o board_setup.o irqmap.o
obj-y += platform.o
obj-y := board_setup.o irqmap.o platform.o
EXTRA_CFLAGS += -Werror
......@@ -30,8 +30,11 @@
#include <prom.h>
#include <au1xxx.h>
extern void _board_init_irq(void);
extern void (*board_init_irq)(void);
const char *get_system_type(void)
{
return "Alchemy Pb1200";
}
void board_reset(void)
{
......@@ -41,7 +44,19 @@ void board_reset(void)
void __init board_setup(void)
{
char *argptr = NULL;
char *argptr;
argptr = prom_getcmdline();
#ifdef CONFIG_SERIAL_8250_CONSOLE
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
#ifdef CONFIG_FB_AU1200
strcat(argptr, " video=au1200fb:panel:bs");
#endif
#if 0
{
......@@ -99,16 +114,6 @@ void __init board_setup(void)
}
#endif
#ifdef CONFIG_FB_AU1200
argptr = prom_getcmdline();
#ifdef CONFIG_MIPS_PB1200
strcat(argptr, " video=au1200fb:panel:bs");
#endif
#ifdef CONFIG_MIPS_DB1200
strcat(argptr, " video=au1200fb:panel:bs");
#endif
#endif
/*
* The Pb1200 development board uses external MUX for PSC0 to
* support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
......@@ -124,9 +129,6 @@ void __init board_setup(void)
#ifdef CONFIG_MIPS_DB1200
printk(KERN_INFO "AMD Alchemy Db1200 Board\n");
#endif
/* Setup Pb1200 External Interrupt Controller */
board_init_irq = _board_init_irq;
}
int board_au1200fb_panel(void)
......
......@@ -40,91 +40,65 @@
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
/* This is external interrupt cascade */
{ AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 },
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
/*
* Support for External interrupts on the Pb1200 Development platform.
*/
static volatile int pb1200_cascade_en;
irqreturn_t pb1200_cascade_handler(int irq, void *dev_id)
static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d)
{
unsigned short bisr = bcsr->int_status;
int extirq_nr = 0;
/* Clear all the edge interrupts. This has no effect on level. */
bcsr->int_status = bisr;
for ( ; bisr; bisr &= bisr - 1) {
extirq_nr = PB1200_INT_BEGIN + __ffs(bisr);
/* Ack and dispatch IRQ */
do_IRQ(extirq_nr);
}
return IRQ_RETVAL(1);
}
inline void pb1200_enable_irq(unsigned int irq_nr)
{
bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
for ( ; bisr; bisr &= bisr - 1)
generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr));
}
inline void pb1200_disable_irq(unsigned int irq_nr)
/* NOTE: both the enable and mask bits must be cleared, otherwise the
* CPLD generates tons of spurious interrupts (at least on the DB1200).
*/
static void pb1200_mask_irq(unsigned int irq_nr)
{
bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
au_sync();
}
static unsigned int pb1200_setup_cascade(void)
static void pb1200_maskack_irq(unsigned int irq_nr)
{
return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
0, "Pb1200 Cascade", &pb1200_cascade_handler);
}
static unsigned int pb1200_startup_irq(unsigned int irq)
{
if (++pb1200_cascade_en == 1) {
int res;
res = pb1200_setup_cascade();
if (res)
return res;
}
pb1200_enable_irq(irq);
return 0;
bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->int_status = 1 << (irq_nr - PB1200_INT_BEGIN); /* ack */
au_sync();
}
static void pb1200_shutdown_irq(unsigned int irq)
static void pb1200_unmask_irq(unsigned int irq_nr)
{
pb1200_disable_irq(irq);
if (--pb1200_cascade_en == 0)
free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
au_sync();
}
static struct irq_chip external_irq_type = {
static struct irq_chip pb1200_cpld_irq_type = {
#ifdef CONFIG_MIPS_PB1200
.name = "Pb1200 Ext",
#endif
#ifdef CONFIG_MIPS_DB1200
.name = "Db1200 Ext",
#endif
.startup = pb1200_startup_irq,
.shutdown = pb1200_shutdown_irq,
.ack = pb1200_disable_irq,
.mask = pb1200_disable_irq,
.mask_ack = pb1200_disable_irq,
.unmask = pb1200_enable_irq,
.mask = pb1200_mask_irq,
.mask_ack = pb1200_maskack_irq,
.unmask = pb1200_unmask_irq,
};
void _board_init_irq(void)
void __init board_init_irq(void)
{
unsigned int irq;
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
#ifdef CONFIG_MIPS_PB1200
/* We have a problem with CPLD rev 3. */
if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
......@@ -146,15 +120,15 @@ void _board_init_irq(void)
panic("Game over. Your score is 0.");
}
#endif
/* mask & disable & ack all */
bcsr->intclr_mask = 0xffff;
bcsr->intclr = 0xffff;
bcsr->int_status = 0xffff;
au_sync();
for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) {
set_irq_chip_and_handler(irq, &external_irq_type,
handle_level_irq);
pb1200_disable_irq(irq);
}
for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
handle_level_irq, "level");
/*
* GPIO_7 can not be hooked here, so it is hooked upon first
* request of any source attached to the cascade.
*/
set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
}
......@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1500 board.
#
lib-y := init.o board_setup.o irqmap.o
obj-y := board_setup.o
......@@ -25,20 +25,64 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1500.h>
#include <prom.h>
char irq_tab_alchemy[][5] __initdata = {
[12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */
[13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */
};
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
{ AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
};
const char *get_system_type(void)
{
return "Alchemy Pb1500";
}
void board_reset(void)
{
/* Hit BCSR.RST_VDDI[SOFT_RESET] */
au_writel(0x00000000, PB1500_RST_VDDI);
}
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
void __init board_setup(void)
{
u32 pin_func;
u32 sys_freqctrl, sys_clksrc;
char *argptr;
argptr = prom_getcmdline();
#ifdef CONFIG_SERIAL_8250_CONSOLE
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
/* au1000 does not support vra, au1500 and au1100 do */
strcat(argptr, " au1000_audio=vra");
argptr = prom_getcmdline();
#endif
sys_clksrc = sys_freqctrl = pin_func = 0;
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
......
......@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1550 board.
#
lib-y := init.o board_setup.o irqmap.o
obj-y := board_setup.o
......@@ -28,20 +28,54 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1550.h>
#include <prom.h>
char irq_tab_alchemy[][5] __initdata = {
[12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */
[13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
};
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
};
const char *get_system_type(void)
{
return "Alchemy Pb1550";
}
void board_reset(void)
{
/* Hit BCSR.SYSTEM[RESET] */
au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C);
}
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
void __init board_setup(void)
{
u32 pin_func;
#ifdef CONFIG_SERIAL_8250_CONSOLE
char *argptr;
argptr = prom_getcmdline();
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
/*
* Enable PSC1 SYNC for AC'97. Normaly done in audio driver,
* but it is board specific code, so put it here.
......
/*
* Alchemy Development Board example suspend userspace interface.
*
* (c) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
*/
#include <linux/init.h>
#include <linux/kobject.h>
#include <linux/suspend.h>
#include <linux/sysfs.h>
#include <asm/mach-au1x00/au1000.h>
/*
* Generic suspend userspace interface for Alchemy development boards.
* This code exports a few sysfs nodes under /sys/power/db1x/ which
* can be used by userspace to en/disable all au1x-provided wakeup
* sources and configure the timeout after which the the TOYMATCH2 irq
* is to trigger a wakeup.
*/
static unsigned long db1x_pm_sleep_secs;
static unsigned long db1x_pm_wakemsk;
static unsigned long db1x_pm_last_wakesrc;
static int db1x_pm_enter(suspend_state_t state)
{
/* enable GPIO based wakeup */
au_writel(1, SYS_PININPUTEN);
/* clear and setup wake cause and source */
au_writel(0, SYS_WAKEMSK);
au_sync();
au_writel(0, SYS_WAKESRC);
au_sync();
au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
au_sync();
/* setup 1Hz-timer-based wakeup: wait for reg access */
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
asm volatile ("nop");
au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
au_sync();
/* wait for value to really hit the register */
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
asm volatile ("nop");
/* ...and now the sandman can come! */
au_sleep();
return 0;
}
static int db1x_pm_begin(suspend_state_t state)
{
if (!db1x_pm_wakemsk) {
printk(KERN_ERR "db1x: no wakeup source activated!\n");
return -EINVAL;
}
return 0;
}
static void db1x_pm_end(void)
{
/* read and store wakeup source, the clear the register. To
* be able to clear it, WAKEMSK must be cleared first.
*/
db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
au_writel(0, SYS_WAKEMSK);
au_writel(0, SYS_WAKESRC);
au_sync();
}
static struct platform_suspend_ops db1x_pm_ops = {
.valid = suspend_valid_only_mem,
.begin = db1x_pm_begin,
.enter = db1x_pm_enter,
.end = db1x_pm_end,
};
#define ATTRCMP(x) (0 == strcmp(attr->attr.name, #x))
static ssize_t db1x_pmattr_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
int idx;
if (ATTRCMP(timer_timeout))
return sprintf(buf, "%lu\n", db1x_pm_sleep_secs);
else if (ATTRCMP(timer))
return sprintf(buf, "%u\n",
!!(db1x_pm_wakemsk & SYS_WAKEMSK_M2));
else if (ATTRCMP(wakesrc))
return sprintf(buf, "%lu\n", db1x_pm_last_wakesrc);
else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
idx = (attr->attr.name)[4] - '0';
return sprintf(buf, "%d\n",
!!(db1x_pm_wakemsk & SYS_WAKEMSK_GPIO(idx)));
} else if (ATTRCMP(wakemsk)) {
return sprintf(buf, "%08lx\n", db1x_pm_wakemsk);
}
return -ENOENT;
}
static ssize_t db1x_pmattr_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *instr,
size_t bytes)
{
unsigned long l;
int tmp;
if (ATTRCMP(timer_timeout)) {
tmp = strict_strtoul(instr, 0, &l);
if (tmp)
return tmp;
db1x_pm_sleep_secs = l;
} else if (ATTRCMP(timer)) {
if (instr[0] != '0')
db1x_pm_wakemsk |= SYS_WAKEMSK_M2;
else
db1x_pm_wakemsk &= ~SYS_WAKEMSK_M2;
} else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
tmp = (attr->attr.name)[4] - '0';
if (instr[0] != '0') {
db1x_pm_wakemsk |= SYS_WAKEMSK_GPIO(tmp);
} else {
db1x_pm_wakemsk &= ~SYS_WAKEMSK_GPIO(tmp);
}
} else if (ATTRCMP(wakemsk)) {
tmp = strict_strtoul(instr, 0, &l);
if (tmp)
return tmp;
db1x_pm_wakemsk = l & 0x0000003f;
} else
bytes = -ENOENT;
return bytes;
}
#define ATTR(x) \
static struct kobj_attribute x##_attribute = \
__ATTR(x, 0664, db1x_pmattr_show, \
db1x_pmattr_store);
ATTR(gpio0) /* GPIO-based wakeup enable */
ATTR(gpio1)
ATTR(gpio2)
ATTR(gpio3)
ATTR(gpio4)
ATTR(gpio5)
ATTR(gpio6)
ATTR(gpio7)
ATTR(timer) /* TOYMATCH2-based wakeup enable */
ATTR(timer_timeout) /* timer-based wakeup timeout value, in seconds */
ATTR(wakesrc) /* contents of SYS_WAKESRC after last wakeup */
ATTR(wakemsk) /* direct access to SYS_WAKEMSK */
#define ATTR_LIST(x) & x ## _attribute.attr
static struct attribute *db1x_pmattrs[] = {
ATTR_LIST(gpio0),
ATTR_LIST(gpio1),
ATTR_LIST(gpio2),
ATTR_LIST(gpio3),
ATTR_LIST(gpio4),
ATTR_LIST(gpio5),
ATTR_LIST(gpio6),
ATTR_LIST(gpio7),
ATTR_LIST(timer),
ATTR_LIST(timer_timeout),
ATTR_LIST(wakesrc),
ATTR_LIST(wakemsk),
NULL, /* terminator */
};
static struct attribute_group db1x_pmattr_group = {
.name = "db1x",
.attrs = db1x_pmattrs,
};
/*
* Initialize suspend interface
*/
static int __init pm_init(void)
{
/* init TOY to tick at 1Hz if not already done. No need to wait
* for confirmation since there's plenty of time from here to
* the next suspend cycle.
*/
if (au_readl(SYS_TOYTRIM) != 32767) {
au_writel(32767, SYS_TOYTRIM);
au_sync();
}
db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
au_writel(0, SYS_WAKESRC);
au_sync();
au_writel(0, SYS_WAKEMSK);
au_sync();
suspend_set_ops(&db1x_pm_ops);
return sysfs_create_group(power_kobj, &db1x_pmattr_group);
}
late_initcall(pm_init);
/*
* Common code used by all Alchemy develboards.
*
* BRIEF MODULE DESCRIPTION
* Pb1550 board setup
* Extracted from files which had this to say:
*
* Copyright 2001, 2008 MontaVista Software Inc.
* Copyright 2000, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or modify it
......@@ -29,15 +29,19 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <asm/mach-au1x00/au1000.h>
#include <prom.h>
const char *get_system_type(void)
{
return "Alchemy Pb1550";
}
#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || \
defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || \
defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500) || \
defined(CONFIG_MIPS_BOSPORUS) || defined(CONFIG_MIPS_MIRAGE)
#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x04000000
#else /* Au1550/Au1200-based develboards */
#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x08000000
#endif
void __init prom_init(void)
{
......@@ -51,8 +55,8 @@ void __init prom_init(void)
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str)
memsize = 0x08000000;
memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
else
strict_strtol(memsize_str, 0, &memsize);
strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
......@@ -32,6 +32,8 @@
#include <asm/mach-au1x00/au1000.h>
#include <prom.h>
extern int (*board_pci_idsel)(unsigned int devsel, int assert);
int mtx1_pci_idsel(unsigned int devsel, int assert);
......@@ -43,6 +45,16 @@ void board_reset(void)
void __init board_setup(void)
{
#ifdef CONFIG_SERIAL_8250_CONSOLE
char *argptr;
argptr = prom_getcmdline();
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
/* Enable USB power switch */
au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR);
......
......@@ -55,6 +55,6 @@ void __init prom_init(void)
if (!memsize_str)
memsize = 0x04000000;
else
strict_strtol(memsize_str, 0, &memsize);
strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
......@@ -27,7 +27,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
char irq_tab_alchemy[][5] __initdata = {
......@@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = {
};
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
{ AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
/*
* BRIEF MODULE DESCRIPTION
* Pb1000 board setup
*
* Copyright 2001, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.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 <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <prom.h>
const char *get_system_type(void)
{
return "Alchemy Pb1000";
}
void __init prom_init(void)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = (int)fw_arg0;
prom_argv = (char **)fw_arg1;
prom_envp = (char **)fw_arg2;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str)
memsize = 0x04000000;
else
strict_strtol(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
/*
* BRIEF MODULE DESCRIPTION
* Au1xxx irq map table
*
* Copyright 2003 Embedded Edge, LLC
* dan@embeddededge.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 <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
/*
*
* BRIEF MODULE DESCRIPTION
* Pb1100 board setup
*
* Copyright 2002, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.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 <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <prom.h>
const char *get_system_type(void)
{
return "Alchemy Pb1100";
}
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_arg3;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str)
memsize = 0x04000000;
else
strict_strtol(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
/*
* BRIEF MODULE DESCRIPTION
* Au1xx0 IRQ map table
*
* Copyright 2003 Embedded Edge, LLC
* dan@embeddededge.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 <linux/init.h>
#include <asm/mach-au1x00/au1000.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card Fully_Inserted# */
{ AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card STSCHG# */
{ AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card IRQ# */
{ AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, /* DC_IRQ# */
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
/*
*
* BRIEF MODULE DESCRIPTION
* PB1200 board setup
*
* Copyright 2001, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.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 <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <prom.h>
const char *get_system_type(void)
{
return "Alchemy Pb1200";
}
void __init prom_init(void)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = (int)fw_arg0;
prom_argv = (char **)fw_arg1;
prom_envp = (char **)fw_arg2;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str)
memsize = 0x08000000;
else
strict_strtol(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
/*
*
* BRIEF MODULE DESCRIPTION
* Pb1500 board setup
*
* Copyright 2001, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.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 <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <prom.h>
const char *get_system_type(void)
{
return "Alchemy Pb1500";
}
void __init prom_init(void)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = (int)fw_arg0;
prom_argv = (char **)fw_arg1;
prom_envp = (char **)fw_arg2;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str)
memsize = 0x04000000;
else
strict_strtol(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
/*
* BRIEF MODULE DESCRIPTION
* Au1xxx irq map table
*
* Copyright 2003 Embedded Edge, LLC
* dan@embeddededge.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 <linux/init.h>
#include <asm/mach-au1x00/au1000.h>
char irq_tab_alchemy[][5] __initdata = {
[12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */
[13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */
};
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
/*
* BRIEF MODULE DESCRIPTION
* Au1xx0 IRQ map table
*
* Copyright 2003 Embedded Edge, LLC
* dan@embeddededge.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 <linux/init.h>
#include <asm/mach-au1x00/au1000.h>
char irq_tab_alchemy[][5] __initdata = {
[12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */
[13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
};
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
......@@ -28,6 +28,8 @@
#include <asm/mach-au1x00/au1000.h>
#include <prom.h>
void board_reset(void)
{
/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
......@@ -38,6 +40,16 @@ void __init board_setup(void)
{
u32 pin_func;
#ifdef CONFIG_SERIAL_8250_CONSOLE
char *argptr;
argptr = prom_getcmdline();
argptr = strstr(argptr, "console=");
if (argptr == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
pin_func |= SYS_PF_UR3;
......
......@@ -53,6 +53,6 @@ void __init prom_init(void)
if (!memsize_str)
memsize = 0x04000000;
else
strict_strtol(memsize_str, 0, &memsize);
strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
......@@ -27,23 +27,26 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
{ AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_207, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* CF interrupt */
{ AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 },
};
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
void __init board_init_irq(void)
{
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
}
config CAVIUM_OCTEON_SPECIFIC_OPTIONS
bool "Enable Octeon specific options"
depends on CPU_CAVIUM_OCTEON
default "y"
config CAVIUM_OCTEON_2ND_KERNEL
bool "Build the kernel to be used as a 2nd kernel on the same chip"
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
default "n"
help
This option configures this kernel to be linked at a different
address and use the 2nd uart for output. This allows a kernel built
with this option to be run at the same time as one built without this
option.
config CAVIUM_OCTEON_HW_FIX_UNALIGNED
bool "Enable hardware fixups of unaligned loads and stores"
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
default "y"
help
Configure the Octeon hardware to automatically fix unaligned loads
and stores. Normally unaligned accesses are fixed using a kernel
exception handler. This option enables the hardware automatic fixups,
which requires only an extra 3 cycles. Disable this option if you
are running code that relies on address exceptions on unaligned
accesses.
config CAVIUM_OCTEON_CVMSEG_SIZE
int "Number of L1 cache lines reserved for CVMSEG memory"
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
range 0 54
default 1
help
CVMSEG LM is a segment that accesses portions of the dcache as a
local memory; the larger CVMSEG is, the smaller the cache is.
This selects the size of CVMSEG LM, which is in cache blocks. The
legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
between zero and 6192 bytes).
config CAVIUM_OCTEON_LOCK_L2
bool "Lock often used kernel code in the L2"
depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
default "y"
help
Enable locking parts of the kernel into the L2 cache.
config CAVIUM_OCTEON_LOCK_L2_TLB
bool "Lock the TLB handler in L2"
depends on CAVIUM_OCTEON_LOCK_L2
default "y"
help
Lock the low level TLB fast path into L2.
config CAVIUM_OCTEON_LOCK_L2_EXCEPTION
bool "Lock the exception handler in L2"
depends on CAVIUM_OCTEON_LOCK_L2
default "y"
help
Lock the low level exception handler into L2.
config CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT
bool "Lock the interrupt handler in L2"
depends on CAVIUM_OCTEON_LOCK_L2
default "y"
help
Lock the low level interrupt handler into L2.
config CAVIUM_OCTEON_LOCK_L2_INTERRUPT
bool "Lock the 2nd level interrupt handler in L2"
depends on CAVIUM_OCTEON_LOCK_L2
default "y"
help
Lock the 2nd level interrupt handler in L2.
config CAVIUM_OCTEON_LOCK_L2_MEMCPY
bool "Lock memcpy() in L2"
depends on CAVIUM_OCTEON_LOCK_L2
default "y"
help
Lock the kernel's implementation of memcpy() into L2.
config ARCH_SPARSEMEM_ENABLE
def_bool y
select SPARSEMEM_STATIC
depends on CPU_CAVIUM_OCTEON
#
# Makefile for the Cavium Octeon specific kernel interface routines
# under Linux.
#
# 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) 2005-2008 Cavium Networks
#
obj-y := setup.o serial.o octeon-irq.o csrc-octeon.o
obj-y += dma-octeon.o flash_setup.o
obj-y += octeon-memcpy.o
obj-$(CONFIG_SMP) += smp.o
/*
* 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 by Ralf Baechle
*/
#include <linux/clocksource.h>
#include <linux/init.h>
#include <asm/time.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-ipd-defs.h>
/*
* Set the current core's cvmcount counter to the value of the
* IPD_CLK_COUNT. We do this on all cores as they are brought
* on-line. This allows for a read from a local cpu register to
* access a synchronized counter.
*
*/
void octeon_init_cvmcount(void)
{
unsigned long flags;
unsigned loops = 2;
/* Clobber loops so GCC will not unroll the following while loop. */
asm("" : "+r" (loops));
local_irq_save(flags);
/*
* Loop several times so we are executing from the cache,
* which should give more deterministic timing.
*/
while (loops--)
write_c0_cvmcount(cvmx_read_csr(CVMX_IPD_CLK_COUNT));
local_irq_restore(flags);
}
static cycle_t octeon_cvmcount_read(void)
{
return read_c0_cvmcount();
}
static struct clocksource clocksource_mips = {
.name = "OCTEON_CVMCOUNT",
.read = octeon_cvmcount_read,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
void __init plat_time_init(void)
{
clocksource_mips.rating = 300;
clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
clocksource_register(&clocksource_mips);
}
/*
* 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) 2000 Ani Joshi <ajoshi@unixbox.com>
* Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
* Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
* swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
* IP32 changes by Ilya.
* Cavium Networks: Create new dma setup for Cavium Networks Octeon based on
* the kernels original.
*/
#include <linux/types.h>
#include <linux/mm.h>
#include <dma-coherence.h>
dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
{
/* Without PCI/PCIe this function can be called for Octeon internal
devices such as USB. These devices all support 64bit addressing */
mb();
return virt_to_phys(ptr);
}
void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
{
/* Without PCI/PCIe this function can be called for Octeon internal
* devices such as USB. These devices all support 64bit addressing */
return;
}
#
# Makefile for the Cavium Octeon specific kernel interface routines
# under Linux.
#
# 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) 2005-2008 Cavium Networks
#
obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
This diff is collapsed.
This diff is collapsed.
/***********************license start***************
* Author: Cavium Networks
*
* Contact: support@caviumnetworks.com
* This file is part of the OCTEON SDK
*
* Copyright (c) 2003-2008 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* or visit http://www.gnu.org/licenses/.
*
* This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information
***********************license end**************************************/
/*
* This module provides system/board/application information obtained
* by the bootloader.
*/
#include <asm/octeon/cvmx.h>
#include <asm/octeon/cvmx-spinlock.h>
#include <asm/octeon/cvmx-sysinfo.h>
/**
* This structure defines the private state maintained by sysinfo module.
*
*/
static struct {
struct cvmx_sysinfo sysinfo; /* system information */
cvmx_spinlock_t lock; /* mutex spinlock */
} state = {
.lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER
};
/*
* Global variables that define the min/max of the memory region set
* up for 32 bit userspace access.
*/
uint64_t linux_mem32_min;
uint64_t linux_mem32_max;
uint64_t linux_mem32_wired;
uint64_t linux_mem32_offset;
/**
* This function returns the application information as obtained
* by the bootloader. This provides the core mask of the cores
* running the same application image, as well as the physical
* memory regions available to the core.
*
* Returns Pointer to the boot information structure
*
*/
struct cvmx_sysinfo *cvmx_sysinfo_get(void)
{
return &(state.sysinfo);
}
/**
* This function is used in non-simple executive environments (such as
* Linux kernel, u-boot, etc.) to configure the minimal fields that
* are required to use simple executive files directly.
*
* Locking (if required) must be handled outside of this
* function
*
* @phy_mem_desc_ptr:
* Pointer to global physical memory descriptor
* (bootmem descriptor) @board_type: Octeon board
* type enumeration
*
* @board_rev_major:
* Board major revision
* @board_rev_minor:
* Board minor revision
* @cpu_clock_hz:
* CPU clock freqency in hertz
*
* Returns 0: Failure
* 1: success
*/
int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
uint16_t board_type,
uint8_t board_rev_major,
uint8_t board_rev_minor,
uint32_t cpu_clock_hz)
{
/* The sysinfo structure was already initialized */
if (state.sysinfo.board_type)
return 0;
memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo));
state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr;
state.sysinfo.board_type = board_type;
state.sysinfo.board_rev_major = board_rev_major;
state.sysinfo.board_rev_minor = board_rev_minor;
state.sysinfo.cpu_clock_hz = cpu_clock_hz;
return 1;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -38,6 +38,9 @@
#ifndef cpu_has_tx39_cache
#define cpu_has_tx39_cache (cpu_data[0].options & MIPS_CPU_TX39_CACHE)
#endif
#ifndef cpu_has_octeon_cache
#define cpu_has_octeon_cache 0
#endif
#ifndef cpu_has_fpu
#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU)
#define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU)
......
This diff is collapsed.
......@@ -42,7 +42,7 @@ ASMMACRO(_ehb,
/*
* TLB hazards
*/
#if defined(CONFIG_CPU_MIPSR2)
#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
/*
* MIPSR2 defines ehb for hazard avoidance
......@@ -138,7 +138,7 @@ do { \
__instruction_hazard(); \
} while (0)
#elif defined(CONFIG_CPU_R10000)
#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_CAVIUM_OCTEON)
/*
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment